From 8134a52f56697a51c734e1406d57a05fda77bac7 Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Sun, 15 May 2005 18:05:38 +0000 Subject: [PATCH] Service properties enhancement. --- ChangeLog | 6 + SConstruct | 5 +- examples/example6.cpp | 50 ------ examples/example7.cpp | 110 ++++++++++++ src/messaging/imap/IMAPConnection.cpp | 72 +++++++- src/messaging/imap/IMAPStore.cpp | 53 ++++-- src/messaging/maildir/maildirStore.cpp | 39 ++-- src/messaging/pop3/POP3Store.cpp | 79 +++++--- src/messaging/sendmail/sendmailTransport.cpp | 38 ++-- src/messaging/serviceInfos.cpp | 150 ++++++++++++++++ src/messaging/smtp/SMTPTransport.cpp | 71 +++++--- src/propertySet.cpp | 40 +++++ vmime/messaging/imap/IMAPConnection.hpp | 17 +- vmime/messaging/imap/IMAPStore.hpp | 21 ++- vmime/messaging/maildir/maildirStore.hpp | 9 +- vmime/messaging/pop3/POP3Store.hpp | 23 ++- .../messaging/sendmail/sendmailTransport.hpp | 9 +- vmime/messaging/serviceInfos.hpp | 170 ++++++++++++++++-- vmime/messaging/smtp/SMTPTransport.hpp | 20 ++- vmime/propertySet.hpp | 64 +++++++ 20 files changed, 861 insertions(+), 185 deletions(-) create mode 100644 examples/example7.cpp create mode 100644 src/messaging/serviceInfos.cpp diff --git a/ChangeLog b/ChangeLog index db343837..601b6992 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,12 @@ VERSION 0.7.1cvs ================ +2005-05-15 Vincent Richard + + * messaging/serviceInfos.{hpp|cpp}: changed getAvailableProperties() to + return 'serviceInfos::property' objects instead of strings. This permits + setting service properties in a more generic manner. + 2005-05-03 Vincent Richard * messaging/imap/IMAPFolder.cpp: fixed missing space in "STATUS" command + diff --git a/SConstruct b/SConstruct index 0c0f7725..56792a8e 100644 --- a/SConstruct +++ b/SConstruct @@ -176,7 +176,8 @@ libvmime_examples_sources = [ 'examples/example3.cpp', 'examples/example4.cpp', 'examples/example5.cpp', - 'examples/example6.cpp' + 'examples/example6.cpp', + 'examples/example7.cpp' ] libvmime_messaging_sources = [ @@ -190,7 +191,7 @@ libvmime_messaging_sources = [ 'messaging/message.cpp', 'messaging/message.hpp', 'messaging/service.cpp', 'messaging/service.hpp', 'messaging/serviceFactory.cpp', 'messaging/serviceFactory.hpp', - 'messaging/serviceInfos.hpp', + 'messaging/serviceInfos.cpp', 'messaging/serviceInfos.hpp', 'messaging/session.cpp', 'messaging/session.hpp', 'messaging/simpleAuthenticator.cpp', 'messaging/simpleAuthenticator.hpp', 'messaging/socket.hpp', diff --git a/examples/example6.cpp b/examples/example6.cpp index 3f3f3f37..304990d7 100644 --- a/examples/example6.cpp +++ b/examples/example6.cpp @@ -72,56 +72,6 @@ int main() // VMime initialization vmime::platformDependant::setHandler(); - // - // Test the new enumeration system for encoders - // - -#if 1 - vmime::encoderFactory* ef = vmime::encoderFactory::getInstance(); - - std::cout << "Available encoders:" << std::endl; - - for (int i = 0 ; i < ef->getEncoderCount() ; ++i) - { - const vmime::encoderFactory::registeredEncoder& enc = *ef->getEncoderAt(i); - - std::cout << " * " << enc.getName() << std::endl; - - vmime::encoder* e = enc.create(); - - std::vector props = e->getAvailableProperties(); - - for (std::vector ::const_iterator it = props.begin() ; it != props.end() ; ++it) - std::cout << " - " << *it << std::endl; - - delete (e); - } -#endif - - // ====================================================================================== - - // - // Test the new enumeration system for messaging services - // - -#if 1 - vmime::messaging::serviceFactory* sf = vmime::messaging::serviceFactory::getInstance(); - - std::cout << "Available messaging services:" << std::endl; - - for (int i = 0 ; i < sf->getServiceCount() ; ++i) - { - const vmime::messaging::serviceFactory::registeredService& serv = *sf->getServiceAt(i); - - std::cout << " * " << serv.getName() << " (" << serv.getInfos().getDefaultPort() << ")" << std::endl; - - std::vector props = serv.getInfos().getAvailableProperties(); - - for (std::vector ::const_iterator it = props.begin() ; it != props.end() ; ++it) - std::cout << " - " << serv.getInfos().getPropertyPrefix() + *it << std::endl; - } -#endif - vmime::messaging::session sess; sess.getProperties()["store.protocol"] = "imap"; sess.getProperties()["transport.protocol"] = "smtp"; diff --git a/examples/example7.cpp b/examples/example7.cpp new file mode 100644 index 00000000..16492bb4 --- /dev/null +++ b/examples/example7.cpp @@ -0,0 +1,110 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2005 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., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +// +// EXAMPLE DESCRIPTION: +// ==================== +// This sample program demonstrates how to enumerate encoders and +// messaging services in VMime. +// +// For more information, please visit: +// http://www.vmime.org/ +// + +#include + +#include "vmime/vmime.hpp" +#include "vmime/platforms/posix/posixHandler.hpp" + + +int main() +{ + // VMime initialization + vmime::platformDependant::setHandler(); + + // Enumerate encoders + vmime::encoderFactory* ef = vmime::encoderFactory::getInstance(); + + std::cout << "Available encoders:" << std::endl; + + for (int i = 0 ; i < ef->getEncoderCount() ; ++i) + { + const vmime::encoderFactory::registeredEncoder& enc = *ef->getEncoderAt(i); + + std::cout << " * " << enc.getName() << std::endl; + + vmime::encoder* e = enc.create(); + + std::vector props = e->getAvailableProperties(); + + for (std::vector ::const_iterator it = props.begin() ; it != props.end() ; ++it) + std::cout << " - " << *it << std::endl; + + delete (e); + } + + std::cout << std::endl; + + // Enumerate messaging services and their properties + vmime::messaging::serviceFactory* sf = vmime::messaging::serviceFactory::getInstance(); + + std::cout << "Available messaging services:" << std::endl; + + for (int i = 0 ; i < sf->getServiceCount() ; ++i) + { + const vmime::messaging::serviceFactory::registeredService& serv = *sf->getServiceAt(i); + + std::cout << " * " << serv.getName() << std::endl; + + std::vector props = + serv.getInfos().getAvailableProperties(); + + for (std::vector ::const_iterator it = props.begin() ; + it != props.end() ; ++it) + { + const vmime::messaging::serviceInfos::property& p = *it; + + const vmime::string name = serv.getInfos().getPropertyPrefix() + p.getName(); + + vmime::string type; + + switch (p.getType()) + { + case vmime::messaging::serviceInfos::property::TYPE_INTEGER: type = "TYPE_INTEGER"; break; + case vmime::messaging::serviceInfos::property::TYPE_STRING: type = "TYPE_STRING"; break; + case vmime::messaging::serviceInfos::property::TYPE_BOOL: type = "TYPE_BOOL"; break; + default: type = "(unknown)"; break; + } + + vmime::string flags; + + if (p.getFlags() & vmime::messaging::serviceInfos::property::FLAG_REQUIRED) + flags += " FLAG_REQUIRED"; + if (p.getFlags() & vmime::messaging::serviceInfos::property::FLAG_HIDDEN) + flags += " FLAG_HIDDEN"; + + std::cout << " - " << serv.getInfos().getPropertyPrefix() + p.getName(); + std::cout << " (type=" << type << ", flags=" << flags; + std::cout << ", defaultValue=" << p.getDefaultValue() << ")" << std::endl; + } + } + + std::cout << std::endl; +} + diff --git a/src/messaging/imap/IMAPConnection.cpp b/src/messaging/imap/IMAPConnection.cpp index 0f5934c8..37a132de 100644 --- a/src/messaging/imap/IMAPConnection.cpp +++ b/src/messaging/imap/IMAPConnection.cpp @@ -28,6 +28,15 @@ #include +// Helpers for service properties +#define GET_PROPERTY(type, prop) \ + (m_store->getInfos().getPropertyValue (getSession(), \ + dynamic_cast (m_store->getInfos()).getProperties().prop)) +#define HAS_PROPERTY(prop) \ + (m_store->getInfos().hasProperty(getSession(), \ + dynamic_cast (m_store->getInfos()).getProperties().prop)) + + namespace vmime { namespace messaging { namespace imap { @@ -60,28 +69,26 @@ void IMAPConnection::connect() m_state = STATE_NONE; m_hierarchySeparator = '\0'; - const string address = m_store->getSession()->getProperties()[m_store->getInfos().getPropertyPrefix() + "server.address"]; - const port_t port = m_store->getSession()->getProperties().getProperty(m_store->getInfos().getPropertyPrefix() + "server.port", m_store->getInfos().getDefaultPort()); + const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS); + const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT); // Create the time-out handler - if (m_store->getSession()->getProperties().hasProperty - (m_store->getInfos().getPropertyPrefix() + "timeout.factory")) + if (HAS_PROPERTY(PROPERTY_TIMEOUT_FACTORY)) { timeoutHandlerFactory* tof = platformDependant::getHandler()-> - getTimeoutHandlerFactory(m_store->getSession()->getProperties() - [m_store->getInfos().getPropertyPrefix() + "timeout.factory"]); + getTimeoutHandlerFactory(GET_PROPERTY(string, PROPERTY_TIMEOUT_FACTORY)); m_timeoutHandler = tof->create(); } // Create and connect the socket - socketFactory* sf = platformDependant::getHandler()->getSocketFactory - (m_store->getSession()->getProperties().getProperty - (m_store->getInfos().getPropertyPrefix() + "server.socket-factory", string("default"))); + socketFactory* sf = platformDependant::getHandler()-> + getSocketFactory(GET_PROPERTY(string, PROPERTY_SERVER_SOCKETFACTORY)); m_socket = sf->create(); m_socket->connect(address, port); + delete (m_tag); m_tag = new IMAPTag(); @@ -260,6 +267,53 @@ IMAPParser::response* IMAPConnection::readResponse(IMAPParser::literalHandler* l } +const IMAPConnection::ProtocolStates IMAPConnection::state() const +{ + return (m_state); +} + + +void IMAPConnection::setState(const ProtocolStates state) +{ + m_state = state; +} + +const char IMAPConnection::hierarchySeparator() const +{ + return (m_hierarchySeparator); +} + + +const IMAPTag* IMAPConnection::getTag() const +{ + return (m_tag); +} + + +const IMAPParser* IMAPConnection::getParser() const +{ + return (m_parser); +} + + +const IMAPStore* IMAPConnection::getStore() const +{ + return (m_store); +} + + +IMAPStore* IMAPConnection::getStore() +{ + return (m_store); +} + + +session* IMAPConnection::getSession() +{ + return (m_store->getSession()); +} + + } // imap } // messaging } // vmime diff --git a/src/messaging/imap/IMAPStore.cpp b/src/messaging/imap/IMAPStore.cpp index 81eab9a7..07b22351 100644 --- a/src/messaging/imap/IMAPStore.cpp +++ b/src/messaging/imap/IMAPStore.cpp @@ -230,15 +230,14 @@ const int IMAPStore::getCapabilities() const CAPABILITY_RENAME_FOLDER | CAPABILITY_ADD_MESSAGE | CAPABILITY_COPY_MESSAGE | - CAPABILITY_DELETE_MESSAGE | + CAPABILITY_DELETE_MESSAGE | CAPABILITY_PARTIAL_FETCH | CAPABILITY_MESSAGE_FLAGS | - CAPABILITY_EXTRACT_PART); + CAPABILITY_EXTRACT_PART); } - // Service infos IMAPStore::_infos IMAPStore::sm_infos; @@ -256,39 +255,57 @@ const serviceInfos& IMAPStore::getInfos() const } -const port_t IMAPStore::_infos::getDefaultPort() const -{ - return (143); -} - - const string IMAPStore::_infos::getPropertyPrefix() const { return "store.imap."; } -const std::vector IMAPStore::_infos::getAvailableProperties() const +const IMAPStore::_infos::props& IMAPStore::_infos::getProperties() const { - std::vector list; + static props p = + { + // IMAP-specific options + // (none) + + // Common properties + property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED), + property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED), + + property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED), + property(serviceInfos::property::SERVER_PORT, "143"), + property(serviceInfos::property::SERVER_SOCKETFACTORY), + + property(serviceInfos::property::TIMEOUT_FACTORY) + }; + + return p; +} + + +const std::vector IMAPStore::_infos::getAvailableProperties() const +{ + std::vector list; + const props& p = getProperties(); // IMAP-specific options - //list.push_back("auth.mechanism"); + // (none) // Common properties - list.push_back("auth.username"); - list.push_back("auth.password"); + list.push_back(p.PROPERTY_AUTH_USERNAME); + list.push_back(p.PROPERTY_AUTH_PASSWORD); - list.push_back("server.address"); - list.push_back("server.port"); - list.push_back("server.socket-factory"); + list.push_back(p.PROPERTY_SERVER_ADDRESS); + list.push_back(p.PROPERTY_SERVER_PORT); + list.push_back(p.PROPERTY_SERVER_SOCKETFACTORY); - list.push_back("timeout.factory"); + list.push_back(p.PROPERTY_TIMEOUT_FACTORY); return (list); } + } // imap } // messaging } // vmime diff --git a/src/messaging/maildir/maildirStore.cpp b/src/messaging/maildir/maildirStore.cpp index 7188a281..87204299 100644 --- a/src/messaging/maildir/maildirStore.cpp +++ b/src/messaging/maildir/maildirStore.cpp @@ -27,6 +27,13 @@ #include "vmime/platformDependant.hpp" +// Helpers for service properties +#define GET_PROPERTY(type, prop) \ + (sm_infos.getPropertyValue (getSession(), sm_infos.getProperties().prop)) +#define HAS_PROPERTY(prop) \ + (sm_infos.hasProperty(getSession(), sm_infos.getProperties().prop)) + + namespace vmime { namespace messaging { namespace maildir { @@ -108,8 +115,7 @@ void maildirStore::connect() // Get root directory utility::fileSystemFactory* fsf = platformDependant::getHandler()->getFileSystemFactory(); - m_fsPath = fsf->stringToPath - (getSession()->getProperties()[getInfos().getPropertyPrefix() + "server.rootpath"]); + m_fsPath = fsf->stringToPath(GET_PROPERTY(string, PROPERTY_SERVER_ROOTPATH)); utility::auto_ptr rootDir = fsf->create(m_fsPath); @@ -181,10 +187,10 @@ const int maildirStore::getCapabilities() const CAPABILITY_RENAME_FOLDER | CAPABILITY_ADD_MESSAGE | CAPABILITY_COPY_MESSAGE | - CAPABILITY_DELETE_MESSAGE | + CAPABILITY_DELETE_MESSAGE | CAPABILITY_PARTIAL_FETCH | CAPABILITY_MESSAGE_FLAGS | - CAPABILITY_EXTRACT_PART); + CAPABILITY_EXTRACT_PART); } @@ -207,23 +213,30 @@ const serviceInfos& maildirStore::getInfos() const } -const port_t maildirStore::_infos::getDefaultPort() const -{ - return (0); -} - - const string maildirStore::_infos::getPropertyPrefix() const { return "store.maildir."; } -const std::vector maildirStore::_infos::getAvailableProperties() const +const maildirStore::_infos::props& maildirStore::_infos::getProperties() const { - std::vector list; + static props p = + { + property(serviceInfos::property::SERVER_ROOTPATH, serviceInfos::property::FLAG_REQUIRED) + }; - list.push_back("server.rootpath"); + return p; +} + + +const std::vector maildirStore::_infos::getAvailableProperties() const +{ + std::vector list; + const props& p = getProperties(); + + // Maildir-specific properties + list.push_back(p.PROPERTY_SERVER_ROOTPATH); return (list); } diff --git a/src/messaging/pop3/POP3Store.cpp b/src/messaging/pop3/POP3Store.cpp index 69e09bc6..032a8f6f 100644 --- a/src/messaging/pop3/POP3Store.cpp +++ b/src/messaging/pop3/POP3Store.cpp @@ -28,6 +28,13 @@ #include +// Helpers for service properties +#define GET_PROPERTY(type, prop) \ + (sm_infos.getPropertyValue (getSession(), sm_infos.getProperties().prop)) +#define HAS_PROPERTY(prop) \ + (sm_infos.hasProperty(getSession(), sm_infos.getProperties().prop)) + + namespace vmime { namespace messaging { namespace pop3 { @@ -93,23 +100,21 @@ void POP3Store::connect() if (isConnected()) throw exceptions::already_connected(); - const string address = getSession()->getProperties()[sm_infos.getPropertyPrefix() + "server.address"]; - const port_t port = getSession()->getProperties().getProperty(sm_infos.getPropertyPrefix() + "server.port", sm_infos.getDefaultPort()); + const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS); + const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT); // Create the time-out handler - if (getSession()->getProperties().hasProperty - (sm_infos.getPropertyPrefix() + "timeout.factory")) + if (HAS_PROPERTY(PROPERTY_TIMEOUT_FACTORY)) { timeoutHandlerFactory* tof = platformDependant::getHandler()-> - getTimeoutHandlerFactory(getSession()->getProperties() - [sm_infos.getPropertyPrefix() + "timeout.factory"]); + getTimeoutHandlerFactory(GET_PROPERTY(string, PROPERTY_TIMEOUT_FACTORY)); m_timeoutHandler = tof->create(); } // Create and connect the socket - socketFactory* sf = platformDependant::getHandler()->getSocketFactory - (getSession()->getProperties().getProperty(sm_infos.getPropertyPrefix() + "server.socket-factory", string("default"))); + socketFactory* sf = platformDependant::getHandler()-> + getSocketFactory(GET_PROPERTY(string, PROPERTY_SERVER_SOCKETFACTORY)); m_socket = sf->create(); m_socket->connect(address, port); @@ -134,7 +139,7 @@ void POP3Store::connect() // --- S: +OK vincent is a valid mailbox messageId mid(response); - if (getSession()->getProperties().getProperty(sm_infos.getPropertyPrefix() + "options.apop", false)) + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP)) { if (mid.getLeft().length() && mid.getRight().length()) { @@ -149,8 +154,7 @@ void POP3Store::connect() } else { - if (getSession()->getProperties().getProperty(sm_infos.getPropertyPrefix() + - "options.apop.fallback", false) == false) + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) { internalDisconnect(); throw exceptions::authentication_error(response); @@ -160,8 +164,7 @@ void POP3Store::connect() else { // APOP not supported - if (getSession()->getProperties().getProperty(sm_infos.getPropertyPrefix() + - "options.apop.fallback", false) == false) + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) { // Can't fallback on basic authentification internalDisconnect(); @@ -591,35 +594,53 @@ const serviceInfos& POP3Store::getInfos() const } -const port_t POP3Store::_infos::getDefaultPort() const -{ - return (110); -} - - const string POP3Store::_infos::getPropertyPrefix() const { return "store.pop3."; } -const std::vector POP3Store::_infos::getAvailableProperties() const +const POP3Store::_infos::props& POP3Store::_infos::getProperties() const { - std::vector list; + static props p = + { + // POP3-specific options + property("options.apop", serviceInfos::property::TYPE_BOOL, "false"), + property("options.apop.fallback", serviceInfos::property::TYPE_BOOL, "false"), + + // Common properties + property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED), + property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED), + + property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED), + property(serviceInfos::property::SERVER_PORT, "110"), + property(serviceInfos::property::SERVER_SOCKETFACTORY), + + property(serviceInfos::property::TIMEOUT_FACTORY) + }; + + return p; +} + + +const std::vector POP3Store::_infos::getAvailableProperties() const +{ + std::vector list; + const props& p = getProperties(); // POP3-specific options - list.push_back("options.apop"); - list.push_back("options.apop.fallback"); + list.push_back(p.PROPERTY_OPTIONS_APOP); + list.push_back(p.PROPERTY_OPTIONS_APOP_FALLBACK); // Common properties - list.push_back("auth.username"); - list.push_back("auth.password"); + list.push_back(p.PROPERTY_AUTH_USERNAME); + list.push_back(p.PROPERTY_AUTH_PASSWORD); - list.push_back("server.address"); - list.push_back("server.port"); - list.push_back("server.socket-factory"); + list.push_back(p.PROPERTY_SERVER_ADDRESS); + list.push_back(p.PROPERTY_SERVER_PORT); + list.push_back(p.PROPERTY_SERVER_SOCKETFACTORY); - list.push_back("timeout.factory"); + list.push_back(p.PROPERTY_TIMEOUT_FACTORY); return (list); } diff --git a/src/messaging/sendmail/sendmailTransport.cpp b/src/messaging/sendmail/sendmailTransport.cpp index 1d4d2361..969cb7ae 100644 --- a/src/messaging/sendmail/sendmailTransport.cpp +++ b/src/messaging/sendmail/sendmailTransport.cpp @@ -28,6 +28,15 @@ #include "vmime/utility/childProcess.hpp" #include "vmime/utility/smartPtr.hpp" +#include "vmime/config.hpp" + + +// Helpers for service properties +#define GET_PROPERTY(type, prop) \ + (sm_infos.getPropertyValue (getSession(), sm_infos.getProperties().prop)) +#define HAS_PROPERTY(prop) \ + (sm_infos.hasProperty(getSession(), sm_infos.getProperties().prop)) + #if VMIME_BUILTIN_PLATFORM_POSIX @@ -62,8 +71,7 @@ void sendmailTransport::connect() throw exceptions::already_connected(); // Use the specified path for 'sendmail' or a default one if no path is specified - m_sendmailPath = getSession()->getProperties().getProperty - (sm_infos.getPropertyPrefix() + "binpath", string(VMIME_SENDMAIL_PATH)); + m_sendmailPath = GET_PROPERTY(string, PROPERTY_BINPATH); m_connected = true; } @@ -177,24 +185,30 @@ const serviceInfos& sendmailTransport::getInfos() const } -const port_t sendmailTransport::_infos::getDefaultPort() const -{ - return (0); -} - - const string sendmailTransport::_infos::getPropertyPrefix() const { return "transport.sendmail."; } -const std::vector sendmailTransport::_infos::getAvailableProperties() const +const sendmailTransport::_infos::props& sendmailTransport::_infos::getProperties() const { - std::vector list; + static props p = + { + // Path to sendmail (override default) + property("binpath", serviceInfos::property::TYPE_STRING, string(VMIME_SENDMAIL_PATH)) + }; - // Path to sendmail (override default) - list.push_back("binpath"); + return p; +} + + +const std::vector sendmailTransport::_infos::getAvailableProperties() const +{ + std::vector list; + const props& p = getProperties(); + + list.push_back(p.PROPERTY_BINPATH); return (list); } diff --git a/src/messaging/serviceInfos.cpp b/src/messaging/serviceInfos.cpp new file mode 100644 index 00000000..685ccf3e --- /dev/null +++ b/src/messaging/serviceInfos.cpp @@ -0,0 +1,150 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2005 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., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include "vmime/messaging/serviceInfos.hpp" + + +namespace vmime { +namespace messaging { + + +// Common properties +const serviceInfos::property serviceInfos::property::SERVER_ADDRESS + ("server.address", serviceInfos::property::TYPE_STRING); + +const serviceInfos::property serviceInfos::property::SERVER_PORT + ("server.port", serviceInfos::property::TYPE_INTEGER); + +const serviceInfos::property serviceInfos::property::SERVER_ROOTPATH + ("server.rootpath", serviceInfos::property::TYPE_STRING); + +const serviceInfos::property serviceInfos::property::SERVER_SOCKETFACTORY + ("server.socket-factory", serviceInfos::property::TYPE_STRING, "default"); + +const serviceInfos::property serviceInfos::property::AUTH_USERNAME + ("auth.username", serviceInfos::property::TYPE_STRING); + +const serviceInfos::property serviceInfos::property::AUTH_PASSWORD + ("auth.password", serviceInfos::property::TYPE_STRING); + +const serviceInfos::property serviceInfos::property::TIMEOUT_FACTORY + ("timeout.factory", serviceInfos::property::TYPE_STRING); + + + +// serviceInfos + +serviceInfos::serviceInfos() +{ +} + + +serviceInfos::serviceInfos(const serviceInfos&) +{ +} + + +serviceInfos& serviceInfos::operator=(const serviceInfos&) +{ + return (*this); +} + + +serviceInfos::~serviceInfos() +{ +} + + +const bool serviceInfos::hasProperty(session* s, const property& p) const +{ + return s->getProperties().hasProperty(getPropertyPrefix() + p.getName()); +} + + + +// serviceInfos::property + +serviceInfos::property::property + (const string& name, const Types type, + const string& defaultValue, const int flags) + : m_name(name), m_defaultValue(defaultValue), + m_type(type), m_flags(flags) +{ +} + + +serviceInfos::property::property + (const property& p, const int addFlags, const int removeFlags) +{ + m_name = p.m_name; + m_type = p.m_type; + m_defaultValue = p.m_defaultValue; + m_flags = (p.m_flags | addFlags) & ~removeFlags; +} + + +serviceInfos::property::property + (const property& p, const string& newDefaultValue, + const int addFlags, const int removeFlags) +{ + m_name = p.m_name; + m_type = p.m_type; + m_defaultValue = newDefaultValue; + m_flags = (p.m_flags | addFlags) & ~removeFlags; +} + + +serviceInfos::property& serviceInfos::property::operator=(const property& p) +{ + m_name = p.m_name; + m_type = p.m_type; + m_defaultValue = p.m_defaultValue; + m_flags = p.m_flags; + + return (*this); +} + + +const string& serviceInfos::property::getName() const +{ + return (m_name); +} + + +const string& serviceInfos::property::getDefaultValue() const +{ + return (m_defaultValue); +} + + +const serviceInfos::property::Types serviceInfos::property::getType() const +{ + return (m_type); +} + + +const int serviceInfos::property::getFlags() const +{ + return (m_flags); +} + + +} // messaging +} // vmime + diff --git a/src/messaging/smtp/SMTPTransport.cpp b/src/messaging/smtp/SMTPTransport.cpp index 4f7df174..a32b0c95 100644 --- a/src/messaging/smtp/SMTPTransport.cpp +++ b/src/messaging/smtp/SMTPTransport.cpp @@ -29,6 +29,13 @@ #include "vmime/utility/filteredStream.hpp" +// Helpers for service properties +#define GET_PROPERTY(type, prop) \ + (sm_infos.getPropertyValue (getSession(), sm_infos.getProperties().prop)) +#define HAS_PROPERTY(prop) \ + (sm_infos.hasProperty(getSession(), sm_infos.getProperties().prop)) + + namespace vmime { namespace messaging { namespace smtp { @@ -61,23 +68,21 @@ void SMTPTransport::connect() if (isConnected()) throw exceptions::already_connected(); - const string address = getSession()->getProperties()[sm_infos.getPropertyPrefix() + "server.address"]; - const port_t port = getSession()->getProperties().getProperty(sm_infos.getPropertyPrefix() + "server.port", sm_infos.getDefaultPort()); + const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS); + const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT); // Create the time-out handler - if (getSession()->getProperties().hasProperty - (sm_infos.getPropertyPrefix() + "timeout.factory")) + if (HAS_PROPERTY(PROPERTY_TIMEOUT_FACTORY)) { timeoutHandlerFactory* tof = platformDependant::getHandler()-> - getTimeoutHandlerFactory(getSession()->getProperties() - [sm_infos.getPropertyPrefix() + "timeout.factory"]); + getTimeoutHandlerFactory(GET_PROPERTY(string, PROPERTY_TIMEOUT_FACTORY)); m_timeoutHandler = tof->create(); } // Create and connect the socket - socketFactory* sf = platformDependant::getHandler()->getSocketFactory - (getSession()->getProperties().getProperty(sm_infos.getPropertyPrefix() + "server.socket-factory", string("default"))); + socketFactory* sf = platformDependant::getHandler()-> + getSocketFactory(GET_PROPERTY(string, PROPERTY_SERVER_SOCKETFACTORY)); m_socket = sf->create(); m_socket->connect(address, port); @@ -129,8 +134,7 @@ void SMTPTransport::connect() } // Authentication - if (getSession()->getProperties().getProperty - (sm_infos.getPropertyPrefix() + "options.need-authentication", false) == true) + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_NEEDAUTH)) { if (!m_extendedSMTP) { @@ -447,34 +451,51 @@ const serviceInfos& SMTPTransport::getInfos() const } -const port_t SMTPTransport::_infos::getDefaultPort() const -{ - return (25); -} - - const string SMTPTransport::_infos::getPropertyPrefix() const { return "transport.smtp."; } -const std::vector SMTPTransport::_infos::getAvailableProperties() const +const SMTPTransport::_infos::props& SMTPTransport::_infos::getProperties() const { - std::vector list; + static props p = + { + // SMTP-specific options + property("options.need-authentication", serviceInfos::property::TYPE_BOOL, "false"), + + // Common properties + property(serviceInfos::property::AUTH_USERNAME), + property(serviceInfos::property::AUTH_PASSWORD), + + property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED), + property(serviceInfos::property::SERVER_PORT, "25"), + property(serviceInfos::property::SERVER_SOCKETFACTORY), + + property(serviceInfos::property::TIMEOUT_FACTORY) + }; + + return p; +} + + +const std::vector SMTPTransport::_infos::getAvailableProperties() const +{ + std::vector list; + const props& p = getProperties(); // SMTP-specific options - list.push_back("options.need-authentication"); + list.push_back(p.PROPERTY_OPTIONS_NEEDAUTH); // Common properties - list.push_back("auth.username"); - list.push_back("auth.password"); + list.push_back(p.PROPERTY_AUTH_USERNAME); + list.push_back(p.PROPERTY_AUTH_PASSWORD); - list.push_back("server.address"); - list.push_back("server.port"); - list.push_back("server.socket-factory"); + list.push_back(p.PROPERTY_SERVER_ADDRESS); + list.push_back(p.PROPERTY_SERVER_PORT); + list.push_back(p.PROPERTY_SERVER_SOCKETFACTORY); - list.push_back("timeout.factory"); + list.push_back(p.PROPERTY_TIMEOUT_FACTORY); return (list); } diff --git a/src/propertySet.cpp b/src/propertySet.cpp index 67f923ef..88ee4f57 100644 --- a/src/propertySet.cpp +++ b/src/propertySet.cpp @@ -324,6 +324,46 @@ const bool propertySet::property::getValue() const } } + + + +template <> +const string propertySet::valueFromString(const string& value) +{ + return value; +} + + +template <> +const string propertySet::valueToString(const string& value) +{ + return value; +} + + +template <> +const bool propertySet::valueFromString(const string& value) +{ + if (utility::stringUtils::toLower(value) == "true") + return true; + else + { + int val = 0; + + std::istringstream iss(value); + iss >> val; + + return (!iss.fail() && val != 0); + } +} + + +template <> +const string propertySet::valueToString(const bool& value) +{ + return (value ? "true" : "false"); +} + #endif // VMIME_INLINE_TEMPLATE_SPECIALIZATION diff --git a/vmime/messaging/imap/IMAPConnection.hpp b/vmime/messaging/imap/IMAPConnection.hpp index 7fbba8c2..8cf37933 100644 --- a/vmime/messaging/imap/IMAPConnection.hpp +++ b/vmime/messaging/imap/IMAPConnection.hpp @@ -26,6 +26,7 @@ #include "vmime/messaging/authenticator.hpp" #include "vmime/messaging/socket.hpp" #include "vmime/messaging/timeoutHandler.hpp" +#include "vmime/messaging/session.hpp" #include "vmime/messaging/imap/IMAPParser.hpp" @@ -61,11 +62,11 @@ public: STATE_LOGOUT }; - const ProtocolStates state() const { return (m_state); } - void setState(const ProtocolStates state) { m_state = state; } + const ProtocolStates state() const; + void setState(const ProtocolStates state); - const char hierarchySeparator() const { return (m_hierarchySeparator); } + const char hierarchySeparator() const; void send(bool tag, const string& what, bool end); @@ -74,11 +75,13 @@ public: IMAPParser::response* readResponse(IMAPParser::literalHandler* lh = NULL); - const IMAPTag* getTag() const { return (m_tag); } - const IMAPParser* getParser() const { return (m_parser); } + const IMAPTag* getTag() const; + const IMAPParser* getParser() const; - const IMAPStore* getStore() const { return (m_store); } - IMAPStore* getStore() { return (m_store); } + const IMAPStore* getStore() const; + IMAPStore* getStore(); + + session* getSession(); private: diff --git a/vmime/messaging/imap/IMAPStore.hpp b/vmime/messaging/imap/IMAPStore.hpp index 97206f2e..3ce7b8de 100644 --- a/vmime/messaging/imap/IMAPStore.hpp +++ b/vmime/messaging/imap/IMAPStore.hpp @@ -47,6 +47,7 @@ class IMAPStore : public store { friend class IMAPFolder; friend class IMAPMessage; + friend class IMAPConnection; public: @@ -101,10 +102,26 @@ private: { public: - const port_t getDefaultPort() const; + struct props + { + // IMAP-specific options + // (none) + + // Common properties + serviceInfos::property PROPERTY_AUTH_USERNAME; + serviceInfos::property PROPERTY_AUTH_PASSWORD; + + serviceInfos::property PROPERTY_SERVER_ADDRESS; + serviceInfos::property PROPERTY_SERVER_PORT; + serviceInfos::property PROPERTY_SERVER_SOCKETFACTORY; + + serviceInfos::property PROPERTY_TIMEOUT_FACTORY; + }; + + const props& getProperties() const; const string getPropertyPrefix() const; - const std::vector getAvailableProperties() const; + const std::vector getAvailableProperties() const; }; static _infos sm_infos; diff --git a/vmime/messaging/maildir/maildirStore.hpp b/vmime/messaging/maildir/maildirStore.hpp index a5b0ec27..25007e09 100644 --- a/vmime/messaging/maildir/maildirStore.hpp +++ b/vmime/messaging/maildir/maildirStore.hpp @@ -91,10 +91,15 @@ private: { public: - const port_t getDefaultPort() const; + struct props + { + serviceInfos::property PROPERTY_SERVER_ROOTPATH; + }; + + const props& getProperties() const; const string getPropertyPrefix() const; - const std::vector getAvailableProperties() const; + const std::vector getAvailableProperties() const; }; static _infos sm_infos; diff --git a/vmime/messaging/pop3/POP3Store.hpp b/vmime/messaging/pop3/POP3Store.hpp index c7528f9c..fc8210c0 100644 --- a/vmime/messaging/pop3/POP3Store.hpp +++ b/vmime/messaging/pop3/POP3Store.hpp @@ -43,6 +43,8 @@ class POP3Store : public store friend class POP3Folder; friend class POP3Message; +private: + public: POP3Store(session* sess, authenticator* auth); @@ -100,10 +102,27 @@ private: { public: - const port_t getDefaultPort() const; + struct props + { + // POP3-specific options + serviceInfos::property PROPERTY_OPTIONS_APOP; + serviceInfos::property PROPERTY_OPTIONS_APOP_FALLBACK; + + // Common properties + serviceInfos::property PROPERTY_AUTH_USERNAME; + serviceInfos::property PROPERTY_AUTH_PASSWORD; + + serviceInfos::property PROPERTY_SERVER_ADDRESS; + serviceInfos::property PROPERTY_SERVER_PORT; + serviceInfos::property PROPERTY_SERVER_SOCKETFACTORY; + + serviceInfos::property PROPERTY_TIMEOUT_FACTORY; + }; + + const props& getProperties() const; const string getPropertyPrefix() const; - const std::vector getAvailableProperties() const; + const std::vector getAvailableProperties() const; }; static _infos sm_infos; diff --git a/vmime/messaging/sendmail/sendmailTransport.hpp b/vmime/messaging/sendmail/sendmailTransport.hpp index e3ee78c5..accf45b9 100644 --- a/vmime/messaging/sendmail/sendmailTransport.hpp +++ b/vmime/messaging/sendmail/sendmailTransport.hpp @@ -77,10 +77,15 @@ private: { public: - const port_t getDefaultPort() const; + struct props + { + serviceInfos::property PROPERTY_BINPATH; + }; + + const props& getProperties() const; const string getPropertyPrefix() const; - const std::vector getAvailableProperties() const; + const std::vector getAvailableProperties() const; }; static _infos sm_infos; diff --git a/vmime/messaging/serviceInfos.hpp b/vmime/messaging/serviceInfos.hpp index b83a24d8..d812512e 100644 --- a/vmime/messaging/serviceInfos.hpp +++ b/vmime/messaging/serviceInfos.hpp @@ -25,6 +25,8 @@ #include "vmime/types.hpp" +#include "vmime/messaging/session.hpp" + namespace vmime { namespace messaging { @@ -39,22 +41,143 @@ class serviceInfos protected: - serviceInfos() { } - serviceInfos(const serviceInfos&) { } + serviceInfos(); + serviceInfos(const serviceInfos&); private: - serviceInfos& operator=(const serviceInfos&) { return (*this); } + serviceInfos& operator=(const serviceInfos&); public: - virtual ~serviceInfos() { } + virtual ~serviceInfos(); - /** Return the default port used for the underlying protocol. - * - * @return default port number + + /** A service property. */ - virtual const port_t getDefaultPort() const = 0; + class property + { + public: + + /** The common property 'server.address' which is + * the host name or the IP address of the server. */ + static const property SERVER_ADDRESS; + + /** The common property 'server.port' which is + * the port used to connect to the server. */ + static const property SERVER_PORT; + + /** The common property 'server.rootpath' which is + * the full path of the folder on the server (for + * maildir, this is the local filesystem directory). */ + static const property SERVER_ROOTPATH; + + /** The common property 'server.socket-factory' used + * to indicate which factory to use to instanciate + * new socket objects. */ + static const property SERVER_SOCKETFACTORY; + + /** The common property 'auth.username' which is the + * username used to authenticate with the server. */ + static const property AUTH_USERNAME; + + /** The common property 'auth.password' which is the + * password used to authenticate with the server. */ + static const property AUTH_PASSWORD; + + /** The common property 'timeout.factory' used to + * specify which factory to use to instanciate + * time-out handler objects. If none is specified, + * no time-out handler is used. */ + static const property TIMEOUT_FACTORY; + + + /** Value types. + */ + enum Types + { + TYPE_INTEGER, /*< Integer number. */ + TYPE_STRING, /*< Character string. */ + TYPE_BOOL, /*< Boolean (true or false). */ + + TYPE_DEFAULT = TYPE_STRING + }; + + /** Property flags. + */ + enum Flags + { + FLAG_NONE = 0, /*< No flags. */ + FLAG_REQUIRED = (1 << 0), /*< The property must be valued. */ + FLAG_HIDDEN = (1 << 1), /*< The property should not be shown + to the user but can be modified. */ + + FLAG_DEFAULT = FLAG_NONE /*< Default flags. */ + }; + + + /** Construct a new property. + * + * @param name property name + * @param type value type + * @param defaultValue default value + * @param flags property attributes + */ + property(const string& name, const Types type, const string& defaultValue = "", const int flags = FLAG_DEFAULT); + + /** Construct a new property from an existing property. + * + * @param p source property + * @param addFlags flags to add + * @param removeFlags flags to remove + */ + property(const property& p, const int addFlags = FLAG_NONE, const int removeFlags = FLAG_NONE); + + /** Construct a new property from an existing property. + * + * @param p source property + * @param newDefaultValue new default value + * @param addFlags flags to add + * @param removeFlags flags to remove + */ + property(const property& p, const string& newDefaultValue, const int addFlags = FLAG_NONE, const int removeFlags = FLAG_NONE); + + property& operator=(const property& p); + + /** Return the name of the property. + * + * @return property name + */ + const string& getName() const; + + /** Return the default value of the property or + * an empty string if there is no default value. + * + * @return default value for the property + */ + const string& getDefaultValue() const; + + /** Return the value type of the property. + * + * @return property value type + */ + const Types getType() const; + + /** Return the attributes of the property (see + * serviceInfos::property::Types constants). + * + * @return property attributes + */ + const int getFlags() const; + + private: + + string m_name; + string m_defaultValue; + Types m_type; + int m_flags; + }; + /** Return the property prefix used by this service. * Use this to set/get properties in the session object. @@ -65,9 +188,36 @@ public: /** Return a list of available properties for this service. * - * @return list of property names + * @return list of properties */ - virtual const std::vector getAvailableProperties() const = 0; + virtual const std::vector getAvailableProperties() const = 0; + + /** Helper function to retrieve the value of a property. + * + * @param s session object + * @param p property to retrieve + * @throw exceptions::no_such_property if the property does not exist + * and has the flag property::FLAG_REQUIRED + * @return value of the property + */ + template + const TYPE getPropertyValue(session* s, const property& p) const + { + if (p.getFlags() & property::FLAG_REQUIRED) + return s->getProperties()[getPropertyPrefix() + p.getName()].template getValue (); + + return s->getProperties().template getProperty (getPropertyPrefix() + p.getName(), + propertySet::valueFromString (p.getDefaultValue())); + } + + /** Helper function to test if the specified property is set in + * the session object. + * + * @param s session object + * @param p property to test + * @return true if the property is set, false otherwise + */ + const bool hasProperty(session* s, const property& p) const; }; diff --git a/vmime/messaging/smtp/SMTPTransport.hpp b/vmime/messaging/smtp/SMTPTransport.hpp index 3ccfdd49..61a5a7fe 100644 --- a/vmime/messaging/smtp/SMTPTransport.hpp +++ b/vmime/messaging/smtp/SMTPTransport.hpp @@ -79,10 +79,26 @@ private: { public: - const port_t getDefaultPort() const; + struct props + { + // SMTP-specific options + serviceInfos::property PROPERTY_OPTIONS_NEEDAUTH; + + // Common properties + serviceInfos::property PROPERTY_AUTH_USERNAME; + serviceInfos::property PROPERTY_AUTH_PASSWORD; + + serviceInfos::property PROPERTY_SERVER_ADDRESS; + serviceInfos::property PROPERTY_SERVER_PORT; + serviceInfos::property PROPERTY_SERVER_SOCKETFACTORY; + + serviceInfos::property PROPERTY_TIMEOUT_FACTORY; + }; + + const props& getProperties() const; const string getPropertyPrefix() const; - const std::vector getAvailableProperties() const; + const std::vector getAvailableProperties() const; }; static _infos sm_infos; diff --git a/vmime/propertySet.hpp b/vmime/propertySet.hpp index 1a05c632..46df7a95 100644 --- a/vmime/propertySet.hpp +++ b/vmime/propertySet.hpp @@ -342,6 +342,64 @@ private: public: + template + static const TYPE valueFromString(const string& value) + { + TYPE v = TYPE(); + + std::istringstream iss(value); + iss >> v; + + return v; + } + + template + static const string valueToString(const TYPE& value) + { + std::ostringstream oss(value); + oss << value; + + return oss.str(); + } + +#ifdef VMIME_INLINE_TEMPLATE_SPECIALIZATION + + template <> + static const string valueFromString(const string& value) + { + return value; + } + + template <> + static const string valueToString(const string& value) + { + return value; + } + + template <> + static const bool valueFromString(const string& value) + { + if (utility::stringUtils::toLower(m_value) == "true") + return true; + else + { + int val = 0; + + std::istringstream iss(m_value); + iss >> val; + + return (!iss.fail() && val != 0); + } + } + + template <> + static const string valueToString(const bool& value) + { + return (value ? "true" : "false"); + } + +#endif // VMIME_INLINE_TEMPLATE_SPECIALIZATION + /** Return the property list. * * @return list of properties @@ -364,6 +422,12 @@ template <> void propertySet::property::setValue(const bool& value); template <> const string propertySet::property::getValue() const; template <> const bool propertySet::property::getValue() const; +template <> const string propertySet::valueFromString(const string& value); +template <> const string propertySet::valueToString(const string& value); + +template <> const bool propertySet::valueFromString(const string& value); +template <> const string propertySet::valueToString(const bool& value); + #endif // VMIME_INLINE_TEMPLATE_SPECIALIZATION