diff options
Diffstat (limited to 'vmime-master/examples/example6.cpp')
-rw-r--r-- | vmime-master/examples/example6.cpp | 938 |
1 files changed, 938 insertions, 0 deletions
diff --git a/vmime-master/examples/example6.cpp b/vmime-master/examples/example6.cpp new file mode 100644 index 0000000..add24b3 --- /dev/null +++ b/vmime-master/examples/example6.cpp @@ -0,0 +1,938 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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 <iostream> +#include <sstream> +#include <vector> +#include <map> +#include <locale> +#include <clocale> + +#include "vmime/vmime.hpp" +#include "vmime/platforms/posix/posixHandler.hpp" + +#include "example6_tracer.hpp" +#include "example6_authenticator.hpp" +#include "example6_certificateVerifier.hpp" +#include "example6_timeoutHandler.hpp" + + +// Global session object +static vmime::shared_ptr <vmime::net::session> g_session = vmime::net::session::create(); + + +/** Returns the messaging protocols supported by VMime. + * + * @param type service type (vmime::net::service::TYPE_STORE or + * vmime::net::service::TYPE_TRANSPORT) + */ +static const std::string findAvailableProtocols(const vmime::net::service::Type type) { + + vmime::shared_ptr <vmime::net::serviceFactory> sf = + vmime::net::serviceFactory::getInstance(); + + std::ostringstream res; + size_t count = 0; + + for (size_t i = 0 ; i < sf->getServiceCount() ; ++i) { + + const vmime::net::serviceFactory::registeredService& serv = *sf->getServiceAt(i); + + if (serv.getType() == type) { + + if (count != 0) { + res << ", "; + } + + res << serv.getName(); + ++count; + } + } + + return res.str(); +} + + +// Exception helper +static std::ostream& operator<<(std::ostream& os, const vmime::exception& e) { + + os << "* vmime::exceptions::" << e.name() << std::endl; + os << " what = " << e.what() << std::endl; + + // More information for special exceptions + if (dynamic_cast <const vmime::exceptions::command_error*>(&e)) { + + const vmime::exceptions::command_error& cee = + dynamic_cast <const vmime::exceptions::command_error&>(e); + + os << " command = " << cee.command() << std::endl; + os << " response = " << cee.response() << std::endl; + } + + if (dynamic_cast <const vmime::exceptions::invalid_response*>(&e)) { + + const vmime::exceptions::invalid_response& ir = + dynamic_cast <const vmime::exceptions::invalid_response&>(e); + + os << " response = " << ir.response() << std::endl; + } + + if (dynamic_cast <const vmime::exceptions::connection_greeting_error*>(&e)) { + + const vmime::exceptions::connection_greeting_error& cgee = + dynamic_cast <const vmime::exceptions::connection_greeting_error&>(e); + + os << " response = " << cgee.response() << std::endl; + } + + if (dynamic_cast <const vmime::exceptions::authentication_error*>(&e)) { + + const vmime::exceptions::authentication_error& aee = + dynamic_cast <const vmime::exceptions::authentication_error&>(e); + + os << " response = " << aee.response() << std::endl; + } + + if (dynamic_cast <const vmime::exceptions::filesystem_exception*>(&e)) { + + const vmime::exceptions::filesystem_exception& fse = + dynamic_cast <const vmime::exceptions::filesystem_exception&>(e); + + os << " path = " << vmime::platform::getHandler()-> + getFileSystemFactory()->pathToString(fse.path()) << std::endl; + } + + if (e.other()) { + os << *e.other(); + } + + return os; +} + + +/** Print the MIME structure of a message on the standard output. + * + * @param s structure object + * @param level current depth + */ +static void printStructure( + vmime::shared_ptr <const vmime::net::messageStructure> s, + const int level = 0 +) { + + for (size_t i = 0 ; i < s->getPartCount() ; ++i) { + + vmime::shared_ptr <const vmime::net::messagePart> part = s->getPartAt(i); + + for (int j = 0 ; j < level * 2 ; ++j) { + std::cout << " "; + } + + std::cout + << (part->getNumber() + 1) << ". " + << part->getType().generate() + << " [" << part->getSize() << " byte(s)]" + << std::endl; + + printStructure(part->getStructure(), level + 1); + } +} + + +static const vmime::string getFolderPathString(vmime::shared_ptr <vmime::net::folder> f) { + + const vmime::string n = f->getName().getBuffer(); + + if (n.empty()) { // root folder + + return "/"; + + } else { + + vmime::shared_ptr <vmime::net::folder> p = f->getParent(); + return getFolderPathString(p) + n + "/"; + } +} + + +/** Print folders and sub-folders on the standard output. + * + * @param folder current folder + */ +static void printFolders(vmime::shared_ptr <vmime::net::folder> folder, const int level = 0) { + + for (int j = 0 ; j < level * 2 ; ++j) { + std::cout << " "; + } + + const vmime::net::folderAttributes attr = folder->getAttributes(); + std::ostringstream attrStr; + + if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_ALL) { + attrStr << " \\use:All"; + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_ARCHIVE) { + attrStr << " \\use:Archive"; + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_DRAFTS) { + attrStr << " \\use:Drafts"; + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_FLAGGED) { + attrStr << " \\use:Flagged"; + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_JUNK) { + attrStr << " \\use:Junk"; + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_SENT) { + attrStr << " \\use:Sent"; + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_TRASH) { + attrStr << " \\use:Trash"; + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_IMPORTANT) { + attrStr << " \\use:Important"; + } + + if (attr.getFlags() & vmime::net::folderAttributes::FLAG_HAS_CHILDREN) { + attrStr << " \\flag:HasChildren"; + } + if (attr.getFlags() & vmime::net::folderAttributes::FLAG_NO_OPEN) { + attrStr << " \\flag:NoOpen"; + } + + for (size_t i = 0, n = attr.getUserFlags().size() ; i < n ; ++i) { + attrStr << " \\" << attr.getUserFlags()[i]; + } + + std::cout << getFolderPathString(folder); + std::cout << " " << attrStr.str(); + std::cout << std::endl; + + std::vector <vmime::shared_ptr <vmime::net::folder> > subFolders = folder->getFolders(false); + + for (unsigned int i = 0 ; i < subFolders.size() ; ++i) { + printFolders(subFolders[i], level + 1); + } +} + + +/** Print a menu on the standard output. + * + * @param choices menu choices + */ +static unsigned int printMenu(const std::vector <std::string>& choices) { + + std::cout << std::endl; + + for (unsigned int i = 0 ; i < choices.size() ; ++i) { + std::cout << " " << (i + 1) << ". " << choices[i] << std::endl; + } + + std::cout << std::endl; + std::cout << " Your choice? [1-" << choices.size() << "] "; + std::cout.flush(); + + std::string line; + std::getline(std::cin, line); + + std::istringstream iss(line); + + unsigned int choice = 0; + iss >> choice; + + std::cout << std::endl; + + if (choice < 1 || choice > choices.size()) { + return 0; + } else { + return choice; + } +} + + +/** Send a message interactively. + */ +static void sendMessage() { + + try { + + // Request user to enter an URL + std::cout << "Enter an URL to connect to transport service." << std::endl; + std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_TRANSPORT) << std::endl; + std::cout << "(eg. smtp://myserver.com, sendmail://localhost)" << std::endl; + std::cout << "> "; + std::cout.flush(); + + vmime::string urlString; + std::getline(std::cin, urlString); + + vmime::utility::url url(urlString); + + vmime::shared_ptr <vmime::net::transport> tr; + + if (url.getUsername().empty() || url.getPassword().empty()) { + tr = g_session->getTransport(url, vmime::make_shared <interactiveAuthenticator>()); + } else { + tr = g_session->getTransport(url); + } + +#if VMIME_HAVE_TLS_SUPPORT + + // Enable TLS support if available + tr->setProperty("connection.tls", true); + + // Set the time out handler + tr->setTimeoutHandlerFactory(vmime::make_shared <timeoutHandlerFactory>()); + + // Set the object responsible for verifying certificates, in the + // case a secured connection is used (TLS/SSL) + tr->setCertificateVerifier( + vmime::make_shared <interactiveCertificateVerifier>() + ); + +#endif // VMIME_HAVE_TLS_SUPPORT + + // You can also set some properties (see example7 to know the properties + // available for each service). For example, for SMTP: + if (!url.getUsername().empty() || !url.getPassword().empty()) { + tr->setProperty("options.need-authentication", true); + } + + // Trace communication between client and server + vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>(); + tr->setTracerFactory(vmime::make_shared <myTracerFactory>(traceStream)); + + // Information about the mail + std::cout << "Enter email of the expeditor (eg. me@somewhere.com): "; + std::cout.flush(); + + vmime::string fromString; + std::getline(std::cin, fromString); + + vmime::mailbox from(fromString); + vmime::mailboxList to; + + for (bool cont = true ; cont ; ) { + + std::cout << "Enter email of the recipient (empty to stop): "; + std::cout.flush(); + + vmime::string toString; + std::getline(std::cin, toString); + + cont = (toString.size() != 0); + + if (cont) { + to.appendMailbox(vmime::make_shared <vmime::mailbox>(toString)); + } + } + + std::cout << "Enter message data, including headers (end with '.' on a single line):" << std::endl; + + std::ostringstream data; + + for (bool cont = true ; cont ; ) { + + std::string line; + std::getline(std::cin, line); + + if (line == ".") { + cont = false; + } else { + data << line << "\r\n"; + } + } + + // Connect to server + tr->connect(); + + // Send the message + vmime::string msgData = data.str(); + vmime::utility::inputStreamStringAdapter vis(msgData); + + tr->send(from, to, vis, msgData.length()); + + // Note: you could also write this: + // vmime::message msg; + // ... + // tr->send(&msg); + + // Display connection log + std::cout << std::endl; + std::cout << "Connection Trace:" << std::endl; + std::cout << "=================" << std::endl; + std::cout << traceStream->str(); + + tr->disconnect(); + + } catch (vmime::exception& e) { + + std::cerr << std::endl; + std::cerr << e << std::endl; + throw; + + } catch (std::exception& e) { + + std::cerr << std::endl; + std::cerr << "std::exception: " << e.what() << std::endl; + throw; + } +} + + +/** Connect to a message store interactively. + */ +static void connectStore() { + + try { + + // Request user to enter an URL + std::cout << "Enter an URL to connect to store service." << std::endl; + std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_STORE) << std::endl; + std::cout << "(eg. pop3://user:pass@myserver.com, imap://myserver.com:123)" << std::endl; + std::cout << "> "; + std::cout.flush(); + + vmime::string urlString; + std::getline(std::cin, urlString); + + vmime::utility::url url(urlString); + + // If no authenticator is given in argument to getStore(), a default one + // is used. Its behaviour is to get the user credentials from the + // session properties "auth.username" and "auth.password". + vmime::shared_ptr <vmime::net::store> st; + + if (url.getUsername().empty() || url.getPassword().empty()) { + st = g_session->getStore(url, vmime::make_shared <interactiveAuthenticator>()); + } else { + st = g_session->getStore(url); + } + +#if VMIME_HAVE_TLS_SUPPORT + + // Enable TLS support if available + st->setProperty("connection.tls", true); + + // Set the time out handler + st->setTimeoutHandlerFactory(vmime::make_shared <timeoutHandlerFactory>()); + + // Set the object responsible for verifying certificates, in the + // case a secured connection is used (TLS/SSL) + st->setCertificateVerifier( + vmime::make_shared <interactiveCertificateVerifier>() + ); + +#endif // VMIME_HAVE_TLS_SUPPORT + + // Trace communication between client and server + vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>(); + st->setTracerFactory(vmime::make_shared <myTracerFactory>(traceStream)); + + // Connect to the mail store + st->connect(); + + // Display some information about the connection + vmime::shared_ptr <vmime::net::connectionInfos> ci = st->getConnectionInfos(); + + std::cout << std::endl; + std::cout << "Connected to '" << ci->getHost() << "' (port " << ci->getPort() << ")" << std::endl; + std::cout << "Connection is " << (st->isSecuredConnection() ? "" : "NOT ") << "secured." << std::endl; + + // Open the default folder in this store + vmime::shared_ptr <vmime::net::folder> f = st->getDefaultFolder(); +// vmime::shared_ptr <vmime::net::folder> f = st->getFolder(vmime::utility::path("a")); + + f->open(vmime::net::folder::MODE_READ_WRITE); + + vmime::size_t count = f->getMessageCount(); + + std::cout << std::endl; + std::cout << count << " message(s) in your inbox" << std::endl; + + for (bool cont = true ; cont ; ) { + + typedef std::map <vmime::size_t, vmime::shared_ptr <vmime::net::message> > MessageList; + MessageList msgList; + + try { + + std::vector <std::string> choices; + + choices.push_back("Show message flags"); + choices.push_back("Show message structure"); + choices.push_back("Show message header"); + choices.push_back("Show message envelope"); + choices.push_back("Extract whole message"); + choices.push_back("Extract attachments"); + choices.push_back("Status"); + choices.push_back("List folders"); + choices.push_back("Change folder"); + choices.push_back("Add message (to the current folder)"); + choices.push_back("Copy message (into the current folder)"); + choices.push_back("Display trace output"); + choices.push_back("Return to main menu"); + + const int choice = printMenu(choices); + + // Request message number + vmime::shared_ptr <vmime::net::message> msg; + + if (choice == 1 || choice == 2 || choice == 3 || choice == 4 || + choice == 5 || choice == 6 || choice == 11) { + + std::cout << "Enter message number: "; + std::cout.flush(); + + std::string line; + std::getline(std::cin, line); + + std::istringstream iss(line); + + vmime::size_t num = 0; + iss >> num; + + if (num < 1 || num > f->getMessageCount()) { + + std::cerr << "Invalid message number." << std::endl; + continue; + } + + MessageList::iterator it = msgList.find(num); + + if (it != msgList.end()) { + + msg = (*it).second; + + } else { + + msg = f->getMessage(num); + msgList.insert(MessageList::value_type(num, msg)); + } + + std::cout << std::endl; + } + + switch (choice) { + + // Show message flags + case 1: + + f->fetchMessage(msg, vmime::net::fetchAttributes::FLAGS); + + if (msg->getFlags() & vmime::net::message::FLAG_SEEN) { + std::cout << "FLAG_SEEN" << std::endl; + } + if (msg->getFlags() & vmime::net::message::FLAG_RECENT) { + std::cout << "FLAG_RECENT" << std::endl; + } + if (msg->getFlags() & vmime::net::message::FLAG_REPLIED) { + std::cout << "FLAG_REPLIED" << std::endl; + } + if (msg->getFlags() & vmime::net::message::FLAG_DELETED) { + std::cout << "FLAG_DELETED" << std::endl; + } + if (msg->getFlags() & vmime::net::message::FLAG_MARKED) { + std::cout << "FLAG_MARKED" << std::endl; + } + if (msg->getFlags() & vmime::net::message::FLAG_PASSED) { + std::cout << "FLAG_PASSED" << std::endl; + } + + break; + + // Show message structure + case 2: + + f->fetchMessage(msg, vmime::net::fetchAttributes::STRUCTURE); + printStructure(msg->getStructure()); + break; + + // Show message header + case 3: + + f->fetchMessage(msg, vmime::net::fetchAttributes::FULL_HEADER); + std::cout << msg->getHeader()->generate() << std::endl; + break; + + // Show message envelope + case 4: { + + vmime::net::fetchAttributes attr(vmime::net::fetchAttributes::ENVELOPE); + + // If you also want to fetch "Received: " fields: + //attr.add("Received"); + + f->fetchMessage(msg, attr); + + std::cout << msg->getHeader()->generate() << std::endl; + + break; + } + // Extract whole message + case 5: { + + vmime::utility::outputStreamAdapter out(std::cout); + msg->extract(out); + + break; + } + // Extract attachments + case 6: { + + vmime::shared_ptr <vmime::message> parsedMsg = msg->getParsedMessage(); + + std::vector <vmime::shared_ptr <const vmime::attachment> > attchs = + vmime::attachmentHelper::findAttachmentsInMessage(parsedMsg); + + if (attchs.size() > 0) { + + std::cout << attchs.size() << " attachments found." << std::endl; + + for (std::vector <vmime::shared_ptr <const vmime::attachment> >::iterator + it = attchs.begin() ; it != attchs.end() ; ++it) { + + vmime::shared_ptr <const vmime::attachment> att = *it; + + // Get attachment size + vmime::size_t size = 0; + + if (att->getData()->isEncoded()) { + size = att->getData()->getEncoding().getEncoder()->getDecodedSize(att->getData()->getLength()); + } else { + size = att->getData()->getLength(); + } + + std::cout << "Found attachment '" << att->getName().getBuffer() << "'" + << ", size is " << size << " bytes:" << std::endl; + + // Get attachment data + std::cout << std::endl; + std::cout << "========== BEGIN CONTENT ==========" << std::endl; + + vmime::utility::outputStreamAdapter osa(std::cout); + att->getData()->extract(osa); + + std::cout << std::endl; + std::cout << "========== END CONTENT ==========" << std::endl; + + // Or write it to a file + /* + vmime::shared_ptr <vmime::utility::fileSystemFactory> fsf + = vmime::platform::getHandler()->getFileSystemFactory(); + + vmime::shared_ptr <vmime::utility::file> file + = fsf->create(vmime::utility::path::fromString + ("/path/to/attachment-file", "/", vmime::charsets::UTF_8)); + // -or- ("C:\\Temp\\attachment-file", "\\", vmime::charsets::UTF_8)); + + file->createFile(); + + vmime::shared_ptr <vmime::utility::outputStream> output = + file->getFileWriter()->getOutputStream(); + + att->getData()->extract(*output.get()); + */ + } + + } else { + + std::cout << "No attachments found." << std::endl; + } + + break; + } + // Status + case 7: { + + vmime::size_t count, unseen; + f->status(count, unseen); + + std::cout << "Status: count=" << count << ", unseen=" << unseen << std::endl; + break; + } + // List folders + case 8: { + + vmime::shared_ptr <vmime::net::folder> root = st->getRootFolder(); + + printFolders(root); + break; + } + // Change folder + case 9: { + + std::cout << "Enter folder path (eg. /root/subfolder):" << std::endl; + std::cout.flush(); + + std::string path; + std::getline(std::cin, path); + + vmime::shared_ptr <vmime::net::folder> newFolder = st->getRootFolder(); + + for (std::string::size_type s = 0, p = 0 ; ; s = p + 1) { + + p = path.find_first_of('/', s); + + const std::string x = (p == std::string::npos) + ? std::string(path.begin() + s, path.end()) + : std::string(path.begin() + s, path.begin() + p); + + if (!x.empty()) { + newFolder = newFolder->getFolder(vmime::utility::path::component(x)); + } + + if (p == std::string::npos) { + break; + } + } + + newFolder->open(vmime::net::folder::MODE_READ_WRITE); + + count = newFolder->getMessageCount(); + + std::cout << std::endl; + std::cout << count << " message(s) in this folder" << std::endl; + + f->close(true); // 'true' to expunge deleted messages + f = newFolder; + + break; + } + // Add message + case 10: { + + vmime::messageBuilder mb; + + mb.setExpeditor(vmime::mailbox("me@somewhere.com")); + + vmime::addressList to; + to.appendAddress(vmime::make_shared <vmime::mailbox>("you@elsewhere.com")); + mb.setRecipients(to); + + mb.setSubject(vmime::text("Test message from VMime example6")); + mb.getTextPart()->setText( + vmime::make_shared <vmime::stringContentHandler>( + "Body of test message from VMime example6." + ) + ); + + vmime::shared_ptr <vmime::message> msg = mb.construct(); + + vmime::net::messageSet set = f->addMessage(msg); + + if (set.isEmpty()) { + + std::cout << "Message has successfully been added, " + << "but its UID/number is not known." << std::endl; + + } else { + + const vmime::net::messageRange& range = set.getRangeAt(0); + + if (set.isUIDSet()) { + + const vmime::net::message::uid uid = + dynamic_cast <const vmime::net::UIDMessageRange&>(range).getFirst(); + + std::cout << "Message has successfully been added, " + << "its UID is '" << uid << "'." << std::endl; + + } else { + + const vmime::size_t number = + dynamic_cast <const vmime::net::numberMessageRange&>(range).getFirst(); + + std::cout << "Message has successfully been added, " + << "its number is '" << number << "'." << std::endl; + } + } + + break; + } + // Copy message + case 11: { + + vmime::net::messageSet set = f->copyMessages(f->getFullPath(), + vmime::net::messageSet::byNumber(msg->getNumber())); + + if (set.isEmpty()) { + + std::cout << "Message has successfully been copied, " + << "but its UID/number is not known." << std::endl; + + } else { + + const vmime::net::messageRange& range = set.getRangeAt(0); + + if (set.isUIDSet()) { + + const vmime::net::message::uid uid = + dynamic_cast <const vmime::net::UIDMessageRange&>(range).getFirst(); + + std::cout << "Message has successfully been copied, " + << "its UID is '" << uid << "'." << std::endl; + + } else { + + const vmime::size_t number = + dynamic_cast <const vmime::net::numberMessageRange&>(range).getFirst(); + + std::cout << "Message has successfully been copied, " + << "its number is '" << number << "'." << std::endl; + } + } + + break; + } + // Display trace output + case 12: + + std::cout << std::endl; + std::cout << "Connection Trace:" << std::endl; + std::cout << "=================" << std::endl; + std::cout << traceStream->str(); + break; + + // Main menu + case 13: + + f->close(true); // 'true' to expunge deleted messages + cont = false; + break; + } + +/* + // Append message + std::istringstream iss( + "From: me@localhost\r\n" + "To: you@localhost\r\n" + "Subject: Message Text\r\n" + "\r\n" + "This is a test message...\r\n" + "Bye bye!\r\n" + ); + + f->addMessage(iss, iss.str().size()); + + // Folder renaming + { + vmime::shared_ptr <vmime::net::folder> f = st->getFolder(vmime::net::folder::path("c")); + f->rename(vmime::net::folder::path("c2")); + + vmime::shared_ptr <vmime::net::folder> g = st->getFolder(vmime::net::folder::path("c2")); + g->rename(vmime::net::folder::path("c")); + } + + // Message copy: copy all messages from 'f' to 'g' + { + vmime::shared_ptr <vmime::net::folder> g = st->getFolder(vmime::net::folder::path("TEMP")); + + if (!g->exists()) { + g->create(vmime::net::folder::TYPE_CONTAINS_MESSAGES); + } + + f->copyMessages(g->getFullPath()); + } +*/ + + } catch (vmime::exception& e) { + + std::cerr << std::endl; + std::cerr << e << std::endl; + + } catch (std::exception& e) { + + std::cerr << std::endl; + std::cerr << "std::exception: " << e.what() << std::endl; + } + + } // for(cont) + + st->disconnect(); + + } catch (vmime::exception& e) { + + std::cerr << std::endl; + std::cerr << e << std::endl; + throw; + + } catch (std::exception& e) { + + std::cerr << std::endl; + std::cerr << "std::exception: " << e.what() << std::endl; + throw; + } +} + + +/* Show the main menu. + * + * @return true to quit the program, false to continue + */ +static bool menu() { + + std::vector <std::string> items; + + items.push_back("Connect to a message store"); + items.push_back("Send a message"); + items.push_back("Quit"); + + switch (printMenu(items)) { + + // Connect to store + case 1: + + connectStore(); + return false; + + // Send a message + case 2: + + sendMessage(); + return false; + + // Quit + case 3: + + return true; + + // Other choice + default: + + return false; + } +} + + +int main() { + + // Set the global C and C++ locale to the user-configured locale. + // The locale should use UTF-8 encoding for these tests to run successfully. + try { + std::locale::global(std::locale("")); + } catch (std::exception &) { + std::setlocale(LC_ALL, ""); + } + + for (bool quit = false ; !quit ; ) { + + // Loop on main menu + quit = menu(); + } + + return 0; +} |