diff --git a/SConstruct b/SConstruct index 49dccf04..fa618044 100644 --- a/SConstruct +++ b/SConstruct @@ -149,7 +149,7 @@ libvmime_sources = [ 'utility/path.cpp', 'utility/path.hpp', 'utility/progressListener.cpp', 'utility/progressListener.hpp', 'utility/random.cpp', 'utility/random.hpp', - 'utility/smartPtr.hpp', + 'utility/smartPtr.cpp', 'utility/smartPtr.hpp', 'utility/stream.cpp', 'utility/stream.hpp', 'utility/stringProxy.cpp', 'utility/stringProxy.hpp', 'utility/stringUtils.cpp', 'utility/stringUtils.hpp', diff --git a/src/body.cpp b/src/body.cpp index f43e825e..a9e0d674 100644 --- a/src/body.cpp +++ b/src/body.cpp @@ -64,7 +64,7 @@ void body::parse(const string& buffer, const string::size_type position, try { const ref ctf = - m_header->findField(fields::CONTENT_TYPE).dynamicCast (); + m_header.acquire()->findField(fields::CONTENT_TYPE).dynamicCast (); const mediaType type = *ctf->getValue().dynamicCast (); @@ -211,7 +211,7 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe { string boundary; - if (m_header == NULL) + if (m_header.acquire() == NULL) { boundary = generateRandomBoundaryString(); } @@ -220,7 +220,8 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe try { ref ctf = - m_header->findField(fields::CONTENT_TYPE).dynamicCast (); + m_header.acquire()->findField(fields::CONTENT_TYPE) + .dynamicCast (); boundary = ctf->getBoundary(); } @@ -389,7 +390,7 @@ const mediaType body::getContentType() const try { ref ctf = - m_header->findField(fields::CONTENT_TYPE).dynamicCast (); + m_header.acquire()->findField(fields::CONTENT_TYPE).dynamicCast (); return (*ctf->getValue().dynamicCast ()); } @@ -406,7 +407,7 @@ const charset body::getCharset() const try { const ref ctf = - m_header->findField(fields::CONTENT_TYPE).dynamicCast (); + m_header.acquire()->findField(fields::CONTENT_TYPE).dynamicCast (); return (ctf->getCharset()); } @@ -428,7 +429,7 @@ const encoding body::getEncoding() const try { const ref cef = - m_header->findField(fields::CONTENT_TRANSFER_ENCODING); + m_header.acquire()->findField(fields::CONTENT_TRANSFER_ENCODING); return (*cef->getValue().dynamicCast ()); } @@ -440,7 +441,7 @@ const encoding body::getEncoding() const } -void body::setParentPart(weak_ref parent) +void body::setParentPart(ref parent) { m_part = parent; m_header = (parent != NULL ? parent->getHeader() : NULL); @@ -449,7 +450,8 @@ void body::setParentPart(weak_ref parent) const bool body::isRootPart() const { - return (m_part == NULL || m_part->getParentPart() == NULL); + ref part = m_part.acquire(); + return (part == NULL || part->getParentPart() == NULL); } @@ -532,13 +534,15 @@ void body::initNewPart(ref part) { part->m_parent = m_part; - if (m_header != NULL) + ref
hdr = m_header.acquire(); + + if (hdr != NULL) { // Check whether we have a boundary string try { ref ctf = - m_header->findField(fields::CONTENT_TYPE).dynamicCast (); + hdr->findField(fields::CONTENT_TYPE).dynamicCast (); try { @@ -564,7 +568,7 @@ void body::initNewPart(ref part) // No "Content-Type" field: create a new one and generate // a random boundary string. ref ctf = - m_header->getField(fields::CONTENT_TYPE).dynamicCast (); + hdr->getField(fields::CONTENT_TYPE).dynamicCast (); ctf->setValue(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED)); ctf->setBoundary(generateRandomBoundaryString()); diff --git a/src/bodyPart.cpp b/src/bodyPart.cpp index 6903adb2..6d686f9b 100644 --- a/src/bodyPart.cpp +++ b/src/bodyPart.cpp @@ -33,7 +33,7 @@ bodyPart::bodyPart() m_body(vmime::create ()), m_parent(NULL) { - m_body->setParentPart(this); + m_body->setParentPart(thisRef().dynamicCast ()); } @@ -121,9 +121,15 @@ ref bodyPart::getBody() } -weak_ref bodyPart::getParentPart() const +ref bodyPart::getParentPart() { - return (m_parent); + return m_parent.acquire(); +} + + +ref bodyPart::getParentPart() const +{ + return m_parent.acquire(); } diff --git a/src/net/imap/IMAPConnection.cpp b/src/net/imap/IMAPConnection.cpp index bd963f56..9683b009 100644 --- a/src/net/imap/IMAPConnection.cpp +++ b/src/net/imap/IMAPConnection.cpp @@ -41,11 +41,11 @@ // Helpers for service properties #define GET_PROPERTY(type, prop) \ - (m_store->getInfos().getPropertyValue (getSession(), \ - dynamic_cast (m_store->getInfos()).getProperties().prop)) + (m_store.acquire()->getInfos().getPropertyValue (getSession(), \ + dynamic_cast (m_store.acquire()->getInfos()).getProperties().prop)) #define HAS_PROPERTY(prop) \ - (m_store->getInfos().hasProperty(getSession(), \ - dynamic_cast (m_store->getInfos()).getProperties().prop)) + (m_store.acquire()->getInfos().hasProperty(getSession(), \ + dynamic_cast (m_store.acquire()->getInfos()).getProperties().prop)) namespace vmime { @@ -53,7 +53,7 @@ namespace net { namespace imap { -IMAPConnection::IMAPConnection(weak_ref store, ref auth) +IMAPConnection::IMAPConnection(ref store, ref auth) : m_store(store), m_auth(auth), m_socket(NULL), m_parser(NULL), m_tag(NULL), m_hierarchySeparator('\0'), m_state(STATE_NONE), m_timeoutHandler(NULL), m_secured(false) @@ -88,18 +88,20 @@ void IMAPConnection::connect() const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS); const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT); + ref store = m_store.acquire(); + // Create the time-out handler - if (m_store->getTimeoutHandlerFactory()) - m_timeoutHandler = m_store->getTimeoutHandlerFactory()->create(); + if (store->getTimeoutHandlerFactory()) + m_timeoutHandler = store->getTimeoutHandlerFactory()->create(); // Create and connect the socket - m_socket = m_store->getSocketFactory()->create(); + m_socket = store->getSocketFactory()->create(); #if VMIME_HAVE_TLS_SUPPORT - if (m_store->isIMAPS()) // dedicated port/IMAPS + if (store->isIMAPS()) // dedicated port/IMAPS { ref tlsSession = - vmime::create (m_store->getCertificateVerifier()); + vmime::create (store->getCertificateVerifier()); ref tlsSocket = tlsSession->getSocket(m_socket); @@ -150,7 +152,7 @@ void IMAPConnection::connect() const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED) && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED); - if (!m_store->isSecuredConnection() && tls) // only if not IMAPS + if (!store->isSecuredConnection() && tls) // only if not IMAPS { try { @@ -202,7 +204,7 @@ void IMAPConnection::connect() void IMAPConnection::authenticate() { - getAuthenticator()->setService(m_store.toStrong()); + getAuthenticator()->setService(m_store.acquire()); #if VMIME_HAVE_SASL_SUPPORT // First, try SASL authentication @@ -448,7 +450,7 @@ void IMAPConnection::startTLS() } ref tlsSession = - vmime::create (m_store->getCertificateVerifier()); + vmime::create (m_store.acquire()->getCertificateVerifier()); ref tlsSocket = tlsSession->getSocket(m_socket); @@ -693,21 +695,21 @@ ref IMAPConnection::getParser() const } -weak_ref IMAPConnection::getStore() const +ref IMAPConnection::getStore() const { - return (m_store); + return m_store.acquire(); } -weak_ref IMAPConnection::getStore() +ref IMAPConnection::getStore() { - return (m_store); + return m_store.acquire(); } ref IMAPConnection::getSession() { - return (m_store->getSession()); + return m_store.acquire()->getSession(); } diff --git a/src/net/imap/IMAPFolder.cpp b/src/net/imap/IMAPFolder.cpp index f28fa8a3..0179620b 100644 --- a/src/net/imap/IMAPFolder.cpp +++ b/src/net/imap/IMAPFolder.cpp @@ -39,23 +39,25 @@ namespace net { namespace imap { -IMAPFolder::IMAPFolder(const folder::path& path, IMAPStore* store, const int type, const int flags) - : m_store(store), m_connection(m_store->connection()), m_path(path), +IMAPFolder::IMAPFolder(const folder::path& path, ref store, const int type, const int flags) + : m_store(store), m_connection(store->connection()), m_path(path), m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), m_mode(-1), m_open(false), m_type(type), m_flags(flags), m_messageCount(0), m_uidValidity(0) { - m_store->registerFolder(this); + store->registerFolder(this); } IMAPFolder::~IMAPFolder() { - if (m_store) + ref store = m_store.acquire(); + + if (store) { if (m_open) close(false); - m_store->unregisterFolder(this); + store->unregisterFolder(this); } else if (m_open) { @@ -128,12 +130,14 @@ const folder::path IMAPFolder::getFullPath() const void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); // Open a connection for this folder ref connection = - vmime::create (m_store, m_store->getAuthenticator()); + vmime::create (store, store->getAuthenticator()); try { @@ -270,7 +274,9 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) void IMAPFolder::close(const bool expunge) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); if (!isOpen()) @@ -292,7 +298,7 @@ void IMAPFolder::close(const bool expunge) oldConnection->disconnect(); // Now use default store connection - m_connection = m_store->connection(); + m_connection = m_store.acquire()->connection(); m_open = false; m_mode = -1; @@ -317,13 +323,15 @@ void IMAPFolder::onClose() void IMAPFolder::create(const int type) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (isOpen()) throw exceptions::illegal_state("Folder is open"); else if (exists()) throw exceptions::illegal_state("Folder already exists"); - else if (!m_store->isValidFolderName(m_name)) + else if (!store->isValidFolderName(m_name)) throw exceptions::invalid_folder_name(); // Emit the "CREATE" command @@ -365,7 +373,9 @@ void IMAPFolder::create(const int type) const bool IMAPFolder::exists() { - if (!isOpen() && !m_store) + ref store = m_store.acquire(); + + if (!isOpen() && !store) throw exceptions::illegal_state("Store disconnected"); return (testExistAndGetType() != TYPE_UNDEFINED); @@ -458,7 +468,7 @@ ref IMAPFolder::getMessage(const int num) if (num < 1 || num > m_messageCount) throw exceptions::message_not_found(); - return vmime::create (this, num); + return vmime::create (thisRef().dynamicCast (), num); } @@ -473,9 +483,10 @@ std::vector > IMAPFolder::getMessages(const int from, const int t throw exceptions::message_not_found(); std::vector > v; + ref thisFolder = thisRef().dynamicCast (); for (int i = from ; i <= to2 ; ++i) - v.push_back(vmime::create (this, i)); + v.push_back(vmime::create (thisFolder, i)); return (v); } @@ -487,9 +498,10 @@ std::vector > IMAPFolder::getMessages(const std::vector & nu throw exceptions::illegal_state("Folder not open"); std::vector > v; + ref thisFolder = thisRef().dynamicCast (); for (std::vector ::const_iterator it = nums.begin() ; it != nums.end() ; ++it) - v.push_back(vmime::create (this, *it)); + v.push_back(vmime::create (thisFolder, *it)); return (v); } @@ -506,16 +518,20 @@ const int IMAPFolder::getMessageCount() ref IMAPFolder::getFolder(const folder::path::component& name) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); - return vmime::create (m_path / name, m_store); + return vmime::create (m_path / name, store); } std::vector > IMAPFolder::getFolders(const bool recursive) { - if (!isOpen() && !m_store) + ref store = m_store.acquire(); + + if (!isOpen() && !store) throw exceptions::illegal_state("Store disconnected"); // Eg. List folders in '/foo/bar' @@ -591,7 +607,7 @@ std::vector > IMAPFolder::getFolders(const bool recursive) const class IMAPParser::mailbox_flag_list* mailbox_flag_list = mailboxData->mailbox_list()->mailbox_flag_list(); - v.push_back(vmime::create (path, m_store, + v.push_back(vmime::create (path, store, IMAPUtils::folderTypeFromFlags(mailbox_flag_list), IMAPUtils::folderFlagsFromFlags(mailbox_flag_list))); } @@ -604,7 +620,9 @@ std::vector > IMAPFolder::getFolders(const bool recursive) void IMAPFolder::fetchMessages(std::vector >& msg, const int options, utility::progressListener* progress) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -691,12 +709,14 @@ void IMAPFolder::fetchMessages(std::vector >& msg, const int opti void IMAPFolder::fetchMessage(ref msg, const int options) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); - msg.dynamicCast ()->fetch(this, options); + msg.dynamicCast ()->fetch(thisRef().dynamicCast (), options); } @@ -713,19 +733,19 @@ ref IMAPFolder::getParent() if (m_path.isEmpty()) return NULL; else - return vmime::create (m_path.getParent(), m_store); + return vmime::create (m_path.getParent(), m_store.acquire()); } -weak_ref IMAPFolder::getStore() const +ref IMAPFolder::getStore() const { - return (m_store); + return m_store.acquire(); } -weak_ref IMAPFolder::getStore() +ref IMAPFolder::getStore() { - return (m_store); + return m_store.acquire(); } @@ -753,7 +773,9 @@ void IMAPFolder::onStoreDisconnected() void IMAPFolder::deleteMessage(const int num) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -802,10 +824,12 @@ void IMAPFolder::deleteMessage(const int num) void IMAPFolder::deleteMessages(const int from, const int to) { + ref store = m_store.acquire(); + if (from < 1 || (to < from && to != -1)) throw exceptions::invalid_argument(); - if (!m_store) + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -865,10 +889,12 @@ void IMAPFolder::deleteMessages(const int from, const int to) void IMAPFolder::deleteMessages(const std::vector & nums) { + ref store = m_store.acquire(); + if (nums.empty()) throw exceptions::invalid_argument(); - if (!m_store) + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -924,10 +950,12 @@ void IMAPFolder::deleteMessages(const std::vector & nums) void IMAPFolder::setMessageFlags(const int from, const int to, const int flags, const int mode) { + ref store = m_store.acquire(); + if (from < 1 || (to < from && to != -1)) throw exceptions::invalid_argument(); - if (!m_store) + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -1012,7 +1040,9 @@ void IMAPFolder::setMessageFlags(const int from, const int to, const int flags, void IMAPFolder::setMessageFlags(const std::vector & nums, const int flags, const int mode) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -1142,7 +1172,9 @@ void IMAPFolder::addMessage(ref msg, const int flags, void IMAPFolder::addMessage(utility::inputStream& is, const int size, const int flags, vmime::datetime* date, utility::progressListener* progress) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -1243,8 +1275,8 @@ void IMAPFolder::addMessage(utility::inputStream& is, const int size, const int notifyMessageCount(event); // Notify folders with the same path - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it) != this && (*it)->getFullPath() == m_path) { @@ -1261,7 +1293,9 @@ void IMAPFolder::addMessage(utility::inputStream& is, const int size, const int void IMAPFolder::expunge() { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -1330,8 +1364,8 @@ void IMAPFolder::expunge() notifyMessageCount(event); // Notify folders with the same path - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it) != this && (*it)->getFullPath() == m_path) { @@ -1349,13 +1383,15 @@ void IMAPFolder::expunge() void IMAPFolder::rename(const folder::path& newPath) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (m_path.isEmpty() || newPath.isEmpty()) throw exceptions::illegal_operation("Cannot rename root folder"); else if (m_path.getSize() == 1 && m_name.getBuffer() == "INBOX") throw exceptions::illegal_operation("Cannot rename 'INBOX' folder"); - else if (!m_store->isValidFolderName(newPath.getLastComponent())) + else if (!store->isValidFolderName(newPath.getLastComponent())) throw exceptions::invalid_folder_name(); // Build the request text @@ -1392,8 +1428,8 @@ void IMAPFolder::rename(const folder::path& newPath) notifyFolder(event); // Notify folders with the same path and sub-folders - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it) != this && (*it)->getFullPath() == oldPath) { @@ -1424,7 +1460,9 @@ void IMAPFolder::rename(const folder::path& newPath) void IMAPFolder::copyMessage(const folder::path& dest, const int num) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -1440,8 +1478,8 @@ void IMAPFolder::copyMessage(const folder::path& dest, const int num) std::vector nums; nums.push_back(num); - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it)->getFullPath() == dest) { @@ -1458,7 +1496,9 @@ void IMAPFolder::copyMessage(const folder::path& dest, const int num) void IMAPFolder::copyMessages(const folder::path& dest, const int from, const int to) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -1486,8 +1526,8 @@ void IMAPFolder::copyMessages(const folder::path& dest, const int from, const in for (int i = from, j = 0 ; i <= to2 ; ++i, ++j) nums[j] = i; - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it)->getFullPath() == dest) { @@ -1504,7 +1544,9 @@ void IMAPFolder::copyMessages(const folder::path& dest, const int from, const in void IMAPFolder::copyMessages(const folder::path& dest, const std::vector & nums) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -1515,8 +1557,8 @@ void IMAPFolder::copyMessages(const folder::path& dest, const std::vector & // Notify message count changed const int count = nums.size(); - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it)->getFullPath() == dest) { @@ -1556,6 +1598,8 @@ void IMAPFolder::copyMessages(const string& set, const folder::path& dest) void IMAPFolder::status(int& count, int& unseen) { + ref store = m_store.acquire(); + count = 0; unseen = 0; @@ -1567,16 +1611,16 @@ void IMAPFolder::status(int& count, int& unseen) command << " (MESSAGES UNSEEN)"; // Send the request - m_store->m_connection->send(true, command.str(), true); + m_connection->send(true, command.str(), true); // Get the response - utility::auto_ptr resp(m_store->m_connection->readResponse()); + utility::auto_ptr resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { throw exceptions::command_error("STATUS", - m_store->m_connection->getParser()->lastLine(), "bad response"); + m_connection->getParser()->lastLine(), "bad response"); } const std::vector & respDataList = @@ -1588,7 +1632,7 @@ void IMAPFolder::status(int& count, int& unseen) if ((*it)->response_data() == NULL) { throw exceptions::command_error("STATUS", - m_store->m_connection->getParser()->lastLine(), "invalid response"); + m_connection->getParser()->lastLine(), "invalid response"); } const IMAPParser::response_data* responseData = (*it)->response_data(); @@ -1644,8 +1688,8 @@ void IMAPFolder::status(int& count, int& unseen) notifyMessageCount(event); // Notify folders with the same path - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it) != this && (*it)->getFullPath() == m_path) { diff --git a/src/net/imap/IMAPMessage.cpp b/src/net/imap/IMAPMessage.cpp index e7778b95..e796afaf 100644 --- a/src/net/imap/IMAPMessage.cpp +++ b/src/net/imap/IMAPMessage.cpp @@ -53,7 +53,7 @@ public: ref getStructure() const; ref getStructure(); - weak_ref getParent() const { return (m_parent); } + ref getParent() const { return m_parent.acquire(); } const mediaType& getType() const { return (m_mediaType); } const int getSize() const { return (m_size); } @@ -272,18 +272,20 @@ private: // -IMAPMessage::IMAPMessage(IMAPFolder* folder, const int num) +IMAPMessage::IMAPMessage(ref folder, const int num) : m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED), m_expunged(false), m_structure(NULL) { - m_folder->registerMessage(this); + folder->registerMessage(this); } IMAPMessage::~IMAPMessage() { - if (m_folder) - m_folder->unregisterMessage(this); + ref folder = m_folder.acquire(); + + if (folder) + folder->unregisterMessage(this); } @@ -359,7 +361,9 @@ ref IMAPMessage::getHeader() const void IMAPMessage::extract(utility::outputStream& os, utility::progressListener* progress, const int start, const int length, const bool peek) const { - if (!m_folder) + ref folder = m_folder.acquire(); + + if (!folder) throw exceptions::folder_not_found(); extract(NULL, os, progress, start, length, false, peek); @@ -370,7 +374,9 @@ void IMAPMessage::extractPart (ref p, utility::outputStream& os, utility::progressListener* progress, const int start, const int length, const bool peek) const { - if (!m_folder) + ref folder = m_folder.acquire(); + + if (!folder) throw exceptions::folder_not_found(); extract(p, os, progress, start, length, false, peek); @@ -379,7 +385,9 @@ void IMAPMessage::extractPart void IMAPMessage::fetchPartHeader(ref p) { - if (!m_folder) + ref folder = m_folder.acquire(); + + if (!folder) throw exceptions::folder_not_found(); std::ostringstream oss; @@ -395,6 +403,8 @@ void IMAPMessage::extract(ref p, utility::outputStream& os, utility::progressListener* progress, const int start, const int length, const bool headerOnly, const bool peek) const { + ref folder = m_folder.acquire(); + IMAPMessage_literalHandler literalHandler(os, progress); // Construct section identifier @@ -402,7 +412,7 @@ void IMAPMessage::extract(ref p, utility::outputStream& os, if (p != NULL) { - weak_ref currentPart = p.dynamicCast (); + ref currentPart = p.dynamicCast (); std::vector numbers; numbers.push_back(currentPart->getNumber()); @@ -437,17 +447,17 @@ void IMAPMessage::extract(ref p, utility::outputStream& os, command << "<" << start << "." << length << ">"; // Send the request - m_folder->m_connection->send(true, command.str(), true); + folder.constCast ()->m_connection->send(true, command.str(), true); // Get the response utility::auto_ptr resp - (m_folder->m_connection->readResponse(&literalHandler)); + (folder.constCast ()->m_connection->readResponse(&literalHandler)); if (resp->isBad() || resp->response_done()->response_tagged()-> resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { throw exceptions::command_error("FETCH", - m_folder->m_connection->getParser()->lastLine(), "bad response"); + folder.constCast ()->m_connection->getParser()->lastLine(), "bad response"); } @@ -458,9 +468,11 @@ void IMAPMessage::extract(ref p, utility::outputStream& os, } -void IMAPMessage::fetch(IMAPFolder* folder, const int options) +void IMAPMessage::fetch(ref msgFolder, const int options) { - if (m_folder != folder) + ref folder = m_folder.acquire(); + + if (folder != msgFolder) throw exceptions::folder_not_found(); // Send the request @@ -469,16 +481,16 @@ void IMAPMessage::fetch(IMAPFolder* folder, const int options) const string command = IMAPUtils::buildFetchRequest(list, options); - m_folder->m_connection->send(true, command, true); + folder->m_connection->send(true, command, true); // Get the response - utility::auto_ptr resp(m_folder->m_connection->readResponse()); + utility::auto_ptr resp(folder->m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { throw exceptions::command_error("FETCH", - m_folder->m_connection->getParser()->lastLine(), "bad response"); + folder->m_connection->getParser()->lastLine(), "bad response"); } const std::vector & respDataList = @@ -490,7 +502,7 @@ void IMAPMessage::fetch(IMAPFolder* folder, const int options) if ((*it)->response_data() == NULL) { throw exceptions::command_error("FETCH", - m_folder->m_connection->getParser()->lastLine(), "invalid response"); + folder->m_connection->getParser()->lastLine(), "invalid response"); } const IMAPParser::message_data* messageData = @@ -512,6 +524,8 @@ void IMAPMessage::fetch(IMAPFolder* folder, const int options) void IMAPMessage::processFetchResponse (const int options, const IMAPParser::msg_att* msgAtt) { + ref folder = m_folder.acquire(); + // Get message attributes const std::vector atts = msgAtt->items(); @@ -531,7 +545,7 @@ void IMAPMessage::processFetchResponse case IMAPParser::msg_att_item::UID: { std::ostringstream oss; - oss << m_folder->m_uidValidity << ":" << (*it)->unique_id()->value(); + oss << folder->m_uidValidity << ":" << (*it)->unique_id()->value(); m_uid = oss.str(); break; @@ -681,9 +695,11 @@ void IMAPMessage::convertAddressList void IMAPMessage::setFlags(const int flags, const int mode) { - if (!m_folder) + ref folder = m_folder.acquire(); + + if (!folder) throw exceptions::folder_not_found(); - else if (m_folder->m_mode == folder::MODE_READ_ONLY) + else if (folder->m_mode == folder::MODE_READ_ONLY) throw exceptions::illegal_state("Folder is read-only"); // Build the request text @@ -723,16 +739,16 @@ void IMAPMessage::setFlags(const int flags, const int mode) command << *(flagList.end() - 1) << ")"; // Send the request - m_folder->m_connection->send(true, command.str(), true); + folder->m_connection->send(true, command.str(), true); // Get the response - utility::auto_ptr resp(m_folder->m_connection->readResponse()); + utility::auto_ptr resp(folder->m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { throw exceptions::command_error("STORE", - m_folder->m_connection->getParser()->lastLine(), "bad response"); + folder->m_connection->getParser()->lastLine(), "bad response"); } // Update the local flags for this message @@ -776,13 +792,12 @@ void IMAPMessage::setFlags(const int flags, const int mode) nums.push_back(m_num); events::messageChangedEvent event - (m_folder->thisRef().dynamicCast (), - events::messageChangedEvent::TYPE_FLAGS, nums); + (folder, events::messageChangedEvent::TYPE_FLAGS, nums); - for (std::list ::iterator it = m_folder->m_store->m_folders.begin() ; - it != m_folder->m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = folder->m_store.acquire()->m_folders.begin() ; + it != folder->m_store.acquire()->m_folders.end() ; ++it) { - if ((*it)->getFullPath() == m_folder->m_path) + if ((*it)->getFullPath() == folder->m_path) (*it)->notifyMessageChanged(event); } } diff --git a/src/net/imap/IMAPStore.cpp b/src/net/imap/IMAPStore.cpp index ba99761d..e6f82c70 100644 --- a/src/net/imap/IMAPStore.cpp +++ b/src/net/imap/IMAPStore.cpp @@ -63,7 +63,8 @@ ref IMAPStore::getRootFolder() if (!isConnected()) throw exceptions::illegal_state("Not connected"); - return vmime::create (folder::path(), this); + return vmime::create (folder::path(), + thisRef().dynamicCast ()); } @@ -72,7 +73,8 @@ ref IMAPStore::getDefaultFolder() if (!isConnected()) throw exceptions::illegal_state("Not connected"); - return vmime::create (folder::path::component("INBOX"), this); + return vmime::create (folder::path::component("INBOX"), + thisRef().dynamicCast ()); } @@ -81,7 +83,7 @@ ref IMAPStore::getFolder(const folder::path& path) if (!isConnected()) throw exceptions::illegal_state("Not connected"); - return vmime::create (path, this); + return vmime::create (path, thisRef().dynamicCast ()); } @@ -97,7 +99,7 @@ void IMAPStore::connect() throw exceptions::already_connected(); m_connection = vmime::create - (thisWeakRef().dynamicCast (), getAuthenticator()); + (thisRef().dynamicCast (), getAuthenticator()); try { diff --git a/src/net/maildir/maildirFolder.cpp b/src/net/maildir/maildirFolder.cpp index 879868f7..7e596382 100644 --- a/src/net/maildir/maildirFolder.cpp +++ b/src/net/maildir/maildirFolder.cpp @@ -36,23 +36,25 @@ namespace net { namespace maildir { -maildirFolder::maildirFolder(const folder::path& path, weak_ref store) +maildirFolder::maildirFolder(const folder::path& path, ref store) : m_store(store), m_path(path), m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), m_mode(-1), m_open(false), m_unreadMessageCount(0), m_messageCount(0) { - m_store->registerFolder(this); + store->registerFolder(this); } maildirFolder::~maildirFolder() { - if (m_store) + ref store = m_store.acquire(); + + if (store) { if (m_open) close(false); - m_store->unregisterFolder(this); + store->unregisterFolder(this); } else if (m_open) { @@ -92,7 +94,7 @@ const int maildirFolder::getFlags() utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); ref rootDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_CONTAINER)); + (maildirUtils::getFolderFSPath(m_store.acquire(), m_path, maildirUtils::FOLDER_PATH_CONTAINER)); ref it = rootDir->getFiles(); @@ -125,7 +127,9 @@ const folder::path maildirFolder::getFullPath() const void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (isOpen()) throw exceptions::illegal_state("Folder is already open"); @@ -141,7 +145,9 @@ void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) void maildirFolder::close(const bool expunge) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); if (!isOpen()) @@ -187,13 +193,15 @@ void maildirFolder::unregisterMessage(maildirMessage* msg) void maildirFolder::create(const int /* type */) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (isOpen()) throw exceptions::illegal_state("Folder is open"); else if (exists()) throw exceptions::illegal_state("Folder already exists"); - else if (!m_store->isValidFolderName(m_name)) + else if (!store->isValidFolderName(m_name)) throw exceptions::invalid_folder_name(); // Create directory on file system @@ -201,18 +209,18 @@ void maildirFolder::create(const int /* type */) { utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - if (!fsf->isValidPath(maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_ROOT))) + if (!fsf->isValidPath(maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_ROOT))) throw exceptions::invalid_folder_name(); ref rootDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_ROOT)); + (maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_ROOT)); ref newDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_NEW)); + (maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_NEW)); ref tmpDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_TMP)); + (maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_TMP)); ref curDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_CUR)); + (maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_CUR)); rootDir->createDirectory(true); @@ -236,17 +244,19 @@ void maildirFolder::create(const int /* type */) const bool maildirFolder::exists() { + ref store = m_store.acquire(); + utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); ref rootDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_ROOT)); + (maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_ROOT)); ref newDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_NEW)); + (maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_NEW)); ref tmpDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_TMP)); + (maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_TMP)); ref curDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_CUR)); + (maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_CUR)); return (rootDir->exists() && rootDir->isDirectory() && newDir->exists() && newDir->isDirectory() && @@ -263,6 +273,8 @@ const bool maildirFolder::isOpen() const void maildirFolder::scanFolder() { + ref store = m_store.acquire(); + try { m_messageCount = 0; @@ -271,11 +283,11 @@ void maildirFolder::scanFolder() utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); utility::file::path newDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_NEW); + (store, m_path, maildirUtils::FOLDER_PATH_NEW); ref newDir = fsf->create(newDirPath); utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); + (store, m_path, maildirUtils::FOLDER_PATH_CUR); ref curDir = fsf->create(curDirPath); // New received messages (new/) @@ -407,7 +419,7 @@ ref maildirFolder::getMessage(const int num) throw exceptions::message_not_found(); return vmime::create - (thisWeakRef().dynamicCast (), num); + (thisRef().dynamicCast (), num); } @@ -421,12 +433,10 @@ std::vector > maildirFolder::getMessages(const int from, const in throw exceptions::message_not_found(); std::vector > v; + ref thisFolder = thisRef().dynamicCast (); for (int i = from ; i <= to2 ; ++i) - { - v.push_back(vmime::create - (thisWeakRef().dynamicCast (), i)); - } + v.push_back(vmime::create (thisFolder, i)); return (v); } @@ -438,12 +448,10 @@ std::vector > maildirFolder::getMessages(const std::vector & throw exceptions::illegal_state("Folder not open"); std::vector > v; + ref thisFolder = thisRef().dynamicCast (); for (std::vector ::const_iterator it = nums.begin() ; it != nums.end() ; ++it) - { - v.push_back(vmime::create - (thisWeakRef().dynamicCast (), *it)); - } + v.push_back(vmime::create (thisFolder, *it)); return (v); } @@ -457,16 +465,20 @@ const int maildirFolder::getMessageCount() ref maildirFolder::getFolder(const folder::path::component& name) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); - return vmime::create (m_path / name, m_store); + return vmime::create (m_path / name, store); } std::vector > maildirFolder::getFolders(const bool recursive) { - if (!isOpen() && !m_store) + ref store = m_store.acquire(); + + if (!isOpen() && !store) throw exceptions::illegal_state("Store disconnected"); std::vector > list; @@ -479,12 +491,14 @@ std::vector > maildirFolder::getFolders(const bool recursive) void maildirFolder::listFolders(std::vector >& list, const bool recursive) { + ref store = m_store.acquire(); + try { utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); ref rootDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, + (maildirUtils::getFolderFSPath(store, m_path, m_path.isEmpty() ? maildirUtils::FOLDER_PATH_ROOT : maildirUtils::FOLDER_PATH_CONTAINER)); @@ -502,7 +516,7 @@ void maildirFolder::listFolders(std::vector >& list, const bool re m_path / file->getFullPath().getLastComponent(); ref subFolder = - vmime::create (subPath, m_store); + vmime::create (subPath, store); list.push_back(subFolder); @@ -525,27 +539,29 @@ void maildirFolder::listFolders(std::vector >& list, const bool re void maildirFolder::rename(const folder::path& newPath) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (m_path.isEmpty() || newPath.isEmpty()) throw exceptions::illegal_operation("Cannot rename root folder"); - else if (!m_store->isValidFolderName(newPath.getLastComponent())) + else if (!store->isValidFolderName(newPath.getLastComponent())) throw exceptions::invalid_folder_name(); // Rename the directory on the file system utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); ref rootDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_ROOT)); + (maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_ROOT)); ref contDir = fsf->create - (maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_CONTAINER)); + (maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_CONTAINER)); try { const utility::file::path newRootPath = - maildirUtils::getFolderFSPath(m_store, newPath, maildirUtils::FOLDER_PATH_ROOT); + maildirUtils::getFolderFSPath(store, newPath, maildirUtils::FOLDER_PATH_ROOT); const utility::file::path newContPath = - maildirUtils::getFolderFSPath(m_store, newPath, maildirUtils::FOLDER_PATH_CONTAINER); + maildirUtils::getFolderFSPath(store, newPath, maildirUtils::FOLDER_PATH_CONTAINER); rootDir->rename(newRootPath); @@ -563,9 +579,9 @@ void maildirFolder::rename(const folder::path& newPath) { // Revert to old location const utility::file::path rootPath = - maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_ROOT); + maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_ROOT); const utility::file::path contPath = - maildirUtils::getFolderFSPath(m_store, m_path, maildirUtils::FOLDER_PATH_CONTAINER); + maildirUtils::getFolderFSPath(store, m_path, maildirUtils::FOLDER_PATH_CONTAINER); try { @@ -593,8 +609,8 @@ void maildirFolder::rename(const folder::path& newPath) notifyFolder(event); // Notify folders with the same path - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it) != this && (*it)->getFullPath() == oldPath) { @@ -647,10 +663,12 @@ void maildirFolder::deleteMessages(const std::vector & nums) void maildirFolder::setMessageFlags (const int from, const int to, const int flags, const int mode) { + ref store = m_store.acquire(); + if (from < 1 || (to < from && to != -1)) throw exceptions::invalid_argument(); - if (!m_store) + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -733,7 +751,9 @@ void maildirFolder::setMessageFlags void maildirFolder::setMessageFlags (const std::vector & nums, const int flags, const int mode) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -814,10 +834,12 @@ void maildirFolder::setMessageFlags void maildirFolder::setMessageFlagsImpl (const std::vector & nums, const int flags, const int mode) { + ref store = m_store.acquire(); + utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); + (store, m_path, maildirUtils::FOLDER_PATH_CUR); for (std::vector ::const_iterator it = nums.begin() ; it != nums.end() ; ++it) @@ -877,7 +899,9 @@ void maildirFolder::addMessage(ref msg, const int flags, void maildirFolder::addMessage(utility::inputStream& is, const int size, const int flags, vmime::datetime* /* date */, utility::progressListener* progress) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -887,9 +911,9 @@ void maildirFolder::addMessage(utility::inputStream& is, const int size, utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); utility::file::path tmpDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_TMP); + (store, m_path, maildirUtils::FOLDER_PATH_TMP); utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); + (store, m_path, maildirUtils::FOLDER_PATH_CUR); const utility::file::path::component filename = maildirUtils::buildFilename(maildirUtils::generateId(), @@ -940,8 +964,8 @@ void maildirFolder::addMessage(utility::inputStream& is, const int size, notifyMessageCount(event); // Notify folders with the same path - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it) != this && (*it)->getFullPath() == m_path) { @@ -1048,7 +1072,9 @@ void maildirFolder::copyMessageImpl(const utility::file::path& tmpDirPath, void maildirFolder::copyMessage(const folder::path& dest, const int num) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -1059,7 +1085,9 @@ void maildirFolder::copyMessage(const folder::path& dest, const int num) void maildirFolder::copyMessages(const folder::path& dest, const int from, const int to) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -1083,7 +1111,9 @@ void maildirFolder::copyMessages(const folder::path& dest, const int from, const void maildirFolder::copyMessages(const folder::path& dest, const std::vector & nums) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -1095,15 +1125,17 @@ void maildirFolder::copyMessages(const folder::path& dest, const std::vector & nums) { + ref store = m_store.acquire(); + utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); + (store, m_path, maildirUtils::FOLDER_PATH_CUR); utility::file::path destCurDirPath = maildirUtils::getFolderFSPath - (m_store, dest, maildirUtils::FOLDER_PATH_CUR); + (store, dest, maildirUtils::FOLDER_PATH_CUR); utility::file::path destTmpDirPath = maildirUtils::getFolderFSPath - (m_store, dest, maildirUtils::FOLDER_PATH_TMP); + (store, dest, maildirUtils::FOLDER_PATH_TMP); // Create destination directories try @@ -1159,8 +1191,10 @@ void maildirFolder::copyMessagesImpl(const folder::path& dest, const std::vector void maildirFolder::notifyMessagesCopied(const folder::path& dest) { - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + ref store = m_store.acquire(); + + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it) != this && (*it)->getFullPath() == dest) { @@ -1177,6 +1211,8 @@ void maildirFolder::notifyMessagesCopied(const folder::path& dest) void maildirFolder::status(int& count, int& unseen) { + ref store = m_store.acquire(); + const int oldCount = m_messageCount; scanFolder(); @@ -1200,8 +1236,8 @@ void maildirFolder::status(int& count, int& unseen) notifyMessageCount(event); // Notify folders with the same path - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it) != this && (*it)->getFullPath() == m_path) { @@ -1224,7 +1260,9 @@ void maildirFolder::status(int& count, int& unseen) void maildirFolder::expunge() { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -1234,7 +1272,7 @@ void maildirFolder::expunge() utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); + (store, m_path, maildirUtils::FOLDER_PATH_CUR); std::vector nums; int unreadCount = 0; @@ -1289,8 +1327,8 @@ void maildirFolder::expunge() notifyMessageCount(event); // Notify folders with the same path - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it) != this && (*it)->getFullPath() == m_path) { @@ -1315,26 +1353,28 @@ ref maildirFolder::getParent() if (m_path.isEmpty()) return NULL; else - return vmime::create (m_path.getParent(), m_store); + return vmime::create (m_path.getParent(), m_store.acquire()); } -weak_ref maildirFolder::getStore() const +ref maildirFolder::getStore() const { - return (m_store); + return m_store.acquire(); } -weak_ref maildirFolder::getStore() +ref maildirFolder::getStore() { - return (m_store); + return m_store.acquire(); } void maildirFolder::fetchMessages(std::vector >& msg, const int options, utility::progressListener* progress) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -1345,12 +1385,12 @@ void maildirFolder::fetchMessages(std::vector >& msg, if (progress) progress->start(total); - weak_ref _this = thisWeakRef().dynamicCast (); + ref thisFolder = thisRef().dynamicCast (); for (std::vector >::iterator it = msg.begin() ; it != msg.end() ; ++it) { - (*it).dynamicCast ()->fetch(_this, options); + (*it).dynamicCast ()->fetch(thisFolder, options); if (progress) progress->progress(++current, total); @@ -1363,13 +1403,15 @@ void maildirFolder::fetchMessages(std::vector >& msg, void maildirFolder::fetchMessage(ref msg, const int options) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); msg.dynamicCast ()->fetch - (thisWeakRef().dynamicCast (), options); + (thisRef().dynamicCast (), options); } @@ -1384,7 +1426,7 @@ const int maildirFolder::getFetchCapabilities() const const utility::file::path maildirFolder::getMessageFSPath(const int number) const { utility::file::path curDirPath = maildirUtils::getFolderFSPath - (m_store, m_path, maildirUtils::FOLDER_PATH_CUR); + (m_store.acquire(), m_path, maildirUtils::FOLDER_PATH_CUR); return (curDirPath / m_messageInfos[number - 1].path); } diff --git a/src/net/maildir/maildirMessage.cpp b/src/net/maildir/maildirMessage.cpp index 8cfe49be..6c621f21 100644 --- a/src/net/maildir/maildirMessage.cpp +++ b/src/net/maildir/maildirMessage.cpp @@ -43,7 +43,7 @@ class maildirPart : public part { public: - maildirPart(weak_ref parent, const int number, const bodyPart& part); + maildirPart(ref parent, const int number, const bodyPart& part); ~maildirPart(); @@ -111,7 +111,7 @@ public: { } - maildirStructure(weak_ref parent, const bodyPart& part) + maildirStructure(ref parent, const bodyPart& part) { vmime::ref mpart = vmime::create (parent, 0, part); mpart->initStructure(part); @@ -119,7 +119,7 @@ public: m_parts.push_back(mpart); } - maildirStructure(weak_ref parent, const std::vector >& list) + maildirStructure(ref parent, const std::vector >& list) { for (unsigned int i = 0 ; i < list.size() ; ++i) { @@ -164,7 +164,7 @@ ref maildirStructure::m_emptyStructure = vmime::create parent, const int number, const bodyPart& part) +maildirPart::maildirPart(ref parent, const int number, const bodyPart& part) : m_parent(parent), m_header(NULL), m_number(number) { m_headerParsedOffset = part.getHeader()->getParsedOffset(); @@ -191,7 +191,7 @@ void maildirPart::initStructure(const bodyPart& part) else { m_structure = vmime::create - (thisWeakRef().dynamicCast (), + (thisRef().dynamicCast (), part.getBody()->getPartList()); } } @@ -220,18 +220,20 @@ ref maildirPart::getStructure() // maildirMessage // -maildirMessage::maildirMessage(weak_ref folder, const int num) +maildirMessage::maildirMessage(ref folder, const int num) : m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED), m_expunged(false), m_structure(NULL) { - m_folder->registerMessage(this); + folder->registerMessage(this); } maildirMessage::~maildirMessage() { - if (m_folder) - m_folder->unregisterMessage(this); + ref folder = m_folder.acquire(); + + if (folder) + folder->unregisterMessage(this); } @@ -306,10 +308,12 @@ const int maildirMessage::getFlags() const void maildirMessage::setFlags(const int flags, const int mode) { - if (!m_folder) + ref folder = m_folder.acquire(); + + if (!folder) throw exceptions::folder_not_found(); - m_folder->setMessageFlags(m_num, m_num, flags, mode); + folder->setMessageFlags(m_num, m_num, flags, mode); } @@ -336,9 +340,11 @@ void maildirMessage::extractImpl(utility::outputStream& os, utility::progressLis const int start, const int length, const int partialStart, const int partialLength, const bool /* peek */) const { + ref folder = m_folder.acquire(); + utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - const utility::file::path path = m_folder->getMessageFSPath(m_num); + const utility::file::path path = folder->getMessageFSPath(m_num); ref file = fsf->create(path); ref reader = file->getFileReader(); @@ -379,11 +385,13 @@ void maildirMessage::extractImpl(utility::outputStream& os, utility::progressLis void maildirMessage::fetchPartHeader(ref p) { + ref folder = m_folder.acquire(); + ref mp = p.dynamicCast (); utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - const utility::file::path path = m_folder->getMessageFSPath(m_num); + const utility::file::path path = folder->getMessageFSPath(m_num); ref file = fsf->create(path); ref reader = file->getFileReader(); @@ -411,9 +419,11 @@ void maildirMessage::fetchPartHeader(ref p) } -void maildirMessage::fetch(weak_ref folder, const int options) +void maildirMessage::fetch(ref msgFolder, const int options) { - if (m_folder != folder) + ref folder = m_folder.acquire(); + + if (folder != msgFolder) throw exceptions::folder_not_found(); utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); diff --git a/src/net/maildir/maildirStore.cpp b/src/net/maildir/maildirStore.cpp index 79510eb0..4cea5ec3 100644 --- a/src/net/maildir/maildirStore.cpp +++ b/src/net/maildir/maildirStore.cpp @@ -75,7 +75,7 @@ ref maildirStore::getRootFolder() throw exceptions::illegal_state("Not connected"); return vmime::create (folder::path(), - thisWeakRef().dynamicCast ()); + thisRef().dynamicCast ()); } @@ -85,7 +85,7 @@ ref maildirStore::getDefaultFolder() throw exceptions::illegal_state("Not connected"); return vmime::create (folder::path::component("inbox"), - thisWeakRef().dynamicCast ()); + thisRef().dynamicCast ()); } @@ -95,7 +95,7 @@ ref maildirStore::getFolder(const folder::path& path) throw exceptions::illegal_state("Not connected"); return vmime::create (path, - thisWeakRef().dynamicCast ()); + thisRef().dynamicCast ()); } diff --git a/src/net/maildir/maildirUtils.cpp b/src/net/maildir/maildirUtils.cpp index 1737c611..c0594a31 100644 --- a/src/net/maildir/maildirUtils.cpp +++ b/src/net/maildir/maildirUtils.cpp @@ -34,7 +34,8 @@ const vmime::word maildirUtils::NEW_DIR("new", vmime::charset(vmime::charsets::U const utility::file::path maildirUtils::getFolderFSPath - (weak_ref store, const utility::path& folderPath, const FolderFSPathMode mode) + (ref store, const utility::path& folderPath, + const FolderFSPathMode mode) { // Root path utility::file::path path(store->getFileSystemPath()); diff --git a/src/net/pop3/POP3Folder.cpp b/src/net/pop3/POP3Folder.cpp index 0b177a3e..acffff7d 100644 --- a/src/net/pop3/POP3Folder.cpp +++ b/src/net/pop3/POP3Folder.cpp @@ -30,23 +30,25 @@ namespace net { namespace pop3 { -POP3Folder::POP3Folder(const folder::path& path, POP3Store* store) +POP3Folder::POP3Folder(const folder::path& path, ref store) : m_store(store), m_path(path), m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), m_mode(-1), m_open(false) { - m_store->registerFolder(this); + store->registerFolder(this); } POP3Folder::~POP3Folder() { - if (m_store) + ref store = m_store.acquire(); + + if (store) { if (m_open) close(false); - m_store->unregisterFolder(this); + store->unregisterFolder(this); } else if (m_open) { @@ -98,7 +100,9 @@ const folder::path POP3Folder::getFullPath() const void POP3Folder::open(const int mode, bool failIfModeIsNotAvailable) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); if (m_path.isEmpty()) @@ -113,15 +117,15 @@ void POP3Folder::open(const int mode, bool failIfModeIsNotAvailable) } else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") { - m_store->sendRequest("STAT"); + store->sendRequest("STAT"); string response; - m_store->readResponse(response, false); + store->readResponse(response, false); - if (!m_store->isSuccessResponse(response)) + if (!store->isSuccessResponse(response)) throw exceptions::command_error("STAT", response); - m_store->stripResponseCode(response, response); + store->stripResponseCode(response, response); std::istringstream iss(response); iss >> m_messageCount; @@ -140,7 +144,9 @@ void POP3Folder::open(const int mode, bool failIfModeIsNotAvailable) void POP3Folder::close(const bool expunge) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); if (!isOpen()) @@ -148,10 +154,10 @@ void POP3Folder::close(const bool expunge) if (!expunge) { - m_store->sendRequest("RSET"); + store->sendRequest("RSET"); string response; - m_store->readResponse(response, false); + store->readResponse(response, false); } m_open = false; @@ -178,7 +184,9 @@ void POP3Folder::create(const int /* type */) const bool POP3Folder::exists() { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); return (m_path.isEmpty() || (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX")); @@ -193,22 +201,26 @@ const bool POP3Folder::isOpen() const ref POP3Folder::getMessage(const int num) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); else if (num < 1 || num > m_messageCount) throw exceptions::message_not_found(); - return vmime::create (this, num); + return vmime::create (thisRef().dynamicCast (), num); } std::vector > POP3Folder::getMessages(const int from, const int to) { + ref store = m_store.acquire(); + const int to2 = (to == -1 ? m_messageCount : to); - if (!m_store) + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -216,9 +228,10 @@ std::vector > POP3Folder::getMessages(const int from, const int t throw exceptions::message_not_found(); std::vector > v; + ref thisFolder = thisRef().dynamicCast (); for (int i = from ; i <= to2 ; ++i) - v.push_back(vmime::create (this, i)); + v.push_back(vmime::create (thisFolder, i)); return (v); } @@ -226,19 +239,22 @@ std::vector > POP3Folder::getMessages(const int from, const int t std::vector > POP3Folder::getMessages(const std::vector & nums) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); std::vector > v; + ref thisFolder = thisRef().dynamicCast (); for (std::vector ::const_iterator it = nums.begin() ; it != nums.end() ; ++it) { if (*it < 1|| *it > m_messageCount) throw exceptions::message_not_found(); - v.push_back(vmime::create (this, *it)); + v.push_back(vmime::create (thisFolder, *it)); } return (v); @@ -247,7 +263,9 @@ std::vector > POP3Folder::getMessages(const std::vector & nu const int POP3Folder::getMessageCount() { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -258,22 +276,26 @@ const int POP3Folder::getMessageCount() ref POP3Folder::getFolder(const folder::path::component& name) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); - return vmime::create (m_path / name, m_store); + return vmime::create (m_path / name, store); } std::vector > POP3Folder::getFolders(const bool /* recursive */) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); if (m_path.isEmpty()) { std::vector > v; - v.push_back(vmime::create (folder::path::component("INBOX"), m_store)); + v.push_back(vmime::create (folder::path::component("INBOX"), store)); return (v); } else @@ -287,7 +309,9 @@ std::vector > POP3Folder::getFolders(const bool /* recursive */) void POP3Folder::fetchMessages(std::vector >& msg, const int options, utility::progressListener* progress) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -301,7 +325,8 @@ void POP3Folder::fetchMessages(std::vector >& msg, const int opti for (std::vector >::iterator it = msg.begin() ; it != msg.end() ; ++it) { - (*it).dynamicCast ()->fetch(this, options); + (*it).dynamicCast ()->fetch + (thisRef().dynamicCast (), options); if (progress) progress->progress(++current, total); @@ -313,15 +338,15 @@ void POP3Folder::fetchMessages(std::vector >& msg, const int opti std::ostringstream command; command << "LIST"; - m_store->sendRequest(command.str()); + store->sendRequest(command.str()); // Get the response string response; - m_store->readResponse(response, true, NULL); + store->readResponse(response, true, NULL); - if (m_store->isSuccessResponse(response)) + if (store->isSuccessResponse(response)) { - m_store->stripFirstLine(response, response, NULL); + store->stripFirstLine(response, response, NULL); // C: LIST // S: +OK @@ -358,15 +383,15 @@ void POP3Folder::fetchMessages(std::vector >& msg, const int opti std::ostringstream command; command << "UIDL"; - m_store->sendRequest(command.str()); + store->sendRequest(command.str()); // Get the response string response; - m_store->readResponse(response, true, NULL); + store->readResponse(response, true, NULL); - if (m_store->isSuccessResponse(response)) + if (store->isSuccessResponse(response)) { - m_store->stripFirstLine(response, response, NULL); + store->stripFirstLine(response, response, NULL); // C: UIDL // S: +OK @@ -396,12 +421,15 @@ void POP3Folder::fetchMessages(std::vector >& msg, const int opti void POP3Folder::fetchMessage(ref msg, const int options) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); - msg.dynamicCast ()->fetch(this, options); + msg.dynamicCast ()->fetch + (thisRef().dynamicCast (), options); if (options & FETCH_SIZE) { @@ -409,15 +437,15 @@ void POP3Folder::fetchMessage(ref msg, const int options) std::ostringstream command; command << "LIST " << msg->getNumber(); - m_store->sendRequest(command.str()); + store->sendRequest(command.str()); // Get the response string response; - m_store->readResponse(response, false, NULL); + store->readResponse(response, false, NULL); - if (m_store->isSuccessResponse(response)) + if (store->isSuccessResponse(response)) { - m_store->stripResponseCode(response, response); + store->stripResponseCode(response, response); // C: LIST 2 // S: +OK 2 4242 @@ -445,15 +473,15 @@ void POP3Folder::fetchMessage(ref msg, const int options) std::ostringstream command; command << "UIDL " << msg->getNumber(); - m_store->sendRequest(command.str()); + store->sendRequest(command.str()); // Get the response string response; - m_store->readResponse(response, false, NULL); + store->readResponse(response, false, NULL); - if (m_store->isSuccessResponse(response)) + if (store->isSuccessResponse(response)) { - m_store->stripResponseCode(response, response); + store->stripResponseCode(response, response); // C: UIDL 2 // S: +OK 2 QhdPYR:00WBw1Ph7x7 @@ -486,19 +514,19 @@ ref POP3Folder::getParent() if (m_path.isEmpty()) return NULL; else - return vmime::create (m_path.getParent(), m_store); + return vmime::create (m_path.getParent(), m_store.acquire()); } -weak_ref POP3Folder::getStore() const +ref POP3Folder::getStore() const { - return (m_store); + return m_store.acquire(); } -weak_ref POP3Folder::getStore() +ref POP3Folder::getStore() { - return (m_store); + return m_store.acquire(); } @@ -522,7 +550,9 @@ void POP3Folder::onStoreDisconnected() void POP3Folder::deleteMessage(const int num) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -530,12 +560,12 @@ void POP3Folder::deleteMessage(const int num) std::ostringstream command; command << "DELE " << num; - m_store->sendRequest(command.str()); + store->sendRequest(command.str()); string response; - m_store->readResponse(response, false); + store->readResponse(response, false); - if (!m_store->isSuccessResponse(response)) + if (!store->isSuccessResponse(response)) throw exceptions::command_error("DELE", response); // Update local flags @@ -562,10 +592,12 @@ void POP3Folder::deleteMessage(const int num) void POP3Folder::deleteMessages(const int from, const int to) { + ref store = m_store.acquire(); + if (from < 1 || (to < from && to != -1)) throw exceptions::invalid_argument(); - if (!m_store) + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -577,12 +609,12 @@ void POP3Folder::deleteMessages(const int from, const int to) std::ostringstream command; command << "DELE " << i; - m_store->sendRequest(command.str()); + store->sendRequest(command.str()); string response; - m_store->readResponse(response, false); + store->readResponse(response, false); - if (!m_store->isSuccessResponse(response)) + if (!store->isSuccessResponse(response)) throw exceptions::command_error("DELE", response); } @@ -612,10 +644,12 @@ void POP3Folder::deleteMessages(const int from, const int to) void POP3Folder::deleteMessages(const std::vector & nums) { + ref store = m_store.acquire(); + if (nums.empty()) throw exceptions::invalid_argument(); - if (!m_store) + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); @@ -626,12 +660,12 @@ void POP3Folder::deleteMessages(const std::vector & nums) std::ostringstream command; command << "DELE " << (*it); - m_store->sendRequest(command.str()); + store->sendRequest(command.str()); string response; - m_store->readResponse(response, false); + store->readResponse(response, false); - if (!m_store->isSuccessResponse(response)) + if (!store->isSuccessResponse(response)) throw exceptions::command_error("DELE", response); } @@ -716,20 +750,22 @@ void POP3Folder::copyMessages(const folder::path& /* dest */, const std::vector void POP3Folder::status(int& count, int& unseen) { - if (!m_store) + ref store = m_store.acquire(); + + if (!store) throw exceptions::illegal_state("Store disconnected"); else if (!isOpen()) throw exceptions::illegal_state("Folder not open"); - m_store->sendRequest("STAT"); + store->sendRequest("STAT"); string response; - m_store->readResponse(response, false); + store->readResponse(response, false); - if (!m_store->isSuccessResponse(response)) + if (!store->isSuccessResponse(response)) throw exceptions::command_error("STAT", response); - m_store->stripResponseCode(response, response); + store->stripResponseCode(response, response); std::istringstream iss(response); iss >> count; @@ -759,8 +795,8 @@ void POP3Folder::status(int& count, int& unseen) notifyMessageCount(event); // Notify folders with the same path - for (std::list ::iterator it = m_store->m_folders.begin() ; - it != m_store->m_folders.end() ; ++it) + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { if ((*it) != this && (*it)->getFullPath() == m_path) { diff --git a/src/net/pop3/POP3Message.cpp b/src/net/pop3/POP3Message.cpp index c4721dec..59b0406c 100644 --- a/src/net/pop3/POP3Message.cpp +++ b/src/net/pop3/POP3Message.cpp @@ -29,17 +29,19 @@ namespace net { namespace pop3 { -POP3Message::POP3Message(POP3Folder* folder, const int num) +POP3Message::POP3Message(ref folder, const int num) : m_folder(folder), m_num(num), m_size(-1), m_deleted(false) { - m_folder->registerMessage(this); + folder->registerMessage(this); } POP3Message::~POP3Message() { - if (m_folder) - m_folder->unregisterMessage(this); + ref folder = m_folder.acquire(); + + if (folder) + folder->unregisterMessage(this); } @@ -112,9 +114,11 @@ void POP3Message::extract(utility::outputStream& os, utility::progressListener* progress, const int start, const int length, const bool /* peek */) const { - if (!m_folder) + ref folder = m_folder.acquire(); + + if (!folder) throw exceptions::illegal_state("Folder closed"); - else if (!m_folder->m_store) + else if (!folder->getStore()) throw exceptions::illegal_state("Store disconnected"); if (start != 0 && length != -1) @@ -124,17 +128,17 @@ void POP3Message::extract(utility::outputStream& os, std::ostringstream oss; oss << "RETR " << m_num; - const_cast (m_folder)->m_store->sendRequest(oss.str()); + folder.constCast ()->m_store.acquire()->sendRequest(oss.str()); try { POP3Folder::MessageMap::const_iterator it = - m_folder->m_messages.find(const_cast (this)); + folder->m_messages.find(const_cast (this)); - const int totalSize = (it != m_folder->m_messages.end()) + const int totalSize = (it != folder.constCast ()->m_messages.end()) ? (*it).second : 0; - const_cast (m_folder)->m_store-> + folder.constCast ()->m_store.acquire()-> readResponse(os, progress, totalSize); } catch (exceptions::command_error& e) @@ -160,9 +164,11 @@ void POP3Message::fetchPartHeader(ref /* p */) } -void POP3Message::fetch(POP3Folder* folder, const int options) +void POP3Message::fetch(ref msgFolder, const int options) { - if (m_folder != folder) + ref folder = m_folder.acquire(); + + if (folder != msgFolder) throw exceptions::folder_not_found(); // FETCH_STRUCTURE and FETCH_FLAGS are not supported by POP3. @@ -185,12 +191,12 @@ void POP3Message::fetch(POP3Folder* folder, const int options) std::ostringstream oss; oss << "TOP " << m_num << " 0"; - m_folder->m_store->sendRequest(oss.str()); + folder->m_store.acquire()->sendRequest(oss.str()); try { string buffer; - m_folder->m_store->readResponse(buffer, true); + folder->m_store.acquire()->readResponse(buffer, true); m_header = vmime::create
(); m_header->parse(buffer); diff --git a/src/net/pop3/POP3Store.cpp b/src/net/pop3/POP3Store.cpp index 67f478cb..24e5b9c3 100644 --- a/src/net/pop3/POP3Store.cpp +++ b/src/net/pop3/POP3Store.cpp @@ -90,7 +90,8 @@ ref POP3Store::getDefaultFolder() if (!isConnected()) throw exceptions::illegal_state("Not connected"); - return vmime::create (folder::path(folder::path::component("INBOX")), this); + return vmime::create (folder::path(folder::path::component("INBOX")), + thisRef().dynamicCast ()); } @@ -99,7 +100,8 @@ ref POP3Store::getRootFolder() if (!isConnected()) throw exceptions::illegal_state("Not connected"); - return vmime::create (folder::path(), this); + return vmime::create (folder::path(), + thisRef().dynamicCast ()); } @@ -108,7 +110,8 @@ ref POP3Store::getFolder(const folder::path& path) if (!isConnected()) throw exceptions::illegal_state("Not connected"); - return vmime::create (path, this); + return vmime::create (path, + thisRef().dynamicCast ()); } diff --git a/src/object.cpp b/src/object.cpp index cf30a5fa..edce0a20 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -24,10 +24,6 @@ #include "vmime/types.hpp" #include "vmime/object.hpp" -#include // std::find -#include // std::ostringstream -#include // std::runtime_error - #ifndef VMIME_BUILDING_DOC @@ -37,155 +33,66 @@ namespace vmime object::object() - : m_strongCount(0) + : m_refMgr(new utility::refManager(this)) { } object::object(const object&) - : m_strongCount(0) + : m_refMgr(new utility::refManager(this)) { - // Not used +} + + +object& object::operator=(const object&) +{ + // Do _NOT_ copy 'm_refMgr' + return *this; } object::~object() { - for (std::vector ::iterator - it = m_weakRefs.begin() ; it != m_weakRefs.end() ; ++it) - { - (*it)->notifyObjectDestroyed(); - } - -#if VMIME_DEBUG - if (m_strongCount != 0) - { - std::ostringstream oss; - oss << "ERROR: Deleting object and strong count != 0." - << " (" << __FILE__ << ", line " << __LINE__ << ")" << std::endl; - - throw std::runtime_error(oss.str()); - } -#endif // VMIME_DEBUG -} - - -void object::addStrong() const -{ - ++m_strongCount; -} - - -void object::addWeak(utility::weak_ref_base* w) const -{ - m_weakRefs.push_back(w); -} - - -void object::releaseStrong() const -{ - if (--m_strongCount == 0) - delete this; -} - - -void object::releaseWeak(utility::weak_ref_base* w) const -{ - std::vector ::iterator - it = std::find(m_weakRefs.begin(), m_weakRefs.end(), w); - - if (it != m_weakRefs.end()) - m_weakRefs.erase(it); -#if VMIME_DEBUG - else - { - std::ostringstream oss; - oss << "ERROR: weak ref does not exist anymore!" - << " (" << __FILE__ << ", line " << __LINE__ << ")" << std::endl; - - throw std::runtime_error(oss.str()); - } -#endif // VMIME_DEBUG + delete m_refMgr; + m_refMgr = 0; } ref object::thisRef() { -#if VMIME_DEBUG - if (m_strongCount == 0) - { - std::ostringstream oss; - oss << "ERROR: thisRef() MUST NOT be called from the object constructor." - << " (" << __FILE__ << ", line " << __LINE__ << ")" << std::endl; - - throw std::runtime_error(oss.str()); - } -#endif // VMIME_DEBUG - + m_refMgr->addStrong(); return ref ::fromPtr(this); } ref object::thisRef() const { -#if VMIME_DEBUG - if (m_strongCount == 0) - { - std::ostringstream oss; - oss << "ERROR: thisRef() MUST NOT be called from the object constructor." - << " (" << __FILE__ << ", line " << __LINE__ << ")" << std::endl; - - throw std::runtime_error(oss.str()); - } -#endif // VMIME_DEBUG - + m_refMgr->addStrong(); return ref ::fromPtr(this); } weak_ref object::thisWeakRef() { -#if VMIME_DEBUG - if (m_strongCount == 0) - { - std::ostringstream oss; - oss << "ERROR: thisWeakRef() MUST NOT be called from the object constructor." - << " (" << __FILE__ << ", line " << __LINE__ << ")" << std::endl; - - throw std::runtime_error(oss.str()); - } -#endif // VMIME_DEBUG - return weak_ref (thisRef()); } weak_ref object::thisWeakRef() const { -#if VMIME_DEBUG - if (m_strongCount == 0) - { - std::ostringstream oss; - oss << "ERROR: thisWeakRef() MUST NOT be called from the object constructor." - << " (" << __FILE__ << ", line " << __LINE__ << ")" << std::endl; - - throw std::runtime_error(oss.str()); - } -#endif // VMIME_DEBUG - return weak_ref (thisRef()); } -const int object::getStrongRefCount() const +void object::setRefManager(utility::refManager* mgr) { - return m_strongCount; + m_refMgr = mgr; } -const int object::getWeakRefCount() const +utility::refManager* object::getRefManager() const { - return static_cast (m_weakRefs.size()); + return m_refMgr; } diff --git a/src/platformDependant.cpp b/src/platformDependant.cpp index a09cc5e4..c377b716 100644 --- a/src/platformDependant.cpp +++ b/src/platformDependant.cpp @@ -28,7 +28,7 @@ namespace vmime { -platformDependant::handler* platformDependant::sm_handler = NULL; +ref platformDependant::sm_handler = NULL; platformDependant::handler::~handler() diff --git a/src/security/defaultAuthenticator.cpp b/src/security/defaultAuthenticator.cpp index 010d7275..7c3402da 100644 --- a/src/security/defaultAuthenticator.cpp +++ b/src/security/defaultAuthenticator.cpp @@ -44,8 +44,10 @@ defaultAuthenticator::~defaultAuthenticator() const string defaultAuthenticator::getUsername() const { - const string prefix = m_service->getInfos().getPropertyPrefix(); - const propertySet& props = m_service->getSession()->getProperties(); + ref service = m_service.acquire(); + + const string prefix = service->getInfos().getPropertyPrefix(); + const propertySet& props = service->getSession()->getProperties(); if (props.hasProperty(prefix + net::serviceInfos::property::AUTH_USERNAME.getName())) return props[prefix + net::serviceInfos::property::AUTH_USERNAME.getName()]; @@ -56,8 +58,10 @@ const string defaultAuthenticator::getUsername() const const string defaultAuthenticator::getPassword() const { - const string prefix = m_service->getInfos().getPropertyPrefix(); - const propertySet& props = m_service->getSession()->getProperties(); + ref service = m_service.acquire(); + + const string prefix = service->getInfos().getPropertyPrefix(); + const propertySet& props = service->getSession()->getProperties(); if (props.hasProperty(prefix + net::serviceInfos::property::AUTH_PASSWORD.getName())) return props[prefix + net::serviceInfos::property::AUTH_PASSWORD.getName()]; diff --git a/src/utility/smartPtr.cpp b/src/utility/smartPtr.cpp new file mode 100644 index 00000000..376c1251 --- /dev/null +++ b/src/utility/smartPtr.cpp @@ -0,0 +1,166 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2006 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/object.hpp" +#include "vmime/utility/smartPtr.hpp" + + +namespace vmime { +namespace utility { + + +// refManager + +refManager::refManager(object* obj) + : m_object(obj), m_strongCount(1), m_weakCount(1) +{ +} + + +refManager::~refManager() +{ +} + + +const bool refManager::addStrong() +{ + if (m_strongCount <= 0) + return false; + + m_strongCount.increment(); + m_weakCount.increment(); + + return true; +} + + +void refManager::releaseStrong() +{ + m_strongCount.decrement(); + + if (m_strongCount.compareExchange(0, -424242) == 0) // prevent from adding strong refs later + deleteObject(); + + releaseWeak(); +} + + +void refManager::addWeak() +{ + m_weakCount.increment(); +} + + +void refManager::releaseWeak() +{ + if (m_weakCount.decrement() == 0) + deleteManager(); +} + + +object* refManager::getObject() +{ + return m_object; +} + + +void refManager::deleteManager() +{ + delete this; +} + + +void refManager::deleteObject() +{ + try + { + m_object->setRefManager(0); + delete m_object; + } + catch (...) + { + // Exception in destructor + } + + m_object = 0; +} + + +const long refManager::getStrongRefCount() const +{ + return m_strongCount; +} + + +const long refManager::getWeakRefCount() const +{ + return m_weakCount; +} + + + +// refCounter + +refCounter::refCounter(const long initialValue) + : m_value(initialValue) +{ +} + + +refCounter::~refCounter() +{ +} + + +const long refCounter::increment() +{ + return ++m_value; +} + + +const long refCounter::decrement() +{ + return --m_value; +} + + +const long refCounter::compareExchange(const long compare, const long exchangeWith) +{ + const int prev = m_value; + + if (m_value == compare) + m_value = exchangeWith; + + return prev; +} + + +refCounter::operator long() const +{ + return m_value; +} + + +} // utility +} // vmime + diff --git a/tests/utility/smartPtrTest.cpp b/tests/utility/smartPtrTest.cpp index 0ffaa1ec..fe652676 100644 --- a/tests/utility/smartPtrTest.cpp +++ b/tests/utility/smartPtrTest.cpp @@ -39,14 +39,13 @@ VMIME_TEST_SUITE_BEGIN VMIME_TEST(testCast) VMIME_TEST(testContainer) VMIME_TEST(testCompare) - VMIME_TEST(testThisRefCtor) VMIME_TEST_LIST_END struct A : public vmime::object { - const int strongCount() const { return getStrongRefCount(); } - const int weakCount() const { return getWeakRefCount(); } + const int strongCount() const { return getRefManager()->getStrongRefCount(); } + const int weakCount() const { return getRefManager()->getWeakRefCount(); } }; struct B : public virtual A { }; @@ -65,12 +64,6 @@ VMIME_TEST_SUITE_BEGIN bool* m_aliveFlag; }; - struct X : public vmime::object - { - X() { f(thisRef().dynamicCast ()); } - static void f(vmime::ref /* x */) { } - }; - void testNull() { @@ -94,13 +87,13 @@ VMIME_TEST_SUITE_BEGIN VASSERT("1", r1.get() != 0); VASSERT("2", o1_alive); VASSERT_EQ("3", 1, r1->strongCount()); - VASSERT_EQ("4", 0, r1->weakCount()); + VASSERT_EQ("4", 1, r1->weakCount()); vmime::ref r2 = r1; VASSERT("5", o1_alive); VASSERT_EQ("6", 2, r1->strongCount()); - VASSERT_EQ("7", 0, r1->weakCount()); + VASSERT_EQ("7", 2, r1->weakCount()); bool o2_alive; vmime::ref r3 = vmime::create (&o2_alive); @@ -138,12 +131,12 @@ VMIME_TEST_SUITE_BEGIN { vmime::weak_ref w1 = r3; - VASSERT_EQ("22", 1, r3->weakCount()); + VASSERT_EQ("22", 3, r3->weakCount()); } VASSERT("23", o2_alive); VASSERT_EQ("24", 2, r3->strongCount()); - VASSERT_EQ("25", 0, r3->weakCount()); + VASSERT_EQ("25", 2, r3->weakCount()); } void testWeakRef() @@ -152,21 +145,21 @@ VMIME_TEST_SUITE_BEGIN vmime::weak_ref w1 = r1; VASSERT("1", r1.get() != 0); - VASSERT("2", r1.get() == w1.get()); + VASSERT("2", r1.get() == w1.acquire().get()); { vmime::ref r2 = r1; VASSERT("3", r1.get() == r2.get()); - VASSERT("4", r1.get() == w1.get()); + VASSERT("4", r1.get() == w1.acquire().get()); } VASSERT("5", r1.get() != 0); - VASSERT("6", r1.get() == w1.get()); + VASSERT("6", r1.get() == w1.acquire().get()); r1 = 0; - VASSERT("7", w1.get() == 0); + VASSERT("7", w1.acquire().get() == 0); } void testCast() @@ -248,11 +241,5 @@ VMIME_TEST_SUITE_BEGIN VASSERT("10", std::find(v.begin(), v.end(), r3) == v.end()); } - void testThisRefCtor() - { - // BUGFIX: thisRef() MUST NOT be called from the object constructor - VASSERT_THROW("1", vmime::create (), std::runtime_error); - } - VMIME_TEST_SUITE_END diff --git a/vmime/body.hpp b/vmime/body.hpp index 90522779..f913e347 100644 --- a/vmime/body.hpp +++ b/vmime/body.hpp @@ -229,7 +229,7 @@ public: private: - void setParentPart(weak_ref parent); + void setParentPart(ref parent); string m_prologText; diff --git a/vmime/bodyPart.hpp b/vmime/bodyPart.hpp index c53ad33a..8bb7fdb4 100644 --- a/vmime/bodyPart.hpp +++ b/vmime/bodyPart.hpp @@ -75,7 +75,14 @@ public: * * @return parent part or NULL if not known */ - weak_ref getParentPart() const; + ref getParentPart(); + + /** Return the parent part of this part (const version). + * + * @return parent part or NULL if not known + */ + ref getParentPart() const; + ref clone() const; void copyFrom(const component& other); diff --git a/vmime/net/folder.hpp b/vmime/net/folder.hpp index 3dd72ed3..5edba493 100644 --- a/vmime/net/folder.hpp +++ b/vmime/net/folder.hpp @@ -306,13 +306,13 @@ public: * * @return the store object to which this folder is attached */ - virtual weak_ref getStore() const = 0; + virtual ref getStore() const = 0; /** Return a reference to the store to which this folder belongs. * * @return the store object to which this folder is attached */ - virtual weak_ref getStore() = 0; + virtual ref getStore() = 0; /** Fetchable objects. */ diff --git a/vmime/net/imap/IMAPConnection.hpp b/vmime/net/imap/IMAPConnection.hpp index 19c1193a..765937ec 100644 --- a/vmime/net/imap/IMAPConnection.hpp +++ b/vmime/net/imap/IMAPConnection.hpp @@ -50,7 +50,7 @@ class IMAPConnection : public object { public: - IMAPConnection(weak_ref store, ref auth); + IMAPConnection(ref store, ref auth); ~IMAPConnection(); @@ -84,8 +84,8 @@ public: ref getTag() const; ref getParser() const; - weak_ref getStore() const; - weak_ref getStore(); + ref getStore() const; + ref getStore(); ref getSession(); diff --git a/vmime/net/imap/IMAPFolder.hpp b/vmime/net/imap/IMAPFolder.hpp index 089c28dd..5662c349 100644 --- a/vmime/net/imap/IMAPFolder.hpp +++ b/vmime/net/imap/IMAPFolder.hpp @@ -55,7 +55,7 @@ private: friend class vmime::creator; // vmime::create - IMAPFolder(const folder::path& path, IMAPStore* store, const int type = TYPE_UNDEFINED, const int flags = FLAG_UNDEFINED); + IMAPFolder(const folder::path& path, ref store, const int type = TYPE_UNDEFINED, const int flags = FLAG_UNDEFINED); IMAPFolder(const IMAPFolder&) : folder() { } ~IMAPFolder(); @@ -109,8 +109,8 @@ public: ref getParent(); - weak_ref getStore() const; - weak_ref getStore(); + ref getStore() const; + ref getStore(); void fetchMessages(std::vector >& msg, const int options, utility::progressListener* progress = NULL); @@ -134,7 +134,7 @@ private: void copyMessages(const string& set, const folder::path& dest); - IMAPStore* m_store; + weak_ref m_store; ref m_connection; folder::path m_path; diff --git a/vmime/net/imap/IMAPMessage.hpp b/vmime/net/imap/IMAPMessage.hpp index a7f53a1e..7e8c6b07 100644 --- a/vmime/net/imap/IMAPMessage.hpp +++ b/vmime/net/imap/IMAPMessage.hpp @@ -49,7 +49,7 @@ private: friend class IMAPFolder; friend class vmime::creator; // vmime::create - IMAPMessage(IMAPFolder* folder, const int num); + IMAPMessage(ref folder, const int num); IMAPMessage(const IMAPMessage&) : message() { } ~IMAPMessage(); @@ -79,7 +79,7 @@ public: private: - void fetch(IMAPFolder* folder, const int options); + void fetch(ref folder, const int options); void processFetchResponse(const int options, const IMAPParser::msg_att* msgAtt); @@ -94,7 +94,7 @@ private: void onFolderClosed(); - IMAPFolder* m_folder; + weak_ref m_folder; int m_num; int m_size; diff --git a/vmime/net/imap/IMAPParser.hpp b/vmime/net/imap/IMAPParser.hpp index ac6310b2..1a6913dd 100644 --- a/vmime/net/imap/IMAPParser.hpp +++ b/vmime/net/imap/IMAPParser.hpp @@ -140,12 +140,12 @@ public: } - weak_ref tag() const + ref getTag() const { - return (m_tag); + return m_tag.acquire(); } - void setSocket(weak_ref sok) + void setSocket(ref sok) { m_socket = sok; } @@ -474,7 +474,7 @@ public: } } - if (tagString == string(*(parser.tag()))) + if (tagString == string(*parser.getTag())) { *currentPos = pos; } @@ -5072,17 +5072,20 @@ public: { string receiveBuffer; + ref toh = m_timeoutHandler.acquire(); + ref sok = m_socket.acquire(); + while (receiveBuffer.empty()) { // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) + if (toh && toh->isTimeOut()) { - if (!m_timeoutHandler->handleTimeOut()) + if (!toh->handleTimeOut()) throw exceptions::operation_timed_out(); } // We have received data: reset the time-out counter - m_socket->receive(receiveBuffer); + sok->receive(receiveBuffer); if (receiveBuffer.empty()) // buffer is empty { @@ -5091,8 +5094,8 @@ public: } // We have received data ... - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); + if (toh) + toh->resetTimeOut(); } m_buffer += receiveBuffer; @@ -5104,11 +5107,14 @@ public: string::size_type len = 0; string receiveBuffer; + ref toh = m_timeoutHandler.acquire(); + ref sok = m_socket.acquire(); + if (m_progress) m_progress->start(count); - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); + if (toh) + toh->resetTimeOut(); if (!m_buffer.empty()) { @@ -5129,16 +5135,16 @@ public: while (len < count) { // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) + if (toh && toh->isTimeOut()) { - if (!m_timeoutHandler->handleTimeOut()) + if (!toh->handleTimeOut()) throw exceptions::operation_timed_out(); - m_timeoutHandler->resetTimeOut(); + toh->resetTimeOut(); } // Receive data from the socket - m_socket->receive(receiveBuffer); + sok->receive(receiveBuffer); if (receiveBuffer.empty()) // buffer is empty { @@ -5147,8 +5153,8 @@ public: } // We have received data: reset the time-out counter - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); + if (toh) + toh->resetTimeOut(); if (len + receiveBuffer.length() > count) { diff --git a/vmime/net/maildir/maildirFolder.hpp b/vmime/net/maildir/maildirFolder.hpp index 3207c807..1e073b47 100644 --- a/vmime/net/maildir/maildirFolder.hpp +++ b/vmime/net/maildir/maildirFolder.hpp @@ -56,7 +56,7 @@ private: friend class vmime::creator; // vmime::create - maildirFolder(const folder::path& path, weak_ref store); + maildirFolder(const folder::path& path, ref store); maildirFolder(const maildirFolder&) : folder() { } ~maildirFolder(); @@ -110,8 +110,8 @@ public: ref getParent(); - weak_ref getStore() const; - weak_ref getStore(); + ref getStore() const; + ref getStore(); void fetchMessages(std::vector >& msg, const int options, utility::progressListener* progress = NULL); diff --git a/vmime/net/maildir/maildirMessage.hpp b/vmime/net/maildir/maildirMessage.hpp index b6fccad6..28f668e6 100644 --- a/vmime/net/maildir/maildirMessage.hpp +++ b/vmime/net/maildir/maildirMessage.hpp @@ -47,7 +47,7 @@ class maildirMessage : public message private: - maildirMessage(weak_ref folder, const int num); + maildirMessage(ref folder, const int num); maildirMessage(const maildirMessage&) : message() { } ~maildirMessage(); @@ -77,7 +77,7 @@ public: private: - void fetch(weak_ref folder, const int options); + void fetch(ref folder, const int options); void onFolderClosed(); diff --git a/vmime/net/maildir/maildirUtils.hpp b/vmime/net/maildir/maildirUtils.hpp index a56a0adc..94484bd5 100644 --- a/vmime/net/maildir/maildirUtils.hpp +++ b/vmime/net/maildir/maildirUtils.hpp @@ -77,7 +77,7 @@ public: * @param mode type of path to return (see FolderFSPathMode) * @return filesystem path for the specified folder */ - static const utility::file::path getFolderFSPath(weak_ref store, + static const utility::file::path getFolderFSPath(ref store, const utility::path& folderPath, const FolderFSPathMode mode); /** Test whether the specified file-system directory corresponds to diff --git a/vmime/net/pop3/POP3Folder.hpp b/vmime/net/pop3/POP3Folder.hpp index c0168b13..db4854f2 100644 --- a/vmime/net/pop3/POP3Folder.hpp +++ b/vmime/net/pop3/POP3Folder.hpp @@ -54,7 +54,7 @@ private: friend class POP3Message; friend class vmime::creator; // vmime::create - POP3Folder(const folder::path& path, POP3Store* store); + POP3Folder(const folder::path& path, ref store); POP3Folder(const POP3Folder&) : folder() { } ~POP3Folder(); @@ -108,8 +108,8 @@ public: ref getParent(); - weak_ref getStore() const; - weak_ref getStore(); + ref getStore() const; + ref getStore(); void fetchMessages(std::vector >& msg, const int options, utility::progressListener* progress = NULL); @@ -129,7 +129,7 @@ private: void parseMultiListOrUidlResponse(const string& response, std::map & result); - POP3Store* m_store; + weak_ref m_store; folder::path m_path; folder::path::component m_name; diff --git a/vmime/net/pop3/POP3Message.hpp b/vmime/net/pop3/POP3Message.hpp index e9dfca48..f9e3810c 100644 --- a/vmime/net/pop3/POP3Message.hpp +++ b/vmime/net/pop3/POP3Message.hpp @@ -49,7 +49,7 @@ private: friend class POP3Folder; friend class vmime::creator; // vmime::create - POP3Message(POP3Folder* folder, const int num); + POP3Message(ref folder, const int num); POP3Message(const POP3Message&) : message() { } ~POP3Message(); @@ -79,11 +79,11 @@ public: private: - void fetch(POP3Folder* folder, const int options); + void fetch(ref folder, const int options); void onFolderClosed(); - POP3Folder* m_folder; + weak_ref m_folder; int m_num; uid m_uid; int m_size; diff --git a/vmime/object.hpp b/vmime/object.hpp index b80b6bce..3e2819e2 100644 --- a/vmime/object.hpp +++ b/vmime/object.hpp @@ -44,84 +44,52 @@ class object template friend class utility::ref; template friend class utility::weak_ref; + friend class utility::refManager; + protected: object(); object(const object&); + object& operator=(const object&); + virtual ~object(); #ifndef VMIME_BUILDING_DOC - /** Add a strong reference to this object. A strong - * reference ensure the object remains alive. - */ - void addStrong() const; - - /** Add a weak reference to this object. A weak - * reference helps to resolve circular references. - */ - void addWeak(utility::weak_ref_base* w) const; - - /** Release a strong reference to this object. - * - * @return true if the object is not referenced anymore. - */ - void releaseStrong() const; - - /** Release a weak reference to this object. - * - * @return true if the object is not referenced anymore. - */ - void releaseWeak(utility::weak_ref_base* w) const; - /** Return a reference to this object. - * \warning NEVER CALL THIS FROM A CONSTRUCTOR! * * @return reference to self */ ref thisRef(); /** Return a reference to this object (const version). - * \warning NEVER CALL THIS FROM A CONSTRUCTOR! * * @return reference to self */ ref thisRef() const; /** Return a weak reference to this object. - * \warning NEVER CALL THIS FROM A CONSTRUCTOR! * * @return weak reference to self */ weak_ref thisWeakRef(); /** Return a weak reference to this object (const version). - * \warning NEVER CALL THIS FROM A CONSTRUCTOR! * * @return weak reference to self */ weak_ref thisWeakRef() const; - /** Return the number of strong refs to this object. - * For debugging purposes only. - * - * @return strong reference count - */ - const int getStrongRefCount() const; - /** Return the number of weak refs to this object. - * For debugging purposes only. - * - * @return weak reference count - */ - const int getWeakRefCount() const; + void setRefManager(utility::refManager* mgr); + utility::refManager* getRefManager() const; + #endif // VMIME_BUILDING_DOC private: - mutable int m_strongCount; - mutable std::vector m_weakRefs; + mutable utility::refManager* m_refMgr; }; diff --git a/vmime/platformDependant.hpp b/vmime/platformDependant.hpp index 1818deca..cd8a7ce2 100644 --- a/vmime/platformDependant.hpp +++ b/vmime/platformDependant.hpp @@ -56,7 +56,7 @@ public: * access platform-dependant objects: sockets, date/time, file system, etc. */ - class handler + class handler : public object { public: @@ -132,11 +132,10 @@ public: template static void setHandler() { - delete (sm_handler); - sm_handler = new TYPE; + sm_handler = vmime::create (); } - static const handler* getHandler() + static ref getHandler() { if (!sm_handler) throw exceptions::no_platform_dependant_handler(); @@ -146,7 +145,7 @@ public: private: - static handler* sm_handler; + static ref sm_handler; }; diff --git a/vmime/utility/smartPtr.hpp b/vmime/utility/smartPtr.hpp index 18d443d9..464faf05 100644 --- a/vmime/utility/smartPtr.hpp +++ b/vmime/utility/smartPtr.hpp @@ -58,6 +58,89 @@ public: }; +/** Reference counter for shared pointers. + */ + +class refCounter +{ +public: + + refCounter(const long initialValue); + ~refCounter(); + + const long increment(); + const long decrement(); + const long compareExchange(const long compare, const long exchangeWith); + + operator long() const; + +private: + + long m_value; +}; + + +/** Manage the life cycle of an object. + */ + +class refManager +{ +public: + + refManager(object* obj); + ~refManager(); + + /** Add a strong reference to the managed object. + */ + const bool addStrong(); + + /** Release a strong reference to the managed object. + * If it is the last reference, the object is destroyed. + */ + void releaseStrong(); + + /** Add a weak reference to the managed object. + */ + void addWeak(); + + /** Release a weak reference to the managed object. + * If it is the last weak reference, the manager is destroyed. + */ + void releaseWeak(); + + /** Return a raw pointer to the managed object. + * + * @return pointer to the managed object + */ + object* getObject(); + + /** Return the number of strong refs to this object. + * For debugging purposes only. + * + * @return strong reference count + */ + const long getStrongRefCount() const; + + /** Return the number of weak refs to this object. + * For debugging purposes only. + * + * @return weak reference count + */ + const long getWeakRefCount() const; + +private: + + void deleteManager(); + void deleteObject(); + + + object* m_object; + + refCounter m_strongCount; + refCounter m_weakCount; +}; + + /** Null reference. */ @@ -69,7 +152,11 @@ private: }; -/** Strong reference (smart pointer). +template +class weak_ref; + + +/** Shared ownership (strong reference to an object). */ template @@ -85,7 +172,7 @@ public: ref(const ref& r) : m_ptr(0) { attach(r); } ref(const null_ref&) : m_ptr(0) { } - virtual ~ref() { detach(); } + virtual ~ref() throw() { detach(); } // Allow creating NULL ref (NULL casts to anything*) ref(class null_pointer*) : m_ptr(0) { } @@ -112,12 +199,10 @@ public: U* p = dynamic_cast (const_cast (m_ptr)); if (!p) return ref (); - p->addStrong(); + if (m_ptr) + m_ptr->getRefManager()->addStrong(); - ref r; - r.m_ptr = p; - - return r; + return ref ::fromPtrImpl(p); } // static_cast @@ -127,12 +212,10 @@ public: U* p = static_cast (const_cast (m_ptr)); if (!p) return ref (); - p->addStrong(); + if (m_ptr) + m_ptr->getRefManager()->addStrong(); - ref r; - r.m_ptr = p; - - return r; + return ref ::fromPtrImpl(p); } // const_cast @@ -142,12 +225,10 @@ public: U* p = const_cast (m_ptr); if (!p) return ref (); - m_ptr->addStrong(); + if (m_ptr) + m_ptr->getRefManager()->addStrong(); - ref r; - r.m_ptr = p; - - return r; + return ref ::fromPtrImpl(p); } // Implicit downcast @@ -155,10 +236,10 @@ public: operator ref () const { if (m_ptr) - m_ptr->addStrong(); + m_ptr->getRefManager()->addStrong(); ref r; - r.m_ptr = m_ptr; // will type check at compile-time (prevent from implicit upcast) + r.m_ptr = m_ptr; // will type check at compile-time (prevent from implicit upcast) return r; } @@ -167,10 +248,10 @@ public: operator ref () { if (m_ptr) - m_ptr->addStrong(); + m_ptr->getRefManager()->addStrong(); ref r; - r.m_ptr = m_ptr; // will type check at compile-time (prevent from implicit upcast) + r.m_ptr = m_ptr; // will type check at compile-time (prevent from implicit upcast) return r; } @@ -181,7 +262,7 @@ public: U* ptr = other.m_ptr; // will type check at compile-time (prevent from implicit upcast) if (ptr) - ptr->addStrong(); + ptr->getRefManager()->addStrong(); detach(); @@ -194,12 +275,9 @@ public: operator ref () const { if (m_ptr) - m_ptr->addStrong(); + m_ptr->getRefManager()->addStrong(); - ref r; - r.m_ptr = m_ptr; - - return r; + return ref ::fromPtrImpl(m_ptr); } // Copy @@ -230,22 +308,50 @@ public: */ static ref fromPtr(T* const ptr) { - if (ptr) - ptr->addStrong(); + return ref ::fromPtrImpl(ptr); + } - ref r; + static ref fromPtrConst(const T* const ptr) + { + return ref ::fromPtrImpl(ptr); + } + + static ref fromWeak(weak_ref wr) + { + refManager* mgr = wr.getManager(); + + if (mgr && mgr->addStrong()) + return ref ::fromPtrImpl(dynamic_cast (mgr->getObject())); + else + return ref (); + } + + static ref fromWeakConst(weak_ref wr) + { + refManager* mgr = wr.getManager(); + + if (mgr && mgr->addStrong()) + return ref ::fromPtrImpl(dynamic_cast (mgr->getObject())); + else + return ref (); + } + +protected: + + template + static ref fromPtrImpl(U* ptr) + { + ref r; r.m_ptr = ptr; return r; } -protected: - void detach() { if (m_ptr) { - m_ptr->releaseStrong(); + m_ptr->getRefManager()->releaseStrong(); m_ptr = 0; } } @@ -254,7 +360,7 @@ protected: void attach(U* const ptr) { if (ptr) - ptr->addStrong(); + ptr->getRefManager()->addStrong(); detach(); @@ -265,7 +371,7 @@ protected: void attach(const ref & r) { if (r.m_ptr) - r.m_ptr->addStrong(); + r.m_ptr->getRefManager()->addStrong(); detach(); @@ -329,169 +435,64 @@ bool operator!=(const null_ref&, const ref & r) -/** Base class for weak references. - */ - -class weak_ref_base -{ - friend class vmime::object; // calls 'notifyObjectDestroyed' - -protected: - - weak_ref_base() { } - weak_ref_base(const weak_ref_base&) { } - virtual ~weak_ref_base() { } - - - virtual void notifyObjectDestroyed() = 0; -}; - - /** Weak reference. * Avoid circular references. */ template -class weak_ref : public weak_ref_base +class weak_ref { public: template friend class weak_ref; - weak_ref() : m_ptr(0) { } - weak_ref(const ref & r) : m_ptr(0) { attach(r); } - weak_ref(const weak_ref& r) : weak_ref_base(), m_ptr(0) { attach(r); } - weak_ref(const null_ref&) : m_ptr(0) { } - weak_ref(T* const p) : m_ptr(0) { attach(p); } + weak_ref() : m_mgr(0) { } + weak_ref(const ref & r) : m_mgr(0) { attach(r); } + weak_ref(const weak_ref& r) : m_mgr(0) { attach(r); } + weak_ref(const null_ref&) : m_mgr(0) { } + weak_ref(class null_pointer*) : m_mgr(0) { } ~weak_ref() { detach(); } - - // Access to wrapped object -// operator const T*() const { return m_ptr; } - operator const void*() const { return m_ptr; } - - T& operator *() { return *m_ptr; } - const T& operator *() const { return *m_ptr; } - - T* operator ->() { return m_ptr; } - const T* operator ->() const { return m_ptr; } - - const T* const get() const { return m_ptr; } - T* const get() { return m_ptr; } - - const bool operator !() const { return m_ptr == NULL; } - - - // dynamic_cast - template - weak_ref dynamicCast() const + /** Return the manager for the object. + * + * @return pointer to the object which manages the object + * or NULL if the weak reference points to nothing + */ + refManager* getManager() { - U* p = dynamic_cast (const_cast (m_ptr)); - if (!p) return weak_ref (); - - weak_ref r; - - p->addWeak(&r); - - r.m_ptr = p; - - return r; + return m_mgr; } - // static_cast - template - weak_ref staticCast() const + /** Try to acquire a strong reference to the object (const version). + * + * @return strong reference or null reference if the + * object is not available anymore + */ + ref acquire() const { - U* p = static_cast (const_cast (m_ptr)); - if (!p) return weak_ref (); - - weak_ref r; - - p->addWeak(&r); - - r.m_ptr = p; - - return r; + return ref ::fromWeakConst(*this); } - // const_cast - template - weak_ref constCast() const + /** Try to acquire a strong reference to the object. + * + * @return strong reference or null reference if the + * object is not available anymore + */ + ref acquire() { - U* p = const_cast (m_ptr); - if (!p) return weak_ref (); - - weak_ref r; - - p->addWeak(&r); - - r.m_ptr = p; - - return r; - } - - // Implicit downcast - template - operator weak_ref () - { - weak_ref r; - - if (m_ptr) - m_ptr->addWeak(&r); - - r.m_ptr = m_ptr; // will type check at compile-time (prevent from implicit upcast) - - return r; - } - - // Implicit downcast - template - operator weak_ref () - { - weak_ref r; - - if (m_ptr) - m_ptr->addWeak(&r); - - r.m_ptr = m_ptr; // will type check at compile-time (prevent from implicit upcast) - - return r; - } - - template - weak_ref & operator=(const weak_ref & other) - { - U* ptr = other.m_ptr; // will type check at compile-time (prevent from implicit upcast) - - if (ptr) - ptr->addWeak(this); - - detach(); - - m_ptr = ptr; - - return *this; - } - - ref toStrong() - { - if (m_ptr == NULL) - return ref (); - - return ref ::fromPtr(m_ptr); + return ref ::fromWeak(*this); } // Implicit non-const => const conversion operator weak_ref () const { + if (m_mgr) + m_mgr->addWeak(); + weak_ref r; - - if (m_ptr) - m_ptr->addWeak(&r); - - r.m_ptr = m_ptr; + r.m_mgr = m_mgr; return r; } @@ -499,12 +500,11 @@ public: template operator weak_ref () const { + if (m_mgr) + m_mgr->addWeak(); + weak_ref r; - - if (m_ptr) - m_ptr->addWeak(&r); - - r.m_ptr = m_ptr; + r.m_mgr = m_mgr; return r; } @@ -516,58 +516,42 @@ public: return *this; } - // NULL-pointer comparison - bool operator==(const class null_pointer*) const { return m_ptr == 0; } - bool operator!=(const class null_pointer*) const { return m_ptr != 0; } - private: - void notifyObjectDestroyed() - { - m_ptr = 0; - } - void detach() { - if (m_ptr) + if (m_mgr) { - m_ptr->releaseWeak(this); - m_ptr = 0; + m_mgr->releaseWeak(); + m_mgr = 0; } } void attach(const ref & r) { if (r.m_ptr) - r.m_ptr->addWeak(this); + r.m_ptr->getRefManager()->addWeak(); detach(); - m_ptr = r.m_ptr; + if (r.m_ptr) + m_mgr = r.m_ptr->getRefManager(); + else + m_mgr = 0; } void attach(const weak_ref& r) { - if (r.m_ptr) - r.m_ptr->addWeak(this); + if (r.m_mgr) + r.m_mgr->addWeak(); detach(); - m_ptr = r.m_ptr; - } - - void attach(T* const p) - { - if (p) - p->addWeak(this); - - detach(); - - m_ptr = p; + m_mgr = r.m_mgr; } - T* m_ptr; + refManager* m_mgr; };