diff --git a/HACKING b/HACKING index f31aa84d..a1cf21ca 100644 --- a/HACKING +++ b/HACKING @@ -80,73 +80,91 @@ width to its preferred settings (eg. 4 or 8 spaces). 2.2. Brace position ------------------- -Open braces should always be at the beginning of the line after the statement -that begins the block. Contents of the brace should be indented by 1 tab. +Open braces should always be at the end of the line of the statement that +begins the block. Contents of the brace should be indented by 1 tab. + + if (expr) { - if (expr) - { do_something(); do_another_thing(); - } - else - { + + } else { + do_something_else(); } +In a function, the opening brace must always be followed by an empty line: + + void header::appendField(const shared_ptr & field) { + + m_fields.push_back(field); + } + +A function with few arguments: + + bool header::hasField(const string& fieldName) const { + + ... + } + +A function with more arguments: + + void header::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition + ) { + + ... + } + 2.3. "switch" statement ----------------------- - switch (expr) - { - case 0: + switch (expr) { - something; - break; + case 0: - case 1: + something; + break; - something_else; - break; + case 1: - case 2: - { - int var = 42; - another_thing; - break; - } + something_else; + break; + case 2: { + + int var = 42; + another_thing; + break; + } } 2.4. Single instruction ----------------------- -Omit braces around simple single-statement body: +Don't omit braces around simple single-statement body: - if (...) + if (...) { something; + } and not: if (...) - { something; - } - -Except when body spans over multiple lines: - - if (...) - { - something_too_long_for( - a_single_line); - } 2.5. Line length ---------------- -Each line of text should not exceed 80 characters. +If possible, each line of text should not exceed 100 characters, except if +manual line wrapping breaks code clarity. Exception: if a comment line contains an example command or a literal URL longer than 100 characters, that line may be longer than 100 characters @@ -290,8 +308,8 @@ Where ever possible, place comments above the code instead of beside it. Comments can be placed at the end of a line when one or more spaces follow. Tabs should NOT be used to indent at the end of a line: - class myClass - { + class myClass { + private: int m_member1; // first member @@ -322,8 +340,8 @@ the purpose of the functions/classes and the meaning of the parameters. * No more than one class per file (except for inner classes). -* Put the inclusion for the class's header file as the first inclusion in - the implementation file. +* Put the #include for the class's header file first in the implementation + file. * Put the copyright header at the top of each file. diff --git a/doc/book/basics.tex b/doc/book/basics.tex index 6dbbff04..94633efd 100644 --- a/doc/book/basics.tex +++ b/doc/book/basics.tex @@ -46,17 +46,17 @@ use the function {\vcode vmime::make\_shared} instead of the {\vcode new} operator. \begin{lstlisting}[caption={Smarts pointers and creating objects}] -class myObject : public vmime::object -{ +class myObject : public vmime::object { + public: myObject(const vmime::string& name) - : m_name(name) - { + : m_name(name) { + } - void sayHello() - { + void sayHello() { + std::cout << "Hello " << m_name << std::endl; } @@ -65,8 +65,8 @@ private: vmime::string m_name; }; -int main() -{ +int main() { + vmime::shared_ptr obj = vmime::make_shared ("world"); @@ -105,12 +105,12 @@ directly or indirectly to itself). The following example illustrates a typical problem of reference counting: \begin{lstlisting} -class parent : public vmime::object -{ +class parent : public vmime::object { + public: - void createChild(vmime::shared_ptr c) - { + void createChild(vmime::shared_ptr c) { + m_child = c; } @@ -119,13 +119,13 @@ private: vmime::shared_ptr m_child; }; -class child : public vmime::object -{ +class child : public vmime::object { + public: child(vmime::shared_ptr p) - : m_parent(p) - { + : m_parent(p) { + } private: @@ -133,8 +133,8 @@ private: vmime::shared_ptr m_parent; }; -int main() -{ +int main() { + vmime::shared_ptr p = vmime::make_shared (); vmime::shared_ptr c = vmime::make_shared (); @@ -179,30 +179,31 @@ Following is an example code for catching VMime exceptions and writing error messages to the console: \begin{lstlisting}[caption={Catching VMime exceptions}] -std::ostream& operator<<(std::ostream& os, const vmime::exception& e) -{ +std::ostream& operator<<(std::ostream& os, const vmime::exception& e) { + os << "* vmime::exceptions::" << e.name() << std::endl; os << " what = " << e.what() << std::endl; // Recursively print all encapsuled exceptions - if (e.other() != NULL) + if (e.other() != NULL) { os << *e.other(); + } return os; } ... -try -{ +try { + // ...some call to VMime... -} -catch (vmime::exception& e) -{ + +} catch (vmime::exception& e) { + std::cerr << e; // VMime exception -} -catch (std::exception& e) -{ + +} catch (std::exception& e) { + std::cerr << e.what(); // standard exception } \end{lstlisting} @@ -250,7 +251,8 @@ vmime::datetime d1("Sat, 08 Oct 2005 14:07:52 +0200"); vmime::datetime d2( /* date */ 2005, vmime::datetime::OCTOBER, 8, /* time */ 14, 7, 52, - /* zone */ vmime::datetime::GMT2); + /* zone */ vmime::datetime::GMT2 +); // Getting day of week const int dow = d2.getWeekDay(); // 'dow' should be datetime::SATURDAY @@ -275,7 +277,8 @@ media type with: \begin{lstlisting} vmime::mediaType theType( /* top-level type */ vmime::mediaTypes::IMAGE, - /* sub-type */ vmime::mediaTypes::IMAGE_JPEG); + /* sub-type */ vmime::mediaTypes::IMAGE_JPEG +); // theType.getType() is "image" // theType.getSubType() is "jpeg" @@ -594,8 +597,9 @@ std::ifstream* fileStream = new std::ifstream(); fileStream->open("/home/vincent/paris.jpg", std::ios::binary); -if (!*fileStream) +if (!*fileStream) { // handle error +} vmime::shared_ptr dataStream = vmime::make_shared (fileStream); @@ -608,13 +612,12 @@ vmime::shared_ptr data = vmime::make_shared (dataStream, 0); // Now create the attachment -ref att = vmime::make_shared - ( - /* attachment data */ data, - /* content type */ vmime::mediaType("image/jpeg"), - /* description */ vmime::text("Holiday photo"), - /* filename */ vmime::word("paris.jpg") - ); +ref att = vmime::make_shared ( + /* attachment data */ data, + /* content type */ vmime::mediaType("image/jpeg"), + /* description */ vmime::text("Holiday photo"), + /* filename */ vmime::word("paris.jpg") +); \end{lstlisting} You will see later that the {\vcode vmime::fileAttachment} class already @@ -647,10 +650,11 @@ vmime::shared_ptr cth = body->getContents(); // Then, extract and convert the contents vmime::utility::outputStreamAdapter out(std::cout); -vmime::utility::charsetFilteredOutputStream fout - (/* source charset */ body->getCharset(), +vmime::utility::charsetFilteredOutputStream fout( + /* source charset */ body->getCharset(), /* dest charset */ vmime::charset("utf-8"), - /* dest stream */ out); + /* dest stream */ out +); cth->extract(fout); @@ -778,8 +782,8 @@ vmime::shared_ptr ef = std::cout << "Available encoders:" << std::endl; -for (int i = 0 ; i < ef->getEncoderCount() ; ++i) -{ +for (int i = 0 ; i < ef->getEncoderCount() ; ++i) { + // Output encoder name vmime::shared_ptr enc = ef->getEncoderAt(i); @@ -792,8 +796,9 @@ for (int i = 0 ; i < ef->getEncoderCount() ; ++i) std::vector props = e->getAvailableProperties(); std::vector ::const_iterator it; - for (it = props.begin() ; it != props.end() ; ++it) + for (it = props.begin() ; it != props.end() ; ++it) { std::cout << " - " << *it << std::endl; + } \end{lstlisting} diff --git a/doc/book/intro.tex b/doc/book/intro.tex index 4fa172e9..fe7bcf51 100644 --- a/doc/book/intro.tex +++ b/doc/book/intro.tex @@ -55,7 +55,7 @@ General Public License\footnote{See Appendix \ref{appendix_license} and \url{http://www.gnu.org/copyleft/gpl.html}} (GPL) version 3: \begin{verbatim} - Copyright (C) 2002-2013 Vincent Richard + Copyright (C) 2002 Vincent Richard VMime library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -79,7 +79,7 @@ GNU Free Documentation License\footnote{See \url{http://www.gnu.org/copyleft/fdl.html}} (FDL): \begin{verbatim} - Copyright (C) 2004-2013 Vincent Richard + Copyright (C) 2004 Vincent Richard Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation diff --git a/doc/book/msg.tex b/doc/book/msg.tex index 50344b62..ce9d8a80 100644 --- a/doc/book/msg.tex +++ b/doc/book/msg.tex @@ -94,8 +94,8 @@ vmime::messageParser mp(msg); std::cout << "Message has " << mp.getAttachmentCount() << " attachment(s)" << std::endl; -for (int i = 0 ; i < mp.getAttachmentCount() ; ++i) -{ +for (int i = 0 ; i < mp.getAttachmentCount() ; ++i) { + vmime::shared_ptr att = mp.getAttachmentAt(i); std::cout << " - " << att->getType().generate() << std::endl; } @@ -104,13 +104,13 @@ for (int i = 0 ; i < mp.getAttachmentCount() ; ++i) std::cout << "Message has " << mp.getTextPartCount() << " text part(s)" << std::endl; -for (int i = 0 ; i < mp.getTextPartCount() ; ++i) -{ +for (int i = 0 ; i < mp.getTextPartCount() ; ++i) { + vmime::shared_ptr tp = mp.getTextPartAt(i); // text/html - if (tp->getType().getSubType() == vmime::mediaTypes::TEXT_HTML) - { + if (tp->getType().getSubType() == vmime::mediaTypes::TEXT_HTML) { + vmime::shared_ptr htp = vmime::dynamicCast (tp); @@ -118,18 +118,18 @@ for (int i = 0 ; i < mp.getTextPartCount() ; ++i) // Plain text is in tp->getPlainText() // Enumerate embedded objects - for (int j = 0 ; j < htp->getObjectCount() ; ++j) - { + for (int j = 0 ; j < htp->getObjectCount() ; ++j) { + vmime::shared_ptr obj = htp->getObjectAt(j); // Identifier (Content-Id or Content-Location) is obj->getId() // Object data is in obj->getData() } - } + // text/plain or anything else - else - { + } else { + // Text is in tp->getText() } } @@ -172,8 +172,7 @@ hdr->appendField(subjectField); vmime::shared_ptr fromField = hfFactory->create(vmime::fields::FROM); -fromField->setValue - (vmime::make_shared ("me@vmime.org")); +fromField->setValue(vmime::make_shared ("me@vmime.org")); hdr->appendField(fromField); // Append a 'To:' field @@ -190,8 +189,11 @@ toField->setValue(recipients); hdr->appendField(toField); // Set the body contents -bdy->setContents(vmime::make_shared - ("This is the text of your message...")); +bdy->setContents( + vmime::make_shared ( + "This is the text of your message..." + ) +); // Output raw message data to standard output vmime::utility::outputStreamAdapter out(std::cout); @@ -207,19 +209,23 @@ previous example, using the {\vcode vmime::messageBuilder} object: \begin{lstlisting}[caption={Building a simple message using {\vcode vmime::messageBuilder}}] -try -{ +try { + vmime::messageBuilder mb; // Fill in some header fields and message body mb.setSubject(vmime::text("Message subject")); mb.setExpeditor(vmime::mailbox("me@vmime.org")); - mb.getRecipients().appendAddress - (vmime::make_shared ("you@vmime.org")); + mb.getRecipients().appendAddress( + vmime::make_shared ("you@vmime.org") + ); mb.getTextPart()->setCharset(vmime::charsets::ISO8859_15); - mb.getTextPart()->setText(vmime::make_shared - ("This is the text of your message...")); + mb.getTextPart()->setText( + vmime::make_shared ( + "This is the text of your message..." + ) + ); // Message construction vmime::shared_ptr msg = mb.construct(); @@ -227,15 +233,15 @@ try // Output raw message data to standard output vmime::utility::outputStreamAdapter out(std::cout); msg->generate(out); -} + // VMime exception -catch (vmime::exception& e) -{ +} catch (vmime::exception& e) { + std::cerr << "vmime::exception: " << e.what() << std::endl; -} + // Standard exception -catch (std::exception& e) -{ +} catch (std::exception& e) { + std::cerr << "std::exception: " << e.what() << std::endl; } \end{lstlisting} @@ -250,17 +256,17 @@ previous example to attach a file to the message: {\vcode vmime::messageBuilder}}] // Create an attachment vmime::shared_ptr att = - vmime::make_shared - ( - /* full path to file */ "/home/vincent/paris.jpg", - /* content type */ vmime::mediaType("image/jpeg), - /* description */ vmime::text("My holidays in Paris") + vmime::make_shared ( + /* full path to file */ "/home/vincent/paris.jpg", + /* content type */ vmime::mediaType("image/jpeg), + /* description */ vmime::text("My holidays in Paris") ); // You can also set some infos about the file att->getFileInfo().setFilename("paris.jpg"); -att->getFileInfo().setCreationDate - (vmime::datetime("30 Apr 2003 14:30:00 +0200")); +att->getFileInfo().setCreationDate( + vmime::datetime("30 Apr 2003 14:30:00 +0200") +); // Add this attachment to the message mb.appendAttachment(att); @@ -283,14 +289,19 @@ using the {\vcode vmime::messageBuilder}}] // Fill in some header fields mb.setSubject(vmime::text("An HTML message")); mb.setExpeditor(vmime::mailbox("me@vmime.org")); -mb.getRecipients().appendAddress - (vmime::make_shared ("you@vmime.org")); +mb.getRecipients().appendAddress( + vmime::make_shared ("you@vmime.org") +); // Set the content-type to "text/html": a text part factory must be // available for the type you are using. The following code will make // the message builder construct the two text parts. -mb.constructTextPart(vmime::mediaType - (vmime::mediaTypes::TEXT, vmime::mediaTypes::TEXT_HTML)); +mb.constructTextPart( + vmime::mediaType( + vmime::mediaTypes::TEXT, + vmime::mediaTypes::TEXT_HTML + ) +); // Set contents of the text parts; the message is available in two formats: // HTML and plain text. The HTML format also includes an embedded image. @@ -306,12 +317,18 @@ const vmime::string id = textPart->addObject("<...image data...>", // -- Set the text textPart->setCharset(vmime::charsets::ISO8859_15); -textPart->setText(vmime::make_shared - ("This is the HTML text, and the image:
" - "")); +textPart->setText( + vmime::make_shared ( + "This is the HTML text, and the image:
" + "" + ) +); -textPart->setPlainText(vmime::make_shared - ("This is the plain text.")); +textPart->setPlainText( + vmime::make_shared ( + "This is the plain text." + ) +); \end{lstlisting} This will create a message having the following structure: @@ -336,11 +353,18 @@ vmime::shared_ptr imageFile = fs->create(fs->stringToPath("/path/to/image.jpg")); vmime::shared_ptr imageCts = - vmime::make_shared - (imageFile->getFileReader()->getInputStream(), imageFile->getLength()); + vmime::make_shared ( + imageFile->getFileReader()->getInputStream(), + imageFile->getLength() + ); -const vmime::string cid = textPart.addObject(imageCts, - vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG)); +const vmime::string cid = textPart.addObject( + imageCts, + vmime::mediaType( + vmime::mediaTypes::IMAGE, + vmime::mediaTypes::IMAGE_JPEG + ) +); \end{lstlisting} @@ -361,8 +385,8 @@ extract its contents to the standard output: \begin{lstlisting}[caption={Testing if a body part is an attachment}] vmime::shared_ptr part; // suppose we have a body part -if (vmime::attachmentHelper::isBodyPartAnAttachment(part)) -{ +if (vmime::attachmentHelper::isBodyPartAnAttachment(part)) { + // The body part contains an attachment, get it vmime::shared_ptr attach = attachmentHelper::getBodyPartAttachment(part); @@ -394,11 +418,10 @@ vmime::shared_ptr msg; // suppose we have a message // Create an attachment vmime::shared_ptr att = - vmime::make_shared - ( - /* full path to file */ "/home/vincent/paris.jpg", - /* content type */ vmime::mediaType("image/jpeg), - /* description */ vmime::text("My holidays in Paris") + vmime::make_shared ( + /* full path to file */ "/home/vincent/paris.jpg", + /* content type */ vmime::mediaType("image/jpeg), + /* description */ vmime::text("My holidays in Paris") ); // Attach it to the message diff --git a/doc/book/net.tex b/doc/book/net.tex index 301e3f11..3fab903a 100644 --- a/doc/book/net.tex +++ b/doc/book/net.tex @@ -300,10 +300,10 @@ The following example shows how to use a custom authenticator to request the user to enter her/his credentials: \begin{lstlisting}[caption={A simple interactive authenticator}] -class myAuthenticator : public vmime::security::defaultAuthenticator -{ - const string getUsername() const - { +class myAuthenticator : public vmime::security::defaultAuthenticator { + + const string getUsername() const { + std::cout << "Enter your username: " << std::endl; vmime::string res; @@ -312,8 +312,8 @@ class myAuthenticator : public vmime::security::defaultAuthenticator return res; } - const string getPassword() const - { + const string getPassword() const { + std::cout << "Enter your password: " << std::endl; vmime::string res; @@ -331,9 +331,10 @@ This is how to use it: vmime::shared_ptr sess = vmime::net::session::create(); // Next, initialize a service which will use our authenticator -vmime::shared_ptr st = - sess->getStore(vmime::utility::url("imap://imap.example.com"), - /* use our authenticator */ vmime::make_shared ()); +vmime::shared_ptr st = sess->getStore( + vmime::utility::url("imap://imap.example.com"), + /* use our authenticator */ vmime::make_shared () +); \end{lstlisting} \vnote{An authenticator object should be used with one and only one service @@ -354,14 +355,15 @@ use the SASL-specific methods {\vcode getAcceptableMechanisms()} and implementation of an SASL authenticator. \begin{lstlisting}[caption={A simple SASL authenticator}] -class mySASLAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator -{ +class mySASLAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator { + typedef vmime::security::sasl::SASLMechanism mechanism; // save us typing - const std::vector > getAcceptableMechanisms - (const std::vector >& available, - const vmime::shared_ptr & suggested) const - { + const std::vector > getAcceptableMechanisms( + const std::vector >& available, + const vmime::shared_ptr & suggested + ) const { + // Here, you can sort the SASL mechanisms in the order they will be // tried. If no SASL mechanism is acceptable (ie. for example, not // enough secure), you can return an empty list. @@ -372,8 +374,8 @@ class mySASLAuthenticator : public vmime::security::sasl::defaultSASLAuthenticat getAcceptableMechanisms(available, suggested); } - void setSASLMechanism(const vmime::shared_ptr & mech) - { + void setSASLMechanism(const vmime::shared_ptr & mech) { + // This is called when the authentication process is going to // try the specified mechanism. // @@ -435,7 +437,8 @@ tr->send( /* expeditor */ from, /* recipient(s) */ to, /* data */ is, - /* total length */ msgData.length()); + /* total length */ msgData.length() +); // We have finished using the service tr->disconnect(); @@ -556,22 +559,26 @@ std::vector > allMessages = folder->getMessages(vmime::net::messageSet::byNumber(1, -1)); // -1 is a special value to mean "the number of the last message in the folder" -folder->fetchMessages(allMessages, +folder->fetchMessages( + allMessages, vmime::net::fetchAttributes::FLAGS | - vmime::net::fetchAttributes::ENVELOPE); + vmime::net::fetchAttributes::ENVELOPE +); + +for (unsigned int i = 0 ; i < allMessages.size() ; ++i) { -for (unsigned int i = 0 ; i < allMessages.size() ; ++i) -{ vmime::shared_ptr msg = allMessages[i]; const int flags = msg->getFlags(); std::cout << "Message " << i << ":" << std::endl; - if (flags & vmime::net::message::FLAG_SEEN) + if (flags & vmime::net::message::FLAG_SEEN) { std::cout << " - is read" << std::endl; - if (flags & vmime::net::message::FLAG_DELETED) + } + if (flags & vmime::net::message::FLAG_DELETED) { std::cout << " - is deleted" << std::endl; + } vmime::shared_ptr hdr = msg->getHeader(); @@ -698,8 +705,8 @@ running. An interface called {\vcode timeoutHandler} is provided: \begin{lstlisting} -class timeoutHandler : public object -{ +class timeoutHandler : public object { + /** Called to test if the time limit has been reached. * * @return true if the timeout delay is elapsed @@ -738,27 +745,27 @@ is thrown. The following example shows how to implement a simple timeout handler: \begin{lstlisting}[caption={Implementing a simple timeout handler}] -class myTimeoutHandler : public vmime::net::timeoutHandler -{ +class myTimeoutHandler : public vmime::net::timeoutHandler { + public: - myTimeoutHandler() - { + myTimeoutHandler() { + m_startTime = time(NULL); } - const bool isTimeOut() - { - return (time(NULL) >= m_startTime + 30); // 30 seconds timeout + const bool isTimeOut() { + + return time(NULL) >= m_startTime + 30; // 30 seconds timeout } - void resetTimeOut() - { + void resetTimeOut() { + m_startTime = time(NULL); } - const bool handleTimeOut() - { + const bool handleTimeOut() { + std::cout << "Operation timed out." << std::endl; << "Press [Y] to continue, or [N] to " << "cancel the operation." << std::endl; @@ -766,7 +773,7 @@ public: std::string response; std::cin >> response; - return (response == "y" || response == "Y"); + return response == "y" || response == "Y"; } private: @@ -781,12 +788,12 @@ is required because the service can use several connections to the server simultaneously, and each connection needs its own timeout handler. \begin{lstlisting} -class myTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory -{ +class myTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory { + public: - ref create() - { + ref create() { + return vmime::make_shared (); } }; @@ -918,13 +925,12 @@ First, we need some code to load existing X.509 certificates: \begin{lstlisting}[caption={Reading a X.509 certificate from a file}] vmime::shared_ptr - loadX509CertificateFromFile(const std::string& path) -{ + loadX509CertificateFromFile(const std::string& path) { + std::ifstream certFile; certFile.open(path.c_str(), std::ios::in | std::ios::binary); - if (!certFile) - { + if (!certFile) { // ...handle error... } @@ -978,12 +984,12 @@ use this in a production application as this is obviously a serious security issue): \begin{lstlisting}[caption={A custom certificate verifier}] -class myCertVerifier : public vmime::security::cert::certificateVerifier -{ +class myCertVerifier : public vmime::security::cert::certificateVerifier { + public: - void verify(const vmime::shared_ptr & certs) - { + void verify(const vmime::shared_ptr & certs) { + // Obtain the subject's certificate vmime::shared_ptr cert = chain->getAt(0); @@ -996,8 +1002,9 @@ public: std::string answer; std::getline(std::cin, answer); - if (answer.length() != 0 && (answer[0] == 'Y' || answer[0] == 'y')) + if (answer.length() != 0 && (answer[0] == 'Y' || answer[0] == 'y')) { return; // OK, we trust the certificate + } // Don't trust this certificate throw vmime::security::cert::certificateException(); @@ -1092,25 +1099,26 @@ First, you have to create your own tracer, which must implement the simply logs to the standard output: \begin{lstlisting}[caption={A simple tracer}] -class myTracer : public vmime::net::tracer -{ +class myTracer : public vmime::net::tracer { + public: myTracer(const vmime::string& proto, const int connectionId) - : m_proto(proto), m_connectionId(connectionId) - { + : m_proto(proto), + m_connectionId(connectionId) { + } // Called by VMime to trace what is sent on the socket - void traceSend(const vmime::string& line) - { + void traceSend(const vmime::string& line) { + std::cout << "[" << m_proto << ":" << m_connectionId << "] C: " << line << std::endl; } // Called by VMime to trace what is received from the socket - void traceReceive(const vmime::string& line) - { + void traceReceive(const vmime::string& line) { + std::cout << "[" < < m_proto << ":" << m_connectionId << "] S: " << line << std::endl; } @@ -1125,16 +1133,18 @@ private: Also create a factory class, used to instanciate your tracer objects: \begin{lstlisting} -class myTracerFactory : public vmime::net::tracerFactory -{ +class myTracerFactory : public vmime::net::tracerFactory { + public: - vmime::shared_ptr create - (const vmime::shared_ptr & serv, - const int connectionId) - { - return vmime::make_shared - (serv->getProtocolName(), connectionId); + vmime::shared_ptr create( + const vmime::shared_ptr & serv, + const int connectionId + ) { + + return vmime::make_shared ( + serv->getProtocolName(), connectionId + ); } }; \end{lstlisting} diff --git a/doc/book/start.tex b/doc/book/start.tex index 74084941..f1693301 100644 --- a/doc/book/start.tex +++ b/doc/book/start.tex @@ -82,8 +82,8 @@ So, if your platform is POSIX, your program should look like this: #include #include -int main() -{ +int main() { + vmime::platform:: setHandler (); diff --git a/examples/example1.cpp b/examples/example1.cpp index b80fe636..c698fa7f 100644 --- a/examples/example1.cpp +++ b/examples/example1.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,23 +39,20 @@ #include "vmime/platforms/posix/posixHandler.hpp" -int main() -{ +int main() { + std::cout << std::endl; // 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 - { + try { std::locale::global(std::locale("")); - } - catch (std::exception &) - { + } catch (std::exception &) { std::setlocale(LC_ALL, ""); } - try - { + try { + vmime::messageBuilder mb; // Fill in the basic fields @@ -74,9 +71,12 @@ int main() mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder")); // Message body - mb.getTextPart()->setText(vmime::make_shared ( - "I'm writing this short text to test message construction " \ - "using the vmime::messageBuilder component.")); + mb.getTextPart()->setText( + vmime::make_shared ( + "I'm writing this short text to test message construction " \ + "using the vmime::messageBuilder component." + ) + ); // Construction vmime::shared_ptr msg = mb.construct(); @@ -87,20 +87,21 @@ int main() vmime::utility::outputStreamAdapter out(std::cout); msg->generate(out); - } + // VMime exception - catch (vmime::exception& e) - { + } catch (vmime::exception& e) { + std::cout << "vmime::exception: " << e.what() << std::endl; throw; - } + // Standard exception - catch (std::exception& e) - { + } catch (std::exception& e) { + std::cout << "std::exception: " << e.what() << std::endl; - //throw; + throw; } std::cout << std::endl; -} + return 0; +} diff --git a/examples/example2.cpp b/examples/example2.cpp index 67b8d844..da01d756 100644 --- a/examples/example2.cpp +++ b/examples/example2.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,23 +39,20 @@ #include "vmime/platforms/posix/posixHandler.hpp" -int main() -{ +int main() { + std::cout << std::endl; // 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 - { + try { std::locale::global(std::locale("")); - } - catch (std::exception &) - { + } catch (std::exception &) { std::setlocale(LC_ALL, ""); } - try - { + try { + vmime::messageBuilder mb; // Fill in the basic fields @@ -74,17 +71,20 @@ int main() mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder")); // Message body - mb.getTextPart()->setText(vmime::make_shared ( - "I'm writing this short text to test message construction " \ - "with attachment, using the vmime::messageBuilder component.")); + mb.getTextPart()->setText( + vmime::make_shared ( + "I'm writing this short text to test message construction " \ + "with attachment, using the vmime::messageBuilder component." + ) + ); // Adding an attachment - vmime::shared_ptr a = vmime::make_shared - ( - __FILE__, // full path to file - vmime::mediaType("application/octet-stream"), // content type - vmime::text("My first attachment") // description - ); + vmime::shared_ptr a = + vmime::make_shared ( + __FILE__, // full path to file + vmime::mediaType("application/octet-stream"), // content type + vmime::text("My first attachment") // description + ); a->getFileInfo().setFilename("example2.cpp"); a->getFileInfo().setCreationDate(vmime::datetime("30 Apr 2003 14:30:00 +0200")); @@ -101,20 +101,21 @@ int main() std::cout << "==================" << std::endl; std::cout << std::endl; std::cout << dataToSend << std::endl; - } + // VMime exception - catch (vmime::exception& e) - { + } catch (vmime::exception& e) { + std::cout << "vmime::exception: " << e.what() << std::endl; throw; - } + // Standard exception - catch (std::exception& e) - { + } catch (std::exception& e) { + std::cout << "std::exception: " << e.what() << std::endl; throw; } std::cout << std::endl; -} + return 0; +} diff --git a/examples/example3.cpp b/examples/example3.cpp index a472e05c..b4522256 100644 --- a/examples/example3.cpp +++ b/examples/example3.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,23 +39,20 @@ #include "vmime/platforms/posix/posixHandler.hpp" -int main() -{ +int main() { + std::cout << std::endl; // 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 - { + try { std::locale::global(std::locale("")); - } - catch (std::exception &) - { + } catch (std::exception &) { std::setlocale(LC_ALL, ""); } - try - { + try { + vmime::messageBuilder mb; // Fill in the basic fields @@ -74,12 +71,17 @@ int main() mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder")); // Set the content-type to "text/html" - mb.constructTextPart(vmime::mediaType - (vmime::mediaTypes::TEXT, vmime::mediaTypes::TEXT_HTML)); + mb.constructTextPart( + vmime::mediaType( + vmime::mediaTypes::TEXT, + vmime::mediaTypes::TEXT_HTML + ) + ); // Fill in the text part: the message is available in two formats: HTML and plain text. // HTML text part also includes an inline image (embedded into the message). - vmime::htmlTextPart& textPart = *vmime::dynamicCast (mb.getTextPart()); + vmime::htmlTextPart& textPart = + *vmime::dynamicCast (mb.getTextPart()); // -- embed an image (the returned "CID" (content identifier) is used to reference // -- the image into HTML content). @@ -93,18 +95,33 @@ int main() imageFile->getFileReader(); vmime::shared_ptr imageCts = - vmime::make_shared - (fileReader->getInputStream(), imageFile->getLength()); + vmime::make_shared ( + fileReader->getInputStream(), + imageFile->getLength() + ); - vmime::shared_ptr obj = textPart.addObject - (imageCts, vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG)); + vmime::shared_ptr obj = + textPart.addObject( + imageCts, + vmime::mediaType( + vmime::mediaTypes::IMAGE, + vmime::mediaTypes::IMAGE_JPEG + ) + ); // -- message text - textPart.setText(vmime::make_shared - (vmime::string("This is the HTML text.
" - "getReferenceId() + vmime::string("\"/>"))); - textPart.setPlainText(vmime::make_shared - ("This is the plain text (without HTML formatting).")); + textPart.setText( + vmime::make_shared ( + vmime::string("This is the HTML text.
" + "getReferenceId() + vmime::string("\"/>") + ) + ); + + textPart.setPlainText( + vmime::make_shared ( + "This is the plain text (without HTML formatting)." + ) + ); // Construction vmime::shared_ptr msg = mb.construct(); @@ -116,20 +133,21 @@ int main() std::cout << "==================" << std::endl; std::cout << std::endl; std::cout << dataToSend << std::endl; - } + // VMime exception - catch (vmime::exception& e) - { + } catch (vmime::exception& e) { + std::cout << "vmime::exception: " << e.what() << std::endl; throw; - } + // Standard exception - catch (std::exception& e) - { + } catch (std::exception& e) { + std::cout << "std::exception: " << e.what() << std::endl; throw; } std::cout << std::endl; -} + return 0; +} diff --git a/examples/example4.cpp b/examples/example4.cpp index 1e0d6657..4d50c2e4 100644 --- a/examples/example4.cpp +++ b/examples/example4.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,71 +39,70 @@ #include "vmime/platforms/posix/posixHandler.hpp" -int main() -{ +int main() { + std::cout << std::endl; // 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 - { + try { std::locale::global(std::locale("")); - } - catch (std::exception &) - { + } catch (std::exception &) { std::setlocale(LC_ALL, ""); } - try - { + try { + vmime::messageParser mp("<...MIME message content...>"); // Enumerate text parts - for (size_t i = 0 ; i < mp.getTextPartCount() ; ++i) - { + for (size_t i = 0 ; i < mp.getTextPartCount() ; ++i) { + const vmime::textPart& part = *mp.getTextPartAt(i); // Output content-type of the part std::cout << part.getType().generate() << std::endl; // text/html - if (part.getType().getSubType() == vmime::mediaTypes::TEXT_HTML) - { + if (part.getType().getSubType() == vmime::mediaTypes::TEXT_HTML) { + const vmime::htmlTextPart& hp = dynamic_cast(part); // HTML text is in "hp.getText()" // Corresponding plain text is in "hp.getPlainText()" // Enumerate embedded objects (eg. images) - for (size_t j = 0 ; j < hp.getObjectCount() ; ++j) - { + for (size_t j = 0 ; j < hp.getObjectCount() ; ++j) { + const vmime::htmlTextPart::embeddedObject& obj = *hp.getObjectAt(j); // Identifier (content-id or content-location) is in "obj.getId()" // Object data is in "obj.getData()" } - } + // text/plain - else - { + } else { + const vmime::textPart& tp = dynamic_cast(part); // Text is in "tp.getText()" } } - } + // VMime exception - catch (vmime::exception& e) - { + } catch (vmime::exception& e) { + std::cout << "vmime::exception: " << e.what() << std::endl; throw; - } + // Standard exception - catch (std::exception& e) - { + } catch (std::exception& e) { + std::cout << "std::exception: " << e.what() << std::endl; throw; } std::cout << std::endl; + + return 0; } diff --git a/examples/example5.cpp b/examples/example5.cpp index d33c64f7..24d5cbfc 100644 --- a/examples/example5.cpp +++ b/examples/example5.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,28 +39,25 @@ #include "vmime/platforms/posix/posixHandler.hpp" -int main() -{ +int main() { + std::cout << std::endl; // 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 - { + try { std::locale::global(std::locale("")); - } - catch (std::exception &) - { + } catch (std::exception &) { std::setlocale(LC_ALL, ""); } - try - { + try { + vmime::messageParser mp("<...MIME message content...>"); // Enumerate attachments - for (size_t i = 0 ; i < mp.getAttachmentCount() ; ++i) - { + for (size_t i = 0 ; i < mp.getAttachmentCount() ; ++i) { + const vmime::attachment& att = *mp.getAttachmentAt(i); // Media type (content type) is in "att.getType()" @@ -68,19 +65,21 @@ int main() // Description is in "att.getDescription()" // Data is in "att.getData()" } - } + // VMime exception - catch (vmime::exception& e) - { + } catch (vmime::exception& e) { + std::cout << "vmime::exception: " << e.what() << std::endl; throw; - } + // Standard exception - catch (std::exception& e) - { + } catch (std::exception& e) { + std::cout << "std::exception: " << e.what() << std::endl; throw; } std::cout << std::endl; + + return 0; } diff --git a/examples/example6.cpp b/examples/example6.cpp index 91a5ba5d..add24b38 100644 --- a/examples/example6.cpp +++ b/examples/example6.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,22 +46,23 @@ static vmime::shared_ptr g_session = vmime::net::session:: * @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) -{ +static const std::string findAvailableProtocols(const vmime::net::service::Type type) { + vmime::shared_ptr sf = vmime::net::serviceFactory::getInstance(); std::ostringstream res; size_t count = 0; - for (size_t i = 0 ; i < sf->getServiceCount() ; ++i) - { + 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) + if (serv.getType() == type) { + + if (count != 0) { res << ", "; + } res << serv.getName(); ++count; @@ -73,14 +74,14 @@ static const std::string findAvailableProtocols(const vmime::net::service::Type // Exception helper -static std::ostream& operator<<(std::ostream& os, const vmime::exception& e) -{ +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 (&e)) - { + if (dynamic_cast (&e)) { + const vmime::exceptions::command_error& cee = dynamic_cast (e); @@ -88,32 +89,32 @@ static std::ostream& operator<<(std::ostream& os, const vmime::exception& e) os << " response = " << cee.response() << std::endl; } - if (dynamic_cast (&e)) - { + if (dynamic_cast (&e)) { + const vmime::exceptions::invalid_response& ir = dynamic_cast (e); os << " response = " << ir.response() << std::endl; } - if (dynamic_cast (&e)) - { + if (dynamic_cast (&e)) { + const vmime::exceptions::connection_greeting_error& cgee = dynamic_cast (e); os << " response = " << cgee.response() << std::endl; } - if (dynamic_cast (&e)) - { + if (dynamic_cast (&e)) { + const vmime::exceptions::authentication_error& aee = dynamic_cast (e); os << " response = " << aee.response() << std::endl; } - if (dynamic_cast (&e)) - { + if (dynamic_cast (&e)) { + const vmime::exceptions::filesystem_exception& fse = dynamic_cast (e); @@ -121,8 +122,9 @@ static std::ostream& operator<<(std::ostream& os, const vmime::exception& e) getFileSystemFactory()->pathToString(fse.path()) << std::endl; } - if (e.other() != NULL) + if (e.other()) { os << *e.other(); + } return os; } @@ -133,35 +135,40 @@ static std::ostream& operator<<(std::ostream& os, const vmime::exception& e) * @param s structure object * @param level current depth */ -static void printStructure(vmime::shared_ptr s, const int level = 0) -{ - for (size_t i = 0 ; i < s->getPartCount() ; ++i) - { +static void printStructure( + vmime::shared_ptr s, + const int level = 0 +) { + + for (size_t i = 0 ; i < s->getPartCount() ; ++i) { + vmime::shared_ptr part = s->getPartAt(i); - for (int j = 0 ; j < level * 2 ; ++j) + for (int j = 0 ; j < level * 2 ; ++j) { std::cout << " "; + } - std::cout << (part->getNumber() + 1) << ". " - << part->getType().generate() - << " [" << part->getSize() << " byte(s)]" - << std::endl; + 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 f) -{ +static const vmime::string getFolderPathString(vmime::shared_ptr f) { + const vmime::string n = f->getName().getBuffer(); - if (n.empty()) // root folder - { + if (n.empty()) { // root folder + return "/"; - } - else - { + + } else { + vmime::shared_ptr p = f->getParent(); return getFolderPathString(p) + n + "/"; } @@ -172,38 +179,43 @@ static const vmime::string getFolderPathString(vmime::shared_ptr folder, const int level = 0) -{ - for (int j = 0 ; j < level * 2 ; ++j) +static void printFolders(vmime::shared_ptr 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) + if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_ALL) { attrStr << " \\use:All"; - else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_ARCHIVE) + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_ARCHIVE) { attrStr << " \\use:Archive"; - else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_DRAFTS) + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_DRAFTS) { attrStr << " \\use:Drafts"; - else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_FLAGGED) + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_FLAGGED) { attrStr << " \\use:Flagged"; - else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_JUNK) + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_JUNK) { attrStr << " \\use:Junk"; - else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_SENT) + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_SENT) { attrStr << " \\use:Sent"; - else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_TRASH) + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_TRASH) { attrStr << " \\use:Trash"; - else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_IMPORTANT) + } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_IMPORTANT) { attrStr << " \\use:Important"; + } - if (attr.getFlags() & vmime::net::folderAttributes::FLAG_HAS_CHILDREN) + if (attr.getFlags() & vmime::net::folderAttributes::FLAG_HAS_CHILDREN) { attrStr << " \\flag:HasChildren"; - if (attr.getFlags() & vmime::net::folderAttributes::FLAG_NO_OPEN) + } + if (attr.getFlags() & vmime::net::folderAttributes::FLAG_NO_OPEN) { attrStr << " \\flag:NoOpen"; + } - for (size_t i = 0, n = attr.getUserFlags().size() ; i < n ; ++i) + for (size_t i = 0, n = attr.getUserFlags().size() ; i < n ; ++i) { attrStr << " \\" << attr.getUserFlags()[i]; + } std::cout << getFolderPathString(folder); std::cout << " " << attrStr.str(); @@ -211,8 +223,9 @@ static void printFolders(vmime::shared_ptr folder, const in std::vector > subFolders = folder->getFolders(false); - for (unsigned int i = 0 ; i < subFolders.size() ; ++i) + for (unsigned int i = 0 ; i < subFolders.size() ; ++i) { printFolders(subFolders[i], level + 1); + } } @@ -220,12 +233,13 @@ static void printFolders(vmime::shared_ptr folder, const in * * @param choices menu choices */ -static unsigned int printMenu(const std::vector & choices) -{ +static unsigned int printMenu(const std::vector & choices) { + std::cout << std::endl; - for (unsigned int i = 0 ; i < choices.size() ; ++i) + 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() << "] "; @@ -241,19 +255,20 @@ static unsigned int printMenu(const std::vector & choices) std::cout << std::endl; - if (choice < 1 || choice > choices.size()) + if (choice < 1 || choice > choices.size()) { return 0; - else + } else { return choice; + } } /** Send a message interactively. */ -static void sendMessage() -{ - try - { +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; @@ -268,10 +283,11 @@ static void sendMessage() vmime::shared_ptr tr; - if (url.getUsername().empty() || url.getPassword().empty()) + if (url.getUsername().empty() || url.getPassword().empty()) { tr = g_session->getTransport(url, vmime::make_shared ()); - else + } else { tr = g_session->getTransport(url); + } #if VMIME_HAVE_TLS_SUPPORT @@ -283,15 +299,17 @@ static void sendMessage() // Set the object responsible for verifying certificates, in the // case a secured connection is used (TLS/SSL) - tr->setCertificateVerifier - (vmime::make_shared ()); + tr->setCertificateVerifier( + vmime::make_shared () + ); #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()) + if (!url.getUsername().empty() || !url.getPassword().empty()) { tr->setProperty("options.need-authentication", true); + } // Trace communication between client and server vmime::shared_ptr traceStream = vmime::make_shared (); @@ -307,8 +325,8 @@ static void sendMessage() vmime::mailbox from(fromString); vmime::mailboxList to; - for (bool cont = true ; cont ; ) - { + for (bool cont = true ; cont ; ) { + std::cout << "Enter email of the recipient (empty to stop): "; std::cout.flush(); @@ -317,23 +335,25 @@ static void sendMessage() cont = (toString.size() != 0); - if (cont) + if (cont) { to.appendMailbox(vmime::make_shared (toString)); + } } std::cout << "Enter message data, including headers (end with '.' on a single line):" << std::endl; std::ostringstream data; - for (bool cont = true ; cont ; ) - { + for (bool cont = true ; cont ; ) { + std::string line; std::getline(std::cin, line); - if (line == ".") + if (line == ".") { cont = false; - else + } else { data << line << "\r\n"; + } } // Connect to server @@ -357,15 +377,15 @@ static void sendMessage() std::cout << traceStream->str(); tr->disconnect(); - } - catch (vmime::exception& e) - { + + } catch (vmime::exception& e) { + std::cerr << std::endl; std::cerr << e << std::endl; throw; - } - catch (std::exception& e) - { + + } catch (std::exception& e) { + std::cerr << std::endl; std::cerr << "std::exception: " << e.what() << std::endl; throw; @@ -375,10 +395,10 @@ static void sendMessage() /** Connect to a message store interactively. */ -static void connectStore() -{ - try - { +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; @@ -396,10 +416,11 @@ static void connectStore() // session properties "auth.username" and "auth.password". vmime::shared_ptr st; - if (url.getUsername().empty() || url.getPassword().empty()) + if (url.getUsername().empty() || url.getPassword().empty()) { st = g_session->getStore(url, vmime::make_shared ()); - else + } else { st = g_session->getStore(url); + } #if VMIME_HAVE_TLS_SUPPORT @@ -411,8 +432,9 @@ static void connectStore() // Set the object responsible for verifying certificates, in the // case a secured connection is used (TLS/SSL) - st->setCertificateVerifier - (vmime::make_shared ()); + st->setCertificateVerifier( + vmime::make_shared () + ); #endif // VMIME_HAVE_TLS_SUPPORT @@ -441,13 +463,13 @@ static void connectStore() std::cout << std::endl; std::cout << count << " message(s) in your inbox" << std::endl; - for (bool cont = true ; cont ; ) - { + for (bool cont = true ; cont ; ) { + typedef std::map > MessageList; MessageList msgList; - try - { + try { + std::vector choices; choices.push_back("Show message flags"); @@ -470,8 +492,8 @@ static void connectStore() vmime::shared_ptr msg; if (choice == 1 || choice == 2 || choice == 3 || choice == 4 || - choice == 5 || choice == 6 || choice == 11) - { + choice == 5 || choice == 6 || choice == 11) { + std::cout << "Enter message number: "; std::cout.flush(); @@ -483,20 +505,20 @@ static void connectStore() vmime::size_t num = 0; iss >> num; - if (num < 1 || num > f->getMessageCount()) - { + if (num < 1 || num > f->getMessageCount()) { + std::cerr << "Invalid message number." << std::endl; continue; } MessageList::iterator it = msgList.find(num); - if (it != msgList.end()) - { + if (it != msgList.end()) { + msg = (*it).second; - } - else - { + + } else { + msg = f->getMessage(num); msgList.insert(MessageList::value_type(num, msg)); } @@ -504,25 +526,31 @@ static void connectStore() std::cout << std::endl; } - switch (choice) - { + switch (choice) { + // Show message flags case 1: f->fetchMessage(msg, vmime::net::fetchAttributes::FLAGS); - if (msg->getFlags() & vmime::net::message::FLAG_SEEN) + if (msg->getFlags() & vmime::net::message::FLAG_SEEN) { std::cout << "FLAG_SEEN" << std::endl; - if (msg->getFlags() & vmime::net::message::FLAG_RECENT) + } + if (msg->getFlags() & vmime::net::message::FLAG_RECENT) { std::cout << "FLAG_RECENT" << std::endl; - if (msg->getFlags() & vmime::net::message::FLAG_REPLIED) + } + if (msg->getFlags() & vmime::net::message::FLAG_REPLIED) { std::cout << "FLAG_REPLIED" << std::endl; - if (msg->getFlags() & vmime::net::message::FLAG_DELETED) + } + if (msg->getFlags() & vmime::net::message::FLAG_DELETED) { std::cout << "FLAG_DELETED" << std::endl; - if (msg->getFlags() & vmime::net::message::FLAG_MARKED) + } + if (msg->getFlags() & vmime::net::message::FLAG_MARKED) { std::cout << "FLAG_MARKED" << std::endl; - if (msg->getFlags() & vmime::net::message::FLAG_PASSED) + } + if (msg->getFlags() & vmime::net::message::FLAG_PASSED) { std::cout << "FLAG_PASSED" << std::endl; + } break; @@ -541,8 +569,8 @@ static void connectStore() break; // Show message envelope - case 4: - { + case 4: { + vmime::net::fetchAttributes attr(vmime::net::fetchAttributes::ENVELOPE); // If you also want to fetch "Received: " fields: @@ -555,37 +583,38 @@ static void connectStore() break; } // Extract whole message - case 5: - { + case 5: { + vmime::utility::outputStreamAdapter out(std::cout); msg->extract(out); break; } // Extract attachments - case 6: - { + case 6: { + vmime::shared_ptr parsedMsg = msg->getParsedMessage(); std::vector > attchs = vmime::attachmentHelper::findAttachmentsInMessage(parsedMsg); - if (attchs.size() > 0) - { + if (attchs.size() > 0) { + std::cout << attchs.size() << " attachments found." << std::endl; for (std::vector >::iterator - it = attchs.begin() ; it != attchs.end() ; ++it) - { + it = attchs.begin() ; it != attchs.end() ; ++it) { + vmime::shared_ptr att = *it; // Get attachment size vmime::size_t size = 0; - if (att->getData()->isEncoded()) + if (att->getData()->isEncoded()) { size = att->getData()->getEncoding().getEncoder()->getDecodedSize(att->getData()->getLength()); - else + } else { size = att->getData()->getLength(); + } std::cout << "Found attachment '" << att->getName().getBuffer() << "'" << ", size is " << size << " bytes:" << std::endl; @@ -618,17 +647,17 @@ static void connectStore() att->getData()->extract(*output.get()); */ } - } - else - { + + } else { + std::cout << "No attachments found." << std::endl; } break; } // Status - case 7: - { + case 7: { + vmime::size_t count, unseen; f->status(count, unseen); @@ -636,17 +665,16 @@ static void connectStore() break; } // List folders - case 8: - { - vmime::shared_ptr - root = st->getRootFolder(); + case 8: { + + vmime::shared_ptr root = st->getRootFolder(); printFolders(root); break; } // Change folder - case 9: - { + case 9: { + std::cout << "Enter folder path (eg. /root/subfolder):" << std::endl; std::cout.flush(); @@ -655,19 +683,21 @@ static void connectStore() vmime::shared_ptr newFolder = st->getRootFolder(); - for (std::string::size_type s = 0, p = 0 ; ; s = p + 1) - { + 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()) + if (!x.empty()) { newFolder = newFolder->getFolder(vmime::utility::path::component(x)); + } - if (p == std::string::npos) + if (p == std::string::npos) { break; + } } newFolder->open(vmime::net::folder::MODE_READ_WRITE); @@ -683,8 +713,8 @@ static void connectStore() break; } // Add message - case 10: - { + case 10: { + vmime::messageBuilder mb; mb.setExpeditor(vmime::mailbox("me@somewhere.com")); @@ -694,32 +724,35 @@ static void connectStore() mb.setRecipients(to); mb.setSubject(vmime::text("Test message from VMime example6")); - mb.getTextPart()->setText(vmime::make_shared ( - "Body of test message from VMime example6.")); + mb.getTextPart()->setText( + vmime::make_shared ( + "Body of test message from VMime example6." + ) + ); vmime::shared_ptr msg = mb.construct(); vmime::net::messageSet set = f->addMessage(msg); - if (set.isEmpty()) - { + if (set.isEmpty()) { + std::cout << "Message has successfully been added, " << "but its UID/number is not known." << std::endl; - } - else - { + + } else { + const vmime::net::messageRange& range = set.getRangeAt(0); - if (set.isUIDSet()) - { + if (set.isUIDSet()) { + const vmime::net::message::uid uid = dynamic_cast (range).getFirst(); std::cout << "Message has successfully been added, " << "its UID is '" << uid << "'." << std::endl; - } - else - { + + } else { + const vmime::size_t number = dynamic_cast (range).getFirst(); @@ -731,30 +764,30 @@ static void connectStore() break; } // Copy message - case 11: - { + case 11: { + vmime::net::messageSet set = f->copyMessages(f->getFullPath(), vmime::net::messageSet::byNumber(msg->getNumber())); - if (set.isEmpty()) - { + if (set.isEmpty()) { + std::cout << "Message has successfully been copied, " << "but its UID/number is not known." << std::endl; - } - else - { + + } else { + const vmime::net::messageRange& range = set.getRangeAt(0); - if (set.isUIDSet()) - { + if (set.isUIDSet()) { + const vmime::net::message::uid uid = dynamic_cast (range).getFirst(); std::cout << "Message has successfully been copied, " << "its UID is '" << uid << "'." << std::endl; - } - else - { + + } else { + const vmime::size_t number = dynamic_cast (range).getFirst(); @@ -808,35 +841,37 @@ static void connectStore() { vmime::shared_ptr g = st->getFolder(vmime::net::folder::path("TEMP")); - if (!g->exists()) + if (!g->exists()) { g->create(vmime::net::folder::TYPE_CONTAINS_MESSAGES); + } f->copyMessages(g->getFullPath()); } */ - } - catch (vmime::exception& e) - { + + } catch (vmime::exception& e) { + std::cerr << std::endl; std::cerr << e << std::endl; - } - catch (std::exception& e) - { + + } catch (std::exception& e) { + std::cerr << std::endl; std::cerr << "std::exception: " << e.what() << std::endl; } + } // for(cont) st->disconnect(); - } - catch (vmime::exception& e) - { + + } catch (vmime::exception& e) { + std::cerr << std::endl; std::cerr << e << std::endl; throw; - } - catch (std::exception& e) - { + + } catch (std::exception& e) { + std::cerr << std::endl; std::cerr << "std::exception: " << e.what() << std::endl; throw; @@ -848,16 +883,16 @@ static void connectStore() * * @return true to quit the program, false to continue */ -static bool menu() -{ +static bool menu() { + std::vector items; items.push_back("Connect to a message store"); items.push_back("Send a message"); items.push_back("Quit"); - switch (printMenu(items)) - { + switch (printMenu(items)) { + // Connect to store case 1: @@ -883,25 +918,21 @@ static bool menu() } -int main() -{ +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 - { + try { std::locale::global(std::locale("")); - } - catch (std::exception &) - { + } catch (std::exception &) { std::setlocale(LC_ALL, ""); } - for (bool quit = false ; !quit ; ) - { + for (bool quit = false ; !quit ; ) { + // Loop on main menu quit = menu(); } return 0; } - diff --git a/examples/example6_authenticator.hpp b/examples/example6_authenticator.hpp index 64336e2a..56f02392 100644 --- a/examples/example6_authenticator.hpp +++ b/examples/example6_authenticator.hpp @@ -3,20 +3,23 @@ #if VMIME_HAVE_SASL_SUPPORT // SASL authentication handler -class interactiveAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator -{ - const std::vector > getAcceptableMechanisms - (const std::vector >& available, - const vmime::shared_ptr & suggested) const - { +class interactiveAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator { + + const std::vector > + getAcceptableMechanisms( + const std::vector >& available, + const vmime::shared_ptr & suggested + ) const { + std::cout << std::endl << "Available SASL mechanisms:" << std::endl; - for (unsigned int i = 0 ; i < available.size() ; ++i) - { + for (unsigned int i = 0 ; i < available.size() ; ++i) { + std::cout << " " << available[i]->getName(); - if (suggested && available[i]->getName() == suggested->getName()) + if (suggested && available[i]->getName() == suggested->getName()) { std::cout << "(suggested)"; + } } std::cout << std::endl << std::endl; @@ -24,31 +27,33 @@ class interactiveAuthenticator : public vmime::security::sasl::defaultSASLAuthen return defaultSASLAuthenticator::getAcceptableMechanisms(available, suggested); } - void setSASLMechanism(const vmime::shared_ptr & mech) - { + void setSASLMechanism(const vmime::shared_ptr & mech) { + std::cout << "Trying '" << mech->getName() << "' authentication mechanism" << std::endl; defaultSASLAuthenticator::setSASLMechanism(mech); } - const vmime::string getUsername() const - { - if (m_username.empty()) + const vmime::string getUsername() const { + + if (m_username.empty()) { m_username = getUserInput("Username"); + } return m_username; } - const vmime::string getPassword() const - { - if (m_password.empty()) + const vmime::string getPassword() const { + + if (m_password.empty()) { m_password = getUserInput("Password"); + } return m_password; } - static const vmime::string getUserInput(const std::string& prompt) - { + static const vmime::string getUserInput(const std::string& prompt) { + std::cout << prompt << ": "; std::cout.flush(); @@ -67,26 +72,28 @@ private: #else // !VMIME_HAVE_SASL_SUPPORT // Simple authentication handler -class interactiveAuthenticator : public vmime::security::defaultAuthenticator -{ - const vmime::string getUsername() const - { - if (m_username.empty()) +class interactiveAuthenticator : public vmime::security::defaultAuthenticator { + + const vmime::string getUsername() const { + + if (m_username.empty()) { m_username = getUserInput("Username"); + } return m_username; } - const vmime::string getPassword() const - { - if (m_password.empty()) + const vmime::string getPassword() const { + + if (m_password.empty()) { m_password = getUserInput("Password"); + } return m_password; } - static const vmime::string getUserInput(const std::string& prompt) - { + static const vmime::string getUserInput(const std::string& prompt) { + std::cout << prompt << ": "; std::cout.flush(); @@ -103,4 +110,3 @@ private: }; #endif // VMIME_HAVE_SASL_SUPPORT - diff --git a/examples/example6_certificateVerifier.hpp b/examples/example6_certificateVerifier.hpp index b4b47a2a..3d8bf82e 100644 --- a/examples/example6_certificateVerifier.hpp +++ b/examples/example6_certificateVerifier.hpp @@ -3,20 +3,23 @@ #if VMIME_HAVE_TLS_SUPPORT // Certificate verifier (TLS/SSL) -class interactiveCertificateVerifier : public vmime::security::cert::defaultCertificateVerifier -{ +class interactiveCertificateVerifier : public vmime::security::cert::defaultCertificateVerifier { + public: - void verify(const vmime::shared_ptr & chain, const vmime::string& hostname) - { - try - { + void verify( + const vmime::shared_ptr & chain, + const vmime::string& hostname + ) { + + try { + setX509TrustedCerts(m_trustedCerts); defaultCertificateVerifier::verify(chain, hostname); - } - catch (vmime::security::cert::certificateException&) - { + + } catch (vmime::security::cert::certificateException&) { + // Obtain subject's certificate vmime::shared_ptr cert = chain->getAt(0); @@ -29,13 +32,14 @@ public: std::getline(std::cin, answer); if (answer.length() != 0 && - (answer[0] == 'Y' || answer[0] == 'y')) - { + (answer[0] == 'Y' || answer[0] == 'y')) { + // Accept it, and remember user's choice for later - if (cert->getType() == "X.509") - { - m_trustedCerts.push_back(vmime::dynamicCast - (cert)); + if (cert->getType() == "X.509") { + + m_trustedCerts.push_back( + vmime::dynamicCast (cert) + ); setX509TrustedCerts(m_trustedCerts); defaultCertificateVerifier::verify(chain, hostname); @@ -44,8 +48,7 @@ public: return; } - throw vmime::security::cert::certificateException - ("User did not accept the certificate."); + throw vmime::security::cert::certificateException("User did not accept the certificate."); } } @@ -59,4 +62,3 @@ std::vector > interactiveCertificateVerifier::m_trustedCerts; #endif // VMIME_HAVE_TLS_SUPPORT - diff --git a/examples/example6_timeoutHandler.hpp b/examples/example6_timeoutHandler.hpp index 3e188baf..7999084d 100644 --- a/examples/example6_timeoutHandler.hpp +++ b/examples/example6_timeoutHandler.hpp @@ -5,17 +5,17 @@ * Used to stop the current operation after too much time, or if the user * requested cancellation. */ -class timeoutHandler : public vmime::net::timeoutHandler -{ +class timeoutHandler : public vmime::net::timeoutHandler { + public: timeoutHandler() - : m_start(time(NULL)) - { + : m_start(time(NULL)) { + } - bool isTimeOut() - { + bool isTimeOut() { + // This is a cancellation point: return true if you want to cancel // the current operation. If you return true, handleTimeOut() will // be called just after this, and before actually cancelling the @@ -25,15 +25,15 @@ public: return (time(NULL) - m_start) >= 10; // seconds } - void resetTimeOut() - { + void resetTimeOut() { + // Called at the beginning of an operation (eg. connecting, // a read() or a write() on a socket...) m_start = time(NULL); } - bool handleTimeOut() - { + bool handleTimeOut() { + // If isTimeOut() returned true, this function will be called. This // allows you to interact with the user, ie. display a prompt to // know whether he wants to cancel the operation. @@ -49,13 +49,12 @@ private: }; -class timeoutHandlerFactory : public vmime::net::timeoutHandlerFactory -{ +class timeoutHandlerFactory : public vmime::net::timeoutHandlerFactory { + public: - vmime::shared_ptr create() - { + vmime::shared_ptr create() { + return vmime::make_shared (); } }; - diff --git a/examples/example6_tracer.hpp b/examples/example6_tracer.hpp index 8f57f56c..27090cf7 100644 --- a/examples/example6_tracer.hpp +++ b/examples/example6_tracer.hpp @@ -1,25 +1,29 @@ /** Tracer used to demonstrate logging communication between client and server. */ +class myTracer : public vmime::net::tracer { -class myTracer : public vmime::net::tracer -{ public: - myTracer(const vmime::shared_ptr & stream, - const vmime::shared_ptr & serv, const int connectionId) - : m_stream(stream), m_service(serv), m_connectionId(connectionId) - { + myTracer( + const vmime::shared_ptr & stream, + const vmime::shared_ptr & serv, + const int connectionId + ) + : m_stream(stream), + m_service(serv), + m_connectionId(connectionId) { + } - void traceSend(const vmime::string& line) - { + void traceSend(const vmime::string& line) { + *m_stream << "[" << m_service->getProtocolName() << ":" << m_connectionId << "] C: " << line << std::endl; } - void traceReceive(const vmime::string& line) - { + void traceReceive(const vmime::string& line) { + *m_stream << "[" << m_service->getProtocolName() << ":" << m_connectionId << "] S: " << line << std::endl; } @@ -31,18 +35,21 @@ private: const int m_connectionId; }; -class myTracerFactory : public vmime::net::tracerFactory -{ + +class myTracerFactory : public vmime::net::tracerFactory { + public: myTracerFactory(const vmime::shared_ptr & stream) - : m_stream(stream) - { + : m_stream(stream) { + } - vmime::shared_ptr create - (const vmime::shared_ptr & serv, const int connectionId) - { + vmime::shared_ptr create( + const vmime::shared_ptr & serv, + const int connectionId + ) { + return vmime::make_shared (m_stream, serv, connectionId); } @@ -50,4 +57,3 @@ private: vmime::shared_ptr m_stream; }; - diff --git a/examples/example7.cpp b/examples/example7.cpp index ae508697..db96dbda 100644 --- a/examples/example7.cpp +++ b/examples/example7.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,16 +39,16 @@ #include "vmime/platforms/posix/posixHandler.hpp" -int main() -{ +int main() { + // Enumerate encoders vmime::shared_ptr ef = vmime::utility::encoder::encoderFactory::getInstance(); std::cout << "Available encoders:" << std::endl; - for (size_t i = 0 ; i < ef->getEncoderCount() ; ++i) - { + for (size_t i = 0 ; i < ef->getEncoderCount() ; ++i) { + vmime::shared_ptr enc = ef->getEncoderAt(i); @@ -59,8 +59,9 @@ int main() std::vector props = e->getAvailableProperties(); - for (std::vector ::const_iterator it = props.begin() ; it != props.end() ; ++it) + for (std::vector ::const_iterator it = props.begin() ; it != props.end() ; ++it) { std::cout << " - " << *it << std::endl; + } } std::cout << std::endl; @@ -71,8 +72,8 @@ int main() std::cout << "Available messaging services:" << std::endl; - for (size_t i = 0 ; i < sf->getServiceCount() ; ++i) - { + for (size_t i = 0 ; i < sf->getServiceCount() ; ++i) { + const vmime::net::serviceFactory::registeredService& serv = *sf->getServiceAt(i); std::cout << " * " << serv.getName() << std::endl; @@ -81,28 +82,29 @@ int main() serv.getInfos().getAvailableProperties(); for (std::vector ::const_iterator it = props.begin() ; - it != props.end() ; ++it) - { + it != props.end() ; ++it) { + const vmime::net::serviceInfos::property& p = *it; const vmime::string name = serv.getInfos().getPropertyPrefix() + p.getName(); vmime::string type; - switch (p.getType()) - { - case vmime::net::serviceInfos::property::TYPE_INTEGER: type = "TYPE_INTEGER"; break; - case vmime::net::serviceInfos::property::TYPE_STRING: type = "TYPE_STRING"; break; - case vmime::net::serviceInfos::property::TYPE_BOOLEAN: type = "TYPE_BOOLEAN"; break; - default: type = "(unknown)"; break; + switch (p.getType()) { + case vmime::net::serviceInfos::property::TYPE_INTEGER: type = "TYPE_INTEGER"; break; + case vmime::net::serviceInfos::property::TYPE_STRING: type = "TYPE_STRING"; break; + case vmime::net::serviceInfos::property::TYPE_BOOLEAN: type = "TYPE_BOOLEAN"; break; + default: type = "(unknown)"; break; } vmime::string flags; - if (p.getFlags() & vmime::net::serviceInfos::property::FLAG_REQUIRED) + if (p.getFlags() & vmime::net::serviceInfos::property::FLAG_REQUIRED) { flags += " FLAG_REQUIRED"; - if (p.getFlags() & vmime::net::serviceInfos::property::FLAG_HIDDEN) + } + if (p.getFlags() & vmime::net::serviceInfos::property::FLAG_HIDDEN) { flags += " FLAG_HIDDEN"; + } std::cout << " - " << serv.getInfos().getPropertyPrefix() + p.getName(); std::cout << " (type=" << type << ", flags=" << flags; @@ -111,5 +113,6 @@ int main() } std::cout << std::endl; -} + return 0; +} diff --git a/examples/viewer/viewer.cpp b/examples/viewer/viewer.cpp index 1d6daa05..a03120ac 100644 --- a/examples/viewer/viewer.cpp +++ b/examples/viewer/viewer.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -53,8 +53,12 @@ vmime::shared_ptr currentMessage; -void insertRowInModel(GtkTreeStore* model, vmime::shared_ptr comp, GtkTreeIter* parent = NULL) -{ +void insertRowInModel( + GtkTreeStore* model, + vmime::shared_ptr comp, + GtkTreeIter* parent = NULL +) { + GtkTreeIter iter; gtk_tree_store_append(model, &iter, parent); @@ -62,15 +66,14 @@ void insertRowInModel(GtkTreeStore* model, vmime::shared_ptr const std::vector > children = comp->getChildComponents(); - for (int i = 0 ; i < children.size() ; ++i) - { + for (int i = 0 ; i < children.size() ; ++i) { insertRowInModel(model, children[i], &iter); } } -void updateTreeView() -{ +void updateTreeView() { + GtkTreeStore* model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeView))); g_object_ref(model); @@ -85,8 +88,8 @@ void updateTreeView() } -static void treeViewSelChanged(GtkTreeView* treeView, gpointer userData) -{ +static void treeViewSelChanged(GtkTreeView* treeView, gpointer userData) { + GtkTreePath* path = NULL; GtkTreeViewColumn* col = NULL; @@ -112,19 +115,18 @@ static void treeViewSelChanged(GtkTreeView* treeView, gpointer userData) } -static void destroy(GtkWidget* widget, gpointer data) -{ +static void destroy(GtkWidget* widget, gpointer data) { + gtk_main_quit(); } -void openFile(const std::string& filename) -{ +void openFile(const std::string& filename) { + std::ifstream file; file.open(filename.c_str(), std::ios::in | std::ios::binary); - if (!file) - { + if (!file) { std::cerr << "Can't open file '" << filename << "'." << std::endl; return; } @@ -132,12 +134,10 @@ void openFile(const std::string& filename) vmime::string data; char buffer[16384]; - do - { + do { file.read(buffer, sizeof(buffer)); data += vmime::string(buffer, file.gcount()); - } - while (file.gcount()); + } while (file.gcount()); vmime::shared_ptr msg = vmime::make_shared (); msg->parse(data); @@ -147,13 +147,13 @@ void openFile(const std::string& filename) char* convData = g_convert_with_fallback(data.c_str(), data.length(), "UTF-8", "ISO-8859-1", "?", NULL, NULL, NULL); - if (convData == NULL) - { + if (!convData) { + gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textArea)), "GLib UTF-8 conversion error.", -1); - } - else - { + + } else { + gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textArea)), convData, strlen(convData)); @@ -164,16 +164,19 @@ void openFile(const std::string& filename) } -static void onFileOpen() -{ - GtkWidget* dlg = gtk_file_chooser_dialog_new - ("Open Message File", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); +static void onFileOpen() { + + GtkWidget* dlg = gtk_file_chooser_dialog_new( + "Open Message File", + GTK_WINDOW(window), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL + ); + + if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_ACCEPT) { - if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_ACCEPT) - { char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg)); openFile(filename); @@ -187,8 +190,7 @@ static void onFileOpen() // UI definitions -static const GtkActionEntry uiActions[] = -{ +static const GtkActionEntry uiActions[] = { { "FileMenu", NULL, "_File" }, { "FileOpen", GTK_STOCK_OPEN, "_Open...", "O", NULL, G_CALLBACK(onFileOpen) }, { "FileExit", GTK_STOCK_QUIT, "_Exit", "Q", NULL, G_CALLBACK(gtk_main_quit) } @@ -205,8 +207,8 @@ static const char* uiDefinition = ""; -int main(int argc, char* argv[]) -{ +int main(int argc, char* argv[]) { + // VMime initialization vmime::platform::setHandler(); @@ -290,5 +292,3 @@ int main(int argc, char* argv[]) return 0; } - - diff --git a/src/vmime/address.cpp b/src/vmime/address.cpp index c6fa74f1..3bc434fa 100644 --- a/src/vmime/address.cpp +++ b/src/vmime/address.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,12 +29,11 @@ #include "vmime/parserHelpers.hpp" -namespace vmime -{ +namespace vmime { -address::address() -{ +address::address() { + } @@ -66,10 +65,15 @@ address-list = (address *("," address)) / obs-addr-list */ -shared_ptr
address::parseNext - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition, bool *isLastAddressOfGroup) -{ +shared_ptr
address::parseNext( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition, + bool *isLastAddressOfGroup +) { + bool escaped = false; bool quoted = false; bool quotedRFC2047 = false; @@ -78,135 +82,151 @@ shared_ptr
address::parseNext bool stop = false; int commentLevel = 0; - if (isLastAddressOfGroup) + if (isLastAddressOfGroup) { *isLastAddressOfGroup = false; + } size_t pos = position; - while (pos < end && parserHelpers::isSpace(buffer[pos])) + while (pos < end && parserHelpers::isSpace(buffer[pos])) { ++pos; + } const size_t start = pos; - while (!stop && pos < end) - { - if (escaped) - { + while (!stop && pos < end) { + + if (escaped) { + escaped = false; - } - else - { - switch (buffer[pos]) - { - case '\\': - escaped = true; - break; - case '"': - quoted = !quoted; - break; - case '<': - inRouteAddr = true; - break; - case '>': - inRouteAddr = false; - break; - case '(': + } else { - ++commentLevel; - break; + switch (buffer[pos]) { - case ')': + case '\\': - if (commentLevel > 0) - --commentLevel; + escaped = true; + break; - break; + case '"': - case '=': + quoted = !quoted; + break; - if (commentLevel == 0 && !quoted && !quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '?') - { - ++pos; - quotedRFC2047 = true; - } + case '<': - break; + inRouteAddr = true; + break; - case '?': + case '>': - if (commentLevel == 0 && quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '=') - { - ++pos; - quotedRFC2047 = false; - } + inRouteAddr = false; + break; - break; + case '(': - default: - { - if (commentLevel == 0 && !quoted && !quotedRFC2047 && !inRouteAddr) - { - switch (buffer[pos]) - { - case ';': + ++commentLevel; + break; - if (isGroup) - { - if (pos + 1 < end && buffer[pos + 1] == ',') - ++pos; - } + case ')': - if (isLastAddressOfGroup) - *isLastAddressOfGroup = true; - - stop = true; - break; - - case ':': - - isGroup = true; - break; - - case ',': - - if (!isGroup) stop = true; - break; + if (commentLevel > 0) { + --commentLevel; } - } - break; - } + break; + + case '=': + + if (commentLevel == 0 && !quoted && !quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '?') { + ++pos; + quotedRFC2047 = true; + } + + break; + + case '?': + + if (commentLevel == 0 && quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '=') { + ++pos; + quotedRFC2047 = false; + } + + break; + + default: + { + if (commentLevel == 0 && !quoted && !quotedRFC2047 && !inRouteAddr) { + + switch (buffer[pos]) { + + case ';': + + if (isGroup) { + + if (pos + 1 < end && buffer[pos + 1] == ',') { + ++pos; + } + } + + if (isLastAddressOfGroup) { + *isLastAddressOfGroup = true; + } + + stop = true; + break; + + case ':': + + isGroup = true; + break; + + case ',': + + if (!isGroup) { + stop = true; + } + + break; + } + } + + break; + } } } - if (!stop) + if (!stop) { ++pos; + } } - if (newPosition) - { - if (pos == end) + if (newPosition) { + + if (pos == end) { *newPosition = end; - else + } else { *newPosition = pos + 1; // ',' or ';' + } } // Parse extracted address (mailbox or group) - if (pos != start) - { + if (pos != start) { + shared_ptr
parsedAddress; - if (isGroup) + if (isGroup) { parsedAddress = make_shared (); - else + } else { parsedAddress = make_shared (); + } parsedAddress->parse(ctx, buffer, start, pos, NULL); parsedAddress->setParsedBounds(start, pos); - return (parsedAddress); + return parsedAddress; } return null; diff --git a/src/vmime/address.hpp b/src/vmime/address.hpp index 5eb510f9..f83f2381 100644 --- a/src/vmime/address.hpp +++ b/src/vmime/address.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,8 +29,7 @@ #include "vmime/headerFieldValue.hpp" -namespace vmime -{ +namespace vmime { /** Abstract class representing a mailbox or a group of mailboxes. @@ -38,9 +37,8 @@ namespace vmime * This class define a common behaviour for the mailbox * and mailboxGroup classes. */ +class VMIME_EXPORT address : public headerFieldValue { -class VMIME_EXPORT address : public headerFieldValue -{ protected: address(); @@ -74,10 +72,14 @@ public: * of a group (end delimiter was found), or false otherwise (may be set to NULL) * @return a new address object, or null if no more address is available in the input buffer */ - static shared_ptr
parseNext - (const parsingContext& ctx, const string& buffer, - const size_t position, const size_t end, - size_t* newPosition, bool *isLastAddressOfGroup); + static shared_ptr
parseNext( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition, + bool *isLastAddressOfGroup + ); }; diff --git a/src/vmime/addressList.cpp b/src/vmime/addressList.cpp index 23834f6f..03c9e8f4 100644 --- a/src/vmime/addressList.cpp +++ b/src/vmime/addressList.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,181 +28,204 @@ #include "vmime/mailboxGroup.hpp" -namespace vmime -{ +namespace vmime { -addressList::addressList() -{ +addressList::addressList() { + } addressList::addressList(const addressList& addrList) - : headerFieldValue() -{ + : headerFieldValue() { + copyFrom(addrList); } -addressList::~addressList() -{ +addressList::~addressList() { + removeAllAddresses(); } -void addressList::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void addressList::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + removeAllAddresses(); size_t pos = position; - while (pos < end) - { + while (pos < end) { + shared_ptr
parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, NULL); - if (parsedAddress != NULL) + if (parsedAddress) { m_list.push_back(parsedAddress); + } } setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void addressList::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void addressList::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + size_t pos = curLinePos; generationContext tmpCtx(ctx); tmpCtx.setMaxLineLength(tmpCtx.getMaxLineLength() - 2); - if (!m_list.empty()) - { - for (std::vector >::const_iterator i = m_list.begin() ; ; ) - { + if (!m_list.empty()) { + + for (std::vector >::const_iterator i = m_list.begin() ; ; ) { + (*i)->generate(ctx, os, pos, &pos); - if (++i == m_list.end()) + if (++i == m_list.end()) { break; + } os << ", "; pos += 2; } } - if (newLinePos) + if (newLinePos) { *newLinePos = pos; + } } -void addressList::copyFrom(const component& other) -{ +void addressList::copyFrom(const component& other) { + const addressList& addrList = dynamic_cast (other); removeAllAddresses(); for (std::vector >::const_iterator it = addrList.m_list.begin() ; - it != addrList.m_list.end() ; ++it) - { + it != addrList.m_list.end() ; ++it) { + m_list.push_back(vmime::clone(*it)); } } -addressList& addressList::operator=(const addressList& other) -{ +addressList& addressList::operator=(const addressList& other) { + copyFrom(other); - return (*this); + return *this; } -addressList& addressList::operator=(const mailboxList& other) -{ +addressList& addressList::operator=(const mailboxList& other) { + removeAllAddresses(); - for (size_t i = 0 ; i < other.getMailboxCount() ; ++i) + for (size_t i = 0 ; i < other.getMailboxCount() ; ++i) { m_list.push_back(dynamicCast
(other.getMailboxAt(i)->clone())); + } - return (*this); + return *this; } -shared_ptr addressList::clone() const -{ +shared_ptr addressList::clone() const { + return make_shared (*this); } -void addressList::appendAddress(const shared_ptr
&addr) -{ +void addressList::appendAddress(const shared_ptr
&addr) { + m_list.push_back(addr); } -void addressList::insertAddressBefore(const shared_ptr
& beforeAddress, const shared_ptr
& addr) -{ - const std::vector >::iterator it = std::find - (m_list.begin(), m_list.end(), beforeAddress); +void addressList::insertAddressBefore(const shared_ptr
& beforeAddress, const shared_ptr
& addr) { - if (it == m_list.end()) + const std::vector >::iterator it = std::find( + m_list.begin(), m_list.end(), beforeAddress + ); + + if (it == m_list.end()) { throw std::out_of_range("Invalid position"); + } m_list.insert(it, addr); } -void addressList::insertAddressBefore(const size_t pos, const shared_ptr
& addr) -{ - if (pos >= m_list.size()) +void addressList::insertAddressBefore(const size_t pos, const shared_ptr
& addr) { + + if (pos >= m_list.size()) { throw std::out_of_range("Invalid position"); + } m_list.insert(m_list.begin() + pos, addr); } -void addressList::insertAddressAfter(const shared_ptr
& afterAddress, const shared_ptr
& addr) -{ - const std::vector >::iterator it = std::find - (m_list.begin(), m_list.end(), afterAddress); +void addressList::insertAddressAfter( + const shared_ptr
& afterAddress, + const shared_ptr
& addr +) { - if (it == m_list.end()) + const std::vector >::iterator it = std::find( + m_list.begin(), m_list.end(), afterAddress + ); + + if (it == m_list.end()) { throw std::out_of_range("Invalid position"); + } m_list.insert(it + 1, addr); } -void addressList::insertAddressAfter(const size_t pos, const shared_ptr
& addr) -{ - if (pos >= m_list.size()) +void addressList::insertAddressAfter(const size_t pos, const shared_ptr
& addr) { + + if (pos >= m_list.size()) { throw std::out_of_range("Invalid position"); + } m_list.insert(m_list.begin() + pos + 1, addr); } -void addressList::removeAddress(const shared_ptr
& addr) -{ - const std::vector >::iterator it = std::find - (m_list.begin(), m_list.end(), addr); +void addressList::removeAddress(const shared_ptr
& addr) { - if (it == m_list.end()) + const std::vector >::iterator it = std::find( + m_list.begin(), m_list.end(), addr + ); + + if (it == m_list.end()) { throw std::out_of_range("Invalid position"); + } m_list.erase(it); } -void addressList::removeAddress(const size_t pos) -{ - if (pos >= m_list.size()) +void addressList::removeAddress(const size_t pos) { + + if (pos >= m_list.size()) { throw std::out_of_range("Invalid position"); + } const std::vector >::iterator it = m_list.begin() + pos; @@ -210,90 +233,90 @@ void addressList::removeAddress(const size_t pos) } -void addressList::removeAllAddresses() -{ +void addressList::removeAllAddresses() { + m_list.clear(); } -size_t addressList::getAddressCount() const -{ - return (m_list.size()); +size_t addressList::getAddressCount() const { + + return m_list.size(); } -bool addressList::isEmpty() const -{ - return (m_list.empty()); +bool addressList::isEmpty() const { + + return m_list.empty(); } -shared_ptr
addressList::getAddressAt(const size_t pos) -{ - return (m_list[pos]); +shared_ptr
addressList::getAddressAt(const size_t pos) { + + return m_list[pos]; } -const shared_ptr addressList::getAddressAt(const size_t pos) const -{ - return (m_list[pos]); +const shared_ptr addressList::getAddressAt(const size_t pos) const { + + return m_list[pos]; } -const std::vector > addressList::getAddressList() const -{ +const std::vector > addressList::getAddressList() const { + std::vector > list; list.reserve(m_list.size()); for (std::vector >::const_iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { + it != m_list.end() ; ++it) { + list.push_back(*it); } - return (list); + return list; } -const std::vector > addressList::getAddressList() -{ - return (m_list); +const std::vector > addressList::getAddressList() { + + return m_list; } -const std::vector > addressList::getChildComponents() -{ +const std::vector > addressList::getChildComponents() { + std::vector > list; copy_vector(m_list, list); - return (list); + return list; } -shared_ptr addressList::toMailboxList() const -{ +shared_ptr addressList::toMailboxList() const { + shared_ptr res = make_shared (); for (std::vector >::const_iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { + it != m_list.end() ; ++it) { + shared_ptr addr = *it; - if (addr->isGroup()) - { + if (addr->isGroup()) { + const std::vector > mailboxes = dynamicCast (addr)->getMailboxList(); for (std::vector >::const_iterator jt = mailboxes.begin() ; - jt != mailboxes.end() ; ++jt) - { + jt != mailboxes.end() ; ++jt) { + res->appendMailbox(vmime::clone(*jt)); } - } - else - { + + } else { + res->appendMailbox(dynamicCast (addr->clone())); } } diff --git a/src/vmime/addressList.hpp b/src/vmime/addressList.hpp index c0909069..69cbd74a 100644 --- a/src/vmime/addressList.hpp +++ b/src/vmime/addressList.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,8 +31,7 @@ #include "vmime/address.hpp" -namespace vmime -{ +namespace vmime { class mailboxList; @@ -40,9 +39,8 @@ class mailboxList; /** A list of addresses. */ +class VMIME_EXPORT addressList : public headerFieldValue { -class VMIME_EXPORT addressList : public headerFieldValue -{ public: addressList(); @@ -71,7 +69,10 @@ public: * @param addr address to insert * @throw std::out_of_range if the address is not in the list */ - void insertAddressBefore(const shared_ptr
& beforeAddress, const shared_ptr
& addr); + void insertAddressBefore( + const shared_ptr
& beforeAddress, + const shared_ptr
& addr + ); /** Insert a new address before the specified position. * @@ -88,7 +89,10 @@ public: * @param addr address to insert * @throw std::out_of_range if the address is not in the list */ - void insertAddressAfter(const shared_ptr
& afterAddress, const shared_ptr
& addr); + void insertAddressAfter( + const shared_ptr
& afterAddress, + const shared_ptr
& addr + ); /** Insert a new address after the specified position. * @@ -171,18 +175,20 @@ private: protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/attachment.hpp b/src/vmime/attachment.hpp index 862e5d9e..be20e33d 100644 --- a/src/vmime/attachment.hpp +++ b/src/vmime/attachment.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,15 +34,13 @@ #include "vmime/encoding.hpp" -namespace vmime -{ +namespace vmime { /** Base class for all types of attachment. */ +class VMIME_EXPORT attachment : public object { -class VMIME_EXPORT attachment : public object -{ friend class messageBuilder; friend class messageParser; friend class attachmentHelper; diff --git a/src/vmime/attachmentHelper.cpp b/src/vmime/attachmentHelper.cpp index 252a0377..86051226 100644 --- a/src/vmime/attachmentHelper.cpp +++ b/src/vmime/attachmentHelper.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,36 +33,39 @@ #include -namespace vmime -{ +namespace vmime { // static -bool attachmentHelper::isBodyPartAnAttachment - (const shared_ptr & part, const unsigned int options) -{ +bool attachmentHelper::isBodyPartAnAttachment( + const shared_ptr & part, + const unsigned int options +) { + // First, try with "Content-Disposition" field. // If not present, we will try with "Content-Type" field. shared_ptr cdf = part->getHeader()->findField (fields::CONTENT_DISPOSITION); - if (cdf) - { + if (cdf) { + const contentDisposition disp = *cdf->getValue (); - if (disp.getName() != contentDispositionTypes::INLINE) + if (disp.getName() != contentDispositionTypes::INLINE) { return true; + } + + if ((options & INLINE_OBJECTS) == 0) { - if ((options & INLINE_OBJECTS) == 0) - { // If the Content-Disposition is 'inline' and there is no // Content-Id or Content-Location field, it may be an attachment if (!part->getHeader()->hasField(vmime::fields::CONTENT_ID) && - !part->getHeader()->hasField(vmime::fields::CONTENT_LOCATION)) - { + !part->getHeader()->hasField(vmime::fields::CONTENT_LOCATION)) { + // If this is the root part, it might not be an attachment - if (part->getParentPart() == NULL) + if (!part->getParentPart()) { return false; + } return true; } @@ -78,40 +81,46 @@ bool attachmentHelper::isBodyPartAnAttachment shared_ptr ctf = part->getHeader()->findField (fields::CONTENT_TYPE); - if (ctf) - { + if (ctf) { + type = *ctf->getValue (); - if (ctf->hasParameter("name")) + if (ctf->hasParameter("name")) { hasContentTypeName = true; - } - else - { + } + + } else { + // If this is the root part and no Content-Type field is present, // then this may not be a MIME message, so do not assume it is // an attachment - if (part->getParentPart() == NULL) + if (!part->getParentPart()) { return false; + } // No "Content-type" field: assume "application/octet-stream". - type = mediaType(mediaTypes::APPLICATION, - mediaTypes::APPLICATION_OCTET_STREAM); + type = mediaType( + mediaTypes::APPLICATION, + mediaTypes::APPLICATION_OCTET_STREAM + ); } if (type.getType() != mediaTypes::TEXT && - type.getType() != mediaTypes::MULTIPART) - { + type.getType() != mediaTypes::MULTIPART) { + // Compatibility with (obsolete) RFC-1341: if there is a "name" parameter // on the "Content-Type" field, then we assume it is an attachment - if (hasContentTypeName) + if (hasContentTypeName) { return true; + } + + if ((options & INLINE_OBJECTS) == 0) { - if ((options & INLINE_OBJECTS) == 0) - { // If a "Content-Id" field is present, it might be an // embedded object (MHTML messages) - if (part->getHeader()->hasField(vmime::fields::CONTENT_ID)) + if (part->getHeader()->hasField(vmime::fields::CONTENT_ID)) { return false; + } } return true; @@ -122,35 +131,40 @@ bool attachmentHelper::isBodyPartAnAttachment // static -shared_ptr attachmentHelper::getBodyPartAttachment - (const shared_ptr & part, const unsigned int options) -{ - if (!isBodyPartAnAttachment(part, options)) +shared_ptr attachmentHelper::getBodyPartAttachment( + const shared_ptr & part, + const unsigned int options +) { + + if (!isBodyPartAnAttachment(part, options)) { return null; + } mediaType type; shared_ptr ctf = part->getHeader()->findField (fields::CONTENT_TYPE); - if (ctf) - { + if (ctf) { + type = *ctf->getValue (); - } - else - { + + } else { + // No "Content-type" field: assume "application/octet-stream". - type = mediaType(mediaTypes::APPLICATION, - mediaTypes::APPLICATION_OCTET_STREAM); + type = mediaType( + mediaTypes::APPLICATION, + mediaTypes::APPLICATION_OCTET_STREAM + ); } if (type.getType() == mediaTypes::MESSAGE && - type.getSubType() == mediaTypes::MESSAGE_RFC822) - { + type.getSubType() == mediaTypes::MESSAGE_RFC822) { + return make_shared (part); - } - else - { + + } else { + return make_shared (part); } } @@ -158,32 +172,36 @@ shared_ptr attachmentHelper::getBodyPartAttachment // static const std::vector > - attachmentHelper::findAttachmentsInMessage - (const shared_ptr & msg, const unsigned int options) -{ + attachmentHelper::findAttachmentsInMessage( + const shared_ptr & msg, + const unsigned int options + ) { + return findAttachmentsInBodyPart(msg, options); } // static const std::vector > - attachmentHelper::findAttachmentsInBodyPart - (const shared_ptr & part, const unsigned int options) -{ + attachmentHelper::findAttachmentsInBodyPart( + const shared_ptr & part, + const unsigned int options + ) { + std::vector > atts; // Test this part - if (isBodyPartAnAttachment(part, options)) - { + if (isBodyPartAnAttachment(part, options)) { + atts.push_back(getBodyPartAttachment(part, options)); - } + // Find in sub-parts - else - { + } else { + shared_ptr bdy = part->getBody(); - for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) - { + for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) { + std::vector > partAtts = findAttachmentsInBodyPart(bdy->getPartAt(i), options); @@ -196,35 +214,39 @@ const std::vector > // static -void attachmentHelper::addAttachment(const shared_ptr & msg, const shared_ptr & att) -{ +void attachmentHelper::addAttachment(const shared_ptr & msg, const shared_ptr & att) { + // We simply search for a "multipart/mixed" part. If no one exists, // create it in the root part. This (very simple) algorithm should // work in the most cases. - vmime::mediaType mpMixed(vmime::mediaTypes::MULTIPART, - vmime::mediaTypes::MULTIPART_MIXED); + vmime::mediaType mpMixed( + vmime::mediaTypes::MULTIPART, + vmime::mediaTypes::MULTIPART_MIXED + ); shared_ptr part = findBodyPart(msg, mpMixed); - if (part == NULL) // create it - { - if (msg->getBody()->getPartCount() != 0) - { + if (!part) { // create it + + if (msg->getBody()->getPartCount() != 0) { + // Create a new container part for the parts that were in // the root part of the message shared_ptr container = make_shared (); - if (msg->getHeader()->hasField(fields::CONTENT_TYPE)) - { - container->getHeader()->ContentType()->setValue - (msg->getHeader()->ContentType()->getValue()); + if (msg->getHeader()->hasField(fields::CONTENT_TYPE)) { + + container->getHeader()->ContentType()->setValue( + msg->getHeader()->ContentType()->getValue() + ); } - if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING)) - { - container->getHeader()->ContentTransferEncoding()->setValue - (msg->getHeader()->ContentTransferEncoding()->getValue()); + if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING)) { + + container->getHeader()->ContentTransferEncoding()->setValue( + msg->getHeader()->ContentTransferEncoding()->getValue() + ); } // Move parts from the root part to this new part @@ -233,28 +255,31 @@ void attachmentHelper::addAttachment(const shared_ptr & msg, const shar msg->getBody()->removeAllParts(); - for (unsigned int i = 0 ; i < partList.size() ; ++i) + for (unsigned int i = 0 ; i < partList.size() ; ++i) { container->getBody()->appendPart(partList[i]); + } msg->getBody()->appendPart(container); - } - else - { + + } else { + // The message is a simple (RFC-822) message, and do not // contains any MIME part. Move the contents from the // root to a new child part. shared_ptr child = make_shared (); - if (msg->getHeader()->hasField(fields::CONTENT_TYPE)) - { - child->getHeader()->ContentType()->setValue - (msg->getHeader()->ContentType()->getValue()); + if (msg->getHeader()->hasField(fields::CONTENT_TYPE)) { + + child->getHeader()->ContentType()->setValue( + msg->getHeader()->ContentType()->getValue() + ); } - if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING)) - { - child->getHeader()->ContentTransferEncoding()->setValue - (msg->getHeader()->ContentTransferEncoding()->getValue()); + if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING)) { + + child->getHeader()->ContentTransferEncoding()->setValue( + msg->getHeader()->ContentTransferEncoding()->getValue() + ); } child->getBody()->setContents(msg->getBody()->getContents()); @@ -278,22 +303,25 @@ void attachmentHelper::addAttachment(const shared_ptr & msg, const shar // static -shared_ptr attachmentHelper::findBodyPart - (const shared_ptr & part, const mediaType& type) -{ - if (part->getBody()->getContentType() == type) +shared_ptr attachmentHelper::findBodyPart( + const shared_ptr & part, + const mediaType& type +) { + + if (part->getBody()->getContentType() == type) { return part; + } // Try in sub-parts shared_ptr bdy = part->getBody(); - for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) - { - shared_ptr found = - findBodyPart(bdy->getPartAt(i), type); + for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) { - if (found != NULL) + shared_ptr found = findBodyPart(bdy->getPartAt(i), type); + + if (found) { return found; + } } return null; @@ -301,12 +329,11 @@ shared_ptr attachmentHelper::findBodyPart // static -void attachmentHelper::addAttachment(const shared_ptr & msg, const shared_ptr & amsg) -{ +void attachmentHelper::addAttachment(const shared_ptr & msg, const shared_ptr & amsg) { + shared_ptr att = make_shared (amsg); addAttachment(msg, att); } } // vmime - diff --git a/src/vmime/attachmentHelper.hpp b/src/vmime/attachmentHelper.hpp index f1588fe8..f28819fb 100644 --- a/src/vmime/attachmentHelper.hpp +++ b/src/vmime/attachmentHelper.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,14 +31,13 @@ #include "vmime/message.hpp" -namespace vmime -{ +namespace vmime { /** Retrieve attachment information from message parts. */ -class VMIME_EXPORT attachmentHelper -{ +class VMIME_EXPORT attachmentHelper { + public: /** Options for use with the following functions: @@ -46,8 +45,7 @@ public: * getBodyPartAttachment, * and isBodyPartAnAttachment. */ - enum FindOptions - { + enum FindOptions { INLINE_OBJECTS = (1 << 0) /**< Recognize and return inline objects. The aim is to consider MHTML objects (parts with a "Content-Id" or a "Content-Location", such as inline images) as attachments. */ @@ -59,7 +57,10 @@ public: * @param options search options (see FindOptions) * @return true if the part is an attachment, false otherwise */ - static bool isBodyPartAnAttachment(const shared_ptr & part, const unsigned int options = 0); + static bool isBodyPartAnAttachment( + const shared_ptr & part, + const unsigned int options = 0 + ); /** Return attachment information in the specified body part. * If the specified body part does not contain attachment @@ -69,8 +70,10 @@ public: * @param options search options (see FindOptions) * @return attachment found in the part, or NULL */ - static shared_ptr - getBodyPartAttachment(const shared_ptr & part, const unsigned int options = 0); + static shared_ptr getBodyPartAttachment( + const shared_ptr & part, + const unsigned int options = 0 + ); /** Find all attachments contained in the specified part * and all its children parts. @@ -81,7 +84,10 @@ public: * @return a list of attachments found */ static const std::vector > - findAttachmentsInBodyPart(const shared_ptr & part, const unsigned int options = 0); + findAttachmentsInBodyPart( + const shared_ptr & part, + const unsigned int options = 0 + ); /** Find all attachments contained in the specified message. * This is simply a recursive call to getBodyPartAttachment(). @@ -91,26 +97,37 @@ public: * @return a list of attachments found */ static const std::vector > - findAttachmentsInMessage(const shared_ptr & msg, const unsigned int options = 0); + findAttachmentsInMessage( + const shared_ptr & msg, + const unsigned int options = 0 + ); /** Add an attachment to the specified message. * * @param msg message into which to add the attachment * @param att attachment to add */ - static void addAttachment(const shared_ptr & msg, const shared_ptr & att); + static void addAttachment( + const shared_ptr & msg, + const shared_ptr & att + ); /** Add a message attachment to the specified message. * * @param msg message into which to add the attachment * @param amsg message to attach */ - static void addAttachment(const shared_ptr & msg, const shared_ptr & amsg); + static void addAttachment( + const shared_ptr & msg, + const shared_ptr & amsg + ); protected: - static shared_ptr findBodyPart - (const shared_ptr & part, const mediaType& type); + static shared_ptr findBodyPart( + const shared_ptr & part, + const mediaType& type + ); }; @@ -118,4 +135,3 @@ protected: #endif // VMIME_ATTACHMENTHELPER_HPP_INCLUDED - diff --git a/src/vmime/base.cpp b/src/vmime/base.cpp index 9f9a87be..395d7b32 100644 --- a/src/vmime/base.cpp +++ b/src/vmime/base.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -48,8 +48,7 @@ #endif -namespace vmime -{ +namespace vmime { /** "Null" (empty) string. @@ -108,8 +107,8 @@ nullPtrType null; // Line length limits -namespace lineLengthLimits -{ +namespace lineLengthLimits { + const size_t infinite = std::numeric_limits ::max(); } @@ -134,12 +133,10 @@ const size_t npos = std::numeric_limits ::max(); // constructor, for example). // -class initializer -{ -public: +struct initializer { + + initializer() { - initializer() - { parsingContext::getDefaultContext(); generationContext::getDefaultContext(); diff --git a/src/vmime/base.hpp b/src/vmime/base.hpp index b39ff55e..77824771 100644 --- a/src/vmime/base.hpp +++ b/src/vmime/base.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,8 +37,8 @@ #include "vmime/constants.hpp" -namespace vmime -{ +namespace vmime { + class text; class word; class charset; @@ -53,9 +53,9 @@ namespace vmime #ifndef VMIME_BUILDING_DOC // Null pointer - struct nullPtrType - { - template + struct nullPtrType { + + template operator shared_ptr () { return shared_ptr (); } }; @@ -78,47 +78,48 @@ namespace vmime // template - inline T const* cbegin(T const (&array)[N]) - { - return (array); + inline T const* cbegin(T const (&array)[N]) { + + return array; } template - inline T const* cend(T const (&array)[N]) - { - return (array + N); + inline T const* cend(T const (&array)[N]) { + + return array + N; } template - inline T* begin(T (&array)[N]) - { - return (array); + inline T* begin(T (&array)[N]) { + + return array; } template - inline T* end(T (&array)[N]) - { - return (array + N); + inline T* end(T (&array)[N]) { + + return array + N; } template - inline size_t count(T const (&/* array */)[N]) - { - return (N); + inline size_t count(T const (&/* array */)[N]) { + + return N; } // Copy one vector to another, with type conversion template - void copy_vector(const T1& v1, T2& v2) - { + void copy_vector(const T1& v1, T2& v2) { + const typename T1::size_type count = v1.size(); v2.resize(count); - for (typename T1::size_type i = 0 ; i < count ; ++i) + for (typename T1::size_type i = 0 ; i < count ; ++i) { v2[i] = v1[i]; + } } @@ -154,12 +155,11 @@ namespace vmime character limit) for the sake of robustness. */ - namespace lineLengthLimits - { + namespace lineLengthLimits { + extern VMIME_EXPORT const size_t infinite; - enum - { + enum { max = 998, convenient = 78 }; @@ -192,8 +192,8 @@ namespace vmime * This is an alias for dynamic_pointer_cast (obj->clone()). */ template - shared_ptr clone(const shared_ptr & obj) - { + shared_ptr clone(const shared_ptr & obj) { + return dynamic_pointer_cast (obj->clone()); } @@ -201,8 +201,8 @@ namespace vmime * This is an alias for dynamic_pointer_cast (obj->clone()). */ template - shared_ptr clone(const shared_ptr & obj) - { + shared_ptr clone(const shared_ptr & obj) { + return dynamic_pointer_cast (obj->clone()); } @@ -210,8 +210,8 @@ namespace vmime * This is an alias for dynamic_pointer_cast (obj.clone()). */ template - shared_ptr clone(const T& obj) - { + shared_ptr clone(const T& obj) { + return dynamic_pointer_cast (obj.clone()); } @@ -220,24 +220,24 @@ namespace vmime * type Type, and DerivedType is derived from Type. */ template - shared_ptr dynamicCast(const shared_ptr & obj) - { + shared_ptr dynamicCast(const shared_ptr & obj) { + return dynamic_pointer_cast (obj); } /** Const cast helper. */ template - shared_ptr constCast(const shared_ptr & obj) - { + shared_ptr constCast(const shared_ptr & obj) { + return const_pointer_cast (obj); } /** Inherit from this class to indicate the subclass is not copyable, * ie. you want to prohibit copy construction and copy assignment. */ - class VMIME_EXPORT noncopyable - { + class VMIME_EXPORT noncopyable { + protected: noncopyable() { } diff --git a/src/vmime/body.cpp b/src/vmime/body.cpp index 41624b7b..3757026d 100644 --- a/src/vmime/body.cpp +++ b/src/vmime/body.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,75 +39,81 @@ #include "vmime/streamContentHandler.hpp" -namespace vmime -{ +namespace vmime { body::body() - : m_contents(make_shared ()) -{ + : m_contents(make_shared ()) { + } -body::~body() -{ +body::~body() { + } // static -size_t body::findNextBoundaryPosition - (const shared_ptr & parser, const string& boundary, - const size_t position, const size_t end, - size_t* boundaryStart, size_t* boundaryEnd) -{ +size_t body::findNextBoundaryPosition( + const shared_ptr & parser, + const string& boundary, + const size_t position, + const size_t end, + size_t* boundaryStart, + size_t* boundaryEnd +) { + size_t pos = position; - while (pos != npos && pos < end) - { + while (pos != npos && pos < end) { + pos = parser->findNext(boundary, pos); - if (pos == npos) + if (pos == npos) { break; // not found + } + + if (pos != 0) { - if (pos != 0) - { // Skip transport padding bytes (SPACE or HTAB), if any size_t advance = 0; - while (pos != 0) - { + while (pos != 0) { + parser->seek(pos - advance - 1); const byte_t c = parser->peekByte(); - if (c == ' ' || c == '\t') + if (c == ' ' || c == '\t') { ++advance; - else + } else { break; + } } // Ensure the bytes before boundary are "[LF]--": boundary should be // at the beginning of a line, and should start with "--" - if (pos - advance >= 3) - { + if (pos - advance >= 3) { + parser->seek(pos - advance - 3); - if (parser->matchBytes("\n--", 3)) - { + if (parser->matchBytes("\n--", 3)) { + parser->seek(pos + boundary.length()); const byte_t next = parser->peekByte(); // Boundary should be followed by a new line or a dash - if (next == '\r' || next == '\n' || next == '-') - { + if (next == '\r' || next == '\n' || next == '-') { + // Get rid of the "[CR]" just before "[LF]--", if any - if (pos - advance >= 4) - { + if (pos - advance >= 4) { + parser->seek(pos - advance - 4); - if (parser->peekByte() == '\r') + if (parser->peekByte() == '\r') { advance++; + } } *boundaryStart = pos - advance - 3; @@ -127,23 +133,26 @@ size_t body::findNextBoundaryPosition } -void body::parseImpl - (const parsingContext& ctx, - const shared_ptr & parser, - const size_t position, const size_t end, size_t* newPosition) -{ +void body::parseImpl( + const parsingContext& ctx, + const shared_ptr & parser, + const size_t position, + const size_t end, + size_t* newPosition +) { + removeAllParts(); m_prologText.clear(); m_epilogText.clear(); - if (end == position) - { + if (end == position) { setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } return; } @@ -156,40 +165,41 @@ void body::parseImpl shared_ptr ctf = m_part->getHeader()->findField (fields::CONTENT_TYPE); - if (ctf) - { + if (ctf) { + const mediaType type = *ctf->getValue (); - if (type.getType() == mediaTypes::MULTIPART) - { + if (type.getType() == mediaTypes::MULTIPART) { + isMultipart = true; - if (ctf->hasBoundary()) - { + if (ctf->hasBoundary()) { + boundary = ctf->getBoundary(); - } - else - { + + } else { + // No "boundary" parameter specified: we can try to // guess it by scanning the body contents... size_t pos = position; parser->seek(pos); - if (pos + 2 < end && parser->matchBytes("--", 2)) - { + if (pos + 2 < end && parser->matchBytes("--", 2)) { + pos += 2; - } - else - { + + } else { + pos = parser->findNext("\n--", position); - if ((pos != npos) && (pos + 3 < end)) + if ((pos != npos) && (pos + 3 < end)) { pos += 3; // skip \n-- + } } - if ((pos != npos) && (pos < end)) - { + if ((pos != npos) && (pos < end)) { + parser->seek(pos); // Read some bytes after boundary separator @@ -202,8 +212,9 @@ void body::parseImpl // Skip transport padding bytes (SPACE or HTAB), if any size_t boundarySkip = 0; - while (boundarySkip < bufferLen && parserHelpers::isSpace(buffer[boundarySkip])) + while (boundarySkip < bufferLen && parserHelpers::isSpace(buffer[boundarySkip])) { ++boundarySkip; + } // Extract boundary from buffer (stop at first CR or LF). // We have to stop after a reasonnably long boundary length (100) @@ -213,26 +224,27 @@ void body::parseImpl for (byte_t c = buffer[boundarySkip] ; boundaryLen < bufferLen && boundaryLen < 100 && !(c == '\r' || c == '\n') ; - ++boundaryLen, c = buffer[boundarySkip + boundaryLen]) - { + ++boundaryLen, c = buffer[boundarySkip + boundaryLen]) { + boundaryBytes[boundaryLen] = c; } - if (boundaryLen >= 1 && boundaryLen < 100) - { + if (boundaryLen >= 1 && boundaryLen < 100) { + // RFC #1521, Page 31: // "...the boundary parameter, which consists of 1 to 70 // characters from a set of characters known to be very // robust through email gateways, and NOT ending with // white space..." while (boundaryLen != 0 && - parserHelpers::isSpace(boundaryBytes[boundaryLen - 1])) - { + parserHelpers::isSpace(boundaryBytes[boundaryLen - 1])) { + boundaryLen--; } - if (boundaryLen >= 1) + if (boundaryLen >= 1) { boundary = string(boundaryBytes, boundaryBytes + boundaryLen); + } } } } @@ -240,8 +252,8 @@ void body::parseImpl } // This is a multi-part body - if (isMultipart && !boundary.empty()) - { + if (isMultipart && !boundary.empty()) { + size_t partStart = position; size_t pos = position; @@ -251,15 +263,15 @@ void body::parseImpl size_t boundaryStart, boundaryEnd; pos = findNextBoundaryPosition(parser, boundary, pos, end, &boundaryStart, &boundaryEnd); - for (int index = 0 ; !lastPart && (pos != npos) && (pos < end) ; ++index) - { + for (int index = 0 ; !lastPart && (pos != npos) && (pos < end) ; ++index) { + size_t partEnd = boundaryStart; // Check whether it is the last part (boundary terminated by "--") parser->seek(boundaryEnd); - if (boundaryEnd + 1 < end && parser->matchBytes("--", 2)) - { + if (boundaryEnd + 1 < end && parser->matchBytes("--", 2)) { + lastPart = true; boundaryEnd += 2; } @@ -272,37 +284,35 @@ void body::parseImpl boundaryEnd += parser->skipIf(parserHelpers::isSpaceOrTab, end); // End of boundary line - if (boundaryEnd + 1 < end && parser->matchBytes("\r\n", 2)) - { + if (boundaryEnd + 1 < end && parser->matchBytes("\r\n", 2)) { boundaryEnd += 2; - } - else if (boundaryEnd < end && parser->peekByte() == '\n') - { + } else if (boundaryEnd < end && parser->peekByte() == '\n') { ++boundaryEnd; } - if (index == 0) - { - if (partEnd > partStart) - { + if (index == 0) { + + if (partEnd > partStart) { + vmime::text text; text.parse(ctx, parser, partStart, partEnd); m_prologText = text.getWholeBuffer(); - } - else - { + + } else { + m_prologText = ""; } - } - else // index > 0 - { + + } else { // index > 0 + shared_ptr part = m_part->createChildPart(); // End before start may happen on empty bodyparts (directly // successive boundaries without even a line-break) - if (partEnd < partStart) + if (partEnd < partStart) { std::swap(partStart, partEnd); + } part->parse(ctx, parser, partStart, partEnd, NULL); @@ -312,51 +322,49 @@ void body::parseImpl partStart = boundaryEnd; // Find the next boundary - pos = findNextBoundaryPosition - (parser, boundary, boundaryEnd, end, &boundaryStart, &boundaryEnd); + pos = findNextBoundaryPosition( + parser, boundary, boundaryEnd, end, &boundaryStart, &boundaryEnd + ); } m_contents = make_shared (); // Last part was not found: recover from missing boundary - if (!lastPart && pos == npos) - { + if (!lastPart && pos == npos) { + shared_ptr part = m_part->createChildPart(); - try - { + try { part->parse(ctx, parser, partStart, end); - } - catch (std::exception&) - { + } catch (std::exception&) { throw; } m_parts.push_back(part); - } + // Treat remaining text as epilog - else if (partStart < end) - { + } else if (partStart < end) { + vmime::text text; text.parse(ctx, parser, partStart, end); m_epilogText = text.getWholeBuffer(); } - } + // Treat the contents as 'simple' data - else - { + } else { + encoding enc; shared_ptr cef = m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING); - if (cef) - { + if (cef) { + enc = *cef->getValue (); - } - else - { + + } else { + // Defaults to "7bit" (RFC-1521) enc = vmime::encoding(encodingTypes::SEVEN_BIT); } @@ -365,21 +373,23 @@ void body::parseImpl const size_t length = end - position; shared_ptr contentStream = - make_shared - (parser->getUnderlyingStream(), position, length); + make_shared ( + parser->getUnderlyingStream(), position, length + ); m_contents = make_shared (contentStream, length, enc); } setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -text body::getActualPrologText(const generationContext& ctx) const -{ +text body::getActualPrologText(const generationContext& ctx) const { + const string& prologText = m_prologText.empty() ? (isRootPart() @@ -388,15 +398,16 @@ text body::getActualPrologText(const generationContext& ctx) const ) : m_prologText; - if (prologText.empty()) + if (prologText.empty()) { return text(); - else + } else { return text(prologText, vmime::charset("us-ascii")); + } } -text body::getActualEpilogText(const generationContext& ctx) const -{ +text body::getActualEpilogText(const generationContext& ctx) const { + const string& epilogText = m_epilogText.empty() ? (isRootPart() @@ -405,47 +416,51 @@ text body::getActualEpilogText(const generationContext& ctx) const ) : m_epilogText; - if (epilogText.empty()) + if (epilogText.empty()) { return text(); - else + } else { return text(epilogText, vmime::charset("us-ascii")); + } } -void body::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t /* curLinePos */, size_t* newLinePos) const -{ +void body::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t /* curLinePos */, + size_t* newLinePos +) const { + // MIME-Multipart - if (getPartCount() != 0) - { + if (getPartCount() != 0) { + string boundary; - if (!m_part) - { + if (!m_part) { + boundary = generateRandomBoundaryString(); - } - else - { + + } else { + // Use current boundary string, if specified. If no "Content-Type" field is // present, or the boundary is not specified, generate a random one shared_ptr ctf = m_part->getHeader()->findField (fields::CONTENT_TYPE); - if (ctf) - { - if (ctf->hasBoundary()) - { + if (ctf) { + + if (ctf->hasBoundary()) { + boundary = ctf->getBoundary(); - } - else - { + + } else { + // No boundary string specified boundary = generateRandomBoundaryString(); } - } - else - { + + } else { + // No Content-Type (and no boundary string specified) boundary = generateRandomBoundaryString(); } @@ -454,18 +469,20 @@ void body::generateImpl const text prologText = getActualPrologText(ctx); const text epilogText = getActualEpilogText(ctx); - if (!prologText.isEmpty()) - { - prologText.encodeAndFold(ctx, os, 0, - NULL, text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE); + if (!prologText.isEmpty()) { + + prologText.encodeAndFold( + ctx, os, 0, NULL, + text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE + ); os << CRLF; } os << "--" << boundary; - for (size_t p = 0 ; p < getPartCount() ; ++p) - { + for (size_t p = 0 ; p < getPartCount() ; ++p) { + os << CRLF; getPartAt(p)->generate(ctx, os, 0); @@ -475,20 +492,23 @@ void body::generateImpl os << "--" << CRLF; - if (!epilogText.isEmpty()) - { - epilogText.encodeAndFold(ctx, os, 0, - NULL, text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE); + if (!epilogText.isEmpty()) { + + epilogText.encodeAndFold( + ctx, os, 0, NULL, + text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE + ); os << CRLF; } - if (newLinePos) + if (newLinePos) { *newLinePos = 0; - } + } + // Simple body - else - { + } else { + // Generate the contents shared_ptr contents = m_contents->clone(); contents->setContentTypeHint(getContentType()); @@ -498,16 +518,15 @@ void body::generateImpl } -size_t body::getGeneratedSize(const generationContext& ctx) -{ +size_t body::getGeneratedSize(const generationContext& ctx) { + // MIME-Multipart - if (getPartCount() != 0) - { + if (getPartCount() != 0) { + size_t size = 0; // Size of parts and boundaries - for (size_t p = 0 ; p < getPartCount() ; ++p) - { + for (size_t p = 0 ; p < getPartCount() ; ++p) { size += 100; // boundary, CRLF... size += getPartAt(p)->getGeneratedSize(ctx); } @@ -515,42 +534,46 @@ size_t body::getGeneratedSize(const generationContext& ctx) // Size of prolog/epilog text const text prologText = getActualPrologText(ctx); - if (!prologText.isEmpty()) - { + if (!prologText.isEmpty()) { + std::ostringstream oss; utility::outputStreamAdapter osa(oss); - prologText.encodeAndFold(ctx, osa, 0, - NULL, text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE); + prologText.encodeAndFold( + ctx, osa, 0, NULL, + text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE + ); size += oss.str().size(); } const text epilogText = getActualEpilogText(ctx); - if (!epilogText.isEmpty()) - { + if (!epilogText.isEmpty()) { + std::ostringstream oss; utility::outputStreamAdapter osa(oss); - epilogText.encodeAndFold(ctx, osa, 0, - NULL, text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE); + epilogText.encodeAndFold( + ctx, osa, 0, NULL, + text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE + ); size += oss.str().size(); } return size; - } + // Simple body - else - { - if (getEncoding() == m_contents->getEncoding()) - { + } else { + + if (getEncoding() == m_contents->getEncoding()) { + // No re-encoding has to be performed return m_contents->getLength(); - } - else - { + + } else { + shared_ptr srcEncoder = m_contents->getEncoding().getEncoder(); shared_ptr dstEncoder = getEncoding().getEncoder(); @@ -576,8 +599,8 @@ size_t body::getGeneratedSize(const generationContext& ctx) / "," / "-" / "." / "/" / ":" / "=" / "?" */ -const string body::generateRandomBoundaryString() -{ +const string body::generateRandomBoundaryString() { + // 64 characters that can be _safely_ used in a boundary string static const char bchars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-+"; @@ -603,43 +626,43 @@ const string body::generateRandomBoundaryString() unsigned int r = utility::random::getTime(); unsigned int m = static_cast (sizeof(unsigned int)); - for (size_t i = 2 ; i < (sizeof(boundary) / sizeof(boundary[0]) - 1) ; ++i) - { + for (size_t i = 2 ; i < (sizeof(boundary) / sizeof(boundary[0]) - 1) ; ++i) { + boundary[i] = bchars[r & 63]; r >>= 6; - if (--m == 0) - { + if (--m == 0) { r = utility::random::getNext(); m = static_cast (sizeof(unsigned int)); } } - return (string(boundary)); + return string(boundary); } -bool body::isValidBoundary(const string& boundary) -{ +bool body::isValidBoundary(const string& boundary) { + static const string validChars("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'()+_,-./:=?"); const string::const_iterator end = boundary.end(); bool valid = false; - if (boundary.length() > 0 && boundary.length() < 70) - { + if (boundary.length() > 0 && boundary.length() < 70) { + const char last = *(end - 1); - if (!(last == ' ' || last == '\t' || last == '\n')) - { + if (!(last == ' ' || last == '\t' || last == '\n')) { + valid = true; - for (string::const_iterator i = boundary.begin() ; valid && i != end ; ++i) + for (string::const_iterator i = boundary.begin() ; valid && i != end ; ++i) { valid = (validChars.find_first_of(*i) != string::npos); + } } } - return (valid); + return valid; } @@ -648,8 +671,8 @@ bool body::isValidBoundary(const string& boundary) // -void body::setContentType(const mediaType& type, const charset& chset) -{ +void body::setContentType(const mediaType& type, const charset& chset) { + shared_ptr ctf = dynamicCast (m_part->getHeader()->ContentType()); @@ -658,92 +681,93 @@ void body::setContentType(const mediaType& type, const charset& chset) } -void body::setContentType(const mediaType& type) -{ +void body::setContentType(const mediaType& type) { + m_part->getHeader()->ContentType()->setValue(type); } -const mediaType body::getContentType() const -{ +const mediaType body::getContentType() const { + shared_ptr ctf = m_part->getHeader()->findField (fields::CONTENT_TYPE); - if (ctf) - { + if (ctf) { + return *ctf->getValue (); - } - else - { + + } else { + // Defaults to "text/plain" (RFC-1521) - return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); + return mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN); } } -void body::setCharset(const charset& chset) -{ +void body::setCharset(const charset& chset) { + shared_ptr ctf = m_part->getHeader()->findField (fields::CONTENT_TYPE); // If a Content-Type field exists, set charset - if (ctf) - { + if (ctf) { + ctf->setCharset(chset); - } + // Else, create a new Content-Type field of default type "text/plain" // and set charset on it - else - { + } else { + setContentType(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN), chset); } } -const charset body::getCharset() const -{ +const charset body::getCharset() const { + const shared_ptr ctf = m_part->getHeader()->findField (fields::CONTENT_TYPE); - if (ctf) - { - if (ctf->hasCharset()) - { - return (ctf->getCharset()); - } - else - { + if (ctf) { + + if (ctf->hasCharset()) { + + return ctf->getCharset(); + + } else { + // Defaults to "us-ascii" (RFC-1521) - return (vmime::charset(charsets::US_ASCII)); + return vmime::charset(charsets::US_ASCII); } - } - else - { + + } else { + // Defaults to "us-ascii" (RFC-1521) - return (vmime::charset(charsets::US_ASCII)); + return vmime::charset(charsets::US_ASCII); } } -void body::setEncoding(const encoding& enc) -{ +void body::setEncoding(const encoding& enc) { + m_part->getHeader()->ContentTransferEncoding()->setValue(enc); } -const encoding body::getEncoding() const -{ +const encoding body::getEncoding() const { + shared_ptr cef = m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING); - if (cef) - { + if (cef) { + return *cef->getValue (); - } - else - { - if (m_contents->isEncoded()) + + } else { + + if (m_contents->isEncoded()) { return m_contents->getEncoding(); + } } // Defaults to "7bit" (RFC-1521) @@ -751,37 +775,37 @@ const encoding body::getEncoding() const } -void body::setParentPart(bodyPart* parent) -{ +void body::setParentPart(bodyPart* parent) { + m_part = parent; for (std::vector >::iterator it = m_parts.begin() ; - it != m_parts.end() ; ++it) - { + it != m_parts.end() ; ++it) { + shared_ptr childPart = *it; parent->importChildPart(childPart); } } -bool body::isRootPart() const -{ - return (m_part == NULL || m_part->getParentPart() == NULL); +bool body::isRootPart() const { + + return !m_part || !m_part->getParentPart(); } -shared_ptr body::clone() const -{ +shared_ptr body::clone() const { + shared_ptr bdy = make_shared (); bdy->copyFrom(*this); - return (bdy); + return bdy; } -void body::copyFrom(const component& other) -{ +void body::copyFrom(const component& other) { + const body& bdy = dynamic_cast (other); m_prologText = bdy.m_prologText; @@ -791,8 +815,8 @@ void body::copyFrom(const component& other) removeAllParts(); - for (size_t p = 0 ; p < bdy.getPartCount() ; ++p) - { + for (size_t p = 0 ; p < bdy.getPartCount() ; ++p) { + shared_ptr part = m_part->createChildPart(); part->copyFrom(*bdy.getPartAt(p)); @@ -802,68 +826,79 @@ void body::copyFrom(const component& other) } -body& body::operator=(const body& other) -{ +body& body::operator=(const body& other) { + copyFrom(other); - return (*this); + return *this; } -const string& body::getPrologText() const -{ - return (m_prologText); +const string& body::getPrologText() const { + + return m_prologText; } -void body::setPrologText(const string& prologText) -{ +void body::setPrologText(const string& prologText) { + m_prologText = prologText; } -const string& body::getEpilogText() const -{ - return (m_epilogText); +const string& body::getEpilogText() const { + + return m_epilogText; } -void body::setEpilogText(const string& epilogText) -{ +void body::setEpilogText(const string& epilogText) { + m_epilogText = epilogText; } -const shared_ptr body::getContents() const -{ - return (m_contents); +const shared_ptr body::getContents() const { + + return m_contents; } -void body::setContents(const shared_ptr & contents) -{ +void body::setContents(const shared_ptr & contents) { + m_contents = contents; } -void body::setContents(const shared_ptr & contents, const mediaType& type) -{ +void body::setContents( + const shared_ptr & contents, + const mediaType& type +) { + m_contents = contents; setContentType(type); } -void body::setContents(const shared_ptr & contents, const mediaType& type, const charset& chset) -{ +void body::setContents( + const shared_ptr & contents, + const mediaType& type, + const charset& chset +) { + m_contents = contents; setContentType(type, chset); } -void body::setContents(const shared_ptr & contents, const mediaType& type, - const charset& chset, const encoding& enc) -{ +void body::setContents( + const shared_ptr & contents, + const mediaType& type, + const charset& chset, + const encoding& enc +) { + m_contents = contents; setContentType(type, chset); @@ -871,16 +906,17 @@ void body::setContents(const shared_ptr & contents, const } -void body::initNewPart(const shared_ptr & part) -{ +void body::initNewPart(const shared_ptr & part) { + // A part can be in only one body at the same time: if part is // already attached to a parent part, remove it from the current // parent part - if (part->getParentPart()) + if (part->getParentPart()) { part->getParentPart()->getBody()->removePart(part); + } + + if (m_part) { - if (m_part != NULL) - { m_part->importChildPart(part); shared_ptr
hdr = m_part->getHeader(); @@ -889,29 +925,30 @@ void body::initNewPart(const shared_ptr & part) shared_ptr ctf = hdr->findField (fields::CONTENT_TYPE); - if (ctf) - { - if (ctf->hasBoundary()) - { + if (ctf) { + + if (ctf->hasBoundary()) { + const string boundary = ctf->getBoundary(); - if (boundary.empty() || !isValidBoundary(boundary)) + if (boundary.empty() || !isValidBoundary(boundary)) { ctf->setBoundary(generateRandomBoundaryString()); - } - else - { + } + + } else { + // No "boundary" parameter: generate a random one. ctf->setBoundary(generateRandomBoundaryString()); } - if (ctf->getValue ()->getType() != mediaTypes::MULTIPART) - { + if (ctf->getValue ()->getType() != mediaTypes::MULTIPART) { + // Warning: multi-part body but the Content-Type is // not specified as "multipart/..." } - } - else - { + + } else { + // No "Content-Type" field: create a new one and generate // a random boundary string. ctf = hdr->getField (fields::CONTENT_TYPE); @@ -923,135 +960,150 @@ void body::initNewPart(const shared_ptr & part) } -void body::appendPart(const shared_ptr & part) -{ +void body::appendPart(const shared_ptr & part) { + initNewPart(part); m_parts.push_back(part); } -void body::insertPartBefore(const shared_ptr & beforePart, const shared_ptr & part) -{ +void body::insertPartBefore( + const shared_ptr & beforePart, + const shared_ptr & part +) { + initNewPart(part); - const std::vector >::iterator it = std::find - (m_parts.begin(), m_parts.end(), beforePart); + const std::vector >::iterator it = std::find( + m_parts.begin(), m_parts.end(), beforePart + ); - if (it == m_parts.end()) + if (it == m_parts.end()) { throw exceptions::no_such_part(); + } m_parts.insert(it, part); } -void body::insertPartBefore(const size_t pos, const shared_ptr & part) -{ +void body::insertPartBefore( + const size_t pos, + const shared_ptr & part +) { + initNewPart(part); m_parts.insert(m_parts.begin() + pos, part); } -void body::insertPartAfter(const shared_ptr & afterPart, const shared_ptr & part) -{ +void body::insertPartAfter( + const shared_ptr & afterPart, + const shared_ptr & part +) { + initNewPart(part); - const std::vector >::iterator it = std::find - (m_parts.begin(), m_parts.end(), afterPart); + const std::vector >::iterator it = std::find( + m_parts.begin(), m_parts.end(), afterPart + ); - if (it == m_parts.end()) + if (it == m_parts.end()) { throw exceptions::no_such_part(); + } m_parts.insert(it + 1, part); } -void body::insertPartAfter(const size_t pos, const shared_ptr & part) -{ +void body::insertPartAfter(const size_t pos, const shared_ptr & part) { + initNewPart(part); m_parts.insert(m_parts.begin() + pos + 1, part); } -void body::removePart(const shared_ptr & part) -{ - const std::vector >::iterator it = std::find - (m_parts.begin(), m_parts.end(), part); +void body::removePart(const shared_ptr & part) { - if (it == m_parts.end()) + const std::vector >::iterator it = std::find( + m_parts.begin(), m_parts.end(), part + ); + + if (it == m_parts.end()) { throw exceptions::no_such_part(); + } m_parts.erase(it); } -void body::removePart(const size_t pos) -{ +void body::removePart(const size_t pos) { + m_parts.erase(m_parts.begin() + pos); } -void body::removeAllParts() -{ +void body::removeAllParts() { + m_parts.clear(); } -size_t body::getPartCount() const -{ - return (m_parts.size()); +size_t body::getPartCount() const { + + return m_parts.size(); } -bool body::isEmpty() const -{ - return (m_parts.size() == 0); +bool body::isEmpty() const { + + return m_parts.size() == 0; } -shared_ptr body::getPartAt(const size_t pos) -{ - return (m_parts[pos]); +shared_ptr body::getPartAt(const size_t pos) { + + return m_parts[pos]; } -const shared_ptr body::getPartAt(const size_t pos) const -{ - return (m_parts[pos]); +const shared_ptr body::getPartAt(const size_t pos) const { + + return m_parts[pos]; } -const std::vector > body::getPartList() const -{ +const std::vector > body::getPartList() const { + std::vector > list; list.reserve(m_parts.size()); for (std::vector >::const_iterator it = m_parts.begin() ; - it != m_parts.end() ; ++it) - { + it != m_parts.end() ; ++it) { + list.push_back(*it); } - return (list); + return list; } -const std::vector > body::getPartList() -{ - return (m_parts); +const std::vector > body::getPartList() { + + return m_parts; } -const std::vector > body::getChildComponents() -{ +const std::vector > body::getChildComponents() { + std::vector > list; copy_vector(m_parts, list); - return (list); + return list; } diff --git a/src/vmime/body.hpp b/src/vmime/body.hpp index 24f010b4..7ece000e 100644 --- a/src/vmime/body.hpp +++ b/src/vmime/body.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,8 +37,7 @@ #include "vmime/contentHandler.hpp" -namespace vmime -{ +namespace vmime { class bodyPart; @@ -46,9 +45,8 @@ class bodyPart; /** Body section of a MIME part. */ +class VMIME_EXPORT body : public component { -class VMIME_EXPORT body : public component -{ friend class bodyPart; public: @@ -68,7 +66,10 @@ public: * @param part part to insert * @throw exceptions::no_such_part if the part is not in the list */ - void insertPartBefore(const shared_ptr & beforePart, const shared_ptr & part); + void insertPartBefore( + const shared_ptr & beforePart, + const shared_ptr & part + ); /** Insert a new part before the specified position. * @@ -84,7 +85,10 @@ public: * @param part part to insert * @throw exceptions::no_such_part if the part is not in the list */ - void insertPartAfter(const shared_ptr & afterPart, const shared_ptr & part); + void insertPartAfter( + const shared_ptr & afterPart, + const shared_ptr & part + ); /** Insert a new part after the specified position. * @@ -189,7 +193,10 @@ public: * @param contents new body contents * @param type type of contents */ - void setContents(const shared_ptr & contents, const mediaType& type); + void setContents( + const shared_ptr & contents, + const mediaType& type + ); /** Set the body contents, type and charset. * @@ -197,7 +204,11 @@ public: * @param type type of contents * @param chset charset of contents */ - void setContents(const shared_ptr & contents, const mediaType& type, const charset& chset); + void setContents( + const shared_ptr & contents, + const mediaType& type, + const charset& chset + ); /** Set the body contents, type, charset and encoding. * @@ -206,8 +217,12 @@ public: * @param chset charset of contents * @param enc contents encoding */ - void setContents(const shared_ptr & contents, const mediaType& type, - const charset& chset, const encoding& enc); + void setContents( + const shared_ptr & contents, + const mediaType& type, + const charset& chset, + const encoding& enc + ); /** Set the MIME type and charset of contents. * If a charset is defined, it will not be modified. @@ -317,24 +332,30 @@ protected: * before the CRLF or "--" which follows) * @return the position of the boundary string, or npos if not found */ - size_t findNextBoundaryPosition - (const shared_ptr & parser, const string& boundary, - const size_t position, const size_t end, - size_t* boundaryStart, size_t* boundaryEnd); + size_t findNextBoundaryPosition( + const shared_ptr & parser, + const string& boundary, + const size_t position, + const size_t end, + size_t* boundaryStart, + size_t* boundaryEnd + ); // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const shared_ptr & parser, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const shared_ptr & parser, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/bodyPart.cpp b/src/vmime/bodyPart.cpp index c215eb80..ff81994d 100644 --- a/src/vmime/bodyPart.cpp +++ b/src/vmime/bodyPart.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -24,23 +24,26 @@ #include "vmime/bodyPart.hpp" -namespace vmime -{ +namespace vmime { bodyPart::bodyPart() : m_header(make_shared
()), m_body(make_shared ()), - m_parent() -{ + m_parent() { + m_body->setParentPart(this); } -void bodyPart::parseImpl - (const parsingContext& ctx, const shared_ptr & parser, - const size_t position, const size_t end, size_t* newPosition) -{ +void bodyPart::parseImpl( + const parsingContext& ctx, + const shared_ptr & parser, + const size_t position, + const size_t end, + size_t* newPosition +) { + // Parse the headers size_t pos = position; m_header->parse(ctx, parser, pos, end, &pos); @@ -50,34 +53,39 @@ void bodyPart::parseImpl setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void bodyPart::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t /* curLinePos */, size_t* newLinePos) const -{ +void bodyPart::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t /* curLinePos */, + size_t* newLinePos +) const { + m_header->generate(ctx, os); os << CRLF; m_body->generate(ctx, os); - if (newLinePos) + if (newLinePos) { *newLinePos = 0; + } } -size_t bodyPart::getGeneratedSize(const generationContext& ctx) -{ +size_t bodyPart::getGeneratedSize(const generationContext& ctx) { + return m_header->getGeneratedSize(ctx) + 2 /* CRLF */ + m_body->getGeneratedSize(ctx); } -shared_ptr bodyPart::clone() const -{ +shared_ptr bodyPart::clone() const { + shared_ptr p = make_shared (); p->m_parent = NULL; @@ -85,12 +93,12 @@ shared_ptr bodyPart::clone() const p->m_header->copyFrom(*m_header); p->m_body->copyFrom(*m_body); - return (p); + return p; } -void bodyPart::copyFrom(const component& other) -{ +void bodyPart::copyFrom(const component& other) { + const bodyPart& bp = dynamic_cast (other); m_header->copyFrom(*(bp.m_header)); @@ -98,70 +106,71 @@ void bodyPart::copyFrom(const component& other) } -bodyPart& bodyPart::operator=(const bodyPart& other) -{ +bodyPart& bodyPart::operator=(const bodyPart& other) { + copyFrom(other); - return (*this); + return *this; } -const shared_ptr bodyPart::getHeader() const -{ - return (m_header); +const shared_ptr bodyPart::getHeader() const { + + return m_header; } -shared_ptr
bodyPart::getHeader() -{ - return (m_header); +shared_ptr
bodyPart::getHeader() { + + return m_header; } -void bodyPart::setHeader(const shared_ptr
& h) -{ +void bodyPart::setHeader(const shared_ptr
& h) { + m_header = h; } -const shared_ptr bodyPart::getBody() const -{ - return (m_body); +const shared_ptr bodyPart::getBody() const { + + return m_body; } -shared_ptr bodyPart::getBody() -{ - return (m_body); +shared_ptr bodyPart::getBody() { + + return m_body; } -void bodyPart::setBody(const shared_ptr & b) -{ +void bodyPart::setBody(const shared_ptr & b) { + bodyPart* oldPart = b->m_part; m_body = b; m_body->setParentPart(this); // A body is associated to one and only one part - if (oldPart != NULL) + if (oldPart) { oldPart->setBody(make_shared ()); + } } -bodyPart* bodyPart::getParentPart() -{ +bodyPart* bodyPart::getParentPart() { + return m_parent; } -const bodyPart* bodyPart::getParentPart() const -{ +const bodyPart* bodyPart::getParentPart() const { + return m_parent; } -shared_ptr bodyPart::createChildPart() -{ +shared_ptr bodyPart::createChildPart() { + shared_ptr part = make_shared (); part->m_parent = this; @@ -169,22 +178,21 @@ shared_ptr bodyPart::createChildPart() } -void bodyPart::importChildPart(const shared_ptr & part) -{ +void bodyPart::importChildPart(const shared_ptr & part) { + part->m_parent = this; } -const std::vector > bodyPart::getChildComponents() -{ +const std::vector > bodyPart::getChildComponents() { + std::vector > list; list.push_back(m_header); list.push_back(m_body); - return (list); + return list; } } // vmime - diff --git a/src/vmime/bodyPart.hpp b/src/vmime/bodyPart.hpp index 729af253..f63b3675 100644 --- a/src/vmime/bodyPart.hpp +++ b/src/vmime/bodyPart.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,15 +32,13 @@ #include "vmime/body.hpp" -namespace vmime -{ +namespace vmime { /** A MIME part. */ +class VMIME_EXPORT bodyPart : public component { -class VMIME_EXPORT bodyPart : public component -{ friend class body; public: @@ -134,18 +132,20 @@ protected: void importChildPart(const shared_ptr & part); // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const shared_ptr & parser, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const shared_ptr & parser, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/bodyPartAttachment.cpp b/src/vmime/bodyPartAttachment.cpp index 07a92d12..01b306e3 100644 --- a/src/vmime/bodyPartAttachment.cpp +++ b/src/vmime/bodyPartAttachment.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -24,55 +24,57 @@ #include "vmime/bodyPartAttachment.hpp" -namespace vmime -{ +namespace vmime { bodyPartAttachment::bodyPartAttachment(const shared_ptr & part) - : m_part(part) -{ + : m_part(part) { + } -const mediaType bodyPartAttachment::getType() const -{ +const mediaType bodyPartAttachment::getType() const { + shared_ptr ctf = getContentType(); - if (ctf) - { + if (ctf) { + return *ctf->getValue (); - } - else - { + + } else { + // No "Content-type" field: assume "application/octet-stream". - return mediaType(mediaTypes::APPLICATION, - mediaTypes::APPLICATION_OCTET_STREAM); + return mediaType( + mediaTypes::APPLICATION, + mediaTypes::APPLICATION_OCTET_STREAM + ); } } -const word bodyPartAttachment::getName() const -{ +const word bodyPartAttachment::getName() const { + word name; // Try the 'filename' parameter of 'Content-Disposition' field shared_ptr cdf = getContentDisposition(); - if (cdf && cdf->hasFilename()) - { + if (cdf && cdf->hasFilename()) { + name = cdf->getFilename(); - } + // Try the 'name' parameter of 'Content-Type' field - else - { + } else { + shared_ptr ctf = getContentType(); - if (ctf) - { + if (ctf) { + shared_ptr prm = ctf->findParameter("name"); - if (prm != NULL) + if (prm) { name = prm->getValue(); + } } } @@ -80,19 +82,19 @@ const word bodyPartAttachment::getName() const } -const text bodyPartAttachment::getDescription() const -{ +const text bodyPartAttachment::getDescription() const { + text description; shared_ptr cd = getHeader()->findField(fields::CONTENT_DESCRIPTION); - if (cd) - { + if (cd) { + description = *cd->getValue (); - } - else - { + + } else { + // No description available. } @@ -100,47 +102,46 @@ const text bodyPartAttachment::getDescription() const } -const encoding bodyPartAttachment::getEncoding() const -{ +const encoding bodyPartAttachment::getEncoding() const { + return m_part->getBody()->getEncoding(); } -const shared_ptr bodyPartAttachment::getData() const -{ +const shared_ptr bodyPartAttachment::getData() const { + return m_part->getBody()->getContents(); } -shared_ptr bodyPartAttachment::getPart() const -{ +shared_ptr bodyPartAttachment::getPart() const { + return m_part; } -shared_ptr bodyPartAttachment::getHeader() const -{ +shared_ptr bodyPartAttachment::getHeader() const { + return m_part->getHeader(); } -shared_ptr bodyPartAttachment::getContentDisposition() const -{ +shared_ptr bodyPartAttachment::getContentDisposition() const { + return getHeader()->findField (fields::CONTENT_DISPOSITION); } -shared_ptr bodyPartAttachment::getContentType() const -{ +shared_ptr bodyPartAttachment::getContentType() const { + return getHeader()->findField (fields::CONTENT_TYPE); } -void bodyPartAttachment::generateIn(const shared_ptr & /* parent */) const -{ +void bodyPartAttachment::generateIn(const shared_ptr & /* parent */) const { + // Not used } } // vmime - diff --git a/src/vmime/bodyPartAttachment.hpp b/src/vmime/bodyPartAttachment.hpp index 43848bd3..974e2f8c 100644 --- a/src/vmime/bodyPartAttachment.hpp +++ b/src/vmime/bodyPartAttachment.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,14 +34,13 @@ #include "vmime/contentTypeField.hpp" -namespace vmime -{ +namespace vmime { /** An attachment related to a local body part. */ -class VMIME_EXPORT bodyPartAttachment : public attachment -{ +class VMIME_EXPORT bodyPartAttachment : public attachment { + public: bodyPartAttachment(const shared_ptr & part); @@ -75,4 +74,3 @@ private: #endif // VMIME_BODYPARTATTACHMENT_HPP_INCLUDED - diff --git a/src/vmime/charset.cpp b/src/vmime/charset.cpp index 1a291106..8828c563 100644 --- a/src/vmime/charset.cpp +++ b/src/vmime/charset.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,74 +32,93 @@ -namespace vmime -{ +namespace vmime { charset::charset() - : m_name(charsets::US_ASCII) -{ + : m_name(charsets::US_ASCII) { + } charset::charset(const string& name) - : m_name(name) -{ + : m_name(name) { + // If we receive this rfc-1642 valid MIME charset, convert it to something usefull for iconv - if (utility::stringUtils::isStringEqualNoCase(m_name, "unicode-1-1-utf-7")) + if (utility::stringUtils::isStringEqualNoCase(m_name, "unicode-1-1-utf-7")) { m_name = "utf-7"; + } } charset::charset(const char* name) - : m_name(name) -{ + : m_name(name) { + } -void charset::parseImpl - (const parsingContext& /* ctx */, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ - m_name = utility::stringUtils::trim - (string(buffer.begin() + position, buffer.begin() + end)); +void charset::parseImpl( + const parsingContext& /* ctx */, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + + m_name = utility::stringUtils::trim( + string(buffer.begin() + position, buffer.begin() + end) + ); // If we parsed this rfc-1642 valid MIME charset, convert it to something usefull for iconv - if (utility::stringUtils::isStringEqualNoCase(m_name, "unicode-1-1-utf-7")) + if (utility::stringUtils::isStringEqualNoCase(m_name, "unicode-1-1-utf-7")) { m_name = "utf-7"; + } setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void charset::generateImpl - (const generationContext& /* ctx */, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void charset::generateImpl( + const generationContext& /* ctx */, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + os << m_name; - if (newLinePos) + if (newLinePos) { *newLinePos = curLinePos + m_name.length(); + } } -void charset::convert(utility::inputStream& in, utility::outputStream& out, - const charset& source, const charset& dest, - const charsetConverterOptions& opts) -{ +void charset::convert( + utility::inputStream& in, + utility::outputStream& out, + const charset& source, + const charset& dest, + const charsetConverterOptions& opts +) { + shared_ptr conv = charsetConverter::create(source, dest, opts); conv->convert(in, out); } -void charset::convert(const string& in, string& out, const charset& source, const charset& dest, - const charsetConverterOptions& opts) -{ - if (source == dest) - { +void charset::convert( + const string& in, + string& out, + const charset& source, + const charset& dest, + const charsetConverterOptions& opts +) { + + if (source == dest) { out = in; return; } @@ -109,27 +128,26 @@ void charset::convert(const string& in, string& out, const charset& source, cons } -bool charset::isValidText - (const string& text, string::size_type* firstInvalidByte) const -{ +bool charset::isValidText(const string& text, string::size_type* firstInvalidByte) const { + charsetConverterOptions opts; opts.silentlyReplaceInvalidSequences = false; charsetConverter::status st; - try - { + try { + std::string out; // Try converting to UTF-8 shared_ptr conv = charsetConverter::create(*this, vmime::charset("utf-8"), opts); conv->convert(text, out, &st); - } - catch (exceptions::illegal_byte_sequence_for_charset& e) - { + + } catch (exceptions::illegal_byte_sequence_for_charset& e) { + // An illegal byte sequence was found in the input buffer - if (firstInvalidByte) - { + if (firstInvalidByte) { + if (st.inputBytesRead < text.length()) *firstInvalidByte = st.inputBytesRead; else @@ -139,77 +157,79 @@ bool charset::isValidText return false; } - if (firstInvalidByte) + if (firstInvalidByte) { *firstInvalidByte = text.length(); + } return true; } -const charset charset::getLocalCharset() -{ - return (platform::getHandler()->getLocalCharset()); +const charset charset::getLocalCharset() { + + return platform::getHandler()->getLocalCharset(); } -charset& charset::operator=(const charset& other) -{ +charset& charset::operator=(const charset& other) { + copyFrom(other); - return (*this); + return *this; } -bool charset::operator==(const charset& value) const -{ - return (utility::stringUtils::isStringEqualNoCase(m_name, value.m_name)); +bool charset::operator==(const charset& value) const { + + return utility::stringUtils::isStringEqualNoCase(m_name, value.m_name); } -bool charset::operator!=(const charset& value) const -{ +bool charset::operator!=(const charset& value) const { + return !(*this == value); } -shared_ptr charset::clone() const -{ +shared_ptr charset::clone() const { + return make_shared (m_name); } -const string& charset::getName() const -{ - return (m_name); +const string& charset::getName() const { + + return m_name; } -void charset::copyFrom(const component& other) -{ +void charset::copyFrom(const component& other) { + m_name = dynamic_cast (other).m_name; } -const std::vector > charset::getChildComponents() -{ +const std::vector > charset::getChildComponents() { + return std::vector >(); } // Explicitly force encoding for some charsets -struct CharsetEncodingEntry -{ +struct CharsetEncodingEntry { + CharsetEncodingEntry(const string& charset_, const string& encoding_) - : charset(charset_), encoding(encoding_) - { + : charset(charset_), encoding(encoding_) { + } const string charset; const string encoding; }; -CharsetEncodingEntry g_charsetEncodingMap[] = -{ + +CharsetEncodingEntry g_charsetEncodingMap[] = { + // Use QP encoding for ISO-8859-x charsets CharsetEncodingEntry("iso-8859", encodingTypes::QUOTED_PRINTABLE), CharsetEncodingEntry("iso8859", encodingTypes::QUOTED_PRINTABLE), @@ -226,15 +246,16 @@ CharsetEncodingEntry g_charsetEncodingMap[] = }; -bool charset::getRecommendedEncoding(encoding& enc) const -{ +bool charset::getRecommendedEncoding(encoding& enc) const { + // Special treatment for some charsets const string cset = utility::stringUtils::toLower(getName()); - for (unsigned int i = 0 ; i < (sizeof(g_charsetEncodingMap) / sizeof(g_charsetEncodingMap[0])) - 1 ; ++i) - { - if (cset.find(g_charsetEncodingMap[i].charset) != string::npos) - { + for (unsigned int i = 0 ; + i < (sizeof(g_charsetEncodingMap) / sizeof(g_charsetEncodingMap[0])) - 1 ; + ++i) { + + if (cset.find(g_charsetEncodingMap[i].charset) != string::npos) { enc = g_charsetEncodingMap[i].encoding; return true; } diff --git a/src/vmime/charset.hpp b/src/vmime/charset.hpp index 2b8d6109..61f9bd69 100644 --- a/src/vmime/charset.hpp +++ b/src/vmime/charset.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,8 +32,7 @@ #include "vmime/component.hpp" -namespace vmime -{ +namespace vmime { class encoding; // forward reference @@ -41,9 +40,8 @@ class encoding; // forward reference /** Charset description (basic type). */ +class VMIME_EXPORT charset : public component { -class VMIME_EXPORT charset : public component -{ public: charset(); @@ -102,9 +100,13 @@ public: * @throws exceptions::charset_conv_error if an unexpected error occurred * during the conversion */ - static void convert(const string& in, string& out, - const charset& source, const charset& dest, - const charsetConverterOptions& opts = charsetConverterOptions()); + static void convert( + const string& in, + string& out, + const charset& source, + const charset& dest, + const charsetConverterOptions& opts = charsetConverterOptions() + ); /** Convert the contents of an input stream in a specified charset * to another charset and write the result to an output stream. @@ -121,9 +123,13 @@ public: * @throws exceptions::charset_conv_error if an unexpected error occurred * during the conversion */ - static void convert(utility::inputStream& in, utility::outputStream& out, - const charset& source, const charset& dest, - const charsetConverterOptions& opts = charsetConverterOptions()); + static void convert( + utility::inputStream& in, + utility::outputStream& out, + const charset& source, + const charset& dest, + const charsetConverterOptions& opts = charsetConverterOptions() + ); /** Checks whether the specified text is valid in this charset. * @@ -147,18 +153,20 @@ private: protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/charsetConverter.cpp b/src/vmime/charsetConverter.cpp index 525a71ec..96bc3b8f 100644 --- a/src/vmime/charsetConverter.cpp +++ b/src/vmime/charsetConverter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -26,25 +26,26 @@ #include "vmime/charsetConverter_idna.hpp" -namespace vmime -{ +namespace vmime { // static -shared_ptr charsetConverter::create - (const charset& source, const charset& dest, - const charsetConverterOptions& opts) -{ - if (source == "idna" || dest == "idna") +shared_ptr charsetConverter::create( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts +) { + + if (source == "idna" || dest == "idna") { return make_shared (source, dest, opts); - else + } else { return createGenericConverter(source, dest, opts); + } } charsetConverter::status::status() - : inputBytesRead(0), outputBytesWritten(0) -{ + : inputBytesRead(0), outputBytesWritten(0) { } diff --git a/src/vmime/charsetConverter.hpp b/src/vmime/charsetConverter.hpp index 182cc879..2cde4b56 100644 --- a/src/vmime/charsetConverter.hpp +++ b/src/vmime/charsetConverter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,12 +33,10 @@ #include "vmime/utility/filteredStream.hpp" -namespace vmime -{ +namespace vmime { -namespace utility -{ +namespace utility { /** A filtered output stream which applies a charset conversion @@ -52,9 +50,8 @@ namespace utility * 'silentlyReplaceInvalidSequences' flag is set to false in * the charsetConverterOptions. */ +class VMIME_EXPORT charsetFilteredOutputStream : public filteredOutputStream { -class VMIME_EXPORT charsetFilteredOutputStream : public filteredOutputStream -{ }; @@ -63,15 +60,14 @@ class VMIME_EXPORT charsetFilteredOutputStream : public filteredOutputStream /** Convert between charsets. */ +class VMIME_EXPORT charsetConverter : public object { -class VMIME_EXPORT charsetConverter : public object -{ public: /** Holds information about a conversion. */ - struct status - { + struct status { + status(); @@ -91,9 +87,11 @@ public: * @param dest output charset * @param opts conversion options */ - static shared_ptr create - (const charset& source, const charset& dest, - const charsetConverterOptions& opts = charsetConverterOptions()); + static shared_ptr create( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts = charsetConverterOptions() + ); /** Convert a string buffer from one charset to another * charset (in-memory conversion) @@ -128,7 +126,11 @@ public: * @throws exceptions::charset_conv_error if an unexpected error occurred * during the conversion */ - virtual void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL) = 0; + virtual void convert( + utility::inputStream& in, + utility::outputStream& out, + status* st = NULL + ) = 0; /** Returns a filtered output stream which applies a charset * conversion to input bytes. Please note that it may not be @@ -138,15 +140,19 @@ public: * @param opts conversion options * @return a filtered output stream, or NULL if not supported */ - virtual shared_ptr getFilteredOutputStream - (utility::outputStream& os, - const charsetConverterOptions& opts = charsetConverterOptions()) = 0; + virtual shared_ptr + getFilteredOutputStream( + utility::outputStream& os, + const charsetConverterOptions& opts = charsetConverterOptions() + ) = 0; private: - static shared_ptr createGenericConverter - (const charset& source, const charset& dest, - const charsetConverterOptions& opts); + static shared_ptr createGenericConverter( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts + ); }; diff --git a/src/vmime/charsetConverterOptions.cpp b/src/vmime/charsetConverterOptions.cpp index 4b0814af..a18a928d 100644 --- a/src/vmime/charsetConverterOptions.cpp +++ b/src/vmime/charsetConverterOptions.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -24,14 +24,13 @@ #include "vmime/charsetConverterOptions.hpp" -namespace vmime -{ +namespace vmime { charsetConverterOptions::charsetConverterOptions() : silentlyReplaceInvalidSequences(true), - invalidSequence("?") -{ + invalidSequence("?") { + } diff --git a/src/vmime/charsetConverterOptions.hpp b/src/vmime/charsetConverterOptions.hpp index e07d30b2..567e0048 100644 --- a/src/vmime/charsetConverterOptions.hpp +++ b/src/vmime/charsetConverterOptions.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,15 +28,13 @@ #include "vmime/base.hpp" -namespace vmime -{ +namespace vmime { /** Options for charset conversion. */ +class VMIME_EXPORT charsetConverterOptions : public object { -class VMIME_EXPORT charsetConverterOptions : public object -{ public: charsetConverterOptions(); diff --git a/src/vmime/charsetConverter_iconv.cpp b/src/vmime/charsetConverter_iconv.cpp index eebc229b..5c4cc171 100644 --- a/src/vmime/charsetConverter_iconv.cpp +++ b/src/vmime/charsetConverter_iconv.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,8 +34,8 @@ #include "vmime/utility/outputStreamStringAdapter.hpp" -extern "C" -{ +extern "C" { + #ifndef VMIME_BUILDING_DOC #include @@ -45,8 +45,8 @@ extern "C" // second parameter may or may not be 'const'). This relies on the compiler // for choosing the right type. - class ICONV_IN_TYPE - { + class ICONV_IN_TYPE { + public: ICONV_IN_TYPE(const char** ptr) : m_ptr(ptr) { } @@ -62,8 +62,8 @@ extern "C" const char** m_ptr; }; - class ICONV_OUT_TYPE - { + class ICONV_OUT_TYPE { + public: ICONV_OUT_TYPE(char** ptr) : m_ptr(ptr) { } @@ -85,9 +85,12 @@ extern "C" // Output replacement char when an invalid sequence is encountered template -void outputInvalidChar(OUTPUT_CLASS& out, ICONV_DESC cd, - const vmime::charsetConverterOptions& opts = vmime::charsetConverterOptions()) -{ +void outputInvalidChar( + OUTPUT_CLASS& out, + ICONV_DESC cd, + const vmime::charsetConverterOptions& opts = vmime::charsetConverterOptions() +) { + const char* invalidCharIn = opts.invalidSequence.c_str(); vmime::size_t invalidCharInLen = opts.invalidSequence.length(); @@ -96,36 +99,43 @@ void outputInvalidChar(OUTPUT_CLASS& out, ICONV_DESC cd, vmime::size_t invalidCharOutLen = 16; if (iconv(cd, ICONV_IN_TYPE(&invalidCharIn), &invalidCharInLen, - ICONV_OUT_TYPE(&invalidCharOutPtr), &invalidCharOutLen) != static_cast (-1)) - { + ICONV_OUT_TYPE(&invalidCharOutPtr), &invalidCharOutLen) != static_cast (-1)) { + out.write(invalidCharOutBuffer, 16 - invalidCharOutLen); } } -namespace vmime -{ +namespace vmime { // static -shared_ptr charsetConverter::createGenericConverter - (const charset& source, const charset& dest, - const charsetConverterOptions& opts) -{ +shared_ptr charsetConverter::createGenericConverter( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts +) { + return make_shared (source, dest, opts); } -charsetConverter_iconv::charsetConverter_iconv - (const charset& source, const charset& dest, const charsetConverterOptions& opts) - : m_desc(NULL), m_source(source), m_dest(dest), m_options(opts) -{ +charsetConverter_iconv::charsetConverter_iconv( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts +) + : m_desc(NULL), + m_source(source), + m_dest(dest), + m_options(opts) { + // Get an iconv descriptor const iconv_t cd = iconv_open(dest.getName().c_str(), source.getName().c_str()); - if (cd != reinterpret_cast (-1)) - { + if (cd != reinterpret_cast (-1)) { + iconv_t* p = new iconv_t; *p= cd; @@ -134,10 +144,10 @@ charsetConverter_iconv::charsetConverter_iconv } -charsetConverter_iconv::~charsetConverter_iconv() -{ - if (m_desc != NULL) - { +charsetConverter_iconv::~charsetConverter_iconv() { + + if (m_desc) { + // Close iconv handle iconv_close(*static_cast (m_desc)); @@ -147,14 +157,19 @@ charsetConverter_iconv::~charsetConverter_iconv() } -void charsetConverter_iconv::convert - (utility::inputStream& in, utility::outputStream& out, status* st) -{ - if (st) - new (st) status(); +void charsetConverter_iconv::convert( + utility::inputStream& in, + utility::outputStream& out, + status* st +) { - if (m_desc == NULL) + if (st) { + new (st) status(); + } + + if (!m_desc) { throw exceptions::charset_conv_error("Cannot initialize converter."); + } const iconv_t cd = *static_cast (m_desc); @@ -165,8 +180,8 @@ void charsetConverter_iconv::convert bool prevIsInvalid = false; bool breakAfterNext = false; - while (true) - { + while (true) { + // Fullfill the buffer size_t inLength = static_cast (in.read(inBuffer + inPos, sizeof(inBuffer) - inPos) + inPos); size_t outLength = sizeof(outBuffer); @@ -177,23 +192,23 @@ void charsetConverter_iconv::convert // Convert input bytes if (iconv(cd, ICONV_IN_TYPE(&inPtr), ptrLength, - ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast (-1)) - { - if (st && inPtr) - { + ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast (-1)) { + + if (st && inPtr) { st->inputBytesRead += (inPtr - inBuffer); st->outputBytesWritten += (outPtr - outBuffer); } // Illegal input sequence or input sequence has no equivalent // sequence in the destination charset. - if (prevIsInvalid) - { + if (prevIsInvalid) { + // Write successfully converted bytes out.write(outBuffer, sizeof(outBuffer) - outLength); - if (!m_options.silentlyReplaceInvalidSequences) + if (!m_options.silentlyReplaceInvalidSequences) { throw exceptions::illegal_byte_sequence_for_charset(); + } // Output a special character to indicate we don't known how to // convert the sequence at this position @@ -202,9 +217,9 @@ void charsetConverter_iconv::convert // Skip a byte and leave unconverted bytes in the input buffer std::copy(const_cast (inPtr + 1), inBuffer + sizeof(inBuffer), inBuffer); inPos = inLength - 1; - } - else - { + + } else { + // Write successfully converted bytes out.write(outBuffer, sizeof(outBuffer) - outLength); @@ -212,17 +227,17 @@ void charsetConverter_iconv::convert std::copy(const_cast (inPtr), inBuffer + sizeof(inBuffer), inBuffer); inPos = inLength; - if (errno != E2BIG) + if (errno != E2BIG) { prevIsInvalid = true; + } } - } - else - { + + } else { + // Write successfully converted bytes out.write(outBuffer, sizeof(outBuffer) - outLength); - if (st && inPtr) - { + if (st && inPtr) { st->inputBytesRead += (inPtr - inBuffer); st->outputBytesWritten += (outPtr - outBuffer); } @@ -231,20 +246,23 @@ void charsetConverter_iconv::convert prevIsInvalid = false; } - if (breakAfterNext) + if (breakAfterNext) { break; + } // Check for end of data, loop again to flush stateful data from iconv - if (in.eof() && inPos == 0) + if (in.eof() && inPos == 0) { breakAfterNext = true; + } } } -void charsetConverter_iconv::convert(const string& in, string& out, status* st) -{ - if (st) +void charsetConverter_iconv::convert(const string& in, string& out, status* st) { + + if (st) { new (st) status(); + } out.clear(); @@ -258,9 +276,11 @@ void charsetConverter_iconv::convert(const string& in, string& out, status* st) shared_ptr - charsetConverter_iconv::getFilteredOutputStream - (utility::outputStream& os, const charsetConverterOptions& opts) -{ + charsetConverter_iconv::getFilteredOutputStream( + utility::outputStream& os, + const charsetConverterOptions& opts + ) { + return make_shared (m_source, m_dest, &os, opts); } @@ -271,17 +291,23 @@ shared_ptr namespace utility { -charsetFilteredOutputStream_iconv::charsetFilteredOutputStream_iconv - (const charset& source, const charset& dest, outputStream* os, - const charsetConverterOptions& opts) - : m_desc(NULL), m_sourceCharset(source), m_destCharset(dest), - m_stream(*os), m_unconvCount(0), m_options(opts) -{ +charsetFilteredOutputStream_iconv::charsetFilteredOutputStream_iconv( + const charset& source, + const charset& dest, outputStream* os, + const charsetConverterOptions& opts +) + : m_desc(NULL), + m_sourceCharset(source), + m_destCharset(dest), + m_stream(*os), + m_unconvCount(0), + m_options(opts) { + // Get an iconv descriptor const iconv_t cd = iconv_open(dest.getName().c_str(), source.getName().c_str()); - if (cd != reinterpret_cast (-1)) - { + if (cd != reinterpret_cast (-1)) { + iconv_t* p = new iconv_t; *p= cd; @@ -290,10 +316,10 @@ charsetFilteredOutputStream_iconv::charsetFilteredOutputStream_iconv } -charsetFilteredOutputStream_iconv::~charsetFilteredOutputStream_iconv() -{ - if (m_desc != NULL) - { +charsetFilteredOutputStream_iconv::~charsetFilteredOutputStream_iconv() { + + if (m_desc) { + // Close iconv handle iconv_close(*static_cast (m_desc)); @@ -303,17 +329,20 @@ charsetFilteredOutputStream_iconv::~charsetFilteredOutputStream_iconv() } -outputStream& charsetFilteredOutputStream_iconv::getNextOutputStream() -{ +outputStream& charsetFilteredOutputStream_iconv::getNextOutputStream() { + return m_stream; } -void charsetFilteredOutputStream_iconv::writeImpl - (const byte_t* const data, const size_t count) -{ - if (m_desc == NULL) +void charsetFilteredOutputStream_iconv::writeImpl( + const byte_t* const data, + const size_t count +) { + + if (!m_desc) { throw exceptions::charset_conv_error("Cannot initialize converter."); + } const iconv_t cd = *static_cast (m_desc); @@ -322,23 +351,26 @@ void charsetFilteredOutputStream_iconv::writeImpl // If there is some unconverted bytes left, add more data from this // chunk to see if it can now be converted. - while (m_unconvCount != 0 || curDataLen != 0) - { - if (m_unconvCount != 0) - { + while (m_unconvCount != 0 || curDataLen != 0) { + + if (m_unconvCount != 0) { + // Check if an incomplete input sequence is larger than the // input buffer size: should not happen except if something // in the input sequence is invalid. If so, output a special // character and skip one byte in the invalid sequence. - if (m_unconvCount >= sizeof(m_unconvBuffer)) - { - if (!m_options.silentlyReplaceInvalidSequences) + if (m_unconvCount >= sizeof(m_unconvBuffer)) { + + if (!m_options.silentlyReplaceInvalidSequences) { throw exceptions::illegal_byte_sequence_for_charset(); + } outputInvalidChar(m_stream, cd); - std::copy(m_unconvBuffer + 1, - m_unconvBuffer + m_unconvCount, m_unconvBuffer); + std::copy( + m_unconvBuffer + 1, + m_unconvBuffer + m_unconvCount, m_unconvBuffer + ); m_unconvCount--; } @@ -365,16 +397,18 @@ void charsetFilteredOutputStream_iconv::writeImpl const size_t inLength0 = inLength; if (iconv(cd, ICONV_IN_TYPE(&inPtr), &inLength, - ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast (-1)) - { + ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast (-1)) { + const size_t inputConverted = inLength0 - inLength; // Write successfully converted bytes m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength); // Shift unconverted bytes - std::copy(m_unconvBuffer + inputConverted, - m_unconvBuffer + m_unconvCount, m_unconvBuffer); + std::copy( + m_unconvBuffer + inputConverted, + m_unconvBuffer + m_unconvCount, m_unconvBuffer + ); m_unconvCount -= inputConverted; @@ -388,8 +422,9 @@ void charsetFilteredOutputStream_iconv::writeImpl m_unconvCount = 0; } - if (curDataLen == 0) + if (curDataLen == 0) { return; // no more data + } // Now, convert the current data buffer const byte_t* inPtr = curData; @@ -400,8 +435,8 @@ void charsetFilteredOutputStream_iconv::writeImpl const size_t inLength0 = inLength; if (iconv(cd, ICONV_IN_TYPE(&inPtr), &inLength, - ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast (-1)) - { + ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast (-1)) { + // Write successfully converted bytes m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength); @@ -412,17 +447,17 @@ void charsetFilteredOutputStream_iconv::writeImpl // Put one byte byte into the unconverted buffer so // that the next iteration fill it - if (curDataLen != 0) - { + if (curDataLen != 0) { + m_unconvCount = 1; m_unconvBuffer[0] = *curData; curData++; curDataLen--; } - } - else - { + + } else { + // Write successfully converted bytes m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength); @@ -433,18 +468,19 @@ void charsetFilteredOutputStream_iconv::writeImpl } -void charsetFilteredOutputStream_iconv::flush() -{ - if (m_desc == NULL) +void charsetFilteredOutputStream_iconv::flush() { + + if (!m_desc) { throw exceptions::charset_conv_error("Cannot initialize converter."); + } const iconv_t cd = *static_cast (m_desc); size_t offset = 0; // Process unconverted bytes - while (m_unconvCount != 0) - { + while (m_unconvCount != 0) { + // Try a conversion const byte_t* inPtr = m_unconvBuffer + offset; size_t inLength = m_unconvCount; @@ -453,32 +489,34 @@ void charsetFilteredOutputStream_iconv::flush() const size_t inLength0 = inLength; - if (iconv(cd, ICONV_IN_TYPE(&inPtr), &inLength, ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast (-1)) - { + if (iconv(cd, ICONV_IN_TYPE(&inPtr), &inLength, + ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast (-1)) { + const size_t inputConverted = inLength0 - inLength; // Skip a "blocking" character - if (inputConverted == 0) - { - if (!m_options.silentlyReplaceInvalidSequences) + if (inputConverted == 0) { + + if (!m_options.silentlyReplaceInvalidSequences) { throw exceptions::illegal_byte_sequence_for_charset(); + } outputInvalidChar(m_stream, cd); offset++; m_unconvCount--; - } - else - { + + } else { + // Write successfully converted bytes m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength); offset += inputConverted; m_unconvCount -= inputConverted; } - } - else - { + + } else { + // Write successfully converted bytes m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength); diff --git a/src/vmime/charsetConverter_iconv.hpp b/src/vmime/charsetConverter_iconv.hpp index e9a0f28a..c64813cd 100644 --- a/src/vmime/charsetConverter_iconv.hpp +++ b/src/vmime/charsetConverter_iconv.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,15 +34,13 @@ #include "vmime/charsetConverter.hpp" -namespace vmime -{ +namespace vmime { /** A generic charset converter which uses iconv library. */ +class charsetConverter_iconv : public charsetConverter { -class charsetConverter_iconv : public charsetConverter -{ public: /** Construct and initialize an iconv charset converter. @@ -51,17 +49,21 @@ public: * @param dest output charset * @param opts conversion options */ - charsetConverter_iconv(const charset& source, const charset& dest, - const charsetConverterOptions& opts = charsetConverterOptions()); + charsetConverter_iconv( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts = charsetConverterOptions() + ); ~charsetConverter_iconv(); void convert(const string& in, string& out, status* st = NULL); void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL); - shared_ptr getFilteredOutputStream - (utility::outputStream& os, - const charsetConverterOptions& opts = charsetConverterOptions()); + shared_ptr getFilteredOutputStream( + utility::outputStream& os, + const charsetConverterOptions& opts = charsetConverterOptions() + ); private: @@ -77,8 +79,8 @@ private: namespace utility { -class charsetFilteredOutputStream_iconv : public charsetFilteredOutputStream -{ +class charsetFilteredOutputStream_iconv : public charsetFilteredOutputStream { + public: /** Construct a new filter for the specified output stream. @@ -88,9 +90,11 @@ public: * @param os stream into which write filtered data * @param opts conversion options */ - charsetFilteredOutputStream_iconv - (const charset& source, const charset& dest, outputStream* os, - const charsetConverterOptions& opts = charsetConverterOptions()); + charsetFilteredOutputStream_iconv( + const charset& source, + const charset& dest, outputStream* os, + const charsetConverterOptions& opts = charsetConverterOptions() + ); ~charsetFilteredOutputStream_iconv(); diff --git a/src/vmime/charsetConverter_icu.cpp b/src/vmime/charsetConverter_icu.cpp index a41a0842..a7dd474c 100644 --- a/src/vmime/charsetConverter_icu.cpp +++ b/src/vmime/charsetConverter_icu.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,8 +34,8 @@ #include "vmime/utility/outputStreamStringAdapter.hpp" -extern "C" -{ +extern "C" { + #ifndef VMIME_BUILDING_DOC #include @@ -48,59 +48,75 @@ extern "C" #include -namespace vmime -{ +namespace vmime { // static -shared_ptr charsetConverter::createGenericConverter - (const charset& source, const charset& dest, - const charsetConverterOptions& opts) -{ +shared_ptr charsetConverter::createGenericConverter( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts +) { + return make_shared (source, dest, opts); } -charsetConverter_icu::charsetConverter_icu - (const charset& source, const charset& dest, const charsetConverterOptions& opts) - : m_from(NULL), m_to(NULL), m_source(source), m_dest(dest), m_options(opts) -{ +charsetConverter_icu::charsetConverter_icu( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts +) + : m_from(NULL), + m_to(NULL), + m_source(source), + m_dest(dest), + m_options(opts) { + UErrorCode err = U_ZERO_ERROR; m_from = ucnv_open(source.getName().c_str(), &err); - if (!U_SUCCESS(err)) - { - throw exceptions::charset_conv_error - ("Cannot initialize ICU converter for source charset '" + source.getName() + "' (error code: " + u_errorName(err) + "."); + if (!U_SUCCESS(err)) { + + throw exceptions::charset_conv_error( + "Cannot initialize ICU converter for source charset '" + source.getName() + + "' (error code: " + u_errorName(err) + "." + ); } m_to = ucnv_open(dest.getName().c_str(), &err); - if (!U_SUCCESS(err)) - { - throw exceptions::charset_conv_error - ("Cannot initialize ICU converter for destination charset '" + dest.getName() + "' (error code: " + u_errorName(err) + "."); + if (!U_SUCCESS(err)) { + + throw exceptions::charset_conv_error( + "Cannot initialize ICU converter for destination charset '" + dest.getName() + + "' (error code: " + u_errorName(err) + "." + ); } } -charsetConverter_icu::~charsetConverter_icu() -{ +charsetConverter_icu::~charsetConverter_icu() { + if (m_from) ucnv_close(m_from); if (m_to) ucnv_close(m_to); } -void charsetConverter_icu::convert - (utility::inputStream& in, utility::outputStream& out, status* st) -{ +void charsetConverter_icu::convert( + utility::inputStream& in, + utility::outputStream& out, + status* st +) { + UErrorCode err = U_ZERO_ERROR; ucnv_reset(m_from); ucnv_reset(m_to); - if (st) + if (st) { new (st) status(); + } // From buffers byte_t cpInBuffer[16]; // stream data put here @@ -113,34 +129,39 @@ void charsetConverter_icu::convert std::vector cpOutBuffer(cpOutBufferSz); // Tell ICU what to do when encountering an illegal byte sequence - if (m_options.silentlyReplaceInvalidSequences) - { + if (m_options.silentlyReplaceInvalidSequences) { + // Set replacement chars for when converting from Unicode to codepage icu::UnicodeString substString(m_options.invalidSequence.c_str()); ucnv_setSubstString(m_to, substString.getTerminatedBuffer(), -1, &err); - if (U_FAILURE(err)) + if (U_FAILURE(err)) { throw exceptions::charset_conv_error("[ICU] Error when setting substitution string."); - } - else - { + } + + } else { + // Tell ICU top stop (and return an error) on illegal byte sequences - ucnv_setToUCallBack - (m_from, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err); + ucnv_setToUCallBack( + m_from, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err + ); - if (U_FAILURE(err)) + if (U_FAILURE(err)) { throw exceptions::charset_conv_error("[ICU] Error when setting ToU callback."); + } - ucnv_setFromUCallBack - (m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err); + ucnv_setFromUCallBack( + m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err + ); - if (U_FAILURE(err)) + if (U_FAILURE(err)) { throw exceptions::charset_conv_error("[ICU] Error when setting FromU callback."); + } } // Input data available - while (!in.eof()) - { + while (!in.eof()) { + // Read input data into buffer size_t inLength = in.read(cpInBuffer, sizeof(cpInBuffer)); @@ -153,30 +174,36 @@ void charsetConverter_icu::convert UErrorCode toErr; // Loop until all source has been processed - do - { + do { + // Set up target pointers UChar* target = &uOutBuffer[0]; UChar* targetLimit = &target[0] + outSize; toErr = U_ZERO_ERROR; - ucnv_toUnicode(m_from, &target, targetLimit, - &source, sourceLimit, NULL, flush, &toErr); - if (st) + ucnv_toUnicode( + m_from, &target, targetLimit, + &source, sourceLimit, NULL, flush, &toErr + ); + + if (st) { st->inputBytesRead += (source - reinterpret_cast (&cpInBuffer[0])); + } + + if (toErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(toErr)) { - if (toErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(toErr)) - { if (toErr == U_INVALID_CHAR_FOUND || toErr == U_TRUNCATED_CHAR_FOUND || - toErr == U_ILLEGAL_CHAR_FOUND) - { + toErr == U_ILLEGAL_CHAR_FOUND) { + // Error will be thrown later (*) - } - else - { - throw exceptions::charset_conv_error("[ICU] Error converting to Unicode from " + m_source.getName()); + + } else { + + throw exceptions::charset_conv_error( + "[ICU] Error converting to Unicode from " + m_source.getName() + ); } } @@ -187,19 +214,21 @@ void charsetConverter_icu::convert UErrorCode fromErr; // Loop until converted chars are fully written - do - { + do { + char* cpTarget = &cpOutBuffer[0]; const char* cpTargetLimit = &cpOutBuffer[0] + cpOutBufferSz; fromErr = U_ZERO_ERROR; // Write converted bytes (Unicode) to destination codepage - ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit, - &uSource, uSourceLimit, NULL, flush, &fromErr); + ucnv_fromUnicode( + m_to, &cpTarget, cpTargetLimit, + &uSource, uSourceLimit, NULL, flush, &fromErr + ); + + if (st) { - if (st) - { // Decrement input bytes count by the number of input bytes in error char errBytes[16]; int8_t errBytesLen = sizeof(errBytes); @@ -214,22 +243,24 @@ void charsetConverter_icu::convert // (*) If an error occurred while converting from input charset, throw it now if (toErr == U_INVALID_CHAR_FOUND || toErr == U_TRUNCATED_CHAR_FOUND || - toErr == U_ILLEGAL_CHAR_FOUND) - { + toErr == U_ILLEGAL_CHAR_FOUND) { + throw exceptions::illegal_byte_sequence_for_charset(); } - if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) - { + if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) { + if (fromErr == U_INVALID_CHAR_FOUND || fromErr == U_TRUNCATED_CHAR_FOUND || - fromErr == U_ILLEGAL_CHAR_FOUND) - { + fromErr == U_ILLEGAL_CHAR_FOUND) { + throw exceptions::illegal_byte_sequence_for_charset(); - } - else - { - throw exceptions::charset_conv_error("[ICU] Error converting from Unicode to " + m_dest.getName()); + + } else { + + throw exceptions::charset_conv_error( + "[ICU] Error converting from Unicode to " + m_dest.getName() + ); } } @@ -243,10 +274,11 @@ void charsetConverter_icu::convert } -void charsetConverter_icu::convert(const string& in, string& out, status* st) -{ - if (st) +void charsetConverter_icu::convert(const string& in, string& out, status* st) { + + if (st) { new (st) status(); + } out.clear(); @@ -260,9 +292,11 @@ void charsetConverter_icu::convert(const string& in, string& out, status* st) shared_ptr - charsetConverter_icu::getFilteredOutputStream - (utility::outputStream& os, const charsetConverterOptions& opts) -{ + charsetConverter_icu::getFilteredOutputStream( + utility::outputStream& os, + const charsetConverterOptions& opts + ) { + return make_shared (m_source, m_dest, &os, opts); } @@ -273,75 +307,94 @@ shared_ptr namespace utility { -charsetFilteredOutputStream_icu::charsetFilteredOutputStream_icu - (const charset& source, const charset& dest, outputStream* os, - const charsetConverterOptions& opts) - : m_from(NULL), m_to(NULL), m_sourceCharset(source), - m_destCharset(dest), m_stream(*os), m_options(opts) -{ +charsetFilteredOutputStream_icu::charsetFilteredOutputStream_icu( + const charset& source, + const charset& dest, + outputStream* os, + const charsetConverterOptions& opts +) + : m_from(NULL), + m_to(NULL), + m_sourceCharset(source), + m_destCharset(dest), + m_stream(*os), + m_options(opts) { + UErrorCode err = U_ZERO_ERROR; m_from = ucnv_open(source.getName().c_str(), &err); - if (!U_SUCCESS(err)) - { - throw exceptions::charset_conv_error - ("Cannot initialize ICU converter for source charset '" + source.getName() + "' (error code: " + u_errorName(err) + "."); + if (!U_SUCCESS(err)) { + + throw exceptions::charset_conv_error( + "Cannot initialize ICU converter for source charset '" + source.getName() + + "' (error code: " + u_errorName(err) + "." + ); } m_to = ucnv_open(dest.getName().c_str(), &err); - if (!U_SUCCESS(err)) - { - throw exceptions::charset_conv_error - ("Cannot initialize ICU converter for destination charset '" + dest.getName() + "' (error code: " + u_errorName(err) + "."); + if (!U_SUCCESS(err)) { + + throw exceptions::charset_conv_error( + "Cannot initialize ICU converter for destination charset '" + dest.getName() + + "' (error code: " + u_errorName(err) + "." + ); } // Tell ICU what to do when encountering an illegal byte sequence - if (m_options.silentlyReplaceInvalidSequences) - { + if (m_options.silentlyReplaceInvalidSequences) { + // Set replacement chars for when converting from Unicode to codepage icu::UnicodeString substString(m_options.invalidSequence.c_str()); ucnv_setSubstString(m_to, substString.getTerminatedBuffer(), -1, &err); - if (U_FAILURE(err)) + if (U_FAILURE(err)) { throw exceptions::charset_conv_error("[ICU] Error when setting substitution string."); - } - else - { + } + + } else { + // Tell ICU top stop (and return an error) on illegal byte sequences - ucnv_setToUCallBack - (m_to, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err); + ucnv_setToUCallBack( + m_to, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err + ); - if (U_FAILURE(err)) + if (U_FAILURE(err)) { throw exceptions::charset_conv_error("[ICU] Error when setting ToU callback."); + } - ucnv_setFromUCallBack - (m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err); + ucnv_setFromUCallBack( + m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err + ); - if (U_FAILURE(err)) + if (U_FAILURE(err)) { throw exceptions::charset_conv_error("[ICU] Error when setting FromU callback."); + } } } -charsetFilteredOutputStream_icu::~charsetFilteredOutputStream_icu() -{ +charsetFilteredOutputStream_icu::~charsetFilteredOutputStream_icu() { + if (m_from) ucnv_close(m_from); if (m_to) ucnv_close(m_to); } -outputStream& charsetFilteredOutputStream_icu::getNextOutputStream() -{ +outputStream& charsetFilteredOutputStream_icu::getNextOutputStream() { + return m_stream; } -void charsetFilteredOutputStream_icu::writeImpl - (const byte_t* const data, const size_t count) -{ - if (m_from == NULL || m_to == NULL) +void charsetFilteredOutputStream_icu::writeImpl( + const byte_t* const data, + const size_t count +) { + + if (!m_from || !m_to) { throw exceptions::charset_conv_error("Cannot initialize converters."); + } // Allocate buffer for Unicode chars const size_t uniSize = ucnv_getMinCharSize(m_from) * count * sizeof(UChar); @@ -353,29 +406,32 @@ void charsetFilteredOutputStream_icu::writeImpl const char* uniSource = reinterpret_cast (data); const char* uniSourceLimit = uniSource + count; - do - { + do { + // Convert from source charset to Unicode UChar* uniTarget = &uniBuffer[0]; UChar* uniTargetLimit = &uniBuffer[0] + uniSize; toErr = U_ZERO_ERROR; - ucnv_toUnicode(m_from, &uniTarget, uniTargetLimit, - &uniSource, uniSourceLimit, NULL, /* flush */ FALSE, &toErr); + ucnv_toUnicode( + m_from, &uniTarget, uniTargetLimit, + &uniSource, uniSourceLimit, NULL, /* flush */ FALSE, &toErr + ); + + if (U_FAILURE(toErr) && toErr != U_BUFFER_OVERFLOW_ERROR) { - if (U_FAILURE(toErr) && toErr != U_BUFFER_OVERFLOW_ERROR) - { if (toErr == U_INVALID_CHAR_FOUND || toErr == U_TRUNCATED_CHAR_FOUND || - toErr == U_ILLEGAL_CHAR_FOUND) - { + toErr == U_ILLEGAL_CHAR_FOUND) { + throw exceptions::illegal_byte_sequence_for_charset(); - } - else - { - throw exceptions::charset_conv_error - ("[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'."); + + } else { + + throw exceptions::charset_conv_error( + "[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'." + ); } } @@ -391,28 +447,31 @@ void charsetFilteredOutputStream_icu::writeImpl const UChar* cpSource = &uniBuffer[0]; const UChar* cpSourceLimit = &uniBuffer[0] + uniLength; - do - { + do { + char* cpTarget = &cpBuffer[0]; char* cpTargetLimit = &cpBuffer[0] + cpSize; fromErr = U_ZERO_ERROR; - ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit, - &cpSource, cpSourceLimit, NULL, /* flush */ FALSE, &fromErr); + ucnv_fromUnicode( + m_to, &cpTarget, cpTargetLimit, + &cpSource, cpSourceLimit, NULL, /* flush */ FALSE, &fromErr + ); + + if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) { - if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) - { if (fromErr == U_INVALID_CHAR_FOUND || fromErr == U_TRUNCATED_CHAR_FOUND || - fromErr == U_ILLEGAL_CHAR_FOUND) - { + fromErr == U_ILLEGAL_CHAR_FOUND) { + throw exceptions::illegal_byte_sequence_for_charset(); - } - else - { - throw exceptions::charset_conv_error - ("[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'."); + + } else { + + throw exceptions::charset_conv_error( + "[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'." + ); } } @@ -427,10 +486,11 @@ void charsetFilteredOutputStream_icu::writeImpl } -void charsetFilteredOutputStream_icu::flush() -{ - if (m_from == NULL || m_to == NULL) +void charsetFilteredOutputStream_icu::flush() { + + if (!m_from || !m_to) { throw exceptions::charset_conv_error("Cannot initialize converters."); + } // Allocate buffer for Unicode chars const size_t uniSize = ucnv_getMinCharSize(m_from) * 1024 * sizeof(UChar); @@ -442,21 +502,24 @@ void charsetFilteredOutputStream_icu::flush() const char* uniSource = 0; const char* uniSourceLimit = 0; - do - { + do { + // Convert from source charset to Unicode UChar* uniTarget = &uniBuffer[0]; UChar* uniTargetLimit = &uniBuffer[0] + uniSize; toErr = U_ZERO_ERROR; - ucnv_toUnicode(m_from, &uniTarget, uniTargetLimit, - &uniSource, uniSourceLimit, NULL, /* flush */ TRUE, &toErr); + ucnv_toUnicode( + m_from, &uniTarget, uniTargetLimit, + &uniSource, uniSourceLimit, NULL, /* flush */ TRUE, &toErr + ); - if (U_FAILURE(toErr) && toErr != U_BUFFER_OVERFLOW_ERROR) - { - throw exceptions::charset_conv_error - ("[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'."); + if (U_FAILURE(toErr) && toErr != U_BUFFER_OVERFLOW_ERROR) { + + throw exceptions::charset_conv_error( + "[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'." + ); } const size_t uniLength = uniTarget - &uniBuffer[0]; @@ -471,20 +534,23 @@ void charsetFilteredOutputStream_icu::flush() const UChar* cpSource = &uniBuffer[0]; const UChar* cpSourceLimit = &uniBuffer[0] + uniLength; - do - { + do { + char* cpTarget = &cpBuffer[0]; char* cpTargetLimit = &cpBuffer[0] + cpSize; fromErr = U_ZERO_ERROR; - ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit, - &cpSource, cpSourceLimit, NULL, /* flush */ TRUE, &fromErr); + ucnv_fromUnicode( + m_to, &cpTarget, cpTargetLimit, + &cpSource, cpSourceLimit, NULL, /* flush */ TRUE, &fromErr + ); - if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) - { - throw exceptions::charset_conv_error - ("[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'."); + if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) { + + throw exceptions::charset_conv_error( + "[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'." + ); } const size_t cpLength = cpTarget - &cpBuffer[0]; diff --git a/src/vmime/charsetConverter_icu.hpp b/src/vmime/charsetConverter_icu.hpp index 9b03f643..cf5eb6bc 100644 --- a/src/vmime/charsetConverter_icu.hpp +++ b/src/vmime/charsetConverter_icu.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,15 +37,13 @@ struct UConverter; -namespace vmime -{ +namespace vmime { /** A generic charset converter which uses ICU library. */ +class charsetConverter_icu : public charsetConverter { -class charsetConverter_icu : public charsetConverter -{ public: /** Construct and initialize an ICU charset converter. @@ -54,17 +52,21 @@ public: * @param dest output charset * @param opts conversion options */ - charsetConverter_icu(const charset& source, const charset& dest, - const charsetConverterOptions& opts = charsetConverterOptions()); + charsetConverter_icu( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts = charsetConverterOptions() + ); ~charsetConverter_icu(); void convert(const string& in, string& out, status* st = NULL); void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL); - shared_ptr getFilteredOutputStream - (utility::outputStream& os, - const charsetConverterOptions& opts = charsetConverterOptions()); + shared_ptr getFilteredOutputStream( + utility::outputStream& os, + const charsetConverterOptions& opts = charsetConverterOptions() + ); private: @@ -81,8 +83,8 @@ private: namespace utility { -class charsetFilteredOutputStream_icu : public charsetFilteredOutputStream -{ +class charsetFilteredOutputStream_icu : public charsetFilteredOutputStream { + public: /** Construct a new filter for the specified output stream. @@ -92,9 +94,12 @@ public: * @param os stream into which write filtered data * @param opts conversion options */ - charsetFilteredOutputStream_icu - (const charset& source, const charset& dest, outputStream* os, - const charsetConverterOptions& opts = charsetConverterOptions()); + charsetFilteredOutputStream_icu( + const charset& source, + const charset& dest, + outputStream* os, + const charsetConverterOptions& opts = charsetConverterOptions() + ); ~charsetFilteredOutputStream_icu(); diff --git a/src/vmime/charsetConverter_idna.cpp b/src/vmime/charsetConverter_idna.cpp index b9e79842..eb8764f5 100644 --- a/src/vmime/charsetConverter_idna.cpp +++ b/src/vmime/charsetConverter_idna.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,8 +30,7 @@ #include "vmime/utility/outputStreamStringAdapter.hpp" -extern "C" -{ +extern "C" { #include "contrib/punycode/punycode.h" #include "contrib/punycode/punycode.c" @@ -41,26 +40,31 @@ extern "C" #include "contrib/utf8/utf8.h" -namespace vmime -{ +namespace vmime { -charsetConverter_idna::charsetConverter_idna - (const charset& source, const charset& dest, const charsetConverterOptions& opts) - : m_source(source), m_dest(dest), m_options(opts) -{ +charsetConverter_idna::charsetConverter_idna( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts +) + : m_source(source), + m_dest(dest), + m_options(opts) { + } -charsetConverter_idna::~charsetConverter_idna() -{ +charsetConverter_idna::~charsetConverter_idna() { + } -void charsetConverter_idna::convert(utility::inputStream& in, utility::outputStream& out, status* st) -{ - if (st) +void charsetConverter_idna::convert(utility::inputStream& in, utility::outputStream& out, status* st) { + + if (st) { new (st) status(); + } // IDNA should be used for short strings, so it does not matter if we // do not work directly on the stream @@ -75,19 +79,19 @@ void charsetConverter_idna::convert(utility::inputStream& in, utility::outputStr } -void charsetConverter_idna::convert(const string& in, string& out, status* st) -{ - if (st) +void charsetConverter_idna::convert(const string& in, string& out, status* st) { + + if (st) { new (st) status(); + } out.clear(); - if (m_dest == "idna") - { - if (utility::stringUtils::is7bit(in)) - { - if (st) - { + if (m_dest == "idna") { + + if (utility::stringUtils::is7bit(in)) { + + if (st) { st->inputBytesRead = in.length(); st->outputBytesWritten = in.length(); } @@ -106,41 +110,42 @@ void charsetConverter_idna::convert(const string& in, string& out, status* st) std::vector unichars; unichars.reserve(inUTF8.length()); - while (ch < end) - { + while (ch < end) { const utf8::uint32_t uc = utf8::unchecked::next(ch); unichars.push_back(uc); } - if (st) + if (st) { st->inputBytesRead = in.length(); + } punycode_uint inputLen = static_cast (unichars.size()); std::vector output(inUTF8.length() * 2); punycode_uint outputLen = static_cast (output.size()); - const punycode_status status = punycode_encode - (inputLen, &unichars[0], /* case_flags */ NULL, &outputLen, &output[0]); + const punycode_status status = punycode_encode( + inputLen, &unichars[0], /* case_flags */ NULL, &outputLen, &output[0] + ); + + if (status == punycode_success) { - if (status == punycode_success) - { out = string("xn--") + string(output.begin(), output.begin() + outputLen); - if (st) + if (st) { st->outputBytesWritten = out.length(); - } - else - { + } + + } else { + // TODO } - } - else if (m_source == "idna") - { - if (in.length() < 5 || in.substr(0, 4) != "xn--") - { - if (st) - { + + } else if (m_source == "idna") { + + if (in.length() < 5 || in.substr(0, 4) != "xn--") { + + if (st) { st->inputBytesRead = in.length(); st->outputBytesWritten = in.length(); } @@ -155,31 +160,34 @@ void charsetConverter_idna::convert(const string& in, string& out, status* st) std::vector output(in.length() - 4); punycode_uint outputLen = static_cast (output.size()); - const punycode_status status = punycode_decode - (inputLen, &in[4], &outputLen, &output[0], /* case_flags */ NULL); + const punycode_status status = punycode_decode( + inputLen, &in[4], &outputLen, &output[0], /* case_flags */ NULL + ); - if (st) + if (st) { st->inputBytesRead = in.length(); + } + + if (status == punycode_success) { - if (status == punycode_success) - { std::vector outUTF8Bytes(outputLen * 4); char* p = &outUTF8Bytes[0]; for (std::vector ::const_iterator it = output.begin() ; - it != output.begin() + outputLen ; ++it) - { + it != output.begin() + outputLen ; ++it) { + p = utf8::unchecked::append(*it, p); } string outUTF8(&outUTF8Bytes[0], p); charset::convert(outUTF8, out, vmime::charsets::UTF_8, m_dest); - if (st) + if (st) { st->outputBytesWritten = out.length(); - } - else - { + } + + } else { + // TODO } } @@ -187,9 +195,12 @@ void charsetConverter_idna::convert(const string& in, string& out, status* st) shared_ptr - charsetConverter_idna::getFilteredOutputStream - (utility::outputStream& /* os */, const charsetConverterOptions& /* opts */) -{ + charsetConverter_idna::getFilteredOutputStream( + utility::outputStream& /* os */, + const charsetConverterOptions& /* opts */ + ) { + + // Not supported return null; } diff --git a/src/vmime/charsetConverter_idna.hpp b/src/vmime/charsetConverter_idna.hpp index 06ffbcdd..aaf547d0 100644 --- a/src/vmime/charsetConverter_idna.hpp +++ b/src/vmime/charsetConverter_idna.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,15 +28,13 @@ #include "vmime/charsetConverter.hpp" -namespace vmime -{ +namespace vmime { /** A charset converter which can convert to and from Punycode (for IDNA). */ +class charsetConverter_idna : public charsetConverter { -class charsetConverter_idna : public charsetConverter -{ public: /** Construct and initialize an IDNA charset converter. @@ -45,17 +43,21 @@ public: * @param dest output charset * @param opts conversion options */ - charsetConverter_idna(const charset& source, const charset& dest, - const charsetConverterOptions& opts = charsetConverterOptions()); + charsetConverter_idna( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts = charsetConverterOptions() + ); ~charsetConverter_idna(); void convert(const string& in, string& out, status* st = NULL); void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL); - shared_ptr getFilteredOutputStream - (utility::outputStream& os, - const charsetConverterOptions& opts = charsetConverterOptions()); + shared_ptr getFilteredOutputStream( + utility::outputStream& os, + const charsetConverterOptions& opts = charsetConverterOptions() + ); private: diff --git a/src/vmime/charsetConverter_win.cpp b/src/vmime/charsetConverter_win.cpp index 2c65f5fd..eab18291 100644 --- a/src/vmime/charsetConverter_win.cpp +++ b/src/vmime/charsetConverter_win.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -49,37 +49,46 @@ #define CP_UNICODE 1200 -namespace vmime -{ +namespace vmime { // static -shared_ptr charsetConverter::createGenericConverter - (const charset& source, const charset& dest, - const charsetConverterOptions& opts) -{ +shared_ptr charsetConverter::createGenericConverter( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts +) { + return make_shared (source, dest, opts); } -charsetConverter_win::charsetConverter_win - (const charset& source, const charset& dest, const charsetConverterOptions& opts) - : m_source(source), m_dest(dest), m_options(opts) -{ +charsetConverter_win::charsetConverter_win( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts +) + : m_source(source), + m_dest(dest), + m_options(opts) { + } -void charsetConverter_win::convert - (utility::inputStream& in, utility::outputStream& out, status* st) -{ - if (st) +void charsetConverter_win::convert( + utility::inputStream& in, + utility::outputStream& out, + status* st +) { + + if (st) { new (st) status(); + } byte_t buffer[32768]; string inStr, outStr; - while (!in.eof()) - { + while (!in.eof()) { const size_t len = in.read(buffer, sizeof(buffer)); utility::stringUtils::appendBytesToString(inStr, buffer, len); } @@ -90,10 +99,11 @@ void charsetConverter_win::convert } -void charsetConverter_win::convert(const string& in, string& out, status* st) -{ - if (st) +void charsetConverter_win::convert(const string& in, string& out, status* st) { + + if (st) { new (st) status(); + } const int sourceCodePage = getCodePage(m_source.getName().c_str()); const int destCodePage = getCodePage(m_dest.getName().c_str()); @@ -103,69 +113,77 @@ void charsetConverter_win::convert(const string& in, string& out, status* st) const WCHAR* unicodePtr = NULL; size_t unicodeLen = 0; - if (sourceCodePage == CP_UNICODE) - { + if (sourceCodePage == CP_UNICODE) { + unicodePtr = reinterpret_cast (in.c_str()); unicodeLen = in.length() / 2; - } - else - { - const size_t bufferSize = MultiByteToWideChar - (sourceCodePage, 0, in.c_str(), static_cast (in.length()), - NULL, 0) * sizeof(WCHAR); // in wide characters + + } else { + + const size_t bufferSize = MultiByteToWideChar( + sourceCodePage, 0, in.c_str(), static_cast (in.length()), NULL, 0 + ) * sizeof(WCHAR); // in wide characters unicodeBuffer.resize(bufferSize); DWORD flags = 0; - if (!m_options.silentlyReplaceInvalidSequences) + if (!m_options.silentlyReplaceInvalidSequences) { flags |= MB_ERR_INVALID_CHARS; + } unicodePtr = reinterpret_cast (&unicodeBuffer[0]); - unicodeLen = MultiByteToWideChar - (sourceCodePage, 0, in.c_str(), static_cast (in.length()), - reinterpret_cast (&unicodeBuffer[0]), static_cast (bufferSize)); + unicodeLen = MultiByteToWideChar( + sourceCodePage, 0, in.c_str(), static_cast (in.length()), + reinterpret_cast (&unicodeBuffer[0]), static_cast (bufferSize) + ); + + if (unicodeLen == 0) { + + if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) { - if (unicodeLen == 0) - { - if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) - { throw exceptions::illegal_byte_sequence_for_charset(); - } - else - { - throw exceptions::charset_conv_error("MultiByteToWideChar() failed when converting to Unicode from " + m_source.getName()); + + } else { + + throw exceptions::charset_conv_error( + "MultiByteToWideChar() failed when converting to Unicode from " + m_source.getName() + ); } } } // Convert from Unicode to destination charset - if (destCodePage == CP_UNICODE) - { + if (destCodePage == CP_UNICODE) { + out.assign(reinterpret_cast (unicodePtr), unicodeLen * 2); - } - else - { - const size_t bufferSize = WideCharToMultiByte - (destCodePage, 0, unicodePtr, static_cast (unicodeLen), - NULL, 0, 0, NULL); // in multibyte characters + + } else { + + const size_t bufferSize = WideCharToMultiByte( + destCodePage, 0, unicodePtr, static_cast (unicodeLen), + NULL, 0, 0, NULL + ); // in multibyte characters std::vector buffer; buffer.resize(bufferSize); - const size_t len = WideCharToMultiByte - (destCodePage, 0, unicodePtr, static_cast (unicodeLen), - &buffer[0], static_cast (bufferSize), 0, NULL); + const size_t len = WideCharToMultiByte( + destCodePage, 0, unicodePtr, static_cast (unicodeLen), + &buffer[0], static_cast (bufferSize), 0, NULL + ); + + if (len == 0) { + + if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) { - if (len == 0) - { - if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) - { throw exceptions::illegal_byte_sequence_for_charset(); - } - else - { - throw exceptions::charset_conv_error("WideCharToMultiByte() failed when converting from Unicode to " + m_source.getName()); + + } else { + + throw exceptions::charset_conv_error( + "WideCharToMultiByte() failed when converting from Unicode to " + m_source.getName() + ); } } @@ -175,15 +193,16 @@ void charsetConverter_win::convert(const string& in, string& out, status* st) // static -int charsetConverter_win::getCodePage(const char* name) -{ - if (_stricmp(name, charsets::UTF_16) == 0) // wchar_t is UTF-16 on Windows +int charsetConverter_win::getCodePage(const char* name) { + + if (_stricmp(name, charsets::UTF_16) == 0) { // wchar_t is UTF-16 on Windows return CP_UNICODE; + } // "cp1252" --> return 1252 if ((name[0] == 'c' || name[0] == 'C') && - (name[1] == 'p' || name[1] == 'P')) - { + (name[1] == 'p' || name[1] == 'P')) { + return atoi(name + 2); } @@ -192,9 +211,11 @@ int charsetConverter_win::getCodePage(const char* name) shared_ptr - charsetConverter_win::getFilteredOutputStream - (utility::outputStream& /* os */, const charsetConverterOptions& /* opts */) -{ + charsetConverter_win::getFilteredOutputStream( + utility::outputStream& /* os */, + const charsetConverterOptions& /* opts */ + ) { + // TODO: implement me! return null; } diff --git a/src/vmime/charsetConverter_win.hpp b/src/vmime/charsetConverter_win.hpp index 7cf38104..d20970b9 100644 --- a/src/vmime/charsetConverter_win.hpp +++ b/src/vmime/charsetConverter_win.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,8 +34,7 @@ #include "vmime/charsetConverter.hpp" -namespace vmime -{ +namespace vmime { /** A generic charset converter which uses Windows MultiByteToWideChar @@ -49,9 +48,8 @@ namespace vmime * * Also, "status" is not supported by this converter for the same reason. */ +class charsetConverter_win : public charsetConverter { -class charsetConverter_win : public charsetConverter -{ public: /** Construct and initialize a Windows charset converter. @@ -60,14 +58,19 @@ public: * @param dest output charset * @param opts conversion options */ - charsetConverter_win(const charset& source, const charset& dest, - const charsetConverterOptions& opts = charsetConverterOptions()); + charsetConverter_win( + const charset& source, + const charset& dest, + const charsetConverterOptions& opts = charsetConverterOptions() + ); void convert(const string& in, string& out, status* st); void convert(utility::inputStream& in, utility::outputStream& out, status* st); - shared_ptr - getFilteredOutputStream(utility::outputStream& os, const charsetConverterOptions& opts); + shared_ptr getFilteredOutputStream( + utility::outputStream& os, + const charsetConverterOptions& opts + ); private: diff --git a/src/vmime/component.cpp b/src/vmime/component.cpp index 342d087b..7adf8f71 100644 --- a/src/vmime/component.cpp +++ b/src/vmime/component.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,48 +31,54 @@ #include -namespace vmime -{ +namespace vmime { component::component() - : m_parsedOffset(0), m_parsedLength(0) -{ + : m_parsedOffset(0), m_parsedLength(0) { + } -component::~component() -{ +component::~component() { + } -void component::parse - (const shared_ptr & inputStream, const size_t length) -{ +void component::parse( + const shared_ptr & inputStream, + const size_t length +) { + parse(inputStream, 0, length, NULL); } -void component::parse - (const shared_ptr & inputStream, const size_t position, - const size_t end, size_t* newPosition) -{ +void component::parse( + const shared_ptr & inputStream, + const size_t position, + const size_t end, + size_t* newPosition) { + parse(parsingContext::getDefaultContext(), inputStream, position, end, newPosition); } -void component::parse - (const parsingContext& ctx, - const shared_ptr & inputStream, const size_t position, - const size_t end, size_t* newPosition) -{ +void component::parse( + const parsingContext& ctx, + const shared_ptr & inputStream, + const size_t position, + const size_t end, + size_t* newPosition +) { + m_parsedOffset = m_parsedLength = 0; shared_ptr seekableStream = dynamicCast (inputStream); - if (seekableStream == NULL || end == 0) - { + if (!seekableStream || end == 0) { + // Read the whole stream into a buffer std::ostringstream oss; utility::outputStreamAdapter ossAdapter(oss); @@ -81,9 +87,9 @@ void component::parse const string buffer = oss.str(); parseImpl(ctx, buffer, 0, buffer.length(), NULL); - } - else - { + + } else { + shared_ptr parser = make_shared (seekableStream); @@ -92,79 +98,95 @@ void component::parse } -void component::parse(const string& buffer) -{ +void component::parse(const string& buffer) { + m_parsedOffset = m_parsedLength = 0; parseImpl(parsingContext::getDefaultContext(), buffer, 0, buffer.length(), NULL); } -void component::parse(const parsingContext& ctx, const string& buffer) -{ +void component::parse(const parsingContext& ctx, const string& buffer) { + m_parsedOffset = m_parsedLength = 0; parseImpl(ctx, buffer, 0, buffer.length(), NULL); } -void component::parse - (const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void component::parse( + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + m_parsedOffset = m_parsedLength = 0; parseImpl(parsingContext::getDefaultContext(), buffer, position, end, newPosition); } -void component::parse - (const parsingContext& ctx, - const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void component::parse( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, size_t* newPosition +) { + m_parsedOffset = m_parsedLength = 0; parseImpl(ctx, buffer, position, end, newPosition); } -void component::offsetParsedBounds(const size_t offset) -{ +void component::offsetParsedBounds(const size_t offset) { + // Offset parsed bounds of this component - if (m_parsedLength != 0) + if (m_parsedLength != 0) { m_parsedOffset += offset; + } // Offset parsed bounds of our children std::vector > children = getChildComponents(); - for (size_t i = 0, n = children.size() ; i < n ; ++i) + for (size_t i = 0, n = children.size() ; i < n ; ++i) { children[i]->offsetParsedBounds(offset); + } } -void component::parseImpl - (const parsingContext& ctx, const shared_ptr & parser, - const size_t position, const size_t end, size_t* newPosition) -{ +void component::parseImpl( + const parsingContext& ctx, + const shared_ptr & parser, + const size_t position, + const size_t end, + size_t* newPosition +) { + // This is the default implementation for parsing from an input stream: // actually, we extract the substring and use the "parse from string" implementation const string buffer = parser->extract(position, end); parseImpl(ctx, buffer, 0, buffer.length(), newPosition); // Recursivey offset parsed bounds on children - if (position != 0) + if (position != 0) { offsetParsedBounds(position); + } - if (newPosition != NULL) + if (newPosition) { *newPosition += position; + } } -void component::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void component::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition) { + // This is the default implementation for parsing from a string: // actually, we encapsulate the string buffer in an input stream, then use // the "parse from input stream" implementation @@ -178,9 +200,11 @@ void component::parseImpl } -const string component::generate - (const size_t maxLineLength, const size_t curLinePos) const -{ +const string component::generate( + const size_t maxLineLength, + const size_t curLinePos +) const { + std::ostringstream oss; utility::outputStreamAdapter adapter(oss); @@ -189,56 +213,63 @@ const string component::generate generateImpl(ctx, adapter, curLinePos, NULL); - return (oss.str()); + return oss.str(); } -void component::generate - (utility::outputStream& os, const size_t curLinePos, size_t* newLinePos) const -{ - generateImpl(generationContext::getDefaultContext(), - os, curLinePos, newLinePos); +void component::generate( + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + + generateImpl(generationContext::getDefaultContext(), os, curLinePos, newLinePos); } -void component::generate - (const generationContext& ctx, utility::outputStream& outputStream, - const size_t curLinePos, size_t* newLinePos) const -{ +void component::generate( + const generationContext& ctx, + utility::outputStream& outputStream, + const size_t curLinePos, + size_t* newLinePos +) const { + generateImpl(ctx, outputStream, curLinePos, newLinePos); } -size_t component::getParsedOffset() const -{ - return (m_parsedOffset); +size_t component::getParsedOffset() const { + + return m_parsedOffset; } -size_t component::getParsedLength() const -{ - return (m_parsedLength); +size_t component::getParsedLength() const { + + return m_parsedLength; } -void component::setParsedBounds(const size_t start, const size_t end) -{ +void component::setParsedBounds(const size_t start, const size_t end) { + m_parsedOffset = start; m_parsedLength = end - start; } -size_t component::getGeneratedSize(const generationContext& ctx) -{ +size_t component::getGeneratedSize(const generationContext& ctx) { + std::vector > children = getChildComponents(); size_t totalSize = 0; - for (std::vector >::iterator it = children.begin() ; it != children.end() ; ++it) + for (std::vector >::iterator it = children.begin() ; + it != children.end() ; ++it) { + totalSize += (*it)->getGeneratedSize(ctx); + } return totalSize; } } // vmime - diff --git a/src/vmime/component.hpp b/src/vmime/component.hpp index 6c360746..91164c30 100644 --- a/src/vmime/component.hpp +++ b/src/vmime/component.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,16 +34,14 @@ #include "vmime/parsingContext.hpp" -namespace vmime -{ +namespace vmime { /** This abstract class is the base class for all the components of a message. * It defines methods for parsing and generating a component. */ +class VMIME_EXPORT component : public object { -class VMIME_EXPORT component : public object -{ public: component(); @@ -80,11 +78,12 @@ public: * @param end end position in the input buffer * @param newPosition will receive the new position in the input buffer */ - void parse - (const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parse( + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); /** Parse RFC-822/MIME data for this component. * @@ -94,12 +93,13 @@ public: * @param end end position in the input buffer * @param newPosition will receive the new position in the input buffer */ - void parse - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parse( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); /** Parse RFC-822/MIME data for this component. If stream is not seekable, * or if end position is not specified, entire contents of the stream will @@ -111,11 +111,12 @@ public: * @param end end position in the input stream * @param newPosition will receive the new position in the input stream */ - void parse - (const shared_ptr & inputStream, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parse( + const shared_ptr & inputStream, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); /** Parse RFC-822/MIME data for this component. If stream is not seekable, * or if end position is not specified, entire contents of the stream will @@ -127,12 +128,13 @@ public: * @param end end position in the input stream * @param newPosition will receive the new position in the input stream */ - void parse - (const parsingContext& ctx, - const shared_ptr & inputStream, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parse( + const parsingContext& ctx, + const shared_ptr & inputStream, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); /** Generate RFC-2822/MIME data for this component. * @@ -142,9 +144,10 @@ public: * @param curLinePos length of the current line in the output buffer * @return generated data */ - virtual const string generate - (const size_t maxLineLength = lineLengthLimits::infinite, - const size_t curLinePos = 0) const; + virtual const string generate( + const size_t maxLineLength = lineLengthLimits::infinite, + const size_t curLinePos = 0 + ) const; /** Generate RFC-2822/MIME data for this component, using the default generation context. * @@ -152,10 +155,11 @@ public: * @param curLinePos length of the current line in the output buffer * @param newLinePos will receive the new line position (length of the last line written) */ - virtual void generate - (utility::outputStream& outputStream, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + virtual void generate( + utility::outputStream& outputStream, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; /** Generate RFC-2822/MIME data for this component, using the default generation context. * @@ -164,11 +168,12 @@ public: * @param curLinePos length of the current line in the output buffer * @param newLinePos will receive the new line position (length of the last line written) */ - virtual void generate - (const generationContext& ctx, - utility::outputStream& outputStream, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + virtual void generate( + const generationContext& ctx, + utility::outputStream& outputStream, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; /** Clone this component. * @@ -222,25 +227,28 @@ protected: void setParsedBounds(const size_t start, const size_t end); // AT LEAST ONE of these parseImpl() functions MUST be implemented in derived class - virtual void parseImpl - (const parsingContext& ctx, - const shared_ptr & parser, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + virtual void parseImpl( + const parsingContext& ctx, + const shared_ptr & parser, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - virtual void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + virtual void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - virtual void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const = 0; + virtual void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const = 0; private: diff --git a/src/vmime/constants.cpp b/src/vmime/constants.cpp index 3b0a54c0..2b242885 100644 --- a/src/vmime/constants.cpp +++ b/src/vmime/constants.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -24,13 +24,12 @@ #include "vmime/constants.hpp" -namespace vmime -{ +namespace vmime { // Media Types -namespace mediaTypes -{ +namespace mediaTypes { + // Types const char* const TEXT = "text"; const char* const MULTIPART = "multipart"; @@ -72,8 +71,8 @@ namespace mediaTypes // Encoding types -namespace encodingTypes -{ +namespace encodingTypes { + const char* const SEVEN_BIT = "7bit"; const char* const EIGHT_BIT = "8bit"; const char* const BASE64 = "base64"; @@ -84,16 +83,16 @@ namespace encodingTypes // Content disposition types -namespace contentDispositionTypes -{ +namespace contentDispositionTypes { + const char* const INLINE = "inline"; const char* const ATTACHMENT = "attachment"; } // Charsets -namespace charsets -{ +namespace charsets { + const char* const ISO8859_1 = "iso-8859-1"; const char* const ISO8859_2 = "iso-8859-2"; const char* const ISO8859_3 = "iso-8859-3"; @@ -159,8 +158,8 @@ namespace charsets // Fields -namespace fields -{ +namespace fields { + const char* const RECEIVED = "Received"; const char* const FROM = "From"; const char* const SENDER = "Sender"; @@ -204,32 +203,32 @@ namespace fields // Constants for disposition action modes (RFC-3978). -namespace dispositionActionModes -{ +namespace dispositionActionModes { + const char* const MANUAL = "manual"; const char* const AUTOMATIC = "automatic"; } // Constants for disposition sending modes (RFC-3798). -namespace dispositionSendingModes -{ +namespace dispositionSendingModes { + const char* const SENT_MANUALLY = "MDN-sent-manually"; const char* const SENT_AUTOMATICALLY ="MDN-sent-automatically"; } // Constants for disposition types (RFC-3798). -namespace dispositionTypes -{ +namespace dispositionTypes { + const char* const DISPLAYED = "displayed"; const char* const DELETED = "deleted"; } // Constants for disposition modifiers (RFC-3798). -namespace dispositionModifiers -{ +namespace dispositionModifiers { + const char* const ERROR = "error"; } diff --git a/src/vmime/constants.hpp b/src/vmime/constants.hpp index 8e6e3f83..17fbd3ad 100644 --- a/src/vmime/constants.hpp +++ b/src/vmime/constants.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,11 +37,11 @@ #endif -namespace vmime -{ +namespace vmime { + /** Constants for media types. */ - namespace mediaTypes - { + namespace mediaTypes { + // Types extern VMIME_EXPORT const char* const TEXT; extern VMIME_EXPORT const char* const MULTIPART; @@ -83,8 +83,8 @@ namespace vmime /** Constants for encoding types. */ - namespace encodingTypes - { + namespace encodingTypes { + extern VMIME_EXPORT const char* const SEVEN_BIT; extern VMIME_EXPORT const char* const EIGHT_BIT; extern VMIME_EXPORT const char* const BASE64; @@ -95,16 +95,16 @@ namespace vmime /** Constants for content disposition types (RFC-2183). */ - namespace contentDispositionTypes - { + namespace contentDispositionTypes { + extern VMIME_EXPORT const char* const INLINE; extern VMIME_EXPORT const char* const ATTACHMENT; } /** Constants for charsets. */ - namespace charsets - { + namespace charsets { + extern VMIME_EXPORT const char* const ISO8859_1; extern VMIME_EXPORT const char* const ISO8859_2; extern VMIME_EXPORT const char* const ISO8859_3; @@ -169,8 +169,8 @@ namespace vmime } /** Constants for standard field names. */ - namespace fields - { + namespace fields { + extern VMIME_EXPORT const char* const RECEIVED; extern VMIME_EXPORT const char* const FROM; extern VMIME_EXPORT const char* const SENDER; @@ -213,8 +213,8 @@ namespace vmime } /** Constants for disposition action modes (RFC-3978). */ - namespace dispositionActionModes - { + namespace dispositionActionModes { + /** User implicitely displayed or deleted the message (filter or * any other automatic action). */ extern VMIME_EXPORT const char* const AUTOMATIC; @@ -224,8 +224,8 @@ namespace vmime } /** Constants for disposition sending modes (RFC-3798). */ - namespace dispositionSendingModes - { + namespace dispositionSendingModes { + /** The MDN was sent because the MUA had previously been configured * to do so automatically. */ extern VMIME_EXPORT const char* const SENT_AUTOMATICALLY; @@ -235,8 +235,8 @@ namespace vmime } /** Constants for disposition types (RFC-3798). */ - namespace dispositionTypes - { + namespace dispositionTypes { + /** Message has been displayed to the user. */ extern VMIME_EXPORT const char* const DISPLAYED; /** Message has been deleted without being displayed. */ @@ -246,8 +246,8 @@ namespace vmime } /** Constants for disposition modifiers (RFC-3798). */ - namespace dispositionModifiers - { + namespace dispositionModifiers { + extern VMIME_EXPORT const char* const ERROR; } } diff --git a/src/vmime/contentDisposition.cpp b/src/vmime/contentDisposition.cpp index 3cf92e27..1602273c 100644 --- a/src/vmime/contentDisposition.cpp +++ b/src/vmime/contentDisposition.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -25,107 +25,118 @@ #include "vmime/utility/stringUtils.hpp" -namespace vmime -{ +namespace vmime { contentDisposition::contentDisposition() - : m_name(contentDispositionTypes::INLINE) -{ + : m_name(contentDispositionTypes::INLINE) { + } contentDisposition::contentDisposition(const string& name) - : m_name(utility::stringUtils::toLower(name)) -{ + : m_name(utility::stringUtils::toLower(name)) { + } contentDisposition::contentDisposition(const contentDisposition& type) - : headerFieldValue(), m_name(type.m_name) -{ + : headerFieldValue(), m_name(type.m_name) { + } -void contentDisposition::parseImpl - (const parsingContext& /* ctx */, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ - m_name = utility::stringUtils::trim(utility::stringUtils::toLower - (string(buffer.begin() + position, buffer.begin() + end))); +void contentDisposition::parseImpl( + const parsingContext& /* ctx */, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + + m_name = utility::stringUtils::trim( + utility::stringUtils::toLower( + string(buffer.begin() + position, buffer.begin() + end) + ) + ); setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void contentDisposition::generateImpl - (const generationContext& /* ctx */, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void contentDisposition::generateImpl( + const generationContext& /* ctx */, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + os << m_name; - if (newLinePos) + if (newLinePos) { *newLinePos = curLinePos + m_name.length(); + } } -contentDisposition& contentDisposition::operator=(const string& name) -{ +contentDisposition& contentDisposition::operator=(const string& name) { + m_name = utility::stringUtils::toLower(name); - return (*this); + return *this; } -bool contentDisposition::operator==(const contentDisposition& value) const -{ - return (utility::stringUtils::toLower(m_name) == value.m_name); +bool contentDisposition::operator==(const contentDisposition& value) const { + + return utility::stringUtils::toLower(m_name) == value.m_name; } -bool contentDisposition::operator!=(const contentDisposition& value) const -{ +bool contentDisposition::operator!=(const contentDisposition& value) const { + return !(*this == value); } -shared_ptr contentDisposition::clone() const -{ +shared_ptr contentDisposition::clone() const { + return make_shared (*this); } -void contentDisposition::copyFrom(const component& other) -{ +void contentDisposition::copyFrom(const component& other) { + const contentDisposition& d = dynamic_cast (other); m_name = d.m_name; } -contentDisposition& contentDisposition::operator=(const contentDisposition& other) -{ +contentDisposition& contentDisposition::operator=(const contentDisposition& other) { + copyFrom(other); - return (*this); + return *this; } -const string& contentDisposition::getName() const -{ - return (m_name); +const string& contentDisposition::getName() const { + + return m_name; } -void contentDisposition::setName(const string& name) -{ +void contentDisposition::setName(const string& name) { + m_name = name; } -const std::vector > contentDisposition::getChildComponents() -{ +const std::vector > contentDisposition::getChildComponents() { + return std::vector >(); } diff --git a/src/vmime/contentDisposition.hpp b/src/vmime/contentDisposition.hpp index c934b81d..636c0fb5 100644 --- a/src/vmime/contentDisposition.hpp +++ b/src/vmime/contentDisposition.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,15 +29,13 @@ #include "vmime/headerFieldValue.hpp" -namespace vmime -{ +namespace vmime { /** Content disposition (basic type). */ +class VMIME_EXPORT contentDisposition : public headerFieldValue { -class VMIME_EXPORT contentDisposition : public headerFieldValue -{ public: contentDisposition(); @@ -78,18 +76,20 @@ private: protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/contentDispositionField.cpp b/src/vmime/contentDispositionField.cpp index efa99b4e..7e50680e 100644 --- a/src/vmime/contentDispositionField.cpp +++ b/src/vmime/contentDispositionField.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -25,132 +25,136 @@ #include "vmime/exception.hpp" -namespace vmime -{ +namespace vmime { -contentDispositionField::contentDispositionField() -{ +contentDispositionField::contentDispositionField() { + } contentDispositionField::contentDispositionField(contentDispositionField&) - : parameterizedHeaderField() -{ + : parameterizedHeaderField() { + } -bool contentDispositionField::hasCreationDate() const -{ +bool contentDispositionField::hasCreationDate() const { + return hasParameter("creation-date"); } -const datetime contentDispositionField::getCreationDate() const -{ +const datetime contentDispositionField::getCreationDate() const { + shared_ptr param = findParameter("creation-date"); - if (param) + if (param) { return param->getValueAs (); - else + } else { return datetime::now(); + } } -void contentDispositionField::setCreationDate(const datetime& creationDate) -{ +void contentDispositionField::setCreationDate(const datetime& creationDate) { + getParameter("creation-date")->setValue(creationDate); } -bool contentDispositionField::hasModificationDate() const -{ +bool contentDispositionField::hasModificationDate() const { + return hasParameter("modification-date"); } -const datetime contentDispositionField::getModificationDate() const -{ +const datetime contentDispositionField::getModificationDate() const { + shared_ptr param = findParameter("modification-date"); - if (param) + if (param) { return param->getValueAs (); - else + } else { return datetime::now(); + } } -void contentDispositionField::setModificationDate(const datetime& modificationDate) -{ +void contentDispositionField::setModificationDate(const datetime& modificationDate) { + getParameter("modification-date")->setValue(modificationDate); } -bool contentDispositionField::hasReadDate() const -{ +bool contentDispositionField::hasReadDate() const { + return hasParameter("read-date"); } -const datetime contentDispositionField::getReadDate() const -{ +const datetime contentDispositionField::getReadDate() const { + shared_ptr param = findParameter("read-date"); - if (param) + if (param) { return param->getValueAs (); - else + } else { return datetime::now(); + } } -void contentDispositionField::setReadDate(const datetime& readDate) -{ +void contentDispositionField::setReadDate(const datetime& readDate) { + getParameter("read-date")->setValue(readDate); } -bool contentDispositionField::hasFilename() const -{ +bool contentDispositionField::hasFilename() const { + return hasParameter("filename"); } -const word contentDispositionField::getFilename() const -{ +const word contentDispositionField::getFilename() const { + shared_ptr param = findParameter("filename"); - if (param) + if (param) { return param->getValue(); - else + } else { return word(); + } } -void contentDispositionField::setFilename(const word& filename) -{ +void contentDispositionField::setFilename(const word& filename) { + getParameter("filename")->setValue(filename); } -bool contentDispositionField::hasSize() const -{ +bool contentDispositionField::hasSize() const { + return hasParameter("size"); } -const string contentDispositionField::getSize() const -{ +const string contentDispositionField::getSize() const { + shared_ptr param = findParameter("size"); - if (param) + if (param) { return param->getValue().getBuffer(); - else + } else { return ""; + } } -void contentDispositionField::setSize(const string& size) -{ +void contentDispositionField::setSize(const string& size) { + getParameter("size")->setValue(word(size, vmime::charsets::US_ASCII)); } diff --git a/src/vmime/contentDispositionField.hpp b/src/vmime/contentDispositionField.hpp index aac4c5de..89eb9076 100644 --- a/src/vmime/contentDispositionField.hpp +++ b/src/vmime/contentDispositionField.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,15 +32,13 @@ #include "vmime/word.hpp" -namespace vmime -{ +namespace vmime { /** Describes presentation information, as per RFC-2183. */ +class VMIME_EXPORT contentDispositionField : public parameterizedHeaderField { -class VMIME_EXPORT contentDispositionField : public parameterizedHeaderField -{ friend class headerFieldFactory; protected: diff --git a/src/vmime/contentHandler.cpp b/src/vmime/contentHandler.cpp index 3afe4324..0a0e6ade 100644 --- a/src/vmime/contentHandler.cpp +++ b/src/vmime/contentHandler.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -24,16 +24,15 @@ #include "vmime/contentHandler.hpp" -namespace vmime -{ +namespace vmime { // No encoding = "binary" encoding const encoding contentHandler::NO_ENCODING(encodingTypes::BINARY); -contentHandler::~contentHandler() -{ +contentHandler::~contentHandler() { + } diff --git a/src/vmime/contentHandler.hpp b/src/vmime/contentHandler.hpp index f62af166..06c16c14 100644 --- a/src/vmime/contentHandler.hpp +++ b/src/vmime/contentHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,12 +34,11 @@ #include "vmime/mediaType.hpp" -namespace vmime -{ +namespace vmime { -class VMIME_EXPORT contentHandler : public object -{ +class VMIME_EXPORT contentHandler : public object { + public: /** Used to specify that enclosed data is not encoded. */ @@ -63,7 +62,11 @@ public: * @param enc encoding for output * @param maxLineLength maximum line length for output */ - virtual void generate(utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength = lineLengthLimits::infinite) const = 0; + virtual void generate( + utility::outputStream& os, + const vmime::encoding& enc, + const size_t maxLineLength = lineLengthLimits::infinite + ) const = 0; /** Extract the contents into the specified stream. If needed, data * will be decoded before being written into the stream. @@ -74,7 +77,10 @@ public: * @param progress progress listener, or NULL if you do not * want to receive progress notifications */ - virtual void extract(utility::outputStream& os, utility::progressListener* progress = NULL) const = 0; + virtual void extract( + utility::outputStream& os, + utility::progressListener* progress = NULL + ) const = 0; /** Extract the contents into the specified stream, without * decoding it. It may be useful in case the encoding is not @@ -84,7 +90,10 @@ public: * @param progress progress listener, or NULL if you do not * want to receive progress notifications */ - virtual void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const = 0; + virtual void extractRaw( + utility::outputStream& os, + utility::progressListener* progress = NULL + ) const = 0; /** Returns the actual length of data. WARNING: this can return 0 if no * length was specified when setting data of this object, or if the diff --git a/src/vmime/contentTypeField.cpp b/src/vmime/contentTypeField.cpp index 9e9ed4c2..ec4971da 100644 --- a/src/vmime/contentTypeField.cpp +++ b/src/vmime/contentTypeField.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -25,89 +25,90 @@ #include "vmime/exception.hpp" -namespace vmime -{ +namespace vmime { -contentTypeField::contentTypeField() -{ +contentTypeField::contentTypeField() { + } contentTypeField::contentTypeField(contentTypeField&) - : parameterizedHeaderField() -{ + : parameterizedHeaderField() { + } -bool contentTypeField::hasBoundary() const -{ +bool contentTypeField::hasBoundary() const { + return hasParameter("boundary"); } -const string contentTypeField::getBoundary() const -{ +const string contentTypeField::getBoundary() const { + shared_ptr param = findParameter("boundary"); - if (param) + if (param) { return param->getValue().getBuffer(); - else + } else { return ""; + } } -void contentTypeField::setBoundary(const string& boundary) -{ +void contentTypeField::setBoundary(const string& boundary) { + getParameter("boundary")->setValue(word(boundary, vmime::charsets::US_ASCII)); } -bool contentTypeField::hasCharset() const -{ +bool contentTypeField::hasCharset() const { + return hasParameter("charset"); } -const charset contentTypeField::getCharset() const -{ +const charset contentTypeField::getCharset() const { + shared_ptr param = findParameter("charset"); - if (param) + if (param) { return param->getValueAs (); - else + } else { return charset(); + } } -void contentTypeField::setCharset(const charset& ch) -{ +void contentTypeField::setCharset(const charset& ch) { + getParameter("charset")->setValue(ch); } -bool contentTypeField::hasReportType() const -{ +bool contentTypeField::hasReportType() const { + return hasParameter("report-type"); } -const string contentTypeField::getReportType() const -{ +const string contentTypeField::getReportType() const { + shared_ptr param = findParameter("report-type"); - if (param) + if (param) { return param->getValue().getBuffer(); - else + } else { return ""; + } } -void contentTypeField::setReportType(const string& reportType) -{ +void contentTypeField::setReportType(const string& reportType) { + getParameter("report-type")->setValue(word(reportType, vmime::charsets::US_ASCII)); } } // vmime - diff --git a/src/vmime/contentTypeField.hpp b/src/vmime/contentTypeField.hpp index 8604c4a3..a63e7da0 100644 --- a/src/vmime/contentTypeField.hpp +++ b/src/vmime/contentTypeField.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,12 +31,11 @@ #include "vmime/charset.hpp" -namespace vmime -{ +namespace vmime { -class VMIME_EXPORT contentTypeField : public parameterizedHeaderField -{ +class VMIME_EXPORT contentTypeField : public parameterizedHeaderField { + friend class headerFieldFactory; protected: diff --git a/src/vmime/context.cpp b/src/vmime/context.cpp index 07fe4875..3fc4941a 100644 --- a/src/vmime/context.cpp +++ b/src/vmime/context.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -24,61 +24,60 @@ #include "vmime/context.hpp" -namespace vmime -{ +namespace vmime { context::context() - : m_internationalizedEmail(false) -{ + : m_internationalizedEmail(false) { + } context::context(const context& ctx) : object(), - m_internationalizedEmail(ctx.m_internationalizedEmail) -{ + m_internationalizedEmail(ctx.m_internationalizedEmail) { + } -context::~context() -{ +context::~context() { + } -bool context::getInternationalizedEmailSupport() const -{ +bool context::getInternationalizedEmailSupport() const { + return m_internationalizedEmail; } -void context::setInternationalizedEmailSupport(const bool support) -{ +void context::setInternationalizedEmailSupport(const bool support) { + m_internationalizedEmail = support; } -const charsetConverterOptions& context::getCharsetConversionOptions() const -{ +const charsetConverterOptions& context::getCharsetConversionOptions() const { + return m_charsetConvOptions; } -void context::setCharsetConversionOptions(const charsetConverterOptions& opts) -{ +void context::setCharsetConversionOptions(const charsetConverterOptions& opts) { + m_charsetConvOptions = opts; } -context& context::operator=(const context& ctx) -{ +context& context::operator=(const context& ctx) { + copyFrom(ctx); return *this; } -void context::copyFrom(const context& ctx) -{ +void context::copyFrom(const context& ctx) { + m_internationalizedEmail = ctx.m_internationalizedEmail; m_charsetConvOptions = ctx.m_charsetConvOptions; } diff --git a/src/vmime/context.hpp b/src/vmime/context.hpp index 767ec05a..1d009500 100644 --- a/src/vmime/context.hpp +++ b/src/vmime/context.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,15 +29,13 @@ #include "vmime/charsetConverterOptions.hpp" -namespace vmime -{ +namespace vmime { /** Holds configuration parameters used either for parsing or generating messages. */ +class VMIME_EXPORT context : public object { -class VMIME_EXPORT context : public object -{ public: virtual ~context(); @@ -74,8 +72,8 @@ public: /** Switches between contexts temporarily. */ template - class switcher - { + class switcher { + public: /** Switches to the specified context. @@ -85,15 +83,15 @@ public: * @param newCtx new context */ switcher(CTX_CLASS& newCtx) - : m_oldCtxData(CTX_CLASS::getDefaultContext()), m_newCtx(&newCtx) - { + : m_oldCtxData(CTX_CLASS::getDefaultContext()), m_newCtx(&newCtx) { + CTX_CLASS::getDefaultContext().copyFrom(newCtx); } /** Restores back saved context. */ - ~switcher() - { + ~switcher() { + CTX_CLASS::getDefaultContext().copyFrom(m_oldCtxData); } diff --git a/src/vmime/dateTime.cpp b/src/vmime/dateTime.cpp index eca8e785..fd443030 100644 --- a/src/vmime/dateTime.cpp +++ b/src/vmime/dateTime.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,8 +31,7 @@ #include "vmime/utility/datetimeUtils.hpp" -namespace vmime -{ +namespace vmime { /* @@ -68,20 +67,24 @@ zone = "UT" / "GMT" ; Universal Time */ -void datetime::parseImpl - (const parsingContext& /* ctx */, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void datetime::parseImpl( + const parsingContext& /* ctx */, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + const char* const pend = buffer.data() + end; const char* p = buffer.data() + position; // Parse the date and time value while (p < pend && parserHelpers::isSpace(*p)) ++p; - if (p < pend) - { - if (parserHelpers::isAlpha(*p)) - { + if (p < pend) { + + if (parserHelpers::isAlpha(*p)) { + // Ignore week day while (p < pend && parserHelpers::isAlpha(*p)) ++p; while (p < pend && parserHelpers::isSpace(*p)) ++p; @@ -91,34 +94,32 @@ void datetime::parseImpl bool dayParsed = false; - if (parserHelpers::isAlpha(*p)) - { + if (parserHelpers::isAlpha(*p)) { + // Ill-formed date/time, this may be the month, // so we skip day parsing (will be done later) - } - else - { + + } else { + while (p < pend && !parserHelpers::isDigit(*p)) ++p; - if (p < pend && parserHelpers::isDigit(*p)) - { + if (p < pend && parserHelpers::isDigit(*p)) { + // Month day int day = 0; - do - { + do { day = day * 10 + (*p - '0'); ++p; - } - while (p < pend && parserHelpers::isDigit(*p)); + } while (p < pend && parserHelpers::isDigit(*p)); m_day = (day >= 1 && day <= 31) ? day : 1; while (p < pend && !parserHelpers::isSpace(*p)) ++p; while (p < pend && parserHelpers::isSpace(*p)) ++p; - } - else - { + + } else { + m_day = 1; // Skip everything to the next field @@ -129,135 +130,131 @@ void datetime::parseImpl dayParsed = true; } - if (p < pend && parserHelpers::isAlpha(*p)) - { + if (p < pend && parserHelpers::isAlpha(*p)) { + // Month char_t month[4] = { 0 }; int monthLength = 0; - do - { + do { month[monthLength++] = *p; ++p; - } - while (monthLength < 3 && p < pend && parserHelpers::isAlpha(*p)); + } while (monthLength < 3 && p < pend && parserHelpers::isAlpha(*p)); while (p < pend && parserHelpers::isAlpha(*p)) ++p; - switch (month[0]) - { - case 'a': - case 'A': - { - if (month[1] == 'u' || month[1] == 'U') - m_month = AUGUST; - else - m_month = APRIL; // by default + switch (month[0]) { - break; - } - case 'd': - case 'D': - { - m_month = DECEMBER; - break; - } - case 'f': - case 'F': - { - m_month = FEBRUARY; - break; - } - case 'j': - case 'J': - { - if (month[1] == 'u' || month[1] == 'U') - { - if (month[2] == 'l' || month[2] == 'L') - m_month = JULY; - else // if (month[2] == 'n' || month[2] == 'N') - m_month = JUNE; + case 'a': + case 'A': { + + if (month[1] == 'u' || month[1] == 'U') + m_month = AUGUST; + else + m_month = APRIL; // by default + + break; } - else - { + case 'd': + case 'D': { + + m_month = DECEMBER; + break; + } + case 'f': + case 'F': { + + m_month = FEBRUARY; + break; + } + case 'j': + case 'J': { + + if (month[1] == 'u' || month[1] == 'U') { + + if (month[2] == 'l' || month[2] == 'L') { + m_month = JULY; + } else { // if (month[2] == 'n' || month[2] == 'N') + m_month = JUNE; + } + + } else { + + m_month = JANUARY; // by default + } + + break; + } + case 'm': + case 'M': { + + if ((month[1] == 'a' || month[1] == 'A') && + (month[2] == 'y' || month[2] == 'Y')) { + + m_month = MAY; + + } else { + + m_month = MARCH; // by default + } + + break; + } + case 'n': + case 'N': { + + m_month = NOVEMBER; + break; + } + case 'o': + case 'O': { + + m_month = OCTOBER; + break; + } + case 's': + case 'S': { + + m_month = SEPTEMBER; + break; + } + default: { + m_month = JANUARY; // by default + break; } - - break; - } - case 'm': - case 'M': - { - if ((month[1] == 'a' || month[1] == 'A') && - (month[2] == 'y' || month[2] == 'Y')) - { - m_month = MAY; - } - else - { - m_month = MARCH; // by default - } - - break; - } - case 'n': - case 'N': - { - m_month = NOVEMBER; - break; - } - case 'o': - case 'O': - { - m_month = OCTOBER; - break; - } - case 's': - case 'S': - { - m_month = SEPTEMBER; - break; - } - default: - { - m_month = JANUARY; // by default - break; - } - } while (p < pend && !parserHelpers::isSpace(*p)) ++p; while (p < pend && parserHelpers::isSpace(*p)) ++p; - } - else - { + + } else { + m_month = JANUARY; - if (parserHelpers::isDigit(*p)) - { + if (parserHelpers::isDigit(*p)) { + // Here, we expected a month, but it maybe // a ill-formed date, so try to parse a year // (we don't skip anything). - } - else - { + + } else { + // Skip everything to the next field while (p < pend && !parserHelpers::isSpace(*p)) ++p; while (p < pend && parserHelpers::isSpace(*p)) ++p; } } - if (!dayParsed && p < pend && parserHelpers::isDigit(*p)) - { + if (!dayParsed && p < pend && parserHelpers::isDigit(*p)) { + // Month day int day = 0; - do - { + do { day = day * 10 + (*p - '0'); ++p; - } - while (p < pend && parserHelpers::isDigit(*p)); + } while (p < pend && parserHelpers::isDigit(*p)); m_day = (day >= 1 && day <= 31) ? day : 1; @@ -265,26 +262,24 @@ void datetime::parseImpl while (p < pend && parserHelpers::isSpace(*p)) ++p; } - if (p < pend && parserHelpers::isDigit(*p)) - { + if (p < pend && parserHelpers::isDigit(*p)) { + // Check for ill-formed date/time and try to recover - if (p + 2 < pend && *(p + 2) == ':') - { + if (p + 2 < pend && *(p + 2) == ':') { + // Skip year (default to current), and advance // to time parsing m_year = now().getYear(); - } - else - { + + } else { + // Year int year = 0; - do - { + do { year = year * 10 + (*p - '0'); ++p; - } - while (p < pend && parserHelpers::isDigit(*p)); + } while (p < pend && parserHelpers::isDigit(*p)); if (year < 70) m_year = year + 2000; else if (year < 1000) m_year = year + 1900; @@ -293,9 +288,9 @@ void datetime::parseImpl while (p < pend && !parserHelpers::isSpace(*p)) ++p; while (p < pend && parserHelpers::isSpace(*p)) ++p; } - } - else - { + + } else { + m_year = 1970; // Skip everything to the next field @@ -303,89 +298,83 @@ void datetime::parseImpl while (p < pend && parserHelpers::isSpace(*p)) ++p; } - if (p < pend && parserHelpers::isDigit(*p)) - { + if (p < pend && parserHelpers::isDigit(*p)) { + // Hour int hour = 0; - do - { + do { hour = hour * 10 + (*p - '0'); ++p; - } - while (p < pend && parserHelpers::isDigit(*p)); + } while (p < pend && parserHelpers::isDigit(*p)); m_hour = (hour >= 0 && hour <= 23) ? hour : 0; while (p < pend && parserHelpers::isSpace(*p)) ++p; - if (p < pend && *p == ':') - { + if (p < pend && *p == ':') { + ++p; while (p < pend && parserHelpers::isSpace(*p)) ++p; - if (p < pend && parserHelpers::isDigit(*p)) - { + if (p < pend && parserHelpers::isDigit(*p)) { + // Minute int minute = 0; - do - { + do { minute = minute * 10 + (*p - '0'); ++p; - } - while (p < pend && parserHelpers::isDigit(*p)); + } while (p < pend && parserHelpers::isDigit(*p)); m_minute = (minute >= 0 && minute <= 59) ? minute : 0; while (p < pend && parserHelpers::isSpace(*p)) ++p; - if (p < pend && *p == ':') - { + if (p < pend && *p == ':') { + ++p; while (p < pend && parserHelpers::isSpace(*p)) ++p; - if (p < pend && parserHelpers::isDigit(*p)) - { + if (p < pend && parserHelpers::isDigit(*p)) { + // Second int second = 0; - do - { + do { second = second * 10 + (*p - '0'); ++p; - } - while (p < pend && parserHelpers::isDigit(*p)); + } while (p < pend && parserHelpers::isDigit(*p)); m_second = (second >= 0 && second <= 59) ? second : 0; while (p < pend && !parserHelpers::isSpace(*p)) ++p; while (p < pend && parserHelpers::isSpace(*p)) ++p; - } - else - { + + } else { + m_second = 0; } - } - else - { + + } else { + m_second = 0; } - } - else - { + + } else { + m_minute = 0; } - } - else - { + + } else { + m_minute = 0; } - } - else - { + + } else { + m_hour = 0; // Skip everything to the next field @@ -393,43 +382,40 @@ void datetime::parseImpl while (p < pend && parserHelpers::isSpace(*p)) ++p; } - if (p + 1 < pend && (*p == '+' || *p == '-') && parserHelpers::isDigit(*(p + 1))) - { + if (p + 1 < pend && (*p == '+' || *p == '-') && parserHelpers::isDigit(*(p + 1))) { + const char_t sign = *p; ++p; // Zone offset (in hour/minutes) int offset = 0; - do - { + do { offset = offset * 10 + (*p - '0'); ++p; - } - while (p < pend && parserHelpers::isDigit(*p)); + } while (p < pend && parserHelpers::isDigit(*p)); const int hourOff = offset / 100; const int minOff = offset % 100; - if (sign == '+') + if (sign == '+') { m_zone = hourOff * 60 + minOff; - else + } else { m_zone = -(hourOff * 60 + minOff); - } - else if (p < pend && isalpha(*p)) - { + } + + } else if (p < pend && isalpha(*p)) { + bool done = false; // Zone offset (Time zone name) char_t zone[4] = { 0 }; int zoneLength = 0; - do - { + do { zone[zoneLength++] = *p; ++p; - } - while (zoneLength < 3 && p < pend); + } while (zoneLength < 3 && p < pend); switch (zone[0]) { @@ -451,12 +437,13 @@ void datetime::parseImpl case 'e': case 'E': { - if (zoneLength >= 2) - { - if (zone[1] == 's' || zone[1] == 'S') + if (zoneLength >= 2) { + + if (zone[1] == 's' || zone[1] == 'S') { m_zone = EST; - else + } else { m_zone = EDT; + } done = true; } @@ -464,14 +451,15 @@ void datetime::parseImpl break; } case 'm': - case 'M': - { - if (zoneLength >= 2) - { - if (zone[1] == 's' || zone[1] == 'S') + case 'M': { + + if (zoneLength >= 2) { + + if (zone[1] == 's' || zone[1] == 'S') { m_zone = MST; - else + } else { m_zone = MDT; + } done = true; } @@ -479,14 +467,15 @@ void datetime::parseImpl break; } case 'p': - case 'P': - { - if (zoneLength >= 2) - { - if (zone[1] == 's' || zone[1] == 'S') + case 'P': { + + if (zoneLength >= 2) { + + if (zone[1] == 's' || zone[1] == 'S') { m_zone = PST; - else + } else { m_zone = PDT; + } done = true; } @@ -496,10 +485,10 @@ void datetime::parseImpl case 'g': case 'G': case 'u': - case 'U': - { - if (zoneLength >= 2) - { + case 'U': { + + if (zoneLength >= 2) { + m_zone = GMT; // = UTC done = true; } @@ -509,16 +498,16 @@ void datetime::parseImpl } - if (!done) - { + if (!done) { + const char_t z = zone[0]; // Military time zone - if (z != 'j' && z != 'J') - { + if (z != 'j' && z != 'J') { + typedef std::map Map; - static const Map::value_type offsetMapInit[] = - { + static const Map::value_type offsetMapInit[] = { + Map::value_type('a', -60), Map::value_type('b', -120), Map::value_type('c', -180), @@ -547,31 +536,34 @@ void datetime::parseImpl Map::value_type('z', 0), }; - static const Map offsetMap - (::vmime::begin(offsetMapInit), - ::vmime::end(offsetMapInit)); + + static const Map offsetMap( + ::vmime::begin(offsetMapInit), + ::vmime::end(offsetMapInit) + ); Map::const_iterator pos = offsetMap.find(parserHelpers::toLower(z)); - if (pos != offsetMap.end()) + if (pos != offsetMap.end()) { m_zone = (*pos).second; - else + } else { m_zone = GMT; - } - else - { + } + + } else { + m_zone = GMT; } } - } - else - { + + } else { + m_zone = 0; } - } - else - { + + } else { + m_year = 1970; m_month = JANUARY; m_day = 1; @@ -585,20 +577,26 @@ void datetime::parseImpl setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void datetime::generateImpl - (const generationContext& /* ctx */, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ - static const char* dayNames[] = - { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; - static const char* monthNames[] = - { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +void datetime::generateImpl( + const generationContext& /* ctx */, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + + static const char* dayNames[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + static const char* monthNames[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; const int z = ((m_zone < 0) ? -m_zone : m_zone); const int zh = z / 60; @@ -618,64 +616,89 @@ void datetime::generateImpl const string& str = oss.str(); os << str; - if (newLinePos) + if (newLinePos) { *newLinePos = curLinePos + str.length(); + } } datetime::datetime() : m_year(1970), m_month(1), m_day(1), - m_hour(0), m_minute(0), m_second(0), m_zone(0) -{ + m_hour(0), m_minute(0), m_second(0), m_zone(0) { + } datetime::datetime(const int year, const int month, const int day) : m_year(year), m_month(month), m_day(day), - m_hour(0), m_minute(0), m_second(0), m_zone(0) -{ + m_hour(0), m_minute(0), m_second(0), m_zone(0) { + } -datetime::datetime(const int year, const int month, const int day, - const int hour, const int minute, const int second, - const int zone) - : m_year(year), m_month(month), m_day(day), - m_hour(hour), m_minute(minute), m_second(second), m_zone(zone) -{ +datetime::datetime( + const int year, + const int month, + const int day, + const int hour, + const int minute, + const int second, + const int zone +) + : m_year(year), + m_month(month), + m_day(day), + m_hour(hour), + m_minute(minute), + m_second(second), + m_zone(zone) { + } datetime::datetime(const datetime& d) - : headerFieldValue(), m_year(d.m_year), m_month(d.m_month), m_day(d.m_day), - m_hour(d.m_hour), m_minute(d.m_minute), m_second(d.m_second), m_zone(d.m_zone) -{ + : headerFieldValue(), + m_year(d.m_year), + m_month(d.m_month), + m_day(d.m_day), + m_hour(d.m_hour), + m_minute(d.m_minute), + m_second(d.m_second), + m_zone(d.m_zone) { + } -datetime::datetime(const time_t t, const int zone) -{ +datetime::datetime(const time_t t, const int zone) { #if VMIME_HAVE_LOCALTIME_S + struct tm tms; - if (!gmtime_s(&tms, &t)) + if (!gmtime_s(&tms, &t)) { localtime_s(&tms, &t); + } + #elif VMIME_HAVE_LOCALTIME_R struct tm tms; - if (!gmtime_r(&t, &tms)) + if (!gmtime_r(&t, &tms)) { localtime_r(&t, &tms); + } + #else + struct tm* gtm = gmtime(&t); struct tm* ltm = localtime(&t); struct tm tms; - if (gtm) + if (gtm) { tms = *gtm; - else if (ltm) + } else if (ltm) { tms = *ltm; + } + #endif m_year = tms.tm_year + 1900; @@ -688,19 +711,19 @@ datetime::datetime(const time_t t, const int zone) } -datetime::datetime(const string& date) -{ +datetime::datetime(const string& date) { + parse(date); } -datetime::~datetime() -{ +datetime::~datetime() { + } -void datetime::copyFrom(const component& other) -{ +void datetime::copyFrom(const component& other) { + const datetime& d = dynamic_cast (other); m_year = d.m_year; @@ -713,22 +736,22 @@ void datetime::copyFrom(const component& other) } -datetime& datetime::operator=(const datetime& other) -{ +datetime& datetime::operator=(const datetime& other) { + copyFrom(other); - return (*this); + return *this; } -datetime& datetime::operator=(const string& s) -{ +datetime& datetime::operator=(const string& s) { + parse(s); - return (*this); + return *this; } -void datetime::getTime(int& hour, int& minute, int& second, int& zone) const -{ +void datetime::getTime(int& hour, int& minute, int& second, int& zone) const { + hour = m_hour; minute = m_minute; second = m_second; @@ -736,25 +759,29 @@ void datetime::getTime(int& hour, int& minute, int& second, int& zone) const } -void datetime::getTime(int& hour, int& minute, int& second) const -{ +void datetime::getTime(int& hour, int& minute, int& second) const { + hour = m_hour; minute = m_minute; second = m_second; } -void datetime::getDate(int& year, int& month, int& day) const -{ +void datetime::getDate(int& year, int& month, int& day) const { + year = m_year; month = m_month; day = m_day; } -void datetime::setTime(const int hour, const int minute, - const int second, const int zone) -{ +void datetime::setTime( + const int hour, + const int minute, + const int second, + const int zone +) { + m_hour = hour; m_minute = minute; m_second = second; @@ -762,40 +789,44 @@ void datetime::setTime(const int hour, const int minute, } -void datetime::setDate(const int year, const int month, const int day) -{ +void datetime::setDate( + const int year, + const int month, + const int day +) { + m_year = year; m_month = month; m_day = day; } -const datetime datetime::now() -{ - return (platform::getHandler()->getCurrentLocalTime()); +const datetime datetime::now() { + + return platform::getHandler()->getCurrentLocalTime(); } -shared_ptr datetime::clone() const -{ +shared_ptr datetime::clone() const { + return make_shared (*this); } -const std::vector > datetime::getChildComponents() -{ +const std::vector > datetime::getChildComponents() { + return std::vector >(); } -int datetime::getYear() const { return (m_year); } -int datetime::getMonth() const { return (m_month); } -int datetime::getDay() const { return (m_day); } -int datetime::getHour() const { return (m_hour); } -int datetime::getMinute() const { return (m_minute); } -int datetime::getSecond() const { return (m_second); } -int datetime::getZone() const { return (m_zone); } -int datetime::getWeekDay() const { return (utility::datetimeUtils::getDayOfWeek(m_year, m_month, m_day)); } +int datetime::getYear() const { return m_year; } +int datetime::getMonth() const { return m_month; } +int datetime::getDay() const { return m_day; } +int datetime::getHour() const { return m_hour; } +int datetime::getMinute() const { return m_minute; } +int datetime::getSecond() const { return m_second; } +int datetime::getZone() const { return m_zone; } +int datetime::getWeekDay() const { return utility::datetimeUtils::getDayOfWeek(m_year, m_month, m_day); } int datetime::getWeek() const { return utility::datetimeUtils::getWeekOfYear(m_year, m_month, m_day); } void datetime::setYear(const int year) { m_year = year; } @@ -807,87 +838,87 @@ void datetime::setSecond(const int second) { m_second = second; } void datetime::setZone(const int zone) { m_zone = zone; } -bool datetime::operator==(const datetime& other) const -{ +bool datetime::operator==(const datetime& other) const { + const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this); const datetime ut2 = utility::datetimeUtils::toUniversalTime(other); - return (ut1.m_year == ut2.m_year && - ut1.m_month == ut2.m_month && - ut1.m_day == ut2.m_day && - ut1.m_hour == ut2.m_hour && - ut1.m_minute == ut2.m_minute && - ut1.m_second == ut2.m_second); + return ut1.m_year == ut2.m_year && + ut1.m_month == ut2.m_month && + ut1.m_day == ut2.m_day && + ut1.m_hour == ut2.m_hour && + ut1.m_minute == ut2.m_minute && + ut1.m_second == ut2.m_second; } -bool datetime::operator!=(const datetime& other) const -{ +bool datetime::operator!=(const datetime& other) const { + const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this); const datetime ut2 = utility::datetimeUtils::toUniversalTime(other); - return (ut1.m_year != ut2.m_year || - ut1.m_month != ut2.m_month || - ut1.m_day != ut2.m_day || - ut1.m_hour != ut2.m_hour || - ut1.m_minute != ut2.m_minute || - ut1.m_second != ut2.m_second); + return ut1.m_year != ut2.m_year || + ut1.m_month != ut2.m_month || + ut1.m_day != ut2.m_day || + ut1.m_hour != ut2.m_hour || + ut1.m_minute != ut2.m_minute || + ut1.m_second != ut2.m_second; } -bool datetime::operator<(const datetime& other) const -{ +bool datetime::operator<(const datetime& other) const { + const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this); const datetime ut2 = utility::datetimeUtils::toUniversalTime(other); - return ((ut1.m_year < ut2.m_year) || - ((ut1.m_year == ut2.m_year) && ((ut1.m_month < ut2.m_month) || - ((ut1.m_month == ut2.m_month) && ((ut1.m_day < ut2.m_day) || - ((ut1.m_day == ut2.m_day) && ((ut1.m_hour < ut2.m_hour) || - ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute < ut2.m_minute) || - ((ut1.m_minute == ut2.m_minute) && ((ut1.m_second < ut2.m_second)))))))))))); + return (ut1.m_year < ut2.m_year) || + ((ut1.m_year == ut2.m_year) && ((ut1.m_month < ut2.m_month) || + ((ut1.m_month == ut2.m_month) && ((ut1.m_day < ut2.m_day) || + ((ut1.m_day == ut2.m_day) && ((ut1.m_hour < ut2.m_hour) || + ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute < ut2.m_minute) || + ((ut1.m_minute == ut2.m_minute) && ((ut1.m_second < ut2.m_second))))))))))); } -bool datetime::operator<=(const datetime& other) const -{ +bool datetime::operator<=(const datetime& other) const { + const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this); const datetime ut2 = utility::datetimeUtils::toUniversalTime(other); - return ((ut1.m_year < ut2.m_year) || - ((ut1.m_year == ut2.m_year) && ((ut1.m_month < ut2.m_month) || - ((ut1.m_month == ut2.m_month) && ((ut1.m_day < ut2.m_day) || - ((ut1.m_day == ut2.m_day) && ((ut1.m_hour < ut2.m_hour) || - ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute < ut2.m_minute) || - ((ut1.m_minute == ut2.m_minute) && ((ut1.m_second <= ut2.m_second)))))))))))); + return (ut1.m_year < ut2.m_year) || + ((ut1.m_year == ut2.m_year) && ((ut1.m_month < ut2.m_month) || + ((ut1.m_month == ut2.m_month) && ((ut1.m_day < ut2.m_day) || + ((ut1.m_day == ut2.m_day) && ((ut1.m_hour < ut2.m_hour) || + ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute < ut2.m_minute) || + ((ut1.m_minute == ut2.m_minute) && ((ut1.m_second <= ut2.m_second))))))))))); } -bool datetime::operator>(const datetime& other) const -{ +bool datetime::operator>(const datetime& other) const { + const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this); const datetime ut2 = utility::datetimeUtils::toUniversalTime(other); - return ((ut1.m_year > ut2.m_year) || - ((ut1.m_year == ut2.m_year) && ((ut1.m_month > ut2.m_month) || - ((ut1.m_month == ut2.m_month) && ((ut1.m_day > ut2.m_day) || - ((ut1.m_day == ut2.m_day) && ((ut1.m_hour > ut2.m_hour) || - ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute > ut2.m_minute) || - ((ut1.m_minute == ut2.m_minute) && (ut1.m_second > ut2.m_second))))))))))); + return (ut1.m_year > ut2.m_year) || + ((ut1.m_year == ut2.m_year) && ((ut1.m_month > ut2.m_month) || + ((ut1.m_month == ut2.m_month) && ((ut1.m_day > ut2.m_day) || + ((ut1.m_day == ut2.m_day) && ((ut1.m_hour > ut2.m_hour) || + ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute > ut2.m_minute) || + ((ut1.m_minute == ut2.m_minute) && (ut1.m_second > ut2.m_second)))))))))); } -bool datetime::operator>=(const datetime& other) const -{ +bool datetime::operator>=(const datetime& other) const { + const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this); const datetime ut2 = utility::datetimeUtils::toUniversalTime(other); - return ((ut1.m_year > ut2.m_year) || - ((ut1.m_year == ut2.m_year) && ((ut1.m_month > ut2.m_month) || - ((ut1.m_month == ut2.m_month) && ((ut1.m_day > ut2.m_day) || - ((ut1.m_day == ut2.m_day) && ((ut1.m_hour > ut2.m_hour) || - ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute > ut2.m_minute) || - ((ut1.m_minute == ut2.m_minute) && (ut1.m_second >= ut2.m_second))))))))))); + return (ut1.m_year > ut2.m_year) || + ((ut1.m_year == ut2.m_year) && ((ut1.m_month > ut2.m_month) || + ((ut1.m_month == ut2.m_month) && ((ut1.m_day > ut2.m_day) || + ((ut1.m_day == ut2.m_day) && ((ut1.m_hour > ut2.m_hour) || + ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute > ut2.m_minute) || + ((ut1.m_minute == ut2.m_minute) && (ut1.m_second >= ut2.m_second)))))))))); } diff --git a/src/vmime/dateTime.hpp b/src/vmime/dateTime.hpp index 7af63040..64e8dad4 100644 --- a/src/vmime/dateTime.hpp +++ b/src/vmime/dateTime.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,21 +31,31 @@ #include -namespace vmime -{ +namespace vmime { /** Date and time (basic type). */ +class VMIME_EXPORT datetime : public headerFieldValue { -class VMIME_EXPORT datetime : public headerFieldValue -{ public: // Constructors datetime(); - datetime(const int year, const int month, const int day); - datetime(const int year, const int month, const int day, const int hour, const int minute, const int second, const int zone = GMT); + datetime( + const int year, + const int month, + const int day + ); + datetime( + const int year, + const int month, + const int day, + const int hour, + const int minute, + const int second, + const int zone = GMT + ); datetime(const datetime& d); datetime(const string& date); datetime(const time_t t, const int zone = GMT); @@ -54,8 +64,8 @@ public: ~datetime(); // Some time zones (in minutes) - enum TimeZones - { + enum TimeZones { + GMT_12 = -720, // GMT-12h GMT_11 = -660, // GMT-11h GMT_10 = -600, // GMT-10h @@ -124,8 +134,8 @@ public: }; // Months list - enum Months - { + enum Months { + // Long JANUARY = 1, FEBRUARY = 2, @@ -155,8 +165,8 @@ public: }; // Days of week list - enum DaysOfWeek - { + enum DaysOfWeek { + // Long SUNDAY = 0, MONDAY = 1, @@ -242,18 +252,20 @@ public: protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/defaultAttachment.cpp b/src/vmime/defaultAttachment.cpp index 2eb9289a..36eaa3cf 100644 --- a/src/vmime/defaultAttachment.cpp +++ b/src/vmime/defaultAttachment.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,57 +28,75 @@ #include "vmime/encoding.hpp" -namespace vmime -{ +namespace vmime { -defaultAttachment::defaultAttachment() -{ +defaultAttachment::defaultAttachment() { + } -defaultAttachment::defaultAttachment(const shared_ptr & data, - const encoding& enc, const mediaType& type, const text& desc, const word& name) - : m_type(type), m_desc(desc), m_data(data), m_encoding(enc), m_name(name) -{ +defaultAttachment::defaultAttachment( + const shared_ptr & data, + const encoding& enc, + const mediaType& type, + const text& desc, + const word& name +) + : m_type(type), + m_desc(desc), + m_data(data), + m_encoding(enc), + m_name(name) { + } -defaultAttachment::defaultAttachment(const shared_ptr & data, - const mediaType& type, const text& desc, const word& name) - : m_type(type), m_desc(desc), m_data(data), - m_encoding(encoding::decide(data)), m_name(name) -{ +defaultAttachment::defaultAttachment( + const shared_ptr & data, + const mediaType& type, + const text& desc, + const word& name +) + : m_type(type), + m_desc(desc), + m_data(data), + m_encoding(encoding::decide(data)), + m_name(name) { + } defaultAttachment::defaultAttachment(const defaultAttachment& attach) - : attachment(), m_type(attach.m_type), m_desc(attach.m_desc), + : attachment(), + m_type(attach.m_type), + m_desc(attach.m_desc), m_data(vmime::clone(attach.m_data)), - m_encoding(attach.m_encoding), m_name(attach.m_name) -{ + m_encoding(attach.m_encoding), + m_name(attach.m_name) { + } -defaultAttachment::~defaultAttachment() -{ +defaultAttachment::~defaultAttachment() { + } -defaultAttachment& defaultAttachment::operator=(const defaultAttachment& attach) -{ +defaultAttachment& defaultAttachment::operator=(const defaultAttachment& attach) { + m_type = attach.m_type; m_desc = attach.m_desc; m_name = attach.m_name; m_data = vmime::clone(attach.m_data); m_encoding = attach.m_encoding; - return (*this); + return *this; } -void defaultAttachment::generateIn(const shared_ptr & parent) const -{ +void defaultAttachment::generateIn(const shared_ptr & parent) const { + // Create and append a new part for this attachment shared_ptr part = make_shared (); parent->getBody()->appendPart(part); @@ -87,8 +105,8 @@ void defaultAttachment::generateIn(const shared_ptr & parent) const } -void defaultAttachment::generatePart(const shared_ptr & part) const -{ +void defaultAttachment::generatePart(const shared_ptr & part) const { + // Set header fields part->getHeader()->ContentType()->setValue(m_type); if (!m_desc.isEmpty()) part->getHeader()->ContentDescription()->setValue(m_desc); @@ -101,44 +119,44 @@ void defaultAttachment::generatePart(const shared_ptr & part) const } -const mediaType defaultAttachment::getType() const -{ +const mediaType defaultAttachment::getType() const { + return m_type; } -const text defaultAttachment::getDescription() const -{ +const text defaultAttachment::getDescription() const { + return m_desc; } -const word defaultAttachment::getName() const -{ +const word defaultAttachment::getName() const { + return m_name; } -const shared_ptr defaultAttachment::getData() const -{ +const shared_ptr defaultAttachment::getData() const { + return m_data; } -const encoding defaultAttachment::getEncoding() const -{ +const encoding defaultAttachment::getEncoding() const { + return m_encoding; } -shared_ptr defaultAttachment::getPart() const -{ +shared_ptr defaultAttachment::getPart() const { + return null; } -shared_ptr defaultAttachment::getHeader() const -{ +shared_ptr defaultAttachment::getHeader() const { + return null; } diff --git a/src/vmime/defaultAttachment.hpp b/src/vmime/defaultAttachment.hpp index 817e834b..ce1c603c 100644 --- a/src/vmime/defaultAttachment.hpp +++ b/src/vmime/defaultAttachment.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,15 +29,13 @@ #include "vmime/encoding.hpp" -namespace vmime -{ +namespace vmime { /** Default implementation for attachments. */ +class VMIME_EXPORT defaultAttachment : public attachment { -class VMIME_EXPORT defaultAttachment : public attachment -{ protected: // For use in derived classes. @@ -45,8 +43,21 @@ protected: public: - defaultAttachment(const shared_ptr & data, const encoding& enc, const mediaType& type, const text& desc = NULL_TEXT, const word& name = NULL_WORD); - defaultAttachment(const shared_ptr & data, const mediaType& type, const text& desc = NULL_TEXT, const word& name = NULL_WORD); + defaultAttachment( + const shared_ptr & data, + const encoding& enc, + const mediaType& type, + const text& desc = NULL_TEXT, + const word& name = NULL_WORD + ); + + defaultAttachment( + const shared_ptr & data, + const mediaType& type, + const text& desc = NULL_TEXT, + const word& name = NULL_WORD + ); + defaultAttachment(const defaultAttachment& attach); ~defaultAttachment(); diff --git a/src/vmime/disposition.cpp b/src/vmime/disposition.cpp index 352d3251..6e10cb9d 100644 --- a/src/vmime/disposition.cpp +++ b/src/vmime/disposition.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -27,25 +27,30 @@ #include "vmime/utility/stringUtils.hpp" -namespace vmime -{ +namespace vmime { -disposition::disposition() -{ +disposition::disposition() { + } -disposition::disposition(const string& actionMode, const string& sendingMode, - const string& type, const string& modifier) - : m_actionMode(actionMode), m_sendingMode(sendingMode), m_type(type) -{ +disposition::disposition( + const string& actionMode, + const string& sendingMode, + const string& type, + const string& modifier +) + : m_actionMode(actionMode), + m_sendingMode(sendingMode), + m_type(type) { + m_modifiers.push_back(modifier); } -shared_ptr disposition::clone() const -{ +shared_ptr disposition::clone() const { + shared_ptr disp = make_shared (); disp->m_actionMode = m_actionMode; @@ -55,12 +60,12 @@ shared_ptr disposition::clone() const std::copy(m_modifiers.begin(), m_modifiers.end(), disp->m_modifiers.begin()); - return (disp); + return disp; } -void disposition::copyFrom(const component& other) -{ +void disposition::copyFrom(const component& other) { + const disposition& disp = dynamic_cast (other); m_actionMode = disp.m_actionMode; @@ -72,71 +77,71 @@ void disposition::copyFrom(const component& other) } -disposition& disposition::operator=(const disposition& other) -{ +disposition& disposition::operator=(const disposition& other) { + copyFrom(other); - return (*this); + return *this; } -const std::vector > disposition::getChildComponents() -{ +const std::vector > disposition::getChildComponents() { + return std::vector >(); } -void disposition::setActionMode(const string& mode) -{ +void disposition::setActionMode(const string& mode) { + m_actionMode = mode; } -const string& disposition::getActionMode() const -{ - return (m_actionMode); +const string& disposition::getActionMode() const { + + return m_actionMode; } -void disposition::setSendingMode(const string& mode) -{ +void disposition::setSendingMode(const string& mode) { + m_sendingMode = mode; } -const string& disposition::getSendingMode() const -{ - return (m_sendingMode); +const string& disposition::getSendingMode() const { + + return m_sendingMode; } -void disposition::setType(const string& type) -{ +void disposition::setType(const string& type) { + m_type = type; } -const string& disposition::getType() const -{ - return (m_type); +const string& disposition::getType() const { + + return m_type; } -void disposition::addModifier(const string& modifier) -{ - if (!hasModifier(modifier)) +void disposition::addModifier(const string& modifier) { + + if (!hasModifier(modifier)) { m_modifiers.push_back(utility::stringUtils::toLower(modifier)); + } } -void disposition::removeModifier(const string& modifier) -{ +void disposition::removeModifier(const string& modifier) { + const string modifierLC = utility::stringUtils::toLower(modifier); for (std::vector ::iterator it = m_modifiers.begin() ; - it != m_modifiers.end() ; ++it) - { - if (*it == modifierLC) - { + it != m_modifiers.end() ; ++it) { + + if (*it == modifierLC) { m_modifiers.erase(it); break; } @@ -144,37 +149,42 @@ void disposition::removeModifier(const string& modifier) } -void disposition::removeAllModifiers() -{ +void disposition::removeAllModifiers() { + m_modifiers.clear(); } -bool disposition::hasModifier(const string& modifier) const -{ +bool disposition::hasModifier(const string& modifier) const { + const string modifierLC = utility::stringUtils::toLower(modifier); for (std::vector ::const_iterator it = m_modifiers.begin() ; - it != m_modifiers.end() ; ++it) - { - if (*it == modifierLC) - return (true); + it != m_modifiers.end() ; ++it) { + + if (*it == modifierLC) { + return true; + } } - return (false); + return false; } -const std::vector disposition::getModifierList() const -{ - return (m_modifiers); +const std::vector disposition::getModifierList() const { + + return m_modifiers; } -void disposition::parseImpl - (const parsingContext& /* ctx */, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void disposition::parseImpl( + const parsingContext& /* ctx */, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + // disposition-mode ";" disposition-type // [ "/" disposition-modifier *( "," disposition-modifier ) ] // @@ -182,105 +192,116 @@ void disposition::parseImpl size_t pos = position; - while (pos < end && parserHelpers::isSpace(buffer[pos])) + while (pos < end && parserHelpers::isSpace(buffer[pos])) { ++pos; + } // -- disposition-mode const size_t modeStart = pos; size_t modeEnd = pos; - while (pos < end && buffer[pos] != ';') - { + while (pos < end && buffer[pos] != ';') { ++modeEnd; ++pos; } - while (modeEnd > modeStart && parserHelpers::isSpace(buffer[modeEnd - 1])) + while (modeEnd > modeStart && parserHelpers::isSpace(buffer[modeEnd - 1])) { --modeEnd; + } const string mode = string(buffer.begin() + modeStart, buffer.begin() + modeEnd); const size_t slash = mode.find('/'); - if (slash != string::npos) - { + if (slash != string::npos) { + m_actionMode = string(mode.begin(), mode.begin() + slash); m_sendingMode = string(mode.begin() + slash + 1, mode.end()); - } - else - { + + } else { + m_actionMode = mode; m_sendingMode.clear(); } - if (pos < end) - { + if (pos < end) { // Skip ';' ++pos; } - while (pos < end && parserHelpers::isSpace(buffer[pos])) + while (pos < end && parserHelpers::isSpace(buffer[pos])) { ++pos; + } // -- disposition-type const size_t typeStart = pos; size_t typeEnd = pos; - while (pos < end && buffer[pos] != '/') - { + while (pos < end && buffer[pos] != '/') { ++typeEnd; ++pos; } - while (typeEnd > typeStart && parserHelpers::isSpace(buffer[typeEnd - 1])) + while (typeEnd > typeStart && parserHelpers::isSpace(buffer[typeEnd - 1])) { --typeEnd; + } m_type = string(buffer.begin() + typeStart, buffer.begin() + typeEnd); m_modifiers.clear(); - if (pos < end) // modifiers follow - { + if (pos < end) { // modifiers follow + // Skip '/' ++pos; - while (pos < end) - { - while (pos < end && parserHelpers::isSpace(buffer[pos])) + while (pos < end) { + + while (pos < end && parserHelpers::isSpace(buffer[pos])) { ++pos; + } const size_t modifierStart = pos; size_t modifierEnd = pos; - while (pos < end && buffer[pos] != ',') - { + while (pos < end && buffer[pos] != ',') { ++modifierEnd; ++pos; } - while (modifierEnd > modifierStart && parserHelpers::isSpace(buffer[modifierEnd - 1])) + while (modifierEnd > modifierStart && parserHelpers::isSpace(buffer[modifierEnd - 1])) { --modifierEnd; + } - if (modifierEnd > modifierStart) - { - m_modifiers.push_back(string(buffer.begin() + modifierStart, - buffer.begin() + modifierEnd)); + if (modifierEnd > modifierStart) { + + m_modifiers.push_back( + string( + buffer.begin() + modifierStart, + buffer.begin() + modifierEnd + ) + ); } // Skip ',' - if (pos < end) + if (pos < end) { ++pos; + } } } - if (newPosition) + if (newPosition) { *newPosition = pos; + } } -void disposition::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void disposition::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + size_t pos = curLinePos; const string actionMode = (m_actionMode.empty() ? "automatic-action" : m_actionMode); @@ -289,8 +310,7 @@ void disposition::generateImpl os << actionMode << "/" << sendingMode << ";"; pos += actionMode.length() + 1 + sendingMode.length() + 1; - if (pos > ctx.getMaxLineLength()) - { + if (pos > ctx.getMaxLineLength()) { os << NEW_LINE_SEQUENCE; pos = NEW_LINE_SEQUENCE_LENGTH; } @@ -300,18 +320,19 @@ void disposition::generateImpl os << type; pos += type.length(); - if (m_modifiers.size() >= 1) - { - for (std::vector ::size_type i = 0, n = 0 ; i < m_modifiers.size() ; ++i) - { + if (m_modifiers.size() >= 1) { + + for (std::vector ::size_type i = 0, n = 0 ; i < m_modifiers.size() ; ++i) { + const string mod = utility::stringUtils::trim(m_modifiers[i]); - if (!mod.empty()) - { - if (n == 0) + if (!mod.empty()) { + + if (n == 0) { os << "/"; - else + } else { os << ","; + } os << mod; pos += 1 + mod.length(); @@ -321,8 +342,9 @@ void disposition::generateImpl } } - if (newLinePos) + if (newLinePos) { *newLinePos = pos; + } } diff --git a/src/vmime/disposition.hpp b/src/vmime/disposition.hpp index 7322c21d..d4b023bf 100644 --- a/src/vmime/disposition.hpp +++ b/src/vmime/disposition.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,19 +31,22 @@ #include -namespace vmime -{ +namespace vmime { /** Disposition - from RFC-3798 (basic type). */ +class VMIME_EXPORT disposition : public headerFieldValue { -class VMIME_EXPORT disposition : public headerFieldValue -{ public: disposition(); - disposition(const string& actionMode, const string& sendingMode, const string& type, const string& modifier); + disposition( + const string& actionMode, + const string& sendingMode, + const string& type, + const string& modifier + ); shared_ptr clone() const; @@ -137,18 +140,20 @@ private: protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; @@ -156,4 +161,3 @@ protected: #endif // VMIME_DISPOSITION_HPP_INCLUDED - diff --git a/src/vmime/emailAddress.cpp b/src/vmime/emailAddress.cpp index 08c7a35b..1be678a5 100644 --- a/src/vmime/emailAddress.cpp +++ b/src/vmime/emailAddress.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,8 +31,7 @@ #include "vmime/utility/stringUtils.hpp" -namespace vmime -{ +namespace vmime { /** Decode an IDNA-encoded domain name ("xn--5rtw95l.xn--wgv71a") @@ -41,48 +40,52 @@ namespace vmime * @param idnaDomain domain name encoded with IDNA * @return decoded domain name in UTF-8 */ -static const string domainNameFromIDNA(const string& idnaDomain) -{ +static const string domainNameFromIDNA(const string& idnaDomain) { + std::ostringstream domainName; size_t p = 0; for (size_t n = idnaDomain.find('.', p) ; - (n = idnaDomain.find('.', p)) != string::npos ; p = n + 1) - { + (n = idnaDomain.find('.', p)) != string::npos ; p = n + 1) { + const string encodedPart(idnaDomain.begin() + p, idnaDomain.begin() + n); if (encodedPart.length() > 4 && encodedPart[0] == 'x' && encodedPart[1] == 'n' && - encodedPart[2] == '-' && encodedPart[3] == '-') - { + encodedPart[2] == '-' && encodedPart[3] == '-') { + string decodedPart; - charset::convert(encodedPart, decodedPart, - vmime::charsets::IDNA, vmime::charsets::UTF_8); + charset::convert( + encodedPart, decodedPart, + vmime::charsets::IDNA, vmime::charsets::UTF_8 + ); domainName << decodedPart << '.'; - } - else - { + + } else { + domainName << encodedPart << '.'; // not encoded } } - if (p < idnaDomain.length()) - { + if (p < idnaDomain.length()) { + const string encodedPart(idnaDomain.begin() + p, idnaDomain.end()); if (encodedPart.length() > 4 && encodedPart[0] == 'x' && encodedPart[1] == 'n' && - encodedPart[2] == '-' && encodedPart[3] == '-') - { + encodedPart[2] == '-' && encodedPart[3] == '-') { + string decodedPart; - charset::convert(encodedPart, decodedPart, - vmime::charsets::IDNA, vmime::charsets::UTF_8); + charset::convert( + encodedPart, decodedPart, + vmime::charsets::IDNA, vmime::charsets::UTF_8 + ); domainName << decodedPart; - } - else - { + + } else { + domainName << encodedPart; // not encoded } } @@ -97,26 +100,30 @@ static const string domainNameFromIDNA(const string& idnaDomain) * @param domainName domain name in UTF-8 * @return domain name encoded with IDNA */ -static const string domainNameToIDNA(const string& domainName) -{ +static const string domainNameToIDNA(const string& domainName) { + std::ostringstream idnaDomain; size_t p = 0; for (size_t n = domainName.find('.', p) ; - (n = domainName.find('.', p)) != string::npos ; p = n + 1) - { + (n = domainName.find('.', p)) != string::npos ; p = n + 1) { + string idnaPart; - charset::convert(string(domainName.begin() + p, domainName.begin() + n), - idnaPart, vmime::charsets::UTF_8, vmime::charsets::IDNA); + charset::convert( + string(domainName.begin() + p, domainName.begin() + n), idnaPart, + vmime::charsets::UTF_8, vmime::charsets::IDNA + ); idnaDomain << idnaPart << '.'; } - if (p < domainName.length()) - { + if (p < domainName.length()) { + string idnaPart; - charset::convert(string(domainName.begin() + p, domainName.end()), - idnaPart, vmime::charsets::UTF_8, vmime::charsets::IDNA); + charset::convert( + string(domainName.begin() + p, domainName.end()), idnaPart, + vmime::charsets::UTF_8, vmime::charsets::IDNA + ); idnaDomain << idnaPart; } @@ -127,52 +134,60 @@ static const string domainNameToIDNA(const string& domainName) -emailAddress::emailAddress() -{ +emailAddress::emailAddress() { + } emailAddress::emailAddress(const emailAddress& eml) - : component(), m_localName(eml.m_localName), m_domainName(eml.m_domainName) -{ + : component(), + m_localName(eml.m_localName), + m_domainName(eml.m_domainName) { + } -emailAddress::emailAddress(const string& email) -{ +emailAddress::emailAddress(const string& email) { + parse(email); } -emailAddress::emailAddress(const char* email) -{ +emailAddress::emailAddress(const char* email) { + parse(email); } emailAddress::emailAddress(const string& localName, const string& domainName) - : component(), m_localName(word(localName, vmime::charsets::UTF_8)), - m_domainName(word(domainName, vmime::charsets::UTF_8)) -{ + : component(), + m_localName(word(localName, vmime::charsets::UTF_8)), + m_domainName(word(domainName, vmime::charsets::UTF_8)) { + } emailAddress::emailAddress(const word& localName, const word& domainName) - : component(), m_localName(localName), m_domainName(domainName) -{ + : component(), + m_localName(localName), + m_domainName(domainName) { + } -void emailAddress::parseImpl - (const parsingContext& /* ctx */, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void emailAddress::parseImpl( + const parsingContext& /* ctx */, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + const char* const pend = buffer.data() + end; const char* const pstart = buffer.data() + position; const char* p = pstart; - enum ParserStates - { + enum ParserStates { State_Before, State_LocalPartStart, State_LocalPartMiddle, @@ -199,361 +214,367 @@ void emailAddress::parseImpl int commentLevel = 0; bool localPartIsRFC2047 = false; - while (p < pend && !stop) - { + while (p < pend && !stop) { + const char c = *p; - if ((localPart.str().length() + domainPart.str().length()) >= 256) - { + if ((localPart.str().length() + domainPart.str().length()) >= 256) { state = State_Error; break; } - switch (state) - { - case State_Before: + switch (state) { - if (parserHelpers::isSpace(c)) - ++p; - else - state = State_LocalPartStart; + case State_Before: - break; - - case State_LocalPartStart: - - if (c == '"') - { - state = State_LocalPartQuoted; - ++p; - } - else if (c == '=') - { - state = State_LocalPartRFC2047Start; - ++p; - } - else if (c == '(') - { - state = State_LocalPartComment; - ++commentLevel; - ++p; - } - else - { - state = State_LocalPartMiddle; - localPart << c; - ++p; - } - - break; - - case State_LocalPartComment: - - if (escapeNext) - { - escapeNext = false; - ++p; - } - else if (c == '\\') - { - escapeNext = true; - ++p; - } - else if (c == '(') - { - ++commentLevel; - ++p; - } - else if (c == ')') - { - if (--commentLevel == 0) - { - // End of comment - state = State_LocalPartMiddle; + if (parserHelpers::isSpace(c)) { + ++p; + } else { + state = State_LocalPartStart; } - ++p; - } - else - { - // Comment continues - ++p; - } + break; - break; + case State_LocalPartStart: - case State_LocalPartQuoted: + if (c == '"') { - if (escapeNext) - { - escapeNext = false; + state = State_LocalPartQuoted; + ++p; - if (c == '"' || c == '\\') - { + } else if (c == '=') { + + state = State_LocalPartRFC2047Start; + ++p; + + } else if (c == '(') { + + state = State_LocalPartComment; + ++commentLevel; + ++p; + + } else { + + state = State_LocalPartMiddle; localPart << c; ++p; } - else - { - // This char cannot be escaped - state = State_Error; + + break; + + case State_LocalPartComment: + + if (escapeNext) { + + escapeNext = false; + ++p; + + } else if (c == '\\') { + + escapeNext = true; + ++p; + + } else if (c == '(') { + + ++commentLevel; + ++p; + + } else if (c == ')') { + + if (--commentLevel == 0) { + // End of comment + state = State_LocalPartMiddle; + } + + ++p; + + } else { + + // Comment continues + ++p; } - } - else if (c == '"') - { - // End of quoted string - state = State_LocalPartMiddle; - ++p; - } - else if (c == '\\') - { - escapeNext = true; - ++p; - } - else - { - localPart << c; - ++p; - } - break; + break; - case State_LocalPartRFC2047Start: + case State_LocalPartQuoted: - if (c == '?') - { - state = State_LocalPartRFC2047Middle; - localPart << "=?"; - localPartIsRFC2047 = true; - ++p; - } - else - { - state = State_LocalPartMiddle; - localPart << '='; - localPart << c; - ++p; - } + if (escapeNext) { - break; + escapeNext = false; - case State_LocalPartMiddle: + if (c == '"' || c == '\\') { - if (c == '.') - { - prevIsDot = true; - localPart << c; - ++p; - } - else if (c == '"' && prevIsDot) - { - prevIsDot = false; - state = State_LocalPartQuoted; - ++p; - } - else if (c == '(') - { - // By allowing comments anywhere in the local part, - // we are more permissive than RFC-2822 - state = State_LocalPartComment; - ++commentLevel; - ++p; - } - else if (c == '@') - { - atFound = true; - state = State_DomainPartStart; - ++p; - } - else if (parserHelpers::isSpace(c)) - { - // Allow not specifying domain part - state = State_End; - } - else - { - prevIsDot = false; - localPart << c; - ++p; - } + localPart << c; + ++p; - break; + } else { - case State_LocalPartRFC2047Middle: + // This char cannot be escaped + state = State_Error; + } - if (c == '?') - { - state = State_LocalPartRFC2047MiddleQM; - ++p; - } - else - { - localPart << c; - ++p; - } + } else if (c == '"') { - break; + // End of quoted string + state = State_LocalPartMiddle; + ++p; - case State_LocalPartRFC2047MiddleQM: + } else if (c == '\\') { - if (c == '=') - { - // End of RFC-2047 encoded word - state = State_LocalPartRFC2047End; - localPart << "?="; - ++p; - } - else - { - state = State_LocalPartRFC2047Middle; - localPart << '?'; - localPart << c; - ++p; - } + escapeNext = true; + ++p; - break; + } else { - case State_LocalPartRFC2047End: + localPart << c; + ++p; + } - if (c == '@') - { - atFound = true; - state = State_DomainPartStart; - ++p; - } - else - { - state = State_End; - } + break; - break; + case State_LocalPartRFC2047Start: - case State_DomainPartStart: + if (c == '?') { - if (c == '(') - { - state = State_DomainPartComment; - ++commentLevel; - ++p; - } - else - { - state = State_DomainPartMiddle; - domainPart << c; - ++p; - } + state = State_LocalPartRFC2047Middle; + localPart << "=?"; + localPartIsRFC2047 = true; + ++p; - break; + } else { - case State_DomainPartMiddle: + state = State_LocalPartMiddle; + localPart << '='; + localPart << c; + ++p; + } - if (parserHelpers::isSpace(c)) - { - state = State_End; - } - else if (c == '(') - { - // By allowing comments anywhere in the domain part, - // we are more permissive than RFC-2822 - state = State_DomainPartComment; - ++commentLevel; - ++p; - } - else - { - domainPart << c; - ++p; - } + break; - break; + case State_LocalPartMiddle: - case State_DomainPartComment: + if (c == '.') { + + prevIsDot = true; + localPart << c; + ++p; + + } else if (c == '"' && prevIsDot) { + + prevIsDot = false; + state = State_LocalPartQuoted; + ++p; + + } else if (c == '(') { + + // By allowing comments anywhere in the local part, + // we are more permissive than RFC-2822 + state = State_LocalPartComment; + ++commentLevel; + ++p; + + } else if (c == '@') { + + atFound = true; + state = State_DomainPartStart; + ++p; + + } else if (parserHelpers::isSpace(c)) { + + // Allow not specifying domain part + state = State_End; + + } else { + + prevIsDot = false; + localPart << c; + ++p; + } + + break; + + case State_LocalPartRFC2047Middle: + + if (c == '?') { + + state = State_LocalPartRFC2047MiddleQM; + ++p; + + } else { + + localPart << c; + ++p; + } + + break; + + case State_LocalPartRFC2047MiddleQM: + + if (c == '=') { + + // End of RFC-2047 encoded word + state = State_LocalPartRFC2047End; + localPart << "?="; + ++p; + + } else { + + state = State_LocalPartRFC2047Middle; + localPart << '?'; + localPart << c; + ++p; + } + + break; + + case State_LocalPartRFC2047End: + + if (c == '@') { + + atFound = true; + state = State_DomainPartStart; + ++p; + + } else { + + state = State_End; + } + + break; + + case State_DomainPartStart: + + if (c == '(') { + + state = State_DomainPartComment; + ++commentLevel; + ++p; + + } else { - if (escapeNext) - { - escapeNext = false; - ++p; - } - else if (c == '\\') - { - escapeNext = true; - ++p; - } - else if (c == '(') - { - ++commentLevel; - ++p; - } - else if (c == ')') - { - if (--commentLevel == 0) - { - // End of comment state = State_DomainPartMiddle; + domainPart << c; + ++p; } - ++p; - } - else - { - // Comment continues - ++p; - } + break; - break; + case State_DomainPartMiddle: - case State_End: - case State_Error: + if (parserHelpers::isSpace(c)) { - stop = true; - break; + state = State_End; + + } else if (c == '(') { + + // By allowing comments anywhere in the domain part, + // we are more permissive than RFC-2822 + state = State_DomainPartComment; + ++commentLevel; + ++p; + + } else { + + domainPart << c; + ++p; + } + + break; + + case State_DomainPartComment: + + if (escapeNext) { + + escapeNext = false; + ++p; + + } else if (c == '\\') { + + escapeNext = true; + ++p; + + } else if (c == '(') { + + ++commentLevel; + ++p; + + } else if (c == ')') { + + if (--commentLevel == 0) { + + // End of comment + state = State_DomainPartMiddle; + } + + ++p; + + } else { + + // Comment continues + ++p; + } + + break; + + case State_End: + case State_Error: + + stop = true; + break; } } - if (p == pend && state != State_Error) - { - if (state == State_DomainPartMiddle) + if (p == pend && state != State_Error) { + + if (state == State_DomainPartMiddle) { state = State_End; - else if (state == State_LocalPartMiddle) + } else if (state == State_LocalPartMiddle) { state = State_End; // allow not specifying domain part + } } - if (state != State_End) - { + if (state != State_End) { + m_localName = word("invalid", vmime::charsets::UTF_8); m_domainName = word("invalid", vmime::charsets::UTF_8); - } - else - { - // If the domain part is missing, use local host name - if (domainPart.str().empty() && !atFound) - domainPart << platform::getHandler()->getHostName(); - if (localPartIsRFC2047) + } else { + + // If the domain part is missing, use local host name + if (domainPart.str().empty() && !atFound) { + domainPart << platform::getHandler()->getHostName(); + } + + if (localPartIsRFC2047) { m_localName.parse(localPart.str()); - else + } else { m_localName = word(localPart.str(), vmime::charsets::UTF_8); + } m_domainName = word(domainNameFromIDNA(domainPart.str()), vmime::charsets::UTF_8); } setParsedBounds(position, p - pend); - if (newPosition) + if (newPosition) { *newPosition = p - pend; + } } -void emailAddress::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void emailAddress::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + string localPart, domainPart; if (ctx.getInternationalizedEmailSupport() && (!utility::stringUtils::is7bit(m_localName.getBuffer()) || - !utility::stringUtils::is7bit(m_domainName.getBuffer()))) - { + !utility::stringUtils::is7bit(m_domainName.getBuffer()))) { + // Local part string localPartUTF8(m_localName.getConvertedText(vmime::charsets::UTF_8)); word localPartWord(localPartUTF8, vmime::charsets::UTF_8); @@ -563,9 +584,9 @@ void emailAddress::generateImpl // Domain part domainPart = m_domainName.getConvertedText(vmime::charsets::UTF_8); - } - else - { + + } else { + // Local part vmime::utility::outputStreamStringAdapter os(localPart); m_localName.generate(ctx, os, 0, NULL, text::QUOTE_IF_NEEDED, NULL); @@ -578,8 +599,8 @@ void emailAddress::generateImpl << "@" << domainPart; - if (newLinePos) - { + if (newLinePos) { + *newLinePos = curLinePos + localPart.length() + 1 // @ @@ -588,21 +609,21 @@ void emailAddress::generateImpl } -bool emailAddress::operator==(const class emailAddress& eml) const -{ - return (m_localName == eml.m_localName && - m_domainName == eml.m_domainName); +bool emailAddress::operator==(const class emailAddress& eml) const { + + return m_localName == eml.m_localName && + m_domainName == eml.m_domainName; } -bool emailAddress::operator!=(const class emailAddress& eml) const -{ +bool emailAddress::operator!=(const class emailAddress& eml) const { + return !(*this == eml); } -void emailAddress::copyFrom(const component& other) -{ +void emailAddress::copyFrom(const component& other) { + const emailAddress& source = dynamic_cast (other); m_localName = source.m_localName; @@ -610,57 +631,57 @@ void emailAddress::copyFrom(const component& other) } -emailAddress& emailAddress::operator=(const emailAddress& other) -{ +emailAddress& emailAddress::operator=(const emailAddress& other) { + copyFrom(other); - return (*this); + return *this; } -shared_ptr emailAddress::clone() const -{ +shared_ptr emailAddress::clone() const { + return make_shared (*this); } -const word& emailAddress::getLocalName() const -{ +const word& emailAddress::getLocalName() const { + return m_localName; } -void emailAddress::setLocalName(const word& localName) -{ +void emailAddress::setLocalName(const word& localName) { + m_localName = localName; } -const word& emailAddress::getDomainName() const -{ +const word& emailAddress::getDomainName() const { + return m_domainName; } -void emailAddress::setDomainName(const word& domainName) -{ +void emailAddress::setDomainName(const word& domainName) { + m_domainName = domainName; } -const std::vector > emailAddress::getChildComponents() -{ +const std::vector > emailAddress::getChildComponents() { + return std::vector >(); } -bool emailAddress::isEmpty() const -{ +bool emailAddress::isEmpty() const { + return m_localName.isEmpty(); } -const string emailAddress::toString() const -{ +const string emailAddress::toString() const { + std::ostringstream oss; utility::outputStreamAdapter adapter(oss); @@ -673,8 +694,8 @@ const string emailAddress::toString() const } -const text emailAddress::toText() const -{ +const text emailAddress::toText() const { + text txt; txt.appendWord(make_shared (m_localName)); txt.appendWord(make_shared ("@", vmime::charsets::US_ASCII)); diff --git a/src/vmime/emailAddress.hpp b/src/vmime/emailAddress.hpp index 30ee24ab..78249967 100644 --- a/src/vmime/emailAddress.hpp +++ b/src/vmime/emailAddress.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,15 +29,13 @@ #include "vmime/text.hpp" -namespace vmime -{ +namespace vmime { /** An email address: local name and domain name (basic type). */ +class VMIME_EXPORT emailAddress : public component { -class VMIME_EXPORT emailAddress : public component -{ public: emailAddress(); @@ -114,18 +112,20 @@ public: using component::generate; // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/emptyContentHandler.cpp b/src/vmime/emptyContentHandler.cpp index e0f191f3..3cf7965b 100644 --- a/src/vmime/emptyContentHandler.cpp +++ b/src/vmime/emptyContentHandler.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -24,92 +24,101 @@ #include "vmime/emptyContentHandler.hpp" -namespace vmime -{ +namespace vmime { -emptyContentHandler::emptyContentHandler() -{ +emptyContentHandler::emptyContentHandler() { + } -shared_ptr emptyContentHandler::clone() const -{ +shared_ptr emptyContentHandler::clone() const { + return make_shared (); } -void emptyContentHandler::generate(utility::outputStream& /* os */, const vmime::encoding& /* enc */, - const size_t /* maxLineLength */) const -{ +void emptyContentHandler::generate( + utility::outputStream& /* os */, + const vmime::encoding& /* enc */, + const size_t /* maxLineLength */ +) const { + // Nothing to do. } -void emptyContentHandler::extract(utility::outputStream& /* os */, +void emptyContentHandler::extract( + utility::outputStream& /* os */, utility::progressListener* progress) const { - if (progress) + if (progress) { progress->start(0); + } // Nothing to do. - if (progress) + if (progress) { progress->stop(0); + } } -void emptyContentHandler::extractRaw(utility::outputStream& /* os */, - utility::progressListener* progress) const -{ - if (progress) +void emptyContentHandler::extractRaw( + utility::outputStream& /* os */, + utility::progressListener* progress +) const { + + if (progress) { progress->start(0); + } // Nothing to do. - if (progress) + if (progress) { progress->stop(0); + } } -size_t emptyContentHandler::getLength() const -{ - return (0); +size_t emptyContentHandler::getLength() const { + + return 0; } -bool emptyContentHandler::isEmpty() const -{ - return (true); -} +bool emptyContentHandler::isEmpty() const { - -bool emptyContentHandler::isEncoded() const -{ - return (false); -} - - -const vmime::encoding& emptyContentHandler::getEncoding() const -{ - return (NO_ENCODING); -} - - -bool emptyContentHandler::isBuffered() const -{ return true; } -void emptyContentHandler::setContentTypeHint(const mediaType& type) -{ +bool emptyContentHandler::isEncoded() const { + + return false; +} + + +const vmime::encoding& emptyContentHandler::getEncoding() const { + + return NO_ENCODING; +} + + +bool emptyContentHandler::isBuffered() const { + + return true; +} + + +void emptyContentHandler::setContentTypeHint(const mediaType& type) { + m_contentType = type; } -const mediaType emptyContentHandler::getContentTypeHint() const -{ +const mediaType emptyContentHandler::getContentTypeHint() const { + return m_contentType; } diff --git a/src/vmime/emptyContentHandler.hpp b/src/vmime/emptyContentHandler.hpp index 369a4206..b7e08978 100644 --- a/src/vmime/emptyContentHandler.hpp +++ b/src/vmime/emptyContentHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,22 +28,32 @@ #include "vmime/contentHandler.hpp" -namespace vmime -{ +namespace vmime { -class VMIME_EXPORT emptyContentHandler : public contentHandler -{ +class VMIME_EXPORT emptyContentHandler : public contentHandler { + public: emptyContentHandler(); shared_ptr clone() const; - void generate(utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength = lineLengthLimits::infinite) const; + void generate( + utility::outputStream& os, + const vmime::encoding& enc, + const size_t maxLineLength = lineLengthLimits::infinite + ) const; - void extract(utility::outputStream& os, utility::progressListener* progress = NULL) const; - void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const; + void extract( + utility::outputStream& os, + utility::progressListener* progress = NULL + ) const; + + void extractRaw( + utility::outputStream& os, + utility::progressListener* progress = NULL + ) const; size_t getLength() const; diff --git a/src/vmime/encoding.cpp b/src/vmime/encoding.cpp index 649bee79..23814a67 100644 --- a/src/vmime/encoding.cpp +++ b/src/vmime/encoding.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,118 +30,140 @@ #include -namespace vmime -{ +namespace vmime { encoding::encoding() : m_name(encodingTypes::SEVEN_BIT), - m_usage(USAGE_UNKNOWN) -{ + m_usage(USAGE_UNKNOWN) { + } encoding::encoding(const string& name) : m_name(utility::stringUtils::toLower(name)), - m_usage(USAGE_UNKNOWN) -{ + m_usage(USAGE_UNKNOWN) { + } encoding::encoding(const string& name, const EncodingUsage usage) : m_name(utility::stringUtils::toLower(name)), - m_usage(usage) -{ + m_usage(usage) { + } encoding::encoding(const encoding& enc) - : headerFieldValue(), m_name(enc.m_name), m_usage(enc.m_usage) -{ + : headerFieldValue(), + m_name(enc.m_name), + m_usage(enc.m_usage) { } -void encoding::parseImpl - (const parsingContext& /* ctx */, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void encoding::parseImpl( + const parsingContext& /* ctx */, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + m_usage = USAGE_UNKNOWN; - m_name = utility::stringUtils::toLower(utility::stringUtils::trim - (utility::stringUtils::unquote(utility::stringUtils::trim - (string(buffer.begin() + position, buffer.begin() + end))))); + m_name = utility::stringUtils::toLower( + utility::stringUtils::trim( + utility::stringUtils::unquote( + utility::stringUtils::trim( + string(buffer.begin() + position, buffer.begin() + end) + ) + ) + ) + ); - if (m_name.empty()) + if (m_name.empty()) { m_name = encodingTypes::SEVEN_BIT; // assume default "7-bit" + } setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void encoding::generateImpl - (const generationContext& /* ctx */, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void encoding::generateImpl( + const generationContext& /* ctx */, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + os << m_name; - if (newLinePos) + if (newLinePos) { *newLinePos = curLinePos + m_name.length(); + } } -shared_ptr encoding::getEncoder() const -{ +shared_ptr encoding::getEncoder() const { + shared_ptr encoder = utility::encoder::encoderFactory::getInstance()->create(generate()); // FIXME: this should not be here (move me into QP encoder instead?) - if (m_usage == USAGE_TEXT && m_name == encodingTypes::QUOTED_PRINTABLE) + if (m_usage == USAGE_TEXT && m_name == encodingTypes::QUOTED_PRINTABLE) { encoder->getProperties()["text"] = true; + } return encoder; } -encoding& encoding::operator=(const encoding& other) -{ +encoding& encoding::operator=(const encoding& other) { + copyFrom(other); return (*this); } -encoding& encoding::operator=(const string& name) -{ +encoding& encoding::operator=(const string& name) { + m_name = utility::stringUtils::toLower(name); m_usage = USAGE_UNKNOWN; - return (*this); + + return *this; } -bool encoding::operator==(const encoding& value) const -{ - return (utility::stringUtils::toLower(m_name) == value.m_name); +bool encoding::operator==(const encoding& value) const { + + return utility::stringUtils::toLower(m_name) == value.m_name; } -bool encoding::operator!=(const encoding& value) const -{ +bool encoding::operator!=(const encoding& value) const { + return !(*this == value); } -const encoding encoding::decideImpl - (const string::const_iterator begin, const string::const_iterator end) -{ +const encoding encoding::decideImpl( + const string::const_iterator begin, + const string::const_iterator end +) { + const string::difference_type length = end - begin; - const string::difference_type count = std::count_if - (begin, end, std::bind2nd(std::less(), 127)); + const string::difference_type count = std::count_if( + begin, end, + std::bind2nd(std::less(), 127) + ); // All is in 7-bit US-ASCII --> 7-bit (or Quoted-Printable...) - if (length == count) - { + if (length == count) { + // Now, we check if there is any line with more than // "lineLengthLimits::convenient" characters (7-bit requires that) string::const_iterator p = begin; @@ -149,49 +171,51 @@ const encoding encoding::decideImpl const size_t maxLen = lineLengthLimits::convenient; size_t len = 0; - for ( ; p != end && len <= maxLen ; ) - { - if (*p == '\n') - { + for ( ; p != end && len <= maxLen ; ) { + + if (*p == '\n') { + len = 0; ++p; // May or may not need to be encoded, we don't take // any risk (avoid problems with SMTP) - if (p != end && *p == '.') + if (p != end && *p == '.') { len = maxLen + 1; - } - else - { + } + + } else { + ++len; ++p; } } - if (len > maxLen) - return (encoding(encodingTypes::QUOTED_PRINTABLE)); - else - return (encoding(encodingTypes::SEVEN_BIT)); - } + if (len > maxLen) { + return encoding(encodingTypes::QUOTED_PRINTABLE); + } else { + return encoding(encodingTypes::SEVEN_BIT); + } + // Less than 20% non US-ASCII --> Quoted-Printable - else if ((length - count) <= length / 5) - { - return (encoding(encodingTypes::QUOTED_PRINTABLE)); - } + } else if ((length - count) <= length / 5) { + + return encoding(encodingTypes::QUOTED_PRINTABLE); + // Otherwise --> Base64 - else - { - return (encoding(encodingTypes::BASE64)); + } else { + + return encoding(encodingTypes::BASE64); } } -bool encoding::shouldReencode() const -{ +bool encoding::shouldReencode() const { + if (m_name == encodingTypes::BASE64 || m_name == encodingTypes::QUOTED_PRINTABLE || - m_name == encodingTypes::UUENCODE) - { + m_name == encodingTypes::UUENCODE) { + return false; } @@ -199,18 +223,21 @@ bool encoding::shouldReencode() const } -const encoding encoding::decide - (const shared_ptr & data, const EncodingUsage usage) -{ +const encoding encoding::decide( + const shared_ptr & data, + const EncodingUsage usage +) { + // Do not re-encode data if it is already encoded - if (data->isEncoded() && !data->getEncoding().shouldReencode()) + if (data->isEncoded() && !data->getEncoding().shouldReencode()) { return data->getEncoding(); + } encoding enc; if (usage == USAGE_TEXT && data->isBuffered() && - data->getLength() > 0 && data->getLength() < 32768) - { + data->getLength() > 0 && data->getLength() < 32768) { + // Extract data into temporary buffer string buffer; utility::outputStreamStringAdapter os(buffer); @@ -219,9 +246,9 @@ const encoding encoding::decide os.flush(); enc = decideImpl(buffer.begin(), buffer.end()); - } - else - { + + } else { + enc = encoding(encodingTypes::BASE64); } @@ -231,19 +258,23 @@ const encoding encoding::decide } -const encoding encoding::decide(const shared_ptr & data, - const charset& chset, const EncodingUsage usage) -{ - // Do not re-encode data if it is already encoded - if (data->isEncoded() && !data->getEncoding().shouldReencode()) - return data->getEncoding(); +const encoding encoding::decide( + const shared_ptr & data, + const charset& chset, + const EncodingUsage usage +) { + + // Do not re-encode data if it is already encoded + if (data->isEncoded() && !data->getEncoding().shouldReencode()) { + return data->getEncoding(); + } + + if (usage == USAGE_TEXT) { - if (usage == USAGE_TEXT) - { encoding recEncoding; - if (chset.getRecommendedEncoding(recEncoding)) - { + if (chset.getRecommendedEncoding(recEncoding)) { + recEncoding.setUsage(usage); return recEncoding; } @@ -253,46 +284,46 @@ const encoding encoding::decide(const shared_ptr & data, } -shared_ptr encoding::clone() const -{ +shared_ptr encoding::clone() const { + return make_shared (*this); } -void encoding::copyFrom(const component& other) -{ +void encoding::copyFrom(const component& other) { + const encoding& e = dynamic_cast (other); m_name = e.m_name; } -const string& encoding::getName() const -{ - return (m_name); +const string& encoding::getName() const { + + return m_name; } -void encoding::setName(const string& name) -{ +void encoding::setName(const string& name) { + m_name = name; } -encoding::EncodingUsage encoding::getUsage() const -{ +encoding::EncodingUsage encoding::getUsage() const { + return m_usage; } -void encoding::setUsage(const EncodingUsage usage) -{ +void encoding::setUsage(const EncodingUsage usage) { + m_usage = usage; } -const std::vector > encoding::getChildComponents() -{ +const std::vector > encoding::getChildComponents() { + return std::vector >(); } diff --git a/src/vmime/encoding.hpp b/src/vmime/encoding.hpp index 48973daa..2ff17ef6 100644 --- a/src/vmime/encoding.hpp +++ b/src/vmime/encoding.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,8 +31,7 @@ #include "vmime/utility/encoder/encoder.hpp" -namespace vmime -{ +namespace vmime { class contentHandler; @@ -40,13 +39,12 @@ class contentHandler; /** Content encoding (basic type). */ +class VMIME_EXPORT encoding : public headerFieldValue { -class VMIME_EXPORT encoding : public headerFieldValue -{ public: - enum EncodingUsage - { + enum EncodingUsage { + USAGE_UNKNOWN, USAGE_TEXT, /**< Use for body text. */ USAGE_BINARY_DATA /**< Use for attachment, image... */ @@ -99,7 +97,10 @@ public: * @param usage context of use of data * @return suitable encoding for specified data */ - static const encoding decide(const shared_ptr & data, const EncodingUsage usage = USAGE_BINARY_DATA); + static const encoding decide( + const shared_ptr & data, + const EncodingUsage usage = USAGE_BINARY_DATA + ); /** Decide which encoding to use based on the specified data and charset. * @@ -108,7 +109,11 @@ public: * @param usage context of use of data * @return suitable encoding for specified data and charset */ - static const encoding decide(const shared_ptr & data, const charset& chset, const EncodingUsage usage = USAGE_BINARY_DATA); + static const encoding decide( + const shared_ptr & data, + const charset& chset, + const EncodingUsage usage = USAGE_BINARY_DATA + ); shared_ptr clone() const; @@ -144,23 +149,28 @@ private: * @param end end iterator in buffer * @return suitable encoding for specified data */ - static const encoding decideImpl(const string::const_iterator begin, const string::const_iterator end); + static const encoding decideImpl( + const string::const_iterator begin, + const string::const_iterator end + ); protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/exception.cpp b/src/vmime/exception.cpp index b96b7c37..fb9dea94 100644 --- a/src/vmime/exception.cpp +++ b/src/vmime/exception.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,31 +35,31 @@ const exception exception::NO_EXCEPTION; exception::exception() - : std::runtime_error(""), m_other(NULL) -{ + : std::runtime_error(""), m_other(NULL) { + } exception::exception(const string& what, const exception& other) - : std::runtime_error(what), m_other(&other != &NO_EXCEPTION ? other.clone() : NULL) -{ + : std::runtime_error(what), m_other(&other != &NO_EXCEPTION ? other.clone() : NULL) { + } exception::exception(const exception& e) - : std::runtime_error(e.what()), m_other(e.m_other == NULL ? NULL : e.m_other->clone()) -{ + : std::runtime_error(e.what()), m_other(e.m_other == NULL ? NULL : e.m_other->clone()) { + } -exception::~exception() throw() -{ - delete (m_other); +exception::~exception() throw() { + + delete m_other; } -void exception::chainException(const exception& other) -{ +void exception::chainException(const exception& other) { + exception* e = other.clone(); delete m_other; @@ -67,27 +67,26 @@ void exception::chainException(const exception& other) } -const exception* exception::other() const throw() -{ - return (m_other); +const exception* exception::other() const throw() { + + return m_other; } -const char* exception::name() const throw() -{ +const char* exception::name() const throw() { + return "exception"; } -exception* exception::clone() const -{ +exception* exception::clone() const { + return new exception(*this); } -namespace exceptions -{ +namespace exceptions { // diff --git a/src/vmime/exception.hpp b/src/vmime/exception.hpp index 9dcbf641..da0ec246 100644 --- a/src/vmime/exception.hpp +++ b/src/vmime/exception.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,15 +32,13 @@ #include "vmime/utility/path.hpp" -namespace vmime -{ +namespace vmime { /** Base class for VMime exceptions. */ +class VMIME_EXPORT exception : public std::runtime_error { -class VMIME_EXPORT exception : public std::runtime_error -{ private: exception* m_other; @@ -87,13 +85,11 @@ protected: /** List of all VMime exceptions. */ - -namespace exceptions -{ +namespace exceptions { -class VMIME_EXPORT bad_field_value_type : public vmime::exception -{ +class VMIME_EXPORT bad_field_value_type : public vmime::exception { + public: bad_field_value_type(const string& fieldName, const exception& other = NO_EXCEPTION); @@ -104,8 +100,8 @@ public: }; -class VMIME_EXPORT charset_conv_error : public vmime::exception -{ +class VMIME_EXPORT charset_conv_error : public vmime::exception { + public: charset_conv_error(const string& what = "", const exception& other = NO_EXCEPTION); @@ -116,8 +112,8 @@ public: }; -class VMIME_EXPORT illegal_byte_sequence_for_charset : public vmime::exception -{ +class VMIME_EXPORT illegal_byte_sequence_for_charset : public vmime::exception { + public: illegal_byte_sequence_for_charset(const string& what = "", const exception& other = NO_EXCEPTION); @@ -130,9 +126,8 @@ public: /** No encoder has been found for the specified encoding name. */ +class VMIME_EXPORT no_encoder_available : public vmime::exception { -class VMIME_EXPORT no_encoder_available : public vmime::exception -{ public: no_encoder_available(const string& name, const exception& other = NO_EXCEPTION); @@ -145,9 +140,8 @@ public: /** No algorithm has been found for the specified name. */ +class VMIME_EXPORT no_digest_algorithm_available : public vmime::exception { -class VMIME_EXPORT no_digest_algorithm_available : public vmime::exception -{ public: no_digest_algorithm_available(const string& name, const exception& other = NO_EXCEPTION); @@ -158,8 +152,8 @@ public: }; -class VMIME_EXPORT no_such_field : public vmime::exception -{ +class VMIME_EXPORT no_such_field : public vmime::exception { + public: no_such_field(const exception& other = NO_EXCEPTION); @@ -170,8 +164,8 @@ public: }; -class VMIME_EXPORT no_such_part : public vmime::exception -{ +class VMIME_EXPORT no_such_part : public vmime::exception { + public: no_such_part(const exception& other = NO_EXCEPTION); @@ -182,8 +176,8 @@ public: }; -class VMIME_EXPORT no_such_message_id : public vmime::exception -{ +class VMIME_EXPORT no_such_message_id : public vmime::exception { + public: no_such_message_id(const exception& other = NO_EXCEPTION); @@ -194,8 +188,8 @@ public: }; -class VMIME_EXPORT open_file_error : public vmime::exception -{ +class VMIME_EXPORT open_file_error : public vmime::exception { + public: open_file_error(const exception& other = NO_EXCEPTION); @@ -206,8 +200,8 @@ public: }; -class VMIME_EXPORT no_factory_available : public vmime::exception -{ +class VMIME_EXPORT no_factory_available : public vmime::exception { + public: no_factory_available(const exception& other = NO_EXCEPTION); @@ -218,8 +212,8 @@ public: }; -class VMIME_EXPORT no_platform_handler : public vmime::exception -{ +class VMIME_EXPORT no_platform_handler : public vmime::exception { + public: no_platform_handler(const exception& other = NO_EXCEPTION); @@ -232,9 +226,8 @@ public: /** No expeditor specified. */ +class VMIME_EXPORT no_expeditor : public vmime::exception { -class VMIME_EXPORT no_expeditor : public vmime::exception -{ public: no_expeditor(const exception& other = NO_EXCEPTION); @@ -247,9 +240,8 @@ public: /** No recipient specified. */ +class VMIME_EXPORT no_recipient : public vmime::exception { -class VMIME_EXPORT no_recipient : public vmime::exception -{ public: no_recipient(const exception& other = NO_EXCEPTION); @@ -262,9 +254,8 @@ public: /** There is no property with that name in the set. */ +class VMIME_EXPORT no_such_property : public vmime::exception { -class VMIME_EXPORT no_such_property : public vmime::exception -{ public: no_such_property(const string& name, const exception& other = NO_EXCEPTION); @@ -277,9 +268,8 @@ public: /** Bad type specified when reading property. */ +class VMIME_EXPORT invalid_property_type : public vmime::exception { -class VMIME_EXPORT invalid_property_type : public vmime::exception -{ public: invalid_property_type(const exception& other = NO_EXCEPTION); @@ -292,9 +282,8 @@ public: /** Bad argument was passed to the function. */ +class VMIME_EXPORT invalid_argument : public vmime::exception { -class VMIME_EXPORT invalid_argument : public vmime::exception -{ public: invalid_argument(const exception& other = NO_EXCEPTION); @@ -307,9 +296,8 @@ public: /** Underlying operating system error. */ +class VMIME_EXPORT system_error : public vmime::exception { -class VMIME_EXPORT system_error : public vmime::exception -{ public: system_error(const string& what, const exception& other = NO_EXCEPTION); @@ -322,9 +310,8 @@ public: /** The URL is malformed. */ +class VMIME_EXPORT malformed_url : public vmime::exception { -class VMIME_EXPORT malformed_url : public vmime::exception -{ public: malformed_url(const string& error, const exception& other = NO_EXCEPTION); @@ -341,9 +328,8 @@ public: /** Base class for exceptions thrown by the networking module. */ +class VMIME_EXPORT net_exception : public vmime::exception { -class VMIME_EXPORT net_exception : public vmime::exception -{ public: net_exception(const string& what, const exception& other = NO_EXCEPTION); @@ -362,9 +348,8 @@ typedef net_exception messaging_exception; /** Socket error. */ +class VMIME_EXPORT socket_exception : public net_exception { -class VMIME_EXPORT socket_exception : public net_exception -{ public: socket_exception(const string& what = "", const exception& other = NO_EXCEPTION); @@ -379,9 +364,8 @@ public: /** Socket not connected: you are trying to write to/read from a socket which * is not connected to a peer. */ +class VMIME_EXPORT socket_not_connected_exception : public socket_exception { -class VMIME_EXPORT socket_not_connected_exception : public socket_exception -{ public: socket_not_connected_exception(const string& what = "", const exception& other = NO_EXCEPTION); @@ -396,9 +380,8 @@ public: /** Error while connecting to the server: this may be a DNS resolution error * or a connection error (for example, time-out while connecting). */ +class VMIME_EXPORT connection_error : public socket_exception { -class VMIME_EXPORT connection_error : public socket_exception -{ public: connection_error(const string& what = "", const exception& other = NO_EXCEPTION); @@ -411,9 +394,8 @@ public: /** Server did not initiated the connection correctly. */ +class VMIME_EXPORT connection_greeting_error : public net_exception { -class VMIME_EXPORT connection_greeting_error : public net_exception -{ public: connection_greeting_error(const string& response, const exception& other = NO_EXCEPTION); @@ -433,9 +415,8 @@ private: /** Error while giving credentials to the server (wrong username * or password, or wrong authentication method). */ +class VMIME_EXPORT authentication_error : public net_exception { -class VMIME_EXPORT authentication_error : public net_exception -{ public: authentication_error(const string& response, const exception& other = NO_EXCEPTION); @@ -454,9 +435,8 @@ private: /** Option not supported. */ +class VMIME_EXPORT unsupported_option : public net_exception { -class VMIME_EXPORT unsupported_option : public net_exception -{ public: unsupported_option(const exception& other = NO_EXCEPTION); @@ -470,9 +450,8 @@ public: /** The current state of the object does not permit to execute the * operation (for example, you try to close a folder which is not open). */ +class VMIME_EXPORT illegal_state : public net_exception { -class VMIME_EXPORT illegal_state : public net_exception -{ public: illegal_state(const string& state, const exception& other = NO_EXCEPTION); @@ -485,9 +464,8 @@ public: /** Folder not found (does not exist). */ +class VMIME_EXPORT folder_not_found : public net_exception { -class VMIME_EXPORT folder_not_found : public net_exception -{ public: folder_not_found(const exception& other = NO_EXCEPTION); @@ -500,9 +478,8 @@ public: /** Folder is already open in the same session. */ +class VMIME_EXPORT folder_already_open : public net_exception { -class VMIME_EXPORT folder_already_open : public net_exception -{ public: folder_already_open(const exception& other = NO_EXCEPTION); @@ -515,9 +492,8 @@ public: /** Message not found (does not exist). */ +class VMIME_EXPORT message_not_found : public net_exception { -class VMIME_EXPORT message_not_found : public net_exception -{ public: message_not_found(const exception& other = NO_EXCEPTION); @@ -530,9 +506,8 @@ public: /** Operation not supported by the underlying protocol. */ +class VMIME_EXPORT operation_not_supported : public net_exception { -class VMIME_EXPORT operation_not_supported : public net_exception -{ public: operation_not_supported(const exception& other = NO_EXCEPTION); @@ -545,9 +520,8 @@ public: /** The operation timed out (time-out delay is elapsed). */ +class VMIME_EXPORT operation_timed_out : public net_exception { -class VMIME_EXPORT operation_timed_out : public net_exception -{ public: operation_timed_out(const exception& other = NO_EXCEPTION); @@ -560,9 +534,8 @@ public: /** The operation has been cancelled. */ +class VMIME_EXPORT operation_cancelled : public net_exception { -class VMIME_EXPORT operation_cancelled : public net_exception -{ public: operation_cancelled(const exception& other = NO_EXCEPTION); @@ -576,9 +549,8 @@ public: /** Must call fetchMessage() or fetchHeader() before accessing * the requested object. */ +class VMIME_EXPORT unfetched_object : public net_exception { -class VMIME_EXPORT unfetched_object : public net_exception -{ public: unfetched_object(const exception& other = NO_EXCEPTION); @@ -591,9 +563,8 @@ public: /** The service is not currently connected. */ +class VMIME_EXPORT not_connected : public net_exception { -class VMIME_EXPORT not_connected : public net_exception -{ public: not_connected(const exception& other = NO_EXCEPTION); @@ -606,9 +577,8 @@ public: /** The service is already connected (must disconnect before). */ +class VMIME_EXPORT already_connected : public net_exception { -class VMIME_EXPORT already_connected : public net_exception -{ public: already_connected(const exception& other = NO_EXCEPTION); @@ -621,9 +591,8 @@ public: /** Illegal operation: cannot run this operation on the object. */ +class VMIME_EXPORT illegal_operation : public net_exception { -class VMIME_EXPORT illegal_operation : public net_exception -{ public: illegal_operation(const string& msg = "", const exception& other = NO_EXCEPTION); @@ -636,12 +605,17 @@ public: /** Command error: operation failed (this is specific to the underlying protocol). */ +class VMIME_EXPORT command_error : public net_exception { -class VMIME_EXPORT command_error : public net_exception -{ public: - command_error(const string& command, const string& response, const string& desc = "", const exception& other = NO_EXCEPTION); + command_error( + const string& command, + const string& response, + const string& desc = "", + const exception& other = NO_EXCEPTION + ); + ~command_error() throw(); /** Return the name of the command which have thrown the exception. @@ -670,12 +644,16 @@ private: /** The server returned an invalid response. */ +class VMIME_EXPORT invalid_response : public net_exception { -class VMIME_EXPORT invalid_response : public net_exception -{ public: - invalid_response(const string& command, const string& response, const exception& other = NO_EXCEPTION); + invalid_response( + const string& command, + const string& response, + const exception& other = NO_EXCEPTION + ); + ~invalid_response() throw(); /** Return the name of the command which have thrown the exception. @@ -704,9 +682,8 @@ private: /** Partial fetch is not supported by the underlying protocol. */ +class VMIME_EXPORT partial_fetch_not_supported : public net_exception { -class VMIME_EXPORT partial_fetch_not_supported : public net_exception -{ public: partial_fetch_not_supported(const exception& other = NO_EXCEPTION); @@ -719,9 +696,8 @@ public: /** Folder name is invalid. */ +class VMIME_EXPORT invalid_folder_name : public net_exception { -class VMIME_EXPORT invalid_folder_name : public net_exception -{ public: invalid_folder_name(const string& error = "", const exception& other = NO_EXCEPTION); @@ -740,12 +716,16 @@ public: /** Base class for exceptions thrown by the filesystem features. */ +class VMIME_EXPORT filesystem_exception : public vmime::exception { -class VMIME_EXPORT filesystem_exception : public vmime::exception -{ public: - filesystem_exception(const string& what, const utility::path& path, const exception& other = NO_EXCEPTION); + filesystem_exception( + const string& what, + const utility::path& path, + const exception& other = NO_EXCEPTION + ); + ~filesystem_exception() throw(); /** Return the full path of the file have thrown the exception. @@ -765,9 +745,8 @@ private: /** File is not a directory. */ +class VMIME_EXPORT not_a_directory : public filesystem_exception { -class VMIME_EXPORT not_a_directory : public filesystem_exception -{ public: not_a_directory(const utility::path& path, const exception& other = NO_EXCEPTION); @@ -780,9 +759,8 @@ public: /** File not found. */ +class VMIME_EXPORT file_not_found : public filesystem_exception { -class VMIME_EXPORT file_not_found : public filesystem_exception -{ public: file_not_found(const utility::path& path, const exception& other = NO_EXCEPTION); @@ -798,9 +776,8 @@ public: /** Authentication exception. */ +class VMIME_EXPORT authentication_exception : public vmime::exception { -class VMIME_EXPORT authentication_exception : public vmime::exception -{ public: authentication_exception(const string& what, const exception& other = NO_EXCEPTION); @@ -813,9 +790,8 @@ public: /** The requested information cannot be provided. */ +class VMIME_EXPORT no_auth_information : public authentication_exception { -class VMIME_EXPORT no_auth_information : public authentication_exception -{ public: no_auth_information(const exception& other = NO_EXCEPTION); @@ -831,9 +807,8 @@ public: /** Base class for exceptions thrown by SASL module. */ +class VMIME_EXPORT sasl_exception : public authentication_exception { -class VMIME_EXPORT sasl_exception : public authentication_exception -{ public: sasl_exception(const string& what, const exception& other = NO_EXCEPTION); @@ -846,9 +821,8 @@ public: /** No mechanism is registered with the specified name. */ +class VMIME_EXPORT no_such_mechanism : public sasl_exception { -class VMIME_EXPORT no_such_mechanism : public sasl_exception -{ public: no_such_mechanism(const string& name, const exception& other = NO_EXCEPTION); @@ -867,9 +841,8 @@ public: /** Base class for exceptions thrown by TLS module. */ +class VMIME_EXPORT tls_exception : public vmime::exception { -class VMIME_EXPORT tls_exception : public vmime::exception -{ public: tls_exception(const string& what, const exception& other = NO_EXCEPTION); @@ -883,7 +856,6 @@ public: #endif // VMIME_HAVE_TLS_SUPPORT - } // exceptions diff --git a/src/vmime/export.hpp b/src/vmime/export.hpp index 90f0cc3a..a3b4dfbe 100644 --- a/src/vmime/export.hpp +++ b/src/vmime/export.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 diff --git a/src/vmime/fileAttachment.cpp b/src/vmime/fileAttachment.cpp index f1697519..ac755708 100644 --- a/src/vmime/fileAttachment.cpp +++ b/src/vmime/fileAttachment.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,12 +42,14 @@ #include "vmime/utility/file.hpp" -namespace vmime -{ +namespace vmime { -fileAttachment::fileAttachment(const string& filepath, const mediaType& type) -{ +fileAttachment::fileAttachment( + const string& filepath, + const mediaType& type +) { + m_type = type; setData(filepath); @@ -56,8 +58,12 @@ fileAttachment::fileAttachment(const string& filepath, const mediaType& type) } -fileAttachment::fileAttachment(const string& filepath, const mediaType& type, const text& desc) -{ +fileAttachment::fileAttachment( + const string& filepath, + const mediaType& type, + const text& desc +) { + m_type = type; m_desc = desc; @@ -67,9 +73,13 @@ fileAttachment::fileAttachment(const string& filepath, const mediaType& type, co } -fileAttachment::fileAttachment(const string& filepath, const mediaType& type, - const text& desc, const encoding& enc) -{ +fileAttachment::fileAttachment( + const string& filepath, + const mediaType& type, + const text& desc, + const encoding& enc +) { + m_type = type; m_desc = desc; @@ -79,10 +89,14 @@ fileAttachment::fileAttachment(const string& filepath, const mediaType& type, } -fileAttachment::fileAttachment(const shared_ptr & cts, const word& filename, const mediaType& type) -{ - if (!filename.isEmpty()) +fileAttachment::fileAttachment( + const shared_ptr & cts, + const word& filename, + const mediaType& type) { + + if (!filename.isEmpty()) { m_fileInfo.setFilename(filename); + } m_type = type; @@ -92,11 +106,16 @@ fileAttachment::fileAttachment(const shared_ptr & cts, const wor } -fileAttachment::fileAttachment(const shared_ptr & cts, const word& filename, - const mediaType& type, const text& desc) -{ - if (!filename.isEmpty()) +fileAttachment::fileAttachment( + const shared_ptr & cts, + const word& filename, + const mediaType& type, + const text& desc +) { + + if (!filename.isEmpty()) { m_fileInfo.setFilename(filename); + } m_type = type; m_desc = desc; @@ -107,11 +126,17 @@ fileAttachment::fileAttachment(const shared_ptr & cts, const wor } -fileAttachment::fileAttachment(const shared_ptr & cts, const word& filename, - const mediaType& type, const text& desc, const encoding& enc) -{ - if (!filename.isEmpty()) +fileAttachment::fileAttachment( + const shared_ptr & cts, + const word& filename, + const mediaType& type, + const text& desc, + const encoding& enc +) { + + if (!filename.isEmpty()) { m_fileInfo.setFilename(filename); + } m_type = type; m_desc = desc; @@ -121,34 +146,36 @@ fileAttachment::fileAttachment(const shared_ptr & cts, const wor } -void fileAttachment::setData(const string& filepath) -{ +void fileAttachment::setData(const string& filepath) { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); utility::file::path path = fsf->stringToPath(filepath); shared_ptr file = fsf->create(path); - if (!file->isFile()) + if (!file->isFile()) { throw exceptions::open_file_error(); + } - m_data = make_shared - (file->getFileReader()->getInputStream(), file->getLength()); + m_data = make_shared ( + file->getFileReader()->getInputStream(), file->getLength() + ); m_fileInfo.setFilename(path.getLastComponent()); m_fileInfo.setSize(file->getLength()); } -void fileAttachment::setData(const shared_ptr & cts) -{ +void fileAttachment::setData(const shared_ptr & cts) { + m_data = cts; m_fileInfo.setSize(cts->getLength()); } -void fileAttachment::generatePart(const shared_ptr & part) const -{ +void fileAttachment::generatePart(const shared_ptr & part) const { + defaultAttachment::generatePart(part); shared_ptr cdf = @@ -162,14 +189,14 @@ void fileAttachment::generatePart(const shared_ptr & part) const } -const fileAttachment::fileInfo& fileAttachment::getFileInfo() const -{ +const fileAttachment::fileInfo& fileAttachment::getFileInfo() const { + return m_fileInfo; } -fileAttachment::fileInfo& fileAttachment::getFileInfo() -{ +fileAttachment::fileInfo& fileAttachment::getFileInfo() { + return m_fileInfo; } @@ -180,39 +207,43 @@ fileAttachment::fileInfo& fileAttachment::getFileInfo() // fileAttachment::fileInfo::fileInfo() - : m_filename(NULL), m_size(NULL), m_creationDate(NULL), m_modifDate(NULL), m_readDate(NULL) -{ + : m_filename(NULL), + m_size(NULL), + m_creationDate(NULL), + m_modifDate(NULL), + m_readDate(NULL) { + } fileAttachment::fileInfo::~fileInfo() { - delete (m_filename); - delete (m_size); - delete (m_creationDate); - delete (m_modifDate); - delete (m_readDate); + delete m_filename; + delete m_size; + delete m_creationDate; + delete m_modifDate; + delete m_readDate; } -bool fileAttachment::fileInfo::hasFilename() const { return (m_filename != NULL); } -const word& fileAttachment::fileInfo::getFilename() const { return (*m_filename); } +bool fileAttachment::fileInfo::hasFilename() const { return m_filename; } +const word& fileAttachment::fileInfo::getFilename() const { return *m_filename; } void fileAttachment::fileInfo::setFilename(const string& name) { if (m_filename) { *m_filename = name; } else { m_filename = new word(name); } } void fileAttachment::fileInfo::setFilename(const word& name) { if (m_filename) { *m_filename = name; } else { m_filename = new word(name); } } -bool fileAttachment::fileInfo::hasCreationDate() const { return (m_creationDate != NULL); } -const datetime& fileAttachment::fileInfo::getCreationDate() const { return (*m_creationDate); } +bool fileAttachment::fileInfo::hasCreationDate() const { return m_creationDate; } +const datetime& fileAttachment::fileInfo::getCreationDate() const { return *m_creationDate; } void fileAttachment::fileInfo::setCreationDate(const datetime& date) { if (m_creationDate) { *m_creationDate = date; } else { m_creationDate = new datetime(date); } } -bool fileAttachment::fileInfo::hasModificationDate() const { return (m_modifDate != NULL); } -const datetime& fileAttachment::fileInfo::getModificationDate() const { return (*m_modifDate); } +bool fileAttachment::fileInfo::hasModificationDate() const { return m_modifDate; } +const datetime& fileAttachment::fileInfo::getModificationDate() const { return *m_modifDate; } void fileAttachment::fileInfo::setModificationDate(const datetime& date) { if (m_modifDate) { *m_modifDate = date; } else { m_modifDate = new datetime(date); } } -bool fileAttachment::fileInfo::hasReadDate() const { return (m_readDate != NULL); } -const datetime& fileAttachment::fileInfo::getReadDate() const { return (*m_readDate); } +bool fileAttachment::fileInfo::hasReadDate() const { return m_readDate; } +const datetime& fileAttachment::fileInfo::getReadDate() const { return *m_readDate; } void fileAttachment::fileInfo::setReadDate(const datetime& date) { if (m_readDate) { *m_readDate = date; } else { m_readDate = new datetime(date); } } -bool fileAttachment::fileInfo::hasSize() const { return (m_size != NULL); } -size_t fileAttachment::fileInfo::getSize() const { return (*m_size); } +bool fileAttachment::fileInfo::hasSize() const { return m_size; } +size_t fileAttachment::fileInfo::getSize() const { return *m_size; } void fileAttachment::fileInfo::setSize(const size_t size) { if (m_size) { *m_size = size; } else { m_size = new size_t(size); } } @@ -220,4 +251,3 @@ void fileAttachment::fileInfo::setSize(const size_t size) { if (m_size) { *m_siz #endif // VMIME_HAVE_FILESYSTEM_FEATURES - diff --git a/src/vmime/fileAttachment.hpp b/src/vmime/fileAttachment.hpp index 03e3e283..c77662f2 100644 --- a/src/vmime/fileAttachment.hpp +++ b/src/vmime/fileAttachment.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,29 +37,58 @@ #include "vmime/utility/stream.hpp" -namespace vmime -{ +namespace vmime { /** Attachment of type 'file'. */ +class VMIME_EXPORT fileAttachment : public defaultAttachment { -class VMIME_EXPORT fileAttachment : public defaultAttachment -{ public: - fileAttachment(const string& filepath, const mediaType& type); - fileAttachment(const string& filepath, const mediaType& type, const text& desc); - fileAttachment(const string& filepath, const mediaType& type, const text& desc, const encoding& enc); + fileAttachment( + const string& filepath, + const mediaType& type + ); - fileAttachment(const shared_ptr & cts, const word& filename, const mediaType& type); - fileAttachment(const shared_ptr & cts, const word& filename, const mediaType& type, const text& desc); - fileAttachment(const shared_ptr & cts, const word& filename, const mediaType& type, const text& desc, const encoding& enc); + fileAttachment( + const string& filepath, + const mediaType& type, + const text& desc + ); + + fileAttachment( + const string& filepath, + const mediaType& type, + const text& desc, + const encoding& enc + ); + + fileAttachment( + const shared_ptr & cts, + const word& filename, + const mediaType& type + ); + + fileAttachment( + const shared_ptr & cts, + const word& filename, + const mediaType& type, + const text& desc + ); + + fileAttachment( + const shared_ptr & cts, + const word& filename, + const mediaType& type, + const text& desc, + const encoding& enc + ); /** Stores information about a file attachment. */ - class VMIME_EXPORT fileInfo - { + class VMIME_EXPORT fileInfo { + public: fileInfo(); diff --git a/src/vmime/fileContentHandler.cpp b/src/vmime/fileContentHandler.cpp index 531151b4..baedf69c 100644 --- a/src/vmime/fileContentHandler.cpp +++ b/src/vmime/fileContentHandler.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,57 +30,61 @@ #include "vmime/fileContentHandler.hpp" -namespace vmime -{ +namespace vmime { fileContentHandler::fileContentHandler() - : streamContentHandler() -{ + : streamContentHandler() { + } -fileContentHandler::fileContentHandler - (const shared_ptr & file, const vmime::encoding& enc) -{ +fileContentHandler::fileContentHandler( + const shared_ptr & file, + const vmime::encoding& enc +) { + setData(file, enc); } -fileContentHandler::~fileContentHandler() -{ +fileContentHandler::~fileContentHandler() { + } fileContentHandler::fileContentHandler(const fileContentHandler& cts) - : streamContentHandler() -{ + : streamContentHandler() { + setData(cts.m_file, cts.m_encoding); } -fileContentHandler& fileContentHandler::operator=(const fileContentHandler& cts) -{ +fileContentHandler& fileContentHandler::operator=(const fileContentHandler& cts) { + setData(cts.m_file, cts.m_encoding); return *this; } -shared_ptr fileContentHandler::clone() const -{ +shared_ptr fileContentHandler::clone() const { + return make_shared (*this); } -void fileContentHandler::setData - (const shared_ptr & file, const vmime::encoding& enc) -{ +void fileContentHandler::setData( + const shared_ptr & file, + const vmime::encoding& enc +) { + m_file = file; m_encoding = enc; - streamContentHandler::setData - (file->getFileReader()->getInputStream(), file->getLength(), enc); + streamContentHandler::setData( + file->getFileReader()->getInputStream(), file->getLength(), enc + ); } diff --git a/src/vmime/fileContentHandler.hpp b/src/vmime/fileContentHandler.hpp index 1436a002..80df0695 100644 --- a/src/vmime/fileContentHandler.hpp +++ b/src/vmime/fileContentHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,15 +35,13 @@ #include "vmime/utility/file.hpp" -namespace vmime -{ +namespace vmime { /** A content handler which obtains its data from a file. */ +class VMIME_EXPORT fileContentHandler : public streamContentHandler { -class VMIME_EXPORT fileContentHandler : public streamContentHandler -{ public: /** Creates a new empty content handler. No data can be extracted until @@ -61,9 +59,10 @@ public: * * @return a reference to a new content handler */ - fileContentHandler - (const shared_ptr & file, - const vmime::encoding& enc = NO_ENCODING); + fileContentHandler( + const shared_ptr & file, + const vmime::encoding& enc = NO_ENCODING + ); ~fileContentHandler(); @@ -78,9 +77,10 @@ public: * @param enc set to anything other than NO_ENCODING if the data contained * in the file is already encoded with the specified encoding */ - void setData - (const shared_ptr & file, - const vmime::encoding& enc = NO_ENCODING); + void setData( + const shared_ptr & file, + const vmime::encoding& enc = NO_ENCODING + ); private: diff --git a/src/vmime/generatedMessageAttachment.cpp b/src/vmime/generatedMessageAttachment.cpp index b58b56d8..ad9e678a 100644 --- a/src/vmime/generatedMessageAttachment.cpp +++ b/src/vmime/generatedMessageAttachment.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -26,62 +26,63 @@ #include "vmime/utility/outputStreamAdapter.hpp" -namespace vmime -{ +namespace vmime { -generatedMessageAttachment::generatedMessageAttachment(const shared_ptr & part) - : m_bpa(make_shared (part)) -{ +generatedMessageAttachment::generatedMessageAttachment( + const shared_ptr & part +) + : m_bpa(make_shared (part)) { + } -const mediaType generatedMessageAttachment::getType() const -{ +const mediaType generatedMessageAttachment::getType() const { + return mediaType(mediaTypes::MESSAGE, mediaTypes::MESSAGE_RFC822); } -const text generatedMessageAttachment::getDescription() const -{ +const text generatedMessageAttachment::getDescription() const { + return m_bpa->getDescription(); } -const word generatedMessageAttachment::getName() const -{ +const word generatedMessageAttachment::getName() const { + return m_bpa->getName(); } -const shared_ptr generatedMessageAttachment::getData() const -{ +const shared_ptr generatedMessageAttachment::getData() const { + return m_bpa->getData(); } -const encoding generatedMessageAttachment::getEncoding() const -{ +const encoding generatedMessageAttachment::getEncoding() const { + return m_bpa->getEncoding(); } -shared_ptr generatedMessageAttachment::getPart() const -{ +shared_ptr generatedMessageAttachment::getPart() const { + return m_bpa->getPart(); } -shared_ptr generatedMessageAttachment::getHeader() const -{ +shared_ptr generatedMessageAttachment::getHeader() const { + return m_bpa->getHeader(); } -shared_ptr generatedMessageAttachment::getMessage() const -{ - if (m_msg == NULL) - { +shared_ptr generatedMessageAttachment::getMessage() const { + + if (!m_msg) { + // Extract data std::ostringstream oss; utility::outputStreamAdapter os(oss); @@ -97,8 +98,8 @@ shared_ptr generatedMessageAttachment::getMessage() const } -void generatedMessageAttachment::generateIn(const shared_ptr & /* parent */) const -{ +void generatedMessageAttachment::generateIn(const shared_ptr & /* parent */) const { + // Not used (see 'parsedMessageAttachment') } diff --git a/src/vmime/generatedMessageAttachment.hpp b/src/vmime/generatedMessageAttachment.hpp index e1e00cc7..b65fcc15 100644 --- a/src/vmime/generatedMessageAttachment.hpp +++ b/src/vmime/generatedMessageAttachment.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,14 +32,13 @@ #include "vmime/bodyPartAttachment.hpp" -namespace vmime -{ +namespace vmime { /** A message attachment that can be extracted from a message. */ -class VMIME_EXPORT generatedMessageAttachment : public messageAttachment -{ +class VMIME_EXPORT generatedMessageAttachment : public messageAttachment { + public: generatedMessageAttachment(const shared_ptr & part); @@ -76,4 +75,3 @@ private: #endif // VMIME_GENERATEDMESSAGEATTACHMENT_HPP_INCLUDED - diff --git a/src/vmime/generationContext.cpp b/src/vmime/generationContext.cpp index 4b637432..24757c70 100644 --- a/src/vmime/generationContext.cpp +++ b/src/vmime/generationContext.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -24,8 +24,7 @@ #include "vmime/generationContext.hpp" -namespace vmime -{ +namespace vmime { generationContext::generationContext() @@ -34,8 +33,8 @@ generationContext::generationContext() "does not understand MIME message format."), m_epilogText(""), m_wrapMessageId(true), - m_paramValueMode(PARAMETER_VALUE_RFC2231_ONLY) -{ + m_paramValueMode(PARAMETER_VALUE_RFC2231_ONLY) { + } @@ -45,86 +44,89 @@ generationContext::generationContext(const generationContext& ctx) m_prologText(ctx.m_prologText), m_epilogText(ctx.m_epilogText), m_wrapMessageId(ctx.m_wrapMessageId), - m_paramValueMode(ctx.m_paramValueMode) -{ + m_paramValueMode(ctx.m_paramValueMode) { + } -generationContext& generationContext::getDefaultContext() -{ +generationContext& generationContext::getDefaultContext() { + static generationContext ctx; return ctx; } -size_t generationContext::getMaxLineLength() const -{ +size_t generationContext::getMaxLineLength() const { + return m_maxLineLength; } -void generationContext::setMaxLineLength(const size_t maxLineLength) -{ +void generationContext::setMaxLineLength(const size_t maxLineLength) { + m_maxLineLength = maxLineLength; } -const string generationContext::getPrologText() const -{ +const string generationContext::getPrologText() const { + return m_prologText; } -void generationContext::setPrologText(const string& prologText) -{ +void generationContext::setPrologText(const string& prologText) { + m_prologText = prologText; } -const string generationContext::getEpilogText() const -{ +const string generationContext::getEpilogText() const { + return m_epilogText; } -void generationContext::setEpilogText(const string& epilogText) -{ +void generationContext::setEpilogText(const string& epilogText) { + m_epilogText = epilogText; } -bool generationContext::getWrapMessageId() const -{ + +bool generationContext::getWrapMessageId() const { + return m_wrapMessageId; } -void generationContext::setWrapMessageId(const bool& wrapMessageId) -{ + +void generationContext::setWrapMessageId(const bool& wrapMessageId) { + m_wrapMessageId = wrapMessageId; } -void generationContext::setEncodedParameterValueMode(const EncodedParameterValueModes mode) -{ + +void generationContext::setEncodedParameterValueMode(const EncodedParameterValueModes mode) { + m_paramValueMode = mode; } generationContext::EncodedParameterValueModes - generationContext::getEncodedParameterValueMode() const -{ + generationContext::getEncodedParameterValueMode() const { + return m_paramValueMode; } -generationContext& generationContext::operator=(const generationContext& ctx) -{ +generationContext& generationContext::operator=(const generationContext& ctx) { + copyFrom(ctx); return *this; } -void generationContext::copyFrom(const generationContext& ctx) -{ +void generationContext::copyFrom(const generationContext& ctx) { + context::copyFrom(ctx); m_maxLineLength = ctx.m_maxLineLength; diff --git a/src/vmime/generationContext.hpp b/src/vmime/generationContext.hpp index 1cb4ce67..5e36513c 100644 --- a/src/vmime/generationContext.hpp +++ b/src/vmime/generationContext.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,15 +28,13 @@ #include "vmime/context.hpp" -namespace vmime -{ +namespace vmime { /** Holds configuration parameters used for generating messages. */ +class VMIME_EXPORT generationContext : public context { -class VMIME_EXPORT generationContext : public context -{ public: generationContext(); @@ -103,8 +101,8 @@ public: /** Modes available for generating values in parameterized header fields. */ - enum EncodedParameterValueModes - { + enum EncodedParameterValueModes { + PARAMETER_VALUE_NO_ENCODING, /**< Only generate 7-bit (ASCII-only) values, even if the value contains non-ASCII chars or if folding is needed. */ diff --git a/src/vmime/header.cpp b/src/vmime/header.cpp index cd2a6f7e..c7d7ca08 100644 --- a/src/vmime/header.cpp +++ b/src/vmime/header.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,17 +28,16 @@ #include -namespace vmime -{ +namespace vmime { -header::header() -{ +header::header() { + } -header::~header() -{ +header::~header() { + removeAllFields(); } @@ -62,70 +61,79 @@ field-body-contents = specials tokens, or else consisting of texts> */ -void header::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void header::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + size_t pos = position; removeAllFields(); - while (pos < end) - { + while (pos < end) { + shared_ptr field = headerField::parseNext(ctx, buffer, pos, end, &pos); - if (field == NULL) break; + if (!field) break; m_fields.push_back(field); } setParsedBounds(position, pos); - if (newPosition) + if (newPosition) { *newPosition = pos; + } } -void header::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t /* curLinePos */, size_t* newLinePos) const -{ +void header::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t /* curLinePos */, + size_t* newLinePos +) const { + // Generate the fields for (std::vector >::const_iterator it = m_fields.begin() ; - it != m_fields.end() ; ++it) - { + it != m_fields.end() ; ++it) { + (*it)->generate(ctx, os); os << CRLF; } - if (newLinePos) + if (newLinePos) { *newLinePos = 0; + } } -size_t header::getGeneratedSize(const generationContext& ctx) -{ +size_t header::getGeneratedSize(const generationContext& ctx) { + return component::getGeneratedSize(ctx) + 2 * m_fields.size() /* CRLF */; } -shared_ptr header::clone() const -{ +shared_ptr header::clone() const { + shared_ptr
hdr = make_shared
(); hdr->m_fields.reserve(m_fields.size()); for (std::vector >::const_iterator it = m_fields.begin() ; - it != m_fields.end() ; ++it) - { + it != m_fields.end() ; ++it) { + hdr->m_fields.push_back(vmime::clone(*it)); } - return (hdr); + return hdr; } -void header::copyFrom(const component& other) -{ +void header::copyFrom(const component& other) { + const header& h = dynamic_cast (other); std::vector > fields; @@ -133,8 +141,8 @@ void header::copyFrom(const component& other) fields.reserve(h.m_fields.size()); for (std::vector >::const_iterator it = h.m_fields.begin() ; - it != h.m_fields.end() ; ++it) - { + it != h.m_fields.end() ; ++it) { + fields.push_back(vmime::clone(*it)); } @@ -145,217 +153,238 @@ void header::copyFrom(const component& other) } -header& header::operator=(const header& other) -{ +header& header::operator=(const header& other) { + copyFrom(other); - return (*this); + return *this; } -bool header::hasField(const string& fieldName) const -{ +bool header::hasField(const string& fieldName) const { + std::vector >::const_iterator pos = - std::find_if(m_fields.begin(), m_fields.end(), - fieldHasName(utility::stringUtils::toLower(fieldName))); + std::find_if( + m_fields.begin(), m_fields.end(), + fieldHasName(utility::stringUtils::toLower(fieldName)) + ); - return (pos != m_fields.end()); + return pos != m_fields.end(); } -shared_ptr header::findField(const string& fieldName) const -{ +shared_ptr header::findField(const string& fieldName) const { + // Find the first field that matches the specified name std::vector >::const_iterator pos = - std::find_if(m_fields.begin(), m_fields.end(), - fieldHasName(utility::stringUtils::toLower(fieldName))); + std::find_if( + m_fields.begin(), m_fields.end(), + fieldHasName(utility::stringUtils::toLower(fieldName)) + ); // No field with this name can be found - if (pos == m_fields.end()) + if (pos == m_fields.end()) { return null; + } // Else, return a reference to the existing field - return (*pos); + return *pos; } -std::vector > header::findAllFields(const string& fieldName) -{ +std::vector > header::findAllFields(const string& fieldName) { + std::vector > result; std::back_insert_iterator > > back(result); - std::remove_copy_if(m_fields.begin(), m_fields.end(), back, - fieldHasNotName(utility::stringUtils::toLower(fieldName))); + std::remove_copy_if( + m_fields.begin(), m_fields.end(), back, + fieldHasNotName(utility::stringUtils::toLower(fieldName)) + ); return result; } -shared_ptr header::getField(const string& fieldName) -{ +shared_ptr header::getField(const string& fieldName) { + const string name = utility::stringUtils::toLower(fieldName); // Find the first field that matches the specified name std::vector >::const_iterator pos = m_fields.begin(); const std::vector >::const_iterator end = m_fields.end(); - while (pos != end && utility::stringUtils::toLower((*pos)->getName()) != name) + while (pos != end && utility::stringUtils::toLower((*pos)->getName()) != name) { ++pos; + } // If no field with this name can be found, create a new one - if (pos == end) - { + if (pos == end) { + shared_ptr field = headerFieldFactory::getInstance()->create(fieldName); appendField(field); // Return a reference to the new field return (field); - } + // Else, return a reference to the existing field - else - { - return (*pos); + } else { + + return *pos; } } -void header::appendField(const shared_ptr & field) -{ +void header::appendField(const shared_ptr & field) { + m_fields.push_back(field); } -void header::insertFieldBefore(const shared_ptr & beforeField, const shared_ptr & field) -{ - const std::vector >::iterator it = std::find - (m_fields.begin(), m_fields.end(), beforeField); +void header::insertFieldBefore( + const shared_ptr & beforeField, + const shared_ptr & field +) { - if (it == m_fields.end()) + const std::vector >::iterator it = + std::find(m_fields.begin(), m_fields.end(), beforeField); + + if (it == m_fields.end()) { throw exceptions::no_such_field(); + } m_fields.insert(it, field); } -void header::insertFieldBefore(const size_t pos, const shared_ptr & field) -{ +void header::insertFieldBefore(const size_t pos, const shared_ptr & field) { + m_fields.insert(m_fields.begin() + pos, field); } -void header::insertFieldAfter(const shared_ptr & afterField, const shared_ptr & field) -{ - const std::vector >::iterator it = std::find - (m_fields.begin(), m_fields.end(), afterField); +void header::insertFieldAfter( + const shared_ptr & afterField, + const shared_ptr & field +) { - if (it == m_fields.end()) + const std::vector >::iterator it = + std::find(m_fields.begin(), m_fields.end(), afterField); + + if (it == m_fields.end()) { throw exceptions::no_such_field(); + } m_fields.insert(it + 1, field); } -void header::insertFieldAfter(const size_t pos, const shared_ptr & field) -{ +void header::insertFieldAfter(const size_t pos, const shared_ptr & field) { + m_fields.insert(m_fields.begin() + pos + 1, field); } -void header::removeField(const shared_ptr & field) -{ - const std::vector >::iterator it = std::find - (m_fields.begin(), m_fields.end(), field); +void header::removeField(const shared_ptr & field) { - if (it == m_fields.end()) + const std::vector >::iterator it = + std::find(m_fields.begin(), m_fields.end(), field); + + if (it == m_fields.end()) { throw exceptions::no_such_field(); + } m_fields.erase(it); } -void header::removeField(const size_t pos) -{ +void header::removeField(const size_t pos) { + const std::vector >::iterator it = m_fields.begin() + pos; m_fields.erase(it); } -void header::replaceField(const shared_ptr & field, const shared_ptr & newField) -{ +void header::replaceField( + const shared_ptr & field, + const shared_ptr & newField +) { + insertFieldBefore(field, newField); removeField(field); } -void header::removeAllFields() -{ +void header::removeAllFields() { + m_fields.clear(); } -void header::removeAllFields(const string& fieldName) -{ +void header::removeAllFields(const string& fieldName) { + std::vector > fields = findAllFields(fieldName); - for (unsigned int i = 0 ; i < fields.size() ; ++i) + for (unsigned int i = 0 ; i < fields.size() ; ++i) { removeField(fields[i]); + } } -size_t header::getFieldCount() const -{ - return (m_fields.size()); +size_t header::getFieldCount() const { + + return m_fields.size(); } -bool header::isEmpty() const -{ - return (m_fields.empty()); +bool header::isEmpty() const { + + return m_fields.empty(); } -const shared_ptr header::getFieldAt(const size_t pos) -{ - return (m_fields[pos]); +const shared_ptr header::getFieldAt(const size_t pos) { + + return m_fields[pos]; } -const shared_ptr header::getFieldAt(const size_t pos) const -{ - return (m_fields[pos]); +const shared_ptr header::getFieldAt(const size_t pos) const { + + return m_fields[pos]; } -const std::vector > header::getFieldList() const -{ +const std::vector > header::getFieldList() const { + std::vector > list; list.reserve(m_fields.size()); for (std::vector >::const_iterator it = m_fields.begin() ; - it != m_fields.end() ; ++it) - { + it != m_fields.end() ; ++it) { + list.push_back(*it); } - return (list); + return list; } -const std::vector > header::getFieldList() -{ - return (m_fields); +const std::vector > header::getFieldList() { + + return m_fields; } -const std::vector > header::getChildComponents() -{ +const std::vector > header::getChildComponents() { + std::vector > list; copy_vector(m_fields, list); - return (list); + return list; } @@ -364,23 +393,23 @@ const std::vector > header::getChildComponents() header::fieldHasName::fieldHasName(const string& name) - : m_name(name) -{ + : m_name(name) { + } -bool header::fieldHasName::operator() (const shared_ptr & field) -{ +bool header::fieldHasName::operator() (const shared_ptr & field) { + return utility::stringUtils::toLower(field->getName()) == m_name; } header::fieldHasNotName::fieldHasNotName(const string& name) - : m_name(name) -{ + : m_name(name) { + } -bool header::fieldHasNotName::operator() (const shared_ptr & field) -{ +bool header::fieldHasNotName::operator() (const shared_ptr & field) { + return utility::stringUtils::toLower(field->getName()) != m_name; } diff --git a/src/vmime/header.hpp b/src/vmime/header.hpp index f2fd0666..7b4a1616 100644 --- a/src/vmime/header.hpp +++ b/src/vmime/header.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,8 +33,7 @@ #include "vmime/headerFieldFactory.hpp" -namespace vmime -{ +namespace vmime { class bodyPart; @@ -42,9 +41,8 @@ class bodyPart; /** Header section of a MIME part. */ +class VMIME_EXPORT header : public component { -class VMIME_EXPORT header : public component -{ friend class bodyPart; friend class body; friend class message; @@ -120,8 +118,8 @@ public: * with this name was found */ template - shared_ptr findField(const string& fieldName) const - { + shared_ptr findField(const string& fieldName) const { + return dynamicCast (findField(fieldName)); } @@ -137,14 +135,15 @@ public: * specified type */ template - shared_ptr findFieldValue(const string& fieldName) const - { + shared_ptr findFieldValue(const string& fieldName) const { + shared_ptr field = findField(fieldName); - if (field) + if (field) { return dynamicCast (field->getValue()); - else + } else { return null; + } } /** Find all fields that match the specified name. @@ -176,8 +175,8 @@ public: * if no field is found */ template - shared_ptr getField(const string& fieldName) - { + shared_ptr getField(const string& fieldName) { + return dynamicCast (getField(fieldName)); } @@ -193,7 +192,10 @@ public: * @param field field to insert * @throw exceptions::no_such_field if the field is not in the list */ - void insertFieldBefore(const shared_ptr & beforeField, const shared_ptr & field); + void insertFieldBefore( + const shared_ptr & beforeField, + const shared_ptr & field + ); /** Insert a new field before the specified position. * @@ -201,7 +203,10 @@ public: * the beginning of the list) * @param field field to insert */ - void insertFieldBefore(const size_t pos, const shared_ptr & field); + void insertFieldBefore( + const size_t pos, + const shared_ptr & field + ); /** Insert a new field after the specified field. * @@ -209,14 +214,20 @@ public: * @param field field to insert * @throw exceptions::no_such_field if the field is not in the list */ - void insertFieldAfter(const shared_ptr & afterField, const shared_ptr & field); + void insertFieldAfter( + const shared_ptr & afterField, + const shared_ptr & field + ); /** Insert a new field after the specified position. * * @param pos position of the field before the new field * @param field field to insert */ - void insertFieldAfter(const size_t pos, const shared_ptr & field); + void insertFieldAfter( + const size_t pos, + const shared_ptr & field + ); /** Remove the specified field from the list. * @@ -237,7 +248,10 @@ public: * @param newField field to replace with * @throw exceptions::no_such_field if the field is not in the list */ - void replaceField(const shared_ptr & field, const shared_ptr & newField); + void replaceField( + const shared_ptr & field, + const shared_ptr & newField + ); /** Remove all fields from the list. */ @@ -298,8 +312,8 @@ private: std::vector > m_fields; - class fieldHasName - { + class fieldHasName { + public: fieldHasName(const string& name); @@ -310,8 +324,8 @@ private: string m_name; }; - class fieldHasNotName - { + class fieldHasNotName { + public: fieldHasNotName(const string& name); @@ -325,18 +339,20 @@ private: protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/headerField.cpp b/src/vmime/headerField.cpp index 05f5b046..bff365dc 100644 --- a/src/vmime/headerField.cpp +++ b/src/vmime/headerField.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,130 +29,147 @@ #include "vmime/exception.hpp" -namespace vmime -{ +namespace vmime { headerField::headerField() - : m_name("X-Undefined") -{ + : m_name("X-Undefined") { + } headerField::headerField(const string& fieldName) - : m_name(fieldName) -{ + : m_name(fieldName) { + } -headerField::~headerField() -{ +headerField::~headerField() { + } -shared_ptr headerField::clone() const -{ +shared_ptr headerField::clone() const { + shared_ptr field = headerFieldFactory::getInstance()->create(m_name); field->copyFrom(*this); - return (field); + return field; } -void headerField::copyFrom(const component& other) -{ +void headerField::copyFrom(const component& other) { + const headerField& hf = dynamic_cast (other); m_value->copyFrom(*hf.m_value); } -headerField& headerField::operator=(const headerField& other) -{ +headerField& headerField::operator=(const headerField& other) { + copyFrom(other); - return (*this); + return *this; } -shared_ptr headerField::parseNext - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +shared_ptr headerField::parseNext( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + size_t pos = position; - while (pos < end) - { + while (pos < end) { + char_t c = buffer[pos]; // Check for end of headers (empty line): although RFC-822 recommends // to use CRLF for header/body separator (see 4.1 SYNTAX), here, we // also check for LF for compatibility with broken implementations... - if (c == '\n') - { - if (newPosition) + if (c == '\n') { + + if (newPosition) { *newPosition = pos + 1; // LF: illegal + } return null; - } - else if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') - { - if (newPosition) + + } else if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') { + + if (newPosition) { *newPosition = pos + 2; // CR+LF + } return null; } // This line may be a field description - if (!parserHelpers::isSpace(c)) - { + if (!parserHelpers::isSpace(c)) { + const size_t nameStart = pos; // remember the start position of the line - while (pos < end && (buffer[pos] != ':' && !parserHelpers::isSpace(buffer[pos]))) + while (pos < end && (buffer[pos] != ':' && !parserHelpers::isSpace(buffer[pos]))) { ++pos; + } const size_t nameEnd = pos; - while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t')) + while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t')) { ++pos; + } + + if (buffer[pos] != ':') { - if (buffer[pos] != ':') - { switch (ctx.getHeaderParseErrorRecoveryMethod()) { + case vmime::headerParseRecoveryMethod::SKIP_LINE: // Humm...does not seem to be a valid header line. // Skip this error and advance to the next line pos = nameStart; - while (pos < end && buffer[pos] != '\n') + while (pos < end && buffer[pos] != '\n') { ++pos; + } - if (pos < end && buffer[pos] == '\n') + if (pos < end && buffer[pos] == '\n') { ++pos; + } + break; // case vmime::headerParseRecoveryMethod::APPEND_TO_PREVIOUS_LINE: +// // // TODO Implement this... // break; case vmime::headerParseRecoveryMethod::ASSUME_END_OF_HEADERS: + return null; break; } - } - else - { + + } else { + // Extract the field name - const string name(buffer.begin() + nameStart, - buffer.begin() + nameEnd); + const string name( + buffer.begin() + nameStart, + buffer.begin() + nameEnd + ); // Skip ':' character - while (pos < end && buffer[pos] == ':') + while (pos < end && buffer[pos] == ':') { ++pos; + } // Skip spaces between ':' and the field contents - while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t')) + while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t')) { ++pos; + } const size_t contentsStart = pos; size_t contentsEnd = 0; @@ -160,19 +177,20 @@ shared_ptr headerField::parseNext bool firstLine = true; // Parse field value, taking care of line folding (value on multiple lines) - for (size_t eol = 0 ; parserHelpers::findEOL(buffer, pos, end, &eol) ; pos = eol) - { + for (size_t eol = 0 ; parserHelpers::findEOL(buffer, pos, end, &eol) ; pos = eol) { + // If the line does not start with a folding indicator (SPACE or TAB), // and this is not the first line, then stop parsing lines - if (!firstLine && !(buffer[pos] == ' ' || buffer[pos] == '\t')) + if (!firstLine && !(buffer[pos] == ' ' || buffer[pos] == '\t')) { break; + } contentsEnd = eol; firstLine = false; } - if (pos == end && contentsEnd == 0) - { + if (pos == end && contentsEnd == 0) { + // End of data, and no CRLF was found at the end contentsEnd = end; } @@ -180,8 +198,8 @@ shared_ptr headerField::parseNext // Strip spaces from end of header lines while (contentsEnd > contentsStart && (buffer[contentsEnd - 1] == ' ' || buffer[contentsEnd - 1] == '\t' || - buffer[contentsEnd - 1] == '\r' || buffer[contentsEnd - 1] == '\n')) - { + buffer[contentsEnd - 1] == '\r' || buffer[contentsEnd - 1] == '\n')) { + contentsEnd--; } @@ -191,145 +209,164 @@ shared_ptr headerField::parseNext field->parse(ctx, buffer, contentsStart, contentsEnd, NULL); field->setParsedBounds(nameStart, pos); - if (newPosition) + if (newPosition) { *newPosition = pos; + } - return (field); + return field; } - } - else - { + + } else { + // If the line contains only space characters, we assume it is // the end of the headers. - while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t')) + while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t')) { ++pos; + } - if (pos < end && buffer[pos] == '\n') - { - if (newPosition) + if (pos < end && buffer[pos] == '\n') { + + if (newPosition) { *newPosition = pos + 1; // LF: illegal + } return null; - } - else if (pos + 1 < end && buffer[pos] == '\r' && buffer[pos + 1] == '\n') - { - if (newPosition) + + } else if (pos + 1 < end && buffer[pos] == '\r' && buffer[pos + 1] == '\n') { + + if (newPosition) { *newPosition = pos + 2; // CR+LF + } return null; } // Skip this error and advance to the next line - while (pos < end && buffer[pos] != '\n') + while (pos < end && buffer[pos] != '\n') { ++pos; + } - if (buffer[pos] == '\n') + if (buffer[pos] == '\n') { ++pos; + } } } - if (newPosition) + if (newPosition) { *newPosition = pos; + } return null; } -void headerField::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void headerField::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + m_value->parse(ctx, buffer, position, end, newPosition); } -void headerField::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void headerField::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + os << m_name + ": "; m_value->generate(ctx, os, curLinePos + m_name.length() + 2, newLinePos); } -size_t headerField::getGeneratedSize(const generationContext& ctx) -{ +size_t headerField::getGeneratedSize(const generationContext& ctx) { + return m_name.length() + 2 /* ": " */ + m_value->getGeneratedSize(ctx); } -const string headerField::getName() const -{ +const string headerField::getName() const { + return m_name; } -void headerField::setName(const string& name) -{ +void headerField::setName(const string& name) { + m_name = name; } -bool headerField::isCustom() const -{ - return (m_name.length() > 2 && m_name[0] == 'X' && m_name[1] == '-'); +bool headerField::isCustom() const { + + return m_name.length() > 2 && m_name[0] == 'X' && m_name[1] == '-'; } -const std::vector > headerField::getChildComponents() -{ +const std::vector > headerField::getChildComponents() { + std::vector > list; - if (m_value) + if (m_value) { list.push_back(m_value); + } - return (list); + return list; } -shared_ptr headerField::getValue() const -{ +shared_ptr headerField::getValue() const { + return m_value; } -shared_ptr headerField::getValue() -{ +shared_ptr headerField::getValue() { + return m_value; } -void headerField::setValue(const shared_ptr & value) -{ - if (!headerFieldFactory::getInstance()->isValueTypeValid(*this, *value)) +void headerField::setValue(const shared_ptr & value) { + + if (!headerFieldFactory::getInstance()->isValueTypeValid(*this, *value)) { throw exceptions::bad_field_value_type(getName()); + } - if (value != NULL) + if (value != NULL) { m_value = value; + } } -void headerField::setValueConst(const shared_ptr & value) -{ - if (!headerFieldFactory::getInstance()->isValueTypeValid(*this, *value)) +void headerField::setValueConst(const shared_ptr & value) { + + if (!headerFieldFactory::getInstance()->isValueTypeValid(*this, *value)) { throw exceptions::bad_field_value_type(getName()); + } m_value = vmime::clone(value); } -void headerField::setValue(const headerFieldValue& value) -{ - if (!headerFieldFactory::getInstance()->isValueTypeValid(*this, value)) +void headerField::setValue(const headerFieldValue& value) { + + if (!headerFieldFactory::getInstance()->isValueTypeValid(*this, value)) { throw exceptions::bad_field_value_type(getName()); + } m_value = vmime::clone(value); } -void headerField::setValue(const string& value) -{ +void headerField::setValue(const string& value) { + parse(value); } diff --git a/src/vmime/headerField.hpp b/src/vmime/headerField.hpp index 9c49235c..66e99460 100644 --- a/src/vmime/headerField.hpp +++ b/src/vmime/headerField.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,15 +30,13 @@ #include "vmime/headerFieldValue.hpp" -namespace vmime -{ +namespace vmime { /** Base class for header fields. */ +class VMIME_EXPORT headerField : public component { -class VMIME_EXPORT headerField : public component -{ friend class headerFieldFactory; friend class header; @@ -90,8 +88,8 @@ public: * @return value object */ template - shared_ptr getValue() const - { + shared_ptr getValue() const { + return dynamicCast (m_value); } @@ -107,8 +105,8 @@ public: * @return value object */ template - shared_ptr getValue() - { + shared_ptr getValue() { + return dynamicCast (m_value); } @@ -154,29 +152,32 @@ public: * @return parsed header field, or NULL if no more header field can be parsed * in the input buffer */ - static shared_ptr parseNext - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + static shared_ptr parseNext( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); size_t getGeneratedSize(const generationContext& ctx); protected: - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; string m_name; diff --git a/src/vmime/headerFieldFactory.cpp b/src/vmime/headerFieldFactory.cpp index 5c60543e..db281fae 100644 --- a/src/vmime/headerFieldFactory.cpp +++ b/src/vmime/headerFieldFactory.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,12 +38,11 @@ #include "vmime/mailboxField.hpp" -namespace vmime -{ +namespace vmime { -headerFieldFactory::headerFieldFactory() -{ +headerFieldFactory::headerFieldFactory() { + // Register parameterized fields registerField (vmime::fields::CONTENT_TYPE); registerField (vmime::fields::CONTENT_TRANSFER_ENCODING); @@ -85,67 +84,75 @@ headerFieldFactory::headerFieldFactory() } -headerFieldFactory::~headerFieldFactory() -{ +headerFieldFactory::~headerFieldFactory() { + } -shared_ptr headerFieldFactory::getInstance() -{ +shared_ptr headerFieldFactory::getInstance() { + static headerFieldFactory instance; return shared_ptr (&instance, noop_shared_ptr_deleter ()); } -shared_ptr headerFieldFactory::create - (const string& name, const string& body) -{ +shared_ptr headerFieldFactory::create( + const string& name, + const string& body +) { + NameMap::const_iterator pos = m_nameMap.find(utility::stringUtils::toLower(name)); shared_ptr field; - if (pos != m_nameMap.end()) + if (pos != m_nameMap.end()) { field = ((*pos).second)(); - else + } else { field = registerer ::creator(); + } field->setName(name); field->setValue(createValue(name)); - if (body != NULL_STRING) + if (body != NULL_STRING) { field->parse(body); + } return field; } -shared_ptr headerFieldFactory::createValue(const string& fieldName) -{ - ValueMap::const_iterator pos = m_valueMap.find - (utility::stringUtils::toLower(fieldName)); +shared_ptr headerFieldFactory::createValue(const string& fieldName) { + + ValueMap::const_iterator pos = m_valueMap.find( + utility::stringUtils::toLower(fieldName) + ); shared_ptr value; - if (pos != m_valueMap.end()) + if (pos != m_valueMap.end()) { value = ((*pos).second.allocFunc)(); - else + } else { value = registerer ::creator(); + } return value; } -bool headerFieldFactory::isValueTypeValid - (const headerField& field, const headerFieldValue& value) const -{ +bool headerFieldFactory::isValueTypeValid( + const headerField& field, + const headerFieldValue& value +) const { + ValueMap::const_iterator pos = m_valueMap.find (utility::stringUtils::toLower(field.getName())); - if (pos != m_valueMap.end()) + if (pos != m_valueMap.end()) { return ((*pos).second.checkTypeFunc)(value); + } return true; // No info on this field } } // vmime - diff --git a/src/vmime/headerFieldFactory.hpp b/src/vmime/headerFieldFactory.hpp index 960f27b7..b3e34159 100644 --- a/src/vmime/headerFieldFactory.hpp +++ b/src/vmime/headerFieldFactory.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,15 +29,13 @@ #include "vmime/utility/stringUtils.hpp" -namespace vmime -{ +namespace vmime { /** Creates header field and header field value objects. */ +class VMIME_EXPORT headerFieldFactory { -class VMIME_EXPORT headerFieldFactory -{ protected: headerFieldFactory(); @@ -49,8 +47,8 @@ protected: NameMap m_nameMap; - struct ValueInfo - { + struct ValueInfo { + typedef shared_ptr (*ValueAllocFunc)(void); typedef bool (*ValueTypeCheckFunc)(const object&); @@ -67,24 +65,26 @@ public: static shared_ptr getInstance(); #ifndef VMIME_BUILDING_DOC + // TYPE must inherit from BASE_TYPE template - class registerer - { + class registerer { + public: - static bool checkType(const object& obj) - { + static bool checkType(const object& obj) { + const TYPE* typedObj = dynamic_cast (&obj); return typedObj != NULL; } - static shared_ptr creator() - { + static shared_ptr creator() { + // Allocate a new object return shared_ptr (new TYPE()); } }; + #endif // VMIME_BUILDING_DOC @@ -94,11 +94,14 @@ public: * @param name field name (eg. "X-MyField") */ template - void registerField(const string& name) - { - m_nameMap.insert(NameMap::value_type - (utility::stringUtils::toLower(name), - ®isterer ::creator)); + void registerField(const string& name) { + + m_nameMap.insert( + NameMap::value_type( + utility::stringUtils::toLower(name), + ®isterer ::creator + ) + ); } /** Register a field value type. @@ -107,14 +110,18 @@ public: * @param name field name */ template - void registerFieldValue(const string& name) - { + void registerFieldValue(const string& name) { + ValueInfo vi; vi.allocFunc = ®isterer ::creator; vi.checkTypeFunc = ®isterer ::checkType; - m_valueMap.insert(ValueMap::value_type - (utility::stringUtils::toLower(name), vi)); + m_valueMap.insert( + ValueMap::value_type( + utility::stringUtils::toLower(name), + vi + ) + ); } /** Create a new field object for the specified field name. diff --git a/src/vmime/headerFieldValue.cpp b/src/vmime/headerFieldValue.cpp index a93e0061..073edbe5 100644 --- a/src/vmime/headerFieldValue.cpp +++ b/src/vmime/headerFieldValue.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -26,12 +26,11 @@ #include "vmime/utility/outputStreamAdapter.hpp" -namespace vmime -{ +namespace vmime { -size_t headerFieldValue::getGeneratedSize(const generationContext& ctx) -{ +size_t headerFieldValue::getGeneratedSize(const generationContext& ctx) { + std::ostringstream oss; utility::outputStreamAdapter osa(oss); diff --git a/src/vmime/headerFieldValue.hpp b/src/vmime/headerFieldValue.hpp index a3681953..20d17680 100644 --- a/src/vmime/headerFieldValue.hpp +++ b/src/vmime/headerFieldValue.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,16 +29,14 @@ #include "vmime/component.hpp" -namespace vmime -{ +namespace vmime { /** Base class for all classes that can be used as a value * for a header field. */ +class VMIME_EXPORT headerFieldValue : public component { -class VMIME_EXPORT headerFieldValue : public component -{ public: size_t getGeneratedSize(const generationContext& ctx); @@ -49,4 +47,3 @@ public: #endif // VMIME_HEADERFIELDVALUE_HPP_INCLUDED - diff --git a/src/vmime/htmlTextPart.cpp b/src/vmime/htmlTextPart.cpp index bda33cc0..a30023c6 100644 --- a/src/vmime/htmlTextPart.cpp +++ b/src/vmime/htmlTextPart.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,47 +34,52 @@ #include "vmime/utility/outputStreamAdapter.hpp" -namespace vmime -{ +namespace vmime { htmlTextPart::htmlTextPart() : m_plainText(make_shared ()), - m_text(make_shared ()) -{ + m_text(make_shared ()) { + } -htmlTextPart::~htmlTextPart() -{ +htmlTextPart::~htmlTextPart() { + } -const mediaType htmlTextPart::getType() const -{ +const mediaType htmlTextPart::getType() const { + return mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML); } -size_t htmlTextPart::getPartCount() const -{ - return (m_plainText->isEmpty() ? 1 : 2); +size_t htmlTextPart::getPartCount() const { + + return m_plainText->isEmpty() ? 1 : 2; } -void htmlTextPart::generateIn(const shared_ptr & /* message */, const shared_ptr & parent) const -{ +void htmlTextPart::generateIn( + const shared_ptr & /* message */, + const shared_ptr & parent +) const { + // Plain text - if (!m_plainText->isEmpty()) - { + if (!m_plainText->isEmpty()) { + // -- Create a new part shared_ptr part = make_shared (); parent->getBody()->appendPart(part); // -- Set contents - part->getBody()->setContents(m_plainText, - mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN), m_charset, - encoding::decide(m_plainText, m_charset, encoding::USAGE_TEXT)); + part->getBody()->setContents( + m_plainText, + mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN), + m_charset, + encoding::decide(m_plainText, m_charset, encoding::USAGE_TEXT) + ); } // HTML text @@ -82,27 +87,31 @@ void htmlTextPart::generateIn(const shared_ptr & /* message */, const shared_ptr htmlPart = make_shared (); // -- Set contents - htmlPart->getBody()->setContents(m_text, - mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML), m_charset, - encoding::decide(m_text, m_charset, encoding::USAGE_TEXT)); + htmlPart->getBody()->setContents( + m_text, + mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML), + m_charset, + encoding::decide(m_text, m_charset, encoding::USAGE_TEXT) + ); // Handle the case we have embedded objects - if (!m_objects.empty()) - { + if (!m_objects.empty()) { + // Create a "multipart/related" body part shared_ptr relPart = make_shared (); parent->getBody()->appendPart(relPart); - relPart->getHeader()->ContentType()-> - setValue(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_RELATED)); + relPart->getHeader()->ContentType()->setValue( + mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_RELATED) + ); // Add the HTML part into this part relPart->getBody()->appendPart(htmlPart); // Also add objects into this part for (std::vector >::const_iterator it = m_objects.begin() ; - it != m_objects.end() ; ++it) - { + it != m_objects.end() ; ++it) { + shared_ptr objPart = make_shared (); relPart->getBody()->appendPart(objPart); @@ -112,8 +121,8 @@ void htmlTextPart::generateIn(const shared_ptr & /* message */, const (id[0] == 'c' || id[0] == 'C') && (id[1] == 'i' || id[1] == 'I') && (id[2] == 'd' || id[2] == 'D') && - id[3] == ':') - { + id[3] == ':') { + id = id.substr(4); } @@ -125,38 +134,46 @@ void htmlTextPart::generateIn(const shared_ptr & /* message */, const objPart->getBody()->setContents((*it)->getData()->clone()); } - } - else - { + + } else { + // Add the HTML part into the parent part parent->getBody()->appendPart(htmlPart); } } -void htmlTextPart::findEmbeddedParts(const bodyPart& part, - std::vector >& cidParts, std::vector >& locParts) -{ - for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i) - { +void htmlTextPart::findEmbeddedParts( + const bodyPart& part, + std::vector >& cidParts, + std::vector >& locParts +) { + + for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i) { + shared_ptr p = part.getBody()->getPartAt(i); // For a part to be an embedded object, it must have either a // Content-Id field or a Content-Location field. - if (p->getHeader()->hasField(fields::CONTENT_ID)) + if (p->getHeader()->hasField(fields::CONTENT_ID)) { cidParts.push_back(p); + } - if (p->getHeader()->hasField(fields::CONTENT_LOCATION)) + if (p->getHeader()->hasField(fields::CONTENT_LOCATION)) { locParts.push_back(p); + } findEmbeddedParts(*p, cidParts, locParts); } } -void htmlTextPart::addEmbeddedObject(const bodyPart& part, const string& id, - const embeddedObject::ReferenceType refType) -{ +void htmlTextPart::addEmbeddedObject( + const bodyPart& part, + const string& id, + const embeddedObject::ReferenceType refType +) { + // The object may already exists. This can happen if an object is // identified by both a Content-Id and a Content-Location. In this // case, there will be two embedded objects with two different IDs @@ -167,23 +184,33 @@ void htmlTextPart::addEmbeddedObject(const bodyPart& part, const string& id, shared_ptr ctf = part.getHeader()->findField(fields::CONTENT_TYPE); - if (ctf) - { + if (ctf) { + type = *ctf->getValue (); - } - else - { + + } else { + // No "Content-type" field: assume "application/octet-stream". } - m_objects.push_back(make_shared - (vmime::clone(part.getBody()->getContents()), - part.getBody()->getEncoding(), id, type, refType)); + m_objects.push_back( + make_shared ( + vmime::clone(part.getBody()->getContents()), + part.getBody()->getEncoding(), + id, + type, + refType + ) + ); } -void htmlTextPart::parse(const shared_ptr & message, const shared_ptr & parent, const shared_ptr & textPart) -{ +void htmlTextPart::parse( + const shared_ptr & message, + const shared_ptr & parent, + const shared_ptr & textPart +) { + // Search for possible embedded objects in the _whole_ message. std::vector > cidParts; std::vector > locParts; @@ -204,39 +231,42 @@ void htmlTextPart::parse(const shared_ptr & message, const share shared_ptr ctf = textPart->getHeader()->findField (fields::CONTENT_TYPE); - if (ctf && ctf->hasCharset()) + if (ctf && ctf->hasCharset()) { m_charset = ctf->getCharset(); - else + } else { m_charset = charset(); + } // Extract embedded objects. The algorithm is quite simple: for each previously // found inline part, we check if its CID/Location is contained in the HTML text. - for (std::vector >::const_iterator p = cidParts.begin() ; p != cidParts.end() ; ++p) - { + for (std::vector >::const_iterator p = cidParts.begin() ; + p != cidParts.end() ; ++p) { + const shared_ptr midField = (*p)->getHeader()->findField(fields::CONTENT_ID); const messageId mid = *midField->getValue (); if (data.find("CID:" + mid.getId()) != string::npos || - data.find("cid:" + mid.getId()) != string::npos) - { + data.find("cid:" + mid.getId()) != string::npos) { + // This part is referenced in the HTML text. // Add it to the embedded object list. addEmbeddedObject(**p, mid.getId(), embeddedObject::REFERENCED_BY_ID); } } - for (std::vector >::const_iterator p = locParts.begin() ; p != locParts.end() ; ++p) - { + for (std::vector >::const_iterator p = locParts.begin() ; + p != locParts.end() ; ++p) { + const shared_ptr locField = (*p)->getHeader()->findField(fields::CONTENT_LOCATION); const text loc = *locField->getValue (); const string locStr = loc.getWholeBuffer(); - if (data.find(locStr) != string::npos) - { + if (data.find(locStr) != string::npos) { + // This part is referenced in the HTML text. // Add it to the embedded object list. addEmbeddedObject(**p, locStr, embeddedObject::REFERENCED_BY_LOCATION); @@ -244,65 +274,68 @@ void htmlTextPart::parse(const shared_ptr & message, const share } // Extract plain text, if any. - if (!findPlainTextPart(*message, *parent, *textPart)) - { + if (!findPlainTextPart(*message, *parent, *textPart)) { + m_plainText = make_shared (); } } -bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& parent, const bodyPart& textPart) -{ +bool htmlTextPart::findPlainTextPart( + const bodyPart& part, + const bodyPart& parent, + const bodyPart& textPart +) { + // We search for the nearest "multipart/alternative" part. const shared_ptr ctf = part.getHeader()->findField(fields::CONTENT_TYPE); - if (ctf) - { + if (ctf) { + const mediaType type = *ctf->getValue (); if (type.getType() == mediaTypes::MULTIPART && - type.getSubType() == mediaTypes::MULTIPART_ALTERNATIVE) - { + type.getSubType() == mediaTypes::MULTIPART_ALTERNATIVE) { + shared_ptr foundPart; - for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i) - { + for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i) { + const shared_ptr p = part.getBody()->getPartAt(i); if (p.get() == &parent || // if "text/html" is in "multipart/related" - p.get() == &textPart) // if not... - { + p.get() == &textPart) { // if not... + foundPart = p; } } - if (foundPart) - { + if (foundPart) { + bool found = false; // Now, search for the alternative plain text part - for (size_t i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i) - { + for (size_t i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i) { + const shared_ptr p = part.getBody()->getPartAt(i); const shared_ptr ctf = p->getHeader()->findField(fields::CONTENT_TYPE); - if (ctf) - { + if (ctf) { const mediaType type = *ctf->getValue (); if (type.getType() == mediaTypes::TEXT && - type.getSubType() == mediaTypes::TEXT_PLAIN) - { + type.getSubType() == mediaTypes::TEXT_PLAIN) { + m_plainText = p->getBody()->getContents()->clone(); found = true; } - } - else - { + + } else { + // No "Content-type" field. } } @@ -313,16 +346,16 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren return found; } } - } - else - { + + } else { + // No "Content-type" field. } bool found = false; - for (size_t i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i) - { + for (size_t i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i) { + found = findPlainTextPart(*part.getBody()->getPartAt(i), parent, textPart); } @@ -330,50 +363,50 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren } -const charset& htmlTextPart::getCharset() const -{ +const charset& htmlTextPart::getCharset() const { + return m_charset; } -void htmlTextPart::setCharset(const charset& ch) -{ +void htmlTextPart::setCharset(const charset& ch) { + m_charset = ch; } -shared_ptr htmlTextPart::getPlainText() const -{ +shared_ptr htmlTextPart::getPlainText() const { + return m_plainText; } -void htmlTextPart::setPlainText(const shared_ptr & plainText) -{ +void htmlTextPart::setPlainText(const shared_ptr & plainText) { + m_plainText = plainText->clone(); } -const shared_ptr htmlTextPart::getText() const -{ +const shared_ptr htmlTextPart::getText() const { + return m_text; } -void htmlTextPart::setText(const shared_ptr & text) -{ +void htmlTextPart::setText(const shared_ptr & text) { + m_text = text->clone(); } -size_t htmlTextPart::getObjectCount() const -{ +size_t htmlTextPart::getObjectCount() const { + return m_objects.size(); } -shared_ptr htmlTextPart::getObjectAt(const size_t pos) const -{ +shared_ptr htmlTextPart::getObjectAt(const size_t pos) const { + return m_objects[pos]; } @@ -381,36 +414,42 @@ shared_ptr htmlTextPart::getObjectAt(const shared_ptr htmlTextPart::findObject(const string& id) const { for (std::vector >::const_iterator o = m_objects.begin() ; - o != m_objects.end() ; ++o) - { - if ((*o)->matchesId(id)) + o != m_objects.end() ; ++o) { + + if ((*o)->matchesId(id)) { return *o; + } } return null; } -bool htmlTextPart::hasObject(const string& id) const -{ +bool htmlTextPart::hasObject(const string& id) const { + for (std::vector >::const_iterator o = m_objects.begin() ; - o != m_objects.end() ; ++o) - { - if ((*o)->matchesId(id)) + o != m_objects.end() ; ++o) { + + if ((*o)->matchesId(id)) { return true; + } } return false; } -shared_ptr htmlTextPart::addObject - (const shared_ptr & data, const vmime::encoding& enc, const mediaType& type) -{ +shared_ptr htmlTextPart::addObject( + const shared_ptr & data, + const vmime::encoding& enc, + const mediaType& type +) { + const messageId mid(messageId::generateId()); - shared_ptr obj = make_shared - (data, enc, mid.getId(), type, embeddedObject::REFERENCED_BY_ID); + shared_ptr obj = make_shared ( + data, enc, mid.getId(), type, embeddedObject::REFERENCED_BY_ID + ); m_objects.push_back(obj); @@ -418,16 +457,20 @@ shared_ptr htmlTextPart::addObject } -shared_ptr htmlTextPart::addObject - (const shared_ptr & data, const mediaType& type) -{ +shared_ptr htmlTextPart::addObject( + const shared_ptr & data, + const mediaType& type +) { + return addObject(data, encoding::decide(data), type); } -shared_ptr htmlTextPart::addObject - (const string& data, const mediaType& type) -{ +shared_ptr htmlTextPart::addObject( + const string& data, + const mediaType& type +) { + shared_ptr cts = make_shared (data); return addObject(cts, encoding::decide(cts), type); } @@ -438,76 +481,85 @@ shared_ptr htmlTextPart::addObject // htmlTextPart::embeddedObject // -htmlTextPart::embeddedObject::embeddedObject - (const shared_ptr & data, const encoding& enc, - const string& id, const mediaType& type, const ReferenceType refType) +htmlTextPart::embeddedObject::embeddedObject( + const shared_ptr & data, + const encoding& enc, + const string& id, + const mediaType& type, + const ReferenceType refType +) : m_data(vmime::clone(data)), - m_encoding(enc), m_id(id), m_type(type), m_refType(refType) -{ + m_encoding(enc), + m_id(id), + m_type(type), + m_refType(refType) { + } -shared_ptr htmlTextPart::embeddedObject::getData() const -{ +shared_ptr htmlTextPart::embeddedObject::getData() const { + return m_data; } -const vmime::encoding htmlTextPart::embeddedObject::getEncoding() const -{ +const vmime::encoding htmlTextPart::embeddedObject::getEncoding() const { + return m_encoding; } -const string htmlTextPart::embeddedObject::getId() const -{ +const string htmlTextPart::embeddedObject::getId() const { + return m_id; } -const string htmlTextPart::embeddedObject::getReferenceId() const -{ - if (m_refType == REFERENCED_BY_ID) +const string htmlTextPart::embeddedObject::getReferenceId() const { + + if (m_refType == REFERENCED_BY_ID) { return string("cid:") + m_id; - else + } else { return m_id; + } } -const mediaType htmlTextPart::embeddedObject::getType() const -{ +const mediaType htmlTextPart::embeddedObject::getType() const { + return m_type; } -htmlTextPart::embeddedObject::ReferenceType htmlTextPart::embeddedObject::getReferenceType() const -{ +htmlTextPart::embeddedObject::ReferenceType htmlTextPart::embeddedObject::getReferenceType() const { + return m_refType; } -bool htmlTextPart::embeddedObject::matchesId(const string& id) const -{ - if (m_refType == REFERENCED_BY_ID) +bool htmlTextPart::embeddedObject::matchesId(const string& id) const { + + if (m_refType == REFERENCED_BY_ID) { return m_id == cleanId(id); - else + } else { return m_id == id; + } } // static -const string htmlTextPart::embeddedObject::cleanId(const string& id) -{ +const string htmlTextPart::embeddedObject::cleanId(const string& id) { + if (id.length() >= 4 && (id[0] == 'c' || id[0] == 'C') && (id[1] == 'i' || id[1] == 'I') && (id[2] == 'd' || id[2] == 'D') && - id[3] == ':') - { + id[3] == ':') { + return id.substr(4); - } - else - { + + } else { + return id; } } diff --git a/src/vmime/htmlTextPart.hpp b/src/vmime/htmlTextPart.hpp index 5ccdf4fa..ac2711b9 100644 --- a/src/vmime/htmlTextPart.hpp +++ b/src/vmime/htmlTextPart.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,15 +32,13 @@ #include "vmime/contentHandler.hpp" -namespace vmime -{ +namespace vmime { /** Text part of type 'text/html'. */ +class VMIME_EXPORT htmlTextPart : public textPart { -class VMIME_EXPORT htmlTextPart : public textPart -{ public: htmlTextPart(); @@ -59,13 +57,11 @@ public: /** Embedded object (eg: image for <IMG> tag). */ - class VMIME_EXPORT embeddedObject : public object - { + class VMIME_EXPORT embeddedObject : public object { public: /** The ways embedded objects can be referenced. */ - enum ReferenceType - { + enum ReferenceType { REFERENCED_BY_ID, /**< Referenced by Content-Id. */ REFERENCED_BY_LOCATION /**< Referenced by Content-Location. */ }; @@ -79,9 +75,13 @@ public: * @param refType reference type * @return a reference to a new embedded object */ - embeddedObject(const shared_ptr & data, const encoding& enc, - const string& id, const mediaType& type, - const ReferenceType refType); + embeddedObject( + const shared_ptr & data, + const encoding& enc, + const string& id, + const mediaType& type, + const ReferenceType refType + ); /** Return data stored in this embedded object. * @@ -185,7 +185,10 @@ public: * @return an unique object identifier used to identify the new * object among all other embedded objects */ - shared_ptr addObject(const string& data, const mediaType& type); + shared_ptr addObject( + const string& data, + const mediaType& type + ); /** Embed an object and returns a string which identifies it. * The returned identifier is suitable for use in the 'src' attribute @@ -196,7 +199,10 @@ public: * @return an unique object identifier used to identify the new * object among all other embedded objects */ - shared_ptr addObject(const shared_ptr & data, const mediaType& type); + shared_ptr addObject( + const shared_ptr & data, + const mediaType& type + ); /** Embed an object and returns a string which identifies it. * The returned identifier is suitable for use in the 'src' attribute @@ -208,13 +214,25 @@ public: * @return an unique object identifier used to identify the new * object among all other embedded objects */ - shared_ptr addObject(const shared_ptr & data, const encoding& enc, const mediaType& type); + shared_ptr addObject( + const shared_ptr & data, + const encoding& enc, + const mediaType& type + ); size_t getPartCount() const; - void generateIn(const shared_ptr & message, const shared_ptr & parent) const; - void parse(const shared_ptr & message, const shared_ptr & parent, const shared_ptr & textPart); + void generateIn( + const shared_ptr & message, + const shared_ptr & parent + ) const; + + void parse( + const shared_ptr & message, + const shared_ptr & parent, + const shared_ptr & textPart + ); private: @@ -224,10 +242,23 @@ private: std::vector > m_objects; - void findEmbeddedParts(const bodyPart& part, std::vector >& cidParts, std::vector >& locParts); - void addEmbeddedObject(const bodyPart& part, const string& id, const embeddedObject::ReferenceType refType); + void findEmbeddedParts( + const bodyPart& part, + std::vector >& cidParts, + std::vector >& locParts + ); - bool findPlainTextPart(const bodyPart& part, const bodyPart& parent, const bodyPart& textPart); + void addEmbeddedObject( + const bodyPart& part, + const string& id, + const embeddedObject::ReferenceType refType + ); + + bool findPlainTextPart( + const bodyPart& part, + const bodyPart& parent, + const bodyPart& textPart + ); }; diff --git a/src/vmime/mailbox.cpp b/src/vmime/mailbox.cpp index c4b230c4..b2a577db 100644 --- a/src/vmime/mailbox.cpp +++ b/src/vmime/mailbox.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -26,30 +26,32 @@ #include "vmime/utility/outputStreamStringAdapter.hpp" -namespace vmime -{ +namespace vmime { -mailbox::mailbox() -{ +mailbox::mailbox() { + } mailbox::mailbox(const mailbox& mbox) - : address(), m_name(mbox.m_name), m_email(mbox.m_email) -{ + : address(), + m_name(mbox.m_name), + m_email(mbox.m_email) { + } mailbox::mailbox(const emailAddress& email) - : m_email(email) -{ + : m_email(email) { + } mailbox::mailbox(const text& name, const emailAddress& email) - : m_name(name), m_email(email) -{ + : m_name(name), + m_email(email) { + } @@ -66,10 +68,14 @@ angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr */ -void mailbox::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void mailbox::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + const char* const pend = buffer.data() + end; const char* const pstart = buffer.data() + position; const char* p = pstart; @@ -78,8 +84,7 @@ void mailbox::parseImpl while (p < pend && parserHelpers::isSpace(*p)) ++p; // Current state for parsing machine - enum States - { + enum States { State_None, State_Name, State_Address @@ -92,96 +97,98 @@ void mailbox::parseImpl string address; bool hadBrackets = false; - while (p < pend) - { - if (state == State_Name) - { - if (*p == '<') - { + while (p < pend) { + + if (state == State_Name) { + + if (*p == '<') { + state = State_Address; continue; } - if (*p == '"') // Quoted string - { + if (*p == '"') { // Quoted string + ++p; bool escaped = false; - while (p < pend) - { - if (escaped) - { + while (p < pend) { + + if (escaped) { + name += *p; escaped = false; - } - else if (*p == '\\') - { + + } else if (*p == '\\') { + escaped = true; - } - else - { - if (*p == '"') - { + + } else { + + if (*p == '"') { + ++p; break; - } - else - { + + } else { + name += *p; } } ++p; } - } - else - { + + } else { + bool escaped = false; int comment = 0; - while (p < pend) - { - if (escaped) - { + while (p < pend) { + + if (escaped) { + if (!comment) name += *p; escaped = false; - } - else if (comment) - { - if (*p == '\\') + + } else if (comment) { + + if (*p == '\\') { escaped = true; - else if (*p == '(') + } else if (*p == '(') { ++comment; - else if (*p == ')') + } else if (*p == ')') { --comment; - } - else if (*p == '\\') - { + } + + } else if (*p == '\\') { + escaped = true; - } - else if (*p == '(') - { + + } else if (*p == '(') { + ++comment; - } - else if (*p == '<') - { + + } else if (*p == '<') { + // Erase any space between display name and
string::iterator q = name.end(); - while (q != name.begin() && parserHelpers::isSpace(*(q - 1))) + while (q != name.begin() && parserHelpers::isSpace(*(q - 1))) { --q; + } name.erase(q, name.end()); break; - } - else if (/* parserHelpers::isSpace(*p) || */ *p == '@') - { + + } else if (/* parserHelpers::isSpace(*p) || */ *p == '@') { + break; - } - else - { + + } else { + name += *p; } @@ -189,8 +196,8 @@ void mailbox::parseImpl } } - if (p < pend && *p == '@') - { + if (p < pend && *p == '@') { + // (*) Actually, we were parsing the local-part of an address // and not a display name... address = name; @@ -199,92 +206,94 @@ void mailbox::parseImpl bool escaped = false; int comment = 0; - while (p < pend) - { - if (escaped) - { + while (p < pend) { + + if (escaped) { + if (!comment) address += *p; escaped = false; - } - else if (comment) - { - if (*p == '\\') + + } else if (comment) { + + if (*p == '\\') { escaped = true; - else if (*p == '(') + } else if (*p == '(') { ++comment; - else if (*p == ')') + } else if (*p == ')') { --comment; - } - else if (*p == '\\') - { + } + + } else if (*p == '\\') { + escaped = true; - } - else if (*p == '(') - { + + } else if (*p == '(') { + ++comment; - } - else if (parserHelpers::isSpace(*p)) - { + + } else if (parserHelpers::isSpace(*p)) { + break; - } - else - { + + } else { + address += *p; } ++p; } - } - else - { + + } else { + while (p < pend && parserHelpers::isSpace(*p)) ++p; state = State_None; } - } - else if (state == State_Address) - { + + } else if (state == State_Address) { + bool escaped = false; int comment = 0; - while (p < pend) - { - if (escaped) - { + while (p < pend) { + + if (escaped) { + if (!comment) address += *p; escaped = false; - } - else if (comment) - { - if (*p == '\\') + + } else if (comment) { + + if (*p == '\\') { escaped = true; - else if (*p == '(') + } else if (*p == '(') { ++comment; - else if (*p == ')') + } else if (*p == ')') { --comment; - } - else if (*p == '(') - { + } + + } else if (*p == '(') { + ++comment; - } - else if (*p == '\\') - { + + } else if (*p == '\\') { + escaped = true; - } - else if (*p == '<') - { + + } else if (*p == '<') { + // If we found a '<' here, it means that the address // starts _only_ here...and the stuff we have parsed // before belongs actually to the display name! name += address; address.clear(); - } - else if (*p == '>') - { + + } else if (*p == '>') { + hadBrackets = true; break; - } - else if (!parserHelpers::isSpace(*p)) - { + + } else if (!parserHelpers::isSpace(*p)) { + address += *p; } @@ -292,54 +301,56 @@ void mailbox::parseImpl } break; - } - else - { + + } else { + while (p < pend && parserHelpers::isSpace(*p)) ++p; - if (p < pend) - { - //if (*p == '<') - state = State_Address; + if (p < pend) { + state = State_Address; } } } // Swap name and address when no address was found // (email address is mandatory, whereas name is optional). - if (address.empty() && !name.empty() && !hadBrackets) - { + if (address.empty() && !name.empty() && !hadBrackets) { + m_name.removeAllWords(); m_email.parse(ctx, name); - } - else - { + + } else { + text::decodeAndUnfold(ctx, name, &m_name); m_email.parse(ctx, address); } setParsedBounds(position, position + (p - pstart)); - if (newPosition) + if (newPosition) { *newPosition = position + (p - pstart); + } } -void mailbox::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void mailbox::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + string generatedEmail; utility::outputStreamStringAdapter generatedEmailStream(generatedEmail); m_email.generate(ctx, generatedEmailStream, 0, NULL); - if (m_name.isEmpty()) - { + if (m_name.isEmpty()) { + size_t pos = curLinePos; // No display name is specified, only email address. - if (curLinePos + generatedEmail.length() > ctx.getMaxLineLength()) - { + if (curLinePos + generatedEmail.length() > ctx.getMaxLineLength()) { + os << NEW_LINE_SEQUENCE; pos = NEW_LINE_SEQUENCE.length(); } @@ -347,11 +358,12 @@ void mailbox::generateImpl os << generatedEmail; pos += generatedEmail.length(); - if (newLinePos) + if (newLinePos) { *newLinePos = pos; - } - else - { + } + + } else { + // We have to encode the name: // - if it contains characters in a charset different from "US-ASCII", // - and/or if it contains one or more of these special chars: @@ -361,50 +373,52 @@ void mailbox::generateImpl // and/or contain the special chars. bool forceEncode = false; - for (size_t w = 0 ; !forceEncode && w != m_name.getWordCount() ; ++w) - { - if (m_name.getWordAt(w)->getCharset() == charset(charsets::US_ASCII)) - { + for (size_t w = 0 ; !forceEncode && w != m_name.getWordCount() ; ++w) { + + if (m_name.getWordAt(w)->getCharset() == charset(charsets::US_ASCII)) { + const string& buffer = m_name.getWordAt(w)->getBuffer(); for (string::const_iterator c = buffer.begin() ; - !forceEncode && c != buffer.end() ; ++c) - { - switch (*c) - { - case '\r': - case '\n': - case '\t': - case ';': - case ',': - case '<': case '>': - case '(': case ')': - case '@': - case '/': - case '?': - case '.': - case '=': - case ':': - case '"': + !forceEncode && c != buffer.end() ; ++c) { - forceEncode = true; - break; + switch (*c) { + + case '\r': + case '\n': + case '\t': + case ';': + case ',': + case '<': case '>': + case '(': case ')': + case '@': + case '/': + case '?': + case '.': + case '=': + case ':': + case '"': + + forceEncode = true; + break; } } - } - else - { + + } else { + forceEncode = true; } } size_t pos = curLinePos; - m_name.encodeAndFold(ctx, os, pos, &pos, - text::QUOTE_IF_POSSIBLE | (forceEncode ? text::FORCE_ENCODING : 0)); + m_name.encodeAndFold( + ctx, os, pos, &pos, + text::QUOTE_IF_POSSIBLE | (forceEncode ? text::FORCE_ENCODING : 0) + ); + + if (pos + generatedEmail.length() + 3 > ctx.getMaxLineLength()) { - if (pos + generatedEmail.length() + 3 > ctx.getMaxLineLength()) - { os << NEW_LINE_SEQUENCE; pos = NEW_LINE_SEQUENCE.length(); } @@ -412,26 +426,27 @@ void mailbox::generateImpl os << " <" << generatedEmail << ">"; pos += 2 + generatedEmail.length() + 1; - if (newLinePos) + if (newLinePos) { *newLinePos = pos; + } } } -bool mailbox::operator==(const class mailbox& mailbox) const -{ - return (m_name == mailbox.m_name && m_email == mailbox.m_email); +bool mailbox::operator==(const class mailbox& mailbox) const { + + return m_name == mailbox.m_name && m_email == mailbox.m_email; } -bool mailbox::operator!=(const class mailbox& mailbox) const -{ +bool mailbox::operator!=(const class mailbox& mailbox) const { + return !(*this == mailbox); } -void mailbox::copyFrom(const component& other) -{ +void mailbox::copyFrom(const component& other) { + const mailbox& source = dynamic_cast (other); m_name = source.m_name; @@ -439,64 +454,64 @@ void mailbox::copyFrom(const component& other) } -mailbox& mailbox::operator=(const mailbox& other) -{ +mailbox& mailbox::operator=(const mailbox& other) { + copyFrom(other); - return (*this); + return *this; } -shared_ptr mailbox::clone() const -{ +shared_ptr mailbox::clone() const { + return make_shared (*this); } -bool mailbox::isEmpty() const -{ +bool mailbox::isEmpty() const { + return m_email.isEmpty(); } -void mailbox::clear() -{ +void mailbox::clear() { + m_name.removeAllWords(); m_email = emailAddress(); } -bool mailbox::isGroup() const -{ - return (false); +bool mailbox::isGroup() const { + + return false; } -const text& mailbox::getName() const -{ - return (m_name); +const text& mailbox::getName() const { + + return m_name; } -void mailbox::setName(const text& name) -{ +void mailbox::setName(const text& name) { + m_name = name; } -const emailAddress& mailbox::getEmail() const -{ - return (m_email); +const emailAddress& mailbox::getEmail() const { + + return m_email; } -void mailbox::setEmail(const emailAddress& email) -{ +void mailbox::setEmail(const emailAddress& email) { + m_email = email; } -const std::vector > mailbox::getChildComponents() -{ +const std::vector > mailbox::getChildComponents() { + return std::vector >(); } diff --git a/src/vmime/mailbox.hpp b/src/vmime/mailbox.hpp index 88abc0f5..c563129d 100644 --- a/src/vmime/mailbox.hpp +++ b/src/vmime/mailbox.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,15 +30,13 @@ #include "vmime/text.hpp" -namespace vmime -{ +namespace vmime { /** A mailbox: full name + email (basic type). */ +class VMIME_EXPORT mailbox : public address { -class VMIME_EXPORT mailbox : public address -{ friend class mailboxGroup; friend class mailboxField; @@ -102,18 +100,20 @@ public: using address::generate; // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/mailboxField.cpp b/src/vmime/mailboxField.cpp index 29fe9d33..82ef5921 100644 --- a/src/vmime/mailboxField.cpp +++ b/src/vmime/mailboxField.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,45 +28,51 @@ #ifndef VMIME_BUILDING_DOC -namespace vmime -{ +namespace vmime { -mailboxField::mailboxField() -{ +mailboxField::mailboxField() { + } mailboxField::mailboxField(const mailboxField&) - : headerField() -{ + : headerField() { + } -void mailboxField::parse - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void mailboxField::parse( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + shared_ptr mbox = make_shared (); // Here, we cannot simply call "m_mailbox.parse()" because it // may have more than one address specified (even if this field // should contain only one). We are never too much careful... - shared_ptr
parsedAddress = address::parseNext(ctx, buffer, position, end, newPosition, NULL); + shared_ptr
parsedAddress = address::parseNext( + ctx, buffer, position, end, newPosition, NULL + ); + + if (parsedAddress) { + + if (parsedAddress->isGroup()) { - if (parsedAddress) - { - if (parsedAddress->isGroup()) - { // If it is a group of mailboxes, take the first // mailbox of the group shared_ptr group = dynamicCast (parsedAddress); - if (!group->isEmpty()) + if (!group->isEmpty()) { mbox = group->getMailboxAt(0); - } - else - { + } + + } else { + // Parse only if it is a mailbox mbox = dynamicCast (parsedAddress); } @@ -78,8 +84,9 @@ void mailboxField::parse setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } @@ -87,4 +94,3 @@ void mailboxField::parse #endif // VMIME_BUILDING_DOC - diff --git a/src/vmime/mailboxField.hpp b/src/vmime/mailboxField.hpp index ca6863c0..6c653616 100644 --- a/src/vmime/mailboxField.hpp +++ b/src/vmime/mailboxField.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,16 +33,14 @@ #ifndef VMIME_BUILDING_DOC -namespace vmime -{ +namespace vmime { /** Work-around for malformed header fields that are of type 'mailbox' * and contains multiple addresses. */ +class VMIME_EXPORT mailboxField : public headerField { -class VMIME_EXPORT mailboxField : public headerField -{ friend class headerFieldFactory; protected: @@ -52,9 +50,13 @@ protected: public: - void parse(const parsingContext& ctx, const string& buffer, - const size_t position, const size_t end, - size_t * newPosition = NULL); + void parse( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t * newPosition = NULL + ); }; @@ -65,4 +67,3 @@ public: #endif // VMIME_MAILBOXFIELD_HPP_INCLUDED - diff --git a/src/vmime/mailboxGroup.cpp b/src/vmime/mailboxGroup.cpp index 99ca8282..38a6e35e 100644 --- a/src/vmime/mailboxGroup.cpp +++ b/src/vmime/mailboxGroup.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -26,79 +26,83 @@ #include "vmime/exception.hpp" -namespace vmime -{ +namespace vmime { -mailboxGroup::mailboxGroup() -{ +mailboxGroup::mailboxGroup() { + } mailboxGroup::mailboxGroup(const mailboxGroup& mboxGroup) - : address() -{ + : address() { + copyFrom(mboxGroup); } mailboxGroup::mailboxGroup(const text& name) - : m_name(name) -{ + : m_name(name) { + } -mailboxGroup::~mailboxGroup() -{ +mailboxGroup::~mailboxGroup() { + removeAllMailboxes(); } -void mailboxGroup::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void mailboxGroup::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + const char* const pend = buffer.data() + end; const char* const pstart = buffer.data() + position; const char* p = pstart; - while (p < pend && parserHelpers::isSpace(*p)) + while (p < pend && parserHelpers::isSpace(*p)) { ++p; + } string name; - while (p < pend && *p != ':') - { + while (p < pend && *p != ':') { name += *p; ++p; } - if (p < pend && *p == ':') + if (p < pend && *p == ':') { ++p; + } size_t pos = position + (p - pstart); bool isLastAddressOfGroup = false; - while (pos < end && !isLastAddressOfGroup) - { - shared_ptr
parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, &isLastAddressOfGroup); + while (pos < end && !isLastAddressOfGroup) { + + shared_ptr
parsedAddress = + address::parseNext(ctx, buffer, pos, end, &pos, &isLastAddressOfGroup); + + if (parsedAddress) { + + if (parsedAddress->isGroup()) { - if (parsedAddress) - { - if (parsedAddress->isGroup()) - { shared_ptr group = dynamicCast (parsedAddress); // Sub-groups are not allowed in mailbox groups: so, we add all // the contents of the sub-group into this group... - for (size_t i = 0 ; i < group->getMailboxCount() ; ++i) - { + for (size_t i = 0 ; i < group->getMailboxCount() ; ++i) { m_list.push_back(vmime::clone(group->getMailboxAt(i))); } - } - else - { + + } else { + m_list.push_back(dynamicCast (parsedAddress)); } } @@ -108,15 +112,19 @@ void mailboxGroup::parseImpl setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void mailboxGroup::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void mailboxGroup::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + // We have to encode the name: // - if it contains characters in a charset different from "US-ASCII", // - and/or if it contains one or more of these special chars: @@ -126,32 +134,32 @@ void mailboxGroup::generateImpl // and/or contain the special chars. bool forceEncode = false; - for (size_t w = 0 ; !forceEncode && w < m_name.getWordCount() ; ++w) - { - if (m_name.getWordAt(w)->getCharset() == charset(charsets::US_ASCII)) - { + for (size_t w = 0 ; !forceEncode && w < m_name.getWordCount() ; ++w) { + + if (m_name.getWordAt(w)->getCharset() == charset(charsets::US_ASCII)) { + const string& buffer = m_name.getWordAt(w)->getBuffer(); for (string::const_iterator c = buffer.begin() ; - !forceEncode && c != buffer.end() ; ++c) - { - switch (*c) - { - case ' ': - case '\t': - case ';': - case ',': - case '<': case '>': - case '(': case ')': - case '@': - case '/': - case '?': - case '.': - case '=': - case ':': + !forceEncode && c != buffer.end() ; ++c) { - forceEncode = true; - break; + switch (*c) { + + case ' ': + case '\t': + case ';': + case ',': + case '<': case '>': + case '(': case ')': + case '@': + case '/': + case '?': + case '.': + case '=': + case ':': + + forceEncode = true; + break; } } } @@ -162,22 +170,24 @@ void mailboxGroup::generateImpl generationContext tmpCtx(ctx); tmpCtx.setMaxLineLength(ctx.getMaxLineLength() - 2); - m_name.encodeAndFold(ctx, os, pos, &pos, - forceEncode ? text::FORCE_ENCODING : 0); + m_name.encodeAndFold( + ctx, os, pos, &pos, + forceEncode ? text::FORCE_ENCODING : 0 + ); os << ":"; ++pos; for (std::vector >::const_iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { - if (it != m_list.begin()) - { + it != m_list.end() ; ++it) { + + if (it != m_list.begin()) { + os << ", "; pos += 2; - } - else - { + + } else { + os << " "; ++pos; } @@ -188,13 +198,14 @@ void mailboxGroup::generateImpl os << ";"; pos++; - if (newLinePos) + if (newLinePos) { *newLinePos = pos; + } } -void mailboxGroup::copyFrom(const component& other) -{ +void mailboxGroup::copyFrom(const component& other) { + const mailboxGroup& source = dynamic_cast (other); m_name = source.m_name; @@ -202,114 +213,132 @@ void mailboxGroup::copyFrom(const component& other) removeAllMailboxes(); for (std::vector >::const_iterator it = source.m_list.begin() ; - it != source.m_list.end() ; ++it) - { + it != source.m_list.end() ; ++it) { + m_list.push_back(vmime::clone(*it)); } } -shared_ptr mailboxGroup::clone() const -{ +shared_ptr mailboxGroup::clone() const { + return make_shared (*this); } -mailboxGroup& mailboxGroup::operator=(const component& other) -{ +mailboxGroup& mailboxGroup::operator=(const component& other) { + copyFrom(other); - return (*this); + return *this; } -const text& mailboxGroup::getName() const -{ - return (m_name); +const text& mailboxGroup::getName() const { + + return m_name; } -void mailboxGroup::setName(const text& name) -{ +void mailboxGroup::setName(const text& name) { + m_name = name; } -bool mailboxGroup::isGroup() const -{ - return (true); +bool mailboxGroup::isGroup() const { + + return true; } -bool mailboxGroup::isEmpty() const -{ - return (m_list.empty()); +bool mailboxGroup::isEmpty() const { + + return m_list.empty(); } -void mailboxGroup::appendMailbox(const shared_ptr & mbox) -{ +void mailboxGroup::appendMailbox(const shared_ptr & mbox) { + m_list.push_back(mbox); } -void mailboxGroup::insertMailboxBefore(const shared_ptr & beforeMailbox, const shared_ptr & mbox) -{ - const std::vector >::iterator it = std::find - (m_list.begin(), m_list.end(), beforeMailbox); +void mailboxGroup::insertMailboxBefore( + const shared_ptr & beforeMailbox, + const shared_ptr & mbox +) { - if (it == m_list.end()) + const std::vector >::iterator it = + std::find(m_list.begin(), m_list.end(), beforeMailbox); + + if (it == m_list.end()) { throw std::out_of_range("Invalid position"); + } m_list.insert(it, mbox); } -void mailboxGroup::insertMailboxBefore(const size_t pos, const shared_ptr & mbox) -{ - if (pos >= m_list.size()) +void mailboxGroup::insertMailboxBefore( + const size_t pos, + const shared_ptr & mbox +) { + + if (pos >= m_list.size()) { throw std::out_of_range("Invalid position"); + } m_list.insert(m_list.begin() + pos, mbox); } -void mailboxGroup::insertMailboxAfter(const shared_ptr & afterMailbox, const shared_ptr & mbox) -{ - const std::vector >::iterator it = std::find - (m_list.begin(), m_list.end(), afterMailbox); +void mailboxGroup::insertMailboxAfter( + const shared_ptr & afterMailbox, + const shared_ptr & mbox +) { - if (it == m_list.end()) + const std::vector >::iterator it = + std::find(m_list.begin(), m_list.end(), afterMailbox); + + if (it == m_list.end()) { throw std::out_of_range("Invalid position"); + } m_list.insert(it + 1, mbox); } -void mailboxGroup::insertMailboxAfter(const size_t pos, const shared_ptr & mbox) -{ - if (pos >= m_list.size()) +void mailboxGroup::insertMailboxAfter( + const size_t pos, + const shared_ptr & mbox +) { + + if (pos >= m_list.size()) { throw std::out_of_range("Invalid position"); + } m_list.insert(m_list.begin() + pos + 1, mbox); } -void mailboxGroup::removeMailbox(const shared_ptr & mbox) -{ - const std::vector >::iterator it = std::find - (m_list.begin(), m_list.end(), mbox); +void mailboxGroup::removeMailbox(const shared_ptr & mbox) { - if (it == m_list.end()) + const std::vector >::iterator it = + std::find(m_list.begin(), m_list.end(), mbox); + + if (it == m_list.end()) { throw std::out_of_range("Invalid position"); + } m_list.erase(it); } -void mailboxGroup::removeMailbox(const size_t pos) -{ - if (pos >= m_list.size()) +void mailboxGroup::removeMailbox(const size_t pos) { + + if (pos >= m_list.size()) { throw std::out_of_range("Invalid position"); + } const std::vector >::iterator it = m_list.begin() + pos; @@ -317,59 +346,59 @@ void mailboxGroup::removeMailbox(const size_t pos) } -void mailboxGroup::removeAllMailboxes() -{ +void mailboxGroup::removeAllMailboxes() { + m_list.clear(); } -size_t mailboxGroup::getMailboxCount() const -{ - return (m_list.size()); +size_t mailboxGroup::getMailboxCount() const { + + return m_list.size(); } -shared_ptr mailboxGroup::getMailboxAt(const size_t pos) -{ - return (m_list[pos]); +shared_ptr mailboxGroup::getMailboxAt(const size_t pos) { + + return m_list[pos]; } -const shared_ptr mailboxGroup::getMailboxAt(const size_t pos) const -{ - return (m_list[pos]); +const shared_ptr mailboxGroup::getMailboxAt(const size_t pos) const { + + return m_list[pos]; } -const std::vector > mailboxGroup::getMailboxList() const -{ +const std::vector > mailboxGroup::getMailboxList() const { + std::vector > list; list.reserve(m_list.size()); for (std::vector >::const_iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { + it != m_list.end() ; ++it) { + list.push_back(*it); } - return (list); + return list; } -const std::vector > mailboxGroup::getMailboxList() -{ - return (m_list); +const std::vector > mailboxGroup::getMailboxList() { + + return m_list; } -const std::vector > mailboxGroup::getChildComponents() -{ +const std::vector > mailboxGroup::getChildComponents() { + std::vector > list; copy_vector(m_list, list); - return (list); + return list; } diff --git a/src/vmime/mailboxGroup.hpp b/src/vmime/mailboxGroup.hpp index 7ae8fd9a..4a7da3e3 100644 --- a/src/vmime/mailboxGroup.hpp +++ b/src/vmime/mailboxGroup.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,15 +30,13 @@ #include "vmime/text.hpp" -namespace vmime -{ +namespace vmime { /** A group of mailboxes (basic type). */ +class VMIME_EXPORT mailboxGroup : public address { -class VMIME_EXPORT mailboxGroup : public address -{ public: mailboxGroup(); @@ -78,7 +76,10 @@ public: * @param mbox mailbox to insert * @throw std::out_of_range if the mailbox is not in the list */ - void insertMailboxBefore(const shared_ptr & beforeMailbox, const shared_ptr & mbox); + void insertMailboxBefore( + const shared_ptr & beforeMailbox, + const shared_ptr & mbox + ); /** Insert a new mailbox before the specified position. * @@ -87,7 +88,10 @@ public: * @param mbox mailbox to insert * @throw std::out_of_range if the position is out of range */ - void insertMailboxBefore(const size_t pos, const shared_ptr & mbox); + void insertMailboxBefore( + const size_t pos, + const shared_ptr & mbox + ); /** Insert a new mailbox after the specified mailbox. * @@ -95,7 +99,10 @@ public: * @param mbox mailbox to insert * @throw std::out_of_range if the mailbox is not in the list */ - void insertMailboxAfter(const shared_ptr & afterMailbox, const shared_ptr & mbox); + void insertMailboxAfter( + const shared_ptr & afterMailbox, + const shared_ptr & mbox + ); /** Insert a new mailbox after the specified position. * @@ -103,7 +110,10 @@ public: * @param mbox mailbox to insert * @throw std::out_of_range if the position is out of range */ - void insertMailboxAfter(const size_t pos, const shared_ptr & mbox); + void insertMailboxAfter( + const size_t pos, + const shared_ptr & mbox + ); /** Remove the specified mailbox from the list. * @@ -173,18 +183,20 @@ private: protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/mailboxList.cpp b/src/vmime/mailboxList.cpp index bc99818b..e7aba81b 100644 --- a/src/vmime/mailboxList.cpp +++ b/src/vmime/mailboxList.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -26,181 +26,198 @@ #include "vmime/exception.hpp" -namespace vmime -{ +namespace vmime { -mailboxList::mailboxList() -{ +mailboxList::mailboxList() { + } mailboxList::mailboxList(const mailboxList& mboxList) - : headerFieldValue(), m_list(mboxList.m_list) -{ + : headerFieldValue(), + m_list(mboxList.m_list) { + } -void mailboxList::appendMailbox(const shared_ptr & mbox) -{ +void mailboxList::appendMailbox(const shared_ptr & mbox) { + m_list.appendAddress(mbox); } -void mailboxList::insertMailboxBefore(const shared_ptr & beforeMailbox, const shared_ptr & mbox) -{ +void mailboxList::insertMailboxBefore( + const shared_ptr & beforeMailbox, + const shared_ptr & mbox +) { + m_list.insertAddressBefore(beforeMailbox, mbox); } -void mailboxList::insertMailboxBefore(const size_t pos, const shared_ptr & mbox) -{ +void mailboxList::insertMailboxBefore( + const size_t pos, + const shared_ptr & mbox +) { + m_list.insertAddressBefore(pos, mbox); } -void mailboxList::insertMailboxAfter(const shared_ptr & afterMailbox, const shared_ptr & mbox) -{ +void mailboxList::insertMailboxAfter( + const shared_ptr & afterMailbox, + const shared_ptr & mbox +) { + m_list.insertAddressAfter(afterMailbox, mbox); } -void mailboxList::insertMailboxAfter(const size_t pos, const shared_ptr & mbox) -{ +void mailboxList::insertMailboxAfter( + const size_t pos, + const shared_ptr & mbox +) { + m_list.insertAddressAfter(pos, mbox); } -void mailboxList::removeMailbox(const shared_ptr & mbox) -{ +void mailboxList::removeMailbox(const shared_ptr & mbox) { + m_list.removeAddress(mbox); } -void mailboxList::removeMailbox(const size_t pos) -{ +void mailboxList::removeMailbox(const size_t pos) { + m_list.removeAddress(pos); } -void mailboxList::removeAllMailboxes() -{ +void mailboxList::removeAllMailboxes() { + m_list.removeAllAddresses(); } -size_t mailboxList::getMailboxCount() const -{ - return (m_list.getAddressCount()); +size_t mailboxList::getMailboxCount() const { + + return m_list.getAddressCount(); } -bool mailboxList::isEmpty() const -{ - return (m_list.isEmpty()); +bool mailboxList::isEmpty() const { + + return m_list.isEmpty(); } -shared_ptr mailboxList::getMailboxAt(const size_t pos) -{ +shared_ptr mailboxList::getMailboxAt(const size_t pos) { + return dynamicCast (m_list.getAddressAt(pos)); } -const shared_ptr mailboxList::getMailboxAt(const size_t pos) const -{ +const shared_ptr mailboxList::getMailboxAt(const size_t pos) const { + return dynamicCast (m_list.getAddressAt(pos)); } -const std::vector > mailboxList::getMailboxList() const -{ +const std::vector > mailboxList::getMailboxList() const { + const std::vector > addrList = m_list.getAddressList(); std::vector > res; for (std::vector >::const_iterator it = addrList.begin() ; - it != addrList.end() ; ++it) - { + it != addrList.end() ; ++it) { + const shared_ptr mbox = dynamicCast (*it); - if (mbox != NULL) + if (mbox) { res.push_back(mbox); + } } - return (res); + return res; } -const std::vector > mailboxList::getMailboxList() -{ +const std::vector > mailboxList::getMailboxList() { + const std::vector > addrList = m_list.getAddressList(); std::vector > res; for (std::vector >::const_iterator it = addrList.begin() ; - it != addrList.end() ; ++it) - { + it != addrList.end() ; ++it) { + const shared_ptr mbox = dynamicCast (*it); - if (mbox != NULL) + if (mbox) { res.push_back(mbox); + } } - return (res); + return res; } -shared_ptr mailboxList::clone() const -{ +shared_ptr mailboxList::clone() const { + return make_shared (*this); } -void mailboxList::copyFrom(const component& other) -{ +void mailboxList::copyFrom(const component& other) { + const mailboxList& mboxList = dynamic_cast (other); m_list = mboxList.m_list; } -mailboxList& mailboxList::operator=(const mailboxList& other) -{ +mailboxList& mailboxList::operator=(const mailboxList& other) { + copyFrom(other); - return (*this); + return *this; } -const std::vector > mailboxList::getChildComponents() -{ - return (m_list.getChildComponents()); +const std::vector > mailboxList::getChildComponents() { + + return m_list.getChildComponents(); } -void mailboxList::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void mailboxList::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + m_list.removeAllAddresses(); size_t pos = position; - while (pos < end) - { + while (pos < end) { + shared_ptr
parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, NULL); - if (parsedAddress != NULL) - { - if (parsedAddress->isGroup()) - { + if (parsedAddress) { + + if (parsedAddress->isGroup()) { + shared_ptr group = dynamicCast (parsedAddress); - for (size_t i = 0 ; i < group->getMailboxCount() ; ++i) - { + for (size_t i = 0 ; i < group->getMailboxCount() ; ++i) { m_list.appendAddress(group->getMailboxAt(i)); } - } - else - { + + } else { + m_list.appendAddress(parsedAddress); } } @@ -208,20 +225,25 @@ void mailboxList::parseImpl setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void mailboxList::generateImpl(const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void mailboxList::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + m_list.generate(ctx, os, curLinePos, newLinePos); } -shared_ptr mailboxList::toAddressList() const -{ +shared_ptr mailboxList::toAddressList() const { + return vmime::clone(m_list); } diff --git a/src/vmime/mailboxList.hpp b/src/vmime/mailboxList.hpp index aca39136..8d799d2c 100644 --- a/src/vmime/mailboxList.hpp +++ b/src/vmime/mailboxList.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,8 +29,7 @@ #include "vmime/mailbox.hpp" -namespace vmime -{ +namespace vmime { /** A list of mailboxes (basic type). @@ -38,9 +37,8 @@ namespace vmime * This class works exactly like 'addressList' except it prevents user * from inserting mailbox groups where it is not allowed by the RFC. */ +class VMIME_EXPORT mailboxList : public headerFieldValue { -class VMIME_EXPORT mailboxList : public headerFieldValue -{ public: mailboxList(); @@ -163,18 +161,20 @@ private: protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/mdn/MDNHelper.cpp b/src/vmime/mdn/MDNHelper.cpp index d416532e..a21a1816 100644 --- a/src/vmime/mdn/MDNHelper.cpp +++ b/src/vmime/mdn/MDNHelper.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,16 +38,16 @@ namespace vmime { namespace mdn { -void MDNHelper::attachMDNRequest(const shared_ptr & msg, const mailboxList& mailboxes) -{ +void MDNHelper::attachMDNRequest(const shared_ptr & msg, const mailboxList& mailboxes) { + shared_ptr
hdr = msg->getHeader(); hdr->DispositionNotificationTo()->setValue(mailboxes); } -void MDNHelper::attachMDNRequest(const shared_ptr & msg, const mailbox& mbox) -{ +void MDNHelper::attachMDNRequest(const shared_ptr & msg, const mailbox& mbox) { + mailboxList mboxList; mboxList.appendMailbox(vmime::clone(mbox)); @@ -55,22 +55,23 @@ void MDNHelper::attachMDNRequest(const shared_ptr & msg, const mailbox& } -const std::vector MDNHelper::getPossibleMDNs(const shared_ptr & msg) -{ +const std::vector MDNHelper::getPossibleMDNs(const shared_ptr & msg) { + std::vector result; const shared_ptr hdr = msg->getHeader(); - if (hdr->hasField(fields::DISPOSITION_NOTIFICATION_TO)) - { + if (hdr->hasField(fields::DISPOSITION_NOTIFICATION_TO)) { + const mailboxList& dnto = *hdr->DispositionNotificationTo()->getValue (); - for (size_t i = 0 ; i < dnto.getMailboxCount() ; ++i) + for (size_t i = 0 ; i < dnto.getMailboxCount() ; ++i) { result.push_back(sendableMDNInfos(msg, *dnto.getMailboxAt(i))); + } } - return (result); + return result; } @@ -82,31 +83,32 @@ bool MDNHelper::isMDN(const shared_ptr & msg) // - a Content-Type field is present and its value is "multipart/report" // - a "report-type" parameter is present in the Content-Type field, // and its value is "disposition-notification" - if (hdr->hasField(fields::CONTENT_TYPE)) - { + if (hdr->hasField(fields::CONTENT_TYPE)) { + const contentTypeField& ctf = *dynamicCast (hdr->ContentType()); const mediaType type = *ctf.getValue (); if (type.getType() == vmime::mediaTypes::MULTIPART && - type.getSubType() == vmime::mediaTypes::MULTIPART_REPORT) - { + type.getSubType() == vmime::mediaTypes::MULTIPART_REPORT) { + if (ctf.hasParameter("report-type") && - ctf.getReportType() == "disposition-notification") - { - return (true); + ctf.getReportType() == "disposition-notification") { + + return true; } } } - return (false); + return false; } receivedMDNInfos MDNHelper::getReceivedMDN(const shared_ptr & msg) { - if (!isMDN(msg)) + if (!isMDN(msg)) { throw exceptions::invalid_argument(); + } return receivedMDNInfos(msg); } @@ -117,25 +119,28 @@ bool MDNHelper::needConfirmation(const shared_ptr & msg) shared_ptr hdr = msg->getHeader(); // No "Return-Path" field - if (!hdr->hasField(fields::RETURN_PATH)) + if (!hdr->hasField(fields::RETURN_PATH)) { return true; + } // More than one address in Disposition-Notification-To - if (hdr->hasField(fields::DISPOSITION_NOTIFICATION_TO)) - { + if (hdr->hasField(fields::DISPOSITION_NOTIFICATION_TO)) { + const mailboxList& dnto = *hdr->DispositionNotificationTo()->getValue (); - if (dnto.getMailboxCount() > 1) + if (dnto.getMailboxCount() > 1) { return true; - else if (dnto.getMailboxCount() == 0) + } else if (dnto.getMailboxCount() == 0) { return false; + } // Return-Path != Disposition-Notification-To const mailbox& mbox = *dnto.getMailboxAt(0); const path& rp = *hdr->ReturnPath()->getValue (); - if (mbox.getEmail() != rp.getLocalPart() + "@" + rp.getDomain()) + if (mbox.getEmail() != rp.getLocalPart() + "@" + rp.getDomain()) { return true; + } } // User confirmation not needed @@ -143,23 +148,27 @@ bool MDNHelper::needConfirmation(const shared_ptr & msg) } -shared_ptr MDNHelper::buildMDN(const sendableMDNInfos& mdnInfos, - const string& text, - const charset& ch, - const mailbox& expeditor, - const disposition& dispo, - const string& reportingUA, - const std::vector & reportingUAProducts, - const std::map & fields) -{ +shared_ptr MDNHelper::buildMDN( + const sendableMDNInfos& mdnInfos, + const string& text, + const charset& ch, + const mailbox& expeditor, + const disposition& dispo, + const string& reportingUA, + const std::vector & reportingUAProducts, + const std::map & fields +) { + // Create a new message shared_ptr msg = make_shared (); // Fill-in header fields shared_ptr
hdr = msg->getHeader(); - hdr->ContentType()->setValue(mediaType(vmime::mediaTypes::MULTIPART, - vmime::mediaTypes::MULTIPART_REPORT)); + hdr->ContentType()->setValue( + mediaType(vmime::mediaTypes::MULTIPART, vmime::mediaTypes::MULTIPART_REPORT) + ); + dynamicCast (hdr->ContentType())->setReportType("disposition-notification"); hdr->Disposition()->setValue(dispo); @@ -180,36 +189,42 @@ shared_ptr MDNHelper::buildMDN(const sendableMDNInfos& mdnInfos, dispo, reportingUA, reportingUAProducts, fields)); msg->getBody()->appendPart(createThirdMDNPart(mdnInfos)); - return (msg); + return msg; } -shared_ptr MDNHelper::createFirstMDNPart(const sendableMDNInfos& /* mdnInfos */, - const string& text, const charset& ch) -{ +shared_ptr MDNHelper::createFirstMDNPart( + const sendableMDNInfos& /* mdnInfos */, + const string& text, + const charset& ch +) { + shared_ptr part = make_shared (); // Header shared_ptr
hdr = part->getHeader(); - hdr->ContentType()->setValue(mediaType(vmime::mediaTypes::TEXT, - vmime::mediaTypes::TEXT_PLAIN)); + hdr->ContentType()->setValue( + mediaType(vmime::mediaTypes::TEXT, vmime::mediaTypes::TEXT_PLAIN) + ); dynamicCast (hdr->ContentType())->setCharset(ch); // Body part->getBody()->setContents(make_shared (text)); - return (part); + return part; } -shared_ptr MDNHelper::createSecondMDNPart(const sendableMDNInfos& mdnInfos, - const disposition& dispo, - const string& reportingUA, - const std::vector & reportingUAProducts, - const std::map & additionalFields) -{ +shared_ptr MDNHelper::createSecondMDNPart( + const sendableMDNInfos& mdnInfos, + const disposition& dispo, + const string& reportingUA, + const std::vector & reportingUAProducts, + const std::map & additionalFields +) { + shared_ptr part = make_shared (); // Header @@ -240,17 +255,18 @@ shared_ptr MDNHelper::createSecondMDNPart(const sendableMDNInfos& mdn header fields; // -- Reporting-UA (optional) - if (!reportingUA.empty()) - { + if (!reportingUA.empty()) { + string ruaText; ruaText = reportingUA; - for (unsigned int i = 0 ; i < reportingUAProducts.size() ; ++i) - { - if (i == 0) + for (unsigned int i = 0 ; i < reportingUAProducts.size() ; ++i) { + + if (i == 0) { ruaText += "; "; - else + } else { ruaText += ", "; + } ruaText += reportingUAProducts[i]; } @@ -272,8 +288,8 @@ shared_ptr MDNHelper::createSecondMDNPart(const sendableMDNInfos& mdn fields.appendField(fr); // -- Original-Message-ID - if (mdnInfos.getMessage()->getHeader()->hasField(vmime::fields::MESSAGE_ID)) - { + if (mdnInfos.getMessage()->getHeader()->hasField(vmime::fields::MESSAGE_ID)) { + fields.OriginalMessageId()->setValueConst (mdnInfos.getMessage()->getHeader()->MessageId()->getValue()); } @@ -284,37 +300,30 @@ shared_ptr MDNHelper::createSecondMDNPart(const sendableMDNInfos& mdn // -- Failure, Error and Warning fields std::map ::const_iterator it; - if (additionalFields.size() > 0) - { - it = additionalFields.find(vmime::fields::ERROR); - if (it != additionalFields.end()) - { - shared_ptr error = headerFieldFactory::getInstance()-> - create(vmime::fields::ERROR); + if (additionalFields.size() > 0) { + + if ((it = additionalFields.find(vmime::fields::ERROR)) != additionalFields.end()) { + + shared_ptr error = headerFieldFactory::getInstance()->create(vmime::fields::ERROR); error->setValue(it->second); fields.appendField(error); } - it = additionalFields.find(vmime::fields::WARNING); - if (it != additionalFields.end()) - { - shared_ptr warn = headerFieldFactory::getInstance()-> - create(vmime::fields::WARNING); + if ((it = additionalFields.find(vmime::fields::WARNING)) != additionalFields.end()) { + + shared_ptr warn = headerFieldFactory::getInstance()->create(vmime::fields::WARNING); warn->setValue(it->second); fields.appendField(warn); } - it = additionalFields.find(vmime::fields::FAILURE); - if (it != additionalFields.end()) - { - shared_ptr fail = headerFieldFactory::getInstance()-> - create(vmime::fields::FAILURE); + if ((it = additionalFields.find(vmime::fields::FAILURE)) != additionalFields.end()) { + + shared_ptr fail = headerFieldFactory::getInstance()->create(vmime::fields::FAILURE); fail->setValue(it->second); fields.appendField(fail); } } - std::ostringstream oss; utility::outputStreamAdapter vos(oss); @@ -322,12 +331,12 @@ shared_ptr MDNHelper::createSecondMDNPart(const sendableMDNInfos& mdn part->getBody()->setContents(make_shared (oss.str())); - return (part); + return part; } -shared_ptr MDNHelper::createThirdMDNPart(const sendableMDNInfos& mdnInfos) -{ +shared_ptr MDNHelper::createThirdMDNPart(const sendableMDNInfos& mdnInfos) { + shared_ptr part = make_shared (); // Header @@ -345,7 +354,7 @@ shared_ptr MDNHelper::createThirdMDNPart(const sendableMDNInfos& mdnI part->getBody()->setContents(make_shared (oss.str())); - return (part); + return part; } diff --git a/src/vmime/mdn/MDNHelper.hpp b/src/vmime/mdn/MDNHelper.hpp index d7ba2487..c1bec2f3 100644 --- a/src/vmime/mdn/MDNHelper.hpp +++ b/src/vmime/mdn/MDNHelper.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,9 +38,8 @@ namespace mdn { /** Helper for creating or extracting Message Disposition * Notifications (MDN), as defined in RFC-3798. */ +class VMIME_EXPORT MDNHelper { -class VMIME_EXPORT MDNHelper -{ public: /** Attach a MDN request to the specified message. @@ -105,28 +104,32 @@ public: * @param fields additional MDN fields, like "Error", "Warning" or "Failure" (optional) * @return a new message object containing the MDN */ - static shared_ptr buildMDN(const sendableMDNInfos& mdnInfos, - const string& text, - const charset& ch, - const mailbox& expeditor, - const disposition& dispo, - const string& reportingUA = NULL_STRING, - const std::vector & reportingUAProducts - = std::vector (), - const std::map & fields - = (std::map ())); + static shared_ptr buildMDN( + const sendableMDNInfos& mdnInfos, + const string& text, + const charset& ch, + const mailbox& expeditor, + const disposition& dispo, + const string& reportingUA = NULL_STRING, + const std::vector & reportingUAProducts = std::vector (), + const std::map & fields = std::map () + ); private: - static shared_ptr createFirstMDNPart(const sendableMDNInfos& mdnInfos, - const string& text, const charset& ch); - - static shared_ptr createSecondMDNPart(const sendableMDNInfos& mdnInfos, - const disposition& dispo, - const string& reportingUA, - const std::vector & reportingUAProducts, - const std::map & fields); + static shared_ptr createFirstMDNPart( + const sendableMDNInfos& mdnInfos, + const string& text, + const charset& ch + ); + static shared_ptr createSecondMDNPart( + const sendableMDNInfos& mdnInfos, + const disposition& dispo, + const string& reportingUA, + const std::vector & reportingUAProducts, + const std::map & fields + ); static shared_ptr createThirdMDNPart(const sendableMDNInfos& mdnInfos); }; diff --git a/src/vmime/mdn/MDNInfos.cpp b/src/vmime/mdn/MDNInfos.cpp index a70161b7..3efe9f9f 100644 --- a/src/vmime/mdn/MDNInfos.cpp +++ b/src/vmime/mdn/MDNInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,8 +29,8 @@ namespace mdn { -MDNInfos::~MDNInfos() -{ +MDNInfos::~MDNInfos() { + } diff --git a/src/vmime/mdn/MDNInfos.hpp b/src/vmime/mdn/MDNInfos.hpp index 030aa23e..f6d7929b 100644 --- a/src/vmime/mdn/MDNInfos.hpp +++ b/src/vmime/mdn/MDNInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,9 +35,8 @@ namespace mdn { /** Holds information about Message Disposition Notifications (MDN). */ +class VMIME_EXPORT MDNInfos : public object { -class VMIME_EXPORT MDNInfos : public object -{ public: virtual ~MDNInfos(); diff --git a/src/vmime/mdn/receivedMDNInfos.cpp b/src/vmime/mdn/receivedMDNInfos.cpp index 6036fcec..6f4463e5 100644 --- a/src/vmime/mdn/receivedMDNInfos.cpp +++ b/src/vmime/mdn/receivedMDNInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,52 +31,52 @@ namespace mdn { receivedMDNInfos::receivedMDNInfos(const shared_ptr & msg) - : m_msg(msg) -{ + : m_msg(msg) { + extract(); } receivedMDNInfos::receivedMDNInfos(const receivedMDNInfos& other) - : MDNInfos() -{ + : MDNInfos() { + copyFrom(other); } -receivedMDNInfos& receivedMDNInfos::operator=(const receivedMDNInfos& other) -{ +receivedMDNInfos& receivedMDNInfos::operator=(const receivedMDNInfos& other) { + copyFrom(other); - return (*this); + return *this; } -const shared_ptr receivedMDNInfos::getMessage() const -{ - return (m_msg); +const shared_ptr receivedMDNInfos::getMessage() const { + + return m_msg; } -const messageId receivedMDNInfos::getOriginalMessageId() const -{ - return (m_omid); +const messageId receivedMDNInfos::getOriginalMessageId() const { + + return m_omid; } -const disposition receivedMDNInfos::getDisposition() const -{ - return (m_disp); +const disposition receivedMDNInfos::getDisposition() const { + + return m_disp; } -const string receivedMDNInfos::getContentMIC() const -{ +const string receivedMDNInfos::getContentMIC() const { + return m_contentMIC; } -void receivedMDNInfos::copyFrom(const receivedMDNInfos& other) -{ +void receivedMDNInfos::copyFrom(const receivedMDNInfos& other) { + m_msg = other.m_msg; m_omid = other.m_omid; m_disp = other.m_disp; @@ -84,23 +84,24 @@ void receivedMDNInfos::copyFrom(const receivedMDNInfos& other) } -void receivedMDNInfos::extract() -{ +void receivedMDNInfos::extract() { + const shared_ptr bdy = m_msg->getBody(); - for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) - { + for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) { + const shared_ptr part = bdy->getPartAt(i); - if (!part->getHeader()->hasField(fields::CONTENT_TYPE)) + if (!part->getHeader()->hasField(fields::CONTENT_TYPE)) { continue; + } const mediaType& type = *part->getHeader()->ContentType()->getValue (); // Extract from second part (message/disposition-notification) if (type.getType() == vmime::mediaTypes::MESSAGE && - type.getSubType() == vmime::mediaTypes::MESSAGE_DISPOSITION_NOTIFICATION) - { + type.getSubType() == vmime::mediaTypes::MESSAGE_DISPOSITION_NOTIFICATION) { + std::ostringstream oss; utility::outputStreamAdapter vos(oss); @@ -113,20 +114,23 @@ void receivedMDNInfos::extract() shared_ptr omid = fields.findFieldValue (fields::ORIGINAL_MESSAGE_ID); - if (omid) + if (omid) { m_omid = *omid; + } shared_ptr disp = fields.findFieldValue (fields::DISPOSITION); - if (disp) + if (disp) { m_disp = *disp; + } shared_ptr contentMIC = fields.findFieldValue ("Received-content-MIC"); - if (contentMIC) + if (contentMIC) { m_contentMIC = contentMIC->generate(); + } } } } diff --git a/src/vmime/mdn/receivedMDNInfos.hpp b/src/vmime/mdn/receivedMDNInfos.hpp index f849a58e..7809acbc 100644 --- a/src/vmime/mdn/receivedMDNInfos.hpp +++ b/src/vmime/mdn/receivedMDNInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,9 +39,8 @@ namespace mdn { /** Holds information about a Message Disposition Notification (MDN) * that has been received. */ +class VMIME_EXPORT receivedMDNInfos : public MDNInfos { -class VMIME_EXPORT receivedMDNInfos : public MDNInfos -{ public: receivedMDNInfos(const shared_ptr & msg); diff --git a/src/vmime/mdn/sendableMDNInfos.cpp b/src/vmime/mdn/sendableMDNInfos.cpp index 85232c1f..281655fb 100644 --- a/src/vmime/mdn/sendableMDNInfos.cpp +++ b/src/vmime/mdn/sendableMDNInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,39 +29,40 @@ namespace mdn { sendableMDNInfos::sendableMDNInfos(const shared_ptr & msg, const mailbox& mbox) - : m_msg(msg), m_mailbox(mbox) -{ + : m_msg(msg), + m_mailbox(mbox) { + } sendableMDNInfos::sendableMDNInfos(const sendableMDNInfos& other) - : MDNInfos() -{ + : MDNInfos() { + copyFrom(other); } -sendableMDNInfos& sendableMDNInfos::operator=(const sendableMDNInfos& other) -{ +sendableMDNInfos& sendableMDNInfos::operator=(const sendableMDNInfos& other) { + copyFrom(other); - return (*this); + return *this; } -const shared_ptr sendableMDNInfos::getMessage() const -{ - return (m_msg); +const shared_ptr sendableMDNInfos::getMessage() const { + + return m_msg; } -const mailbox& sendableMDNInfos::getRecipient() const -{ - return (m_mailbox); +const mailbox& sendableMDNInfos::getRecipient() const { + + return m_mailbox; } -void sendableMDNInfos::copyFrom(const sendableMDNInfos& other) -{ +void sendableMDNInfos::copyFrom(const sendableMDNInfos& other) { + m_msg = other.m_msg; m_mailbox = other.m_mailbox; } diff --git a/src/vmime/mdn/sendableMDNInfos.hpp b/src/vmime/mdn/sendableMDNInfos.hpp index 2c40c3a8..5b69b948 100644 --- a/src/vmime/mdn/sendableMDNInfos.hpp +++ b/src/vmime/mdn/sendableMDNInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,9 +37,8 @@ namespace mdn { /** Holds information about a Message Disposition Notifications (MDN) * that is to be sent. */ +class VMIME_EXPORT sendableMDNInfos : public MDNInfos { -class VMIME_EXPORT sendableMDNInfos : public MDNInfos -{ public: sendableMDNInfos(const shared_ptr & msg, const mailbox& mbox); diff --git a/src/vmime/mediaType.cpp b/src/vmime/mediaType.cpp index 60486da7..95475937 100644 --- a/src/vmime/mediaType.cpp +++ b/src/vmime/mediaType.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -25,33 +25,37 @@ #include "vmime/parserHelpers.hpp" -namespace vmime -{ +namespace vmime { mediaType::mediaType() - : m_type(mediaTypes::APPLICATION), m_subType(mediaTypes::APPLICATION_OCTET_STREAM) -{ + : m_type(mediaTypes::APPLICATION), + m_subType(mediaTypes::APPLICATION_OCTET_STREAM) { + } -mediaType::mediaType(const string& type) -{ +mediaType::mediaType(const string& type) { + parse(type); } mediaType::mediaType(const string& type, const string& subType) : m_type(utility::stringUtils::toLower(type)), - m_subType(utility::stringUtils::toLower(subType)) -{ + m_subType(utility::stringUtils::toLower(subType)) { + } -void mediaType::parseImpl - (const parsingContext& /* ctx */, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void mediaType::parseImpl( + const parsingContext& /* ctx */, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + const char* const pend = buffer.data() + end; const char* const pstart = buffer.data() + position; const char* p = pstart; @@ -61,79 +65,95 @@ void mediaType::parseImpl while (p < pend && *p != '/') ++p; - m_type = utility::stringUtils::trim(utility::stringUtils::toLower( - string(buffer.begin() + typeStart, - buffer.begin() + position + (p - pstart)))); + m_type = utility::stringUtils::trim( + utility::stringUtils::toLower( + string( + buffer.begin() + typeStart, + buffer.begin() + position + (p - pstart) + ) + ) + ); + + if (p < pend) { - if (p < pend) - { // Skip '/' character ++p; // Extract the sub-type - m_subType = utility::stringUtils::trim(utility::stringUtils::toLower( - string(buffer.begin() + position + (p - pstart), - buffer.begin() + end))); + m_subType = utility::stringUtils::trim( + utility::stringUtils::toLower( + string( + buffer.begin() + position + (p - pstart), + buffer.begin() + end + ) + ) + ); } setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void mediaType::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void mediaType::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + const string value = m_type + "/" + m_subType; - if (curLinePos + value.length() > ctx.getMaxLineLength()) - { + if (curLinePos + value.length() > ctx.getMaxLineLength()) { + os << NEW_LINE_SEQUENCE; os << value; - if (newLinePos) + if (newLinePos) { *newLinePos = NEW_LINE_SEQUENCE_LENGTH + value.length(); - } - else - { + } + + } else { + os << value; - if (newLinePos) + if (newLinePos) { *newLinePos = curLinePos + value.length(); + } } } -bool mediaType::operator==(const mediaType& type) const -{ - return (m_type == type.m_type && m_subType == type.m_subType); +bool mediaType::operator==(const mediaType& type) const { + + return m_type == type.m_type && m_subType == type.m_subType; } -bool mediaType::operator!=(const mediaType& type) const -{ +bool mediaType::operator!=(const mediaType& type) const { + return !(*this == type); } -mediaType& mediaType::operator=(const string& type) -{ +mediaType& mediaType::operator=(const string& type) { + parse(type); - return (*this); + return *this; } -shared_ptr mediaType::clone() const -{ +shared_ptr mediaType::clone() const { + return make_shared (m_type, m_subType); } -void mediaType::copyFrom(const component& other) -{ +void mediaType::copyFrom(const component& other) { + const mediaType& mt = dynamic_cast (other); m_type = mt.m_type; @@ -141,45 +161,45 @@ void mediaType::copyFrom(const component& other) } -mediaType& mediaType::operator=(const mediaType& other) -{ +mediaType& mediaType::operator=(const mediaType& other) { + copyFrom(other); - return (*this); + return *this; } -const string& mediaType::getType() const -{ - return (m_type); +const string& mediaType::getType() const { + + return m_type; } -void mediaType::setType(const string& type) -{ +void mediaType::setType(const string& type) { + m_type = utility::stringUtils::toLower(type); } -const string& mediaType::getSubType() const -{ - return (m_subType); +const string& mediaType::getSubType() const { + + return m_subType; } -void mediaType::setSubType(const string& subType) -{ +void mediaType::setSubType(const string& subType) { + m_subType = utility::stringUtils::toLower(subType); } -void mediaType::setFromString(const string& type) -{ +void mediaType::setFromString(const string& type) { + parse(type); } -const std::vector > mediaType::getChildComponents() -{ +const std::vector > mediaType::getChildComponents() { + return std::vector >(); } diff --git a/src/vmime/mediaType.hpp b/src/vmime/mediaType.hpp index a7d6f4e4..4026167d 100644 --- a/src/vmime/mediaType.hpp +++ b/src/vmime/mediaType.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,15 +29,13 @@ #include "vmime/headerFieldValue.hpp" -namespace vmime -{ +namespace vmime { /** Content media type (basic type). */ +class VMIME_EXPORT mediaType : public headerFieldValue { -class VMIME_EXPORT mediaType : public headerFieldValue -{ public: mediaType(); @@ -98,18 +96,20 @@ protected: string m_subType; // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/message.cpp b/src/vmime/message.cpp index 76735496..f034cdb5 100644 --- a/src/vmime/message.cpp +++ b/src/vmime/message.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,18 +28,19 @@ #include -namespace vmime -{ +namespace vmime { -message::message() -{ +message::message() { + } -const string message::generate - (const size_t maxLineLength, const size_t curLinePos) const -{ +const string message::generate( + const size_t maxLineLength, + const size_t curLinePos +) const { + return bodyPart::generate(maxLineLength, curLinePos); } diff --git a/src/vmime/message.hpp b/src/vmime/message.hpp index 62ff77e1..1b97a5d7 100644 --- a/src/vmime/message.hpp +++ b/src/vmime/message.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,15 +29,13 @@ #include "vmime/generationContext.hpp" -namespace vmime -{ +namespace vmime { /** A MIME message. */ +class VMIME_EXPORT message : public bodyPart { -class VMIME_EXPORT message : public bodyPart -{ public: message(); @@ -49,13 +47,13 @@ public: // Override default generate() functions so that we can change // the default 'maxLineLength' value - const string generate - (const size_t maxLineLength = generationContext::getDefaultContext().getMaxLineLength(), - const size_t curLinePos = 0) const; + const string generate( + const size_t maxLineLength = generationContext::getDefaultContext().getMaxLineLength(), + const size_t curLinePos = 0 + ) const; }; - } // vmime diff --git a/src/vmime/messageAttachment.hpp b/src/vmime/messageAttachment.hpp index 641fd3e1..2d95d20b 100644 --- a/src/vmime/messageAttachment.hpp +++ b/src/vmime/messageAttachment.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,15 +29,13 @@ #include "vmime/message.hpp" -namespace vmime -{ +namespace vmime { /** Attachment of type message/rfc822. */ +class VMIME_EXPORT messageAttachment : public attachment { -class VMIME_EXPORT messageAttachment : public attachment -{ public: /** Return the message encapsulated in this attachment. @@ -52,4 +50,3 @@ public: #endif // VMIME_MESSAGEATTACHMENT_HPP_INCLUDED - diff --git a/src/vmime/messageBuilder.cpp b/src/vmime/messageBuilder.cpp index 445758c9..4de81bf4 100644 --- a/src/vmime/messageBuilder.cpp +++ b/src/vmime/messageBuilder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -27,24 +27,23 @@ #include "vmime/textPartFactory.hpp" -namespace vmime -{ +namespace vmime { -messageBuilder::messageBuilder() -{ +messageBuilder::messageBuilder() { + // By default there is one text part of type "text/plain" constructTextPart(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); } -messageBuilder::~messageBuilder() -{ +messageBuilder::~messageBuilder() { + } -shared_ptr messageBuilder::construct() const -{ +shared_ptr messageBuilder::construct() const { + // Create a new message shared_ptr msg = make_shared (); @@ -53,22 +52,26 @@ shared_ptr messageBuilder::construct() const if (((m_to.isEmpty()) || (m_to.getAddressAt(0)->isEmpty() && !m_to.getAddressAt(0)->isGroup())) && (m_cc.isEmpty() || m_cc.getAddressAt(0)->isEmpty()) && - (m_bcc.isEmpty() || m_bcc.getAddressAt(0)->isEmpty())) - { + (m_bcc.isEmpty() || m_bcc.getAddressAt(0)->isEmpty())) { + throw exceptions::no_recipient(); } - if (!m_from.isEmpty()) + if (!m_from.isEmpty()) { msg->getHeader()->From()->setValue(m_from); + } - if (!m_to.isEmpty()) + if (!m_to.isEmpty()) { msg->getHeader()->To()->setValue(m_to); + } - if (!m_cc.isEmpty()) + if (!m_cc.isEmpty()) { msg->getHeader()->Cc()->setValue(m_cc); + } - if (!m_bcc.isEmpty()) + if (!m_bcc.isEmpty()) { msg->getHeader()->Bcc()->setValue(m_bcc); + } // Add a "Date" field msg->getHeader()->Date()->setValue(datetime::now()); @@ -94,56 +97,60 @@ shared_ptr messageBuilder::construct() const // | // +-- ... (other attachments/parts) // - if (!m_attach.empty() && m_textPart->getPartCount() > 1) - { + if (!m_attach.empty() && m_textPart->getPartCount() > 1) { + // Set parent part (message) to "multipart/mixed" - msg->getHeader()->ContentType()->setValue - (mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED)); + msg->getHeader()->ContentType()->setValue( + mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED) + ); // Create a sub-part "multipart/alternative" for text parts shared_ptr subPart = make_shared (); msg->getBody()->appendPart(subPart); - subPart->getHeader()->ContentType()->setValue - (mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE)); + subPart->getHeader()->ContentType()->setValue( + mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE) + ); // Generate the text parts into this sub-part (normally, this // sub-part will have the "multipart/alternative" content-type...) m_textPart->generateIn(msg, subPart); - } - else - { + + } else { + // Generate the text part(s) directly into the message m_textPart->generateIn(msg, msg); // If any attachment, set message content-type to "multipart/mixed" - if (!m_attach.empty()) - { - msg->getHeader()->ContentType()->setValue - (mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED)); - } + if (!m_attach.empty()) { + + msg->getHeader()->ContentType()->setValue( + mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED) + ); + // Else, set it to "multipart/alternative" if there are more than one text part. - else if (m_textPart->getPartCount() > 1) - { - msg->getHeader()->ContentType()->setValue - (mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE)); + } else if (m_textPart->getPartCount() > 1) { + + msg->getHeader()->ContentType()->setValue( + mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE) + ); } } // Generate the attachments - if (!m_attach.empty()) - { + if (!m_attach.empty()) { + for (std::vector >::const_iterator a = m_attach.begin() ; - a != m_attach.end() ; ++a) - { + a != m_attach.end() ; ++a) { + (*a)->generateIn(msg); } } // If there is only one part in the message, move it into the message // (hence, the message will not be multipart...) - if (msg->getBody()->getPartCount() == 1) - { + if (msg->getBody()->getPartCount() == 1) { + const bodyPart& part = *msg->getBody()->getPartAt(0); // Make a full copy of the body, otherwise the copyFrom() will delete the body we're copying @@ -153,8 +160,8 @@ shared_ptr messageBuilder::construct() const const std::vector > fields = part.getHeader()->getFieldList(); for (std::vector >::const_iterator it = fields.begin() ; - it != fields.end() ; ++it) - { + it != fields.end() ; ++it) { + *(msg->getHeader()->getField((*it)->getName())) = **it; } @@ -163,32 +170,29 @@ shared_ptr messageBuilder::construct() const msg->getBody()->copyFrom(*bodyCopy); } - return (msg); + return msg; } -void messageBuilder::attach(const shared_ptr & attach) -{ +void messageBuilder::attach(const shared_ptr & attach) { + appendAttachment(attach); } -void messageBuilder::appendAttachment(const shared_ptr & attach) -{ +void messageBuilder::appendAttachment(const shared_ptr & attach) { + m_attach.push_back(attach); } -void messageBuilder::constructTextPart(const mediaType& type) -{ +void messageBuilder::constructTextPart(const mediaType& type) { + shared_ptr part; - try - { + try { part = textPartFactory::getInstance()->create(type); - } - catch (exceptions::no_factory_available& e) - { + } catch (exceptions::no_factory_available& e) { throw; } @@ -196,133 +200,133 @@ void messageBuilder::constructTextPart(const mediaType& type) } -shared_ptr messageBuilder::getTextPart() -{ - return (m_textPart); +shared_ptr messageBuilder::getTextPart() { + + return m_textPart; } -const mailbox& messageBuilder::getExpeditor() const -{ - return (m_from); +const mailbox& messageBuilder::getExpeditor() const { + + return m_from; } -void messageBuilder::setExpeditor(const mailbox& expeditor) -{ +void messageBuilder::setExpeditor(const mailbox& expeditor) { + m_from = expeditor; } -const addressList& messageBuilder::getRecipients() const -{ - return (m_to); +const addressList& messageBuilder::getRecipients() const { + + return m_to; } -addressList& messageBuilder::getRecipients() -{ - return (m_to); +addressList& messageBuilder::getRecipients() { + + return m_to; } -void messageBuilder::setRecipients(const addressList& recipients) -{ +void messageBuilder::setRecipients(const addressList& recipients) { + m_to = recipients; } -const addressList& messageBuilder::getCopyRecipients() const -{ - return (m_cc); +const addressList& messageBuilder::getCopyRecipients() const { + + return m_cc; } -addressList& messageBuilder::getCopyRecipients() -{ - return (m_cc); +addressList& messageBuilder::getCopyRecipients() { + + return m_cc; } -void messageBuilder::setCopyRecipients(const addressList& cc) -{ +void messageBuilder::setCopyRecipients(const addressList& cc) { + m_cc = cc; } -const addressList& messageBuilder::getBlindCopyRecipients() const -{ - return (m_bcc); +const addressList& messageBuilder::getBlindCopyRecipients() const { + + return m_bcc; } -addressList& messageBuilder::getBlindCopyRecipients() -{ - return (m_bcc); +addressList& messageBuilder::getBlindCopyRecipients() { + + return m_bcc; } -void messageBuilder::setBlindCopyRecipients(const addressList& bcc) -{ +void messageBuilder::setBlindCopyRecipients(const addressList& bcc) { + m_bcc = bcc; } -const text& messageBuilder::getSubject() const -{ - return (m_subject); +const text& messageBuilder::getSubject() const { + + return m_subject; } -void messageBuilder::setSubject(const text& subject) -{ +void messageBuilder::setSubject(const text& subject) { + m_subject = subject; } -void messageBuilder::removeAttachment(const size_t pos) -{ +void messageBuilder::removeAttachment(const size_t pos) { + m_attach.erase(m_attach.begin() + pos); } -const shared_ptr messageBuilder::getAttachmentAt(const size_t pos) const -{ - return (m_attach[pos]); +const shared_ptr messageBuilder::getAttachmentAt(const size_t pos) const { + + return m_attach[pos]; } -shared_ptr messageBuilder::getAttachmentAt(const size_t pos) -{ - return (m_attach[pos]); +shared_ptr messageBuilder::getAttachmentAt(const size_t pos) { + + return m_attach[pos]; } -size_t messageBuilder::getAttachmentCount() const -{ - return (m_attach.size()); +size_t messageBuilder::getAttachmentCount() const { + + return m_attach.size(); } -const std::vector > messageBuilder::getAttachmentList() const -{ +const std::vector > messageBuilder::getAttachmentList() const { + std::vector > res; res.reserve(m_attach.size()); for (std::vector >::const_iterator it = m_attach.begin() ; - it != m_attach.end() ; ++it) - { + it != m_attach.end() ; ++it) { + res.push_back(*it); } - return (res); + return res; } -const std::vector > messageBuilder::getAttachmentList() -{ - return (m_attach); +const std::vector > messageBuilder::getAttachmentList() { + + return m_attach; } diff --git a/src/vmime/messageBuilder.hpp b/src/vmime/messageBuilder.hpp index 4b5e15ce..bfe5ed9d 100644 --- a/src/vmime/messageBuilder.hpp +++ b/src/vmime/messageBuilder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,15 +37,13 @@ #include "vmime/bodyPart.hpp" -namespace vmime -{ +namespace vmime { /** A helper for building MIME messages. */ +class VMIME_EXPORT messageBuilder { -class VMIME_EXPORT messageBuilder -{ public: messageBuilder(); diff --git a/src/vmime/messageId.cpp b/src/vmime/messageId.cpp index 18926b4b..c8ea6426 100644 --- a/src/vmime/messageId.cpp +++ b/src/vmime/messageId.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -27,30 +27,32 @@ #include "vmime/parserHelpers.hpp" -namespace vmime -{ +namespace vmime { -messageId::messageId() -{ +messageId::messageId() { + } -messageId::messageId(const string& id) -{ +messageId::messageId(const string& id) { + parse(id); } messageId::messageId(const messageId& mid) - : headerFieldValue(), m_left(mid.m_left), m_right(mid.m_right) -{ + : headerFieldValue(), + m_left(mid.m_left), + m_right(mid.m_right) { + } messageId::messageId(const string& left, const string& right) - : m_left(left), m_right(right) -{ + : m_left(left), + m_right(right) { + } @@ -61,10 +63,14 @@ messageId::messageId(const string& left, const string& right) msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS] */ -void messageId::parseImpl - (const parsingContext& /* ctx */, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void messageId::parseImpl( + const parsingContext& /* ctx */, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + const char* const pend = buffer.data() + end; const char* const pstart = buffer.data() + position; const char* p = pstart; @@ -76,27 +82,26 @@ void messageId::parseImpl bool escape = false; bool stop = false; - for ( ; !stop && p < pend ; ++p) - { - if (escape) - { + for ( ; !stop && p < pend ; ++p) { + + if (escape) { + // Ignore this character - } - else - { - switch (*p) - { - case '(': ++commentLevel; break; - case ')': --commentLevel; break; - case '\\': escape = true; break; - case '<': - { - if (commentLevel == 0) - { - stop = true; - break; + + } else { + + switch (*p) { + + case '(': ++commentLevel; break; + case ')': --commentLevel; break; + case '\\': escape = true; break; + case '<': { + + if (commentLevel == 0) { + stop = true; + break; + } } - } } } @@ -105,27 +110,30 @@ void messageId::parseImpl // Fix for message ids without angle brackets (invalid) bool hasBrackets = true; - if (p == pend) // no opening angle bracket found - { + if (p == pend) { // no opening angle bracket found + hasBrackets = false; p = pstart; - while (p < pend && parserHelpers::isSpace(*p)) + while (p < pend && parserHelpers::isSpace(*p)) { ++p; + } } - if (p < pend) - { + if (p < pend) { + // Extract left part const size_t leftStart = position + (p - pstart); while (p < pend && *p != '@' && *p != '>') ++p; - m_left = string(buffer.begin() + leftStart, - buffer.begin() + position + (p - pstart)); + m_left = string( + buffer.begin() + leftStart, + buffer.begin() + position + (p - pstart) + ); + + if (p < pend) { - if (p < pend) - { // Skip '@' ++p; @@ -134,89 +142,110 @@ void messageId::parseImpl while (p < pend && *p != '>' && (hasBrackets || !parserHelpers::isSpace(*p))) ++p; - m_right = string(buffer.begin() + rightStart, - buffer.begin() + position + (p - pstart)); + m_right = string( + buffer.begin() + rightStart, + buffer.begin() + position + (p - pstart) + ); } } setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -shared_ptr messageId::parseNext - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +shared_ptr messageId::parseNext( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + size_t pos = position; - while (pos < end && parserHelpers::isSpace(buffer[pos])) + while (pos < end && parserHelpers::isSpace(buffer[pos])) { ++pos; + } + + if (pos != end) { - if (pos != end) - { const size_t begin = pos; - while (pos < end && !parserHelpers::isSpace(buffer[pos])) + while (pos < end && !parserHelpers::isSpace(buffer[pos])) { ++pos; + } shared_ptr mid = make_shared (); mid->parse(ctx, buffer, begin, pos, NULL); - if (newPosition != NULL) + if (newPosition) { *newPosition = pos; + } - return (mid); + return mid; } - if (newPosition != NULL) + if (newPosition) { *newPosition = end; + } return null; } -const string messageId::getId() const -{ - if (m_right.empty()) - return m_left; +const string messageId::getId() const { - return (m_left + '@' + m_right); + if (m_right.empty()) { + return m_left; + } + + return m_left + '@' + m_right; } -void messageId::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void messageId::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + size_t pos = curLinePos; - if (ctx.getWrapMessageId() && (curLinePos + m_left.length() + m_right.length() + 3 > ctx.getMaxLineLength())) - { + if (ctx.getWrapMessageId() && + (curLinePos + m_left.length() + m_right.length() + 3 > ctx.getMaxLineLength())) { + os << NEW_LINE_SEQUENCE; pos = NEW_LINE_SEQUENCE_LENGTH; } os << '<' << m_left; - if (m_right != "") os << '@' << m_right; + + if (m_right != "") { + os << '@' << m_right; + } + os << '>'; - if (newLinePos) + if (newLinePos) { *newLinePos = pos + m_left.length() + m_right.length() + 3; + } } -messageId& messageId::operator=(const string& id) -{ +messageId& messageId::operator=(const string& id) { + parse(id); - return (*this); + return *this; } -messageId messageId::generateId() -{ +messageId messageId::generateId() { + std::ostringstream left; left.imbue(std::locale::classic()); @@ -229,30 +258,30 @@ messageId messageId::generateId() left << std::hex << utility::random::getNext(); left << std::hex << utility::random::getNext(); - return (messageId(left.str(), platform::getHandler()->getHostName())); + return messageId(left.str(), platform::getHandler()->getHostName()); } -bool messageId::operator==(const messageId& mid) const -{ - return (m_left == mid.m_left && m_right == mid.m_right); +bool messageId::operator==(const messageId& mid) const { + + return m_left == mid.m_left && m_right == mid.m_right; } -bool messageId::operator!=(const messageId& mid) const -{ +bool messageId::operator!=(const messageId& mid) const { + return !(*this == mid); } -shared_ptr messageId::clone() const -{ +shared_ptr messageId::clone() const { + return make_shared (*this); } -void messageId::copyFrom(const component& other) -{ +void messageId::copyFrom(const component& other) { + const messageId& mid = dynamic_cast (other); m_left = mid.m_left; @@ -260,39 +289,39 @@ void messageId::copyFrom(const component& other) } -messageId& messageId::operator=(const messageId& other) -{ +messageId& messageId::operator=(const messageId& other) { + copyFrom(other); - return (*this); + return *this; } -const string& messageId::getLeft() const -{ - return (m_left); +const string& messageId::getLeft() const { + + return m_left; } -void messageId::setLeft(const string& left) -{ +void messageId::setLeft(const string& left) { + m_left = left; } -const string& messageId::getRight() const -{ - return (m_right); +const string& messageId::getRight() const { + + return m_right; } -void messageId::setRight(const string& right) -{ +void messageId::setRight(const string& right) { + m_right = right; } -const std::vector > messageId::getChildComponents() -{ +const std::vector > messageId::getChildComponents() { + return std::vector >(); } diff --git a/src/vmime/messageId.hpp b/src/vmime/messageId.hpp index 83527468..8edbe3e3 100644 --- a/src/vmime/messageId.hpp +++ b/src/vmime/messageId.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,15 +29,13 @@ #include "vmime/headerFieldValue.hpp" -namespace vmime -{ +namespace vmime { /** Message identifier (basic type). */ +class VMIME_EXPORT messageId : public headerFieldValue { -class VMIME_EXPORT messageId : public headerFieldValue -{ friend class messageIdSequence; public: @@ -107,18 +105,20 @@ private: protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; /** Parse a message-id from an input buffer. * @@ -128,12 +128,13 @@ protected: * @param newPosition will receive the new position in the input buffer * @return a new message-id object, or null if no more message-id can be parsed from the input buffer */ - static shared_ptr parseNext - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition); + static shared_ptr parseNext( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition + ); }; diff --git a/src/vmime/messageIdSequence.cpp b/src/vmime/messageIdSequence.cpp index 4365fa3c..2b68bcc7 100644 --- a/src/vmime/messageIdSequence.cpp +++ b/src/vmime/messageIdSequence.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -23,229 +23,254 @@ #include "vmime/messageIdSequence.hpp" #include "vmime/exception.hpp" + #include -namespace vmime -{ +namespace vmime { +messageIdSequence::messageIdSequence() { - -messageIdSequence::messageIdSequence() -{ } -messageIdSequence::~messageIdSequence() -{ +messageIdSequence::~messageIdSequence() { + removeAllMessageIds(); } messageIdSequence::messageIdSequence(const messageIdSequence& midSeq) - : headerFieldValue() -{ + : headerFieldValue() { + copyFrom(midSeq); } -shared_ptr messageIdSequence::clone() const -{ +shared_ptr messageIdSequence::clone() const { + return make_shared (*this); } -void messageIdSequence::copyFrom(const component& other) -{ +void messageIdSequence::copyFrom(const component& other) { + const messageIdSequence& midSeq = dynamic_cast (other); removeAllMessageIds(); - for (unsigned int i = 0 ; i < midSeq.m_list.size() ; ++i) + for (unsigned int i = 0 ; i < midSeq.m_list.size() ; ++i) { m_list.push_back(vmime::clone(midSeq.m_list[i])); + } } -messageIdSequence& messageIdSequence::operator=(const messageIdSequence& other) -{ +messageIdSequence& messageIdSequence::operator=(const messageIdSequence& other) { + copyFrom(other); - return (*this); + return *this; } -const std::vector > messageIdSequence::getChildComponents() -{ +const std::vector > messageIdSequence::getChildComponents() { + std::vector > res; copy_vector(m_list, res); - return (res); + return res; } -void messageIdSequence::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void messageIdSequence::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + removeAllMessageIds(); size_t pos = position; - while (pos < end) - { + while (pos < end) { + shared_ptr parsedMid = messageId::parseNext(ctx, buffer, pos, end, &pos); - if (parsedMid != NULL) + if (parsedMid) { m_list.push_back(parsedMid); + } } setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void messageIdSequence::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void messageIdSequence::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + size_t pos = curLinePos; - if (!m_list.empty()) - { + if (!m_list.empty()) { + generationContext tmpCtx(ctx); tmpCtx.setMaxLineLength(ctx.getMaxLineLength() - 2); - for (std::vector >::const_iterator it = m_list.begin() ; ; ) - { + for (std::vector >::const_iterator it = m_list.begin() ; ; ) { + (*it)->generate(ctx, os, pos, &pos); - if (++it == m_list.end()) + if (++it == m_list.end()) { break; + } os << " "; pos++; } } - if (newLinePos) + if (newLinePos) { *newLinePos = pos; + } } -void messageIdSequence::appendMessageId(const shared_ptr & mid) -{ +void messageIdSequence::appendMessageId(const shared_ptr & mid) { + m_list.push_back(mid); } -void messageIdSequence::insertMessageIdBefore(const shared_ptr & beforeMid, const shared_ptr & mid) -{ - const std::vector >::iterator it = std::find - (m_list.begin(), m_list.end(), beforeMid); +void messageIdSequence::insertMessageIdBefore( + const shared_ptr & beforeMid, + const shared_ptr & mid +) { - if (it == m_list.end()) + const std::vector >::iterator it = + std::find(m_list.begin(), m_list.end(), beforeMid); + + if (it == m_list.end()) { throw exceptions::no_such_message_id(); + } m_list.insert(it, mid); } -void messageIdSequence::insertMessageIdBefore(const size_t pos, const shared_ptr & mid) -{ +void messageIdSequence::insertMessageIdBefore( + const size_t pos, + const shared_ptr & mid +) { + m_list.insert(m_list.begin() + pos, mid); } -void messageIdSequence::insertMessageIdAfter(const shared_ptr & afterMid, const shared_ptr & mid) -{ - const std::vector >::iterator it = std::find - (m_list.begin(), m_list.end(), afterMid); +void messageIdSequence::insertMessageIdAfter( + const shared_ptr & afterMid, + const shared_ptr & mid +) { - if (it == m_list.end()) + const std::vector >::iterator it = + std::find(m_list.begin(), m_list.end(), afterMid); + + if (it == m_list.end()) { throw exceptions::no_such_message_id(); + } m_list.insert(it + 1, mid); } -void messageIdSequence::insertMessageIdAfter(const size_t pos, const shared_ptr & mid) -{ +void messageIdSequence::insertMessageIdAfter( + const size_t pos, + const shared_ptr & mid +) { + m_list.insert(m_list.begin() + pos + 1, mid); } void messageIdSequence::removeMessageId(const shared_ptr & mid) { - const std::vector >::iterator it = std::find - (m_list.begin(), m_list.end(), mid); + const std::vector >::iterator it = + std::find(m_list.begin(), m_list.end(), mid); - if (it == m_list.end()) + if (it == m_list.end()) { throw exceptions::no_such_message_id(); + } m_list.erase(it); } -void messageIdSequence::removeMessageId(const size_t pos) -{ +void messageIdSequence::removeMessageId(const size_t pos) { + const std::vector >::iterator it = m_list.begin() + pos; m_list.erase(it); } -void messageIdSequence::removeAllMessageIds() -{ +void messageIdSequence::removeAllMessageIds() { + m_list.clear(); } -size_t messageIdSequence::getMessageIdCount() const -{ - return (m_list.size()); +size_t messageIdSequence::getMessageIdCount() const { + + return m_list.size(); } -bool messageIdSequence::isEmpty() const -{ - return (m_list.empty()); +bool messageIdSequence::isEmpty() const { + + return m_list.empty(); } -const shared_ptr messageIdSequence::getMessageIdAt(const size_t pos) -{ - return (m_list[pos]); +const shared_ptr messageIdSequence::getMessageIdAt(const size_t pos) { + + return m_list[pos]; } -const shared_ptr messageIdSequence::getMessageIdAt(const size_t pos) const -{ - return (m_list[pos]); +const shared_ptr messageIdSequence::getMessageIdAt(const size_t pos) const { + + return m_list[pos]; } -const std::vector > messageIdSequence::getMessageIdList() const -{ +const std::vector > messageIdSequence::getMessageIdList() const { + std::vector > list; list.reserve(m_list.size()); for (std::vector >::const_iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { + it != m_list.end() ; ++it) { + list.push_back(*it); } - return (list); + return list; } -const std::vector > messageIdSequence::getMessageIdList() -{ - return (m_list); +const std::vector > messageIdSequence::getMessageIdList() { + + return m_list; } diff --git a/src/vmime/messageIdSequence.hpp b/src/vmime/messageIdSequence.hpp index b0eea464..e5d0eb64 100644 --- a/src/vmime/messageIdSequence.hpp +++ b/src/vmime/messageIdSequence.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,15 +28,13 @@ #include "vmime/messageId.hpp" -namespace vmime -{ +namespace vmime { /** A list of message identifiers (basic type). */ +class VMIME_EXPORT messageIdSequence : public headerFieldValue { -class VMIME_EXPORT messageIdSequence : public headerFieldValue -{ public: messageIdSequence(); @@ -80,7 +78,10 @@ public: * @param mid message-id to insert * @throw exceptions::no_such_message_id if the message-id is not in the list */ - void insertMessageIdAfter(const shared_ptr & afterMid, const shared_ptr & mid); + void insertMessageIdAfter( + const shared_ptr & afterMid, + const shared_ptr & mid + ); /** Insert a new message-id after the specified position. * @@ -151,18 +152,20 @@ private: protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/messageParser.cpp b/src/vmime/messageParser.cpp index c5295504..21ac09bb 100644 --- a/src/vmime/messageParser.cpp +++ b/src/vmime/messageParser.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,12 +33,11 @@ #include "vmime/contentDispositionField.hpp" -namespace vmime -{ +namespace vmime { -messageParser::messageParser(const string& buffer) -{ +messageParser::messageParser(const string& buffer) { + shared_ptr msg = make_shared (); msg->parse(buffer); @@ -46,27 +45,27 @@ messageParser::messageParser(const string& buffer) } -messageParser::messageParser(const shared_ptr & msg) -{ +messageParser::messageParser(const shared_ptr & msg) { + parse(msg); } -messageParser::~messageParser() -{ +messageParser::~messageParser() { + } -void messageParser::parse(const shared_ptr & msg) -{ +void messageParser::parse(const shared_ptr & msg) { + // Header fields (if field is present, copy its value, else do nothing) #ifndef VMIME_BUILDING_DOC -#define TRY_FIELD(var, type, name) \ - { \ +#define TRY_FIELD(var, type, name) { \ shared_ptr fldValue = msg->getHeader()->findFieldValue (name); \ - if (fldValue) \ + if (fldValue) { \ var = *fldValue; \ + } \ } TRY_FIELD(m_from, mailbox, fields::FROM); @@ -84,18 +83,19 @@ void messageParser::parse(const shared_ptr & msg) // Date shared_ptr recv = msg->getHeader()->findField(fields::RECEIVED); - if (recv) - { + if (recv) { + m_date = recv->getValue ()->getDate(); - } - else - { + + } else { + shared_ptr date = msg->getHeader()->findField(fields::DATE); - if (date) + if (date) { m_date = *date->getValue (); - else + } else { m_date = datetime::now(); + } } // Attachments @@ -106,58 +106,64 @@ void messageParser::parse(const shared_ptr & msg) } -void messageParser::findAttachments(const shared_ptr & msg) -{ +void messageParser::findAttachments(const shared_ptr & msg) { + m_attach = attachmentHelper::findAttachmentsInMessage(msg); } -void messageParser::findTextParts(const shared_ptr & msg, const shared_ptr & part) -{ +void messageParser::findTextParts( + const shared_ptr & msg, + const shared_ptr & part +) { + // Handle the case in which the message is not multipart: if the body part is // "text/*", take this part. - if (part->getBody()->getPartCount() == 0) - { + if (part->getBody()->getPartCount() == 0) { + mediaType type(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN); bool accept = false; shared_ptr ctf = msg->getHeader()->findField (fields::CONTENT_TYPE); - if (ctf) - { + if (ctf) { + const mediaType ctfType = *ctf->getValue (); - if (ctfType.getType() == mediaTypes::TEXT) - { + if (ctfType.getType() == mediaTypes::TEXT) { + type = ctfType; accept = true; } - } - else - { + + } else { + // No "Content-type" field: assume "text/plain". accept = true; } - if (accept) - { + if (accept) { + shared_ptr txtPart = textPartFactory::getInstance()->create(type); txtPart->parse(msg, msg, msg); m_textParts.push_back(txtPart); } - } + // Multipart message - else - { + } else { + findSubTextParts(msg, part); } } -bool messageParser::findSubTextParts(const shared_ptr & msg, const shared_ptr & part) -{ +bool messageParser::findSubTextParts( + const shared_ptr & msg, + const shared_ptr & part +) { + // In general, all the text parts are contained in parallel in the same // parent part (or message). // So, wherever the text parts are, all we have to do is to find the first @@ -165,62 +171,63 @@ bool messageParser::findSubTextParts(const shared_ptr & msg, con std::vector > textParts; - for (size_t i = 0 ; i < part->getBody()->getPartCount() ; ++i) - { + for (size_t i = 0 ; i < part->getBody()->getPartCount() ; ++i) { + const shared_ptr p = part->getBody()->getPartAt(i); shared_ptr ctf = p->getHeader()->findField (fields::CONTENT_TYPE); - if (ctf) - { + if (ctf) { + const mediaType type = *ctf->getValue (); contentDisposition disp; // default should be inline - if (type.getType() == mediaTypes::TEXT) - { + if (type.getType() == mediaTypes::TEXT) { + shared_ptr cdf = p->getHeader()-> findField (fields::CONTENT_DISPOSITION); - if (cdf) - { + if (cdf) { + disp = *cdf->getValue (); - } - else - { + + } else { + // No "Content-Disposition" field, assume default } - if (disp.getName() == contentDispositionTypes::INLINE) + if (disp.getName() == contentDispositionTypes::INLINE) { textParts.push_back(p); + } } - } - else - { + + } else { + // No "Content-type" field. } } - if (textParts.size()) - { + if (textParts.size()) { + // Okay. So we have found at least one text part for (std::vector >::const_iterator p = textParts.begin() ; - p != textParts.end() ; ++p) - { + p != textParts.end() ; ++p) { + const contentTypeField& ctf = *(*p)->getHeader()->findField (fields::CONTENT_TYPE); const mediaType type = *ctf.getValue (); - try - { + try { + shared_ptr txtPart = textPartFactory::getInstance()->create(type); txtPart->parse(msg, part, *p); m_textParts.push_back(txtPart); - } - catch (exceptions::no_factory_available& e) - { + + } catch (exceptions::no_factory_available& e) { + // Content-type not recognized. } } @@ -228,8 +235,7 @@ bool messageParser::findSubTextParts(const shared_ptr & msg, con bool found = false; - for (size_t i = 0 ; !found && (i < part->getBody()->getPartCount()) ; ++i) - { + for (size_t i = 0 ; !found && (i < part->getBody()->getPartCount()) ; ++i) { found = findSubTextParts(msg, part->getBody()->getPartAt(i)); } @@ -237,85 +243,85 @@ bool messageParser::findSubTextParts(const shared_ptr & msg, con } -const mailbox& messageParser::getExpeditor() const -{ - return (m_from); +const mailbox& messageParser::getExpeditor() const { + + return m_from; } -const addressList& messageParser::getRecipients() const -{ - return (m_to); +const addressList& messageParser::getRecipients() const { + + return m_to; } -const addressList& messageParser::getCopyRecipients() const -{ - return (m_cc); +const addressList& messageParser::getCopyRecipients() const { + + return m_cc; } -const addressList& messageParser::getBlindCopyRecipients() const -{ - return (m_bcc); +const addressList& messageParser::getBlindCopyRecipients() const { + + return m_bcc; } -const text& messageParser::getSubject() const -{ - return (m_subject); +const text& messageParser::getSubject() const { + + return m_subject; } -const datetime& messageParser::getDate() const -{ - return (m_date); +const datetime& messageParser::getDate() const { + + return m_date; } -const std::vector > messageParser::getAttachmentList() const -{ +const std::vector > messageParser::getAttachmentList() const { + return m_attach; } -size_t messageParser::getAttachmentCount() const -{ - return (m_attach.size()); +size_t messageParser::getAttachmentCount() const { + + return m_attach.size(); } -const shared_ptr messageParser::getAttachmentAt(const size_t pos) const -{ - return (m_attach[pos]); +const shared_ptr messageParser::getAttachmentAt(const size_t pos) const { + + return m_attach[pos]; } -const std::vector > messageParser::getTextPartList() const -{ +const std::vector > messageParser::getTextPartList() const { + std::vector > res; res.reserve(m_textParts.size()); for (std::vector >::const_iterator it = m_textParts.begin() ; - it != m_textParts.end() ; ++it) - { + it != m_textParts.end() ; ++it) { + res.push_back(*it); } - return (res); + return res; } -size_t messageParser::getTextPartCount() const -{ - return (m_textParts.size()); +size_t messageParser::getTextPartCount() const { + + return m_textParts.size(); } -const shared_ptr messageParser::getTextPartAt(const size_t pos) const -{ - return (m_textParts[pos]); +const shared_ptr messageParser::getTextPartAt(const size_t pos) const { + + return m_textParts[pos]; } diff --git a/src/vmime/messageParser.hpp b/src/vmime/messageParser.hpp index 5413862d..8019ef37 100644 --- a/src/vmime/messageParser.hpp +++ b/src/vmime/messageParser.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,15 +37,13 @@ #include "vmime/textPart.hpp" -namespace vmime -{ +namespace vmime { /** A helper for parsing MIME messages. */ +class VMIME_EXPORT messageParser { -class VMIME_EXPORT messageParser -{ public: messageParser(const string& buffer); @@ -148,8 +146,15 @@ private: void findAttachments(const shared_ptr & msg); - void findTextParts(const shared_ptr & msg, const shared_ptr & part); - bool findSubTextParts(const shared_ptr & msg, const shared_ptr & part); + void findTextParts( + const shared_ptr & msg, + const shared_ptr & part + ); + + bool findSubTextParts( + const shared_ptr & msg, + const shared_ptr & part + ); }; diff --git a/src/vmime/misc/importanceHelper.cpp b/src/vmime/misc/importanceHelper.cpp index ac298619..20c8e13b 100644 --- a/src/vmime/misc/importanceHelper.cpp +++ b/src/vmime/misc/importanceHelper.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,14 +31,14 @@ namespace vmime { namespace misc { -void importanceHelper::resetImportance(const shared_ptr & msg) -{ +void importanceHelper::resetImportance(const shared_ptr & msg) { + resetImportanceHeader(msg->getHeader()); } -void importanceHelper::resetImportanceHeader(const shared_ptr
& hdr) -{ +void importanceHelper::resetImportanceHeader(const shared_ptr
& hdr) { + shared_ptr fld; if ((fld = hdr->findField("X-Priority"))) @@ -49,19 +49,19 @@ void importanceHelper::resetImportanceHeader(const shared_ptr
& hdr) } -importanceHelper::Importance importanceHelper::getImportance(const shared_ptr & msg) -{ +importanceHelper::Importance importanceHelper::getImportance(const shared_ptr & msg) { + return getImportanceHeader(msg->getHeader()); } -importanceHelper::Importance importanceHelper::getImportanceHeader(const shared_ptr & hdr) -{ +importanceHelper::Importance importanceHelper::getImportanceHeader(const shared_ptr & hdr) { + // Try "X-Priority" field shared_ptr fld = hdr->findField("X-Priority"); - if (fld) - { + if (fld) { + const string value = fld->getValue ()->getWholeBuffer(); int n = IMPORTANCE_NORMAL; @@ -73,89 +73,88 @@ importanceHelper::Importance importanceHelper::getImportanceHeader(const shared_ Importance i = IMPORTANCE_NORMAL; - switch (n) - { - case 1: i = IMPORTANCE_HIGHEST; break; - case 2: i = IMPORTANCE_HIGH; break; - case 3: i = IMPORTANCE_NORMAL; break; - case 4: i = IMPORTANCE_LOW; break; - case 5: i = IMPORTANCE_LOWEST; break; + switch (n) { + case 1: i = IMPORTANCE_HIGHEST; break; + case 2: i = IMPORTANCE_HIGH; break; + case 3: i = IMPORTANCE_NORMAL; break; + case 4: i = IMPORTANCE_LOW; break; + case 5: i = IMPORTANCE_LOWEST; break; } - return (i); - } - else - { + return i; + + } else { + // Try "Importance" field fld = hdr->findField("Importance"); - if (fld) - { + if (fld) { + const string value = utility::stringUtils::toLower(utility::stringUtils::trim (fld->getValue ()->getWholeBuffer())); - if (value == "low") - return (IMPORTANCE_LOWEST); - else if (value == "high") - return (IMPORTANCE_HIGHEST); - else - return (IMPORTANCE_NORMAL); - } - else - { + if (value == "low") { + return IMPORTANCE_LOWEST; + } else if (value == "high") { + return IMPORTANCE_HIGHEST; + } else { + return IMPORTANCE_NORMAL; + } + + } else { + // Default - return (IMPORTANCE_NORMAL); + return IMPORTANCE_NORMAL; } } // Should not go here... - return (IMPORTANCE_NORMAL); + return IMPORTANCE_NORMAL; } -void importanceHelper::setImportance(const shared_ptr & msg, const Importance i) -{ +void importanceHelper::setImportance(const shared_ptr & msg, const Importance i) { + setImportanceHeader(msg->getHeader(), i); } -void importanceHelper::setImportanceHeader(const shared_ptr
& hdr, const Importance i) -{ +void importanceHelper::setImportanceHeader(const shared_ptr
& hdr, const Importance i) { + // "X-Priority:" Field shared_ptr fld = hdr->getField("X-Priority"); - switch (i) - { - case IMPORTANCE_HIGHEST: fld->setValue("1 (Highest)"); break; - case IMPORTANCE_HIGH: fld->setValue("2 (High)"); break; - default: - case IMPORTANCE_NORMAL: fld->setValue("3 (Normal)"); break; - case IMPORTANCE_LOW: fld->setValue("4 (Low)"); break; - case IMPORTANCE_LOWEST: fld->setValue("5 (Lowest)"); break; + switch (i) { + case IMPORTANCE_HIGHEST: fld->setValue("1 (Highest)"); break; + case IMPORTANCE_HIGH: fld->setValue("2 (High)"); break; + default: + case IMPORTANCE_NORMAL: fld->setValue("3 (Normal)"); break; + case IMPORTANCE_LOW: fld->setValue("4 (Low)"); break; + case IMPORTANCE_LOWEST: fld->setValue("5 (Lowest)"); break; } // "Importance:" Field fld = hdr->getField("Importance"); - switch (i) - { - case IMPORTANCE_HIGHEST: - case IMPORTANCE_HIGH: + switch (i) { - fld->setValue("high"); - break; + case IMPORTANCE_HIGHEST: + case IMPORTANCE_HIGH: - default: - case IMPORTANCE_NORMAL: + fld->setValue("high"); + break; - fld->setValue("normal"); - break; + default: + case IMPORTANCE_NORMAL: - case IMPORTANCE_LOWEST: - case IMPORTANCE_LOW: + fld->setValue("normal"); + break; - fld->setValue("low"); - break; + case IMPORTANCE_LOWEST: + case IMPORTANCE_LOW: + + fld->setValue("low"); + break; } } diff --git a/src/vmime/misc/importanceHelper.hpp b/src/vmime/misc/importanceHelper.hpp index 18dc2364..45e0bcc7 100644 --- a/src/vmime/misc/importanceHelper.hpp +++ b/src/vmime/misc/importanceHelper.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,14 +38,12 @@ namespace misc { * Basically, it wraps the use of the 'X-Priority' (non standard) * and 'Importance' (RFC-1327, RFC-1911) fields. */ +class VMIME_EXPORT importanceHelper { -class VMIME_EXPORT importanceHelper -{ public: /** Different levels of importance. */ - enum Importance - { + enum Importance { IMPORTANCE_HIGHEST, IMPORTANCE_HIGH, IMPORTANCE_NORMAL, diff --git a/src/vmime/net/builtinServices.inl b/src/vmime/net/builtinServices.inl index fa2f3fe3..2f67d2e0 100644 --- a/src/vmime/net/builtinServices.inl +++ b/src/vmime/net/builtinServices.inl @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 diff --git a/src/vmime/net/connectionInfos.hpp b/src/vmime/net/connectionInfos.hpp index 6c86eeab..0e519c7e 100644 --- a/src/vmime/net/connectionInfos.hpp +++ b/src/vmime/net/connectionInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,8 +40,8 @@ namespace net { /** Information about the connection used by a service. */ -class VMIME_EXPORT connectionInfos : public object -{ +class VMIME_EXPORT connectionInfos : public object { + public: /** Return the host to which the service is connected. diff --git a/src/vmime/net/defaultConnectionInfos.cpp b/src/vmime/net/defaultConnectionInfos.cpp index 335e8f6f..889f214a 100644 --- a/src/vmime/net/defaultConnectionInfos.cpp +++ b/src/vmime/net/defaultConnectionInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,19 +35,19 @@ namespace net { defaultConnectionInfos::defaultConnectionInfos(const string& host, const port_t port) - : m_host(host), m_port(port) -{ + : m_host(host), m_port(port) { + } -const string defaultConnectionInfos::getHost() const -{ +const string defaultConnectionInfos::getHost() const { + return m_host; } -port_t defaultConnectionInfos::getPort() const -{ +port_t defaultConnectionInfos::getPort() const { + return m_port; } diff --git a/src/vmime/net/defaultConnectionInfos.hpp b/src/vmime/net/defaultConnectionInfos.hpp index 50673bbc..f3488595 100644 --- a/src/vmime/net/defaultConnectionInfos.hpp +++ b/src/vmime/net/defaultConnectionInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,8 +40,8 @@ namespace net { /** Information about the connection used by a service. */ -class VMIME_EXPORT defaultConnectionInfos : public connectionInfos -{ +class VMIME_EXPORT defaultConnectionInfos : public connectionInfos { + public: defaultConnectionInfos(const string& host, const port_t port); diff --git a/src/vmime/net/defaultTimeoutHandler.cpp b/src/vmime/net/defaultTimeoutHandler.cpp index 306289c0..f5dcc7d6 100644 --- a/src/vmime/net/defaultTimeoutHandler.cpp +++ b/src/vmime/net/defaultTimeoutHandler.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard +// Copyright (C) 2002 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 @@ -34,39 +34,39 @@ namespace vmime { namespace net { -defaultTimeoutHandler::defaultTimeoutHandler() -{ +defaultTimeoutHandler::defaultTimeoutHandler() { + m_startTime = time(NULL); } -defaultTimeoutHandler::~defaultTimeoutHandler() -{ +defaultTimeoutHandler::~defaultTimeoutHandler() { + } -bool defaultTimeoutHandler::isTimeOut() -{ +bool defaultTimeoutHandler::isTimeOut() { + return time(NULL) - m_startTime >= 30; } -void defaultTimeoutHandler::resetTimeOut() -{ +void defaultTimeoutHandler::resetTimeOut() { + m_startTime = time(NULL); } -bool defaultTimeoutHandler::handleTimeOut() -{ +bool defaultTimeoutHandler::handleTimeOut() { + return false; } -shared_ptr defaultTimeoutHandlerFactory::create() -{ +shared_ptr defaultTimeoutHandlerFactory::create() { + return make_shared (); } diff --git a/src/vmime/net/defaultTimeoutHandler.hpp b/src/vmime/net/defaultTimeoutHandler.hpp index a45b9739..545c6550 100644 --- a/src/vmime/net/defaultTimeoutHandler.hpp +++ b/src/vmime/net/defaultTimeoutHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard +// Copyright (C) 2002 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 @@ -44,9 +44,8 @@ namespace net { * is to throw a exceptions::operation_timed_out exception when an * operation is blocked for more than 30 seconds. */ +class VMIME_EXPORT defaultTimeoutHandler : public timeoutHandler { -class VMIME_EXPORT defaultTimeoutHandler : public timeoutHandler -{ public: defaultTimeoutHandler(); @@ -64,9 +63,8 @@ private: /** A class that creates default timeout handlers. */ +class defaultTimeoutHandlerFactory : public timeoutHandlerFactory { -class defaultTimeoutHandlerFactory : public timeoutHandlerFactory -{ public: shared_ptr create(); diff --git a/src/vmime/net/events.cpp b/src/vmime/net/events.cpp index 6d056ae6..86608127 100644 --- a/src/vmime/net/events.cpp +++ b/src/vmime/net/events.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,13 +42,13 @@ namespace events { // event // -event::event() -{ +event::event() { + } -event::~event() -{ +event::~event() { + } @@ -59,10 +59,14 @@ event::~event() const char* messageCountEvent::EVENT_CLASS = "messageCountEvent"; -messageCountEvent::messageCountEvent - (const shared_ptr & folder, const Types type, const std::vector & nums) - : m_folder(folder), m_type(type) -{ +messageCountEvent::messageCountEvent( + const shared_ptr & folder, + const Types type, + const std::vector & nums +) + : m_folder(folder), + m_type(type) { + m_nums.resize(nums.size()); std::copy(nums.begin(), nums.end(), m_nums.begin()); } @@ -73,17 +77,18 @@ messageCountEvent::Types messageCountEvent::getType() const { return (m_type); } const std::vector & messageCountEvent::getNumbers() const { return (m_nums); } -void messageCountEvent::dispatch(messageCountListener* listener) -{ - if (m_type == TYPE_ADDED) +void messageCountEvent::dispatch(messageCountListener* listener) { + + if (m_type == TYPE_ADDED) { listener->messagesAdded(dynamicCast (shared_from_this())); - else + } else { listener->messagesRemoved(dynamicCast (shared_from_this())); + } } -const char* messageCountEvent::getClass() const -{ +const char* messageCountEvent::getClass() const { + return EVENT_CLASS; } @@ -95,10 +100,14 @@ const char* messageCountEvent::getClass() const const char* messageChangedEvent::EVENT_CLASS = "messageChangedEvent"; -messageChangedEvent::messageChangedEvent - (const shared_ptr & folder, const Types type, const std::vector & nums) - : m_folder(folder), m_type(type) -{ +messageChangedEvent::messageChangedEvent( + const shared_ptr & folder, + const Types type, + const std::vector & nums +) + : m_folder(folder), + m_type(type) { + m_nums.resize(nums.size()); std::copy(nums.begin(), nums.end(), m_nums.begin()); } @@ -109,14 +118,14 @@ messageChangedEvent::Types messageChangedEvent::getType() const { return (m_type const std::vector & messageChangedEvent::getNumbers() const { return (m_nums); } -void messageChangedEvent::dispatch(messageChangedListener* listener) -{ +void messageChangedEvent::dispatch(messageChangedListener* listener) { + listener->messageChanged(dynamicCast (shared_from_this())); } -const char* messageChangedEvent::getClass() const -{ +const char* messageChangedEvent::getClass() const { + return EVENT_CLASS; } @@ -128,11 +137,17 @@ const char* messageChangedEvent::getClass() const const char* folderEvent::EVENT_CLASS = "folderEvent"; -folderEvent::folderEvent - (const shared_ptr & folder, const Types type, - const utility::path& oldPath, const utility::path& newPath) - : m_folder(folder), m_type(type), m_oldPath(oldPath), m_newPath(newPath) -{ +folderEvent::folderEvent( + const shared_ptr & folder, + const Types type, + const utility::path& oldPath, + const utility::path& newPath +) + : m_folder(folder), + m_type(type), + m_oldPath(oldPath), + m_newPath(newPath) { + } @@ -140,19 +155,18 @@ shared_ptr folderEvent::getFolder() const { return (m_folder); } folderEvent::Types folderEvent::getType() const { return (m_type); } -void folderEvent::dispatch(folderListener* listener) -{ - switch (m_type) - { - case TYPE_CREATED: listener->folderCreated(dynamicCast (shared_from_this())); break; - case TYPE_RENAMED: listener->folderRenamed(dynamicCast (shared_from_this())); break; - case TYPE_DELETED: listener->folderDeleted(dynamicCast (shared_from_this())); break; +void folderEvent::dispatch(folderListener* listener) { + + switch (m_type) { + case TYPE_CREATED: listener->folderCreated(dynamicCast (shared_from_this())); break; + case TYPE_RENAMED: listener->folderRenamed(dynamicCast (shared_from_this())); break; + case TYPE_DELETED: listener->folderDeleted(dynamicCast (shared_from_this())); break; } } -const char* folderEvent::getClass() const -{ +const char* folderEvent::getClass() const { + return EVENT_CLASS; } diff --git a/src/vmime/net/events.hpp b/src/vmime/net/events.hpp index 772c4d9d..2ad64e79 100644 --- a/src/vmime/net/events.hpp +++ b/src/vmime/net/events.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,9 +46,8 @@ namespace events { /** Event occurring on folders or messages. */ +class VMIME_EXPORT event : public object, public enable_shared_from_this { -class VMIME_EXPORT event : public object, public enable_shared_from_this -{ public: event(); @@ -60,22 +59,24 @@ public: /** Event about the message count in a folder. */ +class VMIME_EXPORT messageCountEvent : public event { -class VMIME_EXPORT messageCountEvent : public event -{ public: static const char* EVENT_CLASS; - enum Types - { + enum Types { TYPE_ADDED, /**< New messages have been added. */ TYPE_REMOVED /**< Messages have been expunged (renumbering). */ }; - messageCountEvent(const shared_ptr & folder, const Types type, const std::vector & nums); + messageCountEvent( + const shared_ptr & folder, + const Types type, + const std::vector & nums + ); /** Return the folder in which messages have been added/removed. * @@ -114,9 +115,8 @@ private: /** Listener for events about the message count in a folder. */ +class VMIME_EXPORT messageCountListener { -class VMIME_EXPORT messageCountListener -{ protected: virtual ~messageCountListener() { } @@ -130,21 +130,23 @@ public: /** Event occuring on a message. */ +class VMIME_EXPORT messageChangedEvent : public event { -class VMIME_EXPORT messageChangedEvent : public event -{ public: static const char* EVENT_CLASS; - enum Types - { + enum Types { TYPE_FLAGS // flags changed }; - messageChangedEvent(const shared_ptr & folder, const Types type, const std::vector & nums); + messageChangedEvent( + const shared_ptr & folder, + const Types type, + const std::vector & nums + ); /** Return the folder in which messages have changed. * @@ -183,9 +185,8 @@ private: /** Listener for events occuring on a message. */ +class VMIME_EXPORT messageChangedListener { -class VMIME_EXPORT messageChangedListener -{ protected: virtual ~messageChangedListener() { } @@ -198,23 +199,26 @@ public: /** Event occuring on a folder. */ +class VMIME_EXPORT folderEvent : public event { -class VMIME_EXPORT folderEvent : public event -{ public: static const char* EVENT_CLASS; - enum Types - { + enum Types { TYPE_CREATED, /**< A folder was created. */ TYPE_DELETED, /**< A folder was deleted. */ TYPE_RENAMED /**< A folder was renamed. */ }; - folderEvent(const shared_ptr & folder, const Types type, const utility::path& oldPath, const utility::path& newPath); + folderEvent( + const shared_ptr & folder, + const Types type, + const utility::path& oldPath, + const utility::path& newPath + ); /** Return the folder on which the event occurred. * @@ -248,9 +252,8 @@ private: /** Listener for events occuring on a folder. */ +class VMIME_EXPORT folderListener { -class VMIME_EXPORT folderListener -{ protected: virtual ~folderListener() { } diff --git a/src/vmime/net/fetchAttributes.cpp b/src/vmime/net/fetchAttributes.cpp index d499674c..d9b54b83 100644 --- a/src/vmime/net/fetchAttributes.cpp +++ b/src/vmime/net/fetchAttributes.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,51 +39,54 @@ namespace net { fetchAttributes::fetchAttributes() - : m_predefinedAttribs(0) -{ + : m_predefinedAttribs(0) { + } fetchAttributes::fetchAttributes(const int attribs) - : m_predefinedAttribs(attribs) -{ + : m_predefinedAttribs(attribs) { + } fetchAttributes::fetchAttributes(const fetchAttributes& attribs) - : object() -{ + : object() { + m_predefinedAttribs = attribs.m_predefinedAttribs; m_headers = attribs.m_headers; } -void fetchAttributes::add(const int attribs) -{ +void fetchAttributes::add(const int attribs) { + m_predefinedAttribs |= attribs; } -void fetchAttributes::add(const string& header) -{ +void fetchAttributes::add(const string& header) { + m_headers.push_back(utility::stringUtils::toLower(header)); } -bool fetchAttributes::has(const int attribs) const -{ +bool fetchAttributes::has(const int attribs) const { + return (m_predefinedAttribs & attribs) != 0; } -bool fetchAttributes::has(const string& header) const -{ - return std::find(m_headers.begin(), m_headers.end(), utility::stringUtils::toLower(header)) != m_headers.end(); +bool fetchAttributes::has(const string& header) const { + + return std::find( + m_headers.begin(), m_headers.end(), + utility::stringUtils::toLower(header) + ) != m_headers.end(); } -const std::vector fetchAttributes::getHeaderFields() const -{ +const std::vector fetchAttributes::getHeaderFields() const { + return m_headers; } diff --git a/src/vmime/net/fetchAttributes.hpp b/src/vmime/net/fetchAttributes.hpp index d01e9f50..19d92627 100644 --- a/src/vmime/net/fetchAttributes.hpp +++ b/src/vmime/net/fetchAttributes.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,14 +42,13 @@ namespace net { /** Holds a set of attributes to fetch for a message. */ -class VMIME_EXPORT fetchAttributes : public object -{ +class VMIME_EXPORT fetchAttributes : public object { + public: /** Predefined attributes that can be fetched. */ - enum PredefinedFetchAttributes - { + enum PredefinedFetchAttributes { ENVELOPE = (1 << 0), /**< Sender, recipients, date, subject. */ STRUCTURE = (1 << 1), /**< MIME structure (body parts). */ CONTENT_INFO = (1 << 2), /**< Top-level content type. */ @@ -114,8 +113,7 @@ public: * @param attribs one or more OR-ed values of the PredefinedFetchAttributes enum * @return true if the specified attributes are to be fetched */ - VMIME_DEPRECATED inline bool operator&(const int attribs) const - { + VMIME_DEPRECATED inline bool operator&(const int attribs) const { return has(attribs); } diff --git a/src/vmime/net/folder.cpp b/src/vmime/net/folder.cpp index 38f60523..6e01b602 100644 --- a/src/vmime/net/folder.cpp +++ b/src/vmime/net/folder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,96 +36,91 @@ namespace vmime { namespace net { -int folder::getType() -{ +int folder::getType() { + return getAttributes().getType(); } -int folder::getFlags() -{ +int folder::getFlags() { + return getAttributes().getFlags(); } -void folder::addMessageChangedListener(events::messageChangedListener* l) -{ +void folder::addMessageChangedListener(events::messageChangedListener* l) { + m_messageChangedListeners.push_back(l); } -void folder::removeMessageChangedListener(events::messageChangedListener* l) -{ +void folder::removeMessageChangedListener(events::messageChangedListener* l) { + std::remove(m_messageChangedListeners.begin(), m_messageChangedListeners.end(), l); } -void folder::notifyMessageChanged(const shared_ptr & event) -{ +void folder::notifyMessageChanged(const shared_ptr & event) { + for (std::list ::iterator - it = m_messageChangedListeners.begin() ; it != m_messageChangedListeners.end() ; ++it) - { + it = m_messageChangedListeners.begin() ; it != m_messageChangedListeners.end() ; ++it) { + event->dispatch(*it); } } -void folder::addMessageCountListener(events::messageCountListener* l) -{ +void folder::addMessageCountListener(events::messageCountListener* l) { + m_messageCountListeners.push_back(l); } -void folder::removeMessageCountListener(events::messageCountListener* l) -{ +void folder::removeMessageCountListener(events::messageCountListener* l) { + std::remove(m_messageCountListeners.begin(), m_messageCountListeners.end(), l); } -void folder::notifyMessageCount(const shared_ptr & event) -{ +void folder::notifyMessageCount(const shared_ptr & event) { + for (std::list ::iterator - it = m_messageCountListeners.begin() ; it != m_messageCountListeners.end() ; ++it) - { + it = m_messageCountListeners.begin() ; it != m_messageCountListeners.end() ; ++it) { + event->dispatch(*it); } } -void folder::addFolderListener(events::folderListener* l) -{ +void folder::addFolderListener(events::folderListener* l) { + m_folderListeners.push_back(l); } -void folder::removeFolderListener(events::folderListener* l) -{ +void folder::removeFolderListener(events::folderListener* l) { + std::remove(m_folderListeners.begin(), m_folderListeners.end(), l); } -void folder::notifyFolder(const shared_ptr & event) -{ +void folder::notifyFolder(const shared_ptr & event) { + for (std::list ::iterator - it = m_folderListeners.begin() ; it != m_folderListeners.end() ; ++it) - { + it = m_folderListeners.begin() ; it != m_folderListeners.end() ; ++it) { + event->dispatch(*it); } } -void folder::notifyEvent(const shared_ptr & event) -{ - if (event->getClass() == events::messageCountEvent::EVENT_CLASS) - { +void folder::notifyEvent(const shared_ptr & event) { + + if (event->getClass() == events::messageCountEvent::EVENT_CLASS) { notifyMessageCount(dynamicCast (event)); - } - else if (event->getClass() == events::messageChangedEvent::EVENT_CLASS) - { + } else if (event->getClass() == events::messageChangedEvent::EVENT_CLASS) { notifyMessageChanged(dynamicCast (event)); - } - else if (event->getClass() == events::folderEvent::EVENT_CLASS) - { + } else if (event->getClass() == events::folderEvent::EVENT_CLASS) { notifyFolder(dynamicCast (event)); } } diff --git a/src/vmime/net/folder.hpp b/src/vmime/net/folder.hpp index 8117d7d1..4d5cf6ef 100644 --- a/src/vmime/net/folder.hpp +++ b/src/vmime/net/folder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -58,17 +58,15 @@ class store; /** Abstract representation of a folder in a message store. */ +class VMIME_EXPORT folder : public object, public enable_shared_from_this { -class VMIME_EXPORT folder : public object, public enable_shared_from_this -{ protected: folder(const folder&) : object(), enable_shared_from_this () { } folder() { } - enum PrivateConstants - { + enum PrivateConstants { TYPE_UNDEFINED = 9999, /**< Used internally to indicate type has not been initialized yet. */ FLAG_UNDEFINED = 9999 /**< Used internally to indicate flags have not @@ -86,8 +84,7 @@ public: /** Open mode. */ - enum Modes - { + enum Modes { MODE_READ_ONLY, /**< Read-only mode (no modification to folder or messages is possible). */ MODE_READ_WRITE /**< Full access mode (read and write). */ }; @@ -273,11 +270,12 @@ public: * support returning the number or UID of an added message) * @throw exceptions::net_exception if an error occurs */ - virtual messageSet addMessage - (const shared_ptr & msg, - const int flags = -1, - vmime::datetime* date = NULL, - utility::progressListener* progress = NULL) = 0; + virtual messageSet addMessage( + const shared_ptr & msg, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ) = 0; /** Add a message to this folder. * @@ -291,12 +289,13 @@ public: * support returning the number or UID of an added message) * @throw exceptions::net_exception if an error occurs */ - virtual messageSet addMessage - (utility::inputStream& is, - const size_t size, - const int flags = -1, - vmime::datetime* date = NULL, - utility::progressListener* progress = NULL) = 0; + virtual messageSet addMessage( + utility::inputStream& is, + const size_t size, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ) = 0; /** Copy messages from this folder to another folder. * @@ -307,8 +306,10 @@ public: * support returning the number or UID of a copied message) * @throw exceptions::net_exception if an error occurs */ - virtual messageSet copyMessages - (const folder::path& dest, const messageSet& msgs) = 0; + virtual messageSet copyMessages( + const folder::path& dest, + const messageSet& msgs + ) = 0; /** Request folder status without opening it. * @@ -358,7 +359,11 @@ public: * @param progress progress listener, or NULL if not used * @throw exceptions::net_exception if an error occurs */ - virtual void fetchMessages(std::vector >& msg, const fetchAttributes& attribs, utility::progressListener* progress = NULL) = 0; + virtual void fetchMessages( + std::vector >& msg, + const fetchAttributes& attribs, + utility::progressListener* progress = NULL + ) = 0; /** Fetch objects for the specified message. * @@ -366,7 +371,10 @@ public: * @param attribs set of attributes to fetch * @throw exceptions::net_exception if an error occurs */ - virtual void fetchMessage(const shared_ptr & msg, const fetchAttributes& attribs) = 0; + virtual void fetchMessage( + const shared_ptr & msg, + const fetchAttributes& attribs + ) = 0; /** Get new references to messages in this folder, given either their * sequence numbers or UIDs, and fetch objects for them at the same time. @@ -378,8 +386,10 @@ public: * @see folder::getMessages() * @see folder::fetchMessages() */ - virtual std::vector > getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs) = 0; + virtual std::vector > getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs + ) = 0; /** Return the list of fetchable objects supported by * the underlying protocol (see folder::fetchAttributes). diff --git a/src/vmime/net/folderAttributes.cpp b/src/vmime/net/folderAttributes.cpp index 1a283764..107007cf 100644 --- a/src/vmime/net/folderAttributes.cpp +++ b/src/vmime/net/folderAttributes.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard +// Copyright (C) 2002 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 @@ -39,8 +39,8 @@ namespace net { folderAttributes::folderAttributes() : m_type(TYPE_CONTAINS_FOLDERS | TYPE_CONTAINS_MESSAGES), m_flags(0), - m_specialUse(SPECIALUSE_NONE) -{ + m_specialUse(SPECIALUSE_NONE) { + } @@ -49,67 +49,67 @@ folderAttributes::folderAttributes(const folderAttributes& attribs) m_type(attribs.m_type), m_flags(attribs.m_flags), m_userFlags(attribs.m_userFlags), - m_specialUse(attribs.m_specialUse) -{ + m_specialUse(attribs.m_specialUse) { + } -int folderAttributes::getType() const -{ +int folderAttributes::getType() const { + return m_type; } -void folderAttributes::setType(const int type) -{ +void folderAttributes::setType(const int type) { + m_type = type; } -int folderAttributes::getSpecialUse() const -{ +int folderAttributes::getSpecialUse() const { + return m_specialUse; } -void folderAttributes::setSpecialUse(const int use) -{ +void folderAttributes::setSpecialUse(const int use) { + m_specialUse = use; } -int folderAttributes::getFlags() const -{ +int folderAttributes::getFlags() const { + return m_flags; } -void folderAttributes::setFlags(const int flags) -{ +void folderAttributes::setFlags(const int flags) { + m_flags = flags; } -bool folderAttributes::hasFlag(const int flag) -{ +bool folderAttributes::hasFlag(const int flag) { + return (m_flags & flag) != 0; } -const std::vector folderAttributes::getUserFlags() const -{ +const std::vector folderAttributes::getUserFlags() const { + return m_userFlags; } -void folderAttributes::setUserFlags(const std::vector & flags) -{ +void folderAttributes::setUserFlags(const std::vector & flags) { + m_userFlags = flags; } -bool folderAttributes::hasUserFlag(const string& flag) -{ +bool folderAttributes::hasUserFlag(const string& flag) { + return std::find(m_userFlags.begin(), m_userFlags.end(), flag) != m_userFlags.end(); } diff --git a/src/vmime/net/folderAttributes.hpp b/src/vmime/net/folderAttributes.hpp index d6c51926..b91347b5 100644 --- a/src/vmime/net/folderAttributes.hpp +++ b/src/vmime/net/folderAttributes.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard +// Copyright (C) 2002 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 @@ -42,22 +42,20 @@ namespace net { /** Holds a set of attributes for a folder. */ -class VMIME_EXPORT folderAttributes : public object -{ +class VMIME_EXPORT folderAttributes : public object { + public: /** Folder types. */ - enum Types - { + enum Types { TYPE_CONTAINS_FOLDERS = (1 << 0), /**< Folder can contain folders. */ TYPE_CONTAINS_MESSAGES = (1 << 1) /**< Folder can contain messages. */ }; /** Folder flags. */ - enum Flags - { + enum Flags { FLAG_HAS_CHILDREN = (1 << 0), /**< Folder contains subfolders. */ FLAG_NO_OPEN = (1 << 1) /**< Folder cannot be open. */ }; @@ -66,8 +64,7 @@ public: * Not all protocols support this. At the current time, only IMAP supports this, * if the server has the SPECIAL-USE capability. */ - enum SpecialUses - { + enum SpecialUses { SPECIALUSE_NONE, /**< User folder, no special use (or unknown). */ SPECIALUSE_ALL, /**< Virtual folder containing all messages. */ SPECIALUSE_ARCHIVE, /**< Folder is used to archives messages (server-dependent). */ @@ -139,7 +136,7 @@ public: * * @param flag combination of one ore more folder flags (see folderAttributes::Flags enum) * @return true if the specified flags are all set, or false otherwise - */ + */ bool hasFlag(const int flag); /** Set the user-defined flags of the folder. diff --git a/src/vmime/net/folderStatus.hpp b/src/vmime/net/folderStatus.hpp index e80b5a9f..fcc4afc0 100644 --- a/src/vmime/net/folderStatus.hpp +++ b/src/vmime/net/folderStatus.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,9 +40,8 @@ namespace net { /** Holds the status of a mail store folder. */ +class VMIME_EXPORT folderStatus : public object { -class VMIME_EXPORT folderStatus : public object -{ public: /** Returns the total number of messages in the folder. diff --git a/src/vmime/net/imap/IMAPCommand.cpp b/src/vmime/net/imap/IMAPCommand.cpp index 908b9152..8911ed02 100644 --- a/src/vmime/net/imap/IMAPCommand.cpp +++ b/src/vmime/net/imap/IMAPCommand.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard +// Copyright (C) 2002 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 @@ -41,14 +41,15 @@ namespace imap { IMAPCommand::IMAPCommand(const string& text, const string& traceText) - : m_text(text), m_traceText(traceText) -{ + : m_text(text), + m_traceText(traceText) { + } // static -shared_ptr IMAPCommand::LOGIN(const string& username, const string& password) -{ +shared_ptr IMAPCommand::LOGIN(const string& username, const string& password) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "LOGIN " << IMAPUtils::quoteString(username) @@ -63,8 +64,8 @@ shared_ptr IMAPCommand::LOGIN(const string& username, const string // static -shared_ptr IMAPCommand::AUTHENTICATE(const string& mechName) -{ +shared_ptr IMAPCommand::AUTHENTICATE(const string& mechName) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "AUTHENTICATE " << mechName; @@ -74,8 +75,8 @@ shared_ptr IMAPCommand::AUTHENTICATE(const string& mechName) // static -shared_ptr IMAPCommand::AUTHENTICATE(const string& mechName, const string& initialResponse) -{ +shared_ptr IMAPCommand::AUTHENTICATE(const string& mechName, const string& initialResponse) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "AUTHENTICATE " << mechName << " " << initialResponse; @@ -85,8 +86,8 @@ shared_ptr IMAPCommand::AUTHENTICATE(const string& mechName, const // static -shared_ptr IMAPCommand::LIST(const string& refName, const string& mailboxName) -{ +shared_ptr IMAPCommand::LIST(const string& refName, const string& mailboxName) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "LIST " << IMAPUtils::quoteString(refName) @@ -97,25 +98,28 @@ shared_ptr IMAPCommand::LIST(const string& refName, const string& // static -shared_ptr IMAPCommand::SELECT - (const bool readOnly, const string& mailboxName, const std::vector & params) -{ +shared_ptr IMAPCommand::SELECT( + const bool readOnly, + const string& mailboxName, + const std::vector & params +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); - if (readOnly) + if (readOnly) { cmd << "EXAMINE "; - else + } else { cmd << "SELECT "; + } cmd << IMAPUtils::quoteString(mailboxName); - if (!params.empty()) - { + if (!params.empty()) { + cmd << " ("; - for (size_t i = 0, n = params.size() ; i < n ; ++i) - { + for (size_t i = 0, n = params.size() ; i < n ; ++i) { if (i != 0) cmd << " "; cmd << params[i]; } @@ -128,17 +132,18 @@ shared_ptr IMAPCommand::SELECT // static -shared_ptr IMAPCommand::STATUS - (const string& mailboxName, const std::vector & attribs) -{ +shared_ptr IMAPCommand::STATUS( + const string& mailboxName, + const std::vector & attribs +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "STATUS " << IMAPUtils::quoteString(mailboxName); cmd << " ("; - for (size_t i = 0, n = attribs.size() ; i < n ; ++i) - { + for (size_t i = 0, n = attribs.size() ; i < n ; ++i) { if (i != 0) cmd << " "; cmd << attribs[i]; } @@ -150,19 +155,20 @@ shared_ptr IMAPCommand::STATUS // static -shared_ptr IMAPCommand::CREATE - (const string& mailboxName, const std::vector & params) -{ +shared_ptr IMAPCommand::CREATE( + const string& mailboxName, + const std::vector & params +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "CREATE " << IMAPUtils::quoteString(mailboxName); - if (!params.empty()) - { + if (!params.empty()) { + cmd << " ("; - for (size_t i = 0, n = params.size() ; i < n ; ++i) - { + for (size_t i = 0, n = params.size() ; i < n ; ++i) { if (i != 0) cmd << " "; cmd << params[i]; } @@ -175,8 +181,8 @@ shared_ptr IMAPCommand::CREATE // static -shared_ptr IMAPCommand::DELETE(const string& mailboxName) -{ +shared_ptr IMAPCommand::DELETE(const string& mailboxName) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "DELETE " << IMAPUtils::quoteString(mailboxName); @@ -186,9 +192,11 @@ shared_ptr IMAPCommand::DELETE(const string& mailboxName) // static -shared_ptr IMAPCommand::RENAME - (const string& mailboxName, const string& newMailboxName) -{ +shared_ptr IMAPCommand::RENAME( + const string& mailboxName, + const string& newMailboxName +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "RENAME " << IMAPUtils::quoteString(mailboxName) @@ -199,27 +207,29 @@ shared_ptr IMAPCommand::RENAME // static -shared_ptr IMAPCommand::FETCH - (const messageSet& msgs, const std::vector & params) -{ +shared_ptr IMAPCommand::FETCH( + const messageSet& msgs, + const std::vector & params +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); - if (msgs.isUIDSet()) + if (msgs.isUIDSet()) { cmd << "UID FETCH " << IMAPUtils::messageSetToSequenceSet(msgs); - else + } else { cmd << "FETCH " << IMAPUtils::messageSetToSequenceSet(msgs); - - if (params.size() == 1) - { - cmd << " " << params[0]; } - else - { + + if (params.size() == 1) { + + cmd << " " << params[0]; + + } else { + cmd << " ("; - for (size_t i = 0, n = params.size() ; i < n ; ++i) - { + for (size_t i = 0, n = params.size() ; i < n ; ++i) { if (i != 0) cmd << " "; cmd << params[i]; } @@ -232,28 +242,32 @@ shared_ptr IMAPCommand::FETCH // static -shared_ptr IMAPCommand::STORE - (const messageSet& msgs, const int mode, const std::vector & flags) -{ +shared_ptr IMAPCommand::STORE( + const messageSet& msgs, + const int mode, + const std::vector & flags +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); - if (msgs.isUIDSet()) + if (msgs.isUIDSet()) { cmd << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs); - else + } else { cmd << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs); + } - if (mode == message::FLAG_MODE_ADD) + if (mode == message::FLAG_MODE_ADD) { cmd << " +FLAGS "; - else if (mode == message::FLAG_MODE_REMOVE) + } else if (mode == message::FLAG_MODE_REMOVE) { cmd << " -FLAGS "; - else // if (mode == message::FLAG_MODE_SET) + } else { // if (mode == message::FLAG_MODE_SET) cmd << " FLAGS "; + } cmd << "("; - for (size_t i = 0, n = flags.size() ; i < n ; ++i) - { + for (size_t i = 0, n = flags.size() ; i < n ; ++i) { if (i != 0) cmd << " "; cmd << flags[i]; } @@ -265,20 +279,22 @@ shared_ptr IMAPCommand::STORE // static -shared_ptr IMAPCommand::APPEND - (const string& mailboxName, const std::vector & flags, - vmime::datetime* date, const size_t size) -{ +shared_ptr IMAPCommand::APPEND( + const string& mailboxName, + const std::vector & flags, + vmime::datetime* date, + const size_t size +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "APPEND " << IMAPUtils::quoteString(mailboxName); - if (!flags.empty()) - { + if (!flags.empty()) { + cmd << " ("; - for (size_t i = 0, n = flags.size() ; i < n ; ++i) - { + for (size_t i = 0, n = flags.size() ; i < n ; ++i) { if (i != 0) cmd << " "; cmd << flags[i]; } @@ -286,8 +302,9 @@ shared_ptr IMAPCommand::APPEND cmd << ")"; } - if (date != NULL) + if (date != NULL) { cmd << " " << IMAPUtils::dateTime(*date); + } cmd << " {" << size << "}"; @@ -296,16 +313,19 @@ shared_ptr IMAPCommand::APPEND // static -shared_ptr IMAPCommand::COPY - (const messageSet& msgs, const string& mailboxName) -{ +shared_ptr IMAPCommand::COPY( + const messageSet& msgs, + const string& mailboxName +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); - if (msgs.isUIDSet()) + if (msgs.isUIDSet()) { cmd << "UID COPY " << IMAPUtils::messageSetToSequenceSet(msgs); - else + } else { cmd << "COPY " << IMAPUtils::messageSetToSequenceSet(msgs); + } cmd << " " << IMAPUtils::quoteString(mailboxName); @@ -314,90 +334,97 @@ shared_ptr IMAPCommand::COPY // static -shared_ptr IMAPCommand::SEARCH - (const std::vector & keys, const vmime::charset* charset) -{ +shared_ptr IMAPCommand::SEARCH( + const std::vector & keys, + const vmime::charset* charset +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "SEARCH"; - if (charset) + if (charset) { cmd << " CHARSET " << charset->getName(); + } - for (size_t i = 0, n = keys.size() ; i < n ; ++i) + for (size_t i = 0, n = keys.size() ; i < n ; ++i) { cmd << " " << keys[i]; + } return createCommand(cmd.str()); } // static -shared_ptr IMAPCommand::STARTTLS() -{ +shared_ptr IMAPCommand::STARTTLS() { + return createCommand("STARTTLS"); } // static -shared_ptr IMAPCommand::CAPABILITY() -{ +shared_ptr IMAPCommand::CAPABILITY() { + return createCommand("CAPABILITY"); } // static -shared_ptr IMAPCommand::NOOP() -{ +shared_ptr IMAPCommand::NOOP() { + return createCommand("NOOP"); } // static -shared_ptr IMAPCommand::EXPUNGE() -{ +shared_ptr IMAPCommand::EXPUNGE() { + return createCommand("EXPUNGE"); } // static -shared_ptr IMAPCommand::CLOSE() -{ +shared_ptr IMAPCommand::CLOSE() { + return createCommand("CLOSE"); } // static -shared_ptr IMAPCommand::LOGOUT() -{ +shared_ptr IMAPCommand::LOGOUT() { + return createCommand("LOGOUT"); } // static -shared_ptr IMAPCommand::createCommand - (const string& text, const string& traceText) -{ - if (traceText.empty()) +shared_ptr IMAPCommand::createCommand( + const string& text, + const string& traceText +) { + + if (traceText.empty()) { return shared_ptr (new IMAPCommand(text, text)); - else + } else { return shared_ptr (new IMAPCommand(text, traceText)); + } } -const string IMAPCommand::getText() const -{ +const string IMAPCommand::getText() const { + return m_text; } -const string IMAPCommand::getTraceText() const -{ +const string IMAPCommand::getTraceText() const { + return m_traceText; } -void IMAPCommand::send(const shared_ptr & conn) -{ +void IMAPCommand::send(const shared_ptr & conn) { + conn->sendCommand(dynamicCast (shared_from_this())); } diff --git a/src/vmime/net/imap/IMAPCommand.hpp b/src/vmime/net/imap/IMAPCommand.hpp index 09f34c66..4915a577 100644 --- a/src/vmime/net/imap/IMAPCommand.hpp +++ b/src/vmime/net/imap/IMAPCommand.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard +// Copyright (C) 2002 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 @@ -48,8 +48,8 @@ class IMAPConnection; /** An IMAP command that will be sent to the server. */ -class VMIME_EXPORT IMAPCommand : public object, public enable_shared_from_this -{ +class VMIME_EXPORT IMAPCommand : public object, public enable_shared_from_this { + public: static shared_ptr LOGIN(const string& username, const string& password); diff --git a/src/vmime/net/imap/IMAPConnection.cpp b/src/vmime/net/imap/IMAPConnection.cpp index 7fc86188..0e593829 100644 --- a/src/vmime/net/imap/IMAPConnection.cpp +++ b/src/vmime/net/imap/IMAPConnection.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -66,17 +66,30 @@ namespace net { namespace imap { -IMAPConnection::IMAPConnection(const shared_ptr & store, const shared_ptr & 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), m_firstTag(true), m_capabilitiesFetched(false), m_noModSeq(false) -{ +IMAPConnection::IMAPConnection( + const shared_ptr & store, + const shared_ptr & 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), + m_firstTag(true), + m_capabilitiesFetched(false), + m_noModSeq(false) { + static int connectionId = 0; m_tag = make_shared (); - if (store->getTracerFactory()) + if (store->getTracerFactory()) { m_tracer = store->getTracerFactory()->create(store, ++connectionId); + } m_parser = make_shared (); m_parser->setTag(m_tag); @@ -84,26 +97,28 @@ IMAPConnection::IMAPConnection(const shared_ptr & store, const shared } -IMAPConnection::~IMAPConnection() -{ - try - { - if (isConnected()) +IMAPConnection::~IMAPConnection() { + + try { + + if (isConnected()) { disconnect(); - else if (m_socket) + } else if (m_socket) { internalDisconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -void IMAPConnection::connect() -{ - if (isConnected()) +void IMAPConnection::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } m_state = STATE_NONE; m_hierarchySeparator = '\0'; @@ -114,16 +129,17 @@ void IMAPConnection::connect() shared_ptr store = m_store.lock(); // Create the time-out handler - if (store->getTimeoutHandlerFactory()) + if (store->getTimeoutHandlerFactory()) { m_timeoutHandler = store->getTimeoutHandlerFactory()->create(); + } // Create and connect the socket m_socket = store->getSocketFactory()->create(m_timeoutHandler); m_socket->setTracer(m_tracer); #if VMIME_HAVE_TLS_SUPPORT - if (store->isIMAPS()) // dedicated port/IMAPS - { + if (store->isIMAPS()) { // dedicated port/IMAPS + shared_ptr tlsSession = tls::TLSSession::create (store->getCertificateVerifier(), store->getSession()->getTLSProperties()); @@ -135,8 +151,8 @@ void IMAPConnection::connect() m_secured = true; m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); - } - else + + } else #endif // VMIME_HAVE_TLS_SUPPORT { m_cntInfos = make_shared (address, port); @@ -160,19 +176,19 @@ void IMAPConnection::connect() scoped_ptr greet(m_parser->readGreeting()); bool needAuth = false; - if (greet->resp_cond_bye()) - { + if (greet->resp_cond_bye()) { + internalDisconnect(); throw exceptions::connection_greeting_error(greet->getErrorLog()); - } - else if (greet->resp_cond_auth()->condition() != IMAPParser::resp_cond_auth::PREAUTH) - { + + } else if (greet->resp_cond_auth()->condition() != IMAPParser::resp_cond_auth::PREAUTH) { + needAuth = true; } if (greet->resp_cond_auth()->resp_text()->resp_text_code() && - greet->resp_cond_auth()->resp_text()->resp_text_code()->capability_data()) - { + greet->resp_cond_auth()->resp_text()->resp_text_code()->capability_data()) { + processCapabilityResponseData(greet->resp_cond_auth()->resp_text()->resp_text_code()->capability_data()); } @@ -183,28 +199,25 @@ void IMAPConnection::connect() const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED) && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED); - if (!store->isIMAPS() && tls) // only if not IMAPS - { - try - { + if (!store->isIMAPS() && tls) { // only if not IMAPS + + try { + startTLS(); - } + // Non-fatal error - catch (exceptions::command_error&) - { - if (tlsRequired) - { + } catch (exceptions::command_error&) { + + if (tlsRequired) { m_state = STATE_NONE; throw; - } - else - { + } else { // TLS is not required, so don't bother } - } + // Fatal error - catch (...) - { + } catch (...) { + m_state = STATE_NONE; throw; } @@ -212,14 +225,14 @@ void IMAPConnection::connect() #endif // VMIME_HAVE_TLS_SUPPORT // Authentication - if (needAuth) - { - try - { + if (needAuth) { + + try { + authenticate(); - } - catch (...) - { + + } catch (...) { + m_state = STATE_NONE; throw; } @@ -233,34 +246,34 @@ void IMAPConnection::connect() } -void IMAPConnection::authenticate() -{ +void IMAPConnection::authenticate() { + getAuthenticator()->setService(m_store.lock()); #if VMIME_HAVE_SASL_SUPPORT // First, try SASL authentication - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) - { - try - { + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) { + + try { + authenticateSASL(); return; - } - catch (exceptions::authentication_error&) - { - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) - { + + } catch (exceptions::authentication_error&) { + + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) { + // Can't fallback on normal authentication internalDisconnect(); throw; - } - else - { + + } else { + // Ignore, will try normal authentication } - } - catch (exception&) - { + + } catch (exception&) { + internalDisconnect(); throw; } @@ -276,36 +289,38 @@ void IMAPConnection::authenticate() scoped_ptr resp(m_parser->readResponse()); - if (resp->isBad()) - { + if (resp->isBad()) { + internalDisconnect(); throw exceptions::command_error("LOGIN", resp->getErrorLog()); - } - else if (resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { + + } else if (resp->response_done()->response_tagged()-> + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + internalDisconnect(); throw exceptions::authentication_error(resp->getErrorLog()); } // Server capabilities may change when logged in - if (!processCapabilityResponseData(resp.get())) + if (!processCapabilityResponseData(resp.get())) { invalidateCapabilities(); + } } #if VMIME_HAVE_SASL_SUPPORT -void IMAPConnection::authenticateSASL() -{ - if (!dynamicCast (getAuthenticator())) +void IMAPConnection::authenticateSASL() { + + if (!dynamicCast (getAuthenticator())) { throw exceptions::authentication_error("No SASL authenticator available."); + } const std::vector capa = getCapabilities(); std::vector saslMechs; - for (unsigned int i = 0 ; i < capa.size() ; ++i) - { + for (unsigned int i = 0 ; i < capa.size() ; ++i) { + const string& x = capa[i]; if (x.length() > 5 && @@ -313,53 +328,53 @@ void IMAPConnection::authenticateSASL() (x[1] == 'U' || x[1] == 'u') && (x[2] == 'T' || x[2] == 't') && (x[3] == 'H' || x[3] == 'h') && - x[4] == '=') - { + x[4] == '=') { + saslMechs.push_back(string(x.begin() + 5, x.end())); } } - if (saslMechs.empty()) + if (saslMechs.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } std::vector > mechList; shared_ptr saslContext = security::sasl::SASLContext::create(); - for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) - { - try - { - mechList.push_back - (saslContext->createMechanism(saslMechs[i])); - } - catch (exceptions::no_such_mechanism&) - { + for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) { + + try { + mechList.push_back(saslContext->createMechanism(saslMechs[i])); + } catch (exceptions::no_such_mechanism&) { // Ignore mechanism } } - if (mechList.empty()) + if (mechList.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } // Try to suggest a mechanism among all those supported shared_ptr suggestedMech = saslContext->suggestMechanism(mechList); - if (!suggestedMech) + if (!suggestedMech) { throw exceptions::authentication_error("Unable to suggest SASL mechanism."); + } // Allow application to choose which mechanisms to use mechList = dynamicCast (getAuthenticator())-> getAcceptableMechanisms(mechList, suggestedMech); - if (mechList.empty()) + if (mechList.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } // Try each mechanism in the list in turn - for (unsigned int i = 0 ; i < mechList.size() ; ++i) - { + for (unsigned int i = 0 ; i < mechList.size() ; ++i) { + shared_ptr mech = mechList[i]; shared_ptr saslSession = @@ -369,8 +384,8 @@ void IMAPConnection::authenticateSASL() shared_ptr authCmd; - if (saslSession->getMechanism()->hasInitialResponse()) - { + if (saslSession->getMechanism()->hasInitialResponse()) { + byte_t* initialResp = 0; size_t initialRespLen = 0; @@ -379,50 +394,50 @@ void IMAPConnection::authenticateSASL() string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen)); delete [] initialResp; - if (encodedInitialResp.empty()) + if (encodedInitialResp.empty()) { authCmd = IMAPCommand::AUTHENTICATE(mech->getName(), "="); - else + } else { authCmd = IMAPCommand::AUTHENTICATE(mech->getName(), encodedInitialResp); - } - else - { + } + + } else { + authCmd = IMAPCommand::AUTHENTICATE(mech->getName()); } authCmd->send(dynamicCast (shared_from_this())); - for (bool cont = true ; cont ; ) - { + for (bool cont = true ; cont ; ) { + scoped_ptr resp(m_parser->readResponse()); if (resp->response_done() && resp->response_done()->response_tagged() && resp->response_done()->response_tagged()->resp_cond_state()-> - status() == IMAPParser::resp_cond_state::OK) - { + status() == IMAPParser::resp_cond_state::OK) { + m_socket = saslSession->getSecuredSocket(m_socket); return; - } - else - { + + } else { + std::vector respDataList = resp->continue_req_or_response_data(); string response; bool hasResponse = false; - for (unsigned int i = 0 ; i < respDataList.size() ; ++i) - { - if (respDataList[i]->continue_req()) - { + for (unsigned int i = 0 ; i < respDataList.size() ; ++i) { + + if (respDataList[i]->continue_req()) { + response = respDataList[i]->continue_req()->resp_text()->text(); hasResponse = true; break; } } - if (!hasResponse) - { + if (!hasResponse) { cont = false; continue; } @@ -433,8 +448,8 @@ void IMAPConnection::authenticateSASL() byte_t* resp = 0; size_t respLen = 0; - try - { + try { + // Extract challenge saslContext->decodeB64(response, &challenge, &challengeLen); @@ -446,22 +461,21 @@ void IMAPConnection::authenticateSASL() const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n"; sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length()); - if (m_tracer) + if (m_tracer) { m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange"); + } // Server capabilities may change when logged in invalidateCapabilities(); - } - catch (exceptions::sasl_exception& e) - { - if (challenge) - { + + } catch (exceptions::sasl_exception& e) { + + if (challenge) { delete [] challenge; challenge = NULL; } - if (resp) - { + if (resp) { delete [] resp; resp = NULL; } @@ -469,31 +483,35 @@ void IMAPConnection::authenticateSASL() // Cancel SASL exchange sendRaw(utility::stringUtils::bytesFromString("*\r\n"), 3); - if (m_tracer) + if (m_tracer) { m_tracer->traceSend("*"); - } - catch (...) - { - if (challenge) - delete [] challenge; + } - if (resp) + } catch (...) { + + if (challenge) { + delete [] challenge; + } + + if (resp) { delete [] resp; + } throw; } - if (challenge) + if (challenge) { delete [] challenge; + } - if (resp) + if (resp) { delete [] resp; + } } } } - throw exceptions::authentication_error - ("Could not authenticate using SASL: all mechanisms failed."); + throw exceptions::authentication_error("Could not authenticate using SASL: all mechanisms failed."); } #endif // VMIME_HAVE_SASL_SUPPORT @@ -501,27 +519,26 @@ void IMAPConnection::authenticateSASL() #if VMIME_HAVE_TLS_SUPPORT -void IMAPConnection::startTLS() -{ - try - { +void IMAPConnection::startTLS() { + + try { + IMAPCommand::STARTTLS()->send(dynamicCast (shared_from_this())); scoped_ptr resp(m_parser->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error - ("STARTTLS", resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("STARTTLS", resp->getErrorLog(), "bad response"); } - shared_ptr tlsSession = tls::TLSSession::create - (m_store.lock()->getCertificateVerifier(), - m_store.lock()->getSession()->getTLSProperties()); + shared_ptr tlsSession = tls::TLSSession::create( + m_store.lock()->getCertificateVerifier(), + m_store.lock()->getSession()->getTLSProperties() + ); - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); + shared_ptr tlsSocket = tlsSession->getSocket(m_socket); tlsSocket->handshake(); @@ -529,8 +546,9 @@ void IMAPConnection::startTLS() m_parser->setSocket(m_socket); m_secured = true; - m_cntInfos = make_shared - (m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket); + m_cntInfos = make_shared ( + m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket + ); // " Once TLS has been started, the client MUST discard cached // information about server capabilities and SHOULD re-issue the @@ -538,14 +556,14 @@ void IMAPConnection::startTLS() // man-in-the-middle attacks which alter the capabilities list prior // to STARTTLS. " (RFC-2595) invalidateCapabilities(); - } - catch (exceptions::command_error&) - { + + } catch (exceptions::command_error&) { + // Non-fatal error throw; - } - catch (exception&) - { + + } catch (exception&) { + // Fatal error internalDisconnect(); throw; @@ -555,24 +573,41 @@ void IMAPConnection::startTLS() #endif // VMIME_HAVE_TLS_SUPPORT -const std::vector IMAPConnection::getCapabilities() -{ - if (!m_capabilitiesFetched) +const std::vector IMAPConnection::getCapabilities() { + + if (!m_capabilitiesFetched) { fetchCapabilities(); + } return m_capabilities; } -bool IMAPConnection::hasCapability(const string& capa) -{ - if (!m_capabilitiesFetched) +bool IMAPConnection::hasCapability(const string& capa) { + + if (!m_capabilitiesFetched) { fetchCapabilities(); + } const string normCapa = utility::stringUtils::toUpper(capa); - for (size_t i = 0, n = m_capabilities.size() ; i < n ; ++i) - { + for (size_t i = 0, n = m_capabilities.size() ; i < n ; ++i) { + + if (m_capabilities[i] == normCapa) { + return true; + } + } + + return false; +} + + +bool IMAPConnection::hasCapability(const string& capa) const { + + const string normCapa = utility::stringUtils::toUpper(capa); + + for (size_t i = 0, n = m_capabilities.size() ; i < n ; ++i) { + if (m_capabilities[i] == normCapa) return true; } @@ -581,56 +616,44 @@ bool IMAPConnection::hasCapability(const string& capa) } -bool IMAPConnection::hasCapability(const string& capa) const -{ - const string normCapa = utility::stringUtils::toUpper(capa); +void IMAPConnection::invalidateCapabilities() { - for (size_t i = 0, n = m_capabilities.size() ; i < n ; ++i) - { - if (m_capabilities[i] == normCapa) - return true; - } - - return false; -} - - -void IMAPConnection::invalidateCapabilities() -{ m_capabilities.clear(); m_capabilitiesFetched = false; } -void IMAPConnection::fetchCapabilities() -{ +void IMAPConnection::fetchCapabilities() { + IMAPCommand::CAPABILITY()->send(dynamicCast (shared_from_this())); scoped_ptr resp(m_parser->readResponse()); if (resp->response_done()->response_tagged()-> - resp_cond_state()->status() == IMAPParser::resp_cond_state::OK) - { + resp_cond_state()->status() == IMAPParser::resp_cond_state::OK) { + processCapabilityResponseData(resp.get()); } } -bool IMAPConnection::processCapabilityResponseData(const IMAPParser::response* resp) -{ +bool IMAPConnection::processCapabilityResponseData(const IMAPParser::response* resp) { + const std::vector & respDataList = resp->continue_req_or_response_data(); - for (size_t i = 0 ; i < respDataList.size() ; ++i) - { - if (respDataList[i]->response_data() == NULL) + for (size_t i = 0 ; i < respDataList.size() ; ++i) { + + if (respDataList[i]->response_data() == NULL) { continue; + } const IMAPParser::capability_data* capaData = respDataList[i]->response_data()->capability_data(); - if (capaData == NULL) + if (capaData == NULL) { continue; + } processCapabilityResponseData(capaData); return true; @@ -640,18 +663,19 @@ bool IMAPConnection::processCapabilityResponseData(const IMAPParser::response* r } -void IMAPConnection::processCapabilityResponseData(const IMAPParser::capability_data* capaData) -{ +void IMAPConnection::processCapabilityResponseData(const IMAPParser::capability_data* capaData) { + std::vector res; std::vector caps = capaData->capabilities(); - for (unsigned int j = 0 ; j < caps.size() ; ++j) - { - if (caps[j]->auth_type()) + for (unsigned int j = 0 ; j < caps.size() ; ++j) { + + if (caps[j]->auth_type()) { res.push_back("AUTH=" + caps[j]->auth_type()->name()); - else + } else { res.push_back(utility::stringUtils::toUpper(caps[j]->atom()->value())); + } } m_capabilities = res; @@ -659,44 +683,46 @@ void IMAPConnection::processCapabilityResponseData(const IMAPParser::capability_ } -shared_ptr IMAPConnection::getAuthenticator() -{ +shared_ptr IMAPConnection::getAuthenticator() { + return m_auth; } -bool IMAPConnection::isConnected() const -{ - return (m_socket && m_socket->isConnected() && - (m_state == STATE_AUTHENTICATED || m_state == STATE_SELECTED)); +bool IMAPConnection::isConnected() const { + + return m_socket + && m_socket->isConnected() + && (m_state == STATE_AUTHENTICATED || m_state == STATE_SELECTED); } -bool IMAPConnection::isSecuredConnection() const -{ +bool IMAPConnection::isSecuredConnection() const { + return m_secured; } -shared_ptr IMAPConnection::getConnectionInfos() const -{ +shared_ptr IMAPConnection::getConnectionInfos() const { + return m_cntInfos; } -void IMAPConnection::disconnect() -{ - if (!isConnected()) +void IMAPConnection::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } internalDisconnect(); } -void IMAPConnection::internalDisconnect() -{ - if (isConnected()) - { +void IMAPConnection::internalDisconnect() { + + if (isConnected()) { + IMAPCommand::LOGOUT()->send(dynamicCast (shared_from_this())); m_socket->disconnect(); @@ -712,15 +738,15 @@ void IMAPConnection::internalDisconnect() } -void IMAPConnection::initHierarchySeparator() -{ +void IMAPConnection::initHierarchySeparator() { + IMAPCommand::LIST("", "")->send(dynamicCast (shared_from_this())); scoped_ptr resp(m_parser->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + internalDisconnect(); throw exceptions::command_error("LIST", resp->getErrorLog(), "bad response"); } @@ -730,34 +756,37 @@ void IMAPConnection::initHierarchySeparator() bool found = false; - for (unsigned int i = 0 ; !found && i < respDataList.size() ; ++i) - { - if (respDataList[i]->response_data() == NULL) + for (unsigned int i = 0 ; !found && i < respDataList.size() ; ++i) { + + if (respDataList[i]->response_data() == NULL) { continue; + } const IMAPParser::mailbox_data* mailboxData = static_cast (respDataList[i]->response_data())->mailbox_data(); - if (mailboxData == NULL || mailboxData->type() != IMAPParser::mailbox_data::LIST) + if (mailboxData == NULL || mailboxData->type() != IMAPParser::mailbox_data::LIST) { continue; + } - if (mailboxData->mailbox_list()->quoted_char() != '\0') - { + if (mailboxData->mailbox_list()->quoted_char() != '\0') { m_hierarchySeparator = mailboxData->mailbox_list()->quoted_char(); found = true; } } - if (!found) // default + if (!found) { // default m_hierarchySeparator = '/'; + } } -void IMAPConnection::sendCommand(const shared_ptr & cmd) -{ - if (!m_firstTag) +void IMAPConnection::sendCommand(const shared_ptr & cmd) { + + if (!m_firstTag) { ++(*m_tag); + } m_socket->send(*m_tag); m_socket->send(" "); @@ -766,8 +795,8 @@ void IMAPConnection::sendCommand(const shared_ptr & cmd) m_firstTag = false; - if (m_tracer) - { + if (m_tracer) { + std::ostringstream oss; oss << string(*m_tag) << " " << cmd->getText(); @@ -776,87 +805,87 @@ void IMAPConnection::sendCommand(const shared_ptr & cmd) } -void IMAPConnection::sendRaw(const byte_t* buffer, const size_t count) -{ +void IMAPConnection::sendRaw(const byte_t* buffer, const size_t count) { + m_socket->sendRaw(buffer, count); } -IMAPParser::response* IMAPConnection::readResponse(IMAPParser::literalHandler* lh) -{ - return (m_parser->readResponse(lh)); +IMAPParser::response* IMAPConnection::readResponse(IMAPParser::literalHandler* lh) { + + return m_parser->readResponse(lh); } -IMAPConnection::ProtocolStates IMAPConnection::state() const -{ - return (m_state); +IMAPConnection::ProtocolStates IMAPConnection::state() const { + + return m_state; } -void IMAPConnection::setState(const ProtocolStates state) -{ +void IMAPConnection::setState(const ProtocolStates state) { + m_state = state; } -char IMAPConnection::hierarchySeparator() const -{ - return (m_hierarchySeparator); +char IMAPConnection::hierarchySeparator() const { + + return m_hierarchySeparator; } -shared_ptr IMAPConnection::getStore() const -{ +shared_ptr IMAPConnection::getStore() const { + return m_store.lock(); } -shared_ptr IMAPConnection::getStore() -{ +shared_ptr IMAPConnection::getStore() { + return m_store.lock(); } -shared_ptr IMAPConnection::getSession() -{ +shared_ptr IMAPConnection::getSession() { + return m_store.lock()->getSession(); } -shared_ptr IMAPConnection::getSocket() const -{ +shared_ptr IMAPConnection::getSocket() const { + return m_socket; } -void IMAPConnection::setSocket(const shared_ptr & sok) -{ +void IMAPConnection::setSocket(const shared_ptr & sok) { + m_socket = sok; m_parser->setSocket(sok); } -shared_ptr IMAPConnection::getTracer() -{ +shared_ptr IMAPConnection::getTracer() { + return m_tracer; } -shared_ptr IMAPConnection::getTag() -{ +shared_ptr IMAPConnection::getTag() { + return m_tag; } -bool IMAPConnection::isMODSEQDisabled() const -{ +bool IMAPConnection::isMODSEQDisabled() const { + return m_noModSeq; } -void IMAPConnection::disableMODSEQ() -{ +void IMAPConnection::disableMODSEQ() { + m_noModSeq = true; } diff --git a/src/vmime/net/imap/IMAPConnection.hpp b/src/vmime/net/imap/IMAPConnection.hpp index 9a277f7c..99750d49 100644 --- a/src/vmime/net/imap/IMAPConnection.hpp +++ b/src/vmime/net/imap/IMAPConnection.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -52,8 +52,8 @@ class IMAPStore; class IMAPCommand; -class VMIME_EXPORT IMAPConnection : public object, public enable_shared_from_this -{ +class VMIME_EXPORT IMAPConnection : public object, public enable_shared_from_this { + public: IMAPConnection(const shared_ptr & store, const shared_ptr & auth); @@ -65,8 +65,7 @@ public: void disconnect(); - enum ProtocolStates - { + enum ProtocolStates { STATE_NONE, STATE_NON_AUTHENTICATED, STATE_AUTHENTICATED, diff --git a/src/vmime/net/imap/IMAPFolder.cpp b/src/vmime/net/imap/IMAPFolder.cpp index a142f7f5..ec39fe3e 100644 --- a/src/vmime/net/imap/IMAPFolder.cpp +++ b/src/vmime/net/imap/IMAPFolder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -52,106 +52,119 @@ namespace net { namespace imap { -IMAPFolder::IMAPFolder(const folder::path& path, const shared_ptr & store, const shared_ptr & attribs) - : 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_attribs(attribs) -{ +IMAPFolder::IMAPFolder( + const folder::path& path, + const shared_ptr & store, + const shared_ptr & attribs +) + : 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_attribs(attribs) { + store->registerFolder(this); m_status = make_shared (); } -IMAPFolder::~IMAPFolder() -{ - try - { +IMAPFolder::~IMAPFolder() { + + try { + shared_ptr store = m_store.lock(); - if (store) - { - if (m_open) + if (store) { + + if (m_open) { close(false); + } store->unregisterFolder(this); - } - else if (m_open) - { + + } else if (m_open) { + m_connection = null; onClose(); } - } - catch (...) - { + + } catch (...) { + // Don't throw in destructor } } -int IMAPFolder::getMode() const -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); +int IMAPFolder::getMode() const { - return (m_mode); + if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + return m_mode; } -const folderAttributes IMAPFolder::getAttributes() -{ +const folderAttributes IMAPFolder::getAttributes() { + // Root folder - if (m_path.isEmpty()) - { + if (m_path.isEmpty()) { + folderAttributes attribs; attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS); attribs.setFlags(folderAttributes::FLAG_HAS_CHILDREN | folderAttributes::FLAG_NO_OPEN); return attribs; - } - else - { - if (!m_attribs) + + } else { + + if (!m_attribs) { testExistAndGetType(); + } return *m_attribs; } } -const folder::path::component IMAPFolder::getName() const -{ - return (m_name); +const folder::path::component IMAPFolder::getName() const { + + return m_name; } -const folder::path IMAPFolder::getFullPath() const -{ - return (m_path); +const folder::path IMAPFolder::getFullPath() const { + + return m_path; } -void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) -{ +void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } // Ensure this folder is not already open in the same session for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == m_path) { throw exceptions::folder_already_open(); + } } // Open a connection for this folder shared_ptr connection = make_shared (store, store->getAuthenticator()); - try - { + try { + connection->connect(); // Emit the "SELECT" command @@ -167,8 +180,9 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) std::vector selectParams; - if (m_connection->hasCapability("CONDSTORE")) + if (m_connection->hasCapability("CONDSTORE")) { selectParams.push_back("CONDSTORE"); + } IMAPCommand::SELECT( mode == MODE_READ_ONLY, @@ -180,67 +194,68 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) scoped_ptr resp(connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("SELECT", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("SELECT", resp->getErrorLog(), "bad response"); } const std::vector & respDataList = resp->continue_req_or_response_data(); for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("SELECT", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + + throw exceptions::command_error("SELECT", resp->getErrorLog(), "invalid response"); } const IMAPParser::response_data* responseData = (*it)->response_data(); // OK Untagged responses: UNSEEN, PERMANENTFLAGS, UIDVALIDITY (optional) - if (responseData->resp_cond_state()) - { + if (responseData->resp_cond_state()) { + const IMAPParser::resp_text_code* code = responseData->resp_cond_state()->resp_text()->resp_text_code(); - if (code != NULL) - { - switch (code->type()) - { - case IMAPParser::resp_text_code::NOMODSEQ: + if (code != NULL) { - connection->disableMODSEQ(); - break; + switch (code->type()) { - default: + case IMAPParser::resp_text_code::NOMODSEQ: + + connection->disableMODSEQ(); + break; + + default: + + break; + } + } + + // Untagged responses: FLAGS, EXISTS, RECENT (required) + } else if (responseData->mailbox_data()) { + + switch (responseData->mailbox_data()->type()) { + + default: break; + + case IMAPParser::mailbox_data::FLAGS: { + + if (!m_attribs) { + m_attribs = make_shared (); + } + + IMAPUtils::mailboxFlagsToFolderAttributes( + connection, + responseData->mailbox_data()->mailbox_flag_list(), + *m_attribs + ); break; } } } - // Untagged responses: FLAGS, EXISTS, RECENT (required) - else if (responseData->mailbox_data()) - { - switch (responseData->mailbox_data()->type()) - { - default: break; - - case IMAPParser::mailbox_data::FLAGS: - { - if (!m_attribs) - m_attribs = make_shared (); - - IMAPUtils::mailboxFlagsToFolderAttributes - (connection, responseData->mailbox_data()->mailbox_flag_list(), *m_attribs); - - break; - } - - } - } } processStatusUpdate(resp.get()); @@ -249,49 +264,52 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) const IMAPParser::resp_text_code* respTextCode = resp->response_done()-> response_tagged()->resp_cond_state()->resp_text()->resp_text_code(); - if (respTextCode) - { + if (respTextCode) { + const int openMode = (respTextCode->type() == IMAPParser::resp_text_code::READ_WRITE) - ? MODE_READ_WRITE : MODE_READ_ONLY; + ? MODE_READ_WRITE + : MODE_READ_ONLY; if (failIfModeIsNotAvailable && - mode == MODE_READ_WRITE && openMode == MODE_READ_ONLY) - { + mode == MODE_READ_WRITE && openMode == MODE_READ_ONLY) { + throw exceptions::operation_not_supported(); } } - m_connection = connection; m_open = true; m_mode = mode; - } - catch (std::exception&) - { + + } catch (std::exception&) { + throw; } } -void IMAPFolder::close(const bool expunge) -{ +void IMAPFolder::close(const bool expunge) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - if (!isOpen()) + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } shared_ptr oldConnection = m_connection; // Emit the "CLOSE" command to expunge messages marked // as deleted (this is fastest than "EXPUNGE") - if (expunge) - { - if (m_mode == MODE_READ_ONLY) + if (expunge) { + + if (m_mode == MODE_READ_ONLY) { throw exceptions::operation_not_supported(); + } IMAPCommand::CLOSE()->send(oldConnection); } @@ -311,11 +329,11 @@ void IMAPFolder::close(const bool expunge) } -void IMAPFolder::onClose() -{ +void IMAPFolder::onClose() { + for (std::vector ::iterator it = m_messages.begin() ; - it != m_messages.end() ; ++it) - { + it != m_messages.end() ; ++it) { + (*it)->onFolderClosed(); } @@ -323,18 +341,19 @@ void IMAPFolder::onClose() } -void IMAPFolder::create(const folderAttributes& attribs) -{ +void IMAPFolder::create(const folderAttributes& attribs) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) + } else if (isOpen()) { throw exceptions::illegal_state("Folder is open"); - else if (exists()) + } else if (exists()) { throw exceptions::illegal_state("Folder already exists"); - else if (!store->isValidFolderName(m_name)) + } else if (!store->isValidFolderName(m_name)) { throw exceptions::invalid_folder_name(); + } // Emit the "CREATE" command // @@ -346,31 +365,33 @@ void IMAPFolder::create(const folderAttributes& attribs) string mailbox = IMAPUtils::pathToString (m_connection->hierarchySeparator(), getFullPath()); - if (attribs.getType() & folderAttributes::TYPE_CONTAINS_FOLDERS) + if (attribs.getType() & folderAttributes::TYPE_CONTAINS_FOLDERS) { mailbox += m_connection->hierarchySeparator(); + } std::vector createParams; - if (attribs.getSpecialUse() != folderAttributes::SPECIALUSE_NONE) - { - if (!m_connection->hasCapability("CREATE-SPECIAL-USE")) + if (attribs.getSpecialUse() != folderAttributes::SPECIALUSE_NONE) { + + if (!m_connection->hasCapability("CREATE-SPECIAL-USE")) { throw exceptions::operation_not_supported(); + } // C: t2 CREATE MySpecial (USE (\Drafts \Sent)) std::ostringstream oss; oss << "USE ("; - switch (attribs.getSpecialUse()) - { - case folderAttributes::SPECIALUSE_NONE: // should not happen - case folderAttributes::SPECIALUSE_ALL: oss << "\\All"; break; - case folderAttributes::SPECIALUSE_ARCHIVE: oss << "\\Archive"; break; - case folderAttributes::SPECIALUSE_DRAFTS: oss << "\\Drafts"; break; - case folderAttributes::SPECIALUSE_FLAGGED: oss << "\\Flagged"; break; - case folderAttributes::SPECIALUSE_JUNK: oss << "\\Junk"; break; - case folderAttributes::SPECIALUSE_SENT: oss << "\\Sent"; break; - case folderAttributes::SPECIALUSE_TRASH: oss << "\\Trash"; break; - case folderAttributes::SPECIALUSE_IMPORTANT: oss << "\\Important"; break; + switch (attribs.getSpecialUse()) { + + case folderAttributes::SPECIALUSE_NONE: // should not happen + case folderAttributes::SPECIALUSE_ALL: oss << "\\All"; break; + case folderAttributes::SPECIALUSE_ARCHIVE: oss << "\\Archive"; break; + case folderAttributes::SPECIALUSE_DRAFTS: oss << "\\Drafts"; break; + case folderAttributes::SPECIALUSE_FLAGGED: oss << "\\Flagged"; break; + case folderAttributes::SPECIALUSE_JUNK: oss << "\\Junk"; break; + case folderAttributes::SPECIALUSE_SENT: oss << "\\Sent"; break; + case folderAttributes::SPECIALUSE_TRASH: oss << "\\Trash"; break; + case folderAttributes::SPECIALUSE_IMPORTANT: oss << "\\Important"; break; } oss << ")"; @@ -384,34 +405,38 @@ void IMAPFolder::create(const folderAttributes& attribs) scoped_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("CREATE", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("CREATE", resp->getErrorLog(), "bad response"); } // Notify folder created shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_CREATED, m_path, m_path); + make_shared ( + dynamicCast (shared_from_this()), + events::folderEvent::TYPE_CREATED, + m_path, m_path + ); notifyFolder(event); } -void IMAPFolder::destroy() -{ +void IMAPFolder::destroy() { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - if (isOpen()) + if (isOpen()) { throw exceptions::illegal_state("Folder is open"); + } - const string mailbox = IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath()); + const string mailbox = IMAPUtils::pathToString( + m_connection->hierarchySeparator(), getFullPath() + ); IMAPCommand::DELETE(mailbox)->send(m_connection); @@ -419,35 +444,37 @@ void IMAPFolder::destroy() scoped_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("DELETE", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("DELETE", resp->getErrorLog(), "bad response"); } // Notify folder deleted shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_DELETED, m_path, m_path); + make_shared ( + dynamicCast (shared_from_this()), + events::folderEvent::TYPE_DELETED, + m_path, m_path + ); notifyFolder(event); } -bool IMAPFolder::exists() -{ +bool IMAPFolder::exists() { + shared_ptr store = m_store.lock(); - if (!isOpen() && !store) + if (!isOpen() && !store) { throw exceptions::illegal_state("Store disconnected"); + } return testExistAndGetType() != -1; } -int IMAPFolder::testExistAndGetType() -{ +int IMAPFolder::testExistAndGetType() { + // To test whether a folder exists, we simple list it using // the "LIST" command, and there should be one unique mailbox // with this name... @@ -467,17 +494,21 @@ int IMAPFolder::testExistAndGetType() // // ==> NO, does not exist - IMAPCommand::LIST("", IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath()))->send(m_connection); + IMAPCommand::LIST( + "", + IMAPUtils::pathToString( + m_connection->hierarchySeparator(), + getFullPath() + ) + )->send(m_connection); scoped_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("LIST", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("LIST", resp->getErrorLog(), "bad response"); } // Check whether the result mailbox list contains this folder @@ -488,23 +519,26 @@ int IMAPFolder::testExistAndGetType() attribs.setType(-1); for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("LIST", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + + throw exceptions::command_error("LIST", resp->getErrorLog(), "invalid response"); } const IMAPParser::mailbox_data* mailboxData = (*it)->response_data()->mailbox_data(); // We are only interested in responses of type "LIST" - if (mailboxData != NULL && mailboxData->type() == IMAPParser::mailbox_data::LIST) - { + if (mailboxData != NULL && + mailboxData->type() == IMAPParser::mailbox_data::LIST) { + // Get the folder type/flags at the same time - IMAPUtils::mailboxFlagsToFolderAttributes - (m_connection, mailboxData->mailbox_list()->mailbox_flag_list(), attribs); + IMAPUtils::mailboxFlagsToFolderAttributes( + m_connection, + mailboxData->mailbox_list()->mailbox_flag_list(), + attribs + ); } } @@ -514,31 +548,35 @@ int IMAPFolder::testExistAndGetType() } -bool IMAPFolder::isOpen() const -{ - return (m_open); +bool IMAPFolder::isOpen() const { + + return m_open; } -shared_ptr IMAPFolder::getMessage(const size_t num) -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); +shared_ptr IMAPFolder::getMessage(const size_t num) { - if (num < 1 || num > m_status->getMessageCount()) + if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + if (num < 1 || num > m_status->getMessageCount()) { throw exceptions::message_not_found(); + } return make_shared (dynamicCast (shared_from_this()), num); } -std::vector > IMAPFolder::getMessages(const messageSet& msgs) -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); +std::vector > IMAPFolder::getMessages(const messageSet& msgs) { - if (msgs.isEmpty()) + if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + if (msgs.isEmpty()) { return std::vector >(); + } std::vector > messages; @@ -565,8 +603,8 @@ std::vector > IMAPFolder::getMessages(const messageSet& ms scoped_ptr resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + throw exceptions::command_error("UID FETCH ... UID", resp->getErrorLog(), "bad response"); } @@ -575,20 +613,20 @@ std::vector > IMAPFolder::getMessages(const messageSet& ms resp->continue_req_or_response_data(); for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("UID FETCH ... UID", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + + throw exceptions::command_error("UID FETCH ... UID", resp->getErrorLog(), "invalid response"); } const IMAPParser::message_data* messageData = (*it)->response_data()->message_data(); // We are only interested in responses of type "FETCH" - if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) + if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) { continue; + } // Get Process fetch response for this message const size_t msgNum = messageData->number(); @@ -598,17 +636,15 @@ std::vector > IMAPFolder::getMessages(const messageSet& ms const std::vector atts = messageData->msg_att()->items(); for (std::vector ::const_iterator - it = atts.begin() ; it != atts.end() ; ++it) - { - if ((*it)->type() == IMAPParser::msg_att_item::UID) - { + it = atts.begin() ; it != atts.end() ; ++it) { + + if ((*it)->type() == IMAPParser::msg_att_item::UID) { msgUID = (*it)->unique_id()->value(); break; } } - if (!msgUID.empty()) - { + if (!msgUID.empty()) { shared_ptr thisFolder = dynamicCast (shared_from_this()); messages.push_back(make_shared (thisFolder, msgNum, msgUID)); } @@ -618,50 +654,55 @@ std::vector > IMAPFolder::getMessages(const messageSet& ms } -size_t IMAPFolder::getMessageCount() -{ - if (!isOpen()) +size_t IMAPFolder::getMessageCount() { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } return m_status->getMessageCount(); } -vmime_uint32 IMAPFolder::getUIDValidity() const -{ - if (!isOpen()) +vmime_uint32 IMAPFolder::getUIDValidity() const { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } return m_status->getUIDValidity(); } -vmime_uint64 IMAPFolder::getHighestModSequence() const -{ - if (!isOpen()) +vmime_uint64 IMAPFolder::getHighestModSequence() const { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } return m_status->getHighestModSeq(); } -shared_ptr IMAPFolder::getFolder(const folder::path::component& name) -{ +shared_ptr IMAPFolder::getFolder(const folder::path::component& name) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - return shared_ptr (new IMAPFolder(m_path / name, store, shared_ptr ())); + return make_shared (m_path / name, store, shared_ptr ()); } -std::vector > IMAPFolder::getFolders(const bool recursive) -{ +std::vector > IMAPFolder::getFolders(const bool recursive) { + shared_ptr store = m_store.lock(); - if (!isOpen() && !store) + if (!isOpen() && !store) { throw exceptions::illegal_state("Store disconnected"); + } // Eg. List folders in '/foo/bar' // @@ -672,17 +713,22 @@ std::vector > IMAPFolder::getFolders(const bool recursive) shared_ptr cmd; - const string pathString = IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath()); + const string pathString = IMAPUtils::pathToString( + m_connection->hierarchySeparator(), getFullPath() + ); + + if (recursive) { - if (recursive) - { cmd = IMAPCommand::LIST(pathString, "*"); - } - else - { - cmd = IMAPCommand::LIST - (pathString.empty() ? "" : (pathString + m_connection->hierarchySeparator()), "%"); + + } else { + + cmd = IMAPCommand::LIST( + pathString.empty() + ? "" + : (pathString + m_connection->hierarchySeparator()), + "%" + ); } cmd->send(m_connection); @@ -691,8 +737,8 @@ std::vector > IMAPFolder::getFolders(const bool recursive) scoped_ptr resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + throw exceptions::command_error("LIST", resp->getErrorLog(), "bad response"); } @@ -703,57 +749,62 @@ std::vector > IMAPFolder::getFolders(const bool recursive) std::vector > v; for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("LIST", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + + throw exceptions::command_error("LIST", resp->getErrorLog(), "invalid response"); } const IMAPParser::mailbox_data* mailboxData = (*it)->response_data()->mailbox_data(); - if (mailboxData == NULL || mailboxData->type() != IMAPParser::mailbox_data::LIST) + if (mailboxData == NULL || mailboxData->type() != IMAPParser::mailbox_data::LIST) { continue; + } // Get folder path const class IMAPParser::mailbox* mailbox = mailboxData->mailbox_list()->mailbox(); - folder::path path = IMAPUtils::stringToPath - (mailboxData->mailbox_list()->quoted_char(), mailbox->name()); + folder::path path = IMAPUtils::stringToPath( + mailboxData->mailbox_list()->quoted_char(), mailbox->name() + ); + + if (recursive || m_path.isDirectParentOf(path)) { - if (recursive || m_path.isDirectParentOf(path)) - { // Append folder to list const class IMAPParser::mailbox_flag_list* mailbox_flag_list = mailboxData->mailbox_list()->mailbox_flag_list(); shared_ptr attribs = make_shared (); - IMAPUtils::mailboxFlagsToFolderAttributes - (m_connection, mailbox_flag_list, *attribs); + IMAPUtils::mailboxFlagsToFolderAttributes(m_connection, mailbox_flag_list, *attribs); - v.push_back(shared_ptr (new IMAPFolder(path, store, attribs))); + v.push_back(make_shared (path, store, attribs)); } } - return (v); + return v; } -void IMAPFolder::fetchMessages(std::vector >& msg, const fetchAttributes& options, - utility::progressListener* progress) -{ +void IMAPFolder::fetchMessages( + std::vector >& msg, + const fetchAttributes& options, + utility::progressListener* progress +) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (msg.empty()) + if (msg.empty()) { return; + } // Build message numbers list std::vector list; @@ -761,24 +812,24 @@ void IMAPFolder::fetchMessages(std::vector >& msg, const f std::map > numberToMsg; - for (std::vector >::iterator it = msg.begin() ; it != msg.end() ; ++it) - { + for (std::vector >::iterator it = msg.begin() ; it != msg.end() ; ++it) { + list.push_back((*it)->getNumber()); numberToMsg[(*it)->getNumber()] = dynamicCast (*it); } // Send the request - IMAPUtils::buildFetchCommand - (m_connection, messageSet::byNumber(list), options)->send(m_connection); + IMAPUtils::buildFetchCommand( + m_connection, messageSet::byNumber(list), options + )->send(m_connection); // Get the response scoped_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("FETCH", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("FETCH", resp->getErrorLog(), "bad response"); } const std::vector & respDataList = @@ -787,58 +838,62 @@ void IMAPFolder::fetchMessages(std::vector >& msg, const f const size_t total = msg.size(); size_t current = 0; - if (progress) + if (progress) { progress->start(total); + } + + try { - try - { for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("FETCH", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + + throw exceptions::command_error("FETCH", resp->getErrorLog(), "invalid response"); } const IMAPParser::message_data* messageData = (*it)->response_data()->message_data(); // We are only interested in responses of type "FETCH" - if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) + if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) { continue; + } // Process fetch response for this message const size_t num = messageData->number(); std::map >::iterator msg = numberToMsg.find(num); - if (msg != numberToMsg.end()) - { + if (msg != numberToMsg.end()) { + (*msg).second->processFetchResponse(options, messageData); - if (progress) + if (progress) { progress->progress(++current, total); + } } } - } - catch (...) - { - if (progress) + + } catch (...) { + + if (progress) { progress->stop(total); + } throw; } - if (progress) + if (progress) { progress->stop(total); + } processStatusUpdate(resp.get()); } -void IMAPFolder::fetchMessage(const shared_ptr & msg, const fetchAttributes& options) -{ +void IMAPFolder::fetchMessage(const shared_ptr & msg, const fetchAttributes& options) { + std::vector > msgs; msgs.push_back(msg); @@ -846,35 +901,37 @@ void IMAPFolder::fetchMessage(const shared_ptr & msg, const fetchAttrib } -std::vector > IMAPFolder::getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs) -{ +std::vector > IMAPFolder::getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs +) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (msgs.isEmpty()) + if (msgs.isEmpty()) { return std::vector >(); + } // Ensure we also get the UID for each message fetchAttributes attribsWithUID(attribs); attribsWithUID.add(fetchAttributes::UID); // Send the request - IMAPUtils::buildFetchCommand - (m_connection, msgs, attribsWithUID)->send(m_connection); + IMAPUtils::buildFetchCommand(m_connection, msgs, attribsWithUID)->send(m_connection); // Get the response scoped_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("FETCH", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("FETCH", resp->getErrorLog(), "bad response"); } const std::vector & respDataList = @@ -883,20 +940,20 @@ std::vector > IMAPFolder::getAndFetchMessages std::vector > messages; for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("FETCH", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + + throw exceptions::command_error("FETCH", resp->getErrorLog(), "invalid response"); } const IMAPParser::message_data* messageData = (*it)->response_data()->message_data(); // We are only interested in responses of type "FETCH" - if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) + if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) { continue; + } // Get message number const size_t msgNum = messageData->number(); @@ -906,10 +963,9 @@ std::vector > IMAPFolder::getAndFetchMessages message::uid msgUID; for (std::vector ::const_iterator - it = atts.begin() ; it != atts.end() ; ++it) - { - if ((*it)->type() == IMAPParser::msg_att_item::UID) - { + it = atts.begin() ; it != atts.end() ; ++it) { + + if ((*it)->type() == IMAPParser::msg_att_item::UID) { msgUID = (*it)->unique_id()->value(); break; } @@ -931,8 +987,8 @@ std::vector > IMAPFolder::getAndFetchMessages } -int IMAPFolder::getFetchCapabilities() const -{ +int IMAPFolder::getFetchCapabilities() const { + return fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | fetchAttributes::STRUCTURE | fetchAttributes::FLAGS | fetchAttributes::SIZE | fetchAttributes::FULL_HEADER | @@ -940,64 +996,71 @@ int IMAPFolder::getFetchCapabilities() const } -shared_ptr IMAPFolder::getParent() -{ - if (m_path.isEmpty()) +shared_ptr IMAPFolder::getParent() { + + if (m_path.isEmpty()) { + return null; - else - return shared_ptr ( - new IMAPFolder(m_path.getParent(), m_store.lock(), shared_ptr ()) + + } else { + + return make_shared ( + m_path.getParent(), m_store.lock(), shared_ptr () ); + } } -shared_ptr IMAPFolder::getStore() const -{ +shared_ptr IMAPFolder::getStore() const { + return m_store.lock(); } -shared_ptr IMAPFolder::getStore() -{ +shared_ptr IMAPFolder::getStore() { + return m_store.lock(); } -void IMAPFolder::registerMessage(IMAPMessage* msg) -{ +void IMAPFolder::registerMessage(IMAPMessage* msg) { + m_messages.push_back(msg); } -void IMAPFolder::unregisterMessage(IMAPMessage* msg) -{ +void IMAPFolder::unregisterMessage(IMAPMessage* msg) { + std::vector ::iterator it = std::find(m_messages.begin(), m_messages.end(), msg); - if (it != m_messages.end()) + if (it != m_messages.end()) { m_messages.erase(it); + } } -void IMAPFolder::onStoreDisconnected() -{ +void IMAPFolder::onStoreDisconnected() { + m_store.reset(); } -void IMAPFolder::deleteMessages(const messageSet& msgs) -{ +void IMAPFolder::deleteMessages(const messageSet& msgs) { + shared_ptr store = m_store.lock(); - if (msgs.isEmpty()) + if (msgs.isEmpty()) { throw exceptions::invalid_argument(); + } - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) + } else if (m_mode == MODE_READ_ONLY) { throw exceptions::illegal_state("Folder is read-only"); + } // Send the request IMAPCommand::STORE( @@ -1009,22 +1072,25 @@ void IMAPFolder::deleteMessages(const messageSet& msgs) scoped_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("STORE", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("STORE", resp->getErrorLog(), "bad response"); } processStatusUpdate(resp.get()); } -void IMAPFolder::setMessageFlags(const messageSet& msgs, const int flags, const int mode) -{ +void IMAPFolder::setMessageFlags( + const messageSet& msgs, + const int flags, + const int mode +) { + const std::vector flagList = IMAPUtils::messageFlagList(flags); - if (!flagList.empty()) - { + if (!flagList.empty()) { + // Send the request IMAPCommand::STORE(msgs, mode, flagList)->send(m_connection); @@ -1032,10 +1098,9 @@ void IMAPFolder::setMessageFlags(const messageSet& msgs, const int flags, const scoped_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("STORE", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("STORE", resp->getErrorLog(), "bad response"); } processStatusUpdate(resp.get()); @@ -1043,10 +1108,13 @@ void IMAPFolder::setMessageFlags(const messageSet& msgs, const int flags, const } -messageSet IMAPFolder::addMessage - (const shared_ptr & msg, const int flags, - vmime::datetime* date, utility::progressListener* progress) -{ +messageSet IMAPFolder::addMessage( + const shared_ptr & msg, + const int flags, + vmime::datetime* date, + utility::progressListener* progress +) { + std::ostringstream oss; utility::outputStreamAdapter ossAdapter(oss); @@ -1059,18 +1127,23 @@ messageSet IMAPFolder::addMessage } -messageSet IMAPFolder::addMessage - (utility::inputStream& is, const size_t size, const int flags, - vmime::datetime* date, utility::progressListener* progress) -{ +messageSet IMAPFolder::addMessage( + utility::inputStream& is, + const size_t size, + const int flags, + vmime::datetime* date, + utility::progressListener* progress +) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) + } else if (m_mode == MODE_READ_ONLY) { throw exceptions::illegal_state("Folder is read-only"); + } // Send the request IMAPCommand::APPEND( @@ -1086,16 +1159,15 @@ messageSet IMAPFolder::addMessage = resp->continue_req_or_response_data(); for (std::vector ::const_iterator - it = respList.begin() ; !ok && (it != respList.end()) ; ++it) - { - if ((*it)->continue_req()) + it = respList.begin() ; !ok && (it != respList.end()) ; ++it) { + + if ((*it)->continue_req()) { ok = true; + } } - if (!ok) - { - throw exceptions::command_error("APPEND", - resp->getErrorLog(), "bad response"); + if (!ok) { + throw exceptions::command_error("APPEND", resp->getErrorLog(), "bad response"); } processStatusUpdate(resp.get()); @@ -1104,17 +1176,20 @@ messageSet IMAPFolder::addMessage const size_t total = size; size_t current = 0; - if (progress) + if (progress) { progress->start(total); + } - const size_t blockSize = std::min(is.getBlockSize(), - static_cast (m_connection->getSocket()->getBlockSize())); + const size_t blockSize = std::min( + is.getBlockSize(), + static_cast (m_connection->getSocket()->getBlockSize()) + ); std::vector vbuffer(blockSize); byte_t* buffer = &vbuffer.front(); - while (!is.eof()) - { + while (!is.eof()) { + // Read some data from the input stream const size_t read = is.read(buffer, blockSize); current += read; @@ -1123,26 +1198,28 @@ messageSet IMAPFolder::addMessage m_connection->sendRaw(buffer, read); // Notify progress - if (progress) + if (progress) { progress->progress(current, total); + } } m_connection->sendRaw(utility::stringUtils::bytesFromString("\r\n"), 2); - if (m_connection->getTracer()) + if (m_connection->getTracer()) { m_connection->getTracer()->traceSendBytes(current); + } - if (progress) + if (progress) { progress->stop(total); + } // Get the response scoped_ptr finalResp(m_connection->readResponse()); if (finalResp->isBad() || finalResp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("APPEND", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("APPEND", resp->getErrorLog(), "bad response"); } processStatusUpdate(finalResp.get()); @@ -1150,23 +1227,25 @@ messageSet IMAPFolder::addMessage const IMAPParser::resp_text_code* respTextCode = finalResp->response_done()->response_tagged()->resp_cond_state()->resp_text()->resp_text_code(); - if (respTextCode && respTextCode->type() == IMAPParser::resp_text_code::APPENDUID) + if (respTextCode && respTextCode->type() == IMAPParser::resp_text_code::APPENDUID) { return IMAPUtils::buildMessageSet(respTextCode->uid_set()); + } return messageSet::empty(); } -void IMAPFolder::expunge() -{ +void IMAPFolder::expunge() { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) + } else if (m_mode == MODE_READ_ONLY) { throw exceptions::illegal_state("Folder is read-only"); + } // Send the request IMAPCommand::EXPUNGE()->send(m_connection); @@ -1175,28 +1254,28 @@ void IMAPFolder::expunge() scoped_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("EXPUNGE", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("EXPUNGE", resp->getErrorLog(), "bad response"); } processStatusUpdate(resp.get()); } -void IMAPFolder::rename(const folder::path& newPath) -{ +void IMAPFolder::rename(const folder::path& newPath) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (m_path.isEmpty() || newPath.isEmpty()) + } 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") + } else if (m_path.getSize() == 1 && m_name.getBuffer() == "INBOX") { throw exceptions::illegal_operation("Cannot rename 'INBOX' folder"); - else if (!store->isValidFolderName(newPath.getLastComponent())) + } else if (!store->isValidFolderName(newPath.getLastComponent())) { throw exceptions::invalid_folder_name(); + } // Send the request IMAPCommand::RENAME( @@ -1208,10 +1287,9 @@ void IMAPFolder::rename(const folder::path& newPath) scoped_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("RENAME", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("RENAME", resp->getErrorLog(), "bad response"); } // Notify folder renamed @@ -1221,26 +1299,31 @@ void IMAPFolder::rename(const folder::path& newPath) m_name = newPath.getLastComponent(); shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); + make_shared ( + dynamicCast (shared_from_this()), + events::folderEvent::TYPE_RENAMED, + oldPath, + newPath + ); notifyFolder(event); // Notify sub-folders for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) { + folder::path oldPath((*it)->m_path); (*it)->m_path.renameParent(oldPath, newPath); shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path); + make_shared ( + dynamicCast ((*it)->shared_from_this()), + events::folderEvent::TYPE_RENAMED, + oldPath, (*it)->m_path + ); (*it)->notifyFolder(event); } @@ -1250,14 +1333,15 @@ void IMAPFolder::rename(const folder::path& newPath) } -messageSet IMAPFolder::copyMessages(const folder::path& dest, const messageSet& set) -{ +messageSet IMAPFolder::copyMessages(const folder::path& dest, const messageSet& set) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } // Send the request IMAPCommand::COPY( @@ -1269,10 +1353,9 @@ messageSet IMAPFolder::copyMessages(const folder::path& dest, const messageSet& scoped_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("COPY", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("COPY", resp->getErrorLog(), "bad response"); } processStatusUpdate(resp.get()); @@ -1280,15 +1363,16 @@ messageSet IMAPFolder::copyMessages(const folder::path& dest, const messageSet& const IMAPParser::resp_text_code* respTextCode = resp->response_done()->response_tagged()->resp_cond_state()->resp_text()->resp_text_code(); - if (respTextCode && respTextCode->type() == IMAPParser::resp_text_code::COPYUID) + if (respTextCode && respTextCode->type() == IMAPParser::resp_text_code::COPYUID) { return IMAPUtils::buildMessageSet(respTextCode->uid_set2()); + } return messageSet::empty(); } -void IMAPFolder::status(size_t& count, size_t& unseen) -{ +void IMAPFolder::status(size_t& count, size_t& unseen) { + count = 0; unseen = 0; @@ -1299,12 +1383,13 @@ void IMAPFolder::status(size_t& count, size_t& unseen) } -shared_ptr IMAPFolder::getStatus() -{ +shared_ptr IMAPFolder::getStatus() { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } // Build the attributes list std::vector attribs; @@ -1314,8 +1399,9 @@ shared_ptr IMAPFolder::getStatus() attribs.push_back("UIDNEXT"); attribs.push_back("UIDVALIDITY"); - if (m_connection->hasCapability("CONDSTORE")) + if (m_connection->hasCapability("CONDSTORE")) { attribs.push_back("HIGHESTMODSEQ"); + } // Send the request IMAPCommand::STATUS( @@ -1327,25 +1413,24 @@ shared_ptr IMAPFolder::getStatus() scoped_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", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("STATUS", resp->getErrorLog(), "bad response"); } const std::vector & respDataList = resp->continue_req_or_response_data(); for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() != NULL) - { + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() != NULL) { + const IMAPParser::response_data* responseData = (*it)->response_data(); if (responseData->mailbox_data() && - responseData->mailbox_data()->type() == IMAPParser::mailbox_data::STATUS) - { + responseData->mailbox_data()->type() == IMAPParser::mailbox_data::STATUS) { + shared_ptr status = make_shared (); status->updateFromResponse(responseData->mailbox_data()); @@ -1356,25 +1441,25 @@ shared_ptr IMAPFolder::getStatus() } } - throw exceptions::command_error("STATUS", - resp->getErrorLog(), "invalid response"); + throw exceptions::command_error("STATUS", resp->getErrorLog(), "invalid response"); } -void IMAPFolder::noop() -{ +void IMAPFolder::noop() { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } IMAPCommand::NOOP()->send(m_connection); scoped_ptr resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + throw exceptions::command_error("NOOP", resp->getErrorLog()); } @@ -1382,8 +1467,8 @@ void IMAPFolder::noop() } -std::vector IMAPFolder::getMessageNumbersStartingOnUID(const message::uid& uid) -{ +std::vector IMAPFolder::getMessageNumbersStartingOnUID(const message::uid& uid) { + // Send the request std::ostringstream uidSearchKey; uidSearchKey.imbue(std::locale::classic()); @@ -1398,22 +1483,20 @@ std::vector IMAPFolder::getMessageNumbersStartingOnUID(const message::u scoped_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("SEARCH", - resp->getErrorLog(), "bad response"); + resp->response_done()->response_tagged()->resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("SEARCH", resp->getErrorLog(), "bad response"); } const std::vector & respDataList = resp->continue_req_or_response_data(); + std::vector seqNumbers; for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("SEARCH", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + throw exceptions::command_error("SEARCH", resp->getErrorLog(), "invalid response"); } const IMAPParser::mailbox_data* mailboxData = @@ -1421,16 +1504,16 @@ std::vector IMAPFolder::getMessageNumbersStartingOnUID(const message::u // We are only interested in responses of type "SEARCH" if (mailboxData == NULL || - mailboxData->type() != IMAPParser::mailbox_data::SEARCH) - { + mailboxData->type() != IMAPParser::mailbox_data::SEARCH) { + continue; } for (std::vector ::const_iterator it = mailboxData->search_nz_number_list().begin() ; it != mailboxData->search_nz_number_list().end(); - ++it) - { + ++it) { + seqNumbers.push_back((*it)->value()); } } @@ -1441,8 +1524,8 @@ std::vector IMAPFolder::getMessageNumbersStartingOnUID(const message::u } -void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) -{ +void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) { + std::vector > events; shared_ptr oldStatus = vmime::clone(m_status); @@ -1451,8 +1534,8 @@ void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) // Process tagged response if (resp->response_done() && resp->response_done()->response_tagged() && resp->response_done()->response_tagged() - ->resp_cond_state()->resp_text()->resp_text_code()) - { + ->resp_cond_state()->resp_text()->resp_text_code()) { + const IMAPParser::resp_text_code* code = resp->response_done()->response_tagged() ->resp_cond_state()->resp_text()->resp_text_code(); @@ -1463,66 +1546,77 @@ void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) // Process untagged responses for (std::vector ::const_iterator it = resp->continue_req_or_response_data().begin() ; - it != resp->continue_req_or_response_data().end() ; ++it) - { + it != resp->continue_req_or_response_data().end() ; ++it) { + if ((*it)->response_data() && (*it)->response_data()->resp_cond_state() && - (*it)->response_data()->resp_cond_state()->resp_text()->resp_text_code()) - { + (*it)->response_data()->resp_cond_state()->resp_text()->resp_text_code()) { + const IMAPParser::resp_text_code* code = (*it)->response_data()->resp_cond_state()->resp_text()->resp_text_code(); m_status->updateFromResponse(code); - } - else if ((*it)->response_data() && (*it)->response_data()->mailbox_data()) - { + + } else if ((*it)->response_data() && (*it)->response_data()->mailbox_data()) { + m_status->updateFromResponse((*it)->response_data()->mailbox_data()); // Update folder attributes, if available - if ((*it)->response_data()->mailbox_data()->type() == IMAPParser::mailbox_data::LIST) - { + if ((*it)->response_data()->mailbox_data()->type() == IMAPParser::mailbox_data::LIST) { + folderAttributes attribs; - IMAPUtils::mailboxFlagsToFolderAttributes - (m_connection, (*it)->response_data()->mailbox_data()->mailbox_list()->mailbox_flag_list(), attribs); + IMAPUtils::mailboxFlagsToFolderAttributes( + m_connection, + (*it)->response_data()->mailbox_data()->mailbox_list()->mailbox_flag_list(), + attribs + ); m_attribs = make_shared (attribs); } - } - else if ((*it)->response_data() && (*it)->response_data()->message_data()) - { + + } else if ((*it)->response_data() && (*it)->response_data()->message_data()) { + const IMAPParser::message_data* msgData = (*it)->response_data()->message_data(); const size_t msgNumber = msgData->number(); - if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::FETCH) - { + if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::FETCH) { + // Message changed for (std::vector ::iterator mit = - m_messages.begin() ; mit != m_messages.end() ; ++mit) - { - if ((*mit)->getNumber() == msgNumber) + m_messages.begin() ; mit != m_messages.end() ; ++mit) { + + if ((*mit)->getNumber() == msgNumber) { (*mit)->processFetchResponse(/* options */ 0, msgData); + } } - events.push_back(make_shared - (dynamicCast (shared_from_this()), - events::messageChangedEvent::TYPE_FLAGS, - std::vector (1, msgNumber))); - } - else if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::EXPUNGE) - { + events.push_back( + make_shared ( + dynamicCast (shared_from_this()), + events::messageChangedEvent::TYPE_FLAGS, + std::vector (1, msgNumber) + ) + ); + + } else if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::EXPUNGE) { + // A message has been expunged, renumber messages for (std::vector ::iterator jt = - m_messages.begin() ; jt != m_messages.end() ; ++jt) - { - if ((*jt)->getNumber() == msgNumber) + m_messages.begin() ; jt != m_messages.end() ; ++jt) { + + if ((*jt)->getNumber() == msgNumber) { (*jt)->setExpunged(); - else if ((*jt)->getNumber() > msgNumber) + } else if ((*jt)->getNumber() > msgNumber) { (*jt)->renumber((*jt)->getNumber() - 1); + } } - events.push_back(make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_REMOVED, - std::vector (1, msgNumber))); + events.push_back( + make_shared ( + dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_REMOVED, + std::vector (1, msgNumber) + ) + ); expungedMessageCount++; } @@ -1530,26 +1624,29 @@ void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) } // New messages arrived - if (m_status->getMessageCount() > oldStatus->getMessageCount() - expungedMessageCount) - { + if (m_status->getMessageCount() > oldStatus->getMessageCount() - expungedMessageCount) { + std::vector newMessageNumbers; for (size_t msgNumber = oldStatus->getMessageCount() - expungedMessageCount ; - msgNumber <= m_status->getMessageCount() ; ++msgNumber) - { + msgNumber <= m_status->getMessageCount() ; ++msgNumber) { + newMessageNumbers.push_back(msgNumber); } - events.push_back(make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_ADDED, - newMessageNumbers)); + events.push_back( + make_shared ( + dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + newMessageNumbers + ) + ); } // Dispatch notifications for (std::vector >::iterator evit = - events.begin() ; evit != events.end() ; ++evit) - { + events.begin() ; evit != events.end() ; ++evit) { + notifyEvent(*evit); } } diff --git a/src/vmime/net/imap/IMAPFolder.hpp b/src/vmime/net/imap/IMAPFolder.hpp index 15663232..3e6b04b5 100644 --- a/src/vmime/net/imap/IMAPFolder.hpp +++ b/src/vmime/net/imap/IMAPFolder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -54,19 +54,23 @@ class IMAPFolderStatus; /** IMAP folder implementation. */ +class VMIME_EXPORT IMAPFolder : public folder { -class VMIME_EXPORT IMAPFolder : public folder -{ private: friend class IMAPStore; friend class IMAPMessage; IMAPFolder(const IMAPFolder&); - IMAPFolder(const folder::path& path, const shared_ptr & store, const shared_ptr & attribs); public: + IMAPFolder( + const folder::path& path, + const shared_ptr & store, + const shared_ptr & attribs + ); + ~IMAPFolder(); int getMode() const; @@ -100,20 +104,26 @@ public: void deleteMessages(const messageSet& msgs); - void setMessageFlags(const messageSet& msgs, const int flags, const int mode = message::FLAG_MODE_SET); + void setMessageFlags( + const messageSet& msgs, + const int flags, + const int mode = message::FLAG_MODE_SET + ); - messageSet addMessage - (const shared_ptr & msg, - const int flags = -1, - vmime::datetime* date = NULL, - utility::progressListener* progress = NULL); + messageSet addMessage( + const shared_ptr & msg, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); - messageSet addMessage - (utility::inputStream& is, - const size_t size, - const int flags = -1, - vmime::datetime* date = NULL, - utility::progressListener* progress = NULL); + messageSet addMessage( + utility::inputStream& is, + const size_t size, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); messageSet copyMessages(const folder::path& dest, const messageSet& msgs); @@ -130,11 +140,18 @@ public: shared_ptr getStore(); - void fetchMessages(std::vector >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL); + void fetchMessages( + std::vector >& msg, + const fetchAttributes& options, + utility::progressListener* progress = NULL + ); + void fetchMessage(const shared_ptr & msg, const fetchAttributes& options); - std::vector > getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs); + std::vector > getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs + ); int getFetchCapabilities() const; diff --git a/src/vmime/net/imap/IMAPFolderStatus.cpp b/src/vmime/net/imap/IMAPFolderStatus.cpp index 73e1dfed..1962c1ca 100644 --- a/src/vmime/net/imap/IMAPFolderStatus.cpp +++ b/src/vmime/net/imap/IMAPFolderStatus.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,8 +41,8 @@ IMAPFolderStatus::IMAPFolderStatus() m_recent(0), m_uidValidity(0), m_uidNext(0), - m_highestModSeq(0) -{ + m_highestModSeq(0) { + } @@ -53,166 +53,158 @@ IMAPFolderStatus::IMAPFolderStatus(const IMAPFolderStatus& other) m_recent(other.m_recent), m_uidValidity(other.m_uidValidity), m_uidNext(other.m_uidNext), - m_highestModSeq(other.m_highestModSeq) -{ + m_highestModSeq(other.m_highestModSeq) { + } -size_t IMAPFolderStatus::getMessageCount() const -{ +size_t IMAPFolderStatus::getMessageCount() const { + return m_count; } -size_t IMAPFolderStatus::getUnseenCount() const -{ +size_t IMAPFolderStatus::getUnseenCount() const { + return m_unseen; } -size_t IMAPFolderStatus::getRecentCount() const -{ +size_t IMAPFolderStatus::getRecentCount() const { + return m_recent; } -vmime_uint32 IMAPFolderStatus::getUIDValidity() const -{ +vmime_uint32 IMAPFolderStatus::getUIDValidity() const { + return m_uidValidity; } -vmime_uint32 IMAPFolderStatus::getUIDNext() const -{ +vmime_uint32 IMAPFolderStatus::getUIDNext() const { + return m_uidNext; } -vmime_uint64 IMAPFolderStatus::getHighestModSeq() const -{ +vmime_uint64 IMAPFolderStatus::getHighestModSeq() const { + return m_highestModSeq; } -shared_ptr IMAPFolderStatus::clone() const -{ +shared_ptr IMAPFolderStatus::clone() const { + return make_shared (*this); } -bool IMAPFolderStatus::updateFromResponse(const IMAPParser::mailbox_data* resp) -{ +bool IMAPFolderStatus::updateFromResponse(const IMAPParser::mailbox_data* resp) { + bool changed = false; - if (resp->type() == IMAPParser::mailbox_data::STATUS) - { + if (resp->type() == IMAPParser::mailbox_data::STATUS) { + const IMAPParser::status_att_list* statusAttList = resp->status_att_list(); for (std::vector ::const_iterator - jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt) - { - switch ((*jt)->type()) - { - case IMAPParser::status_att_val::MESSAGES: - { - const size_t count = - static_cast ((*jt)->value_as_number()->value()); + jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt) { - if (m_count != count) - { - m_count = count; - changed = true; + switch ((*jt)->type()) { + + case IMAPParser::status_att_val::MESSAGES: { + + const size_t count = + static_cast ((*jt)->value_as_number()->value()); + + if (m_count != count) { + m_count = count; + changed = true; + } + + break; } + case IMAPParser::status_att_val::UNSEEN: { - break; - } - case IMAPParser::status_att_val::UNSEEN: - { - const size_t unseen = - static_cast ((*jt)->value_as_number()->value()); + const size_t unseen = + static_cast ((*jt)->value_as_number()->value()); - if (m_unseen != unseen) - { - m_unseen = unseen; - changed = true; + if (m_unseen != unseen) { + m_unseen = unseen; + changed = true; + } + + break; } + case IMAPParser::status_att_val::RECENT: { - break; - } - case IMAPParser::status_att_val::RECENT: - { - const size_t recent = - static_cast ((*jt)->value_as_number()->value()); + const size_t recent = + static_cast ((*jt)->value_as_number()->value()); - if (m_recent != recent) - { - m_recent = recent; - changed = true; + if (m_recent != recent) { + m_recent = recent; + changed = true; + } + + break; } + case IMAPParser::status_att_val::UIDNEXT: { - break; - } - case IMAPParser::status_att_val::UIDNEXT: - { - const vmime_uint32 uidNext = - static_cast ((*jt)->value_as_number()->value()); + const vmime_uint32 uidNext = + static_cast ((*jt)->value_as_number()->value()); - if (m_uidNext != uidNext) - { - m_uidNext = uidNext; - changed = true; + if (m_uidNext != uidNext) { + m_uidNext = uidNext; + changed = true; + } + + break; } + case IMAPParser::status_att_val::UIDVALIDITY: { - break; - } - case IMAPParser::status_att_val::UIDVALIDITY: - { - const vmime_uint32 uidValidity = - static_cast ((*jt)->value_as_number()->value()); + const vmime_uint32 uidValidity = + static_cast ((*jt)->value_as_number()->value()); - if (m_uidValidity != uidValidity) - { - m_uidValidity = uidValidity; - changed = true; + if (m_uidValidity != uidValidity) { + m_uidValidity = uidValidity; + changed = true; + } + + break; } + case IMAPParser::status_att_val::HIGHESTMODSEQ: { - break; - } - case IMAPParser::status_att_val::HIGHESTMODSEQ: - { - const vmime_uint64 highestModSeq = - static_cast ((*jt)->value_as_mod_sequence_value()->value()); + const vmime_uint64 highestModSeq = + static_cast ((*jt)->value_as_mod_sequence_value()->value()); - if (m_highestModSeq != highestModSeq) - { - m_highestModSeq = highestModSeq; - changed = true; + if (m_highestModSeq != highestModSeq) { + m_highestModSeq = highestModSeq; + changed = true; + } + + break; } - break; - } - } } - } - else if (resp->type() == IMAPParser::mailbox_data::EXISTS) - { + + } else if (resp->type() == IMAPParser::mailbox_data::EXISTS) { + const size_t count = static_cast (resp->number()->value()); - if (m_count != count) - { + if (m_count != count) { m_count = count; changed = true; } - } - else if (resp->type() == IMAPParser::mailbox_data::RECENT) - { + + } else if (resp->type() == IMAPParser::mailbox_data::RECENT) { + const size_t recent = static_cast (resp->number()->value()); - if (m_recent != recent) - { + if (m_recent != recent) { m_recent = recent; changed = true; } @@ -222,77 +214,73 @@ bool IMAPFolderStatus::updateFromResponse(const IMAPParser::mailbox_data* resp) } -bool IMAPFolderStatus::updateFromResponse(const IMAPParser::resp_text_code* resp) -{ +bool IMAPFolderStatus::updateFromResponse(const IMAPParser::resp_text_code* resp) { + bool changed = false; - switch (resp->type()) - { - case IMAPParser::resp_text_code::UIDVALIDITY: - { - const vmime_uint32 uidValidity = - static_cast (resp->nz_number()->value()); + switch (resp->type()) { - if (m_uidValidity != uidValidity) - { - m_uidValidity = uidValidity; - changed = true; + case IMAPParser::resp_text_code::UIDVALIDITY: { + + const vmime_uint32 uidValidity = + static_cast (resp->nz_number()->value()); + + if (m_uidValidity != uidValidity) { + m_uidValidity = uidValidity; + changed = true; + } + + break; } + case IMAPParser::resp_text_code::UIDNEXT: { - break; - } - case IMAPParser::resp_text_code::UIDNEXT: - { - const vmime_uint32 uidNext = - static_cast (resp->nz_number()->value()); + const vmime_uint32 uidNext = + static_cast (resp->nz_number()->value()); - if (m_uidNext != uidNext) - { - m_uidNext = uidNext; - changed = true; + if (m_uidNext != uidNext) { + m_uidNext = uidNext; + changed = true; + } + + break; } + case IMAPParser::resp_text_code::UNSEEN: { - break; - } - case IMAPParser::resp_text_code::UNSEEN: - { - const size_t unseen = - static_cast (resp->nz_number()->value()); + const size_t unseen = + static_cast (resp->nz_number()->value()); - if (m_unseen != unseen) - { - m_unseen = unseen; - changed = true; + if (m_unseen != unseen) + { + m_unseen = unseen; + changed = true; + } + + break; } + case IMAPParser::resp_text_code::HIGHESTMODSEQ: { - break; - } - case IMAPParser::resp_text_code::HIGHESTMODSEQ: - { - const vmime_uint64 highestModSeq = - static_cast (resp->mod_sequence_value()->value()); + const vmime_uint64 highestModSeq = + static_cast (resp->mod_sequence_value()->value()); - if (m_highestModSeq != highestModSeq) - { - m_highestModSeq = highestModSeq; - changed = true; + if (m_highestModSeq != highestModSeq) { + m_highestModSeq = highestModSeq; + changed = true; + } + + break; } + case IMAPParser::resp_text_code::NOMODSEQ: { - break; - } - case IMAPParser::resp_text_code::NOMODSEQ: - { - if (m_highestModSeq != 0) - { - m_highestModSeq = 0; - changed = true; + if (m_highestModSeq != 0) { + m_highestModSeq = 0; + changed = true; + } + + break; } + default: - break; - } - default: - - break; + break; } return changed; diff --git a/src/vmime/net/imap/IMAPFolderStatus.hpp b/src/vmime/net/imap/IMAPFolderStatus.hpp index 63143548..846ad771 100644 --- a/src/vmime/net/imap/IMAPFolderStatus.hpp +++ b/src/vmime/net/imap/IMAPFolderStatus.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,9 +43,8 @@ namespace imap { /** Holds the status of an IMAP folder. */ +class VMIME_EXPORT IMAPFolderStatus : public folderStatus { -class VMIME_EXPORT IMAPFolderStatus : public folderStatus -{ public: IMAPFolderStatus(); diff --git a/src/vmime/net/imap/IMAPMessage.cpp b/src/vmime/net/imap/IMAPMessage.cpp index 87f78f38..b09c9c19 100644 --- a/src/vmime/net/imap/IMAPMessage.cpp +++ b/src/vmime/net/imap/IMAPMessage.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -56,25 +56,25 @@ namespace imap { // IMAPMessage_literalHandler // -class IMAPMessage_literalHandler : public IMAPParser::literalHandler -{ +class IMAPMessage_literalHandler : public IMAPParser::literalHandler { + public: - IMAPMessage_literalHandler(utility::outputStream& os, utility::progressListener* progress) - { + IMAPMessage_literalHandler(utility::outputStream& os, utility::progressListener* progress) { + m_target = shared_ptr (new targetStream(progress, os)); } - shared_ptr targetFor(const IMAPParser::component& comp, const int /* data */) - { - if (typeid(comp) == typeid(IMAPParser::msg_att_item)) - { + shared_ptr targetFor(const IMAPParser::component& comp, const int /* data */) { + + if (typeid(comp) == typeid(IMAPParser::msg_att_item)) { + const int type = static_cast (comp).type(); if (type == IMAPParser::msg_att_item::BODY_SECTION || - type == IMAPParser::msg_att_item::RFC822_TEXT) - { + type == IMAPParser::msg_att_item::RFC822_TEXT) { + return m_target; } } @@ -82,8 +82,8 @@ public: return shared_ptr (); } - shared_ptr getTarget() - { + shared_ptr getTarget() { + return m_target; } @@ -101,152 +101,187 @@ private: // -IMAPMessage::IMAPMessage(const shared_ptr & folder, const size_t num) - : m_folder(folder), m_num(num), m_size(-1U), m_flags(FLAG_UNDEFINED), - m_expunged(false), m_modseq(0), m_structure(null) -{ +IMAPMessage::IMAPMessage( + const shared_ptr & folder, + const size_t num +) + : m_folder(folder), + m_num(num), + m_size(-1U), + m_flags(FLAG_UNDEFINED), + m_expunged(false), + m_modseq(0), + m_structure(null) { + folder->registerMessage(this); } -IMAPMessage::IMAPMessage(const shared_ptr & folder, const size_t num, const uid& uid) - : m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED), - m_expunged(false), m_uid(uid), m_modseq(0), m_structure(null) -{ +IMAPMessage::IMAPMessage( + const shared_ptr & folder, + const size_t num, + const uid& uid +) + : m_folder(folder), + m_num(num), + m_size(-1), + m_flags(FLAG_UNDEFINED), + m_expunged(false), + m_uid(uid), + m_modseq(0), + m_structure(null) { + folder->registerMessage(this); } -IMAPMessage::~IMAPMessage() -{ - try - { +IMAPMessage::~IMAPMessage() { + + try { + shared_ptr folder = m_folder.lock(); - if (folder) + if (folder) { folder->unregisterMessage(this); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -void IMAPMessage::onFolderClosed() -{ +void IMAPMessage::onFolderClosed() { + m_folder.reset(); } -size_t IMAPMessage::getNumber() const -{ - return (m_num); +size_t IMAPMessage::getNumber() const { + + return m_num; } -const message::uid IMAPMessage::getUID() const -{ +const message::uid IMAPMessage::getUID() const { + return m_uid; } -vmime_uint64 IMAPMessage::getModSequence() const -{ +vmime_uint64 IMAPMessage::getModSequence() const { + return m_modseq; } -size_t IMAPMessage::getSize() const -{ - if (m_size == -1U) - throw exceptions::unfetched_object(); +size_t IMAPMessage::getSize() const { - return (m_size); + if (m_size == -1U) { + throw exceptions::unfetched_object(); + } + + return m_size; } -bool IMAPMessage::isExpunged() const -{ - return (m_expunged); +bool IMAPMessage::isExpunged() const { + + return m_expunged; } -int IMAPMessage::getFlags() const -{ - if (m_flags == FLAG_UNDEFINED) - throw exceptions::unfetched_object(); +int IMAPMessage::getFlags() const { - return (m_flags); + if (m_flags == FLAG_UNDEFINED) { + throw exceptions::unfetched_object(); + } + + return m_flags; } -shared_ptr IMAPMessage::getStructure() const -{ - if (m_structure == NULL) +shared_ptr IMAPMessage::getStructure() const { + + if (m_structure == NULL) { throw exceptions::unfetched_object(); + } return m_structure; } -shared_ptr IMAPMessage::getStructure() -{ - if (m_structure == NULL) +shared_ptr IMAPMessage::getStructure() { + + if (m_structure == NULL) { throw exceptions::unfetched_object(); + } return m_structure; } -shared_ptr IMAPMessage::getHeader() const -{ - if (m_header == NULL) +shared_ptr IMAPMessage::getHeader() const { + + if (m_header == NULL) { throw exceptions::unfetched_object(); + } - return (m_header); + return m_header; } -void IMAPMessage::extract - (utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const bool peek) const -{ +void IMAPMessage::extract( + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const bool peek +) const { + shared_ptr folder = m_folder.lock(); - if (!folder) + if (!folder) { throw exceptions::folder_not_found(); + } - extractImpl(null, os, progress, start, length, - EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0)); + extractImpl( + null, os, progress, start, length, + EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0) + ); } -void IMAPMessage::extractPart - (const shared_ptr & p, - utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const bool peek) const -{ +void IMAPMessage::extractPart( + const shared_ptr & p, + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const bool peek +) const { + shared_ptr folder = m_folder.lock(); - if (!folder) + if (!folder) { throw exceptions::folder_not_found(); + } - extractImpl(p, os, progress, start, length, - EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0)); + extractImpl( + p, os, progress, start, length, + EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0) + ); } -void IMAPMessage::fetchPartHeader(const shared_ptr & p) -{ +void IMAPMessage::fetchPartHeader(const shared_ptr & p) { + shared_ptr folder = m_folder.lock(); - if (!folder) + if (!folder) { throw exceptions::folder_not_found(); + } std::ostringstream oss; utility::outputStreamAdapter ossAdapter(oss); @@ -257,10 +292,10 @@ void IMAPMessage::fetchPartHeader(const shared_ptr & p) } -void IMAPMessage::fetchPartHeaderForStructure(const shared_ptr & str) -{ - for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) - { +void IMAPMessage::fetchPartHeaderForStructure(const shared_ptr & str) { + + for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) { + shared_ptr part = str->getPartAt(i); // Fetch header of current part @@ -272,42 +307,43 @@ void IMAPMessage::fetchPartHeaderForStructure(const shared_ptr & p, - utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const int extractFlags) const -{ +size_t IMAPMessage::extractImpl( + const shared_ptr & p, + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const int extractFlags +) const { + shared_ptr folder = m_folder.lock(); IMAPMessage_literalHandler literalHandler(os, progress); - if (length == 0) + if (length == 0) { return 0; + } // Construct section identifier std::ostringstream section; section.imbue(std::locale::classic()); - if (p != NULL) - { + if (p != NULL) { + shared_ptr currentPart = dynamicCast (p); std::vector numbers; numbers.push_back(currentPart->getNumber()); currentPart = currentPart->getParent(); - while (currentPart != NULL) - { + while (currentPart != NULL) { numbers.push_back(currentPart->getNumber()); currentPart = currentPart->getParent(); } numbers.erase(numbers.end() - 1); - for (std::vector ::reverse_iterator it = numbers.rbegin() ; it != numbers.rend() ; ++it) - { + for (std::vector ::reverse_iterator it = numbers.rbegin() ; it != numbers.rend() ; ++it) { if (it != numbers.rbegin()) section << "."; section << (*it + 1); } @@ -327,53 +363,57 @@ size_t IMAPMessage::extractImpl bodyDesc << "BODY"; - if (extractFlags & EXTRACT_PEEK) + if (extractFlags & EXTRACT_PEEK) { bodyDesc << ".PEEK"; + } bodyDesc << "["; - if (section.str().empty()) - { + if (section.str().empty()) { + // header + body - if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) + if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) { bodyDesc << ""; // body only - else if (extractFlags & EXTRACT_BODY) + } else if (extractFlags & EXTRACT_BODY) { bodyDesc << "TEXT"; // header only - else if (extractFlags & EXTRACT_HEADER) + } else if (extractFlags & EXTRACT_HEADER) { bodyDesc << "HEADER"; - } - else - { + } + + } else { + bodyDesc << section.str(); // header + body - if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) - { + if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) { + // First, extract header std::ostringstream header; utility::outputStreamAdapter headerStream(header); - const size_t headerLength = extractImpl - (p, headerStream, /* progress */ NULL, - /* start */ 0, /* length */ -1, extractFlags & ~EXTRACT_BODY); + const size_t headerLength = extractImpl( + p, headerStream, /* progress */ NULL, + /* start */ 0, /* length */ -1, extractFlags & ~EXTRACT_BODY + ); size_t s = start; size_t l = length; - if (s < headerLength) - { - if (l == static_cast (-1)) - { + if (s < headerLength) { + + if (l == static_cast (-1)) { + os.write(header.str().data() + s, headerLength - s); - } - else - { + + } else { + size_t headerCopyLength = l; - if (start + headerCopyLength > headerLength) + if (start + headerCopyLength > headerLength) { headerCopyLength = headerLength - start; + } os.write(header.str().data() + s, headerCopyLength); @@ -381,30 +421,31 @@ size_t IMAPMessage::extractImpl } s = 0; - } - else - { + + } else { + s -= headerLength; } // Then, extract body return extractImpl(p, os, progress, s, l, extractFlags & ~EXTRACT_HEADER); - } + // header only - else if (extractFlags & EXTRACT_HEADER) - { + } else if (extractFlags & EXTRACT_HEADER) { + bodyDesc << ".MIME"; // "MIME" not "HEADER" for parts } } bodyDesc << "]"; - if (start != 0 || length != static_cast (-1)) - { - if (length == static_cast (-1)) + if (start != 0 || length != static_cast (-1)) { + + if (length == static_cast (-1)) { bodyDesc << "<" << start << "." << static_cast (-1) << ">"; - else + } else { bodyDesc << "<" << start << "." << length << ">"; + } } std::vector fetchParams; @@ -417,19 +458,16 @@ size_t IMAPMessage::extractImpl )->send(folder->m_connection); // Get the response - scoped_ptr resp - (folder->m_connection->readResponse(&literalHandler)); + scoped_ptr resp(folder->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", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("FETCH", resp->getErrorLog(), "bad response"); } - if (extractFlags & EXTRACT_BODY) - { + if (extractFlags & EXTRACT_BODY) { // TODO: update the flags (eg. flag "\Seen" may have been set) } @@ -437,9 +475,11 @@ size_t IMAPMessage::extractImpl } -int IMAPMessage::processFetchResponse - (const fetchAttributes& options, const IMAPParser::message_data* msgData) -{ +int IMAPMessage::processFetchResponse( + const fetchAttributes& options, + const IMAPParser::message_data* msgData +) { + shared_ptr folder = m_folder.lock(); // Get message attributes @@ -447,138 +487,142 @@ int IMAPMessage::processFetchResponse int changes = 0; for (std::vector ::const_iterator - it = atts.begin() ; it != atts.end() ; ++it) - { - switch ((*it)->type()) - { - case IMAPParser::msg_att_item::FLAGS: - { - int flags = IMAPUtils::messageFlagsFromFlags((*it)->flag_list()); + it = atts.begin() ; it != atts.end() ; ++it) { - if (m_flags != flags) - { - m_flags = flags; - changes |= events::messageChangedEvent::TYPE_FLAGS; + switch ((*it)->type()) { + + case IMAPParser::msg_att_item::FLAGS: { + + int flags = IMAPUtils::messageFlagsFromFlags((*it)->flag_list()); + + if (m_flags != flags) { + m_flags = flags; + changes |= events::messageChangedEvent::TYPE_FLAGS; + } + + break; } + case IMAPParser::msg_att_item::UID: { - break; - } - case IMAPParser::msg_att_item::UID: - { - m_uid = (*it)->unique_id()->value(); - break; - } - case IMAPParser::msg_att_item::MODSEQ: - { - m_modseq = (*it)->mod_sequence_value()->value(); - break; - } - case IMAPParser::msg_att_item::ENVELOPE: - { - if (!options.has(fetchAttributes::FULL_HEADER)) - { - const IMAPParser::envelope* env = (*it)->envelope(); - shared_ptr hdr = getOrCreateHeader(); - - // Date - hdr->Date()->setValue(env->env_date()->value()); - - // Subject - text subject; - text::decodeAndUnfold(env->env_subject()->value(), &subject); - - hdr->Subject()->setValue(subject); - - // From - mailboxList from; - IMAPUtils::convertAddressList(*(env->env_from()), from); - - if (!from.isEmpty()) - hdr->From()->setValue(*(from.getMailboxAt(0))); - - // To - mailboxList to; - IMAPUtils::convertAddressList(*(env->env_to()), to); - - hdr->To()->setValue(to.toAddressList()); - - // Sender - mailboxList sender; - IMAPUtils::convertAddressList(*(env->env_sender()), sender); - - if (!sender.isEmpty()) - hdr->Sender()->setValue(*(sender.getMailboxAt(0))); - - // Reply-to - mailboxList replyTo; - IMAPUtils::convertAddressList(*(env->env_reply_to()), replyTo); - - if (!replyTo.isEmpty()) - hdr->ReplyTo()->setValue(*(replyTo.getMailboxAt(0))); - - // Cc - mailboxList cc; - IMAPUtils::convertAddressList(*(env->env_cc()), cc); - - if (!cc.isEmpty()) - hdr->Cc()->setValue(cc.toAddressList()); - - // Bcc - mailboxList bcc; - IMAPUtils::convertAddressList(*(env->env_bcc()), bcc); - - if (!bcc.isEmpty()) - hdr->Bcc()->setValue(bcc.toAddressList()); + m_uid = (*it)->unique_id()->value(); + break; } + case IMAPParser::msg_att_item::MODSEQ: { - break; - } - case IMAPParser::msg_att_item::BODY_STRUCTURE: - { - m_structure = make_shared ((*it)->body()); - break; - } - case IMAPParser::msg_att_item::RFC822_HEADER: - { - getOrCreateHeader()->parse((*it)->nstring()->value()); - break; - } - case IMAPParser::msg_att_item::RFC822_SIZE: - { - m_size = static_cast ((*it)->number()->value()); - break; - } - case IMAPParser::msg_att_item::BODY_SECTION: - { - if (!options.has(fetchAttributes::FULL_HEADER)) - { - if ((*it)->section()->section_text1() && - (*it)->section()->section_text1()->type() - == IMAPParser::section_text::HEADER_FIELDS) - { - header tempHeader; - tempHeader.parse((*it)->nstring()->value()); + m_modseq = (*it)->mod_sequence_value()->value(); + break; + } + case IMAPParser::msg_att_item::ENVELOPE: { - vmime::header& hdr = *getOrCreateHeader(); - std::vector > fields = tempHeader.getFieldList(); + if (!options.has(fetchAttributes::FULL_HEADER)) { - for (std::vector >::const_iterator jt = fields.begin() ; - jt != fields.end() ; ++jt) - { - hdr.appendField(vmime::clone(*jt)); + const IMAPParser::envelope* env = (*it)->envelope(); + shared_ptr hdr = getOrCreateHeader(); + + // Date + hdr->Date()->setValue(env->env_date()->value()); + + // Subject + text subject; + text::decodeAndUnfold(env->env_subject()->value(), &subject); + + hdr->Subject()->setValue(subject); + + // From + mailboxList from; + IMAPUtils::convertAddressList(*(env->env_from()), from); + + if (!from.isEmpty()) { + hdr->From()->setValue(*(from.getMailboxAt(0))); + } + + // To + mailboxList to; + IMAPUtils::convertAddressList(*(env->env_to()), to); + + hdr->To()->setValue(to.toAddressList()); + + // Sender + mailboxList sender; + IMAPUtils::convertAddressList(*(env->env_sender()), sender); + + if (!sender.isEmpty()) { + hdr->Sender()->setValue(*(sender.getMailboxAt(0))); + } + + // Reply-to + mailboxList replyTo; + IMAPUtils::convertAddressList(*(env->env_reply_to()), replyTo); + + if (!replyTo.isEmpty()) { + hdr->ReplyTo()->setValue(*(replyTo.getMailboxAt(0))); + } + + // Cc + mailboxList cc; + IMAPUtils::convertAddressList(*(env->env_cc()), cc); + + if (!cc.isEmpty()) { + hdr->Cc()->setValue(cc.toAddressList()); + } + + // Bcc + mailboxList bcc; + IMAPUtils::convertAddressList(*(env->env_bcc()), bcc); + + if (!bcc.isEmpty()) { + hdr->Bcc()->setValue(bcc.toAddressList()); } } - } - break; - } - case IMAPParser::msg_att_item::INTERNALDATE: - case IMAPParser::msg_att_item::RFC822: - case IMAPParser::msg_att_item::RFC822_TEXT: - case IMAPParser::msg_att_item::BODY: - { - break; - } + break; + } + case IMAPParser::msg_att_item::BODY_STRUCTURE: { + + m_structure = make_shared ((*it)->body()); + break; + } + case IMAPParser::msg_att_item::RFC822_HEADER: { + + getOrCreateHeader()->parse((*it)->nstring()->value()); + break; + } + case IMAPParser::msg_att_item::RFC822_SIZE: { + + m_size = static_cast ((*it)->number()->value()); + break; + } + case IMAPParser::msg_att_item::BODY_SECTION: { + + if (!options.has(fetchAttributes::FULL_HEADER)) { + + if ((*it)->section()->section_text1() && + (*it)->section()->section_text1()->type() + == IMAPParser::section_text::HEADER_FIELDS) { + + header tempHeader; + tempHeader.parse((*it)->nstring()->value()); + + vmime::header& hdr = *getOrCreateHeader(); + std::vector > fields = tempHeader.getFieldList(); + + for (std::vector >::const_iterator jt = fields.begin() ; + jt != fields.end() ; ++jt) { + + hdr.appendField(vmime::clone(*jt)); + } + } + } + + break; + } + case IMAPParser::msg_att_item::INTERNALDATE: + case IMAPParser::msg_att_item::RFC822: + case IMAPParser::msg_att_item::RFC822_TEXT: + case IMAPParser::msg_att_item::BODY: { + + break; + } } } @@ -587,34 +631,40 @@ int IMAPMessage::processFetchResponse } -shared_ptr
IMAPMessage::getOrCreateHeader() -{ - if (m_header != NULL) - return (m_header); - else - return (m_header = make_shared
()); +shared_ptr
IMAPMessage::getOrCreateHeader() { + + if (m_header != NULL) { + return m_header; + } else { + return m_header = make_shared
(); + } } -void IMAPMessage::setFlags(const int flags, const int mode) -{ +void IMAPMessage::setFlags(const int flags, const int mode) { + shared_ptr folder = m_folder.lock(); - if (!folder) + if (!folder) { throw exceptions::folder_not_found(); + } - if (!m_uid.empty()) + if (!m_uid.empty()) { folder->setMessageFlags(messageSet::byUID(m_uid), flags, mode); - else + } else { folder->setMessageFlags(messageSet::byNumber(m_num), flags, mode); + } } -void IMAPMessage::constructParsedMessage - (const shared_ptr & parentPart, const shared_ptr & str, int level) -{ - if (level == 0) - { +void IMAPMessage::constructParsedMessage( + const shared_ptr & parentPart, + const shared_ptr & str, + int level +) { + + if (level == 0) { + shared_ptr part = str->getPartAt(0); // Copy header @@ -622,17 +672,19 @@ void IMAPMessage::constructParsedMessage parentPart->getHeader()->copyFrom(*hdr); // Initialize body - parentPart->getBody()->setContents - (make_shared - (dynamicCast (shared_from_this()), - part, parentPart->getBody()->getEncoding())); + parentPart->getBody()->setContents( + make_shared ( + dynamicCast (shared_from_this()), + part, parentPart->getBody()->getEncoding() + ) + ); constructParsedMessage(parentPart, part->getStructure(), 1); - } - else - { - for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) - { + + } else { + + for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) { + shared_ptr part = str->getPartAt(i); shared_ptr childPart = make_shared (); @@ -642,10 +694,12 @@ void IMAPMessage::constructParsedMessage childPart->getHeader()->copyFrom(*hdr); // Initialize body - childPart->getBody()->setContents - (make_shared - (dynamicCast (shared_from_this()), - part, childPart->getBody()->getEncoding())); + childPart->getBody()->setContents( + make_shared ( + dynamicCast (shared_from_this()), + part, childPart->getBody()->getEncoding() + ) + ); // Add child part parentPart->getBody()->appendPart(childPart); @@ -657,22 +711,23 @@ void IMAPMessage::constructParsedMessage } -shared_ptr IMAPMessage::getParsedMessage() -{ +shared_ptr IMAPMessage::getParsedMessage() { + // Fetch structure shared_ptr structure; - try - { + try { + structure = getStructure(); - } - catch (exceptions::unfetched_object&) - { + + } catch (exceptions::unfetched_object&) { + std::vector > msgs; msgs.push_back(dynamicCast (shared_from_this())); - m_folder.lock()->fetchMessages - (msgs, fetchAttributes(fetchAttributes::STRUCTURE), /* progress */ NULL); + m_folder.lock()->fetchMessages( + msgs, fetchAttributes(fetchAttributes::STRUCTURE), /* progress */ NULL + ); structure = getStructure(); } @@ -689,14 +744,14 @@ shared_ptr IMAPMessage::getParsedMessage() } -void IMAPMessage::renumber(const size_t number) -{ +void IMAPMessage::renumber(const size_t number) { + m_num = number; } -void IMAPMessage::setExpunged() -{ +void IMAPMessage::setExpunged() { + m_expunged = true; } diff --git a/src/vmime/net/imap/IMAPMessage.hpp b/src/vmime/net/imap/IMAPMessage.hpp index 48722127..60875e8c 100644 --- a/src/vmime/net/imap/IMAPMessage.hpp +++ b/src/vmime/net/imap/IMAPMessage.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -47,9 +47,8 @@ class IMAPFolder; /** IMAP message implementation. */ +class VMIME_EXPORT IMAPMessage : public message { -class VMIME_EXPORT IMAPMessage : public message -{ private: friend class IMAPFolder; @@ -92,18 +91,22 @@ public: int getFlags() const; void setFlags(const int flags, const int mode = FLAG_MODE_SET); - void extract - (utility::outputStream& os, - utility::progressListener* progress = NULL, - const size_t start = 0, const size_t length = -1, - const bool peek = false) const; + void extract( + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; - void extractPart - (const shared_ptr & p, - utility::outputStream& os, - utility::progressListener* progress = NULL, - const size_t start = 0, const size_t length = -1, - const bool peek = false) const; + void extractPart( + const shared_ptr & p, + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; void fetchPartHeader(const shared_ptr & p); @@ -144,7 +147,11 @@ private: * @param str structure for which to construct part * @param level current nesting level (0 is root) */ - void constructParsedMessage(const shared_ptr & parentPart, const shared_ptr & str, int level = 0); + void constructParsedMessage( + const shared_ptr & parentPart, + const shared_ptr & str, + int level = 0 + ); enum ExtractFlags @@ -154,12 +161,14 @@ private: EXTRACT_PEEK = 0x10 }; - size_t extractImpl - (const shared_ptr & p, - utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const int extractFlags) const; + size_t extractImpl( + const shared_ptr & p, + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const int extractFlags + ) const; shared_ptr
getOrCreateHeader(); diff --git a/src/vmime/net/imap/IMAPMessagePart.cpp b/src/vmime/net/imap/IMAPMessagePart.cpp index 6f3e7167..b76457fb 100644 --- a/src/vmime/net/imap/IMAPMessagePart.cpp +++ b/src/vmime/net/imap/IMAPMessagePart.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,129 +36,159 @@ namespace net { namespace imap { -IMAPMessagePart::IMAPMessagePart(const shared_ptr & parent, const size_t number, const IMAPParser::body_type_mpart* mpart) - : m_parent(parent), m_header(null), m_number(number), m_size(0) -{ - m_mediaType = vmime::mediaType - ("multipart", mpart->media_subtype()->value()); +IMAPMessagePart::IMAPMessagePart( + const shared_ptr & parent, + const size_t number, + const IMAPParser::body_type_mpart* mpart +) + : m_parent(parent), + m_header(null), + m_number(number), + m_size(0) { + + m_mediaType = vmime::mediaType( + "multipart", + mpart->media_subtype()->value() + ); } -IMAPMessagePart::IMAPMessagePart(const shared_ptr & parent, const size_t number, const IMAPParser::body_type_1part* part) - : m_parent(parent), m_header(null), m_number(number), m_size(0) -{ - if (part->body_type_text()) - { - m_mediaType = vmime::mediaType - ("text", part->body_type_text()-> - media_text()->media_subtype()->value()); +IMAPMessagePart::IMAPMessagePart( + const shared_ptr & parent, + const size_t number, + const IMAPParser::body_type_1part* part +) + : m_parent(parent), + m_header(null), + m_number(number), + m_size(0) { + + if (part->body_type_text()) { + + m_mediaType = vmime::mediaType( + "text", + part->body_type_text()->media_text()->media_subtype()->value() + ); m_size = part->body_type_text()->body_fields()->body_fld_octets()->value(); - } - else if (part->body_type_msg()) - { - m_mediaType = vmime::mediaType - ("message", part->body_type_msg()-> - media_message()->media_subtype()->value()); - } - else - { - m_mediaType = vmime::mediaType - (part->body_type_basic()->media_basic()->media_type()->value(), - part->body_type_basic()->media_basic()->media_subtype()->value()); + + } else if (part->body_type_msg()) { + + m_mediaType = vmime::mediaType( + "message", + part->body_type_msg()->media_message()->media_subtype()->value() + ); + + } else { + + m_mediaType = vmime::mediaType( + part->body_type_basic()->media_basic()->media_type()->value(), + part->body_type_basic()->media_basic()->media_subtype()->value() + ); m_size = part->body_type_basic()->body_fields()->body_fld_octets()->value(); - if (const auto pparam = part->body_type_basic()->body_fields()->body_fld_param()) - for (const auto& param : pparam->items()) - if (param->string1()->value() == "NAME") + if (const auto pparam = part->body_type_basic()->body_fields()->body_fld_param()) { + for (const auto& param : pparam->items()) { + if (param->string1()->value() == "NAME") { m_name = param->string2()->value(); + } + } + } } m_structure = null; } -shared_ptr IMAPMessagePart::getStructure() const -{ - if (m_structure != NULL) +shared_ptr IMAPMessagePart::getStructure() const { + + if (m_structure) { return m_structure; - else + } else { return IMAPMessageStructure::emptyStructure(); + } } -shared_ptr IMAPMessagePart::getStructure() -{ - if (m_structure != NULL) +shared_ptr IMAPMessagePart::getStructure() { + + if (m_structure) { return m_structure; - else + } else { return IMAPMessageStructure::emptyStructure(); + } } -shared_ptr IMAPMessagePart::getParent() const -{ +shared_ptr IMAPMessagePart::getParent() const { + return m_parent.lock(); } -const mediaType& IMAPMessagePart::getType() const -{ +const mediaType& IMAPMessagePart::getType() const { + return m_mediaType; } -size_t IMAPMessagePart::getSize() const -{ +size_t IMAPMessagePart::getSize() const { + return m_size; } -size_t IMAPMessagePart::getNumber() const -{ +size_t IMAPMessagePart::getNumber() const { + return m_number; } -string IMAPMessagePart::getName() const -{ + +string IMAPMessagePart::getName() const { + return m_name; } -shared_ptr IMAPMessagePart::getHeader() const -{ - if (m_header == NULL) +shared_ptr IMAPMessagePart::getHeader() const { + + if (!m_header) { throw exceptions::unfetched_object(); - else + } else { return m_header; + } } // static -shared_ptr IMAPMessagePart::create - (const shared_ptr & parent, const size_t number, const IMAPParser::body* body) -{ - if (body->body_type_mpart()) - { +shared_ptr IMAPMessagePart::create( + const shared_ptr & parent, + const size_t number, + const IMAPParser::body* body +) { + + if (body->body_type_mpart()) { + shared_ptr part = make_shared (parent, number, body->body_type_mpart()); part->m_structure = make_shared (part, body->body_type_mpart()->list()); return part; - } - else - { + + } else { + return make_shared (parent, number, body->body_type_1part()); } } -header& IMAPMessagePart::getOrCreateHeader() -{ - if (m_header != NULL) +header& IMAPMessagePart::getOrCreateHeader() { + + if (m_header) { return *m_header; - else + } else { return *(m_header = make_shared
()); + } } diff --git a/src/vmime/net/imap/IMAPMessagePart.hpp b/src/vmime/net/imap/IMAPMessagePart.hpp index d095c12f..4a636dd8 100644 --- a/src/vmime/net/imap/IMAPMessagePart.hpp +++ b/src/vmime/net/imap/IMAPMessagePart.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,12 +44,21 @@ namespace imap { class IMAPMessageStructure; -class VMIME_EXPORT IMAPMessagePart : public messagePart -{ +class VMIME_EXPORT IMAPMessagePart : public messagePart { + public: - IMAPMessagePart(const shared_ptr & parent, const size_t number, const IMAPParser::body_type_mpart* mpart); - IMAPMessagePart(const shared_ptr & parent, const size_t number, const IMAPParser::body_type_1part* part); + IMAPMessagePart( + const shared_ptr & parent, + const size_t number, + const IMAPParser::body_type_mpart* mpart + ); + + IMAPMessagePart( + const shared_ptr & parent, + const size_t number, + const IMAPParser::body_type_1part* part + ); shared_ptr getStructure() const; shared_ptr getStructure(); @@ -64,8 +73,11 @@ public: shared_ptr getHeader() const; - static shared_ptr create - (const shared_ptr & parent, const size_t number, const IMAPParser::body* body); + static shared_ptr create( + const shared_ptr & parent, + const size_t number, + const IMAPParser::body* body + ); header& getOrCreateHeader(); diff --git a/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp b/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp index 0917d0f7..d9cc07d9 100644 --- a/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp +++ b/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,35 +42,44 @@ namespace net { namespace imap { -IMAPMessagePartContentHandler::IMAPMessagePartContentHandler - (const shared_ptr & msg, const shared_ptr & part, const vmime::encoding& encoding) - : m_message(msg), m_part(part), m_encoding(encoding) -{ +IMAPMessagePartContentHandler::IMAPMessagePartContentHandler( + const shared_ptr & msg, + const shared_ptr & part, + const vmime::encoding& encoding +) + : m_message(msg), + m_part(part), + m_encoding(encoding) { + } -shared_ptr IMAPMessagePartContentHandler::clone() const -{ - return make_shared - (m_message.lock(), m_part.lock(), m_encoding); +shared_ptr IMAPMessagePartContentHandler::clone() const { + + return make_shared ( + m_message.lock(), m_part.lock(), m_encoding + ); } -void IMAPMessagePartContentHandler::generate - (utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength) const -{ +void IMAPMessagePartContentHandler::generate( + utility::outputStream& os, + const vmime::encoding& enc, + const size_t maxLineLength +) const { + shared_ptr msg = m_message.lock(); shared_ptr part = m_part.lock(); // Data is already encoded - if (isEncoded()) - { + if (isEncoded()) { + // The data is already encoded but the encoding specified for // the generation is different from the current one. We need // to re-encode data: decode from input buffer to temporary // buffer, and then re-encode to output stream... - if (m_encoding != enc) - { + if (m_encoding != enc) { + // Extract part contents to temporary buffer std::ostringstream oss; utility::outputStreamAdapter tmp(oss); @@ -95,16 +104,16 @@ void IMAPMessagePartContentHandler::generate theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT); theEncoder->encode(tempIn, os); - } + // No encoding to perform - else - { + } else { + msg->extractPart(part, os); } - } + // Need to encode data before - else - { + } else { + // Extract part contents to temporary buffer std::ostringstream oss; utility::outputStreamAdapter tmp(oss); @@ -123,20 +132,22 @@ void IMAPMessagePartContentHandler::generate } -void IMAPMessagePartContentHandler::extract - (utility::outputStream& os, utility::progressListener* progress) const -{ +void IMAPMessagePartContentHandler::extract( + utility::outputStream& os, + utility::progressListener* progress +) const { + shared_ptr msg = m_message.lock(); shared_ptr part = m_part.lock(); // No decoding to perform - if (!isEncoded()) - { + if (!isEncoded()) { + msg->extractImpl(part, os, progress, 0, -1, IMAPMessage::EXTRACT_BODY); - } + // Need to decode data - else - { + } else { + // Extract part contents to temporary buffer std::ostringstream oss; utility::outputStreamAdapter tmp(oss); @@ -153,9 +164,11 @@ void IMAPMessagePartContentHandler::extract } -void IMAPMessagePartContentHandler::extractRaw - (utility::outputStream& os, utility::progressListener* progress) const -{ +void IMAPMessagePartContentHandler::extractRaw( + utility::outputStream& os, + utility::progressListener* progress +) const { + shared_ptr msg = m_message.lock(); shared_ptr part = m_part.lock(); @@ -163,44 +176,44 @@ void IMAPMessagePartContentHandler::extractRaw } -size_t IMAPMessagePartContentHandler::getLength() const -{ +size_t IMAPMessagePartContentHandler::getLength() const { + return m_part.lock()->getSize(); } -bool IMAPMessagePartContentHandler::isEncoded() const -{ +bool IMAPMessagePartContentHandler::isEncoded() const { + return m_encoding != NO_ENCODING; } -const vmime::encoding& IMAPMessagePartContentHandler::getEncoding() const -{ +const vmime::encoding& IMAPMessagePartContentHandler::getEncoding() const { + return m_encoding; } -bool IMAPMessagePartContentHandler::isEmpty() const -{ +bool IMAPMessagePartContentHandler::isEmpty() const { + return getLength() == 0; } -bool IMAPMessagePartContentHandler::isBuffered() const -{ +bool IMAPMessagePartContentHandler::isBuffered() const { + return true; } -void IMAPMessagePartContentHandler::setContentTypeHint(const mediaType& type) -{ +void IMAPMessagePartContentHandler::setContentTypeHint(const mediaType& type) { + m_contentType = type; } -const mediaType IMAPMessagePartContentHandler::getContentTypeHint() const -{ +const mediaType IMAPMessagePartContentHandler::getContentTypeHint() const { + return m_contentType; } diff --git a/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp b/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp index 8314fa95..17f53e34 100644 --- a/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp +++ b/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,15 +40,23 @@ namespace net { namespace imap { -class VMIME_EXPORT IMAPMessagePartContentHandler : public contentHandler -{ +class VMIME_EXPORT IMAPMessagePartContentHandler : public contentHandler { + public: - IMAPMessagePartContentHandler(const shared_ptr & msg, const shared_ptr & part, const vmime::encoding& encoding); + IMAPMessagePartContentHandler( + const shared_ptr & msg, + const shared_ptr & part, + const vmime::encoding& encoding + ); shared_ptr clone() const; - void generate(utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength = lineLengthLimits::infinite) const; + void generate( + utility::outputStream& os, + const vmime::encoding& enc, + const size_t maxLineLength = lineLengthLimits::infinite + ) const; void extract(utility::outputStream& os, utility::progressListener* progress = NULL) const; void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const; diff --git a/src/vmime/net/imap/IMAPMessageStructure.cpp b/src/vmime/net/imap/IMAPMessageStructure.cpp index 1e6c1b32..0bc7e909 100644 --- a/src/vmime/net/imap/IMAPMessageStructure.cpp +++ b/src/vmime/net/imap/IMAPMessageStructure.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,50 +36,52 @@ namespace net { namespace imap { -IMAPMessageStructure::IMAPMessageStructure() -{ +IMAPMessageStructure::IMAPMessageStructure() { } -IMAPMessageStructure::IMAPMessageStructure(const IMAPParser::body* body) -{ +IMAPMessageStructure::IMAPMessageStructure(const IMAPParser::body* body) { + m_parts.push_back(IMAPMessagePart::create(null, 0, body)); } -IMAPMessageStructure::IMAPMessageStructure(const shared_ptr & parent, const std::vector & list) -{ +IMAPMessageStructure::IMAPMessageStructure( + const shared_ptr & parent, + const std::vector & list +) { + size_t number = 0; for (std::vector ::const_iterator - it = list.begin() ; it != list.end() ; ++it, ++number) - { + it = list.begin() ; it != list.end() ; ++it, ++number) { + m_parts.push_back(IMAPMessagePart::create(parent, number, *it)); } } -shared_ptr IMAPMessageStructure::getPartAt(const size_t x) const -{ +shared_ptr IMAPMessageStructure::getPartAt(const size_t x) const { + return m_parts[x]; } -shared_ptr IMAPMessageStructure::getPartAt(const size_t x) -{ +shared_ptr IMAPMessageStructure::getPartAt(const size_t x) { + return m_parts[x]; } -size_t IMAPMessageStructure::getPartCount() const -{ +size_t IMAPMessageStructure::getPartCount() const { + return m_parts.size(); } // static -shared_ptr IMAPMessageStructure::emptyStructure() -{ +shared_ptr IMAPMessageStructure::emptyStructure() { + static shared_ptr emptyStructure = make_shared (); return emptyStructure; } diff --git a/src/vmime/net/imap/IMAPMessageStructure.hpp b/src/vmime/net/imap/IMAPMessageStructure.hpp index f24e518c..5eafb04f 100644 --- a/src/vmime/net/imap/IMAPMessageStructure.hpp +++ b/src/vmime/net/imap/IMAPMessageStructure.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,8 +44,8 @@ namespace imap { class IMAPMessagePart; -class VMIME_EXPORT IMAPMessageStructure : public messageStructure -{ +class VMIME_EXPORT IMAPMessageStructure : public messageStructure { + public: IMAPMessageStructure(); diff --git a/src/vmime/net/imap/IMAPParser.hpp b/src/vmime/net/imap/IMAPParser.hpp index 33d091cc..74b5145f 100644 --- a/src/vmime/net/imap/IMAPParser.hpp +++ b/src/vmime/net/imap/IMAPParser.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -193,25 +193,34 @@ namespace imap { static int IMAPParserDebugResponse_level = 0; static std::vector IMAPParserDebugResponse_stack; - class IMAPParserDebugResponse - { + class IMAPParserDebugResponse { + public: - IMAPParserDebugResponse(const string& name, string& line, const size_t currentPos, const bool &result) - : m_name(name), m_line(line), m_pos(currentPos), m_result(result) - { + IMAPParserDebugResponse( + const string& name, + string& line, + const size_t currentPos, + const bool &result + ) + : m_name(name), + m_line(line), + m_pos(currentPos), + m_result(result) { + ++IMAPParserDebugResponse_level; IMAPParserDebugResponse_stack.push_back(name); - for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i) + for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i) { std::cout << " "; + } std::cout << "ENTER(" << m_name << "), pos=" << m_pos; std::cout << std::endl; for (std::vector ::iterator it = IMAPParserDebugResponse_stack.begin() ; - it != IMAPParserDebugResponse_stack.end() ; ++it) - { + it != IMAPParserDebugResponse_stack.end() ; ++it) { + std::cout << "> " << *it << " "; } @@ -219,16 +228,18 @@ namespace imap { std::cout << string(m_line.begin() + (m_pos < 30 ? 0U : m_pos - 30), m_line.begin() + std::min(m_line.length(), m_pos + 30)) << std::endl; - for (size_t i = (m_pos < 30 ? m_pos : (m_pos - (m_pos - 30))) ; i != 0 ; --i) + for (size_t i = (m_pos < 30 ? m_pos : (m_pos - (m_pos - 30))) ; i != 0 ; --i) { std::cout << " "; + } std::cout << "^" << std::endl; } - ~IMAPParserDebugResponse() - { - for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i) + ~IMAPParserDebugResponse() { + + for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i) { std::cout << " "; + } std::cout << "LEAVE(" << m_name << "), result="; std::cout << (m_result ? "TRUE" : "FALSE") << ", pos=" << m_pos; @@ -258,14 +269,18 @@ namespace imap { #endif -class VMIME_EXPORT IMAPParser : public object -{ +class VMIME_EXPORT IMAPParser : public object { + public: IMAPParser() - : m_tag(), m_socket(), m_progress(NULL), m_strict(false), - m_literalHandler(NULL), m_timeoutHandler() - { + : m_tag(), + m_socket(), + m_progress(NULL), + m_strict(false), + m_literalHandler(NULL), + m_timeoutHandler() { + } @@ -273,8 +288,8 @@ public: * * @param tag IMAP command tag */ - void setTag(const shared_ptr & tag) - { + void setTag(const shared_ptr & tag) { + m_tag = tag; } @@ -282,8 +297,8 @@ public: * * @return IMAP command tag */ - shared_ptr getTag() const - { + shared_ptr getTag() const { + return m_tag.lock(); } @@ -292,8 +307,8 @@ public: * * @param sok socket */ - void setSocket(const shared_ptr & sok) - { + void setSocket(const shared_ptr & sok) { + m_socket = sok; } @@ -301,8 +316,8 @@ public: * * @param toh timeout handler */ - void setTimeoutHandler(const shared_ptr & toh) - { + void setTimeoutHandler(const shared_ptr & toh) { + m_timeoutHandler = toh; } @@ -310,8 +325,8 @@ public: * * @param tr tracer */ - void setTracer(const shared_ptr & tr) - { + void setTracer(const shared_ptr & tr) { + m_tracer = tr; } @@ -321,8 +336,8 @@ public: * @param strict true to operate in strict mode, or false * to operate in default, relaxed mode */ - void setStrict(const bool strict) - { + void setStrict(const bool strict) { + m_strict = strict; } @@ -331,8 +346,8 @@ public: * * @return true if we are in strict mode, false otherwise */ - bool isStrict() const - { + bool isStrict() const { + return m_strict; } @@ -344,16 +359,16 @@ public: class component; - class literalHandler - { + class literalHandler { + public: virtual ~literalHandler() { } // Abstract target class - class target - { + class target { + protected: target(utility::progressListener* progress) : m_progress(progress) {} @@ -377,8 +392,8 @@ public: // Target: put in a string - class targetString : public target - { + class targetString : public target { + public: targetString(utility::progressListener* progress, vmime::string& str) @@ -388,14 +403,14 @@ public: vmime::string& string() { return (m_string); } - void putData(const vmime::string& chunk) - { + void putData(const vmime::string& chunk) { + m_string += chunk; m_bytesWritten += chunk.length(); } - size_t getBytesWritten() const - { + size_t getBytesWritten() const { + return m_bytesWritten; } @@ -407,25 +422,32 @@ public: // Target: redirect to an output stream - class targetStream : public target - { + class targetStream : public target { + public: - targetStream(utility::progressListener* progress, utility::outputStream& stream) - : target(progress), m_stream(stream), m_bytesWritten(0) { } + targetStream( + utility::progressListener* progress, + utility::outputStream& stream + ) + : target(progress), + m_stream(stream), + m_bytesWritten(0) { + + } const utility::outputStream& stream() const { return (m_stream); } utility::outputStream& stream() { return (m_stream); } - void putData(const string& chunk) - { + void putData(const string& chunk) { + m_stream.write(chunk.data(), chunk.length()); m_bytesWritten += chunk.length(); } - size_t getBytesWritten() const - { + size_t getBytesWritten() const { + return m_bytesWritten; } @@ -452,8 +474,8 @@ public: // Base class for a terminal or a non-terminal // - class component - { + class component { + public: component() { } @@ -461,8 +483,8 @@ public: virtual const string getComponentName() const = 0; - bool parse(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parse(IMAPParser& parser, string& line, size_t* currentPos) { + bool res = false; DEBUG_ENTER_COMPONENT(getComponentName(), res); res = parseImpl(parser, line, currentPos); @@ -472,12 +494,16 @@ public: virtual bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) = 0; - const string makeResponseLine(const string& comp, const string& line, - const size_t pos) - { + const string makeResponseLine( + const string& comp, + const string& line, + const size_t pos + ) { + #if DEBUG_RESPONSE - if (pos > line.length()) + if (pos > line.length()) { std::cout << "WARNING: component::makeResponseLine(): pos > line.length()" << std::endl; + } #endif string result(line.substr(0, pos)); @@ -491,19 +517,16 @@ public: #define COMPONENT_ALIAS(parent, name) \ - class name : public parent \ - { \ + class name : public parent { \ virtual const string getComponentName() const { return #name; } \ public: \ - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) \ - { \ + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { \ return parent::parseImpl(parser, line, currentPos); \ } \ } #define DECLARE_COMPONENT(name) \ - class name : public component \ - { \ + class name : public component { \ virtual const string getComponentName() const { return #name; } \ public: @@ -513,26 +536,23 @@ public: // template - class one_char : public component - { + class one_char : public component { + public: - const string getComponentName() const - { + const string getComponentName() const { + return string("one_char <") + C + ">"; } - bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) { + const size_t pos = *currentPos; - if (pos < line.length() && line[pos] == C) - { + if (pos < line.length() && line[pos] == C) { *currentPos = pos + 1; return true; - } - else - { + } else { return false; } } @@ -545,20 +565,18 @@ public: DECLARE_COMPONENT(SPACE) - bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) { + size_t pos = *currentPos; - while (pos < line.length() && (line[pos] == ' ' || line[pos] == '\t')) + while (pos < line.length() && (line[pos] == ' ' || line[pos] == '\t')) { ++pos; + } - if (pos > *currentPos) - { + if (pos > *currentPos) { *currentPos = pos; return true; - } - else - { + } else { return false; } } @@ -573,20 +591,20 @@ public: DECLARE_COMPONENT(CRLF) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_TRY_CHECK(SPACE); if (pos + 1 < line.length() && - line[pos] == 0x0d && line[pos + 1] == 0x0a) - { + line[pos] == 0x0d && line[pos + 1] == 0x0a) { + *currentPos = pos + 2; return true; - } - else - { + + } else { + return false; } } @@ -607,8 +625,8 @@ public: DECLARE_COMPONENT(xtag) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; bool end = false; @@ -616,46 +634,42 @@ public: string tagString; tagString.reserve(10); - while (!end && pos < line.length()) - { + while (!end && pos < line.length()) { + const unsigned char c = line[pos]; - switch (c) - { - case '+': - case '(': - case ')': - case '{': - case 0x20: // SPACE - case '%': // list_wildcards - case '*': // list_wildcards - case '"': // quoted_specials - case '\\': // quoted_specials + switch (c) { - end = true; - break; + case '+': + case '(': + case ')': + case '{': + case 0x20: // SPACE + case '%': // list_wildcards + case '*': // list_wildcards + case '"': // quoted_specials + case '\\': // quoted_specials - default: - - if (c <= 0x1f || c >= 0x7f) end = true; - else - { - tagString += c; - ++pos; - } + break; - break; + default: + + if (c <= 0x1f || c >= 0x7f) { + end = true; + } else { + tagString += c; + ++pos; + } + + break; } } - if (tagString == string(*parser.getTag())) - { + if (tagString == string(*parser.getTag())) { *currentPos = pos; return true; - } - else - { + } else { // Invalid tag return false; } @@ -675,41 +689,36 @@ public: DECLARE_COMPONENT(number) number(const bool nonZero = false) - : m_nonZero(nonZero), m_value(0) - { + : m_nonZero(nonZero), + m_value(0) { + } - bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) { + size_t pos = *currentPos; bool valid = true; unsigned int val = 0; - while (valid && pos < line.length()) - { + while (valid && pos < line.length()) { + const char c = line[pos]; - if (c >= '0' && c <= '9') - { + if (c >= '0' && c <= '9') { val = (val * 10) + (c - '0'); ++pos; - } - else - { + } else { valid = false; } } // Check for non-null length (and for non-zero number) - if (!(m_nonZero && val == 0) && pos != *currentPos) - { + if (!(m_nonZero && val == 0) && pos != *currentPos) { m_value = val; *currentPos = pos; return true; - } - else - { + } else { return false; } } @@ -730,12 +739,13 @@ public: // ;; (0 < n < 4,294,967,296) // - class nz_number : public number - { + class nz_number : public number { + public: - nz_number() : number(true) - { + nz_number() + : number(true) { + } }; @@ -745,12 +755,13 @@ public: // ;; Strictly ascending // - class uniqueid : public nz_number - { + class uniqueid : public nz_number { + public: - uniqueid() : nz_number() - { + uniqueid() + : nz_number() { + } }; @@ -763,18 +774,19 @@ public: DECLARE_COMPONENT(uid_range) uid_range() - : m_uniqueid1(NULL), m_uniqueid2(NULL) - { + : m_uniqueid1(NULL), + m_uniqueid2(NULL) { + } - ~uid_range() - { + ~uid_range() { + delete m_uniqueid1; delete m_uniqueid2; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(uniqueid, m_uniqueid1); @@ -805,28 +817,32 @@ public: DECLARE_COMPONENT(uid_set) uid_set() - : m_uniqueid(NULL), m_uid_range(NULL), m_next_uid_set(NULL) - { + : m_uniqueid(NULL), + m_uid_range(NULL), + m_next_uid_set(NULL) { + } - ~uid_set() - { + ~uid_set() { + delete m_uniqueid; delete m_uid_range; delete m_next_uid_set; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; // We have either a 'uid_range' or a 'uniqueid' - if (!VIMAP_PARSER_TRY_GET(IMAPParser::uid_range, m_uid_range)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::uid_range, m_uid_range)) { VIMAP_PARSER_GET(IMAPParser::uniqueid, m_uniqueid); + } // And maybe another 'uid-set' following - if (VIMAP_PARSER_TRY_CHECK(one_char <','>)) + if (VIMAP_PARSER_TRY_CHECK(one_char <','>)) { VIMAP_PARSER_GET(IMAPParser::uid_set, m_next_uid_set); + } *currentPos = pos; @@ -859,56 +875,50 @@ public: DECLARE_COMPONENT(text) text(bool allow8bits = false, const char except = 0) - : m_allow8bits(allow8bits), m_except(except) - { + : m_allow8bits(allow8bits), m_except(except) { } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; size_t len = 0; - if (m_allow8bits || !parser.isStrict()) - { + if (m_allow8bits || !parser.isStrict()) { + const unsigned char except = m_except; - for (bool end = false ; !end && pos < line.length() ; ) - { + for (bool end = false ; !end && pos < line.length() ; ) { + const unsigned char c = line[pos]; - if (c == 0x00 || c == 0x0d || c == 0x0a || c == except) - { + if (c == 0x00 || c == 0x0d || c == 0x0a || c == except) { end = true; - } - else - { + } else { ++pos; ++len; } } - } - else - { + + } else { + const unsigned char except = m_except; - for (bool end = false ; !end && pos < line.length() ; ) - { + for (bool end = false ; !end && pos < line.length() ; ) { + const unsigned char c = line[pos]; - if (c < 0x01 || c > 0x7f || c == 0x0d || c == 0x0a || c == except) - { + if (c < 0x01 || c > 0x7f || c == 0x0d || c == 0x0a || c == except) { end = true; - } - else - { + } else { ++pos; ++len; } } } - if (len == 0) + if (len == 0) { VIMAP_PARSER_FAIL(); + } m_value.resize(len); std::copy(line.begin() + *currentPos, line.begin() + pos, m_value.begin()); @@ -930,34 +940,34 @@ public: }; - class text8 : public text - { + class text8 : public text { + public: - text8() : text(true) - { + text8() : text(true) { + } }; template - class text_except : public text - { + class text_except : public text { + public: - text_except() : text(false, C) - { + text_except() : text(false, C) { + } }; template - class text8_except : public text - { + class text8_except : public text { + public: - text8_except() : text(true, C) - { + text8_except() : text(true, C) { + } }; @@ -971,27 +981,27 @@ public: DECLARE_COMPONENT(QUOTED_CHAR) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; const unsigned char c = static_cast (pos < line.length() ? line[pos] : 0); if (c >= 0x01 && c <= 0x7f && // 0x01 - 0x7f c != '"' && c != '\\' && // quoted_specials - c != '\r' && c != '\n') // CR and LF - { + c != '\r' && c != '\n') { // CR and LF + m_value = c; *currentPos = pos + 1; - } - else if (c == '\\' && pos + 1 < line.length() && - (line[pos + 1] == '"' || line[pos + 1] == '\\')) - { + + } else if (c == '\\' && pos + 1 < line.length() && + (line[pos + 1] == '"' || line[pos + 1] == '\\')) { + m_value = line[pos + 1]; *currentPos = pos + 2; - } - else - { + + } else { + VIMAP_PARSER_FAIL(); } @@ -1018,24 +1028,23 @@ public: DECLARE_COMPONENT(quoted_text) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; size_t len = 0; bool valid = false; m_value.reserve(line.length() - pos); - for (bool end = false, quoted = false ; !end && pos < line.length() ; ) - { + for (bool end = false, quoted = false ; !end && pos < line.length() ; ) { + const unsigned char c = line[pos]; - if (quoted) - { - if (c == '"' || c == '\\') + if (quoted) { + + if (c == '"' || c == '\\') { m_value += c; - else - { + } else { m_value += '\\'; m_value += c; } @@ -1044,39 +1053,40 @@ public: ++pos; ++len; - } - else - { - if (c == '\\') - { + + } else { + + if (c == '\\') { + quoted = true; ++pos; ++len; - } - else if (c == '"') - { + + } else if (c == '"') { + valid = true; end = true; - } - else if (c >= 0x01 && c <= 0x7f && // CHAR - c != 0x0a && c != 0x0d) // CR and LF - { + + } else if (c >= 0x01 && c <= 0x7f && // CHAR + c != 0x0a && c != 0x0d) { // CR and LF + m_value += c; ++pos; ++len; - } - else - { + + } else { + valid = false; end = true; } } } - if (!valid) + if (!valid) { VIMAP_PARSER_FAIL(); + } *currentPos = pos; @@ -1099,8 +1109,8 @@ public: DECLARE_COMPONENT(NIL) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK_WITHARG(special_atom, "nil"); @@ -1128,74 +1138,79 @@ public: DECLARE_COMPONENT(xstring) - xstring(const bool canBeNIL = false, component* comp = NULL, const int data = 0) - : m_canBeNIL(canBeNIL), m_isNIL(true), m_component(comp), m_data(data) - { + xstring( + const bool canBeNIL = false, + component* comp = NULL, + const int data = 0 + ) + : m_canBeNIL(canBeNIL), + m_isNIL(true), + m_component(comp), + m_data(data) { + } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; if (m_canBeNIL && - VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "nil")) - { + VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "nil")) { + // NIL m_isNIL = true; - } - else - { + + } else { + pos = *currentPos; m_isNIL = false; // quoted ::= <"> *QUOTED_CHAR <"> - if (VIMAP_PARSER_TRY_CHECK(one_char <'"'>)) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'"'>)) { + shared_ptr text; VIMAP_PARSER_GET_PTR(quoted_text, text); VIMAP_PARSER_CHECK(one_char <'"'>); - if (parser.m_literalHandler != NULL) - { + if (parser.m_literalHandler != NULL) { + shared_ptr target = parser.m_literalHandler->targetFor(*m_component, m_data); - if (target != NULL) - { + if (target != NULL) { + m_value = "[literal-handler]"; const size_t length = text->value().length(); utility::progressListener* progress = target->progressListener(); - if (progress) - { + if (progress) { progress->start(length); } target->putData(text->value()); - if (progress) - { + if (progress) { progress->progress(length, length); progress->stop(length); } - } - else - { + + } else { + m_value = text->value(); } - } - else - { + + } else { + m_value = text->value(); } DEBUG_FOUND("string[quoted]", ""); - } + // literal ::= "{" number "}" CRLF *CHAR8 - else - { + } else { + VIMAP_PARSER_CHECK(one_char <'{'>); shared_ptr num; @@ -1208,27 +1223,27 @@ public: VIMAP_PARSER_CHECK(CRLF); - if (parser.m_literalHandler != NULL) - { + if (parser.m_literalHandler != NULL) { + shared_ptr target = parser.m_literalHandler->targetFor(*m_component, m_data); - if (target != NULL) - { + if (target != NULL) { + m_value = "[literal-handler]"; parser.m_progress = target->progressListener(); parser.readLiteral(*target, length); parser.m_progress = NULL; - } - else - { + + } else { + literalHandler::targetString target(NULL, m_value); parser.readLiteral(target, length); } - } - else - { + + } else { + literalHandler::targetString target(NULL, m_value); parser.readLiteral(target, length); } @@ -1266,18 +1281,18 @@ public: // nstring ::= string / nil // - class nstring : public xstring - { + class nstring : public xstring { + public: - const string getComponentName() const - { + const string getComponentName() const { + return "nstring"; } nstring(component* comp = NULL, const int data = 0) - : xstring(true, comp, data) - { + : xstring(true, comp, data) { + } }; @@ -1288,19 +1303,16 @@ public: DECLARE_COMPONENT(astring) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; shared_ptr str; VIMAP_PARSER_TRY_GET_PTR(xstring, str); - if (str) - { + if (str) { m_value = str->value(); - } - else - { + } else { shared_ptr at; VIMAP_PARSER_GET_PTR(atom, at); m_value = at->value(); @@ -1335,53 +1347,52 @@ public: DECLARE_COMPONENT(atom) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; size_t len = 0; - for (bool end = false ; !end && pos < line.length() ; ) - { + for (bool end = false ; !end && pos < line.length() ; ) { + const unsigned char c = line[pos]; - switch (c) - { - case '(': - case ')': - case '{': - case 0x20: // SPACE - case '%': // list_wildcards - case '*': // list_wildcards - case '"': // quoted_specials - case '\\': // quoted_specials + switch (c) { - case '[': - case ']': // for "special_atom" + case '(': + case ')': + case '{': + case 0x20: // SPACE + case '%': // list_wildcards + case '*': // list_wildcards + case '"': // quoted_specials + case '\\': // quoted_specials - end = true; - break; + case '[': + case ']': // for "special_atom" - default: - - if (c <= 0x1f || c >= 0x7f) end = true; - else - { - ++pos; - ++len; + break; + + default: + + if (c <= 0x1f || c >= 0x7f) { + end = true; + } else { + ++pos; + ++len; + } } - } } - if (len != 0) - { + if (len != 0) { + m_value.resize(len); std::copy(line.begin() + *currentPos, line.begin() + pos, m_value.begin()); *currentPos = pos; - } - else - { + + } else { + VIMAP_PARSER_FAIL(); } @@ -1407,42 +1418,44 @@ public: // accept these strings in a case-insensitive fashion. " // - class special_atom : public atom - { + class special_atom : public atom { + public: - const std::string getComponentName() const - { + const std::string getComponentName() const { + return string("special_atom <") + m_string + ">"; } special_atom(const char* str) - : m_string(str) // 'string' must be in lower-case - { + : m_string(str) { // 'string' must be in lower-case + } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!atom::parseImpl(parser, line, &pos)) + if (!atom::parseImpl(parser, line, &pos)) { return false; + } const char* cmp = value().c_str(); const char* with = m_string; bool ok = true; - while (ok && *cmp && *with) - { + while (ok && *cmp && *with) { + ok = (std::tolower(*cmp, std::locale()) == *with); ++cmp; ++with; } - if (!ok || *cmp || *with) + if (!ok || *cmp || *with) { VIMAP_PARSER_FAIL(); + } *currentPos = pos; @@ -1462,8 +1475,8 @@ public: DECLARE_COMPONENT(text_mime2) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; shared_ptr theCharset, theEncoding; @@ -1490,28 +1503,28 @@ public: // Decode text scoped_ptr theEncoder; - if (theEncoding->value()[0] == 'q' || theEncoding->value()[0] == 'Q') - { + if (theEncoding->value()[0] == 'q' || theEncoding->value()[0] == 'Q') { + // Quoted-printable theEncoder.reset(new utility::encoder::qpEncoder()); theEncoder->getProperties()["rfc2047"] = true; - } - else if (theEncoding->value()[0] == 'b' || theEncoding->value()[0] == 'B') - { + + } else if (theEncoding->value()[0] == 'b' || theEncoding->value()[0] == 'B') { + // Base64 theEncoder.reset(new utility::encoder::b64Encoder()); } - if (theEncoder.get()) - { + if (theEncoder.get()) { + utility::inputStreamStringAdapter in(theText->value()); utility::outputStreamStringAdapter out(m_value); theEncoder->decode(in, out); - } + // No decoder available - else - { + } else { + m_value = theText->value(); } @@ -1540,26 +1553,27 @@ public: DECLARE_COMPONENT(seq_number) seq_number() - : m_number(NULL), m_star(false) - { + : m_number(NULL), + m_star(false) { + } - ~seq_number() - { + ~seq_number() { + delete m_number; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'*'> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'*'> )) { + m_star = true; m_number = NULL; - } - else - { + + } else { + m_star = false; VIMAP_PARSER_GET(IMAPParser::number, m_number); } @@ -1590,18 +1604,19 @@ public: DECLARE_COMPONENT(seq_range) seq_range() - : m_first(NULL), m_last(NULL) - { + : m_first(NULL), + m_last(NULL) { + } - ~seq_range() - { + ~seq_range() { + delete m_first; delete m_last; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(seq_number, m_first); @@ -1638,26 +1653,30 @@ public: DECLARE_COMPONENT(sequence_set) sequence_set() - : m_number(NULL), m_range(NULL), m_nextSet(NULL) - { + : m_number(NULL), + m_range(NULL), + m_nextSet(NULL) { + } - ~sequence_set() - { + ~sequence_set() { + delete m_number; delete m_range; delete m_nextSet; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!VIMAP_PARSER_TRY_GET(IMAPParser::seq_range, m_range)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::seq_range, m_range)) { VIMAP_PARSER_GET(IMAPParser::seq_number, m_number); + } - if (VIMAP_PARSER_TRY_CHECK(one_char <','> )) + if (VIMAP_PARSER_TRY_CHECK(one_char <','> )) { VIMAP_PARSER_GET(sequence_set, m_nextSet); + } *currentPos = pos; @@ -1686,28 +1705,25 @@ public: DECLARE_COMPONENT(mod_sequence_value) mod_sequence_value() - : m_value(0) - { + : m_value(0) { + } - bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) { + size_t pos = *currentPos; bool valid = true; vmime_uint64 val = 0; - while (valid && pos < line.length()) - { + while (valid && pos < line.length()) { + const char c = line[pos]; - if (c >= '0' && c <= '9') - { + if (c >= '0' && c <= '9') { val = (val * 10) + (c - '0'); ++pos; - } - else - { + } else { valid = false; } } @@ -1747,51 +1763,51 @@ public: DECLARE_COMPONENT(flag) flag() - : m_type(UNKNOWN), m_flag_keyword(NULL) - { + : m_type(UNKNOWN), + m_flag_keyword(NULL) { + } - ~flag() - { - delete (m_flag_keyword); + ~flag() { + + delete m_flag_keyword; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'\\'> )) - { - if (VIMAP_PARSER_TRY_CHECK(one_char <'*'> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'\\'> )) { + + if (VIMAP_PARSER_TRY_CHECK(one_char <'*'> )) { + m_type = STAR; - } - else - { + + } else { + shared_ptr at; VIMAP_PARSER_GET_PTR(atom, at); const string name = utility::stringUtils::toLower(at->value()); - if (name == "answered") + if (name == "answered") { m_type = ANSWERED; - else if (name == "flagged") + } else if (name == "flagged") { m_type = FLAGGED; - else if (name == "deleted") + } else if (name == "deleted") { m_type = DELETED; - else if (name == "seen") + } else if (name == "seen") { m_type = SEEN; - else if (name == "draft") + } else if (name == "draft") { m_type = DRAFT; - else - { + } else { m_type = UNKNOWN; m_name = name; } } - } - else - { + + } else { + m_type = KEYWORD_OR_EXTENSION; VIMAP_PARSER_GET(atom, m_flag_keyword); } @@ -1802,8 +1818,7 @@ public: } - enum Type - { + enum Type { UNKNOWN, ANSWERED, FLAGGED, @@ -1836,23 +1851,22 @@ public: DECLARE_COMPONENT(flag_list) - ~flag_list() - { + ~flag_list() { + for (std::vector ::iterator it = m_flags.begin() ; - it != m_flags.end() ; ++it) - { - delete (*it); + it != m_flags.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_GET_PUSHBACK(flag, m_flags); VIMAP_PARSER_TRY_CHECK(SPACE); } @@ -1882,17 +1896,17 @@ public: DECLARE_COMPONENT(mailbox) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "inbox")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "inbox")) { + m_type = INBOX; m_name = "INBOX"; - } - else - { + + } else { + m_type = OTHER; shared_ptr astr; @@ -1906,8 +1920,7 @@ public: } - enum Type - { + enum Type { INBOX, OTHER }; @@ -1931,109 +1944,121 @@ public: DECLARE_COMPONENT(mailbox_flag) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'\\'> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'\\'> )) { + shared_ptr at; VIMAP_PARSER_GET_PTR(atom, at); const string name = utility::stringUtils::toLower(at->value()); m_type = UNKNOWN; // default - switch (name[0]) - { - case 'a': + switch (name[0]) { - if (name == "all") - m_type = SPECIALUSE_ALL; - else if (name == "archive") - m_type = SPECIALUSE_ARCHIVE; + case 'a': - break; + if (name == "all") { + m_type = SPECIALUSE_ALL; + } else if (name == "archive") { + m_type = SPECIALUSE_ARCHIVE; + } - case 'd': + break; - if (name == "drafts") - m_type = SPECIALUSE_DRAFTS; + case 'd': - break; + if (name == "drafts") { + m_type = SPECIALUSE_DRAFTS; + } - case 'f': + break; - if (name == "flagged") - m_type = SPECIALUSE_FLAGGED; + case 'f': - break; + if (name == "flagged") { + m_type = SPECIALUSE_FLAGGED; + } - case 'h': + break; - if (name == "haschildren") - m_type = HASCHILDREN; - else if (name == "hasnochildren") - m_type = HASNOCHILDREN; + case 'h': - break; + if (name == "haschildren") { + m_type = HASCHILDREN; + } else if (name == "hasnochildren") { + m_type = HASNOCHILDREN; + } - case 'i': + break; - if (name == "important") - m_type = SPECIALUSE_IMPORTANT; + case 'i': - break; + if (name == "important") { + m_type = SPECIALUSE_IMPORTANT; + } - case 'j': + break; - if (name == "junk") - m_type = SPECIALUSE_JUNK; + case 'j': - break; + if (name == "junk") { + m_type = SPECIALUSE_JUNK; + } - case 'm': + break; - if (name == "marked") - m_type = MARKED; + case 'm': - break; + if (name == "marked") { + m_type = MARKED; + } - case 'n': + break; - if (name == "noinferiors") - m_type = NOINFERIORS; - else if (name == "noselect") - m_type = NOSELECT; + case 'n': - break; + if (name == "noinferiors") { + m_type = NOINFERIORS; + } else if (name == "noselect") { + m_type = NOSELECT; + } - case 's': + break; - if (name == "sent") - m_type = SPECIALUSE_SENT; + case 's': - break; + if (name == "sent") { + m_type = SPECIALUSE_SENT; + } - case 't': + break; - if (name == "trash") - m_type = SPECIALUSE_TRASH; + case 't': - break; + if (name == "trash") { + m_type = SPECIALUSE_TRASH; + } - case 'u': + break; - if (name == "unmarked") - m_type = UNMARKED; + case 'u': - break; + if (name == "unmarked") { + m_type = UNMARKED; + } + + break; } - if (m_type == UNKNOWN) + if (m_type == UNKNOWN) { m_name = "\\" + name; - } - else - { + } + + } else { + shared_ptr at; VIMAP_PARSER_GET_PTR(atom, at); const string name = utility::stringUtils::toLower(at->value()); @@ -2048,8 +2073,7 @@ public: } - enum Type - { + enum Type { // RFC-3348 - Child Mailbox Extension HASCHILDREN, HASNOCHILDREN, @@ -2090,23 +2114,22 @@ public: DECLARE_COMPONENT(mailbox_flag_list) - ~mailbox_flag_list() - { + ~mailbox_flag_list() { + for (std::vector ::iterator it = m_flags.begin() ; - it != m_flags.end() ; ++it) - { - delete (*it); + it != m_flags.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_GET_PUSHBACK(mailbox_flag, m_flags); VIMAP_PARSER_TRY_CHECK(SPACE); } @@ -2135,26 +2158,26 @@ public: mailbox_list() : m_mailbox_flag_list(NULL), - m_mailbox(NULL), m_quoted_char('\0') - { + m_mailbox(NULL), m_quoted_char('\0') { + } - ~mailbox_list() - { - delete (m_mailbox_flag_list); - delete (m_mailbox); + ~mailbox_list() { + + delete m_mailbox_flag_list; + delete m_mailbox; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::mailbox_flag_list, m_mailbox_flag_list); VIMAP_PARSER_CHECK(SPACE); - if (!VIMAP_PARSER_TRY_CHECK(NIL)) - { + if (!VIMAP_PARSER_TRY_CHECK(NIL)) { + VIMAP_PARSER_CHECK(one_char <'"'> ); shared_ptr qc; @@ -2194,29 +2217,29 @@ public: DECLARE_COMPONENT(auth_type) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; shared_ptr at; VIMAP_PARSER_GET_PTR(atom, at); m_name = utility::stringUtils::toLower(at->value()); - if (m_name == "kerberos_v4") + if (m_name == "kerberos_v4") { m_type = KERBEROS_V4; - else if (m_name == "gssapi") + } else if (m_name == "gssapi") { m_type = GSSAPI; - else if (m_name == "skey") + } else if (m_name == "skey") { m_type = SKEY; - else + } else { m_type = UNKNOWN; + } return true; } - enum Type - { + enum Type { UNKNOWN, // RFC 1731 - IMAP4 Authentication Mechanisms @@ -2255,47 +2278,38 @@ public: DECLARE_COMPONENT(status_att_val) status_att_val() - : m_value(NULL) - { + : m_value(NULL) { + } - ~status_att_val() - { + ~status_att_val() { + delete m_value; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; // "HIGHESTMODSEQ" SP mod-sequence-valzer - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "highestmodseq")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "highestmodseq")) { + m_type = HIGHESTMODSEQ; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::mod_sequence_value, m_value); - } - else - { - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "messages")) - { + + } else { + + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "messages")) { m_type = MESSAGES; - } - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "recent")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "recent")) { m_type = RECENT; - } - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnext")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnext")) { m_type = UIDNEXT; - } - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidvalidity")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidvalidity")) { m_type = UIDVALIDITY; - } - else - { + } else { VIMAP_PARSER_CHECK_WITHARG(special_atom, "unseen"); m_type = UNSEEN; } @@ -2310,8 +2324,7 @@ public: } - enum Type - { + enum Type { // Extensions HIGHESTMODSEQ, @@ -2332,13 +2345,11 @@ public: Type type() const { return (m_type); } - const IMAPParser::number* value_as_number() const - { + const IMAPParser::number* value_as_number() const { return dynamic_cast (m_value); } - const IMAPParser::mod_sequence_value* value_as_mod_sequence_value() const - { + const IMAPParser::mod_sequence_value* value_as_mod_sequence_value() const { return dynamic_cast (m_value); } }; @@ -2348,23 +2359,24 @@ public: DECLARE_COMPONENT(status_att_list) - ~status_att_list() - { + ~status_att_list() { + for (std::vector ::iterator it = m_values.begin() ; - it != m_values.end() ; ++it) - { + it != m_values.end() ; ++it) { + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET_PUSHBACK(IMAPParser::status_att_val, m_values); - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET_PUSHBACK(IMAPParser::status_att_val, m_values); + } *currentPos = pos; @@ -2390,18 +2402,19 @@ public: DECLARE_COMPONENT(capability) capability() - : m_auth_type(NULL), m_atom(NULL) - { + : m_auth_type(NULL), + m_atom(NULL) { + } - ~capability() - { - delete (m_auth_type); - delete (m_atom); + ~capability() { + + delete m_auth_type; + delete m_atom; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::atom, m_atom); @@ -2413,8 +2426,8 @@ public: (str[1] == 'u' || str[1] == 'U') && (str[2] == 't' || str[2] == 'T') && (str[3] == 'h' || str[3] == 'H') && - (str[4] == '=')) - { + (str[4] == '=')) { + size_t pos = 5; m_auth_type = parser.get (value, &pos); @@ -2449,36 +2462,34 @@ public: DECLARE_COMPONENT(capability_data) - ~capability_data() - { + ~capability_data() { + for (std::vector ::iterator it = m_capabilities.begin() ; - it != m_capabilities.end() ; ++it) - { - delete (*it); + it != m_capabilities.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK_WITHARG(special_atom, "capability"); - while (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { + capability* cap; - if (parser.isStrict() || m_capabilities.empty()) - { + if (parser.isStrict() || m_capabilities.empty()) { VIMAP_PARSER_GET(capability, cap); - } - else - { + } else { VIMAP_PARSER_TRY_GET(capability, cap); // allow SPACE at end of line (Apple iCloud IMAP server) } - if (!cap) + if (!cap) { break; + } m_capabilities.push_back(cap); } @@ -2524,8 +2535,8 @@ public: DECLARE_COMPONENT(date_time) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; // <"> date_day_fixed "-" date_month "-" date_year @@ -2566,8 +2577,9 @@ public: // ("+" / "-") 4digit int sign = 1; - if (!(VIMAP_PARSER_TRY_CHECK(one_char <'+'> ))) + if (!(VIMAP_PARSER_TRY_CHECK(one_char <'+'> ))) { VIMAP_PARSER_CHECK(one_char <'-'> ); + } shared_ptr nz; VIMAP_PARSER_GET_PTR(number, nz); @@ -2591,55 +2603,53 @@ public: const string month(utility::stringUtils::toLower(amo->value())); int mon = vmime::datetime::JANUARY; - if (month.length() >= 3) - { - switch (month[0]) - { - case 'j': - { - switch (month[1]) - { - case 'a': mon = vmime::datetime::JANUARY; break; - case 'u': - { - switch (month[2]) - { - case 'n': mon = vmime::datetime::JUNE; break; - default: mon = vmime::datetime::JULY; break; + if (month.length() >= 3) { + + switch (month[0]) { + + case 'j': { + + switch (month[1]) { + + case 'a': mon = vmime::datetime::JANUARY; break; + case 'u': { + + switch (month[2]) { + + case 'n': mon = vmime::datetime::JUNE; break; + default: mon = vmime::datetime::JULY; break; + } + + break; + } + } break; } + case 'f': mon = vmime::datetime::FEBRUARY; break; + case 'm': { + switch (month[2]) { + case 'r': mon = vmime::datetime::MARCH; break; + default: mon = vmime::datetime::MAY; break; + } + + break; } - - break; - } - case 'f': mon = vmime::datetime::FEBRUARY; break; - case 'm': - { - switch (month[2]) + case 'a': { - case 'r': mon = vmime::datetime::MARCH; break; - default: mon = vmime::datetime::MAY; break; - } + switch (month[1]) { + case 'p': mon = vmime::datetime::APRIL; break; + default: mon = vmime::datetime::AUGUST; break; + } - break; - } - case 'a': - { - switch (month[1]) - { - case 'p': mon = vmime::datetime::APRIL; break; - default: mon = vmime::datetime::AUGUST; break; + break; } - - break; - } - case 's': mon = vmime::datetime::SEPTEMBER; break; - case 'o': mon = vmime::datetime::OCTOBER; break; - case 'n': mon = vmime::datetime::NOVEMBER; break; - case 'd': mon = vmime::datetime::DECEMBER; break; + case 's': mon = vmime::datetime::SEPTEMBER; break; + case 'o': mon = vmime::datetime::OCTOBER; break; + case 'n': mon = vmime::datetime::NOVEMBER; break; + case 'd': mon = vmime::datetime::DECEMBER; break; } } @@ -2669,23 +2679,22 @@ public: DECLARE_COMPONENT(header_list) - ~header_list() - { + ~header_list() { + for (std::vector ::iterator it = m_fld_names.begin() ; - it != m_fld_names.end() ; ++it) - { - delete (*it); + it != m_fld_names.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_GET_PUSHBACK(header_fld_name, m_fld_names); VIMAP_PARSER_TRY_CHECK(SPACE); } @@ -2718,40 +2727,41 @@ public: DECLARE_COMPONENT(body_extension) body_extension() - : m_nstring(NULL), m_number(NULL) - { + : m_nstring(NULL), + m_number(NULL) { + } - ~body_extension() - { - delete (m_nstring); - delete (m_number); + ~body_extension() { + + delete m_nstring; + delete m_number; for (std::vector ::iterator it = m_body_extensions.begin() ; - it != m_body_extensions.end() ; ++it) - { - delete (*it); + it != m_body_extensions.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) { + VIMAP_PARSER_GET_PUSHBACK(body_extension, m_body_extensions); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_GET_PUSHBACK(body_extension, m_body_extensions); VIMAP_PARSER_TRY_CHECK(SPACE); } - } - else - { - if (!VIMAP_PARSER_TRY_GET(IMAPParser::nstring, m_nstring)) + + } else { + + if (!VIMAP_PARSER_TRY_GET(IMAPParser::nstring, m_nstring)) { VIMAP_PARSER_GET(IMAPParser::number, m_number); + } } *currentPos = pos; @@ -2783,43 +2793,43 @@ public: DECLARE_COMPONENT(section_text) section_text() - : m_header_list(NULL) - { + : m_header_list(NULL) { + } - ~section_text() - { - delete (m_header_list); + ~section_text() { + + delete m_header_list; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; // "HEADER.FIELDS" [".NOT"] SPACE header_list const bool b1 = VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "header.fields.not"); const bool b2 = (b1 ? false : VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "header.fields")); - if (b1 || b2) - { + if (b1 || b2) { + m_type = b1 ? HEADER_FIELDS_NOT : HEADER_FIELDS; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::header_list, m_header_list); - } + // "HEADER" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "header")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "header")) { + m_type = HEADER; - } + // "MIME" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "mime")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "mime")) { + m_type = MIME; - } + // "TEXT" - else - { + } else { + m_type = TEXT; VIMAP_PARSER_CHECK_WITHARG(special_atom, "text"); @@ -2831,8 +2841,7 @@ public: } - enum Type - { + enum Type { HEADER, HEADER_FIELDS, HEADER_FIELDS_NOT, @@ -2860,38 +2869,36 @@ public: DECLARE_COMPONENT(section) section() - : m_section_text1(NULL), m_section_text2(NULL) - { + : m_section_text1(NULL), + m_section_text2(NULL) { + } - ~section() - { - delete (m_section_text1); - delete (m_section_text2); + ~section() { + + delete m_section_text1; + delete m_section_text2; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'['> ); - if (!VIMAP_PARSER_TRY_CHECK(one_char <']'> )) - { - if (!VIMAP_PARSER_TRY_GET(section_text, m_section_text1)) - { + if (!VIMAP_PARSER_TRY_CHECK(one_char <']'> )) { + + if (!VIMAP_PARSER_TRY_GET(section_text, m_section_text1)) { + shared_ptr num; VIMAP_PARSER_GET_PTR(nz_number, num); m_nz_numbers.push_back(static_cast (num->value())); - while (VIMAP_PARSER_TRY_CHECK(one_char <'.'> )) - { - if (VIMAP_PARSER_TRY_GET_PTR(nz_number, num)) - { + while (VIMAP_PARSER_TRY_CHECK(one_char <'.'> )) { + + if (VIMAP_PARSER_TRY_GET_PTR(nz_number, num)) { m_nz_numbers.push_back(static_cast (num->value())); - } - else - { + } else { VIMAP_PARSER_GET(section_text, m_section_text2); break; } @@ -2946,21 +2953,23 @@ public: DECLARE_COMPONENT(address) address() - : m_addr_name(NULL), m_addr_adl(NULL), - m_addr_mailbox(NULL), m_addr_host(NULL) - { + : m_addr_name(NULL), + m_addr_adl(NULL), + m_addr_mailbox(NULL), + m_addr_host(NULL) { + } - ~address() - { - delete (m_addr_name); - delete (m_addr_adl); - delete (m_addr_mailbox); - delete (m_addr_host); + ~address() { + + delete m_addr_name; + delete m_addr_adl; + delete m_addr_mailbox; + delete m_addr_host; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); @@ -3000,25 +3009,24 @@ public: DECLARE_COMPONENT(address_list) - ~address_list() - { + ~address_list() { + for (std::vector ::iterator it = m_addresses.begin() ; - it != m_addresses.end() ; ++it) - { + it != m_addresses.end() ; ++it) { + delete (*it); } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!VIMAP_PARSER_TRY_CHECK(NIL)) - { + if (!VIMAP_PARSER_TRY_CHECK(NIL)) { + VIMAP_PARSER_CHECK(one_char <'('> ); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_GET_PUSHBACK(address, m_addresses); VIMAP_PARSER_TRY_CHECK(SPACE); } @@ -3119,29 +3127,35 @@ public: DECLARE_COMPONENT(envelope) envelope() - : m_env_date(NULL), m_env_subject(NULL), - m_env_from(NULL), m_env_sender(NULL), m_env_reply_to(NULL), - m_env_to(NULL), m_env_cc(NULL), m_env_bcc(NULL), - m_env_in_reply_to(NULL), m_env_message_id(NULL) - { + : m_env_date(NULL), + m_env_subject(NULL), + m_env_from(NULL), + m_env_sender(NULL), + m_env_reply_to(NULL), + m_env_to(NULL), + m_env_cc(NULL), + m_env_bcc(NULL), + m_env_in_reply_to(NULL), + m_env_message_id(NULL) { + } - ~envelope() - { - delete (m_env_date); - delete (m_env_subject); - delete (m_env_from); - delete (m_env_sender); - delete (m_env_reply_to); - delete (m_env_to); - delete (m_env_cc); - delete (m_env_bcc); - delete (m_env_in_reply_to); - delete (m_env_message_id); + ~envelope() { + + delete m_env_date; + delete m_env_subject; + delete m_env_from; + delete m_env_sender; + delete m_env_reply_to; + delete m_env_to; + delete m_env_cc; + delete m_env_bcc; + delete m_env_in_reply_to; + delete m_env_message_id; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); @@ -3250,25 +3264,26 @@ public: // "QUOTED-PRINTABLE") <">) / string // - class body_fld_enc : public nstring - { + class body_fld_enc : public nstring { + public: - const string getComponentName() const - { + const string getComponentName() const { + return "body_fld_enc"; } - body_fld_enc() - { + body_fld_enc() { + } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!xstring::parseImpl(parser, line, &pos)) + if (!xstring::parseImpl(parser, line, &pos)) { return false; + } // " When an IMAP4 client sends a FETCH (bodystructure) request // to a server that is running the Exchange Server 2007 IMAP4 @@ -3276,8 +3291,7 @@ public: // (see http://support.microsoft.com/kb/975918/en-us) // // Fail in strict mode - if (isNIL() && parser.isStrict()) - { + if (isNIL() && parser.isStrict()) { VIMAP_PARSER_FAIL(); } @@ -3295,51 +3309,52 @@ public: DECLARE_COMPONENT(body_fld_param_item) body_fld_param_item() - : m_string1(NULL), m_string2(NULL) - { + : m_string1(NULL), + m_string2(NULL) { + } - ~body_fld_param_item() - { - delete (m_string1); - delete (m_string2); + ~body_fld_param_item() { + + delete m_string1; + delete m_string2; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!parser.isStrict()) - { + if (!parser.isStrict()) { + // Some servers send an instead of a here: // eg. ... (CHARSET "X-UNKNOWN") ... - if (!VIMAP_PARSER_TRY_GET(xstring, m_string1)) - { + if (!VIMAP_PARSER_TRY_GET(xstring, m_string1)) { + shared_ptr at; VIMAP_PARSER_GET_PTR(atom, at); m_string1 = new xstring(); m_string1->setValue(at->value()); } - } - else - { + + } else { + VIMAP_PARSER_GET(xstring, m_string1); } VIMAP_PARSER_CHECK(SPACE); - if (!parser.isStrict()) - { + if (!parser.isStrict()) { + // In non-strict mode, allow NIL in value shared_ptr nstr; VIMAP_PARSER_GET_PTR(nstring, nstr); m_string2 = new xstring(); m_string2->setValue(nstr->value()); - } - else - { + + } else { + VIMAP_PARSER_GET(xstring, m_string2); } @@ -3368,31 +3383,30 @@ public: DECLARE_COMPONENT(body_fld_param) - ~body_fld_param() - { + ~body_fld_param() { + for (std::vector ::iterator it = m_items.begin() ; - it != m_items.end() ; ++it) - { - delete (*it); + it != m_items.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) { + VIMAP_PARSER_GET_PUSHBACK(body_fld_param_item, m_items); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET_PUSHBACK(body_fld_param_item, m_items); } - } - else - { + + } else { + VIMAP_PARSER_CHECK(NIL); } @@ -3418,29 +3432,30 @@ public: DECLARE_COMPONENT(body_fld_dsp) body_fld_dsp() - : m_string(NULL), m_body_fld_param(NULL) - { + : m_string(NULL), + m_body_fld_param(NULL) { + } - ~body_fld_dsp() - { - delete (m_string); - delete (m_body_fld_param); + ~body_fld_dsp() { + + delete m_string; + delete m_body_fld_param; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) { + VIMAP_PARSER_GET(xstring, m_string); VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(class body_fld_param, m_body_fld_param); VIMAP_PARSER_CHECK(one_char <')'> ); - } - else - { + + } else { + VIMAP_PARSER_CHECK(NIL); } @@ -3467,31 +3482,30 @@ public: DECLARE_COMPONENT(body_fld_lang) - ~body_fld_lang() - { + ~body_fld_lang() { + for (std::vector ::iterator it = m_strings.begin() ; - it != m_strings.end() ; ++it) - { - delete (*it); + it != m_strings.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) { + VIMAP_PARSER_GET_PUSHBACK(xstring, m_strings); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET_PUSHBACK(xstring, m_strings); } - } - else - { + + } else { + VIMAP_PARSER_GET_PUSHBACK(nstring, m_strings); } @@ -3519,22 +3533,25 @@ public: DECLARE_COMPONENT(body_fields) body_fields() - : m_body_fld_param(NULL), m_body_fld_id(NULL), - m_body_fld_desc(NULL), m_body_fld_enc(NULL), m_body_fld_octets(NULL) - { + : m_body_fld_param(NULL), + m_body_fld_id(NULL), + m_body_fld_desc(NULL), + m_body_fld_enc(NULL), + m_body_fld_octets(NULL) { + } - ~body_fields() - { - delete (m_body_fld_param); - delete (m_body_fld_id); - delete (m_body_fld_desc); - delete (m_body_fld_enc); - delete (m_body_fld_octets); + ~body_fields() { + + delete m_body_fld_param; + delete m_body_fld_id; + delete m_body_fld_desc; + delete m_body_fld_enc; + delete m_body_fld_octets; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::body_fld_param, m_body_fld_param); @@ -3586,17 +3603,17 @@ public: DECLARE_COMPONENT(media_text) media_text() - : m_media_subtype(NULL) - { + : m_media_subtype(NULL) { + } - ~media_text() - { - delete (m_media_subtype); + ~media_text() { + + delete m_media_subtype; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'"'> ); @@ -3629,17 +3646,17 @@ public: DECLARE_COMPONENT(media_message) media_message() - : m_media_subtype(NULL) - { + : m_media_subtype(NULL) { + } - ~media_message() - { + ~media_message() { + delete m_media_subtype; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'"'> ); @@ -3677,18 +3694,19 @@ public: DECLARE_COMPONENT(media_basic) media_basic() - : m_media_type(NULL), m_media_subtype(NULL) - { + : m_media_type(NULL), + m_media_subtype(NULL) { + } - ~media_basic() - { - delete (m_media_type); - delete (m_media_subtype); + ~media_basic() { + + delete m_media_type; + delete m_media_subtype; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(xstring, m_media_type); @@ -3725,20 +3743,22 @@ public: DECLARE_COMPONENT(body_ext_1part) body_ext_1part() - : m_body_fld_md5(NULL), m_body_fld_dsp(NULL), m_body_fld_lang(NULL) - { + : m_body_fld_md5(NULL), + m_body_fld_dsp(NULL), + m_body_fld_lang(NULL) { + } - ~body_ext_1part() - { - delete (m_body_fld_md5); - delete (m_body_fld_dsp); - delete (m_body_fld_lang); + ~body_ext_1part() { + + delete m_body_fld_md5; + delete m_body_fld_dsp; + delete m_body_fld_lang; for (std::vector ::iterator it = m_body_extensions.begin() ; - it != m_body_extensions.end() ; ++it) - { - delete (*it); + it != m_body_extensions.end() ; ++it) { + + delete *it; } } @@ -3749,22 +3769,23 @@ public: VIMAP_PARSER_GET(IMAPParser::body_fld_md5, m_body_fld_md5); // [SPACE body_fld_dsp - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET(IMAPParser::body_fld_dsp, m_body_fld_dsp); // [SPACE body_fld_lang - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET(IMAPParser::body_fld_lang, m_body_fld_lang); // [SPACE 1#body_extension] - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET_PUSHBACK(body_extension, m_body_extensions); - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET_PUSHBACK(body_extension, m_body_extensions); + } } } } @@ -3802,45 +3823,48 @@ public: DECLARE_COMPONENT(body_ext_mpart) body_ext_mpart() - : m_body_fld_param(NULL), m_body_fld_dsp(NULL), m_body_fld_lang(NULL) - { + : m_body_fld_param(NULL), + m_body_fld_dsp(NULL), + m_body_fld_lang(NULL) { + } - ~body_ext_mpart() - { - delete (m_body_fld_param); - delete (m_body_fld_dsp); - delete (m_body_fld_lang); + ~body_ext_mpart() { + + delete m_body_fld_param; + delete m_body_fld_dsp; + delete m_body_fld_lang; for (std::vector ::iterator it = m_body_extensions.begin() ; - it != m_body_extensions.end() ; ++it) - { - delete (*it); + it != m_body_extensions.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::body_fld_param, m_body_fld_param); // [SPACE body_fld_dsp [SPACE body_fld_lang [SPACE 1#body_extension]]] - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET(IMAPParser::body_fld_dsp, m_body_fld_dsp); - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET(IMAPParser::body_fld_lang, m_body_fld_lang); // [SPACE 1#body_extension] - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET_PUSHBACK(body_extension, m_body_extensions); - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET_PUSHBACK(body_extension, m_body_extensions); + } } } } @@ -3876,18 +3900,19 @@ public: DECLARE_COMPONENT(body_type_basic) body_type_basic() - : m_media_basic(NULL), m_body_fields(NULL) - { + : m_media_basic(NULL), + m_body_fields(NULL) { + } - ~body_type_basic() - { - delete (m_media_basic); - delete (m_body_fields); + ~body_type_basic() { + + delete m_media_basic; + delete m_body_fields; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::media_basic, m_media_basic); @@ -3922,22 +3947,25 @@ public: DECLARE_COMPONENT(body_type_msg) body_type_msg() - : m_media_message(NULL), m_body_fields(NULL), - m_envelope(NULL), m_body(NULL), m_body_fld_lines(NULL) - { + : m_media_message(NULL), + m_body_fields(NULL), + m_envelope(NULL), + m_body(NULL), + m_body_fld_lines(NULL) { + } - ~body_type_msg() - { - delete (m_media_message); - delete (m_body_fields); - delete (m_envelope); - delete (m_body); - delete (m_body_fld_lines); + ~body_type_msg() { + + delete m_media_message; + delete m_body_fields; + delete m_envelope; + delete m_body; + delete m_body_fld_lines; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::media_message, m_media_message); @@ -3984,19 +4012,20 @@ public: body_type_text() : m_media_text(NULL), - m_body_fields(NULL), m_body_fld_lines(NULL) - { + m_body_fields(NULL), + m_body_fld_lines(NULL) { + } - ~body_type_text() - { - delete (m_media_text); - delete (m_body_fields); - delete (m_body_fld_lines); + ~body_type_text() { + + delete m_media_text; + delete m_body_fields; + delete m_body_fld_lines; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::media_text, m_media_text); @@ -4032,32 +4061,35 @@ public: DECLARE_COMPONENT(body_type_1part) body_type_1part() - : m_body_type_basic(NULL), m_body_type_msg(NULL), - m_body_type_text(NULL), m_body_ext_1part(NULL) - { + : m_body_type_basic(NULL), + m_body_type_msg(NULL), + m_body_type_text(NULL), + m_body_ext_1part(NULL) { + } - ~body_type_1part() - { - delete (m_body_type_basic); - delete (m_body_type_msg); - delete (m_body_type_text); + ~body_type_1part() { - delete (m_body_ext_1part); + delete m_body_type_basic; + delete m_body_type_msg; + delete m_body_type_text; + delete m_body_ext_1part; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_text, m_body_type_text)) - if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_msg, m_body_type_msg)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_text, m_body_type_text)) { + if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_msg, m_body_type_msg)) { VIMAP_PARSER_GET(IMAPParser::body_type_basic, m_body_type_basic); + } + } - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { - if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_ext_1part, m_body_ext_1part)) + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_ext_1part, m_body_ext_1part)) { --pos; + } } *currentPos = pos; @@ -4091,30 +4123,30 @@ public: DECLARE_COMPONENT(body_type_mpart) body_type_mpart() - : m_media_subtype(NULL), m_body_ext_mpart(NULL) - { + : m_media_subtype(NULL), + m_body_ext_mpart(NULL) { + } - ~body_type_mpart() - { - delete (m_media_subtype); - delete (m_body_ext_mpart); + ~body_type_mpart() { + + delete m_media_subtype; + delete m_body_ext_mpart; for (std::vector ::iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { - delete (*it); + it != m_list.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET_PUSHBACK(xbody, m_list); - while (true) - { + while (true) { VIMAP_PARSER_TRY_GET_PUSHBACK_OR_ELSE(xbody, m_list, break); } @@ -4122,8 +4154,9 @@ public: VIMAP_PARSER_GET(IMAPParser::media_subtype, m_media_subtype); - if (VIMAP_PARSER_TRY_CHECK(SPACE)) + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET(IMAPParser::body_ext_mpart, m_body_ext_mpart); + } *currentPos = pos; @@ -4153,24 +4186,26 @@ public: DECLARE_COMPONENT(xbody) xbody() - : m_body_type_1part(NULL), m_body_type_mpart(NULL) - { + : m_body_type_1part(NULL), + m_body_type_mpart(NULL) { + } - ~xbody() - { - delete (m_body_type_1part); - delete (m_body_type_mpart); + ~xbody() { + + delete m_body_type_1part; + delete m_body_type_mpart; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); - if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_mpart, m_body_type_mpart)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_mpart, m_body_type_mpart)) { VIMAP_PARSER_GET(IMAPParser::body_type_1part, m_body_type_1part); + } VIMAP_PARSER_CHECK(one_char <')'> ); @@ -4207,139 +4242,141 @@ public: DECLARE_COMPONENT(msg_att_item) msg_att_item() - : m_date_time(NULL), m_number(NULL), m_envelope(NULL), - m_uniqueid(NULL), m_nstring(NULL), m_body(NULL), m_flag_list(NULL), - m_section(NULL), m_mod_sequence_value(NULL) + : m_date_time(NULL), + m_number(NULL), + m_envelope(NULL), + m_uniqueid(NULL), + m_nstring(NULL), + m_body(NULL), + m_flag_list(NULL), + m_section(NULL), + m_mod_sequence_value(NULL) { - { } - ~msg_att_item() - { - delete (m_date_time); - delete (m_number); - delete (m_envelope); - delete (m_uniqueid); - delete (m_nstring); - delete (m_body); - delete (m_flag_list); - delete (m_section); + ~msg_att_item() { + + delete m_date_time; + delete m_number; + delete m_envelope; + delete m_uniqueid; + delete m_nstring; + delete m_body; + delete m_flag_list; + delete m_section; delete m_mod_sequence_value; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; // "ENVELOPE" SPACE envelope - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "envelope")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "envelope")) { + m_type = ENVELOPE; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::envelope, m_envelope); - } + // "FLAGS" SPACE "(" #(flag / "\Recent") ")" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "flags")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "flags")) { + m_type = FLAGS; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::flag_list, m_flag_list); - } + // "INTERNALDATE" SPACE date_time - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "internaldate")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "internaldate")) { + m_type = INTERNALDATE; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::date_time, m_date_time); - } + // "RFC822" ".HEADER" SPACE nstring - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.header")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.header")) { + m_type = RFC822_HEADER; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::nstring, m_nstring); - } + // "RFC822" ".TEXT" SPACE nstring - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.text")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.text")) { + m_type = RFC822_TEXT; VIMAP_PARSER_CHECK(SPACE); - m_nstring = parser.getWithArgs - (line, &pos, this, RFC822_TEXT); + m_nstring = parser.getWithArgs (line, &pos, this, RFC822_TEXT); VIMAP_PARSER_FAIL_UNLESS(m_nstring); - } + // "RFC822.SIZE" SPACE number - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.size")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.size")) { + m_type = RFC822_SIZE; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::number, m_number); - } + // "RFC822" SPACE nstring - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822")) { + m_type = RFC822; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::nstring, m_nstring); - } + // "BODY" "STRUCTURE" SPACE body - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "bodystructure")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "bodystructure")) { + m_type = BODY_STRUCTURE; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::body, m_body); - } + // "BODY" section ["<" number ">"] SPACE nstring // "BODY" SPACE body - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "body")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "body")) { + VIMAP_PARSER_TRY_GET(IMAPParser::section, m_section); // "BODY" section ["<" number ">"] SPACE nstring - if (m_section != NULL) - { + if (m_section != NULL) { + m_type = BODY_SECTION; - if (VIMAP_PARSER_TRY_CHECK(one_char <'<'> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'<'> )) { VIMAP_PARSER_GET(IMAPParser::number, m_number); VIMAP_PARSER_CHECK(one_char <'>'> ); } VIMAP_PARSER_CHECK(SPACE); - m_nstring = parser.getWithArgs - (line, &pos, this, BODY_SECTION); + m_nstring = parser.getWithArgs (line, &pos, this, BODY_SECTION); VIMAP_PARSER_FAIL_UNLESS(m_nstring); - } + // "BODY" SPACE body - else - { + } else { + m_type = BODY; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::body, m_body); } - } + // "MODSEQ" SP "(" mod_sequence_value ")" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "modseq")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "modseq")) { + m_type = MODSEQ; VIMAP_PARSER_CHECK(SPACE); @@ -4348,10 +4385,10 @@ public: VIMAP_PARSER_GET(IMAPParser::mod_sequence_value, m_mod_sequence_value); VIMAP_PARSER_CHECK(one_char <')'> ); - } + // "UID" SPACE uniqueid - else - { + } else { + m_type = UID; VIMAP_PARSER_CHECK_WITHARG(special_atom, "uid"); @@ -4366,8 +4403,7 @@ public: } - enum Type - { + enum Type { ENVELOPE, FLAGS, INTERNALDATE, @@ -4418,25 +4454,24 @@ public: DECLARE_COMPONENT(msg_att) - ~msg_att() - { + ~msg_att() { + for (std::vector ::iterator it = m_items.begin() ; - it != m_items.end() ; ++it) - { - delete (*it); + it != m_items.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); m_items.push_back(parser.get (line, &pos)); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET_PUSHBACK(msg_att_item, m_items); } @@ -4464,17 +4499,18 @@ public: DECLARE_COMPONENT(message_data) message_data() - : m_number(0), m_msg_att(NULL) - { + : m_number(0), + m_msg_att(NULL) { + } - ~message_data() - { - delete (m_msg_att); + ~message_data() { + + delete m_msg_att; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; scoped_ptr num; @@ -4483,12 +4519,12 @@ public: VIMAP_PARSER_CHECK(SPACE); - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "expunge")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "expunge")) { + m_type = EXPUNGE; - } - else - { + + } else { + m_type = FETCH; VIMAP_PARSER_CHECK_WITHARG(special_atom, "fetch"); @@ -4502,8 +4538,7 @@ public: } - enum Type - { + enum Type { EXPUNGE, FETCH }; @@ -4547,122 +4582,125 @@ public: DECLARE_COMPONENT(resp_text_code) resp_text_code() - : m_nz_number(NULL), m_atom(NULL), m_flag_list(NULL), - m_text(NULL), m_capability_data(NULL) - { + : m_nz_number(NULL), + m_atom(NULL), + m_flag_list(NULL), + m_text(NULL), + m_capability_data(NULL) { + } - ~resp_text_code() - { - delete (m_nz_number); - delete (m_atom); - delete (m_flag_list); - delete (m_text); + ~resp_text_code() { + + delete m_nz_number; + delete m_atom; + delete m_flag_list; + delete m_text; delete m_capability_data; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; // "ALERT" - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "alert")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "alert")) { + m_type = ALERT; - } + // "PARSE" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "parse")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "parse")) { + m_type = PARSE; - } + // capability_data - else if (VIMAP_PARSER_TRY_GET(IMAPParser::capability_data, m_capability_data)) - { + } else if (VIMAP_PARSER_TRY_GET(IMAPParser::capability_data, m_capability_data)) { + m_type = CAPABILITY; - } + // "PERMANENTFLAGS" SPACE flag_list - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "permanentflags")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "permanentflags")) { + m_type = PERMANENTFLAGS; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::flag_list, m_flag_list); - } + // "READ-ONLY" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "read-only")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "read-only")) { + m_type = READ_ONLY; - } + // "READ-WRITE" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "read-write")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "read-write")) { + m_type = READ_WRITE; - } + // "TRYCREATE" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "trycreate")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "trycreate")) { + m_type = TRYCREATE; - } + // "UIDVALIDITY" SPACE nz_number - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidvalidity")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidvalidity")) { + m_type = UIDVALIDITY; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::nz_number, m_nz_number); - } + // "UIDNEXT" SPACE nz_number - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnext")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnext")) { + m_type = UIDNEXT; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::nz_number, m_nz_number); - } + // "UNSEEN" SPACE nz_number - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "unseen")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "unseen")) { + m_type = UNSEEN; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::nz_number, m_nz_number); - } + // "HIGHESTMODSEQ" SP mod-sequence-value - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "highestmodseq")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "highestmodseq")) { + m_type = HIGHESTMODSEQ; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::mod_sequence_value, m_mod_sequence_value); - } + // "NOMODSEQ" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "nomodseq")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "nomodseq")) { + m_type = NOMODSEQ; - } + // "MODIFIED" SP sequence-set - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "modified")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "modified")) { + m_type = MODIFIED; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::sequence_set, m_sequence_set); - } + // "APPENDUID" SP nz-number SP append-uid - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "appenduid")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "appenduid")) { + m_type = APPENDUID; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::nz_number, m_nz_number); VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::uid_set, m_uid_set); - } + // "COPYUID" SP nz-number SP uid-set SP uid-set - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "copyuid")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "copyuid")) { + m_type = COPYUID; VIMAP_PARSER_CHECK(SPACE); @@ -4671,21 +4709,22 @@ public: VIMAP_PARSER_GET(IMAPParser::uid_set, m_uid_set); VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::uid_set, m_uid_set2); - } + // "UIDNOTSTICKY" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnotsticky")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnotsticky")) { + m_type = UIDNOTSTICKY; - } + // atom [SPACE 1*] - else - { + } else { + m_type = OTHER; VIMAP_PARSER_GET(IMAPParser::atom, m_atom); - if (VIMAP_PARSER_TRY_CHECK(SPACE)) + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET(text_except <']'> , m_text); + } } *currentPos = pos; @@ -4694,8 +4733,7 @@ public: } - enum Type - { + enum Type { // Extensions HIGHESTMODSEQ, NOMODSEQ, @@ -4755,21 +4793,21 @@ public: DECLARE_COMPONENT(resp_text) resp_text() - : m_resp_text_code(NULL) - { + : m_resp_text_code(NULL) { + } - ~resp_text() - { - delete (m_resp_text_code); + ~resp_text() { + + delete m_resp_text_code; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'['> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'['> )) { + VIMAP_PARSER_GET(IMAPParser::resp_text_code, m_resp_text_code); VIMAP_PARSER_CHECK(one_char <']'> ); @@ -4779,21 +4817,18 @@ public: scoped_ptr text1; VIMAP_PARSER_TRY_GET_PTR(text_mime2, text1); - if (text1.get()) - { + if (text1.get()) { + m_text = text1->value(); - } - else - { + + } else { + scoped_ptr text2; VIMAP_PARSER_TRY_GET_PTR(IMAPParser::text, text2); - if (text2.get()) - { + if (text2.get()) { m_text = text2->value(); - } - else - { + } else { // Empty response text } } @@ -4822,35 +4857,32 @@ public: DECLARE_COMPONENT(continue_req) continue_req() - : m_resp_text(NULL) - { + : m_resp_text(NULL) { + } - ~continue_req() - { - delete (m_resp_text); + ~continue_req() { + + delete m_resp_text; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'+'> ); - if (!parser.isStrict()) - { + if (!parser.isStrict()) { + // Some servers do not send SPACE when response text is empty - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET(IMAPParser::resp_text, m_resp_text); - } - else - { + } else { m_resp_text = new IMAPParser::resp_text(); // empty } - } - else - { + + } else { + VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::resp_text, m_resp_text); @@ -4881,29 +4913,25 @@ public: DECLARE_COMPONENT(resp_cond_state) resp_cond_state() - : m_resp_text(NULL), m_status(BAD) - { + : m_resp_text(NULL), + m_status(BAD) { + } - ~resp_cond_state() - { - delete (m_resp_text); + ~resp_cond_state() { + + delete m_resp_text; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "ok")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "ok")) { m_status = OK; - } - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "no")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "no")) { m_status = NO; - } - else - { + } else { VIMAP_PARSER_CHECK_WITHARG(special_atom, "bad"); m_status = BAD; } @@ -4918,8 +4946,7 @@ public: } - enum Status - { + enum Status { OK, NO, BAD @@ -4944,17 +4971,17 @@ public: DECLARE_COMPONENT(resp_cond_bye) resp_cond_bye() - : m_resp_text(NULL) - { + : m_resp_text(NULL) { + } - ~resp_cond_bye() - { - delete (m_resp_text); + ~resp_cond_bye() { + + delete m_resp_text; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK_WITHARG(special_atom, "bye"); @@ -4986,27 +5013,23 @@ public: DECLARE_COMPONENT(resp_cond_auth) resp_cond_auth() - : m_resp_text(NULL) - { + : m_resp_text(NULL) { + } - ~resp_cond_auth() - { - delete (m_resp_text); + ~resp_cond_auth() { + + delete m_resp_text; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "ok")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "ok")) { m_cond = OK; - } - else - { + } else { VIMAP_PARSER_CHECK_WITHARG(special_atom, "preauth"); - m_cond = PREAUTH; } @@ -5020,8 +5043,7 @@ public: } - enum Condition - { + enum Condition { OK, PREAUTH }; @@ -5053,102 +5075,103 @@ public: DECLARE_COMPONENT(mailbox_data) mailbox_data() - : m_number(NULL), m_mailbox_flag_list(NULL), m_mailbox_list(NULL), - m_mailbox(NULL), m_text(NULL), m_status_att_list(NULL) - { + : m_number(NULL), + m_mailbox_flag_list(NULL), + m_mailbox_list(NULL), + m_mailbox(NULL), + m_text(NULL), + m_status_att_list(NULL) { + } - ~mailbox_data() - { - delete (m_number); - delete (m_mailbox_flag_list); - delete (m_mailbox_list); - delete (m_mailbox); - delete (m_text); + ~mailbox_data() { + + delete m_number; + delete m_mailbox_flag_list; + delete m_mailbox_list; + delete m_mailbox; + delete m_text; for (std::vector ::iterator it = m_search_nz_number_list.begin() ; - it != m_search_nz_number_list.end() ; ++it) - { - delete (*it); + it != m_search_nz_number_list.end() ; ++it) { + + delete *it; } delete m_status_att_list; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_GET(IMAPParser::number, m_number)) - { + if (VIMAP_PARSER_TRY_GET(IMAPParser::number, m_number)) { + VIMAP_PARSER_CHECK(SPACE); - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "exists")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "exists")) { m_type = EXISTS; - } - else - { + } else { VIMAP_PARSER_CHECK_WITHARG(special_atom, "recent"); - m_type = RECENT; } - } - else - { + + } else { + // "FLAGS" SPACE mailbox_flag_list - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "flags")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "flags")) { + VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::mailbox_flag_list, m_mailbox_flag_list); m_type = FLAGS; - } + // "LIST" SPACE mailbox_list - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "list")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "list")) { + VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::mailbox_list, m_mailbox_list); m_type = LIST; - } + // "LSUB" SPACE mailbox_list - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "lsub")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "lsub")) { + VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::mailbox_list, m_mailbox_list); m_type = LSUB; - } + // "MAILBOX" SPACE text - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "mailbox")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "mailbox")) { + VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::text, m_text); m_type = MAILBOX; - } + // "SEARCH" [SPACE 1#nz_number] - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "search")) - { - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "search")) { + + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET_PUSHBACK(nz_number, m_search_nz_number_list); - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET_PUSHBACK(nz_number, m_search_nz_number_list); + } } m_type = SEARCH; - } + // "STATUS" SPACE mailbox SPACE // "(" [status_att_list] ")" - else - { + } else { + VIMAP_PARSER_CHECK_WITHARG(special_atom, "status"); VIMAP_PARSER_CHECK(SPACE); @@ -5170,8 +5193,8 @@ public: } - enum Type - { + enum Type { + FLAGS, LIST, LSUB, @@ -5216,38 +5239,46 @@ public: DECLARE_COMPONENT(response_data) response_data() - : m_resp_cond_state(NULL), m_resp_cond_bye(NULL), - m_mailbox_data(NULL), m_message_data(NULL), m_capability_data(NULL) - { + : m_resp_cond_state(NULL), + m_resp_cond_bye(NULL), + m_mailbox_data(NULL), + m_message_data(NULL), + m_capability_data(NULL) { + } - ~response_data() - { - delete (m_resp_cond_state); - delete (m_resp_cond_bye); - delete (m_mailbox_data); - delete (m_message_data); - delete (m_capability_data); + ~response_data() { + + delete m_resp_cond_state; + delete m_resp_cond_bye; + delete m_mailbox_data; + delete m_message_data; + delete m_capability_data; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'*'> ); VIMAP_PARSER_CHECK(SPACE); - if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_state, m_resp_cond_state)) - if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_bye, m_resp_cond_bye)) - if (!VIMAP_PARSER_TRY_GET(IMAPParser::mailbox_data, m_mailbox_data)) - if (!VIMAP_PARSER_TRY_GET(IMAPParser::message_data, m_message_data)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_state, m_resp_cond_state)) { + if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_bye, m_resp_cond_bye)) { + if (!VIMAP_PARSER_TRY_GET(IMAPParser::mailbox_data, m_mailbox_data)) { + if (!VIMAP_PARSER_TRY_GET(IMAPParser::message_data, m_message_data)) { VIMAP_PARSER_GET(IMAPParser::capability_data, m_capability_data); + } + } + } + } + + if (!parser.isStrict()) { - if (!parser.isStrict()) - { // Allow SPACEs at end of line - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { ; + } } VIMAP_PARSER_CHECK(CRLF); @@ -5278,22 +5309,24 @@ public: DECLARE_COMPONENT(continue_req_or_response_data) continue_req_or_response_data() - : m_continue_req(NULL), m_response_data(NULL) - { + : m_continue_req(NULL), + m_response_data(NULL) { + } - ~continue_req_or_response_data() - { - delete (m_continue_req); - delete (m_response_data); + ~continue_req_or_response_data() { + + delete m_continue_req; + delete m_response_data; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!VIMAP_PARSER_TRY_GET(IMAPParser::continue_req, m_continue_req)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::continue_req, m_continue_req)) { VIMAP_PARSER_GET(IMAPParser::response_data, m_response_data); + } *currentPos = pos; @@ -5320,17 +5353,17 @@ public: DECLARE_COMPONENT(response_fatal) response_fatal() - : m_resp_cond_bye(NULL) - { + : m_resp_cond_bye(NULL) { + } - ~response_fatal() - { - delete (m_resp_cond_bye); + ~response_fatal() { + + delete m_resp_cond_bye; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'*'> ); @@ -5338,11 +5371,12 @@ public: VIMAP_PARSER_GET(IMAPParser::resp_cond_bye, m_resp_cond_bye); - if (!parser.isStrict()) - { + if (!parser.isStrict()) { + // Allow SPACEs at end of line - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { ; + } } VIMAP_PARSER_CHECK(CRLF); @@ -5369,28 +5403,29 @@ public: DECLARE_COMPONENT(response_tagged) response_tagged() - : m_resp_cond_state(NULL) - { + : m_resp_cond_state(NULL) { + } - ~response_tagged() - { - delete (m_resp_cond_state); + ~response_tagged() { + + delete m_resp_cond_state; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(IMAPParser::xtag); VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::resp_cond_state, m_resp_cond_state); - if (!parser.isStrict()) - { + if (!parser.isStrict()) { + // Allow SPACEs at end of line - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { ; + } } VIMAP_PARSER_CHECK(CRLF); @@ -5417,22 +5452,24 @@ public: DECLARE_COMPONENT(response_done) response_done() - : m_response_tagged(NULL), m_response_fatal(NULL) - { + : m_response_tagged(NULL), + m_response_fatal(NULL) { + } - ~response_done() - { - delete (m_response_tagged); - delete (m_response_fatal); + ~response_done() { + + delete m_response_tagged; + delete m_response_fatal; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!VIMAP_PARSER_TRY_GET(IMAPParser::response_tagged, m_response_tagged)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::response_tagged, m_response_tagged)) { VIMAP_PARSER_GET(IMAPParser::response_fatal, m_response_fatal); + } *currentPos = pos; @@ -5458,37 +5495,36 @@ public: DECLARE_COMPONENT(response) response() - : m_response_done(NULL) - { + : m_response_done(NULL) { + } - ~response() - { + ~response() { + for (std::vector ::iterator it = m_continue_req_or_response_data.begin() ; - it != m_continue_req_or_response_data.end() ; ++it) - { - delete (*it); + it != m_continue_req_or_response_data.end() ; ++it) { + + delete *it; } - delete (m_response_done); + delete m_response_done; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; string curLine = line; bool partial = false; // partial response IMAPParser::continue_req_or_response_data* resp = NULL; - while ((resp = parser.get (curLine, &pos))) - { + while ((resp = parser.get (curLine, &pos))) { + m_continue_req_or_response_data.push_back(resp); // Partial response (continue_req) - if (resp->continue_req()) - { + if (resp->continue_req()) { partial = true; break; } @@ -5498,8 +5534,7 @@ public: pos = 0; } - if (!partial) - { + if (!partial) { m_response_done = parser.get (curLine, &pos); VIMAP_PARSER_FAIL_UNLESS(m_response_done); } @@ -5510,30 +5545,32 @@ public: } - bool isBad() const - { - if (!response_done()) // incomplete (partial) response - return (true); + bool isBad() const { - if (response_done()->response_fatal()) - return (true); - - if (response_done()->response_tagged()->resp_cond_state()-> - status() == IMAPParser::resp_cond_state::BAD) - { - return (true); + if (!response_done()) { // incomplete (partial) response + return true; } - return (false); + if (response_done()->response_fatal()) { + return true; + } + + if (response_done()->response_tagged()->resp_cond_state()-> + status() == IMAPParser::resp_cond_state::BAD) { + + return true; + } + + return false; } - void setErrorLog(const string& errorLog) - { + void setErrorLog(const string& errorLog) { + m_errorLog = errorLog; } - const string& getErrorLog() const - { + const string& getErrorLog() const { + return m_errorLog; } @@ -5558,25 +5595,27 @@ public: DECLARE_COMPONENT(greeting) greeting() - : m_resp_cond_auth(NULL), m_resp_cond_bye(NULL) - { + : m_resp_cond_auth(NULL), + m_resp_cond_bye(NULL) { + } - ~greeting() - { - delete (m_resp_cond_auth); - delete (m_resp_cond_bye); + ~greeting() { + + delete m_resp_cond_auth; + delete m_resp_cond_bye; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'*'> ); VIMAP_PARSER_CHECK(SPACE); - if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_auth, m_resp_cond_auth)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_auth, m_resp_cond_auth)) { VIMAP_PARSER_GET(IMAPParser::resp_cond_bye, m_resp_cond_bye); + } VIMAP_PARSER_CHECK(CRLF); @@ -5585,13 +5624,13 @@ public: return true; } - void setErrorLog(const string& errorLog) - { + void setErrorLog(const string& errorLog) { + m_errorLog = errorLog; } - const string& getErrorLog() const - { + const string& getErrorLog() const { + return m_errorLog; } @@ -5614,8 +5653,8 @@ public: // The main functions used to parse a response // - response* readResponse(literalHandler* lh = NULL) - { + response* readResponse(literalHandler* lh = NULL) { + size_t pos = 0; string line = readLine(); @@ -5623,8 +5662,9 @@ public: response* resp = get (line, &pos); m_literalHandler = NULL; - if (!resp) + if (!resp) { throw exceptions::invalid_response("", m_errorResponseLine); + } resp->setErrorLog(lastLine()); @@ -5632,15 +5672,16 @@ public: } - greeting* readGreeting() - { + greeting* readGreeting() { + size_t pos = 0; string line = readLine(); greeting* greet = get (line, &pos); - if (!greet) + if (!greet) { throw exceptions::invalid_response("", m_errorResponseLine); + } greet->setErrorLog(lastLine()); @@ -5659,8 +5700,8 @@ public: * @return a raw pointer to the parsed token, or NULL otherwise */ template - TYPE* get(string& line, size_t* currentPos) - { + TYPE* get(string& line, size_t* currentPos) { + component* resp = new TYPE; return internalGet (resp, line, currentPos); } @@ -5680,9 +5721,8 @@ public: * @return a raw pointer to the parsed token, or NULL otherwise */ template - TYPE* getWithArgs(string& line, size_t* currentPos, - ARG1_TYPE arg1, ARG2_TYPE arg2) - { + TYPE* getWithArgs(string& line, size_t* currentPos, ARG1_TYPE arg1, ARG2_TYPE arg2) { + component* resp = new TYPE(arg1, arg2); return internalGet (resp, line, currentPos); } @@ -5690,15 +5730,15 @@ public: private: template - TYPE* internalGet(component* resp, string& line, size_t* currentPos) - { + TYPE* internalGet(component* resp, string& line, size_t* currentPos) { + const size_t oldPos = *currentPos; - if (!resp->parse(*this, line, currentPos)) - { + if (!resp->parse(*this, line, currentPos)) { + *currentPos = oldPos; - delete (resp); + delete resp; return NULL; } @@ -5706,20 +5746,21 @@ private: return static_cast (resp); } - const string lastLine() const - { + const string lastLine() const { + // Remove blanks and new lines at the end of the line. string line(m_lastLine); string::const_iterator it = line.end(); int count = 0; - while (it != line.begin()) - { + while (it != line.begin()) { + const unsigned char c = *(it - 1); - if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) + if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) { break; + } ++count; --it; @@ -5741,19 +5782,16 @@ public: * @return true if the token has been parsed, or false otherwise */ template - bool check(string& line, size_t* currentPos) - { + bool check(string& line, size_t* currentPos) { + const size_t oldPos = *currentPos; TYPE term; - if (!term.parse(*this, line, currentPos)) - { + if (!term.parse(*this, line, currentPos)) { *currentPos = oldPos; return false; - } - else - { + } else { return true; } } @@ -5769,19 +5807,16 @@ public: * @return true if the token has been parsed, or false otherwise */ template - bool checkWithArg(string& line, size_t* currentPos, const ARG_TYPE arg) - { + bool checkWithArg(string& line, size_t* currentPos, const ARG_TYPE arg) { + const size_t oldPos = *currentPos; TYPE term(arg); - if (!term.parse(*this, line, currentPos)) - { + if (!term.parse(*this, line, currentPos)) { *currentPos = oldPos; return false; - } - else - { + } else { return true; } } @@ -5815,12 +5850,11 @@ public: * * @return next line */ - const string readLine() - { + const string readLine() { + size_t pos; - while ((pos = m_buffer.find('\n')) == string::npos) - { + while ((pos = m_buffer.find('\n')) == string::npos) { read(); } @@ -5836,8 +5870,7 @@ public: std::cout << std::endl << "Read line:" << std::endl << line << std::endl; #endif - if (m_tracer) - { + if (m_tracer) { string::size_type len = line.length(); while (len != 0 && (line[len - 1] == '\r' || line[len - 1] == '\n')) --len; m_tracer->traceReceive(line.substr(0, len)); @@ -5849,84 +5882,90 @@ public: /** Fill in the input buffer with data available from the socket stream. * The function blocks until some data is available. */ - void read() - { + void read() { + string receiveBuffer; shared_ptr toh = m_timeoutHandler.lock(); shared_ptr sok = m_socket.lock(); - if (toh) + if (toh) { toh->resetTimeOut(); + } + + while (receiveBuffer.empty()) { - while (receiveBuffer.empty()) - { // Check whether the time-out delay is elapsed - if (toh && toh->isTimeOut()) - { - if (!toh->handleTimeOut()) + if (toh && toh->isTimeOut()) { + if (!toh->handleTimeOut()) { throw exceptions::operation_timed_out(); + } } // We have received data: reset the time-out counter sok->receive(receiveBuffer); - if (receiveBuffer.empty()) // buffer is empty - { - if (sok->getStatus() & socket::STATUS_WANT_WRITE) + if (receiveBuffer.empty()) { // buffer is empty + + if (sok->getStatus() & socket::STATUS_WANT_WRITE) { sok->waitForWrite(); - else + } else { sok->waitForRead(); + } continue; } // We have received data ... - if (toh) + if (toh) { toh->resetTimeOut(); + } } m_buffer += receiveBuffer; } - void readLiteral(literalHandler::target& buffer, size_t count) - { + void readLiteral(literalHandler::target& buffer, size_t count) { + size_t len = 0; string receiveBuffer; shared_ptr toh = m_timeoutHandler.lock(); shared_ptr sok = m_socket.lock(); - if (m_progress) + if (m_progress) { m_progress->start(count); + } - if (toh) + if (toh) { toh->resetTimeOut(); + } + + if (!m_buffer.empty()) { + + if (m_buffer.length() > count) { - if (!m_buffer.empty()) - { - if (m_buffer.length() > count) - { buffer.putData(string(m_buffer.begin(), m_buffer.begin() + count)); m_buffer.erase(m_buffer.begin(), m_buffer.begin() + count); len = count; - } - else - { + + } else { + len += m_buffer.length(); buffer.putData(m_buffer); m_buffer.clear(); } } - while (len < count) - { + while (len < count) { + // Check whether the time-out delay is elapsed - if (toh && toh->isTimeOut()) - { - if (!toh->handleTimeOut()) + if (toh && toh->isTimeOut()) { + + if (!toh->handleTimeOut()) { throw exceptions::operation_timed_out(); + } toh->resetTimeOut(); } @@ -5934,22 +5973,24 @@ public: // Receive data from the socket sok->receive(receiveBuffer); - if (receiveBuffer.empty()) // buffer is empty - { - if (sok->getStatus() & socket::STATUS_WANT_WRITE) + if (receiveBuffer.empty()) { // buffer is empty + + if (sok->getStatus() & socket::STATUS_WANT_WRITE) { sok->waitForWrite(); - else + } else { sok->waitForRead(); + } continue; } // We have received data: reset the time-out counter - if (toh) + if (toh) { toh->resetTimeOut(); + } + + if (len + receiveBuffer.length() > count) { - if (len + receiveBuffer.length() > count) - { const size_t remaining = count - len; // Get the needed amount of data @@ -5960,23 +6001,26 @@ public: m_buffer += receiveBuffer; len = count; - } - else - { + + } else { + buffer.putData(receiveBuffer); len += receiveBuffer.length(); } // Notify progress - if (m_progress) + if (m_progress) { m_progress->progress(len, count); + } } - if (m_tracer) + if (m_tracer) { m_tracer->traceReceiveBytes(count); + } - if (m_progress) + if (m_progress) { m_progress->stop(count); + } } }; diff --git a/src/vmime/net/imap/IMAPSStore.cpp b/src/vmime/net/imap/IMAPSStore.cpp index f70c0915..dd9c318a 100644 --- a/src/vmime/net/imap/IMAPSStore.cpp +++ b/src/vmime/net/imap/IMAPSStore.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,19 +35,22 @@ namespace net { namespace imap { -IMAPSStore::IMAPSStore(const shared_ptr & sess, const shared_ptr & auth) - : IMAPStore(sess, auth, true) -{ +IMAPSStore::IMAPSStore( + const shared_ptr & sess, + const shared_ptr & auth +) + : IMAPStore(sess, auth, true) { + } -IMAPSStore::~IMAPSStore() -{ +IMAPSStore::~IMAPSStore() { + } -const string IMAPSStore::getProtocolName() const -{ +const string IMAPSStore::getProtocolName() const { + return "imaps"; } @@ -58,14 +61,14 @@ const string IMAPSStore::getProtocolName() const IMAPServiceInfos IMAPSStore::sm_infos(true); -const serviceInfos& IMAPSStore::getInfosInstance() -{ +const serviceInfos& IMAPSStore::getInfosInstance() { + return sm_infos; } -const serviceInfos& IMAPSStore::getInfos() const -{ +const serviceInfos& IMAPSStore::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/imap/IMAPSStore.hpp b/src/vmime/net/imap/IMAPSStore.hpp index 8d6896d7..e18a067f 100644 --- a/src/vmime/net/imap/IMAPSStore.hpp +++ b/src/vmime/net/imap/IMAPSStore.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,9 +41,8 @@ namespace imap { /** IMAPS store service. */ +class VMIME_EXPORT IMAPSStore : public IMAPStore { -class VMIME_EXPORT IMAPSStore : public IMAPStore -{ public: IMAPSStore(const shared_ptr & sess, const shared_ptr & auth); diff --git a/src/vmime/net/imap/IMAPServiceInfos.cpp b/src/vmime/net/imap/IMAPServiceInfos.cpp index 46dbc2e1..baed6ba2 100644 --- a/src/vmime/net/imap/IMAPServiceInfos.cpp +++ b/src/vmime/net/imap/IMAPServiceInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,24 +36,24 @@ namespace imap { IMAPServiceInfos::IMAPServiceInfos(const bool imaps) - : m_imaps(imaps) -{ + : m_imaps(imaps) { + } -const string IMAPServiceInfos::getPropertyPrefix() const -{ - if (m_imaps) +const string IMAPServiceInfos::getPropertyPrefix() const { + + if (m_imaps) { return "store.imaps."; - else + } else { return "store.imap."; + } } -const IMAPServiceInfos::props& IMAPServiceInfos::getProperties() const -{ - static props imapProps = - { +const IMAPServiceInfos::props& IMAPServiceInfos::getProperties() const { + + static props imapProps = { // IMAP-specific options #if VMIME_HAVE_SASL_SUPPORT property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"), @@ -73,8 +73,7 @@ const IMAPServiceInfos::props& IMAPServiceInfos::getProperties() const property(serviceInfos::property::SERVER_PORT, "143"), }; - static props imapsProps = - { + static props imapsProps = { // IMAP-specific options #if VMIME_HAVE_SASL_SUPPORT property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"), @@ -98,8 +97,8 @@ const IMAPServiceInfos::props& IMAPServiceInfos::getProperties() const } -const std::vector IMAPServiceInfos::getAvailableProperties() const -{ +const std::vector IMAPServiceInfos::getAvailableProperties() const { + std::vector list; const props& p = getProperties(); @@ -114,8 +113,7 @@ const std::vector IMAPServiceInfos::getAvailablePropert list.push_back(p.PROPERTY_AUTH_PASSWORD); #if VMIME_HAVE_TLS_SUPPORT - if (!m_imaps) - { + if (!m_imaps) { list.push_back(p.PROPERTY_CONNECTION_TLS); list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED); } diff --git a/src/vmime/net/imap/IMAPServiceInfos.hpp b/src/vmime/net/imap/IMAPServiceInfos.hpp index 376f4476..73fca7a0 100644 --- a/src/vmime/net/imap/IMAPServiceInfos.hpp +++ b/src/vmime/net/imap/IMAPServiceInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,15 +41,13 @@ namespace imap { /** Information about IMAP service. */ +class VMIME_EXPORT IMAPServiceInfos : public serviceInfos { -class VMIME_EXPORT IMAPServiceInfos : public serviceInfos -{ public: IMAPServiceInfos(const bool imaps); - struct props - { + struct props { // IMAP-specific options #if VMIME_HAVE_SASL_SUPPORT serviceInfos::property PROPERTY_OPTIONS_SASL; diff --git a/src/vmime/net/imap/IMAPStore.cpp b/src/vmime/net/imap/IMAPStore.cpp index 7abfe8ae..c10e158d 100644 --- a/src/vmime/net/imap/IMAPStore.cpp +++ b/src/vmime/net/imap/IMAPStore.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,130 +44,148 @@ namespace net { namespace imap { -IMAPStore::IMAPStore(const shared_ptr & sess, const shared_ptr & auth, const bool secured) - : store(sess, getInfosInstance(), auth), m_connection(null), m_isIMAPS(secured) -{ +IMAPStore::IMAPStore( + const shared_ptr & sess, + const shared_ptr & auth, + const bool secured +) + : store(sess, getInfosInstance(), auth), + m_connection(null), + m_isIMAPS(secured) { + } -IMAPStore::~IMAPStore() -{ - try - { - if (isConnected()) +IMAPStore::~IMAPStore() { + + try { + + if (isConnected()) { disconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -const string IMAPStore::getProtocolName() const -{ +const string IMAPStore::getProtocolName() const { + return "imap"; } -shared_ptr IMAPStore::getRootFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); +shared_ptr IMAPStore::getRootFolder() { - return shared_ptr - (new IMAPFolder(folder::path(), - dynamicCast (shared_from_this()), - shared_ptr ())); + if (!isConnected()) { + throw exceptions::illegal_state("Not connected"); + } + + return make_shared ( + folder::path(), + dynamicCast (shared_from_this()), + shared_ptr () + ); } -shared_ptr IMAPStore::getDefaultFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); +shared_ptr IMAPStore::getDefaultFolder() { - return shared_ptr - (new IMAPFolder(folder::path::component("INBOX"), - dynamicCast (shared_from_this()), - shared_ptr ())); + if (!isConnected()) { + throw exceptions::illegal_state("Not connected"); + } + + return make_shared ( + folder::path::component("INBOX"), + dynamicCast (shared_from_this()), + shared_ptr () + ); } -shared_ptr IMAPStore::getFolder(const folder::path& path) -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); +shared_ptr IMAPStore::getFolder(const folder::path& path) { - return shared_ptr - (new IMAPFolder(path, - dynamicCast (shared_from_this()), - shared_ptr ())); + if (!isConnected()) { + throw exceptions::illegal_state("Not connected"); + } + + return make_shared ( + path, + dynamicCast (shared_from_this()), + shared_ptr () + ); } -bool IMAPStore::isValidFolderName(const folder::path::component& /* name */) const -{ +bool IMAPStore::isValidFolderName(const folder::path::component& /* name */) const { + return true; } -void IMAPStore::connect() -{ - if (isConnected()) - throw exceptions::already_connected(); +void IMAPStore::connect() { - m_connection = make_shared - (dynamicCast (shared_from_this()), getAuthenticator()); + if (isConnected()) { + throw exceptions::already_connected(); + } + + m_connection = make_shared ( + dynamicCast (shared_from_this()), getAuthenticator() + ); m_connection->connect(); } -bool IMAPStore::isConnected() const -{ - return (m_connection && m_connection->isConnected()); +bool IMAPStore::isConnected() const { + + return m_connection && m_connection->isConnected(); } -bool IMAPStore::isIMAPS() const -{ +bool IMAPStore::isIMAPS() const { + return m_isIMAPS; } -bool IMAPStore::isSecuredConnection() const -{ - if (m_connection == NULL) +bool IMAPStore::isSecuredConnection() const { + + if (!m_connection) { return false; + } return m_connection->isSecuredConnection(); } -shared_ptr IMAPStore::getConnectionInfos() const -{ - if (m_connection == NULL) +shared_ptr IMAPStore::getConnectionInfos() const { + + if (!m_connection) { return null; + } return m_connection->getConnectionInfos(); } -shared_ptr IMAPStore::getConnection() -{ +shared_ptr IMAPStore::getConnection() { + return m_connection; } -void IMAPStore::disconnect() -{ - if (!isConnected()) +void IMAPStore::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } for (std::list ::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { + it != m_folders.end() ; ++it) { + (*it)->onStoreDisconnected(); } @@ -180,60 +198,65 @@ void IMAPStore::disconnect() } -void IMAPStore::noop() -{ - if (!isConnected()) +void IMAPStore::noop() { + + if (!isConnected()) { throw exceptions::not_connected(); + } IMAPCommand::NOOP()->send(m_connection); scoped_ptr resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + throw exceptions::command_error("NOOP", resp->getErrorLog()); } for (std::list ::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { - if ((*it)->isOpen()) + it != m_folders.end() ; ++it) { + + if ((*it)->isOpen()) { (*it)->noop(); + } } } -shared_ptr IMAPStore::connection() -{ - return (m_connection); +shared_ptr IMAPStore::connection() { + + return m_connection; } -void IMAPStore::registerFolder(IMAPFolder* folder) -{ +void IMAPStore::registerFolder(IMAPFolder* folder) { + m_folders.push_back(folder); } -void IMAPStore::unregisterFolder(IMAPFolder* folder) -{ +void IMAPStore::unregisterFolder(IMAPFolder* folder) { + std::list ::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); - if (it != m_folders.end()) m_folders.erase(it); + + if (it != m_folders.end()) { + m_folders.erase(it); + } } -int IMAPStore::getCapabilities() const -{ - return (CAPABILITY_CREATE_FOLDER | - CAPABILITY_RENAME_FOLDER | - CAPABILITY_ADD_MESSAGE | - CAPABILITY_COPY_MESSAGE | - CAPABILITY_DELETE_MESSAGE | - CAPABILITY_PARTIAL_FETCH | - CAPABILITY_MESSAGE_FLAGS | - CAPABILITY_EXTRACT_PART); +int IMAPStore::getCapabilities() const { + + return CAPABILITY_CREATE_FOLDER | + CAPABILITY_RENAME_FOLDER | + CAPABILITY_ADD_MESSAGE | + CAPABILITY_COPY_MESSAGE | + CAPABILITY_DELETE_MESSAGE | + CAPABILITY_PARTIAL_FETCH | + CAPABILITY_MESSAGE_FLAGS | + CAPABILITY_EXTRACT_PART; } @@ -243,14 +266,14 @@ int IMAPStore::getCapabilities() const IMAPServiceInfos IMAPStore::sm_infos(false); -const serviceInfos& IMAPStore::getInfosInstance() -{ +const serviceInfos& IMAPStore::getInfosInstance() { + return sm_infos; } -const serviceInfos& IMAPStore::getInfos() const -{ +const serviceInfos& IMAPStore::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/imap/IMAPStore.hpp b/src/vmime/net/imap/IMAPStore.hpp index 80932af4..018c195e 100644 --- a/src/vmime/net/imap/IMAPStore.hpp +++ b/src/vmime/net/imap/IMAPStore.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -51,16 +51,20 @@ class IMAPFolder; /** IMAP store service. */ +class VMIME_EXPORT IMAPStore : public store { -class VMIME_EXPORT IMAPStore : public store -{ friend class IMAPFolder; friend class IMAPMessage; friend class IMAPConnection; public: - IMAPStore(const shared_ptr & sess, const shared_ptr & auth, const bool secured = false); + IMAPStore( + const shared_ptr & sess, + const shared_ptr & auth, + const bool secured = false + ); + ~IMAPStore(); const string getProtocolName() const; diff --git a/src/vmime/net/imap/IMAPTag.cpp b/src/vmime/net/imap/IMAPTag.cpp index 14d12788..69f48477 100644 --- a/src/vmime/net/imap/IMAPTag.cpp +++ b/src/vmime/net/imap/IMAPTag.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,70 +39,72 @@ const int IMAPTag::sm_maxNumber = 52 * 10 * 10 * 10; IMAPTag::IMAPTag(const int number) - : m_number(number) -{ + : m_number(number) { + m_tag.resize(4); generate(); } IMAPTag::IMAPTag(const IMAPTag& tag) - : object(), m_number(tag.m_number) -{ + : object(), + m_number(tag.m_number) { + m_tag.resize(4); generate(); } IMAPTag::IMAPTag() - : m_number(1) -{ + : m_number(1) { + m_tag.resize(4); generate(); } -IMAPTag& IMAPTag::operator++() -{ +IMAPTag& IMAPTag::operator++() { + ++m_number; - if (m_number >= sm_maxNumber) + if (m_number >= sm_maxNumber) { m_number = 1; + } generate(); - return (*this); + return *this; } -const IMAPTag IMAPTag::operator++(int) -{ +const IMAPTag IMAPTag::operator++(int) { + IMAPTag old(*this); operator++(); - return (old); + return old; } -int IMAPTag::maximumNumber() const -{ +int IMAPTag::maximumNumber() const { + return sm_maxNumber - 1; } -int IMAPTag::number() const -{ - return (m_number); +int IMAPTag::number() const { + + return m_number; } IMAPTag::operator string() const { - return (m_tag); + return m_tag; } -void IMAPTag::generate() -{ +void IMAPTag::generate() { + static const char prefixChars[53] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; diff --git a/src/vmime/net/imap/IMAPTag.hpp b/src/vmime/net/imap/IMAPTag.hpp index 430a3b10..d4292fde 100644 --- a/src/vmime/net/imap/IMAPTag.hpp +++ b/src/vmime/net/imap/IMAPTag.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,8 +39,8 @@ namespace net { namespace imap { -class VMIME_EXPORT IMAPTag : public object -{ +class VMIME_EXPORT IMAPTag : public object { + private: IMAPTag(const int number); diff --git a/src/vmime/net/imap/IMAPUtils.cpp b/src/vmime/net/imap/IMAPUtils.cpp index bffc2c78..353fc2da 100644 --- a/src/vmime/net/imap/IMAPUtils.cpp +++ b/src/vmime/net/imap/IMAPUtils.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,8 +44,8 @@ namespace imap { // static -const string IMAPUtils::quoteString(const string& text) -{ +const string IMAPUtils::quoteString(const string& text) { + // // ATOM_CHAR ::= // @@ -66,66 +66,70 @@ const string IMAPUtils::quoteString(const string& text) bool needQuoting = text.empty(); for (string::const_iterator it = text.begin() ; - !needQuoting && it != text.end() ; ++it) - { + !needQuoting && it != text.end() ; ++it) { + const unsigned char c = *it; - switch (c) - { - case '(': - case ')': - case '{': - case 0x20: // SPACE - case '%': - case '*': - case '"': - case '\\': + switch (c) { - needQuoting = true; - break; + case '(': + case ')': + case '{': + case 0x20: // SPACE + case '%': + case '*': + case '"': + case '\\': - default: - - if (c <= 0x1f || c >= 0x7f) needQuoting = true; - } + break; + + default: + + if (c <= 0x1f || c >= 0x7f) { + needQuoting = true; + } + } } - if (needQuoting) - { + if (needQuoting) { + string quoted; quoted.reserve((text.length() * 3) / 2 + 2); quoted += '"'; - for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) - { + for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) { + const unsigned char c = *it; - if (c == '\\' || c == '"') + if (c == '\\' || c == '"') { quoted += '\\'; + } quoted += c; } quoted += '"'; - return (quoted); - } - else - { - return (text); + return quoted; + + } else { + + return text; } } -const string IMAPUtils::pathToString - (const char hierarchySeparator, const folder::path& path) -{ +const string IMAPUtils::pathToString( + const char hierarchySeparator, + const folder::path& path +) { + string result; - for (size_t i = 0 ; i < path.getSize() ; ++i) - { + for (size_t i = 0 ; i < path.getSize() ; ++i) { + if (i > 0) result += hierarchySeparator; result += toModifiedUTF7(hierarchySeparator, path[i]); } @@ -134,33 +138,35 @@ const string IMAPUtils::pathToString } -const folder::path IMAPUtils::stringToPath - (const char hierarchySeparator, const string& str) -{ +const folder::path IMAPUtils::stringToPath( + const char hierarchySeparator, + const string& str +) { + folder::path result; string::const_iterator begin = str.begin(); - for (string::const_iterator it = str.begin() ; it != str.end() ; ++it) - { - if (*it == hierarchySeparator) - { + for (string::const_iterator it = str.begin() ; it != str.end() ; ++it) { + + if (*it == hierarchySeparator) { result /= fromModifiedUTF7(string(begin, it)); begin = it + 1; } } - if (begin != str.end()) - { + if (begin != str.end()) { result /= fromModifiedUTF7(string(begin, str.end())); } - return (result); + return result; } -const string IMAPUtils::toModifiedUTF7 - (const char hierarchySeparator, const folder::path::component& text) -{ +const string IMAPUtils::toModifiedUTF7( + const char hierarchySeparator, + const folder::path::component& text +) { + // We will replace the hierarchy separator with an equivalent // UTF-7 sequence, so we compute it here... const char base64alphabet[] = @@ -192,13 +198,13 @@ const string IMAPUtils::toModifiedUTF7 size_t remaining = cvt.length(); - for (size_t i = 0, len = cvt.length() ; i < len ; ) - { + for (size_t i = 0, len = cvt.length() ; i < len ; ) { + const unsigned char c = cvt[i]; // Replace hierarchy separator with an equivalent UTF-7 Base64 sequence - if (!base64 && c == hierarchySeparator) - { + if (!base64 && c == hierarchySeparator) { + out += "&" + hsUTF7 + "-"; ++i; @@ -209,72 +215,78 @@ const string IMAPUtils::toModifiedUTF7 size_t n = 0; int ch = 0; - if (c < 0x80) + if (c < 0x80) { ch = c, n = 0; - else if (c < 0xc2) + } else if (c < 0xc2) { return ""; - else if (c < 0xe0) + } else if (c < 0xe0) { ch = c & 0x1f, n = 1; - else if (c < 0xf0) + } else if (c < 0xf0) { ch = c & 0x0f, n = 2; - else if (c < 0xf8) + } else if (c < 0xf8) { ch = c & 0x07, n = 3; - else if (c < 0xfc) + } else if (c < 0xfc) { ch = c & 0x03, n = 4; - else if (c < 0xfe) + } else if (c < 0xfe) { ch = c & 0x01, n = 5; - else + } else { return ""; + } - if (n > remaining) + if (n > remaining) { return ""; // error + } ++i; --remaining; - for (size_t j = 0 ; j < n ; j++) - { - if ((cvt[i + j] & 0xc0) != 0x80) + for (size_t j = 0 ; j < n ; j++) { + + if ((cvt[i + j] & 0xc0) != 0x80) { return ""; // error + } ch = (ch << 6) | (cvt[i + j] & 0x3f); } - if (n > 1 && !(ch >> (n * 5 + 1))) + if (n > 1 && !(ch >> (n * 5 + 1))) { return ""; // error + } i += n; remaining -= n; - if (ch < 0x20 || ch >= 0x7f) - { - if (!base64) - { + if (ch < 0x20 || ch >= 0x7f) { + + if (!base64) { out += '&'; base64 = true; b = 0; k = 10; } - if (ch & ~0xffff) + if (ch & ~0xffff) { ch = 0xfffe; + } out += base64alphabet[b | ch >> k]; k -= 6; - for ( ; k >= 0 ; k -= 6) + for ( ; k >= 0 ; k -= 6) { out += base64alphabet[(ch >> k) & 0x3f]; + } b = (ch << (-k)) & 0x3f; k += 16; - } - else - { - if (base64) - { - if (k > 10) + + } else { + + if (base64) { + + if (k > 10) { out += base64alphabet[b]; + } out += '-'; base64 = false; @@ -282,15 +294,17 @@ const string IMAPUtils::toModifiedUTF7 out += static_cast (ch); - if (ch == '&') + if (ch == '&') { out += '-'; + } } } - if (base64) - { - if (k > 10) + if (base64) { + + if (k > 10) { out += base64alphabet[b]; + } out += '-'; } @@ -299,8 +313,8 @@ const string IMAPUtils::toModifiedUTF7 } -const folder::path::component IMAPUtils::fromModifiedUTF7(const string& text) -{ +const folder::path::component IMAPUtils::fromModifiedUTF7(const string& text) { + // Transcode from modified UTF-7 (RFC-2060). string out; out.reserve(text.length()); @@ -309,62 +323,57 @@ const folder::path::component IMAPUtils::fromModifiedUTF7(const string& text) bool plusOutput = false; unsigned char prev = 0; - for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) - { + for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) { + const unsigned char c = *it; - switch (c) - { - // Start of Base64 sequence - case '&': - { - if (!inB64sequence) - { - inB64sequence = true; - plusOutput = false; + switch (c) { + + // Start of Base64 sequence + case '&': { + + if (!inB64sequence) { + inB64sequence = true; + plusOutput = false; + } else { + out += '&'; + } + + break; } - else - { - out += '&'; + // End of Base64 sequence (or "&-" --> "&") + case '-': { + + if (inB64sequence && prev == '&') { // special case "&-" --> "&" + out += '&'; + } else { + out += '-'; + } + + inB64sequence = false; + break; } + // ',' is used instead of '/' in modified Base64 + case ',': { - break; - } - // End of Base64 sequence (or "&-" --> "&") - case '-': - { - if (inB64sequence && prev == '&') // special case "&-" --> "&" - out += '&'; - else - out += '-'; + if (inB64sequence && !plusOutput) { + out += '+'; + plusOutput = true; + } - inB64sequence = false; - break; - } - // ',' is used instead of '/' in modified Base64 - case ',': - { - if (inB64sequence && !plusOutput) - { - out += '+'; - plusOutput = true; + out += (inB64sequence ? '/' : ','); + break; } + default: { - out += (inB64sequence ? '/' : ','); - break; - } - default: - { - if (inB64sequence && !plusOutput) - { - out += '+'; - plusOutput = true; + if (inB64sequence && !plusOutput) { + out += '+'; + plusOutput = true; + } + + out += c; + break; } - - out += c; - break; - } - } prev = c; @@ -372,94 +381,96 @@ const folder::path::component IMAPUtils::fromModifiedUTF7(const string& text) // Store it as UTF-8 by default string cvt; - charset::convert(out, cvt, - charset(charsets::UTF_7), charset(charsets::UTF_8)); + charset::convert(out, cvt, charset(charsets::UTF_7), charset(charsets::UTF_8)); - return (folder::path::component(cvt, charset(charsets::UTF_8))); + return folder::path::component(cvt, charset(charsets::UTF_8)); } // static -void IMAPUtils::mailboxFlagsToFolderAttributes - (const shared_ptr & cnt, const IMAPParser::mailbox_flag_list* list, - folderAttributes& attribs) -{ +void IMAPUtils::mailboxFlagsToFolderAttributes( + const shared_ptr & cnt, + const IMAPParser::mailbox_flag_list* list, + folderAttributes& attribs +) { + int specialUse = folderAttributes::SPECIALUSE_NONE; int type = folderAttributes::TYPE_CONTAINS_MESSAGES | folderAttributes::TYPE_CONTAINS_FOLDERS; int flags = 0; // If CHILDREN extension (RFC-3348) is not supported, assume folder has children // as we have no hint about it - if (!cnt->hasCapability("CHILDREN")) + if (!cnt->hasCapability("CHILDREN")) { flags |= folderAttributes::FLAG_HAS_CHILDREN; + } const std::vector & mailboxFlags = list->flags(); for (std::vector ::const_iterator it = mailboxFlags.begin() ; - it != mailboxFlags.end() ; ++it) - { - switch ((*it)->type()) - { - case IMAPParser::mailbox_flag::NOSELECT: + it != mailboxFlags.end() ; ++it) { - type &= ~folderAttributes::TYPE_CONTAINS_MESSAGES; - flags |= folderAttributes::FLAG_NO_OPEN; - break; + switch ((*it)->type()) { - case IMAPParser::mailbox_flag::NOINFERIORS: - case IMAPParser::mailbox_flag::HASNOCHILDREN: + case IMAPParser::mailbox_flag::NOSELECT: - flags &= ~folderAttributes::FLAG_HAS_CHILDREN; - break; + type &= ~folderAttributes::TYPE_CONTAINS_MESSAGES; + flags |= folderAttributes::FLAG_NO_OPEN; + break; - case IMAPParser::mailbox_flag::HASCHILDREN: + case IMAPParser::mailbox_flag::NOINFERIORS: + case IMAPParser::mailbox_flag::HASNOCHILDREN: - flags |= folderAttributes::FLAG_HAS_CHILDREN; - break; + flags &= ~folderAttributes::FLAG_HAS_CHILDREN; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_ALL: + case IMAPParser::mailbox_flag::HASCHILDREN: - specialUse = folderAttributes::SPECIALUSE_ALL; - break; + flags |= folderAttributes::FLAG_HAS_CHILDREN; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_ARCHIVE: + case IMAPParser::mailbox_flag::SPECIALUSE_ALL: - specialUse = folderAttributes::SPECIALUSE_ARCHIVE; - break; + specialUse = folderAttributes::SPECIALUSE_ALL; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_DRAFTS: + case IMAPParser::mailbox_flag::SPECIALUSE_ARCHIVE: - specialUse = folderAttributes::SPECIALUSE_DRAFTS; - break; + specialUse = folderAttributes::SPECIALUSE_ARCHIVE; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_FLAGGED: + case IMAPParser::mailbox_flag::SPECIALUSE_DRAFTS: - specialUse = folderAttributes::SPECIALUSE_FLAGGED; - break; + specialUse = folderAttributes::SPECIALUSE_DRAFTS; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_JUNK: + case IMAPParser::mailbox_flag::SPECIALUSE_FLAGGED: - specialUse = folderAttributes::SPECIALUSE_JUNK; - break; + specialUse = folderAttributes::SPECIALUSE_FLAGGED; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_SENT: + case IMAPParser::mailbox_flag::SPECIALUSE_JUNK: - specialUse = folderAttributes::SPECIALUSE_SENT; - break; + specialUse = folderAttributes::SPECIALUSE_JUNK; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_TRASH: + case IMAPParser::mailbox_flag::SPECIALUSE_SENT: - specialUse = folderAttributes::SPECIALUSE_TRASH; - break; + specialUse = folderAttributes::SPECIALUSE_SENT; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_IMPORTANT: + case IMAPParser::mailbox_flag::SPECIALUSE_TRASH: - specialUse = folderAttributes::SPECIALUSE_IMPORTANT; - break; + specialUse = folderAttributes::SPECIALUSE_TRASH; + break; - default: + case IMAPParser::mailbox_flag::SPECIALUSE_IMPORTANT: - break; + specialUse = folderAttributes::SPECIALUSE_IMPORTANT; + break; + + default: + + break; } } @@ -469,49 +480,60 @@ void IMAPUtils::mailboxFlagsToFolderAttributes } -int IMAPUtils::messageFlagsFromFlags(const IMAPParser::flag_list* list) -{ +int IMAPUtils::messageFlagsFromFlags(const IMAPParser::flag_list* list) { + const std::vector & flagList = list->flags(); int flags = 0; for (std::vector ::const_iterator - it = flagList.begin() ; it != flagList.end() ; ++it) - { - switch ((*it)->type()) - { - case IMAPParser::flag::ANSWERED: - flags |= message::FLAG_REPLIED; - break; - case IMAPParser::flag::FLAGGED: - flags |= message::FLAG_MARKED; - break; - case IMAPParser::flag::DELETED: - flags |= message::FLAG_DELETED; - break; - case IMAPParser::flag::SEEN: - flags |= message::FLAG_SEEN; - break; - case IMAPParser::flag::DRAFT: - flags |= message::FLAG_DRAFT; - break; + it = flagList.begin() ; it != flagList.end() ; ++it) { - default: - //case IMAPParser::flag::UNKNOWN: - break; + switch ((*it)->type()) { + + case IMAPParser::flag::ANSWERED: + + flags |= message::FLAG_REPLIED; + break; + + case IMAPParser::flag::FLAGGED: + + flags |= message::FLAG_MARKED; + break; + + case IMAPParser::flag::DELETED: + + flags |= message::FLAG_DELETED; + break; + + case IMAPParser::flag::SEEN: + + flags |= message::FLAG_SEEN; + break; + + case IMAPParser::flag::DRAFT: + + flags |= message::FLAG_DRAFT; + break; + + default: + //case IMAPParser::flag::UNKNOWN: + + break; } } - return (flags); + return flags; } // static -const std::vector IMAPUtils::messageFlagList(const int flags) -{ +const std::vector IMAPUtils::messageFlagList(const int flags) { + std::vector flagList; - if (flags == -1) + if (flags == -1) { return flagList; // default flags + } if (flags & message::FLAG_REPLIED) flagList.push_back("\\Answered"); if (flags & message::FLAG_MARKED) flagList.push_back("\\Flagged"); @@ -524,8 +546,8 @@ const std::vector IMAPUtils::messageFlagList(const int flags) // static -const string IMAPUtils::dateTime(const vmime::datetime& date) -{ +const string IMAPUtils::dateTime(const vmime::datetime& date) { + std::ostringstream res; res.imbue(std::locale::classic()); @@ -545,9 +567,10 @@ const string IMAPUtils::dateTime(const vmime::datetime& date) res << '-'; - static const char* monthNames[12] = - { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + static const char* monthNames[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; res << monthNames[std::min(std::max(date.getMonth() - 1, 0), 11)]; @@ -587,15 +610,17 @@ const string IMAPUtils::dateTime(const vmime::datetime& date) res << '"'; - - return (res.str()); + return res.str(); } // static -shared_ptr IMAPUtils::buildFetchCommand - (const shared_ptr & cnt, const messageSet& msgs, const fetchAttributes& options) -{ +shared_ptr IMAPUtils::buildFetchCommand( + const shared_ptr & cnt, + const messageSet& msgs, + const fetchAttributes& options +) { + // Example: // C: A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)]) // S: * 2 FETCH .... @@ -605,38 +630,45 @@ shared_ptr IMAPUtils::buildFetchCommand std::vector items; - if (options.has(fetchAttributes::SIZE)) + if (options.has(fetchAttributes::SIZE)) { items.push_back("RFC822.SIZE"); + } - if (options.has(fetchAttributes::FLAGS)) + if (options.has(fetchAttributes::FLAGS)) { items.push_back("FLAGS"); + } - if (options.has(fetchAttributes::STRUCTURE)) + if (options.has(fetchAttributes::STRUCTURE)) { items.push_back("BODYSTRUCTURE"); + } + + if (options.has(fetchAttributes::UID)) { - if (options.has(fetchAttributes::UID)) - { items.push_back("UID"); // Also fetch MODSEQ if CONDSTORE is supported - if (cnt && cnt->hasCapability("CONDSTORE") && !cnt->isMODSEQDisabled()) + if (cnt && cnt->hasCapability("CONDSTORE") && !cnt->isMODSEQDisabled()) { items.push_back("MODSEQ"); + } } - if (options.has(fetchAttributes::FULL_HEADER)) + if (options.has(fetchAttributes::FULL_HEADER)) { + items.push_back("RFC822.HEADER"); - else - { - if (options.has(fetchAttributes::ENVELOPE)) + + } else { + + if (options.has(fetchAttributes::ENVELOPE)) { items.push_back("ENVELOPE"); + } std::vector headerFields; - if (options.has(fetchAttributes::CONTENT_INFO)) + if (options.has(fetchAttributes::CONTENT_INFO)) { headerFields.push_back("CONTENT_TYPE"); + } - if (options.has(fetchAttributes::IMPORTANCE)) - { + if (options.has(fetchAttributes::IMPORTANCE)) { headerFields.push_back("IMPORTANCE"); headerFields.push_back("X-PRIORITY"); } @@ -645,15 +677,16 @@ shared_ptr IMAPUtils::buildFetchCommand const std::vector customHeaderFields = options.getHeaderFields(); std::copy(customHeaderFields.begin(), customHeaderFields.end(), std::back_inserter(headerFields)); - if (!headerFields.empty()) - { + if (!headerFields.empty()) { + string list; for (std::vector ::iterator it = headerFields.begin() ; - it != headerFields.end() ; ++it) - { - if (it != headerFields.begin()) + it != headerFields.end() ; ++it) { + + if (it != headerFields.begin()) { list += " "; + } list += *it; } @@ -667,12 +700,14 @@ shared_ptr IMAPUtils::buildFetchCommand // static -void IMAPUtils::convertAddressList - (const IMAPParser::address_list& src, mailboxList& dest) -{ +void IMAPUtils::convertAddressList( + const IMAPParser::address_list& src, + mailboxList& dest +) { + for (std::vector ::const_iterator - it = src.addresses().begin() ; it != src.addresses().end() ; ++it) - { + it = src.addresses().begin() ; it != src.addresses().end() ; ++it) { + const IMAPParser::address& addr = **it; text name; @@ -687,48 +722,52 @@ void IMAPUtils::convertAddressList -class IMAPUIDMessageSetEnumerator : public messageSetEnumerator -{ +class IMAPUIDMessageSetEnumerator : public messageSetEnumerator { + public: IMAPUIDMessageSetEnumerator() - : m_first(true) - { + : m_first(true) { + m_oss.imbue(std::locale::classic()); } - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { - if (!m_first) - m_oss << ","; + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) { - if (range.getFirst() == range.getLast()) + if (!m_first) { + m_oss << ","; + } + + if (range.getFirst() == range.getLast()) { m_oss << range.getFirst(); - else if (range.getLast() == size_t(-1)) + } else if (range.getLast() == size_t(-1)) { m_oss << range.getFirst() << ":*"; - else + } else { m_oss << range.getFirst() << ":" << range.getLast(); + } m_first = false; } - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& range) - { - if (!m_first) - m_oss << ","; + void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& range) { - if (range.getFirst() == range.getLast()) + if (!m_first) { + m_oss << ","; + } + + if (range.getFirst() == range.getLast()) { m_oss << range.getFirst(); - else if (range.getLast() == size_t(-1)) + } else if (range.getLast() == size_t(-1)) { m_oss << range.getFirst() << ":*"; - else + } else { m_oss << range.getFirst() << ":" << range.getLast(); + } m_first = false; } - const std::string str() const - { + const std::string str() const { + return m_oss.str(); } @@ -739,23 +778,24 @@ private: }; -class IMAPMessageSetEnumerator : public messageSetEnumerator -{ +class IMAPMessageSetEnumerator : public messageSetEnumerator { + public: - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { - for (size_t i = range.getFirst(), last = range.getLast() ; i <= last ; ++i) + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) { + + for (size_t i = range.getFirst(), last = range.getLast() ; i <= last ; ++i) { m_list.push_back(i); + } } - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) - { + void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) { + // Not used } - const std::vector & list() const - { + const std::vector & list() const { + return m_list; } @@ -767,8 +807,8 @@ public: // static -const string IMAPUtils::messageSetToSequenceSet(const messageSet& msgs) -{ +const string IMAPUtils::messageSetToSequenceSet(const messageSet& msgs) { + IMAPUIDMessageSetEnumerator en; msgs.enumerate(en); @@ -777,22 +817,28 @@ const string IMAPUtils::messageSetToSequenceSet(const messageSet& msgs) // static -messageSet IMAPUtils::buildMessageSet(const IMAPParser::uid_set* uidSet) -{ +messageSet IMAPUtils::buildMessageSet(const IMAPParser::uid_set* uidSet) { + messageSet set = messageSet::empty(); - for ( ; uidSet ; uidSet = uidSet->next_uid_set()) - { - if (uidSet->uid_range()) - { - set.addRange(UIDMessageRange - (message::uid(uidSet->uid_range()->uniqueid1()->value()), - message::uid(uidSet->uid_range()->uniqueid2()->value()))); - } - else - { - set.addRange(UIDMessageRange - (message::uid(uidSet->uniqueid()->value()))); + for ( ; uidSet ; uidSet = uidSet->next_uid_set()) { + + if (uidSet->uid_range()) { + + set.addRange( + UIDMessageRange( + message::uid(uidSet->uid_range()->uniqueid1()->value()), + message::uid(uidSet->uid_range()->uniqueid2()->value()) + ) + ); + + } else { + + set.addRange( + UIDMessageRange( + message::uid(uidSet->uniqueid()->value()) + ) + ); } } diff --git a/src/vmime/net/imap/IMAPUtils.hpp b/src/vmime/net/imap/IMAPUtils.hpp index a7daf736..957ff846 100644 --- a/src/vmime/net/imap/IMAPUtils.hpp +++ b/src/vmime/net/imap/IMAPUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 diff --git a/src/vmime/net/imap/imap.hpp b/src/vmime/net/imap/imap.hpp index 5e10619a..f25baa4b 100644 --- a/src/vmime/net/imap/imap.hpp +++ b/src/vmime/net/imap/imap.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 diff --git a/src/vmime/net/maildir/format/courierMaildirFormat.cpp b/src/vmime/net/maildir/format/courierMaildirFormat.cpp index 78753796..e6119490 100644 --- a/src/vmime/net/maildir/format/courierMaildirFormat.cpp +++ b/src/vmime/net/maildir/format/courierMaildirFormat.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,33 +42,38 @@ namespace format { courierMaildirFormat::courierMaildirFormat(const shared_ptr & ctx) - : maildirFormat(ctx) -{ + : maildirFormat(ctx) { + } -const string courierMaildirFormat::getName() const -{ +const string courierMaildirFormat::getName() const { + return "courier"; } -void courierMaildirFormat::createFolder(const folder::path& path) -{ +void courierMaildirFormat::createFolder(const folder::path& path) { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) + if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) { throw exceptions::invalid_folder_name(); + } - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); + shared_ptr rootDir = fsf->create( + folderPathToFileSystemPath(path, ROOT_DIRECTORY) + ); - shared_ptr newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); + shared_ptr newDir = fsf->create( + folderPathToFileSystemPath(path, NEW_DIRECTORY) + ); + shared_ptr tmpDir = fsf->create( + folderPathToFileSystemPath(path, TMP_DIRECTORY) + ); + shared_ptr curDir = fsf->create( + folderPathToFileSystemPath(path, CUR_DIRECTORY) + ); rootDir->createDirectory(true); @@ -76,40 +81,45 @@ void courierMaildirFormat::createFolder(const folder::path& path) tmpDir->createDirectory(false); curDir->createDirectory(false); - shared_ptr maildirFile = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY) - / utility::file::path::component("maildirfolder")); + shared_ptr maildirFile = fsf->create( + folderPathToFileSystemPath(path, ROOT_DIRECTORY) + / utility::file::path::component("maildirfolder") + ); maildirFile->createFile(); } -void courierMaildirFormat::destroyFolder(const folder::path& path) -{ +void courierMaildirFormat::destroyFolder(const folder::path& path) { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); // Recursively delete directories of subfolders const std::vector folders = listFolders(path, true); - for (std::vector ::size_type i = 0, n = folders.size() ; i < n ; ++i) - { - maildirUtils::recursiveFSDelete(fsf->create - (folderPathToFileSystemPath(folders[i], ROOT_DIRECTORY))); + for (std::vector ::size_type i = 0, n = folders.size() ; i < n ; ++i) { + + maildirUtils::recursiveFSDelete( + fsf->create(folderPathToFileSystemPath(folders[i], ROOT_DIRECTORY)) + ); } // Recursively delete the directory of this folder - maildirUtils::recursiveFSDelete(fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY))); + maildirUtils::recursiveFSDelete( + fsf->create(folderPathToFileSystemPath(path, ROOT_DIRECTORY)) + ); } -void courierMaildirFormat::renameFolder - (const folder::path& oldPath, const folder::path& newPath) -{ +void courierMaildirFormat::renameFolder( + const folder::path& oldPath, + const folder::path& newPath +) { + const std::vector folders = listFolders(oldPath, true); - for (std::vector ::size_type i = 0, n = folders.size() ; i < n ; ++i) - { + for (std::vector ::size_type i = 0, n = folders.size() ; i < n ; ++i) { + const folder::path folderOldPath = folders[i]; folder::path folderNewPath = folderOldPath; @@ -122,9 +132,11 @@ void courierMaildirFormat::renameFolder } -void courierMaildirFormat::renameFolderImpl - (const folder::path& oldPath, const folder::path& newPath) -{ +void courierMaildirFormat::renameFolderImpl( + const folder::path& oldPath, + const folder::path& newPath +) { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); const utility::file::path oldFSPath = @@ -138,98 +150,109 @@ void courierMaildirFormat::renameFolderImpl } -bool courierMaildirFormat::folderExists(const folder::path& path) const -{ +bool courierMaildirFormat::folderExists(const folder::path& path) const { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); + shared_ptr rootDir = fsf->create( + folderPathToFileSystemPath(path, ROOT_DIRECTORY) + ); - shared_ptr newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); + shared_ptr newDir = fsf->create( + folderPathToFileSystemPath(path, NEW_DIRECTORY) + ); + shared_ptr tmpDir = fsf->create( + folderPathToFileSystemPath(path, TMP_DIRECTORY) + ); + shared_ptr curDir = fsf->create( + folderPathToFileSystemPath(path, CUR_DIRECTORY) + ); - shared_ptr maildirFile = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY) - / utility::file::path::component("maildirfolder")); + shared_ptr maildirFile = fsf->create( + folderPathToFileSystemPath(path, ROOT_DIRECTORY) + / utility::file::path::component("maildirfolder") + ); bool exists = rootDir->exists() && rootDir->isDirectory() && - newDir->exists() && newDir->isDirectory() && - tmpDir->exists() && tmpDir->isDirectory() && - curDir->exists() && curDir->isDirectory(); + newDir->exists() && newDir->isDirectory() && + tmpDir->exists() && tmpDir->isDirectory() && + curDir->exists() && curDir->isDirectory(); // If this is not the root folder, then a file named "maildirfolder" // must also be present in the directory - if (!path.isRoot()) + if (!path.isRoot()) { exists = exists && maildirFile->exists() && maildirFile->isFile(); + } return exists; } -bool courierMaildirFormat::folderHasSubfolders(const folder::path& path) const -{ +bool courierMaildirFormat::folderHasSubfolders(const folder::path& path) const { + std::vector dirs; return listDirectories(path, dirs, true); } -const utility::file::path courierMaildirFormat::folderPathToFileSystemPath - (const folder::path& path, const DirectoryType type) const -{ +const utility::file::path courierMaildirFormat::folderPathToFileSystemPath( + const folder::path& path, + const DirectoryType type +) const { + // Virtual folder "/MyFolder/SubFolder" corresponds to physical // directory "[store root]/.MyFolder.SubFolder" utility::file::path fsPath = getContext()->getStore()->getFileSystemPath(); - if (!path.isRoot()) - { + if (!path.isRoot()) { + string folderComp; - for (size_t i = 0, n = path.getSize() ; i < n ; ++i) + for (size_t i = 0, n = path.getSize() ; i < n ; ++i) { folderComp += "." + toModifiedUTF7(path[i]); + } fsPath /= utility::file::path::component(folderComp); } // Last component - switch (type) - { - case ROOT_DIRECTORY: + switch (type) { - // Nothing to add - break; + case ROOT_DIRECTORY: - case NEW_DIRECTORY: + // Nothing to add + break; - fsPath /= NEW_DIR; - break; + case NEW_DIRECTORY: - case CUR_DIRECTORY: + fsPath /= NEW_DIR; + break; - fsPath /= CUR_DIR; - break; + case CUR_DIRECTORY: - case TMP_DIRECTORY: + fsPath /= CUR_DIR; + break; - fsPath /= TMP_DIR; - break; + case TMP_DIRECTORY: - case CONTAINER_DIRECTORY: + fsPath /= TMP_DIR; + break; - // Not used - break; + case CONTAINER_DIRECTORY: + + // Not used + break; } return fsPath; } -const std::vector courierMaildirFormat::listFolders - (const folder::path& root, const bool recursive) const -{ +const std::vector courierMaildirFormat::listFolders( + const folder::path& root, + const bool recursive +) const { + // First, list directories std::vector dirs; listDirectories(root, dirs, false); @@ -237,69 +260,75 @@ const std::vector courierMaildirFormat::listFolders // Then, map directories to folders std::vector folders; - for (std::vector ::size_type i = 0, n = dirs.size() ; i < n ; ++i) - { + for (std::vector ::size_type i = 0, n = dirs.size() ; i < n ; ++i) { + const string dir = dirs[i].substr(1) + "."; folder::path path; for (size_t pos = dir.find("."), prev = 0 ; - pos != string::npos ; prev = pos + 1, pos = dir.find(".", pos + 1)) - { + pos != string::npos ; prev = pos + 1, pos = dir.find(".", pos + 1)) { + const string comp = dir.substr(prev, pos - prev); path /= fromModifiedUTF7(comp); } - if (recursive || path.getSize() == root.getSize() + 1) + if (recursive || path.getSize() == root.getSize() + 1) { folders.push_back(path); + } } return folders; } -bool courierMaildirFormat::listDirectories(const folder::path& root, - std::vector & dirs, const bool onlyTestForExistence) const -{ +bool courierMaildirFormat::listDirectories( + const folder::path& root, + std::vector & dirs, + const bool onlyTestForExistence +) const { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr rootDir = fsf->create - (getContext()->getStore()->getFileSystemPath()); + shared_ptr rootDir = fsf->create( + getContext()->getStore()->getFileSystemPath() + ); + + if (rootDir->exists()) { - if (rootDir->exists()) - { // To speed up things, and if we are not searching in root folder, // search for directories with a common prefix string base; - if (!root.isRoot()) - { - for (size_t i = 0, n = root.getSize() ; i < n ; ++i) + if (!root.isRoot()) { + for (size_t i = 0, n = root.getSize() ; i < n ; ++i) { base += "." + toModifiedUTF7(root[i]); + } } // Enumerate directories shared_ptr it = rootDir->getFiles(); - while (it->hasMoreElements()) - { + while (it->hasMoreElements()) { + shared_ptr file = it->nextElement(); - if (isSubfolderDirectory(*file)) - { + if (isSubfolderDirectory(*file)) { + const string dir = file->getFullPath().getLastComponent().getBuffer(); - if (base.empty() || (dir.length() > base.length() && dir.substr(0, base.length()) == base)) - { + if (base.empty() || (dir.length() > base.length() && dir.substr(0, base.length()) == base)) { + dirs.push_back(dir); - if (onlyTestForExistence) + if (onlyTestForExistence) { return true; + } } } } - } - else - { + + } else { + // No sub-folder } @@ -310,13 +339,13 @@ bool courierMaildirFormat::listDirectories(const folder::path& root, // static -bool courierMaildirFormat::isSubfolderDirectory(const utility::file& file) -{ +bool courierMaildirFormat::isSubfolderDirectory(const utility::file& file) { + // A directory which names starts with '.' may be a subfolder if (file.isDirectory() && file.getFullPath().getLastComponent().getBuffer().length() >= 1 && - file.getFullPath().getLastComponent().getBuffer()[0] == '.') - { + file.getFullPath().getLastComponent().getBuffer()[0] == '.') { + return true; } @@ -325,8 +354,8 @@ bool courierMaildirFormat::isSubfolderDirectory(const utility::file& file) // static -const string courierMaildirFormat::toModifiedUTF7(const folder::path::component& text) -{ +const string courierMaildirFormat::toModifiedUTF7(const folder::path::component& text) { + // From http://www.courier-mta.org/?maildir.html: // // Folder names can contain any Unicode character, except for control @@ -364,67 +393,65 @@ const string courierMaildirFormat::toModifiedUTF7(const folder::path::component& bool inB64sequence = false; - for (string::const_iterator it = cvt.begin() ; it != cvt.end() ; ++it) - { + for (string::const_iterator it = cvt.begin() ; it != cvt.end() ; ++it) { + const unsigned char c = *it; - switch (c) - { - // Beginning of Base64 sequence: replace '+' with '&' - case '+': - { - if (!inB64sequence) - { - inB64sequence = true; - out += '&'; + switch (c) { + + // Beginning of Base64 sequence: replace '+' with '&' + case '+': { + + if (!inB64sequence) { + inB64sequence = true; + out += '&'; + } else { + out += '+'; + } + + break; } - else - { - out += '+'; + // End of Base64 sequence + case '-': { + + inB64sequence = false; + out += '-'; + break; } + // ',' is used instead of '/' in modified Base64, + // and simply UTF7-encoded out of a Base64 sequence + case '/': { - break; - } - // End of Base64 sequence - case '-': - { - inB64sequence = false; - out += '-'; - break; - } - // ',' is used instead of '/' in modified Base64, - // and simply UTF7-encoded out of a Base64 sequence - case '/': - { - if (inB64sequence) - out += ','; - else - out += "&Lw-"; + if (inB64sequence) { + out += ','; + } else { + out += "&Lw-"; + } - break; - } - // Encode period (should not happen in a Base64 sequence) - case '.': - { - out += "&Lg-"; - break; - } - // '&' (0x26) is represented by the two-octet sequence "&-" - case '&': - { - if (!inB64sequence) - out += "&-"; - else - out += '&'; + break; + } + // Encode period (should not happen in a Base64 sequence) + case '.': { - break; - } - default: - { - out += c; - break; - } + out += "&Lg-"; + break; + } + // '&' (0x26) is represented by the two-octet sequence "&-" + case '&': { + if (!inB64sequence) { + out += "&-"; + } else { + out += '&'; + } + + break; + } + default: { + + out += c; + break; + } } } @@ -433,8 +460,8 @@ const string courierMaildirFormat::toModifiedUTF7(const folder::path::component& // static -const folder::path::component courierMaildirFormat::fromModifiedUTF7(const string& text) -{ +const folder::path::component courierMaildirFormat::fromModifiedUTF7(const string& text) { + // Transcode from modified UTF-7 string out; out.reserve(text.length()); @@ -442,49 +469,47 @@ const folder::path::component courierMaildirFormat::fromModifiedUTF7(const strin bool inB64sequence = false; unsigned char prev = 0; - for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) - { + for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) { + const unsigned char c = *it; - switch (c) - { - // Start of Base64 sequence - case '&': - { - if (!inB64sequence) - { - inB64sequence = true; - out += '+'; - } - else - { - out += '&'; - } + switch (c) { - break; - } - // End of Base64 sequence (or "&-" --> "&") - case '-': - { - if (inB64sequence && prev == '&') - out += '&'; - else - out += '-'; + // Start of Base64 sequence + case '&': { - inB64sequence = false; - break; - } - // ',' is used instead of '/' in modified Base64 - case ',': - { - out += (inB64sequence ? '/' : ','); - break; - } - default: - { - out += c; - break; - } + if (!inB64sequence) { + inB64sequence = true; + out += '+'; + } else { + out += '&'; + } + + break; + } + // End of Base64 sequence (or "&-" --> "&") + case '-': { + + if (inB64sequence && prev == '&') { + out += '&'; + } else { + out += '-'; + } + + inB64sequence = false; + break; + } + // ',' is used instead of '/' in modified Base64 + case ',': { + + out += (inB64sequence ? '/' : ','); + break; + } + default: { + + out += c; + break; + } } @@ -493,37 +518,39 @@ const folder::path::component courierMaildirFormat::fromModifiedUTF7(const strin // Store it as UTF-8 by default string cvt; - charset::convert(out, cvt, - charset(charsets::UTF_7), charset(charsets::UTF_8)); + charset::convert(out, cvt, charset(charsets::UTF_7), charset(charsets::UTF_8)); - return (folder::path::component(cvt, charset(charsets::UTF_8))); + return folder::path::component(cvt, charset(charsets::UTF_8)); } -bool courierMaildirFormat::supports() const -{ +bool courierMaildirFormat::supports() const { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr rootDir = fsf->create - (getContext()->getStore()->getFileSystemPath()); + shared_ptr rootDir = fsf->create( + getContext()->getStore()->getFileSystemPath() + ); + + if (rootDir->exists()) { - if (rootDir->exists()) - { // Try to find a file named "maildirfolder", which indicates // the Maildir is in Courier format shared_ptr it = rootDir->getFiles(); - while (it->hasMoreElements()) - { + while (it->hasMoreElements()) { + shared_ptr file = it->nextElement(); - if (isSubfolderDirectory(*file)) - { - shared_ptr folderFile = fsf->create - (file->getFullPath() / utility::file::path::component("maildirfolder")); + if (isSubfolderDirectory(*file)) { - if (folderFile->exists() && folderFile->isFile()) + shared_ptr folderFile = fsf->create( + file->getFullPath() / utility::file::path::component("maildirfolder") + ); + + if (folderFile->exists() && folderFile->isFile()) { return true; + } } } } diff --git a/src/vmime/net/maildir/format/courierMaildirFormat.hpp b/src/vmime/net/maildir/format/courierMaildirFormat.hpp index 6b6841e2..7db1a834 100644 --- a/src/vmime/net/maildir/format/courierMaildirFormat.hpp +++ b/src/vmime/net/maildir/format/courierMaildirFormat.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,9 +42,8 @@ namespace format { /** Reads Courier/QMail Maildir format. */ +class VMIME_EXPORT courierMaildirFormat : public maildirFormat { -class VMIME_EXPORT courierMaildirFormat : public maildirFormat -{ public: courierMaildirFormat(const shared_ptr & ctx); @@ -68,11 +67,15 @@ public: bool folderExists(const folder::path& path) const; bool folderHasSubfolders(const folder::path& path) const; - const utility::file::path folderPathToFileSystemPath - (const folder::path& path, const DirectoryType type) const; + const utility::file::path folderPathToFileSystemPath( + const folder::path& path, + const DirectoryType type + ) const; - const std::vector listFolders - (const folder::path& root, const bool recursive) const; + const std::vector listFolders( + const folder::path& root, + const bool recursive + ) const; protected: @@ -104,8 +107,11 @@ protected: * @return true if at least one directory has been found, * false otherwise */ - bool listDirectories(const folder::path& root, - std::vector & dirs, const bool onlyTestForExistence) const; + bool listDirectories( + const folder::path& root, + std::vector & dirs, + const bool onlyTestForExistence + ) const; }; diff --git a/src/vmime/net/maildir/format/kmailMaildirFormat.cpp b/src/vmime/net/maildir/format/kmailMaildirFormat.cpp index c52a2f45..4eb89e8b 100644 --- a/src/vmime/net/maildir/format/kmailMaildirFormat.cpp +++ b/src/vmime/net/maildir/format/kmailMaildirFormat.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,33 +42,38 @@ namespace format { kmailMaildirFormat::kmailMaildirFormat(const shared_ptr & ctx) - : maildirFormat(ctx) -{ + : maildirFormat(ctx) { + } -const string kmailMaildirFormat::getName() const -{ +const string kmailMaildirFormat::getName() const { + return "kmail"; } -void kmailMaildirFormat::createFolder(const folder::path& path) -{ +void kmailMaildirFormat::createFolder(const folder::path& path) { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) + if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) { throw exceptions::invalid_folder_name(); + } - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); + shared_ptr rootDir = fsf->create( + folderPathToFileSystemPath(path, ROOT_DIRECTORY) + ); - shared_ptr newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); + shared_ptr newDir = fsf->create( + folderPathToFileSystemPath(path, NEW_DIRECTORY) + ); + shared_ptr tmpDir = fsf->create( + folderPathToFileSystemPath(path, TMP_DIRECTORY) + ); + shared_ptr curDir = fsf->create( + folderPathToFileSystemPath(path, CUR_DIRECTORY) + ); rootDir->createDirectory(true); @@ -78,32 +83,38 @@ void kmailMaildirFormat::createFolder(const folder::path& path) } -void kmailMaildirFormat::destroyFolder(const folder::path& path) -{ +void kmailMaildirFormat::destroyFolder(const folder::path& path) { + // Delete 'folder' and '.folder.directory' directories shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - maildirUtils::recursiveFSDelete(fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY))); // root + maildirUtils::recursiveFSDelete( + fsf->create(folderPathToFileSystemPath(path, ROOT_DIRECTORY)) // root + ); - maildirUtils::recursiveFSDelete(fsf->create - (folderPathToFileSystemPath(path, CONTAINER_DIRECTORY))); // container + maildirUtils::recursiveFSDelete( + fsf->create(folderPathToFileSystemPath(path, CONTAINER_DIRECTORY)) // container + ); } -bool kmailMaildirFormat::folderExists(const folder::path& path) const -{ +bool kmailMaildirFormat::folderExists(const folder::path& path) const { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); + shared_ptr rootDir = fsf->create( + folderPathToFileSystemPath(path, ROOT_DIRECTORY) + ); - shared_ptr newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); + shared_ptr newDir = fsf->create( + folderPathToFileSystemPath(path, NEW_DIRECTORY) + ); + shared_ptr tmpDir = fsf->create( + folderPathToFileSystemPath(path, TMP_DIRECTORY) + ); + shared_ptr curDir = fsf->create( + folderPathToFileSystemPath(path, CUR_DIRECTORY) + ); return rootDir->exists() && rootDir->isDirectory() && newDir->exists() && newDir->isDirectory() && @@ -112,9 +123,11 @@ bool kmailMaildirFormat::folderExists(const folder::path& path) const } -const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath - (const folder::path& path, const DirectoryType type) const -{ +const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath( + const folder::path& path, + const DirectoryType type +) const { + // Root path utility::file::path fsPath = getContext()->getStore()->getFileSystemPath(); @@ -123,8 +136,8 @@ const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath ? pathSize : (pathSize >= 1 ? pathSize - 1 : 0)); // Parent folders - for (size_t i = 0 ; i < count ; ++i) - { + for (size_t i = 0 ; i < count ; ++i) { + utility::file::path::component comp(path[i]); // TODO: may not work with all encodings... @@ -134,36 +147,36 @@ const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath } // Last component - if (path.getSize() != 0 && type != CONTAINER_DIRECTORY) - { + if (path.getSize() != 0 && type != CONTAINER_DIRECTORY) { + fsPath /= path.getLastComponent(); - switch (type) - { - case ROOT_DIRECTORY: + switch (type) { - // Nothing to add - break; + case ROOT_DIRECTORY: - case NEW_DIRECTORY: + // Nothing to add + break; - fsPath /= NEW_DIR; - break; + case NEW_DIRECTORY: - case CUR_DIRECTORY: + fsPath /= NEW_DIR; + break; - fsPath /= CUR_DIR; - break; + case CUR_DIRECTORY: - case TMP_DIRECTORY: + fsPath /= CUR_DIR; + break; - fsPath /= TMP_DIR; - break; + case TMP_DIRECTORY: - case CONTAINER_DIRECTORY: + fsPath /= TMP_DIR; + break; - // Can't happen... - break; + case CONTAINER_DIRECTORY: + + // Can't happen... + break; } } @@ -171,9 +184,11 @@ const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath } -const std::vector kmailMaildirFormat::listFolders - (const folder::path& root, const bool recursive) const -{ +const std::vector kmailMaildirFormat::listFolders( + const folder::path& root, + const bool recursive +) const { + std::vector list; listFoldersImpl(list, root, recursive); @@ -181,49 +196,53 @@ const std::vector kmailMaildirFormat::listFolders } -void kmailMaildirFormat::listFoldersImpl - (std::vector & list, const folder::path& root, const bool recursive) const -{ +void kmailMaildirFormat::listFoldersImpl( + std::vector & list, + const folder::path& root, + const bool recursive +) const { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr rootDir = fsf->create(folderPathToFileSystemPath(root, - root.isEmpty() ? ROOT_DIRECTORY : CONTAINER_DIRECTORY)); + shared_ptr rootDir = fsf->create( + folderPathToFileSystemPath(root, root.isEmpty() ? ROOT_DIRECTORY : CONTAINER_DIRECTORY) + ); + + if (rootDir->exists()) { - if (rootDir->exists()) - { shared_ptr it = rootDir->getFiles(); - while (it->hasMoreElements()) - { + while (it->hasMoreElements()) { + shared_ptr file = it->nextElement(); - if (isSubfolderDirectory(*file)) - { - const utility::path subPath = - root / file->getFullPath().getLastComponent(); + if (isSubfolderDirectory(*file)) { + + const utility::path subPath = root / file->getFullPath().getLastComponent(); list.push_back(subPath); - if (recursive) + if (recursive) { listFoldersImpl(list, subPath, true); + } } } - } - else - { + + } else { + // No sub-folder } } // static -bool kmailMaildirFormat::isSubfolderDirectory(const utility::file& file) -{ +bool kmailMaildirFormat::isSubfolderDirectory(const utility::file& file) { + // A directory which name does not start with '.' is listed as a sub-folder if (file.isDirectory() && file.getFullPath().getLastComponent().getBuffer().length() >= 1 && - file.getFullPath().getLastComponent().getBuffer()[0] != '.') - { + file.getFullPath().getLastComponent().getBuffer()[0] != '.') { + return true; } @@ -231,17 +250,19 @@ bool kmailMaildirFormat::isSubfolderDirectory(const utility::file& file) } -void kmailMaildirFormat::renameFolder(const folder::path& oldPath, const folder::path& newPath) -{ +void kmailMaildirFormat::renameFolder(const folder::path& oldPath, const folder::path& newPath) { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY)); - shared_ptr contDir = fsf->create - (folderPathToFileSystemPath(oldPath, CONTAINER_DIRECTORY)); + shared_ptr rootDir = fsf->create( + folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY) + ); + shared_ptr contDir = fsf->create( + folderPathToFileSystemPath(oldPath, CONTAINER_DIRECTORY) + ); + + try { - try - { const utility::file::path newRootPath = folderPathToFileSystemPath(newPath, ROOT_DIRECTORY); const utility::file::path newContPath = @@ -250,30 +271,24 @@ void kmailMaildirFormat::renameFolder(const folder::path& oldPath, const folder: rootDir->rename(newRootPath); // Container directory may not exist, so ignore error when trying to rename it - try - { + try { contDir->rename(newContPath); - } - catch (exceptions::filesystem_exception& e) - { + } catch (exceptions::filesystem_exception& e) { // Ignore } - } - catch (exceptions::filesystem_exception& e) - { + + } catch (exceptions::filesystem_exception& e) { + // Revert to old location const utility::file::path rootPath = folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY); const utility::file::path contPath = folderPathToFileSystemPath(oldPath, CONTAINER_DIRECTORY); - try - { + try { rootDir->rename(rootPath); contDir->rename(contPath); - } - catch (exceptions::filesystem_exception& e) - { + } catch (exceptions::filesystem_exception& e) { // Ignore (not recoverable) } @@ -282,29 +297,31 @@ void kmailMaildirFormat::renameFolder(const folder::path& oldPath, const folder: } -bool kmailMaildirFormat::folderHasSubfolders(const folder::path& path) const -{ +bool kmailMaildirFormat::folderHasSubfolders(const folder::path& path) const { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, CONTAINER_DIRECTORY)); + shared_ptr rootDir = fsf->create( + folderPathToFileSystemPath(path, CONTAINER_DIRECTORY) + ); shared_ptr it = rootDir->getFiles(); - while (it->hasMoreElements()) - { + while (it->hasMoreElements()) { + shared_ptr file = it->nextElement(); - if (isSubfolderDirectory(*file)) + if (isSubfolderDirectory(*file)) { return true; + } } return false; } -bool kmailMaildirFormat::supports() const -{ +bool kmailMaildirFormat::supports() const { + // This is the default return true; } diff --git a/src/vmime/net/maildir/format/kmailMaildirFormat.hpp b/src/vmime/net/maildir/format/kmailMaildirFormat.hpp index 854e60be..26b557a3 100644 --- a/src/vmime/net/maildir/format/kmailMaildirFormat.hpp +++ b/src/vmime/net/maildir/format/kmailMaildirFormat.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,9 +42,8 @@ namespace format { /** Reads KMail Maildir format. */ +class VMIME_EXPORT kmailMaildirFormat : public maildirFormat { -class VMIME_EXPORT kmailMaildirFormat : public maildirFormat -{ public: kmailMaildirFormat(const shared_ptr & ctx); @@ -68,11 +67,15 @@ public: bool folderExists(const folder::path& path) const; bool folderHasSubfolders(const folder::path& path) const; - const utility::file::path folderPathToFileSystemPath - (const folder::path& path, const DirectoryType type) const; + const utility::file::path folderPathToFileSystemPath( + const folder::path& path, + const DirectoryType type + ) const; - const std::vector listFolders - (const folder::path& root, const bool recursive) const; + const std::vector listFolders( + const folder::path& root, + const bool recursive + ) const; protected: @@ -81,8 +84,11 @@ protected: /** Recursive implementation of listFolders(). */ - void listFoldersImpl(std::vector & list, - const folder::path& root, const bool recursive) const; + void listFoldersImpl( + std::vector & list, + const folder::path& root, + const bool recursive + ) const; /** Test whether the specified file system directory corresponds to * a maildir subfolder. The name of the directory should not start diff --git a/src/vmime/net/maildir/maildir.hpp b/src/vmime/net/maildir/maildir.hpp index 42bbbea4..8835bf4c 100644 --- a/src/vmime/net/maildir/maildir.hpp +++ b/src/vmime/net/maildir/maildir.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 diff --git a/src/vmime/net/maildir/maildirFolder.cpp b/src/vmime/net/maildir/maildirFolder.cpp index fec1294b..8c02025b 100644 --- a/src/vmime/net/maildir/maildirFolder.cpp +++ b/src/vmime/net/maildir/maildirFolder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -49,93 +49,105 @@ namespace net { namespace maildir { -maildirFolder::maildirFolder(const folder::path& path, const shared_ptr & store) - : m_store(store), m_path(path), +maildirFolder::maildirFolder( + const folder::path& path, + const shared_ptr & 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_mode(-1), + m_open(false), + m_unreadMessageCount(0), + m_messageCount(0) { + store->registerFolder(this); } -maildirFolder::~maildirFolder() -{ - try - { +maildirFolder::~maildirFolder() { + + try { + shared_ptr store = m_store.lock(); - if (store) - { - if (m_open) + if (store) { + + if (m_open) { close(false); + } store->unregisterFolder(this); - } - else if (m_open) - { + + } else if (m_open) { + close(false); } - } - catch (...) - { + + } catch (...) { + // Don't throw in destructor } } -void maildirFolder::onStoreDisconnected() -{ +void maildirFolder::onStoreDisconnected() { + m_store.reset(); } -int maildirFolder::getMode() const -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); +int maildirFolder::getMode() const { - return (m_mode); + if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + return m_mode; } -const folderAttributes maildirFolder::getAttributes() -{ +const folderAttributes maildirFolder::getAttributes() { + folderAttributes attribs; - if (m_path.isEmpty()) + if (m_path.isEmpty()) { attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS); - else + } else { attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS | folderAttributes::TYPE_CONTAINS_MESSAGES); + } - if (m_store.lock()->getFormat()->folderHasSubfolders(m_path)) + if (m_store.lock()->getFormat()->folderHasSubfolders(m_path)) { attribs.setFlags(folderAttributes::FLAG_HAS_CHILDREN); // contains at least one sub-folder + } return attribs; } -const folder::path::component maildirFolder::getName() const -{ - return (m_name); +const folder::path::component maildirFolder::getName() const { + + return m_name; } -const folder::path maildirFolder::getFullPath() const -{ - return (m_path); +const folder::path maildirFolder::getFullPath() const { + + return m_path; } -void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) -{ +void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) + } else if (isOpen()) { throw exceptions::illegal_state("Folder is already open"); - else if (!exists()) + } else if (!exists()) { throw exceptions::illegal_state("Folder does not exist"); + } scanFolder(); @@ -144,18 +156,21 @@ void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) } -void maildirFolder::close(const bool expunge) -{ +void maildirFolder::close(const bool expunge) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - if (!isOpen()) + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (expunge) + if (expunge) { this->expunge(); + } m_open = false; m_mode = -1; @@ -164,11 +179,11 @@ void maildirFolder::close(const bool expunge) } -void maildirFolder::onClose() -{ +void maildirFolder::onClose() { + for (std::vector ::iterator it = m_messages.begin() ; - it != m_messages.end() ; ++it) - { + it != m_messages.end() ; ++it) { + (*it)->onFolderClosed(); } @@ -176,144 +191,147 @@ void maildirFolder::onClose() } -void maildirFolder::registerMessage(maildirMessage* msg) -{ +void maildirFolder::registerMessage(maildirMessage* msg) { + m_messages.push_back(msg); } -void maildirFolder::unregisterMessage(maildirMessage* msg) -{ +void maildirFolder::unregisterMessage(maildirMessage* msg) { + std::vector ::iterator it = std::find(m_messages.begin(), m_messages.end(), msg); - if (it != m_messages.end()) + if (it != m_messages.end()) { m_messages.erase(it); + } } -void maildirFolder::create(const folderAttributes& /* attribs */) -{ +void maildirFolder::create(const folderAttributes& /* attribs */) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) + } else if (isOpen()) { throw exceptions::illegal_state("Folder is open"); - else if (exists()) + } else if (exists()) { throw exceptions::illegal_state("Folder already exists"); - else if (!store->isValidFolderName(m_name)) + } else if (!store->isValidFolderName(m_name)) { throw exceptions::invalid_folder_name(); + } // Create directory on file system - try - { + try { store->getFormat()->createFolder(m_path); - } - catch (exceptions::filesystem_exception& e) - { + } catch (exceptions::filesystem_exception& e) { throw exceptions::command_error("CREATE", "", "File system exception", e); } // Notify folder created shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_CREATED, m_path, m_path); + make_shared ( + dynamicCast (shared_from_this()), + events::folderEvent::TYPE_CREATED, + m_path, m_path + ); notifyFolder(event); } -void maildirFolder::destroy() -{ +void maildirFolder::destroy() { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) + } else if (isOpen()) { throw exceptions::illegal_state("Folder is open"); + } // Delete folder - try - { + try { store->getFormat()->destroyFolder(m_path); - } - catch (std::exception&) - { + } catch (std::exception&) { // Ignore exception: anyway, we can't recover from this... } // Notify folder deleted shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_DELETED, m_path, m_path); + make_shared ( + dynamicCast (shared_from_this()), + events::folderEvent::TYPE_DELETED, + m_path, m_path + ); notifyFolder(event); } -bool maildirFolder::exists() -{ +bool maildirFolder::exists() { + shared_ptr store = m_store.lock(); return store->getFormat()->folderExists(m_path); } -bool maildirFolder::isOpen() const -{ - return (m_open); +bool maildirFolder::isOpen() const { + + return m_open; } -void maildirFolder::scanFolder() -{ +void maildirFolder::scanFolder() { + shared_ptr store = m_store.lock(); - try - { + try { + m_messageCount = 0; m_unreadMessageCount = 0; shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - utility::file::path newDirPath = store->getFormat()->folderPathToFileSystemPath - (m_path, maildirFormat::NEW_DIRECTORY); + utility::file::path newDirPath = + store->getFormat()->folderPathToFileSystemPath(m_path, maildirFormat::NEW_DIRECTORY); shared_ptr newDir = fsf->create(newDirPath); - utility::file::path curDirPath = store->getFormat()->folderPathToFileSystemPath - (m_path, maildirFormat::CUR_DIRECTORY); + utility::file::path curDirPath = + store->getFormat()->folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); shared_ptr curDir = fsf->create(curDirPath); // New received messages (new/) shared_ptr nit = newDir->getFiles(); std::vector newMessageFilenames; - while (nit->hasMoreElements()) - { + while (nit->hasMoreElements()) { + shared_ptr file = nit->nextElement(); - if (maildirUtils::isMessageFile(*file)) + if (maildirUtils::isMessageFile(*file)) { newMessageFilenames.push_back(file->getFullPath().getLastComponent()); + } } // Current messages (cur/) shared_ptr cit = curDir->getFiles(); std::vector curMessageFilenames; - while (cit->hasMoreElements()) - { + while (cit->hasMoreElements()) { + shared_ptr file = cit->nextElement(); - if (maildirUtils::isMessageFile(*file)) + if (maildirUtils::isMessageFile(*file)) { curMessageFilenames.push_back(file->getFullPath().getLastComponent()); + } } // Update/delete existing messages (found in previous scan) - for (size_t i = 0 ; i < m_messageInfos.size() ; ++i) - { + for (size_t i = 0 ; i < m_messageInfos.size() ; ++i) { + messageInfos& msgInfos = m_messageInfos[i]; // NOTE: the flags may have changed (eg. moving from 'new' to 'cur' @@ -321,21 +339,24 @@ void maildirFolder::scanFolder() // "maildirUtils::messageIdComparator" to compare only the 'unique' // portion of the filename... - if (msgInfos.type == messageInfos::TYPE_CUR) - { + if (msgInfos.type == messageInfos::TYPE_CUR) { + const std::vector ::iterator pos = - std::find_if(curMessageFilenames.begin(), curMessageFilenames.end(), - maildirUtils::messageIdComparator(msgInfos.path)); + std::find_if( + curMessageFilenames.begin(), + curMessageFilenames.end(), + maildirUtils::messageIdComparator(msgInfos.path) + ); // If we cannot find this message in the 'cur' directory, // it means it has been deleted (and expunged). - if (pos == curMessageFilenames.end()) - { + if (pos == curMessageFilenames.end()) { + msgInfos.type = messageInfos::TYPE_DELETED; - } + // Otherwise, update its information. - else - { + } else { + msgInfos.path = *pos; curMessageFilenames.erase(pos); } @@ -349,8 +370,8 @@ void maildirFolder::scanFolder() // from the 'new' directory to the 'cur' directory, and append them // to our message list. for (std::vector ::const_iterator - it = newMessageFilenames.begin() ; it != newMessageFilenames.end() ; ++it) - { + it = newMessageFilenames.begin() ; it != newMessageFilenames.end() ; ++it) { + const utility::file::path::component newFilename = maildirUtils::buildFilename(maildirUtils::extractId(*it), 0); @@ -362,10 +383,11 @@ void maildirFolder::scanFolder() messageInfos msgInfos; msgInfos.path = newFilename; - if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) + if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) { msgInfos.type = messageInfos::TYPE_DELETED; - else + } else { msgInfos.type = messageInfos::TYPE_CUR; + } m_messageInfos.push_back(msgInfos); } @@ -373,16 +395,17 @@ void maildirFolder::scanFolder() // Add new messages from 'cur': the files have already been moved // from 'new' to 'cur'. Just append them to our message list. for (std::vector ::const_iterator - it = curMessageFilenames.begin() ; it != curMessageFilenames.end() ; ++it) - { + it = curMessageFilenames.begin() ; it != curMessageFilenames.end() ; ++it) { + // Append to message list messageInfos msgInfos; msgInfos.path = *it; - if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) + if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) { msgInfos.type = messageInfos::TYPE_DELETED; - else + } else { msgInfos.type = messageInfos::TYPE_CUR; + } m_messageInfos.push_back(msgInfos); } @@ -391,140 +414,145 @@ void maildirFolder::scanFolder() size_t unreadMessageCount = 0; for (std::vector ::const_iterator - it = m_messageInfos.begin() ; it != m_messageInfos.end() ; ++it) - { - if ((maildirUtils::extractFlags((*it).path) & message::FLAG_SEEN) == 0) + it = m_messageInfos.begin() ; it != m_messageInfos.end() ; ++it) { + + if ((maildirUtils::extractFlags((*it).path) & message::FLAG_SEEN) == 0) { ++unreadMessageCount; + } } m_unreadMessageCount = unreadMessageCount; m_messageCount = static_cast (m_messageInfos.size()); - } - catch (exceptions::filesystem_exception&) - { + + } catch (exceptions::filesystem_exception&) { + // Should not happen... } } -shared_ptr maildirFolder::getMessage(const size_t num) -{ - if (!isOpen()) +shared_ptr maildirFolder::getMessage(const size_t num) { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (num < 1 || num > m_messageCount) + if (num < 1 || num > m_messageCount) { throw exceptions::message_not_found(); + } - return make_shared - (dynamicCast (shared_from_this()), num); + return make_shared (dynamicCast (shared_from_this()), num); } -std::vector > maildirFolder::getMessages(const messageSet& msgs) -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); +std::vector > maildirFolder::getMessages(const messageSet& msgs) { + + if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + if (msgs.isNumberSet()) { - if (msgs.isNumberSet()) - { const std::vector numbers = maildirUtils::messageSetToNumberList(msgs, m_messageCount); std::vector > messages; shared_ptr thisFolder = dynamicCast (shared_from_this()); - for (std::vector ::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) - { - if (*it < 1|| *it > m_messageCount) + for (std::vector ::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) { + + if (*it < 1|| *it > m_messageCount) { throw exceptions::message_not_found(); + } messages.push_back(make_shared (thisFolder, *it)); } return messages; - } - else - { + + } else { + throw exceptions::operation_not_supported(); } } -size_t maildirFolder::getMessageCount() -{ - return (m_messageCount); +size_t maildirFolder::getMessageCount() { + + return m_messageCount; } -shared_ptr maildirFolder::getFolder(const folder::path::component& name) -{ +shared_ptr maildirFolder::getFolder(const folder::path::component& name) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } return shared_ptr (new maildirFolder(m_path / name, store)); } -std::vector > maildirFolder::getFolders(const bool recursive) -{ +std::vector > maildirFolder::getFolders(const bool recursive) { + shared_ptr store = m_store.lock(); - if (!isOpen() && !store) + if (!isOpen() && !store) { throw exceptions::illegal_state("Store disconnected"); + } std::vector > list; listFolders(list, recursive); - return (list); + return list; } -void maildirFolder::listFolders(std::vector >& list, const bool recursive) -{ +void maildirFolder::listFolders(std::vector >& list, const bool recursive) { + shared_ptr store = m_store.lock(); - try - { + try { + std::vector pathList = store->getFormat()->listFolders(m_path, recursive); list.reserve(pathList.size()); - for (std::vector ::size_type i = 0, n = pathList.size() ; i < n ; ++i) - { - shared_ptr subFolder = - shared_ptr (new maildirFolder(pathList[i], store)); + for (std::vector ::size_type i = 0, n = pathList.size() ; i < n ; ++i) { + + shared_ptr subFolder( + new maildirFolder(pathList[i], store) + ); list.push_back(subFolder); } - } - catch (exceptions::filesystem_exception& e) - { + + } catch (exceptions::filesystem_exception& e) { + throw exceptions::command_error("LIST", "", "", e); } } -void maildirFolder::rename(const folder::path& newPath) -{ +void maildirFolder::rename(const folder::path& newPath) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (m_path.isEmpty() || newPath.isEmpty()) + } else if (m_path.isEmpty() || newPath.isEmpty()) { throw exceptions::illegal_operation("Cannot rename root folder"); - else if (!store->isValidFolderName(newPath.getLastComponent())) + } else if (!store->isValidFolderName(newPath.getLastComponent())) { throw exceptions::invalid_folder_name(); + } // Rename the directory on the file system - try - { + try { store->getFormat()->renameFolder(m_path, newPath); - } - catch (vmime::exception& e) - { + } catch (vmime::exception& e) { throw exceptions::command_error("RENAME", "", "", e); } @@ -535,38 +563,44 @@ void maildirFolder::rename(const folder::path& newPath) m_name = newPath.getLastComponent(); shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); + make_shared ( + dynamicCast (shared_from_this()), + events::folderEvent::TYPE_RENAMED, + oldPath, newPath + ); notifyFolder(event); // Notify folders with the same path for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == oldPath) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == oldPath) { + (*it)->m_path = newPath; (*it)->m_name = newPath.getLastComponent(); shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); + make_shared ( + dynamicCast ((*it)->shared_from_this()), + events::folderEvent::TYPE_RENAMED, + oldPath, newPath + ); (*it)->notifyFolder(event); - } - else if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) - { + + } else if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) { + folder::path oldPath((*it)->m_path); (*it)->m_path.renameParent(oldPath, newPath); shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path); + make_shared ( + dynamicCast ((*it)->shared_from_this()), + events::folderEvent::TYPE_RENAMED, + oldPath, (*it)->m_path + ); (*it)->notifyFolder(event); } @@ -574,27 +608,31 @@ void maildirFolder::rename(const folder::path& newPath) } -void maildirFolder::deleteMessages(const messageSet& msgs) -{ +void maildirFolder::deleteMessages(const messageSet& msgs) { + // Mark messages as deleted setMessageFlags(msgs, message::FLAG_DELETED, message::FLAG_MODE_ADD); } -void maildirFolder::setMessageFlags - (const messageSet& msgs, const int flags, const int mode) -{ +void maildirFolder::setMessageFlags( + const messageSet& msgs, + const int flags, + const int mode +) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) + } else if (m_mode == MODE_READ_ONLY) { throw exceptions::illegal_state("Folder is read-only"); + } + + if (msgs.isNumberSet()) { - if (msgs.isNumberSet()) - { const std::vector nums = maildirUtils::messageSetToNumberList(msgs, m_messageCount); // Change message flags @@ -604,113 +642,118 @@ void maildirFolder::setMessageFlags folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); for (std::vector ::const_iterator it = - nums.begin() ; it != nums.end() ; ++it) - { + nums.begin() ; it != nums.end() ; ++it) { + const size_t num = *it - 1; - try - { + try { + const utility::file::path::component path = m_messageInfos[num].path; shared_ptr file = fsf->create(curDirPath / path); int newFlags = maildirUtils::extractFlags(path); - switch (mode) - { - case message::FLAG_MODE_ADD: newFlags |= flags; break; - case message::FLAG_MODE_REMOVE: newFlags &= ~flags; break; - default: - case message::FLAG_MODE_SET: newFlags = flags; break; + switch (mode) { + case message::FLAG_MODE_ADD: newFlags |= flags; break; + case message::FLAG_MODE_REMOVE: newFlags &= ~flags; break; + default: + case message::FLAG_MODE_SET: newFlags = flags; break; } - const utility::file::path::component newPath = maildirUtils::buildFilename - (maildirUtils::extractId(path), newFlags); + const utility::file::path::component newPath = + maildirUtils::buildFilename(maildirUtils::extractId(path), newFlags); file->rename(curDirPath / newPath); - if (flags & message::FLAG_DELETED) + if (flags & message::FLAG_DELETED) { m_messageInfos[num].type = messageInfos::TYPE_DELETED; - else + } else { m_messageInfos[num].type = messageInfos::TYPE_CUR; + } m_messageInfos[num].path = newPath; - } - catch (exceptions::filesystem_exception& e) - { + + } catch (exceptions::filesystem_exception& e) { + // Ignore (not important) } } // Update local flags - switch (mode) - { - case message::FLAG_MODE_ADD: - { - for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && - (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) - { - (*it)->m_flags |= flags; - } - } + switch (mode) { - break; - } - case message::FLAG_MODE_REMOVE: - { - for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && - (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) - { - (*it)->m_flags &= ~flags; - } - } + case message::FLAG_MODE_ADD: { - break; - } - default: - case message::FLAG_MODE_SET: - { - for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && - (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) - { - (*it)->m_flags = flags; - } - } + for (std::vector ::iterator it = + m_messages.begin() ; it != m_messages.end() ; ++it) { - break; - } + if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && + (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) { + + (*it)->m_flags |= flags; + } + } + + break; + } + case message::FLAG_MODE_REMOVE: { + + for (std::vector ::iterator it = + m_messages.begin() ; it != m_messages.end() ; ++it) { + + if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && + (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) { + + (*it)->m_flags &= ~flags; + } + } + + break; + } + default: + case message::FLAG_MODE_SET: { + + for (std::vector ::iterator it = + m_messages.begin() ; it != m_messages.end() ; ++it) { + + if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && + (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) { + + (*it)->m_flags = flags; + } + } + + break; + } } // Notify message flags changed shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageChangedEvent::TYPE_FLAGS, nums); + make_shared ( + dynamicCast (shared_from_this()), + events::messageChangedEvent::TYPE_FLAGS, + nums + ); notifyMessageChanged(event); // TODO: notify other folders with the same path - } - else - { + + } else { + throw exceptions::operation_not_supported(); } } -messageSet maildirFolder::addMessage - (const shared_ptr & msg, const int flags, - vmime::datetime* date, utility::progressListener* progress) -{ +messageSet maildirFolder::addMessage( + const shared_ptr & msg, + const int flags, + vmime::datetime* date, + utility::progressListener* progress +) { + std::ostringstream oss; utility::outputStreamAdapter ossAdapter(oss); @@ -723,50 +766,50 @@ messageSet maildirFolder::addMessage } -messageSet maildirFolder::addMessage - (utility::inputStream& is, const size_t size, - const int flags, vmime::datetime* /* date */, utility::progressListener* progress) -{ +messageSet maildirFolder::addMessage( + utility::inputStream& is, + const size_t size, + const int flags, + vmime::datetime* /* date */, + utility::progressListener* progress +) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) + } else if (m_mode == MODE_READ_ONLY) { throw exceptions::illegal_state("Folder is read-only"); + } shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); utility::file::path tmpDirPath = store->getFormat()-> folderPathToFileSystemPath(m_path,maildirFormat::TMP_DIRECTORY); utility::file::path dstDirPath = store->getFormat()-> - folderPathToFileSystemPath(m_path, + folderPathToFileSystemPath( + m_path, flags == message::FLAG_RECENT ? maildirFormat::NEW_DIRECTORY : - maildirFormat::CUR_DIRECTORY); + maildirFormat::CUR_DIRECTORY + ); const utility::file::path::component filename = - maildirUtils::buildFilename(maildirUtils::generateId(), - ((flags == -1) ? 0 : flags)); + maildirUtils::buildFilename(maildirUtils::generateId(), ((flags == -1) ? 0 : flags)); - try - { + try { shared_ptr tmpDir = fsf->create(tmpDirPath); tmpDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { + } catch (exceptions::filesystem_exception&) { // Don't throw now, it will fail later... } - try - { + try { shared_ptr curDir = fsf->create(dstDirPath); curDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { + } catch (exceptions::filesystem_exception&) { // Don't throw now, it will fail later... } @@ -781,26 +824,29 @@ messageSet maildirFolder::addMessage m_messageInfos.push_back(msgInfos); m_messageCount++; - if ((flags == -1) || !(flags & message::FLAG_SEEN)) + if ((flags == -1) || !(flags & message::FLAG_SEEN)) { m_unreadMessageCount++; + } // Notification std::vector nums; nums.push_back(m_messageCount); shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); + make_shared ( + dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); notifyMessageCount(event); // Notify folders with the same path for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == m_path) { + (*it)->m_messageCount = m_messageCount; (*it)->m_unreadMessageCount = m_unreadMessageCount; @@ -808,9 +854,11 @@ messageSet maildirFolder::addMessage std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin()); shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); + make_shared ( + dynamicCast ((*it)->shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); (*it)->notifyMessageCount(event); } @@ -820,22 +868,25 @@ messageSet maildirFolder::addMessage } -void maildirFolder::copyMessageImpl(const utility::file::path& tmpDirPath, +void maildirFolder::copyMessageImpl( + const utility::file::path& tmpDirPath, const utility::file::path& dstDirPath, const utility::file::path::component& filename, utility::inputStream& is, const size_t size, - utility::progressListener* progress) -{ + utility::progressListener* progress +) { + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); shared_ptr file = fsf->create(tmpDirPath / filename); - if (progress) + if (progress) { progress->start(size); + } // First, write the message into 'tmp'... - try - { + try { + file->createFile(); shared_ptr fw = file->getFileWriter(); @@ -844,35 +895,33 @@ void maildirFolder::copyMessageImpl(const utility::file::path& tmpDirPath, byte_t buffer[65536]; size_t total = 0; - while (!is.eof()) - { + while (!is.eof()) { + const size_t read = is.read(buffer, sizeof(buffer)); - if (read != 0) - { + if (read != 0) { os->write(buffer, read); total += read; } - if (progress) + if (progress) { progress->progress(total, size); + } } os->flush(); - } - catch (exception& e) - { - if (progress) + + } catch (exception& e) { + + if (progress) { progress->stop(size); + } // Delete temporary file - try - { + try { shared_ptr file = fsf->create(tmpDirPath / filename); file->remove(); - } - catch (exceptions::filesystem_exception&) - { + } catch (exceptions::filesystem_exception&) { // Ignore } @@ -880,48 +929,51 @@ void maildirFolder::copyMessageImpl(const utility::file::path& tmpDirPath, } // ...then, move it to 'cur' - try - { + try { + file->rename(dstDirPath / filename); - } - catch (exception& e) - { - if (progress) + + } catch (exception& e) { + + if (progress) { progress->stop(size); + } // Delete temporary file - try - { + try { + file->remove(); shared_ptr file = fsf->create(dstDirPath / filename); file->remove(); - } - catch (exceptions::filesystem_exception&) - { + + } catch (exceptions::filesystem_exception&) { + // Ignore } throw exceptions::command_error("ADD", "", "", e); } - if (progress) + if (progress) { progress->stop(size); + } } -messageSet maildirFolder::copyMessages(const folder::path& dest, const messageSet& msgs) -{ +messageSet maildirFolder::copyMessages(const folder::path& dest, const messageSet& msgs) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - utility::file::path curDirPath = store->getFormat()->folderPathToFileSystemPath - (m_path, maildirFormat::CUR_DIRECTORY); + utility::file::path curDirPath = + store->getFormat()->folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); utility::file::path destCurDirPath = store->getFormat()-> folderPathToFileSystemPath(dest, maildirFormat::CUR_DIRECTORY); @@ -929,34 +981,34 @@ messageSet maildirFolder::copyMessages(const folder::path& dest, const messageSe folderPathToFileSystemPath(dest, maildirFormat::TMP_DIRECTORY); // Create destination directories - try - { + try { + shared_ptr destTmpDir = fsf->create(destTmpDirPath); destTmpDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { + + } catch (exceptions::filesystem_exception&) { + // Don't throw now, it will fail later... } - try - { + try { + shared_ptr destCurDir = fsf->create(destCurDirPath); destCurDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { + + } catch (exceptions::filesystem_exception&) { + // Don't throw now, it will fail later... } // Copy messages const std::vector nums = maildirUtils::messageSetToNumberList(msgs, m_messageCount); - try - { + try { + for (std::vector ::const_iterator it = - nums.begin() ; it != nums.end() ; ++it) - { + nums.begin() ; it != nums.end() ; ++it) { + const size_t num = *it; const messageInfos& msg = m_messageInfos[num - 1]; const int flags = maildirUtils::extractFlags(msg.path); @@ -971,9 +1023,9 @@ messageSet maildirFolder::copyMessages(const folder::path& dest, const messageSe copyMessageImpl(destTmpDirPath, destCurDirPath, filename, *is, file->getLength(), NULL); } - } - catch (exception& e) - { + + } catch (exception& e) { + notifyMessagesCopied(dest); throw exceptions::command_error("COPY", "", "", e); } @@ -984,15 +1036,15 @@ messageSet maildirFolder::copyMessages(const folder::path& dest, const messageSe } -void maildirFolder::notifyMessagesCopied(const folder::path& dest) -{ +void maildirFolder::notifyMessagesCopied(const folder::path& dest) { + shared_ptr store = m_store.lock(); for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == dest) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == dest) { + // We only need to update the first folder we found as calling // status() will notify all the folders with the same path. size_t count, unseen; @@ -1004,8 +1056,8 @@ void maildirFolder::notifyMessagesCopied(const folder::path& dest) } -void maildirFolder::status(size_t& count, size_t& unseen) -{ +void maildirFolder::status(size_t& count, size_t& unseen) { + count = 0; unseen = 0; @@ -1018,8 +1070,8 @@ void maildirFolder::status(size_t& count, size_t& unseen) } -shared_ptr maildirFolder::getStatus() -{ +shared_ptr maildirFolder::getStatus() { + shared_ptr store = m_store.lock(); const size_t oldCount = m_messageCount; @@ -1032,27 +1084,30 @@ shared_ptr maildirFolder::getStatus() status->setUnseenCount(m_unreadMessageCount); // Notify message count changed (new messages) - if (m_messageCount > oldCount) - { + if (m_messageCount > oldCount) { + std::vector nums; nums.reserve(m_messageCount - oldCount); - for (size_t i = oldCount + 1, j = 0 ; i <= m_messageCount ; ++i, ++j) + for (size_t i = oldCount + 1, j = 0 ; i <= m_messageCount ; ++i, ++j) { nums[j] = i; + } shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); + make_shared ( + dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); notifyMessageCount(event); // Notify folders with the same path for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == m_path) { + (*it)->m_messageCount = m_messageCount; (*it)->m_unreadMessageCount = m_unreadMessageCount; @@ -1060,9 +1115,11 @@ shared_ptr maildirFolder::getStatus() std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin()); shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); + make_shared ( + dynamicCast ((*it)->shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); (*it)->notifyMessageCount(event); } @@ -1073,16 +1130,17 @@ shared_ptr maildirFolder::getStatus() } -void maildirFolder::expunge() -{ +void maildirFolder::expunge() { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) + } else if (m_mode == MODE_READ_ONLY) { throw exceptions::illegal_state("Folder is read-only"); + } shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); @@ -1092,43 +1150,43 @@ void maildirFolder::expunge() std::vector nums; size_t unreadCount = 0; - for (size_t num = 1 ; num <= m_messageCount ; ++num) - { + for (size_t num = 1 ; num <= m_messageCount ; ++num) { + messageInfos& infos = m_messageInfos[num - 1]; - if (infos.type == messageInfos::TYPE_DELETED) - { + if (infos.type == messageInfos::TYPE_DELETED) { + nums.push_back(num); for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if ((*it)->m_num == num) + m_messages.begin() ; it != m_messages.end() ; ++it) { + + if ((*it)->m_num == num) { (*it)->m_expunged = true; - else if ((*it)->m_num > num) + } else if ((*it)->m_num > num) { (*it)->m_num--; + } } - if (maildirUtils::extractFlags(infos.path) & message::FLAG_SEEN) + if (maildirUtils::extractFlags(infos.path) & message::FLAG_SEEN) { ++unreadCount; + } // Delete file from file system - try - { + try { shared_ptr file = fsf->create(curDirPath / infos.path); file->remove(); - } - catch (exceptions::filesystem_exception& e) - { + } catch (exceptions::filesystem_exception& e) { // Ignore (not important) } } } - if (!nums.empty()) - { - for (std::vector ::size_type i = nums.size() ; i != 0 ; --i) + if (!nums.empty()) { + + for (std::vector ::size_type i = nums.size() ; i != 0 ; --i) { m_messageInfos.erase(m_messageInfos.begin() + (i - 1)); + } } m_messageCount -= static_cast (nums.size()); @@ -1136,18 +1194,20 @@ void maildirFolder::expunge() // Notify message expunged shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_REMOVED, nums); + make_shared ( + dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_REMOVED, + nums + ); notifyMessageCount(event); // Notify folders with the same path for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == m_path) { + (*it)->m_messageCount = m_messageCount; (*it)->m_unreadMessageCount = m_unreadMessageCount; @@ -1155,9 +1215,11 @@ void maildirFolder::expunge() std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin()); shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::messageCountEvent::TYPE_REMOVED, nums); + make_shared ( + dynamicCast ((*it)->shared_from_this()), + events::messageCountEvent::TYPE_REMOVED, + nums + ); (*it)->notifyMessageCount(event); } @@ -1165,81 +1227,99 @@ void maildirFolder::expunge() } -shared_ptr maildirFolder::getParent() -{ - if (m_path.isEmpty()) +shared_ptr maildirFolder::getParent() { + + if (m_path.isEmpty()) { return null; - else + } else { return shared_ptr (new maildirFolder(m_path.getParent(), m_store.lock())); + } } -shared_ptr maildirFolder::getStore() const -{ +shared_ptr maildirFolder::getStore() const { + return m_store.lock(); } -shared_ptr maildirFolder::getStore() -{ +shared_ptr maildirFolder::getStore() { + return m_store.lock(); } -void maildirFolder::fetchMessages(std::vector >& msg, - const fetchAttributes& options, utility::progressListener* progress) -{ +void maildirFolder::fetchMessages( + std::vector >& msg, + const fetchAttributes& options, + utility::progressListener* progress +) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (msg.empty()) + if (msg.empty()) { return; + } const size_t total = msg.size(); size_t current = 0; - if (progress) + if (progress) { progress->start(total); + } shared_ptr thisFolder = dynamicCast (shared_from_this()); for (std::vector >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { + it != msg.end() ; ++it) { + dynamicCast (*it)->fetch(thisFolder, options); - if (progress) + if (progress) { progress->progress(++current, total); + } } - if (progress) + if (progress) { progress->stop(total); + } } -void maildirFolder::fetchMessage(const shared_ptr & msg, const fetchAttributes& options) -{ +void maildirFolder::fetchMessage( + const shared_ptr & msg, + const fetchAttributes& options +) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - dynamicCast (msg)->fetch - (dynamicCast (shared_from_this()), options); + dynamicCast (msg)->fetch( + dynamicCast (shared_from_this()), + options + ); } -std::vector > maildirFolder::getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs) -{ - if (msgs.isEmpty()) +std::vector > maildirFolder::getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs +) { + + if (msgs.isEmpty()) { return std::vector >(); + } std::vector > messages = getMessages(msgs); fetchMessages(messages, attribs); @@ -1248,26 +1328,30 @@ std::vector > maildirFolder::getAndFetchMessages } -int maildirFolder::getFetchCapabilities() const -{ - return fetchAttributes::ENVELOPE | fetchAttributes::STRUCTURE | - fetchAttributes::CONTENT_INFO | fetchAttributes::FLAGS | - fetchAttributes::SIZE | fetchAttributes::FULL_HEADER | - fetchAttributes::UID | fetchAttributes::IMPORTANCE; +int maildirFolder::getFetchCapabilities() const { + + return fetchAttributes::ENVELOPE | + fetchAttributes::STRUCTURE | + fetchAttributes::CONTENT_INFO | + fetchAttributes::FLAGS | + fetchAttributes::SIZE | + fetchAttributes::FULL_HEADER | + fetchAttributes::UID | + fetchAttributes::IMPORTANCE; } -const utility::file::path maildirFolder::getMessageFSPath(const size_t number) const -{ +const utility::file::path maildirFolder::getMessageFSPath(const size_t number) const { + utility::file::path curDirPath = m_store.lock()->getFormat()-> folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); - return (curDirPath / m_messageInfos[number - 1].path); + return curDirPath / m_messageInfos[number - 1].path; } -std::vector maildirFolder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) -{ +std::vector maildirFolder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) { + throw exceptions::operation_not_supported(); } diff --git a/src/vmime/net/maildir/maildirFolder.hpp b/src/vmime/net/maildir/maildirFolder.hpp index ff0cff61..24f2bf86 100644 --- a/src/vmime/net/maildir/maildirFolder.hpp +++ b/src/vmime/net/maildir/maildirFolder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -52,9 +52,8 @@ class maildirMessage; /** maildir folder implementation. */ +class VMIME_EXPORT maildirFolder : public folder { -class VMIME_EXPORT maildirFolder : public folder -{ private: friend class maildirStore; @@ -97,10 +96,26 @@ public: void deleteMessages(const messageSet& msgs); - void setMessageFlags(const messageSet& msgs, const int flags, const int mode = message::FLAG_MODE_SET); + void setMessageFlags( + const messageSet& msgs, + const int flags, + const int mode = message::FLAG_MODE_SET + ); - messageSet addMessage(const shared_ptr & msg, const int flags = -1, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); - messageSet addMessage(utility::inputStream& is, const size_t size, const int flags = -1, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); + messageSet addMessage( + const shared_ptr & msg, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); + + messageSet addMessage( + utility::inputStream& is, + const size_t size, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); messageSet copyMessages(const folder::path& dest, const messageSet& msgs); @@ -115,11 +130,18 @@ public: shared_ptr getStore(); - void fetchMessages(std::vector >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL); + void fetchMessages( + std::vector >& msg, + const fetchAttributes& options, + utility::progressListener* progress = NULL + ); + void fetchMessage(const shared_ptr & msg, const fetchAttributes& options); - std::vector > getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs); + std::vector > getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs + ); int getFetchCapabilities() const; @@ -161,10 +183,9 @@ private: size_t m_messageCount; // Store information about scanned messages - struct messageInfos - { - enum Type - { + struct messageInfos { + + enum Type { TYPE_CUR, TYPE_DELETED }; diff --git a/src/vmime/net/maildir/maildirFolderStatus.cpp b/src/vmime/net/maildir/maildirFolderStatus.cpp index 9817c1ca..7438d8cf 100644 --- a/src/vmime/net/maildir/maildirFolderStatus.cpp +++ b/src/vmime/net/maildir/maildirFolderStatus.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,45 +37,45 @@ namespace maildir { maildirFolderStatus::maildirFolderStatus() : m_count(0), - m_unseen(0) -{ + m_unseen(0) { + } maildirFolderStatus::maildirFolderStatus(const maildirFolderStatus& other) : folderStatus(), m_count(other.m_count), - m_unseen(other.m_unseen) -{ + m_unseen(other.m_unseen) { + } -size_t maildirFolderStatus::getMessageCount() const -{ +size_t maildirFolderStatus::getMessageCount() const { + return m_count; } -size_t maildirFolderStatus::getUnseenCount() const -{ +size_t maildirFolderStatus::getUnseenCount() const { + return m_unseen; } -void maildirFolderStatus::setMessageCount(const size_t count) -{ +void maildirFolderStatus::setMessageCount(const size_t count) { + m_count = count; } -void maildirFolderStatus::setUnseenCount(const size_t unseen) -{ +void maildirFolderStatus::setUnseenCount(const size_t unseen) { + m_unseen = unseen; } -shared_ptr maildirFolderStatus::clone() const -{ +shared_ptr maildirFolderStatus::clone() const { + return make_shared (*this); } diff --git a/src/vmime/net/maildir/maildirFolderStatus.hpp b/src/vmime/net/maildir/maildirFolderStatus.hpp index 0921f01e..3b69375a 100644 --- a/src/vmime/net/maildir/maildirFolderStatus.hpp +++ b/src/vmime/net/maildir/maildirFolderStatus.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,9 +41,8 @@ namespace maildir { /** Holds the status of a Maildir folder. */ +class VMIME_EXPORT maildirFolderStatus : public folderStatus { -class VMIME_EXPORT maildirFolderStatus : public folderStatus -{ public: maildirFolderStatus(); diff --git a/src/vmime/net/maildir/maildirFormat.cpp b/src/vmime/net/maildir/maildirFormat.cpp index 7f2cb5f1..914c0786 100644 --- a/src/vmime/net/maildir/maildirFormat.cpp +++ b/src/vmime/net/maildir/maildirFormat.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -51,13 +51,13 @@ const utility::file::path::component maildirFormat::NEW_DIR("new", vmime::charse // maildirFormat::context::context(const shared_ptr & store) - : m_store(store) -{ + : m_store(store) { + } -shared_ptr maildirFormat::context::getStore() -{ +shared_ptr maildirFormat::context::getStore() { + return m_store.lock(); } @@ -67,27 +67,28 @@ shared_ptr maildirFormat::context::getStore() // maildirFormat::maildirFormat(const shared_ptr & ctx) - : m_context(ctx) -{ + : m_context(ctx) { + } -shared_ptr maildirFormat::getContext() const -{ +shared_ptr maildirFormat::getContext() const { + return m_context; } // static -shared_ptr maildirFormat::detect(const shared_ptr & store) -{ +shared_ptr maildirFormat::detect(const shared_ptr & store) { + shared_ptr ctx = make_shared (store); // Try Courier format shared_ptr fmt = make_shared (ctx); - if (fmt->supports()) + if (fmt->supports()) { return fmt; + } // Default is KMail format return make_shared (ctx); diff --git a/src/vmime/net/maildir/maildirFormat.hpp b/src/vmime/net/maildir/maildirFormat.hpp index 733303bd..9b9e0636 100644 --- a/src/vmime/net/maildir/maildirFormat.hpp +++ b/src/vmime/net/maildir/maildirFormat.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -45,14 +45,14 @@ namespace maildir { class maildirStore; -/** Interface for an object capable of reading a specific Maildir format. */ +/** Interface for an object capable of reading a specific Maildir format. + */ +class VMIME_EXPORT maildirFormat : public object { -class VMIME_EXPORT maildirFormat : public object -{ public: - class context : public object - { + class context : public object { + public: context(const shared_ptr & store); @@ -66,8 +66,7 @@ public: /** Physical directory types. */ - enum DirectoryType - { + enum DirectoryType { ROOT_DIRECTORY, /**< Root directory. */ NEW_DIRECTORY, /**< Directory containing unread messages. */ CUR_DIRECTORY, /**< Directory containing messages that have been seen. */ @@ -125,8 +124,10 @@ public: * @param type type of directory to return * @return corresponding directory on the file system */ - virtual const utility::file::path folderPathToFileSystemPath - (const folder::path& path, const DirectoryType type) const = 0; + virtual const utility::file::path folderPathToFileSystemPath( + const folder::path& path, + const DirectoryType type + ) const = 0; /** List subfolders in the specified folder. * @@ -135,8 +136,10 @@ public: * returned; if set to false, only direct children are returned. * @return list of subfolders */ - virtual const std::vector listFolders - (const folder::path& root, const bool recursive) const = 0; + virtual const std::vector listFolders( + const folder::path& root, + const bool recursive + ) const = 0; /** Try to detect the format of the specified Maildir store. diff --git a/src/vmime/net/maildir/maildirMessage.cpp b/src/vmime/net/maildir/maildirMessage.cpp index ea3d05a6..ae99c597 100644 --- a/src/vmime/net/maildir/maildirMessage.cpp +++ b/src/vmime/net/maildir/maildirMessage.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -49,132 +49,160 @@ namespace maildir { maildirMessage::maildirMessage(const shared_ptr & folder, const size_t num) - : m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED), - m_expunged(false), m_structure(null) -{ + : m_folder(folder), + m_num(num), + m_size(-1), + m_flags(FLAG_UNDEFINED), + m_expunged(false), + m_structure(null) { + folder->registerMessage(this); } -maildirMessage::~maildirMessage() -{ - try - { +maildirMessage::~maildirMessage() { + + try { + shared_ptr folder = m_folder.lock(); - if (folder) + if (folder) { folder->unregisterMessage(this); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -void maildirMessage::onFolderClosed() -{ +void maildirMessage::onFolderClosed() { + m_folder.reset(); } -size_t maildirMessage::getNumber() const -{ - return (m_num); +size_t maildirMessage::getNumber() const { + + return m_num; } -const message::uid maildirMessage::getUID() const -{ - return (m_uid); +const message::uid maildirMessage::getUID() const { + + return m_uid; } -size_t maildirMessage::getSize() const -{ - if (m_size == static_cast (-1)) +size_t maildirMessage::getSize() const { + + if (m_size == static_cast (-1)) { throw exceptions::unfetched_object(); + } - return (m_size); + return m_size; } -bool maildirMessage::isExpunged() const -{ - return (m_expunged); +bool maildirMessage::isExpunged() const { + + return m_expunged; } -shared_ptr maildirMessage::getStructure() const -{ - if (m_structure == NULL) +shared_ptr maildirMessage::getStructure() const { + + if (!m_structure) { throw exceptions::unfetched_object(); + } return m_structure; } -shared_ptr maildirMessage::getStructure() -{ - if (m_structure == NULL) +shared_ptr maildirMessage::getStructure() { + + if (!m_structure) { throw exceptions::unfetched_object(); + } return m_structure; } -shared_ptr maildirMessage::getHeader() const -{ - if (m_header == NULL) - throw exceptions::unfetched_object(); +shared_ptr maildirMessage::getHeader() const { - return (m_header); + if (!m_header) { + throw exceptions::unfetched_object(); + } + + return m_header; } -int maildirMessage::getFlags() const -{ - if (m_flags == FLAG_UNDEFINED) - throw exceptions::unfetched_object(); +int maildirMessage::getFlags() const { - return (m_flags); + if (m_flags == FLAG_UNDEFINED) { + throw exceptions::unfetched_object(); + } + + return m_flags; } -void maildirMessage::setFlags(const int flags, const int mode) -{ +void maildirMessage::setFlags(const int flags, const int mode) { + shared_ptr folder = m_folder.lock(); - if (!folder) + if (!folder) { throw exceptions::folder_not_found(); + } folder->setMessageFlags(messageSet::byNumber(m_num), flags, mode); } -void maildirMessage::extract(utility::outputStream& os, - utility::progressListener* progress, const size_t start, - const size_t length, const bool peek) const -{ +void maildirMessage::extract( + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const bool peek +) const { + extractImpl(os, progress, 0, m_size, start, length, peek); } -void maildirMessage::extractPart(const shared_ptr & p, utility::outputStream& os, - utility::progressListener* progress, const size_t start, - const size_t length, const bool peek) const -{ +void maildirMessage::extractPart( + const shared_ptr & p, + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const bool peek +) const { + shared_ptr mp = dynamicCast (p); - extractImpl(os, progress, mp->getBodyParsedOffset(), mp->getBodyParsedLength(), - start, length, peek); + extractImpl( + os, progress, mp->getBodyParsedOffset(), mp->getBodyParsedLength(), + start, length, peek + ); } -void maildirMessage::extractImpl(utility::outputStream& os, utility::progressListener* progress, - const size_t start, const size_t length, const size_t partialStart, const size_t partialLength, - const bool /* peek */) const -{ +void maildirMessage::extractImpl( + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const size_t partialStart, + const size_t partialLength, + const bool /* peek */ +) const { + shared_ptr folder = m_folder.lock(); shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); @@ -188,17 +216,21 @@ void maildirMessage::extractImpl(utility::outputStream& os, utility::progressLis is->skip(start + partialStart); byte_t buffer[8192]; - size_t remaining = (partialLength == static_cast (-1) - ? length : std::min(partialLength, length)); + size_t remaining = + (partialLength == static_cast (-1) + ? length + : std::min(partialLength, length) + ); const size_t total = remaining; size_t current = 0; - if (progress) + if (progress) { progress->start(total); + } + + while (!is->eof() && remaining > 0) { - while (!is->eof() && remaining > 0) - { const size_t read = is->read(buffer, std::min(remaining, sizeof(buffer))); remaining -= read; @@ -206,19 +238,21 @@ void maildirMessage::extractImpl(utility::outputStream& os, utility::progressLis os.write(buffer, read); - if (progress) + if (progress) { progress->progress(current, total); + } } - if (progress) + if (progress) { progress->stop(total); + } // TODO: mark as read unless 'peek' is set } -void maildirMessage::fetchPartHeader(const shared_ptr & p) -{ +void maildirMessage::fetchPartHeader(const shared_ptr & p) { + shared_ptr folder = m_folder.lock(); shared_ptr mp = dynamicCast (p); @@ -239,8 +273,8 @@ void maildirMessage::fetchPartHeader(const shared_ptr & p) string contents; contents.reserve(remaining); - while (!is->eof() && remaining > 0) - { + while (!is->eof() && remaining > 0) { + const size_t read = is->read(buffer, std::min(remaining, sizeof(buffer))); remaining -= read; @@ -252,71 +286,71 @@ void maildirMessage::fetchPartHeader(const shared_ptr & p) } -void maildirMessage::fetch(const shared_ptr & msgFolder, const fetchAttributes& options) -{ +void maildirMessage::fetch(const shared_ptr & msgFolder, const fetchAttributes& options) { + shared_ptr folder = m_folder.lock(); - if (folder != msgFolder) + if (folder != msgFolder) { throw exceptions::folder_not_found(); + } shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); const utility::file::path path = folder->getMessageFSPath(m_num); shared_ptr file = fsf->create(path); - if (options.has(fetchAttributes::FLAGS)) + if (options.has(fetchAttributes::FLAGS)) { m_flags = maildirUtils::extractFlags(path.getLastComponent()); + } - if (options.has(fetchAttributes::SIZE)) + if (options.has(fetchAttributes::SIZE)) { m_size = file->getLength(); + } - if (options.has(fetchAttributes::UID)) + if (options.has(fetchAttributes::UID)) { m_uid = maildirUtils::extractId(path.getLastComponent()).getBuffer(); + } if (options.has(fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | fetchAttributes::FULL_HEADER | fetchAttributes::STRUCTURE | - fetchAttributes::IMPORTANCE)) - { + fetchAttributes::IMPORTANCE)) { + string contents; shared_ptr reader = file->getFileReader(); shared_ptr is = reader->getInputStream(); // Need whole message contents for structure - if (options.has(fetchAttributes::STRUCTURE)) - { + if (options.has(fetchAttributes::STRUCTURE)) { + byte_t buffer[16384]; contents.reserve(file->getLength()); - while (!is->eof()) - { + while (!is->eof()) { const size_t read = is->read(buffer, sizeof(buffer)); vmime::utility::stringUtils::appendBytesToString(contents, buffer, read); } - } + // Need only header - else - { + } else { + byte_t buffer[1024]; contents.reserve(4096); - while (!is->eof()) - { + while (!is->eof()) { + const size_t read = is->read(buffer, sizeof(buffer)); vmime::utility::stringUtils::appendBytesToString(contents, buffer, read); const size_t sep1 = contents.rfind("\r\n\r\n"); const size_t sep2 = contents.rfind("\n\n"); - if (sep1 != string::npos) - { + if (sep1 != string::npos) { contents.erase(contents.begin() + sep1 + 4, contents.end()); break; - } - else if (sep2 != string::npos) - { + } else if (sep2 != string::npos) { contents.erase(contents.begin() + sep2 + 2, contents.end()); break; } @@ -327,8 +361,7 @@ void maildirMessage::fetch(const shared_ptr & msgFolder, const fe msg.parse(contents); // Extract structure - if (options.has(fetchAttributes::STRUCTURE)) - { + if (options.has(fetchAttributes::STRUCTURE)) { m_structure = make_shared (shared_ptr (), msg); } @@ -336,25 +369,26 @@ void maildirMessage::fetch(const shared_ptr & msgFolder, const fe if (options.has(fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | fetchAttributes::FULL_HEADER | - fetchAttributes::IMPORTANCE)) - { + fetchAttributes::IMPORTANCE)) { + getOrCreateHeader()->copyFrom(*(msg.getHeader())); } } } -shared_ptr
maildirMessage::getOrCreateHeader() -{ - if (m_header != NULL) - return (m_header); - else +shared_ptr
maildirMessage::getOrCreateHeader() { + + if (m_header) { + return m_header; + } else { return (m_header = make_shared
()); + } } -shared_ptr maildirMessage::getParsedMessage() -{ +shared_ptr maildirMessage::getParsedMessage() { + std::ostringstream oss; utility::outputStreamAdapter os(oss); diff --git a/src/vmime/net/maildir/maildirMessage.hpp b/src/vmime/net/maildir/maildirMessage.hpp index 3e97a981..8cd0aac2 100644 --- a/src/vmime/net/maildir/maildirMessage.hpp +++ b/src/vmime/net/maildir/maildirMessage.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -45,9 +45,8 @@ class maildirFolder; /** maildir message implementation. */ +class VMIME_EXPORT maildirMessage : public message { -class VMIME_EXPORT maildirMessage : public message -{ friend class maildirFolder; maildirMessage(const maildirMessage&) : message() { } @@ -75,8 +74,22 @@ public: int getFlags() const; void setFlags(const int flags, const int mode = FLAG_MODE_SET); - void extract(utility::outputStream& os, utility::progressListener* progress = NULL, const size_t start = 0, const size_t length = -1, const bool peek = false) const; - void extractPart(const shared_ptr & p, utility::outputStream& os, utility::progressListener* progress = NULL, const size_t start = 0, const size_t length = -1, const bool peek = false) const; + void extract( + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; + + void extractPart( + const shared_ptr & p, + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; void fetchPartHeader(const shared_ptr & p); @@ -90,7 +103,15 @@ private: shared_ptr
getOrCreateHeader(); - void extractImpl(utility::outputStream& os, utility::progressListener* progress, const size_t start, const size_t length, const size_t partialStart, const size_t partialLength, const bool peek) const; + void extractImpl( + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const size_t partialStart, + const size_t partialLength, + const bool peek + ) const; weak_ptr m_folder; diff --git a/src/vmime/net/maildir/maildirMessagePart.cpp b/src/vmime/net/maildir/maildirMessagePart.cpp index 787c0198..9d30e24d 100644 --- a/src/vmime/net/maildir/maildirMessagePart.cpp +++ b/src/vmime/net/maildir/maildirMessagePart.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,9 +36,15 @@ namespace net { namespace maildir { -maildirMessagePart::maildirMessagePart(const shared_ptr & parent, const size_t number, const bodyPart& part) - : m_parent(parent), m_header(null), m_number(number) -{ +maildirMessagePart::maildirMessagePart( + const shared_ptr & parent, + const size_t number, + const bodyPart& part +) + : m_parent(parent), + m_header(null), + m_number(number) { + m_headerParsedOffset = part.getHeader()->getParsedOffset(); m_headerParsedLength = part.getHeader()->getParsedLength(); @@ -51,98 +57,104 @@ maildirMessagePart::maildirMessagePart(const shared_ptr & pa } -maildirMessagePart::~maildirMessagePart() -{ +maildirMessagePart::~maildirMessagePart() { + } -void maildirMessagePart::initStructure(const bodyPart& part) -{ - if (part.getBody()->getPartList().size() == 0) +void maildirMessagePart::initStructure(const bodyPart& part) { + + if (part.getBody()->getPartList().size() == 0) { + m_structure = null; - else - { - m_structure = make_shared - (dynamicCast (shared_from_this()), - part.getBody()->getPartList()); + + } else { + + m_structure = make_shared ( + dynamicCast (shared_from_this()), part.getBody()->getPartList() + ); } } -shared_ptr maildirMessagePart::getStructure() const -{ - if (m_structure != NULL) +shared_ptr maildirMessagePart::getStructure() const { + + if (m_structure) { return m_structure; - else + } else { return maildirMessageStructure::emptyStructure(); + } } -shared_ptr maildirMessagePart::getStructure() -{ - if (m_structure != NULL) +shared_ptr maildirMessagePart::getStructure() { + + if (m_structure) { return m_structure; - else + } else { return maildirMessageStructure::emptyStructure(); + } } -const mediaType& maildirMessagePart::getType() const -{ +const mediaType& maildirMessagePart::getType() const { + return m_mediaType; } -size_t maildirMessagePart::getSize() const -{ +size_t maildirMessagePart::getSize() const { + return m_size; } -size_t maildirMessagePart::getNumber() const -{ +size_t maildirMessagePart::getNumber() const { + return m_number; } -shared_ptr maildirMessagePart::getHeader() const -{ - if (m_header == NULL) +shared_ptr maildirMessagePart::getHeader() const { + + if (!m_header) { throw exceptions::unfetched_object(); - else + } else { return m_header; + } } -header& maildirMessagePart::getOrCreateHeader() -{ - if (m_header != NULL) +header& maildirMessagePart::getOrCreateHeader() { + + if (m_header) { return *m_header; - else + } else { return *(m_header = make_shared
()); + } } -size_t maildirMessagePart::getHeaderParsedOffset() const -{ +size_t maildirMessagePart::getHeaderParsedOffset() const { + return m_headerParsedOffset; } -size_t maildirMessagePart::getHeaderParsedLength() const -{ +size_t maildirMessagePart::getHeaderParsedLength() const { + return m_headerParsedLength; } -size_t maildirMessagePart::getBodyParsedOffset() const -{ +size_t maildirMessagePart::getBodyParsedOffset() const { + return m_bodyParsedOffset; } -size_t maildirMessagePart::getBodyParsedLength() const -{ +size_t maildirMessagePart::getBodyParsedLength() const { + return m_bodyParsedLength; } diff --git a/src/vmime/net/maildir/maildirMessagePart.hpp b/src/vmime/net/maildir/maildirMessagePart.hpp index 6aa80019..dd863a2b 100644 --- a/src/vmime/net/maildir/maildirMessagePart.hpp +++ b/src/vmime/net/maildir/maildirMessagePart.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,7 +46,12 @@ class maildirMessagePart : public messagePart { public: - maildirMessagePart(const shared_ptr & parent, const size_t number, const bodyPart& part); + maildirMessagePart( + const shared_ptr & parent, + const size_t number, + const bodyPart& part + ); + ~maildirMessagePart(); diff --git a/src/vmime/net/maildir/maildirMessageStructure.cpp b/src/vmime/net/maildir/maildirMessageStructure.cpp index e01c2a92..1e2f2cc5 100644 --- a/src/vmime/net/maildir/maildirMessageStructure.cpp +++ b/src/vmime/net/maildir/maildirMessageStructure.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,8 +44,11 @@ maildirMessageStructure::maildirMessageStructure() } -maildirMessageStructure::maildirMessageStructure(const shared_ptr & parent, const bodyPart& part) -{ +maildirMessageStructure::maildirMessageStructure( + const shared_ptr & parent, + const bodyPart& part +) { + shared_ptr mpart = make_shared (parent, 0, part); mpart->initStructure(part); @@ -53,10 +56,13 @@ maildirMessageStructure::maildirMessageStructure(const shared_ptr & parent, const std::vector >& list) -{ - for (size_t i = 0 ; i < list.size() ; ++i) - { +maildirMessageStructure::maildirMessageStructure( + const shared_ptr & parent, + const std::vector >& list +) { + + for (size_t i = 0 ; i < list.size() ; ++i) { + shared_ptr mpart = make_shared (parent, i, *list[i]); mpart->initStructure(*list[i]); @@ -65,27 +71,27 @@ maildirMessageStructure::maildirMessageStructure(const shared_ptr maildirMessageStructure::getPartAt(const size_t x) const -{ +shared_ptr maildirMessageStructure::getPartAt(const size_t x) const { + return m_parts[x]; } -shared_ptr maildirMessageStructure::getPartAt(const size_t x) -{ +shared_ptr maildirMessageStructure::getPartAt(const size_t x) { + return m_parts[x]; } -size_t maildirMessageStructure::getPartCount() const -{ +size_t maildirMessageStructure::getPartCount() const { + return m_parts.size(); } // static -shared_ptr maildirMessageStructure::emptyStructure() -{ +shared_ptr maildirMessageStructure::emptyStructure() { + return m_emptyStructure; } diff --git a/src/vmime/net/maildir/maildirMessageStructure.hpp b/src/vmime/net/maildir/maildirMessageStructure.hpp index fce5db6f..1a20ea45 100644 --- a/src/vmime/net/maildir/maildirMessageStructure.hpp +++ b/src/vmime/net/maildir/maildirMessageStructure.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,13 +42,19 @@ namespace maildir { class maildirMessagePart; -class maildirMessageStructure : public messageStructure -{ +class maildirMessageStructure : public messageStructure { + public: maildirMessageStructure(); - maildirMessageStructure(const shared_ptr & parent, const bodyPart& part); - maildirMessageStructure(const shared_ptr & parent, const std::vector >& list); + maildirMessageStructure( + const shared_ptr & parent, + const bodyPart& part + ); + maildirMessageStructure( + const shared_ptr & parent, + const std::vector >& list + ); shared_ptr getPartAt(const size_t x) const; diff --git a/src/vmime/net/maildir/maildirServiceInfos.cpp b/src/vmime/net/maildir/maildirServiceInfos.cpp index 974a0c21..f9d92d37 100644 --- a/src/vmime/net/maildir/maildirServiceInfos.cpp +++ b/src/vmime/net/maildir/maildirServiceInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,21 +35,20 @@ namespace net { namespace maildir { -maildirServiceInfos::maildirServiceInfos() -{ +maildirServiceInfos::maildirServiceInfos() { + } -const string maildirServiceInfos::getPropertyPrefix() const -{ +const string maildirServiceInfos::getPropertyPrefix() const { + return "store.maildir."; } -const maildirServiceInfos::props& maildirServiceInfos::getProperties() const -{ - static props maildirProps = - { +const maildirServiceInfos::props& maildirServiceInfos::getProperties() const { + + static props maildirProps = { property(serviceInfos::property::SERVER_ROOTPATH, serviceInfos::property::FLAG_REQUIRED) }; @@ -57,8 +56,8 @@ const maildirServiceInfos::props& maildirServiceInfos::getProperties() const } -const std::vector maildirServiceInfos::getAvailableProperties() const -{ +const std::vector maildirServiceInfos::getAvailableProperties() const { + std::vector list; const props& p = getProperties(); diff --git a/src/vmime/net/maildir/maildirServiceInfos.hpp b/src/vmime/net/maildir/maildirServiceInfos.hpp index 70ddc6dc..827a7d78 100644 --- a/src/vmime/net/maildir/maildirServiceInfos.hpp +++ b/src/vmime/net/maildir/maildirServiceInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,15 +41,13 @@ namespace maildir { /** Information about maildir service. */ +class VMIME_EXPORT maildirServiceInfos : public serviceInfos { -class VMIME_EXPORT maildirServiceInfos : public serviceInfos -{ public: maildirServiceInfos(); - struct props - { + struct props { serviceInfos::property PROPERTY_SERVER_ROOTPATH; }; diff --git a/src/vmime/net/maildir/maildirStore.cpp b/src/vmime/net/maildir/maildirStore.cpp index 4029eb7d..a994f45c 100644 --- a/src/vmime/net/maildir/maildirStore.cpp +++ b/src/vmime/net/maildir/maildirStore.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -52,90 +52,112 @@ namespace net { namespace maildir { -maildirStore::maildirStore(const shared_ptr & sess, const shared_ptr & auth) - : store(sess, getInfosInstance(), auth), m_connected(false) -{ +maildirStore::maildirStore( + const shared_ptr & sess, + const shared_ptr & auth +) + : store(sess, getInfosInstance(), auth), + m_connected(false) { + } -maildirStore::~maildirStore() -{ - try - { - if (isConnected()) +maildirStore::~maildirStore() { + + try { + + if (isConnected()) { disconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -const string maildirStore::getProtocolName() const -{ +const string maildirStore::getProtocolName() const { + return "maildir"; } -shared_ptr maildirStore::getRootFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); +shared_ptr maildirStore::getRootFolder() { - return shared_ptr - (new maildirFolder(folder::path(), - dynamicCast (shared_from_this()))); + if (!isConnected()) { + throw exceptions::illegal_state("Not connected"); + } + + return shared_ptr ( + new maildirFolder( + folder::path(), + dynamicCast (shared_from_this()) + ) + ); } -shared_ptr maildirStore::getDefaultFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); +shared_ptr maildirStore::getDefaultFolder() { - return shared_ptr - (new maildirFolder(folder::path::component("inbox"), - dynamicCast (shared_from_this()))); + if (!isConnected()) { + throw exceptions::illegal_state("Not connected"); + } + + return shared_ptr ( + new maildirFolder( + folder::path::component("inbox"), + dynamicCast (shared_from_this()) + ) + ); } -shared_ptr maildirStore::getFolder(const folder::path& path) -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); +shared_ptr maildirStore::getFolder(const folder::path& path) { - return shared_ptr - (new maildirFolder(path, dynamicCast (shared_from_this()))); + if (!isConnected()) { + throw exceptions::illegal_state("Not connected"); + } + + return shared_ptr ( + new maildirFolder( + path, + dynamicCast (shared_from_this()) + ) + ); } -bool maildirStore::isValidFolderName(const folder::path::component& name) const -{ - if (!platform::getHandler()->getFileSystemFactory()->isValidPathComponent(name)) +bool maildirStore::isValidFolderName(const folder::path::component& name) const { + + if (!platform::getHandler()->getFileSystemFactory()->isValidPathComponent(name)) { return false; + } const string& buf = name.getBuffer(); // Name cannot start/end with spaces - if (utility::stringUtils::trim(buf) != buf) + if (utility::stringUtils::trim(buf) != buf) { return false; + } // Name cannot start with '.' const size_t length = buf.length(); size_t pos = 0; - while ((pos < length) && (buf[pos] == '.')) + while ((pos < length) && (buf[pos] == '.')) { ++pos; + } return (pos == 0); } -void maildirStore::connect() -{ - if (isConnected()) +void maildirStore::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } // Get root directory shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); @@ -145,14 +167,11 @@ void maildirStore::connect() shared_ptr rootDir = fsf->create(m_fsPath); // Try to create the root directory if it does not exist - if (!(rootDir->exists() && rootDir->isDirectory())) - { - try - { + if (!(rootDir->exists() && rootDir->isDirectory())) { + + try { rootDir->createDirectory(); - } - catch (exceptions::filesystem_exception& e) - { + } catch (exceptions::filesystem_exception& e) { throw exceptions::connection_error("Cannot create root directory.", e); } } @@ -163,29 +182,29 @@ void maildirStore::connect() } -bool maildirStore::isConnected() const -{ - return (m_connected); +bool maildirStore::isConnected() const { + + return m_connected; } -bool maildirStore::isSecuredConnection() const -{ +bool maildirStore::isSecuredConnection() const { + return false; } -shared_ptr maildirStore::getConnectionInfos() const -{ +shared_ptr maildirStore::getConnectionInfos() const { + return make_shared ("localhost", static_cast (0)); } -void maildirStore::disconnect() -{ +void maildirStore::disconnect() { + for (std::list ::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { + it != m_folders.end() ; ++it) { + (*it)->onStoreDisconnected(); } @@ -195,53 +214,56 @@ void maildirStore::disconnect() } -void maildirStore::noop() -{ +void maildirStore::noop() { + // Nothing to do. } -shared_ptr maildirStore::getFormat() -{ +shared_ptr maildirStore::getFormat() { + return m_format; } -shared_ptr maildirStore::getFormat() const -{ +shared_ptr maildirStore::getFormat() const { + return m_format; } -void maildirStore::registerFolder(maildirFolder* folder) -{ +void maildirStore::registerFolder(maildirFolder* folder) { + m_folders.push_back(folder); } -void maildirStore::unregisterFolder(maildirFolder* folder) -{ +void maildirStore::unregisterFolder(maildirFolder* folder) { + std::list ::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); - if (it != m_folders.end()) m_folders.erase(it); + + if (it != m_folders.end()) { + m_folders.erase(it); + } } -const utility::path& maildirStore::getFileSystemPath() const -{ - return (m_fsPath); +const utility::path& maildirStore::getFileSystemPath() const { + + return m_fsPath; } -int maildirStore::getCapabilities() const -{ - return (CAPABILITY_CREATE_FOLDER | - CAPABILITY_RENAME_FOLDER | - CAPABILITY_ADD_MESSAGE | - CAPABILITY_COPY_MESSAGE | - CAPABILITY_DELETE_MESSAGE | - CAPABILITY_PARTIAL_FETCH | - CAPABILITY_MESSAGE_FLAGS | - CAPABILITY_EXTRACT_PART); +int maildirStore::getCapabilities() const { + + return CAPABILITY_CREATE_FOLDER | + CAPABILITY_RENAME_FOLDER | + CAPABILITY_ADD_MESSAGE | + CAPABILITY_COPY_MESSAGE | + CAPABILITY_DELETE_MESSAGE | + CAPABILITY_PARTIAL_FETCH | + CAPABILITY_MESSAGE_FLAGS | + CAPABILITY_EXTRACT_PART; } @@ -251,14 +273,14 @@ int maildirStore::getCapabilities() const maildirServiceInfos maildirStore::sm_infos; -const serviceInfos& maildirStore::getInfosInstance() -{ +const serviceInfos& maildirStore::getInfosInstance() { + return sm_infos; } -const serviceInfos& maildirStore::getInfos() const -{ +const serviceInfos& maildirStore::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/maildir/maildirStore.hpp b/src/vmime/net/maildir/maildirStore.hpp index ba7b8c13..13255c0a 100644 --- a/src/vmime/net/maildir/maildirStore.hpp +++ b/src/vmime/net/maildir/maildirStore.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -53,14 +53,17 @@ class maildirFolder; /** maildir store service. */ +class VMIME_EXPORT maildirStore : public store { -class VMIME_EXPORT maildirStore : public store -{ friend class maildirFolder; public: - maildirStore(const shared_ptr & sess, const shared_ptr & auth); + maildirStore( + const shared_ptr & sess, + const shared_ptr & auth + ); + ~maildirStore(); const string getProtocolName() const; diff --git a/src/vmime/net/maildir/maildirUtils.cpp b/src/vmime/net/maildir/maildirUtils.cpp index 1c75805a..9942e56e 100644 --- a/src/vmime/net/maildir/maildirUtils.cpp +++ b/src/vmime/net/maildir/maildirUtils.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,17 +41,17 @@ namespace net { namespace maildir { -bool maildirUtils::isMessageFile(const utility::file& file) -{ +bool maildirUtils::isMessageFile(const utility::file& file) { + // Ignore files which name begins with '.' if (file.isFile() && file.getFullPath().getLastComponent().getBuffer().length() >= 1 && - file.getFullPath().getLastComponent().getBuffer()[0] != '.') - { - return (true); + file.getFullPath().getLastComponent().getBuffer()[0] != '.') { + + return true; } - return (false); + return false; } @@ -68,28 +68,28 @@ bool maildirUtils::isMessageFile(const utility::file& file) // characters when reading file names. -const utility::file::path::component maildirUtils::extractId - (const utility::file::path::component& filename) -{ +const utility::file::path::component maildirUtils::extractId( + const utility::file::path::component& filename +) { + size_t sep = filename.getBuffer().rfind(':'); // try colon - if (sep == string::npos) - { + if (sep == string::npos) { sep = filename.getBuffer().rfind('-'); // try dash (Windows) if (sep == string::npos) return (filename); } - return (utility::path::component - (string(filename.getBuffer().begin(), filename.getBuffer().begin() + sep))); + return utility::path::component( + string(filename.getBuffer().begin(), filename.getBuffer().begin() + sep) + ); } -int maildirUtils::extractFlags(const utility::file::path::component& comp) -{ +int maildirUtils::extractFlags(const utility::file::path::component& comp) { + size_t sep = comp.getBuffer().rfind(':'); // try colon - if (sep == string::npos) - { + if (sep == string::npos) { sep = comp.getBuffer().rfind('-'); // try dash (Windows) if (sep == string::npos) return 0; } @@ -99,25 +99,24 @@ int maildirUtils::extractFlags(const utility::file::path::component& comp) int flags = 0; - for (size_t i = 0 ; i < count ; ++i) - { - switch (flagsString[i]) - { - case 'R': case 'r': flags |= message::FLAG_REPLIED; break; - case 'S': case 's': flags |= message::FLAG_SEEN; break; - case 'T': case 't': flags |= message::FLAG_DELETED; break; - case 'F': case 'f': flags |= message::FLAG_MARKED; break; - case 'P': case 'p': flags |= message::FLAG_PASSED; break; - case 'D': case 'd': flags |= message::FLAG_DRAFT; break; + for (size_t i = 0 ; i < count ; ++i) { + + switch (flagsString[i]) { + case 'R': case 'r': flags |= message::FLAG_REPLIED; break; + case 'S': case 's': flags |= message::FLAG_SEEN; break; + case 'T': case 't': flags |= message::FLAG_DELETED; break; + case 'F': case 'f': flags |= message::FLAG_MARKED; break; + case 'P': case 'p': flags |= message::FLAG_PASSED; break; + case 'D': case 'd': flags |= message::FLAG_DRAFT; break; } } - return (flags); + return flags; } -const utility::file::path::component maildirUtils::buildFlags(const int flags) -{ +const utility::file::path::component maildirUtils::buildFlags(const int flags) { + string str; str.reserve(8); @@ -130,24 +129,28 @@ const utility::file::path::component maildirUtils::buildFlags(const int flags) if (flags & message::FLAG_DELETED) str += "T"; if (flags & message::FLAG_DRAFT) str += "D"; - return (utility::file::path::component(str)); + return utility::file::path::component(str); } -const utility::file::path::component maildirUtils::buildFilename - (const utility::file::path::component& id, const int flags) -{ - if (flags == message::FLAG_RECENT) +const utility::file::path::component maildirUtils::buildFilename( + const utility::file::path::component& id, + const int flags +) { + + if (flags == message::FLAG_RECENT) { return id; - else - return (buildFilename(id, buildFlags(flags))); + } else { + return buildFilename(id, buildFlags(flags)); + } } -const utility::file::path::component maildirUtils::buildFilename - (const utility::file::path::component& id, - const utility::file::path::component& flags) -{ +const utility::file::path::component maildirUtils::buildFilename( + const utility::file::path::component& id, + const utility::file::path::component& flags +) { + #if VMIME_PLATFORM_IS_WINDOWS static const char DELIMITER[] = "-"; #else @@ -158,8 +161,8 @@ const utility::file::path::component maildirUtils::buildFilename } -const utility::file::path::component maildirUtils::generateId() -{ +const utility::file::path::component maildirUtils::generateId() { + std::ostringstream oss; oss.imbue(std::locale::classic()); @@ -171,70 +174,64 @@ const utility::file::path::component maildirUtils::generateId() oss << "."; oss << platform::getHandler()->getHostName(); - return (utility::file::path::component(oss.str())); + return utility::file::path::component(oss.str()); } -void maildirUtils::recursiveFSDelete(const shared_ptr & dir) -{ +void maildirUtils::recursiveFSDelete(const shared_ptr & dir) { + shared_ptr files = dir->getFiles(); // First, delete files and subdirectories in this directory - while (files->hasMoreElements()) - { + while (files->hasMoreElements()) { + shared_ptr file = files->nextElement(); - if (file->isDirectory()) - { + if (file->isDirectory()) { + maildirUtils::recursiveFSDelete(file); - } - else - { - try - { + + } else { + + try { file->remove(); - } - catch (exceptions::filesystem_exception&) - { + } catch (exceptions::filesystem_exception&) { // Ignore } } } // Then, delete this (empty) directory - try - { + try { dir->remove(); - } - catch (exceptions::filesystem_exception&) - { + } catch (exceptions::filesystem_exception&) { // Ignore } } -class maildirMessageSetEnumerator : public messageSetEnumerator -{ +class maildirMessageSetEnumerator : public messageSetEnumerator { + public: maildirMessageSetEnumerator(const size_t msgCount) - : m_msgCount(msgCount) - { + : m_msgCount(msgCount) { } - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) { + size_t last = range.getLast(); if (last == size_t(-1)) last = m_msgCount; - for (size_t i = range.getFirst() ; i <= last ; ++i) + for (size_t i = range.getFirst() ; i <= last ; ++i) { list.push_back(i); + } } - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) - { + void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) { + // Not supported } @@ -249,8 +246,11 @@ private: // static -const std::vector maildirUtils::messageSetToNumberList(const messageSet& msgs, const size_t msgCount) -{ +const std::vector maildirUtils::messageSetToNumberList( + const messageSet& msgs, + const size_t msgCount +) { + maildirMessageSetEnumerator en(msgCount); msgs.enumerate(en); @@ -263,17 +263,19 @@ const std::vector maildirUtils::messageSetToNumberList(const messageSet // messageIdComparator // -maildirUtils::messageIdComparator::messageIdComparator - (const utility::file::path::component& comp) - : m_comp(maildirUtils::extractId(comp)) -{ +maildirUtils::messageIdComparator::messageIdComparator( + const utility::file::path::component& comp +) + : m_comp(maildirUtils::extractId(comp)) { + } -bool maildirUtils::messageIdComparator::operator() - (const utility::file::path::component& other) const -{ - return (m_comp == maildirUtils::extractId(other)); +bool maildirUtils::messageIdComparator::operator()( + const utility::file::path::component& other +) const { + + return m_comp == maildirUtils::extractId(other); } diff --git a/src/vmime/net/maildir/maildirUtils.hpp b/src/vmime/net/maildir/maildirUtils.hpp index 6f120636..94ab9983 100644 --- a/src/vmime/net/maildir/maildirUtils.hpp +++ b/src/vmime/net/maildir/maildirUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -47,16 +47,15 @@ class maildirStore; /** Miscellaneous helpers functions for maildir messaging system. */ +class VMIME_EXPORT maildirUtils { -class VMIME_EXPORT maildirUtils -{ public: /** Comparator for message filenames, based only on the * unique identifier part of the filename. */ - class messageIdComparator - { + class messageIdComparator { + public: messageIdComparator(const utility::file::path::component& comp); @@ -110,7 +109,10 @@ public: * @param flags flags part of the filename * @return message filename */ - static const utility::file::path::component buildFilename(const utility::file::path::component& id, const utility::file::path::component& flags); + static const utility::file::path::component buildFilename( + const utility::file::path::component& id, + const utility::file::path::component& flags + ); /** Build a filename with the specified id and flags. * @@ -118,7 +120,10 @@ public: * @param flags set of flags * @return message filename */ - static const utility::file::path::component buildFilename(const utility::file::path::component& id, const int flags); + static const utility::file::path::component buildFilename( + const utility::file::path::component& id, + const int flags + ); /** Generate a new unique message identifier. * @@ -138,7 +143,10 @@ public: * @param msgCount number of messages in folder * @return list of message numbers */ - static const std::vector messageSetToNumberList(const messageSet& msgs, const size_t msgCount); + static const std::vector messageSetToNumberList( + const messageSet& msgs, + const size_t msgCount + ); }; diff --git a/src/vmime/net/message.cpp b/src/vmime/net/message.cpp index 1a0c8c2c..2d6f995a 100644 --- a/src/vmime/net/message.cpp +++ b/src/vmime/net/message.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,20 +41,20 @@ string messagePart::getName() const return {}; } -shared_ptr messagePart::getPartAt(const size_t pos) const -{ +shared_ptr messagePart::getPartAt(const size_t pos) const { + return getStructure()->getPartAt(pos); } -shared_ptr messagePart::getPartAt(const size_t pos) -{ +shared_ptr messagePart::getPartAt(const size_t pos) { + return getStructure()->getPartAt(pos); } -size_t messagePart::getPartCount() const -{ +size_t messagePart::getPartCount() const { + return getStructure()->getPartCount(); } @@ -63,19 +63,19 @@ size_t messagePart::getPartCount() const // message::uid -message::uid::uid() -{ +message::uid::uid() { + } message::uid::uid(const string& uid) - : m_str(uid) -{ + : m_str(uid) { + } -message::uid::uid(const unsigned long uid) -{ +message::uid::uid(const unsigned long uid) { + std::ostringstream oss; oss.imbue(std::locale::classic()); oss << uid; @@ -85,33 +85,33 @@ message::uid::uid(const unsigned long uid) message::uid::uid(const char* uid) - : m_str(uid) -{ + : m_str(uid) { + } -message::uid::uid(const uid& other) -{ +message::uid::uid(const uid& other) { + m_str = other.m_str; } -message::uid& message::uid::operator=(const uid& other) -{ +message::uid& message::uid::operator=(const uid& other) { + m_str = other.m_str; return *this; } -message::uid& message::uid::operator=(const string& uid) -{ +message::uid& message::uid::operator=(const string& uid) { + m_str = uid; return *this; } -message::uid& message::uid::operator=(const unsigned long uid) -{ +message::uid& message::uid::operator=(const unsigned long uid) { + std::ostringstream oss; oss.imbue(std::locale::classic()); oss << uid; @@ -122,26 +122,26 @@ message::uid& message::uid::operator=(const unsigned long uid) } -message::uid::operator string() const -{ +message::uid::operator string() const { + return m_str; } -bool message::uid::empty() const -{ +bool message::uid::empty() const { + return m_str.empty(); } -bool message::uid::operator==(const uid& other) const -{ +bool message::uid::operator==(const uid& other) const { + return m_str == other.m_str; } -std::ostream& operator<<(std::ostream& os, const message::uid& uid) -{ +std::ostream& operator<<(std::ostream& os, const message::uid& uid) { + os << static_cast (uid); return os; } diff --git a/src/vmime/net/message.hpp b/src/vmime/net/message.hpp index 68cce415..c0a2839b 100644 --- a/src/vmime/net/message.hpp +++ b/src/vmime/net/message.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -49,13 +49,12 @@ class messageStructure; /** A MIME part in a message. */ +class VMIME_EXPORT messagePart : public object, public enable_shared_from_this { -class VMIME_EXPORT messagePart : public object, public enable_shared_from_this -{ protected: messagePart() { } - messagePart(const messagePart&) : object(), enable_shared_from_this () { } + messagePart(const messagePart&); virtual ~messagePart() { } @@ -100,13 +99,13 @@ public: virtual size_t getNumber() const = 0; /** Return the name of this part. In particular, this corresponds to - * the attachment file name for attachment parts. - * - * The part name may be empty if the part does not advertise it or - * if the underlying protocol does not support it. - * - * @return part name - */ + * the attachment file name for attachment parts. + * + * The part name may be empty if the part does not advertise it or + * if the underlying protocol does not support it. + * + * @return part name + */ virtual string getName() const; /** Return the sub-part at the specified position (zero is the @@ -135,13 +134,12 @@ public: /** Structure of a MIME part/message. */ +class VMIME_EXPORT messageStructure : public object, public enable_shared_from_this { -class VMIME_EXPORT messageStructure : public object, public enable_shared_from_this -{ protected: messageStructure() { } - messageStructure(const messageStructure&) : object(), enable_shared_from_this () { } + messageStructure(const messageStructure&); public: @@ -173,28 +171,24 @@ public: /** Abstract representation of a message in a store/transport service. */ +class VMIME_EXPORT message : public object, public enable_shared_from_this { -class VMIME_EXPORT message : public object, public enable_shared_from_this -{ protected: message() { } - message(const message&) : object(), enable_shared_from_this () { } + message(const message&); - enum PrivateConstants - { + enum PrivateConstants { FLAG_UNDEFINED = 9999 /**< Used internally to indicate flags have not been initialized yet. */ }; public: - virtual ~message() { } - /** The type for an unique message identifier. */ - class VMIME_EXPORT uid - { + class VMIME_EXPORT uid { + public: uid(); @@ -265,8 +259,7 @@ public: /** Possible flags for a message. */ - enum Flags - { + enum Flags { FLAG_SEEN = (1 << 0), /**< Message has been seen. */ FLAG_RECENT = (1 << 1), /**< Message has been recently received. */ FLAG_DELETED = (1 << 2), /**< Message is marked for deletion. */ @@ -278,8 +271,7 @@ public: /** Methods for setting the flags. */ - enum FlagsModes - { + enum FlagsModes { FLAG_MODE_SET, /**< Set (replace) the flags. */ FLAG_MODE_ADD, /**< Add the flags. */ FLAG_MODE_REMOVE /**< Remove the flags. */ @@ -310,12 +302,13 @@ public: * be supported by the protocol (IMAP supports this), but it will NOT throw * an exception if not supported. */ - virtual void extract - (utility::outputStream& os, - utility::progressListener* progress = NULL, - const size_t start = 0, - const size_t length = -1, - const bool peek = false) const = 0; + virtual void extract( + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const = 0; /** Extract the specified MIME part of the message (header + contents). * @@ -330,13 +323,14 @@ public: * be supported by the protocol (IMAP supports this), but it will NOT throw * an exception if not supported. */ - virtual void extractPart - (const shared_ptr & p, - utility::outputStream& os, - utility::progressListener* progress = NULL, - const size_t start = 0, - const size_t length = -1, - const bool peek = false) const = 0; + virtual void extractPart( + const shared_ptr & p, + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const = 0; /** Fetch the MIME header for the specified part. * diff --git a/src/vmime/net/messageSet.cpp b/src/vmime/net/messageSet.cpp index e30ebc5c..654da413 100644 --- a/src/vmime/net/messageSet.cpp +++ b/src/vmime/net/messageSet.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,62 +40,68 @@ namespace net { // messageRange -messageRange::messageRange() -{ +messageRange::messageRange() { + } -messageRange::~messageRange() -{ +messageRange::~messageRange() { + } // numberMessageRange numberMessageRange::numberMessageRange(const size_t number) - : m_first(number), m_last(number) -{ - if (number < 1) + : m_first(number), + m_last(number) { + + if (number < 1) { throw std::invalid_argument("number"); + } } numberMessageRange::numberMessageRange(const size_t first, const size_t last) - : m_first(first), m_last(last) -{ - if (first < 1 || first == static_cast (-1)) + : m_first(first), + m_last(last) { + + if (first < 1 || first == static_cast (-1)) { throw std::invalid_argument("first"); - else if (last != static_cast (-1) && last < first) + } else if (last != static_cast (-1) && last < first) { throw std::invalid_argument("last"); + } } numberMessageRange::numberMessageRange(const numberMessageRange& other) - : messageRange(), m_first(other.m_first), m_last(other.m_last) -{ + : messageRange(), + m_first(other.m_first), + m_last(other.m_last) { + } -size_t numberMessageRange::getFirst() const -{ +size_t numberMessageRange::getFirst() const { + return m_first; } -size_t numberMessageRange::getLast() const -{ +size_t numberMessageRange::getLast() const { + return m_last; } -void numberMessageRange::enumerate(messageSetEnumerator& en) const -{ +void numberMessageRange::enumerate(messageSetEnumerator& en) const { + en.enumerateNumberMessageRange(*this); } -messageRange* numberMessageRange::clone() const -{ +messageRange* numberMessageRange::clone() const { + return new numberMessageRange(*this); } @@ -103,43 +109,47 @@ messageRange* numberMessageRange::clone() const // UIDMessageRange UIDMessageRange::UIDMessageRange(const message::uid& uid) - : m_first(uid), m_last(uid) -{ + : m_first(uid), + m_last(uid) { + } UIDMessageRange::UIDMessageRange(const message::uid& first, const message::uid& last) - : m_first(first), m_last(last) -{ + : m_first(first), + m_last(last) { + } UIDMessageRange::UIDMessageRange(const UIDMessageRange& other) - : messageRange(), m_first(other.m_first), m_last(other.m_last) -{ + : messageRange(), + m_first(other.m_first), + m_last(other.m_last) { + } -const message::uid UIDMessageRange::getFirst() const -{ +const message::uid UIDMessageRange::getFirst() const { + return m_first; } -const message::uid UIDMessageRange::getLast() const -{ +const message::uid UIDMessageRange::getLast() const { + return m_last; } -void UIDMessageRange::enumerate(messageSetEnumerator& en) const -{ +void UIDMessageRange::enumerate(messageSetEnumerator& en) const { + en.enumerateUIDMessageRange(*this); } -messageRange* UIDMessageRange::clone() const -{ +messageRange* UIDMessageRange::clone() const { + return new UIDMessageRange(*this); } @@ -147,38 +157,40 @@ messageRange* UIDMessageRange::clone() const // messageSet -messageSet::messageSet() -{ +messageSet::messageSet() { + } messageSet::messageSet(const messageSet& other) - : object() -{ + : object() { + m_ranges.resize(other.m_ranges.size()); - for (size_t i = 0, n = other.m_ranges.size() ; i < n ; ++i) + for (size_t i = 0, n = other.m_ranges.size() ; i < n ; ++i) { m_ranges[i] = other.m_ranges[i]->clone(); + } } -messageSet::~messageSet() -{ - for (size_t i = 0, n = m_ranges.size() ; i < n ; ++i) +messageSet::~messageSet() { + + for (size_t i = 0, n = m_ranges.size() ; i < n ; ++i) { delete m_ranges[i]; + } } // static -messageSet messageSet::empty() -{ +messageSet messageSet::empty() { + return messageSet(); } // static -messageSet messageSet::byNumber(const size_t number) -{ +messageSet messageSet::byNumber(const size_t number) { + messageSet set; set.m_ranges.push_back(new numberMessageRange(number)); @@ -187,8 +199,8 @@ messageSet messageSet::byNumber(const size_t number) // static -messageSet messageSet::byNumber(const size_t first, const size_t last) -{ +messageSet messageSet::byNumber(const size_t first, const size_t last) { + messageSet set; set.m_ranges.push_back(new numberMessageRange(first, last)); @@ -197,8 +209,8 @@ messageSet messageSet::byNumber(const size_t first, const size_t last) // static -messageSet messageSet::byNumber(const std::vector & numbers) -{ +messageSet messageSet::byNumber(const std::vector & numbers) { + // Sort a copy of the list std::vector sortedNumbers; @@ -212,29 +224,31 @@ messageSet messageSet::byNumber(const std::vector & numbers) messageSet set; for (std::vector ::const_iterator it = sortedNumbers.begin() ; - it != sortedNumbers.end() ; ++it) - { + it != sortedNumbers.end() ; ++it) { + const size_t current = *it; - if (current == previous) + if (current == previous) { continue; // skip duplicates + } - if (current == static_cast (-1)) + if (current == static_cast (-1)) { throw std::invalid_argument("numbers"); + } + + if (previous == static_cast (-1)) { - if (previous == static_cast (-1)) - { previous = current; rangeStart = current; - } - else - { - if (current == previous + 1) - { + + } else { + + if (current == previous + 1) { + previous = current; - } - else - { + + } else { + set.m_ranges.push_back(new numberMessageRange(rangeStart, previous)); previous = current; @@ -250,8 +264,8 @@ messageSet messageSet::byNumber(const std::vector & numbers) // static -messageSet messageSet::byUID(const message::uid& uid) -{ +messageSet messageSet::byUID(const message::uid& uid) { + messageSet set; set.m_ranges.push_back(new UIDMessageRange(uid)); @@ -259,8 +273,8 @@ messageSet messageSet::byUID(const message::uid& uid) } -messageSet messageSet::byUID(const message::uid& first, const message::uid& last) -{ +messageSet messageSet::byUID(const message::uid& first, const message::uid& last) { + messageSet set; set.m_ranges.push_back(new UIDMessageRange(first, last)); @@ -268,27 +282,29 @@ messageSet messageSet::byUID(const message::uid& first, const message::uid& last } -messageSet messageSet::byUID(const std::vector & uids) -{ +messageSet messageSet::byUID(const std::vector & uids) { + std::vector numericUIDs; - for (size_t i = 0, n = uids.size() ; i < n ; ++i) - { + for (size_t i = 0, n = uids.size() ; i < n ; ++i) { + const string uid = uids[i]; int numericUID = 0; const char* p = uid.c_str(); - for ( ; *p >= '0' && *p <= '9' ; ++p) - numericUID = (numericUID * 10) + (*p - '0'); + for ( ; *p >= '0' && *p <= '9' ; ++p) { + numericUID = (numericUID * 10) + (*p - '0'); + } + + if (*p != '\0') { - if (*p != '\0') - { messageSet set; // Non-numeric UID, fall back to plain UID list (single-UID ranges) - for (size_t i = 0, n = uids.size() ; i < n ; ++i) + for (size_t i = 0, n = uids.size() ; i < n ; ++i) { set.m_ranges.push_back(new UIDMessageRange(uids[i])); + } return set; } @@ -309,29 +325,33 @@ messageSet messageSet::byUID(const std::vector & uids) messageSet set; for (std::vector ::const_iterator it = sortedUIDs.begin() ; - it != sortedUIDs.end() ; ++it) - { + it != sortedUIDs.end() ; ++it) { + const vmime_uint32 current = *it; - if (current == previous) + if (current == previous) { continue; // skip duplicates + } + + if (previous == static_cast (-1)) { - if (previous == static_cast (-1)) - { previous = current; rangeStart = current; - } - else - { - if (current == previous + 1) - { + + } else { + + if (current == previous + 1) { + previous = current; - } - else - { - set.m_ranges.push_back(new UIDMessageRange - (utility::stringUtils::toString(rangeStart), - utility::stringUtils::toString(previous))); + + } else { + + set.m_ranges.push_back( + new UIDMessageRange( + utility::stringUtils::toString(rangeStart), + utility::stringUtils::toString(previous) + ) + ); previous = current; rangeStart = current; @@ -339,56 +359,61 @@ messageSet messageSet::byUID(const std::vector & uids) } } - set.m_ranges.push_back(new UIDMessageRange - (utility::stringUtils::toString(rangeStart), - utility::stringUtils::toString(previous))); + set.m_ranges.push_back( + new UIDMessageRange( + utility::stringUtils::toString(rangeStart), + utility::stringUtils::toString(previous) + ) + ); return set; } -void messageSet::addRange(const messageRange& range) -{ - if (!m_ranges.empty() && typeid(*m_ranges[0]) != typeid(range)) +void messageSet::addRange(const messageRange& range) { + + if (!m_ranges.empty() && typeid(*m_ranges[0]) != typeid(range)) { throw std::invalid_argument("range"); + } m_ranges.push_back(range.clone()); } -void messageSet::enumerate(messageSetEnumerator& en) const -{ - for (size_t i = 0, n = m_ranges.size() ; i < n ; ++i) +void messageSet::enumerate(messageSetEnumerator& en) const { + + for (size_t i = 0, n = m_ranges.size() ; i < n ; ++i) { m_ranges[i]->enumerate(en); + } } -bool messageSet::isEmpty() const -{ +bool messageSet::isEmpty() const { + return m_ranges.empty(); } -bool messageSet::isNumberSet() const -{ +bool messageSet::isNumberSet() const { + return !isEmpty() && dynamic_cast (m_ranges[0]) != NULL; } -bool messageSet::isUIDSet() const -{ +bool messageSet::isUIDSet() const { + return !isEmpty() && dynamic_cast (m_ranges[0]) != NULL; } -size_t messageSet::getRangeCount() const -{ +size_t messageSet::getRangeCount() const { + return m_ranges.size(); } -const messageRange& messageSet::getRangeAt(const size_t i) const -{ +const messageRange& messageSet::getRangeAt(const size_t i) const { + return *m_ranges[i]; } diff --git a/src/vmime/net/messageSet.hpp b/src/vmime/net/messageSet.hpp index 1be49761..8b33b0dd 100644 --- a/src/vmime/net/messageSet.hpp +++ b/src/vmime/net/messageSet.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,9 +46,8 @@ class UIDMessageRange; /** Enumerator used to retrieve the message number/UID ranges contained * in a messageSet object. */ +class VMIME_EXPORT messageSetEnumerator { -class VMIME_EXPORT messageSetEnumerator -{ public: virtual void enumerateNumberMessageRange(const numberMessageRange& range) = 0; @@ -59,9 +58,8 @@ public: /** A range of (continuous) messages, designated either by their * sequence number, or by their UID. */ +class VMIME_EXPORT messageRange : public object { -class VMIME_EXPORT messageRange : public object -{ public: virtual ~messageRange(); @@ -86,9 +84,8 @@ protected: /** A range of (continuous) messages designated by their sequence number. */ +class VMIME_EXPORT numberMessageRange : public messageRange { -class VMIME_EXPORT numberMessageRange : public messageRange -{ public: /** Constructs a message range containing a single message. @@ -137,9 +134,8 @@ private: /** A range of (continuous) messages represented by their UID. */ +class VMIME_EXPORT UIDMessageRange : public messageRange { -class VMIME_EXPORT UIDMessageRange : public messageRange -{ public: /** Constructs a message range containing a single message. @@ -211,9 +207,8 @@ private: * vmime::net::messageSet::byUID(1000, "*") * \endcode */ +class VMIME_EXPORT messageSet : public object { -class VMIME_EXPORT messageSet : public object -{ public: ~messageSet(); diff --git a/src/vmime/net/pop3/POP3Command.cpp b/src/vmime/net/pop3/POP3Command.cpp index 528746e0..0e798884 100644 --- a/src/vmime/net/pop3/POP3Command.cpp +++ b/src/vmime/net/pop3/POP3Command.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,28 +43,29 @@ namespace pop3 { POP3Command::POP3Command(const string& text, const string& traceText) - : m_text(text), m_traceText(traceText) -{ + : m_text(text), + m_traceText(traceText) { + } // static -shared_ptr POP3Command::CAPA() -{ +shared_ptr POP3Command::CAPA() { + return createCommand("CAPA"); } // static -shared_ptr POP3Command::NOOP() -{ +shared_ptr POP3Command::NOOP() { + return createCommand("NOOP"); } // static -shared_ptr POP3Command::AUTH(const string& mechName) -{ +shared_ptr POP3Command::AUTH(const string& mechName) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "AUTH " << mechName; @@ -74,8 +75,8 @@ shared_ptr POP3Command::AUTH(const string& mechName) // static -shared_ptr POP3Command::AUTH(const string& mechName, const string& initialResponse) -{ +shared_ptr POP3Command::AUTH(const string& mechName, const string& initialResponse) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "AUTH " << mechName << " " << initialResponse; @@ -85,15 +86,15 @@ shared_ptr POP3Command::AUTH(const string& mechName, const string& // static -shared_ptr POP3Command::STLS() -{ +shared_ptr POP3Command::STLS() { + return createCommand("STLS"); } // static -shared_ptr POP3Command::APOP(const string& username, const string& digest) -{ +shared_ptr POP3Command::APOP(const string& username, const string& digest) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "APOP " << username << " " << digest; @@ -103,8 +104,8 @@ shared_ptr POP3Command::APOP(const string& username, const string& // static -shared_ptr POP3Command::USER(const string& username) -{ +shared_ptr POP3Command::USER(const string& username) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "USER " << username; @@ -118,8 +119,8 @@ shared_ptr POP3Command::USER(const string& username) // static -shared_ptr POP3Command::PASS(const string& password) -{ +shared_ptr POP3Command::PASS(const string& password) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "PASS " << password; @@ -133,22 +134,22 @@ shared_ptr POP3Command::PASS(const string& password) // static -shared_ptr POP3Command::STAT() -{ +shared_ptr POP3Command::STAT() { + return createCommand("STAT"); } // static -shared_ptr POP3Command::LIST() -{ +shared_ptr POP3Command::LIST() { + return createCommand("LIST"); } // static -shared_ptr POP3Command::LIST(const unsigned long msg) -{ +shared_ptr POP3Command::LIST(const unsigned long msg) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "LIST " << msg; @@ -158,15 +159,15 @@ shared_ptr POP3Command::LIST(const unsigned long msg) // static -shared_ptr POP3Command::UIDL() -{ +shared_ptr POP3Command::UIDL() { + return createCommand("UIDL"); } // static -shared_ptr POP3Command::UIDL(const unsigned long msg) -{ +shared_ptr POP3Command::UIDL(const unsigned long msg) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "UIDL " << msg; @@ -176,8 +177,8 @@ shared_ptr POP3Command::UIDL(const unsigned long msg) // static -shared_ptr POP3Command::DELE(const unsigned long msg) -{ +shared_ptr POP3Command::DELE(const unsigned long msg) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "DELE " << msg; @@ -187,8 +188,8 @@ shared_ptr POP3Command::DELE(const unsigned long msg) // static -shared_ptr POP3Command::RETR(const unsigned long msg) -{ +shared_ptr POP3Command::RETR(const unsigned long msg) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "RETR " << msg; @@ -198,8 +199,8 @@ shared_ptr POP3Command::RETR(const unsigned long msg) // static -shared_ptr POP3Command::TOP(const unsigned long msg, const unsigned long lines) -{ +shared_ptr POP3Command::TOP(const unsigned long msg, const unsigned long lines) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "TOP " << msg << " " << lines; @@ -209,48 +210,52 @@ shared_ptr POP3Command::TOP(const unsigned long msg, const unsigne // static -shared_ptr POP3Command::RSET() -{ +shared_ptr POP3Command::RSET() { + return createCommand("RSET"); } // static -shared_ptr POP3Command::QUIT() -{ +shared_ptr POP3Command::QUIT() { + return createCommand("QUIT"); } // static -shared_ptr POP3Command::createCommand - (const string& text, const string& traceText) -{ - if (traceText.empty()) +shared_ptr POP3Command::createCommand( + const string& text, + const string& traceText +) { + + if (traceText.empty()) { return shared_ptr (new POP3Command(text, text)); - else + } else { return shared_ptr (new POP3Command(text, traceText)); + } } -const string POP3Command::getText() const -{ +const string POP3Command::getText() const { + return m_text; } -const string POP3Command::getTraceText() const -{ +const string POP3Command::getTraceText() const { + return m_traceText; } -void POP3Command::send(const shared_ptr & conn) -{ +void POP3Command::send(const shared_ptr & conn) { + conn->getSocket()->send(m_text + "\r\n"); - if (conn->getTracer()) + if (conn->getTracer()) { conn->getTracer()->traceSend(m_traceText); + } } diff --git a/src/vmime/net/pop3/POP3Command.hpp b/src/vmime/net/pop3/POP3Command.hpp index 7718ccb2..06a61b9b 100644 --- a/src/vmime/net/pop3/POP3Command.hpp +++ b/src/vmime/net/pop3/POP3Command.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -50,8 +50,8 @@ class POP3Connection; /** A POP3 command that will be sent to the server. */ -class VMIME_EXPORT POP3Command : public object -{ +class VMIME_EXPORT POP3Command : public object { + public: static shared_ptr CAPA(); diff --git a/src/vmime/net/pop3/POP3Connection.cpp b/src/vmime/net/pop3/POP3Connection.cpp index ed098656..749f7ef1 100644 --- a/src/vmime/net/pop3/POP3Connection.cpp +++ b/src/vmime/net/pop3/POP3Connection.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -63,37 +63,48 @@ namespace pop3 { -POP3Connection::POP3Connection(const shared_ptr & store, const shared_ptr & auth) - : m_store(store), m_auth(auth), m_socket(null), m_timeoutHandler(null), - m_authenticated(false), m_secured(false), m_capabilitiesFetched(false) -{ +POP3Connection::POP3Connection( + const shared_ptr & store, + const shared_ptr & auth +) + : m_store(store), + m_auth(auth), + m_socket(null), + m_timeoutHandler(null), + m_authenticated(false), + m_secured(false), + m_capabilitiesFetched(false) { + static int connectionId = 0; - if (store->getTracerFactory()) + if (store->getTracerFactory()) { m_tracer = store->getTracerFactory()->create(store, ++connectionId); + } } -POP3Connection::~POP3Connection() -{ - try - { - if (isConnected()) +POP3Connection::~POP3Connection() { + + try { + + if (isConnected()) { disconnect(); - else if (m_socket) + } else if (m_socket) { internalDisconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -void POP3Connection::connect() -{ - if (isConnected()) +void POP3Connection::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS); const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT); @@ -101,16 +112,17 @@ void POP3Connection::connect() shared_ptr store = m_store.lock(); // Create the time-out handler - if (store->getTimeoutHandlerFactory()) + if (store->getTimeoutHandlerFactory()) { m_timeoutHandler = store->getTimeoutHandlerFactory()->create(); + } // Create and connect the socket m_socket = store->getSocketFactory()->create(m_timeoutHandler); m_socket->setTracer(m_tracer); #if VMIME_HAVE_TLS_SUPPORT - if (store->isPOP3S()) // dedicated port/POP3S - { + if (store->isPOP3S()) { // dedicated port/POP3S + shared_ptr tlsSession = tls::TLSSession::create (store->getCertificateVerifier(), store->getSession()->getTLSProperties()); @@ -122,8 +134,7 @@ void POP3Connection::connect() m_secured = true; m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); - } - else + } else #endif // VMIME_HAVE_TLS_SUPPORT { m_cntInfos = make_shared (address, port); @@ -136,11 +147,12 @@ void POP3Connection::connect() // eg: C: // --- S: +OK MailSite POP3 Server 5.3.4.0 Ready <36938848.1056800841.634@somewhere.com> - shared_ptr response = POP3Response::readResponse - (dynamicCast (shared_from_this())); + shared_ptr response = POP3Response::readResponse( + dynamicCast (shared_from_this()) + ); + + if (!response->isSuccess()) { - if (!response->isSuccess()) - { internalDisconnect(); throw exceptions::connection_greeting_error(response->getFirstLine()); } @@ -152,27 +164,23 @@ void POP3Connection::connect() const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED) && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED); - if (!store->isPOP3S() && tls) // only if not POP3S - { - try - { + if (!store->isPOP3S() && tls) { // only if not POP3S + + try { + startTLS(); - } + // Non-fatal error - catch (exceptions::command_error&) - { - if (tlsRequired) - { + } catch (exceptions::command_error&) { + + if (tlsRequired) { throw; - } - else - { + } else { // TLS is not required, so don't bother } - } + // Fatal error - catch (...) - { + } catch (...) { throw; } } @@ -183,28 +191,29 @@ void POP3Connection::connect() } -void POP3Connection::disconnect() -{ - if (!isConnected()) +void POP3Connection::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } internalDisconnect(); } -void POP3Connection::internalDisconnect() -{ - if (m_socket) - { - if (m_socket->isConnected()) - { - try - { +void POP3Connection::internalDisconnect() { + + if (m_socket) { + + if (m_socket->isConnected()) { + + try { + POP3Command::QUIT()->send(dynamicCast (shared_from_this())); POP3Response::readResponse(dynamicCast (shared_from_this())); - } - catch (exception&) - { + + } catch (exception&) { + // Not important } @@ -223,36 +232,36 @@ void POP3Connection::internalDisconnect() } -void POP3Connection::authenticate(const messageId& randomMID) -{ +void POP3Connection::authenticate(const messageId& randomMID) { + getAuthenticator()->setService(m_store.lock()); #if VMIME_HAVE_SASL_SUPPORT // First, try SASL authentication - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) - { - try - { + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) { + + try { + authenticateSASL(); m_authenticated = true; return; - } - catch (exceptions::authentication_error&) - { - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) - { + + } catch (exceptions::authentication_error&) { + + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) { + // Can't fallback on APOP/normal authentication internalDisconnect(); throw; - } - else - { + + } else { + // Ignore, will try APOP/normal authentication } - } - catch (exception&) - { + + } catch (exception&) { + internalDisconnect(); throw; } @@ -270,11 +279,11 @@ void POP3Connection::authenticate(const messageId& randomMID) shared_ptr conn = dynamicCast (shared_from_this()); shared_ptr response; - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP)) - { + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP)) { + if (randomMID.getLeft().length() != 0 && - randomMID.getRight().length() != 0) - { + randomMID.getRight().length() != 0) { + // is the result of MD5 applied to "password" shared_ptr md5 = security::digest::messageDigestFactory::getInstance()->create("md5"); @@ -285,13 +294,13 @@ void POP3Connection::authenticate(const messageId& randomMID) POP3Command::APOP(username, md5->getHexDigest())->send(conn); response = POP3Response::readResponse(conn); - if (response->isSuccess()) - { + if (response->isSuccess()) { + m_authenticated = true; return; - } - else - { + + } else { + // Some servers close the connection after an unsuccessful APOP // command, so the fallback may not always work... // @@ -301,31 +310,31 @@ void POP3Connection::authenticate(const messageId& randomMID) // S: +OK Pop server at xxx signing off. // [Connection closed by foreign host.] - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) - { + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) { + // Can't fallback on basic authentication internalDisconnect(); throw exceptions::authentication_error(response->getFirstLine()); } // Ensure connection is valid (cf. note above) - try - { + try { + POP3Command::NOOP()->send(conn); POP3Response::readResponse(conn); - } - catch (exceptions::socket_exception&) - { + + } catch (exceptions::socket_exception&) { + internalDisconnect(); throw exceptions::authentication_error(response->getFirstLine()); } } - } - else - { + + } else { + // APOP not supported - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) - { + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) { + // Can't fallback on basic authentication internalDisconnect(); throw exceptions::authentication_error("APOP not supported"); @@ -343,8 +352,8 @@ void POP3Connection::authenticate(const messageId& randomMID) POP3Command::USER(username)->send(conn); response = POP3Response::readResponse(conn); - if (!response->isSuccess()) - { + if (!response->isSuccess()) { + internalDisconnect(); throw exceptions::authentication_error(response->getFirstLine()); } @@ -352,8 +361,8 @@ void POP3Connection::authenticate(const messageId& randomMID) POP3Command::PASS(password)->send(conn); response = POP3Response::readResponse(conn); - if (!response->isSuccess()) - { + if (!response->isSuccess()) { + internalDisconnect(); throw exceptions::authentication_error(response->getFirstLine()); } @@ -364,16 +373,17 @@ void POP3Connection::authenticate(const messageId& randomMID) #if VMIME_HAVE_SASL_SUPPORT -void POP3Connection::authenticateSASL() -{ - if (!dynamicCast (getAuthenticator())) +void POP3Connection::authenticateSASL() { + + if (!dynamicCast (getAuthenticator())) { throw exceptions::authentication_error("No SASL authenticator available."); + } std::vector capa = getCapabilities(); std::vector saslMechs; - for (unsigned int i = 0 ; i < capa.size() ; ++i) - { + for (unsigned int i = 0 ; i < capa.size() ; ++i) { + const string& x = capa[i]; // C: CAPA @@ -391,8 +401,8 @@ void POP3Connection::authenticateSASL() (x[1] == 'A' || x[1] == 'a') && (x[2] == 'S' || x[2] == 's') && (x[3] == 'L' || x[3] == 'l') && - (x[4] == ' ' || x[4] == '\t')) - { + (x[4] == ' ' || x[4] == '\t')) { + const string list(x.begin() + 5, x.end()); std::istringstream iss(list); @@ -400,52 +410,53 @@ void POP3Connection::authenticateSASL() string mech; - while (iss >> mech) + while (iss >> mech) { saslMechs.push_back(mech); + } } } - if (saslMechs.empty()) + if (saslMechs.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } std::vector > mechList; shared_ptr saslContext = security::sasl::SASLContext::create(); - for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) - { - try - { - mechList.push_back - (saslContext->createMechanism(saslMechs[i])); - } - catch (exceptions::no_such_mechanism&) - { + for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) { + + try { + mechList.push_back(saslContext->createMechanism(saslMechs[i])); + } catch (exceptions::no_such_mechanism&) { // Ignore mechanism } } - if (mechList.empty()) + if (mechList.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } // Try to suggest a mechanism among all those supported shared_ptr suggestedMech = saslContext->suggestMechanism(mechList); - if (!suggestedMech) + if (!suggestedMech) { throw exceptions::authentication_error("Unable to suggest SASL mechanism."); + } // Allow application to choose which mechanisms to use mechList = dynamicCast (getAuthenticator())-> getAcceptableMechanisms(mechList, suggestedMech); - if (mechList.empty()) + if (mechList.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } // Try each mechanism in the list in turn - for (unsigned int i = 0 ; i < mechList.size() ; ++i) - { + for (unsigned int i = 0 ; i < mechList.size() ; ++i) { + shared_ptr mech = mechList[i]; shared_ptr saslSession = @@ -455,8 +466,8 @@ void POP3Connection::authenticateSASL() shared_ptr authCmd; - if (saslSession->getMechanism()->hasInitialResponse()) - { + if (saslSession->getMechanism()->hasInitialResponse()) { + byte_t* initialResp = 0; size_t initialRespLen = 0; @@ -465,103 +476,108 @@ void POP3Connection::authenticateSASL() string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen)); delete [] initialResp; - if (encodedInitialResp.empty()) + if (encodedInitialResp.empty()) { authCmd = POP3Command::AUTH(mech->getName(), "="); - else + } else { authCmd = POP3Command::AUTH(mech->getName(), encodedInitialResp); - } - else - { + } + + } else { + authCmd = POP3Command::AUTH(mech->getName()); } authCmd->send(dynamicCast (shared_from_this())); - for (bool cont = true ; cont ; ) - { + for (bool cont = true ; cont ; ) { + shared_ptr response = POP3Response::readResponse(dynamicCast (shared_from_this())); - switch (response->getCode()) - { - case POP3Response::CODE_OK: - { - m_socket = saslSession->getSecuredSocket(m_socket); - return; - } - case POP3Response::CODE_READY: - { - byte_t* challenge = 0; - size_t challengeLen = 0; + switch (response->getCode()) { - byte_t* resp = 0; - size_t respLen = 0; + case POP3Response::CODE_OK: { - try - { - // Extract challenge - saslContext->decodeB64(response->getText(), &challenge, &challengeLen); - - // Prepare response - saslSession->evaluateChallenge - (challenge, challengeLen, &resp, &respLen); - - // Send response - const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n"; - m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length()); - - if (m_tracer) - m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange"); + m_socket = saslSession->getSecuredSocket(m_socket); + return; } - catch (exceptions::sasl_exception& e) - { - if (challenge) - { - delete [] challenge; - challenge = NULL; + + case POP3Response::CODE_READY: { + + byte_t* challenge = 0; + size_t challengeLen = 0; + + byte_t* resp = 0; + size_t respLen = 0; + + try { + + // Extract challenge + saslContext->decodeB64(response->getText(), &challenge, &challengeLen); + + // Prepare response + saslSession->evaluateChallenge(challenge, challengeLen, &resp, &respLen); + + // Send response + const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n"; + m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length()); + + if (m_tracer) { + m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange"); + } + + } catch (exceptions::sasl_exception& e) { + + if (challenge) { + delete [] challenge; + challenge = NULL; + } + + if (resp) { + delete [] resp; + resp = NULL; + } + + // Cancel SASL exchange + m_socket->send("*\r\n"); + + if (m_tracer) { + m_tracer->traceSend("*"); + } + + } catch (...) { + + if (challenge) { + delete [] challenge; + } + + if (resp) { + delete [] resp; + } + + throw; } - if (resp) - { - delete [] resp; - resp = NULL; + if (challenge) { + delete [] challenge; } - // Cancel SASL exchange - m_socket->send("*\r\n"); - - if (m_tracer) - m_tracer->traceSend("*"); - } - catch (...) - { - if (challenge) - delete [] challenge; - - if (resp) + if (resp) { delete [] resp; + } - throw; + break; } - if (challenge) - delete [] challenge; + default: - if (resp) - delete [] resp; - - break; - } - default: - - cont = false; - break; + cont = false; + break; } } } - throw exceptions::authentication_error - ("Could not authenticate using SASL: all mechanisms failed."); + throw exceptions::authentication_error("Could not authenticate using SASL: all mechanisms failed."); } #endif // VMIME_HAVE_SASL_SUPPORT @@ -569,32 +585,34 @@ void POP3Connection::authenticateSASL() #if VMIME_HAVE_TLS_SUPPORT -void POP3Connection::startTLS() -{ - try - { +void POP3Connection::startTLS() { + + try { + POP3Command::STLS()->send(dynamicCast (shared_from_this())); shared_ptr response = POP3Response::readResponse(dynamicCast (shared_from_this())); - if (!response->isSuccess()) + if (!response->isSuccess()) { throw exceptions::command_error("STLS", response->getFirstLine()); + } - shared_ptr tlsSession = tls::TLSSession::create - (m_store.lock()->getCertificateVerifier(), - m_store.lock()->getSession()->getTLSProperties()); + shared_ptr tlsSession = tls::TLSSession::create( + m_store.lock()->getCertificateVerifier(), + m_store.lock()->getSession()->getTLSProperties() + ); - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); + shared_ptr tlsSocket = tlsSession->getSocket(m_socket); tlsSocket->handshake(); m_socket = tlsSocket; m_secured = true; - m_cntInfos = make_shared - (m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket); + m_cntInfos = make_shared ( + m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket + ); // " Once TLS has been started, the client MUST discard cached // information about server capabilities and SHOULD re-issue @@ -602,14 +620,14 @@ void POP3Connection::startTLS() // man-in-the-middle attacks which alter the capabilities list // prior to STLS. " (RFC-2595) invalidateCapabilities(); - } - catch (exceptions::command_error&) - { + + } catch (exceptions::command_error&) { + // Non-fatal error throw; - } - catch (exception&) - { + + } catch (exception&) { + // Fatal error internalDisconnect(); throw; @@ -619,24 +637,25 @@ void POP3Connection::startTLS() #endif // VMIME_HAVE_TLS_SUPPORT -const std::vector POP3Connection::getCapabilities() -{ - if (!m_capabilitiesFetched) +const std::vector POP3Connection::getCapabilities() { + + if (!m_capabilitiesFetched) { fetchCapabilities(); + } return m_capabilities; } -void POP3Connection::invalidateCapabilities() -{ +void POP3Connection::invalidateCapabilities() { + m_capabilities.clear(); m_capabilitiesFetched = false; } -void POP3Connection::fetchCapabilities() -{ +void POP3Connection::fetchCapabilities() { + POP3Command::CAPA()->send(dynamicCast (shared_from_this())); shared_ptr response = @@ -644,10 +663,11 @@ void POP3Connection::fetchCapabilities() std::vector res; - if (response->isSuccess()) - { - for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) + if (response->isSuccess()) { + + for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) { res.push_back(response->getLineAt(i)); + } } m_capabilities = res; @@ -655,56 +675,56 @@ void POP3Connection::fetchCapabilities() } -bool POP3Connection::isConnected() const -{ +bool POP3Connection::isConnected() const { + return m_socket && m_socket->isConnected() && m_authenticated; } -bool POP3Connection::isSecuredConnection() const -{ +bool POP3Connection::isSecuredConnection() const { + return m_secured; } -shared_ptr POP3Connection::getConnectionInfos() const -{ +shared_ptr POP3Connection::getConnectionInfos() const { + return m_cntInfos; } -shared_ptr POP3Connection::getStore() -{ +shared_ptr POP3Connection::getStore() { + return m_store.lock(); } -shared_ptr POP3Connection::getSession() -{ +shared_ptr POP3Connection::getSession() { + return m_store.lock()->getSession(); } -shared_ptr POP3Connection::getSocket() -{ +shared_ptr POP3Connection::getSocket() { + return m_socket; } -shared_ptr POP3Connection::getTracer() -{ +shared_ptr POP3Connection::getTracer() { + return m_tracer; } -shared_ptr POP3Connection::getTimeoutHandler() -{ +shared_ptr POP3Connection::getTimeoutHandler() { + return m_timeoutHandler; } -shared_ptr POP3Connection::getAuthenticator() -{ +shared_ptr POP3Connection::getAuthenticator() { + return m_auth; } diff --git a/src/vmime/net/pop3/POP3Connection.hpp b/src/vmime/net/pop3/POP3Connection.hpp index 032be5cc..26b3f3c6 100644 --- a/src/vmime/net/pop3/POP3Connection.hpp +++ b/src/vmime/net/pop3/POP3Connection.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -61,11 +61,15 @@ class POP3Store; /** Manage connection to a POP3 server. */ -class VMIME_EXPORT POP3Connection : public object, public enable_shared_from_this -{ +class VMIME_EXPORT POP3Connection : public object, public enable_shared_from_this { + public: - POP3Connection(const shared_ptr & store, const shared_ptr & auth); + POP3Connection( + const shared_ptr & store, + const shared_ptr & auth + ); + virtual ~POP3Connection(); diff --git a/src/vmime/net/pop3/POP3Folder.cpp b/src/vmime/net/pop3/POP3Folder.cpp index 8c34676e..4ca494fe 100644 --- a/src/vmime/net/pop3/POP3Folder.cpp +++ b/src/vmime/net/pop3/POP3Folder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -45,59 +45,67 @@ namespace net { namespace pop3 { -POP3Folder::POP3Folder(const folder::path& path, const shared_ptr & store) - : m_store(store), m_path(path), +POP3Folder::POP3Folder( + const folder::path& path, + const shared_ptr & store +) + : m_store(store), + m_path(path), m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), - m_mode(-1), m_open(false) -{ + m_mode(-1), + m_open(false) { + store->registerFolder(this); } -POP3Folder::~POP3Folder() -{ - try - { +POP3Folder::~POP3Folder() { + + try { + shared_ptr store = m_store.lock(); - if (store) - { - if (m_open) + if (store) { + + if (m_open) { close(false); + } store->unregisterFolder(this); - } - else if (m_open) - { + + } else if (m_open) { + onClose(); } - } - catch (...) - { + + } catch (...) { + // Don't throw in destructor } } -int POP3Folder::getMode() const -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); +int POP3Folder::getMode() const { - return (m_mode); + if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + return m_mode; } -const folderAttributes POP3Folder::getAttributes() -{ +const folderAttributes POP3Folder::getAttributes() { + folderAttributes attribs; - if (m_path.isEmpty()) + if (m_path.isEmpty()) { attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS); - else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") + } else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") { attribs.setType(folderAttributes::TYPE_CONTAINS_MESSAGES); - else + } else { throw exceptions::folder_not_found(); + } attribs.setFlags(0); @@ -105,72 +113,78 @@ const folderAttributes POP3Folder::getAttributes() } -const folder::path::component POP3Folder::getName() const -{ - return (m_name); +const folder::path::component POP3Folder::getName() const { + + return m_name; } -const folder::path POP3Folder::getFullPath() const -{ - return (m_path); +const folder::path POP3Folder::getFullPath() const { + + return m_path; } -void POP3Folder::open(const int mode, bool failIfModeIsNotAvailable) -{ +void POP3Folder::open(const int mode, bool failIfModeIsNotAvailable) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - if (m_path.isEmpty()) - { - if (mode != MODE_READ_ONLY && failIfModeIsNotAvailable) + if (m_path.isEmpty()) { + + if (mode != MODE_READ_ONLY && failIfModeIsNotAvailable) { throw exceptions::operation_not_supported(); + } m_open = true; m_mode = mode; m_messageCount = 0; - } - else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") - { + + } else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") { + POP3Command::STAT()->send(store->getConnection()); shared_ptr response = POP3Response::readResponse(store->getConnection()); - if (!response->isSuccess()) + if (!response->isSuccess()) { throw exceptions::command_error("STAT", response->getFirstLine()); + } std::istringstream iss(response->getText()); iss.imbue(std::locale::classic()); iss >> m_messageCount; - if (iss.fail()) + if (iss.fail()) { throw exceptions::invalid_response("STAT", response->getFirstLine()); + } m_open = true; m_mode = mode; - } - else - { + + } else { + throw exceptions::folder_not_found(); } } -void POP3Folder::close(const bool expunge) -{ + +void POP3Folder::close(const bool expunge) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - if (!isOpen()) + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (!expunge) - { + if (!expunge) { POP3Command::RSET()->send(store->getConnection()); POP3Response::readResponse(store->getConnection()); } @@ -182,168 +196,185 @@ void POP3Folder::close(const bool expunge) } -void POP3Folder::onClose() -{ - for (MessageMap::iterator it = m_messages.begin() ; it != m_messages.end() ; ++it) +void POP3Folder::onClose() { + + for (MessageMap::iterator it = m_messages.begin() ; it != m_messages.end() ; ++it) { (*it).first->onFolderClosed(); + } m_messages.clear(); } -void POP3Folder::create(const folderAttributes& /* attribs */) -{ +void POP3Folder::create(const folderAttributes& /* attribs */) { + throw exceptions::operation_not_supported(); } -void POP3Folder::destroy() -{ +void POP3Folder::destroy() { + throw exceptions::operation_not_supported(); } -bool POP3Folder::exists() -{ +bool POP3Folder::exists() { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - return (m_path.isEmpty() || (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX")); + return m_path.isEmpty() || (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX"); } -bool POP3Folder::isOpen() const -{ - return (m_open); +bool POP3Folder::isOpen() const { + + return m_open; } -shared_ptr POP3Folder::getMessage(const size_t num) -{ +shared_ptr POP3Folder::getMessage(const size_t num) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (num < 1 || num > m_messageCount) + } else if (num < 1 || num > m_messageCount) { throw exceptions::message_not_found(); + } return make_shared (dynamicCast (shared_from_this()), num); } -std::vector > POP3Folder::getMessages(const messageSet& msgs) -{ +std::vector > POP3Folder::getMessages(const messageSet& msgs) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } + + if (msgs.isNumberSet()) { - if (msgs.isNumberSet()) - { const std::vector numbers = POP3Utils::messageSetToNumberList(msgs, m_messageCount); std::vector > messages; shared_ptr thisFolder(dynamicCast (shared_from_this())); - for (std::vector ::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) - { - if (*it < 1|| *it > m_messageCount) + for (std::vector ::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) { + + if (*it < 1|| *it > m_messageCount) { throw exceptions::message_not_found(); + } messages.push_back(make_shared (thisFolder, *it)); } return messages; - } - else - { + + } else { + throw exceptions::operation_not_supported(); } } -size_t POP3Folder::getMessageCount() -{ +size_t POP3Folder::getMessageCount() { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - return (m_messageCount); + return m_messageCount; } -shared_ptr POP3Folder::getFolder(const folder::path::component& name) -{ +shared_ptr POP3Folder::getFolder(const folder::path::component& name) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } return shared_ptr (new POP3Folder(m_path / name, store)); } -std::vector > POP3Folder::getFolders(const bool /* recursive */) -{ +std::vector > POP3Folder::getFolders(const bool /* recursive */) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } + + if (m_path.isEmpty()) { - if (m_path.isEmpty()) - { std::vector > v; v.push_back(shared_ptr (new POP3Folder(folder::path::component("INBOX"), store))); - return (v); - } - else - { + return v; + + } else { + std::vector > v; - return (v); + return v; } } -void POP3Folder::fetchMessages(std::vector >& msg, const fetchAttributes& options, - utility::progressListener* progress) -{ +void POP3Folder::fetchMessages( + std::vector >& msg, + const fetchAttributes& options, + utility::progressListener* progress +) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (msg.empty()) + if (msg.empty()) { return; + } const size_t total = msg.size(); size_t current = 0; - if (progress) + if (progress) { progress->start(total); - - for (std::vector >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - dynamicCast (*it)->fetch - (dynamicCast (shared_from_this()), options); - - if (progress) - progress->progress(++current, total); } - if (options.has(fetchAttributes::SIZE)) - { + for (std::vector >::iterator it = msg.begin() ; + it != msg.end() ; ++it) { + + dynamicCast (*it)->fetch( + dynamicCast (shared_from_this()), + options + ); + + if (progress) { + progress->progress(++current, total); + } + } + + if (options.has(fetchAttributes::SIZE)) { + // Send the "LIST" command POP3Command::LIST()->send(store->getConnection()); @@ -351,8 +382,8 @@ void POP3Folder::fetchMessages(std::vector >& msg, const f shared_ptr response = POP3Response::readMultilineResponse(store->getConnection()); - if (response->isSuccess()) - { + if (response->isSuccess()) { + // C: LIST // S: +OK // S: 1 47548 @@ -362,14 +393,14 @@ void POP3Folder::fetchMessages(std::vector >& msg, const f POP3Utils::parseMultiListOrUidlResponse(response, result); for (std::vector >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { + it != msg.end() ; ++it) { + shared_ptr m = dynamicCast (*it); std::map ::const_iterator x = result.find(m->m_num); - if (x != result.end()) - { + if (x != result.end()) { + size_t size = 0; std::istringstream iss((*x).second); @@ -380,11 +411,10 @@ void POP3Folder::fetchMessages(std::vector >& msg, const f } } } - } - if (options.has(fetchAttributes::UID)) - { + if (options.has(fetchAttributes::UID)) { + // Send the "UIDL" command POP3Command::UIDL()->send(store->getConnection()); @@ -392,8 +422,8 @@ void POP3Folder::fetchMessages(std::vector >& msg, const f shared_ptr response = POP3Response::readMultilineResponse(store->getConnection()); - if (response->isSuccess()) - { + if (response->isSuccess()) { + // C: UIDL // S: +OK // S: 1 whqtswO00WBw418f9t5JxYwZ @@ -403,37 +433,42 @@ void POP3Folder::fetchMessages(std::vector >& msg, const f POP3Utils::parseMultiListOrUidlResponse(response, result); for (std::vector >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { + it != msg.end() ; ++it) { + shared_ptr m = dynamicCast (*it); std::map ::const_iterator x = result.find(m->m_num); - if (x != result.end()) + if (x != result.end()) { m->m_uid = (*x).second; + } } } } - if (progress) + if (progress) { progress->stop(total); + } } -void POP3Folder::fetchMessage(const shared_ptr & msg, const fetchAttributes& options) -{ +void POP3Folder::fetchMessage(const shared_ptr & msg, const fetchAttributes& options) { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - dynamicCast (msg)->fetch - (dynamicCast (shared_from_this()), options); + dynamicCast (msg)->fetch( + dynamicCast (shared_from_this()), + options + ); + + if (options.has(fetchAttributes::SIZE)) { - if (options.has(fetchAttributes::SIZE)) - { // Send the "LIST" command POP3Command::LIST(msg->getNumber())->send(store->getConnection()); @@ -441,8 +476,8 @@ void POP3Folder::fetchMessage(const shared_ptr & msg, const fetchAttrib shared_ptr response = POP3Response::readResponse(store->getConnection()); - if (response->isSuccess()) - { + if (response->isSuccess()) { + string responseText = response->getText(); // C: LIST 2 @@ -453,8 +488,8 @@ void POP3Folder::fetchMessage(const shared_ptr & msg, const fetchAttrib while (it != responseText.end() && !(*it == ' ' || *it == '\t')) ++it; while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it; - if (it != responseText.end()) - { + if (it != responseText.end()) { + size_t size = 0; std::istringstream iss(string(it, responseText.end())); @@ -466,8 +501,8 @@ void POP3Folder::fetchMessage(const shared_ptr & msg, const fetchAttrib } } - if (options.has(fetchAttributes::UID)) - { + if (options.has(fetchAttributes::UID)) { + // Send the "UIDL" command POP3Command::UIDL(msg->getNumber())->send(store->getConnection()); @@ -475,8 +510,8 @@ void POP3Folder::fetchMessage(const shared_ptr & msg, const fetchAttrib shared_ptr response = POP3Response::readResponse(store->getConnection()); - if (response->isSuccess()) - { + if (response->isSuccess()) { + string responseText = response->getText(); // C: UIDL 2 @@ -487,21 +522,22 @@ void POP3Folder::fetchMessage(const shared_ptr & msg, const fetchAttrib while (it != responseText.end() && !(*it == ' ' || *it == '\t')) ++it; while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it; - if (it != responseText.end()) - { - dynamicCast (msg)->m_uid = - string(it, responseText.end()); + if (it != responseText.end()) { + dynamicCast (msg)->m_uid = string(it, responseText.end()); } } } } -std::vector > POP3Folder::getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs) -{ - if (msgs.isEmpty()) +std::vector > POP3Folder::getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs +) { + + if (msgs.isEmpty()) { return std::vector >(); + } std::vector > messages = getMessages(msgs); fetchMessages(messages, attribs); @@ -510,77 +546,84 @@ std::vector > POP3Folder::getAndFetchMessages } -int POP3Folder::getFetchCapabilities() const -{ - return fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | - fetchAttributes::SIZE | fetchAttributes::FULL_HEADER | - fetchAttributes::UID | fetchAttributes::IMPORTANCE; +int POP3Folder::getFetchCapabilities() const { + + return fetchAttributes::ENVELOPE | + fetchAttributes::CONTENT_INFO | + fetchAttributes::SIZE | + fetchAttributes::FULL_HEADER | + fetchAttributes::UID | + fetchAttributes::IMPORTANCE; } -shared_ptr POP3Folder::getParent() -{ - if (m_path.isEmpty()) +shared_ptr POP3Folder::getParent() { + + if (m_path.isEmpty()) { return null; - else + } else { return shared_ptr (new POP3Folder(m_path.getParent(), m_store.lock())); + } } -shared_ptr POP3Folder::getStore() const -{ +shared_ptr POP3Folder::getStore() const { + return m_store.lock(); } -shared_ptr POP3Folder::getStore() -{ +shared_ptr POP3Folder::getStore() { + return m_store.lock(); } -void POP3Folder::registerMessage(POP3Message* msg) -{ +void POP3Folder::registerMessage(POP3Message* msg) { + m_messages.insert(MessageMap::value_type(msg, msg->getNumber())); } -void POP3Folder::unregisterMessage(POP3Message* msg) -{ +void POP3Folder::unregisterMessage(POP3Message* msg) { + m_messages.erase(msg); } -void POP3Folder::onStoreDisconnected() -{ +void POP3Folder::onStoreDisconnected() { + m_store.reset(); } -void POP3Folder::deleteMessages(const messageSet& msgs) -{ +void POP3Folder::deleteMessages(const messageSet& msgs) { + shared_ptr store = m_store.lock(); const std::vector nums = POP3Utils::messageSetToNumberList(msgs, m_messageCount); - if (nums.empty()) + if (nums.empty()) { throw exceptions::invalid_argument(); + } - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } for (std::vector ::const_iterator - it = nums.begin() ; it != nums.end() ; ++it) - { + it = nums.begin() ; it != nums.end() ; ++it) { + POP3Command::DELE(*it)->send(store->getConnection()); shared_ptr response = POP3Response::readResponse(store->getConnection()); - if (!response->isSuccess()) + if (!response->isSuccess()) { throw exceptions::command_error("DELE", response->getFirstLine()); + } } // Sort message list @@ -593,62 +636,77 @@ void POP3Folder::deleteMessages(const messageSet& msgs) // Update local flags for (std::map ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { + m_messages.begin() ; it != m_messages.end() ; ++it) { + POP3Message* msg = (*it).first; - if (std::binary_search(list.begin(), list.end(), msg->getNumber())) + if (std::binary_search(list.begin(), list.end(), msg->getNumber())) { msg->m_deleted = true; + } } // Notify message flags changed shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageChangedEvent::TYPE_FLAGS, list); + make_shared ( + dynamicCast (shared_from_this()), + events::messageChangedEvent::TYPE_FLAGS, + list + ); notifyMessageChanged(event); } -void POP3Folder::setMessageFlags(const messageSet& /* msgs */, - const int /* flags */, const int /* mode */) -{ +void POP3Folder::setMessageFlags( + const messageSet& /* msgs */, + const int /* flags */, + const int /* mode */ +) { + throw exceptions::operation_not_supported(); } -void POP3Folder::rename(const folder::path& /* newPath */) -{ +void POP3Folder::rename(const folder::path& /* newPath */) { + throw exceptions::operation_not_supported(); } -messageSet POP3Folder::addMessage - (const shared_ptr & /* msg */, const int /* flags */, - vmime::datetime* /* date */, utility::progressListener* /* progress */) -{ +messageSet POP3Folder::addMessage( + const shared_ptr & /* msg */, + const int /* flags */, + vmime::datetime* /* date */, + utility::progressListener* /* progress */ +) { + throw exceptions::operation_not_supported(); } -messageSet POP3Folder::addMessage - (utility::inputStream& /* is */, const size_t /* size */, const int /* flags */, - vmime::datetime* /* date */, utility::progressListener* /* progress */) -{ +messageSet POP3Folder::addMessage( + utility::inputStream& /* is */, + const size_t /* size */, + const int /* flags */, + vmime::datetime* /* date */, + utility::progressListener* /* progress */ +) { + throw exceptions::operation_not_supported(); } -messageSet POP3Folder::copyMessages - (const folder::path& /* dest */, const messageSet& /* msgs */) -{ +messageSet POP3Folder::copyMessages( + const folder::path& /* dest */, + const messageSet& /* msgs */ +) { + throw exceptions::operation_not_supported(); } -void POP3Folder::status(size_t& count, size_t& unseen) -{ +void POP3Folder::status(size_t& count, size_t& unseen) { + count = 0; unseen = 0; @@ -661,20 +719,22 @@ void POP3Folder::status(size_t& count, size_t& unseen) } -shared_ptr POP3Folder::getStatus() -{ +shared_ptr POP3Folder::getStatus() { + shared_ptr store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } POP3Command::STAT()->send(store->getConnection()); shared_ptr response = POP3Response::readResponse(store->getConnection()); - if (!response->isSuccess()) + if (!response->isSuccess()) { throw exceptions::command_error("STAT", response->getFirstLine()); + } size_t count = 0; @@ -689,40 +749,45 @@ shared_ptr POP3Folder::getStatus() status->setUnseenCount(count); // Update local message count - if (m_messageCount != count) - { + if (m_messageCount != count) { + const size_t oldCount = m_messageCount; m_messageCount = count; - if (count > oldCount) - { + if (count > oldCount) { + std::vector nums; nums.resize(count - oldCount); - for (size_t i = oldCount + 1, j = 0 ; i <= count ; ++i, ++j) + for (size_t i = oldCount + 1, j = 0 ; i <= count ; ++i, ++j) { nums[j] = i; + } // Notify message count changed shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); + make_shared ( + dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); notifyMessageCount(event); // Notify folders with the same path for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == m_path) { + (*it)->m_messageCount = count; shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); + make_shared ( + dynamicCast ((*it)->shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); (*it)->notifyMessageCount(event); } @@ -734,15 +799,15 @@ shared_ptr POP3Folder::getStatus() } -void POP3Folder::expunge() -{ +void POP3Folder::expunge() { + // Not supported by POP3 protocol (deleted messages are automatically // expunged at the end of the session...). } -std::vector POP3Folder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) -{ +std::vector POP3Folder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) { + throw exceptions::operation_not_supported(); } diff --git a/src/vmime/net/pop3/POP3Folder.hpp b/src/vmime/net/pop3/POP3Folder.hpp index 92be088b..73e29f99 100644 --- a/src/vmime/net/pop3/POP3Folder.hpp +++ b/src/vmime/net/pop3/POP3Folder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -50,9 +50,8 @@ class POP3Message; /** POP3 folder implementation. */ +class VMIME_EXPORT POP3Folder : public folder { -class VMIME_EXPORT POP3Folder : public folder -{ private: friend class POP3Store; @@ -94,10 +93,26 @@ public: void deleteMessages(const messageSet& msgs); - void setMessageFlags(const messageSet& msgs, const int flags, const int mode = message::FLAG_MODE_SET); + void setMessageFlags( + const messageSet& msgs, + const int flags, + const int mode = message::FLAG_MODE_SET + ); - messageSet addMessage(const shared_ptr & msg, const int flags = -1, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); - messageSet addMessage(utility::inputStream& is, const size_t size, const int flags = -1, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); + messageSet addMessage( + const shared_ptr & msg, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); + + messageSet addMessage( + utility::inputStream& is, + const size_t size, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); messageSet copyMessages(const folder::path& dest, const messageSet& msgs); @@ -112,11 +127,18 @@ public: shared_ptr getStore(); - void fetchMessages(std::vector >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL); + void fetchMessages( + std::vector >& msg, + const fetchAttributes& options, + utility::progressListener* progress = NULL + ); + void fetchMessage(const shared_ptr & msg, const fetchAttributes& options); - std::vector > getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs); + std::vector > getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs + ); int getFetchCapabilities() const; diff --git a/src/vmime/net/pop3/POP3FolderStatus.cpp b/src/vmime/net/pop3/POP3FolderStatus.cpp index 15e4cc92..9f2c49fb 100644 --- a/src/vmime/net/pop3/POP3FolderStatus.cpp +++ b/src/vmime/net/pop3/POP3FolderStatus.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,45 +37,45 @@ namespace pop3 { POP3FolderStatus::POP3FolderStatus() : m_count(0), - m_unseen(0) -{ + m_unseen(0) { + } POP3FolderStatus::POP3FolderStatus(const POP3FolderStatus& other) : folderStatus(), m_count(other.m_count), - m_unseen(other.m_unseen) -{ + m_unseen(other.m_unseen) { + } -size_t POP3FolderStatus::getMessageCount() const -{ +size_t POP3FolderStatus::getMessageCount() const { + return m_count; } -size_t POP3FolderStatus::getUnseenCount() const -{ +size_t POP3FolderStatus::getUnseenCount() const { + return m_unseen; } -void POP3FolderStatus::setMessageCount(const size_t count) -{ +void POP3FolderStatus::setMessageCount(const size_t count) { + m_count = count; } -void POP3FolderStatus::setUnseenCount(const size_t unseen) -{ +void POP3FolderStatus::setUnseenCount(const size_t unseen) { + m_unseen = unseen; } -shared_ptr POP3FolderStatus::clone() const -{ +shared_ptr POP3FolderStatus::clone() const { + return make_shared (*this); } diff --git a/src/vmime/net/pop3/POP3FolderStatus.hpp b/src/vmime/net/pop3/POP3FolderStatus.hpp index 74c07a51..0ce413e4 100644 --- a/src/vmime/net/pop3/POP3FolderStatus.hpp +++ b/src/vmime/net/pop3/POP3FolderStatus.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,9 +41,8 @@ namespace pop3 { /** Holds the status of a POP3 folder. */ +class VMIME_EXPORT POP3FolderStatus : public folderStatus { -class VMIME_EXPORT POP3FolderStatus : public folderStatus -{ public: POP3FolderStatus(); diff --git a/src/vmime/net/pop3/POP3Message.cpp b/src/vmime/net/pop3/POP3Message.cpp index 913219b3..8d6b7f53 100644 --- a/src/vmime/net/pop3/POP3Message.cpp +++ b/src/vmime/net/pop3/POP3Message.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,162 +44,186 @@ namespace net { namespace pop3 { -POP3Message::POP3Message(const shared_ptr & folder, const size_t num) - : m_folder(folder), m_num(num), m_size(-1), m_deleted(false) -{ +POP3Message::POP3Message( + const shared_ptr & folder, + const size_t num +) + : m_folder(folder), + m_num(num), + m_size(-1), + m_deleted(false) { + folder->registerMessage(this); } -POP3Message::~POP3Message() -{ - try - { +POP3Message::~POP3Message() { + + try { + shared_ptr folder = m_folder.lock(); - if (folder) + if (folder) { folder->unregisterMessage(this); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -void POP3Message::onFolderClosed() -{ +void POP3Message::onFolderClosed() { + m_folder.reset(); } -size_t POP3Message::getNumber() const -{ - return (m_num); +size_t POP3Message::getNumber() const { + + return m_num; } -const message::uid POP3Message::getUID() const -{ - return (m_uid); +const message::uid POP3Message::getUID() const { + + return m_uid; } -size_t POP3Message::getSize() const -{ - if (m_size == static_cast (-1)) +size_t POP3Message::getSize() const { + + if (m_size == static_cast (-1)) { throw exceptions::unfetched_object(); + } - return (m_size); + return m_size; } -bool POP3Message::isExpunged() const -{ - return (false); +bool POP3Message::isExpunged() const { + + return false; } -int POP3Message::getFlags() const -{ +int POP3Message::getFlags() const { + int flags = 0; - if (m_deleted) + if (m_deleted) { flags |= FLAG_DELETED; + } - return (flags); + return flags; } -shared_ptr POP3Message::getStructure() const -{ +shared_ptr POP3Message::getStructure() const { + throw exceptions::operation_not_supported(); } -shared_ptr POP3Message::getStructure() -{ +shared_ptr POP3Message::getStructure() { + throw exceptions::operation_not_supported(); } -shared_ptr POP3Message::getHeader() const -{ - if (m_header == NULL) +shared_ptr POP3Message::getHeader() const { + + if (!m_header) { throw exceptions::unfetched_object(); + } - return (m_header); + return m_header; } -void POP3Message::extract - (utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const bool /* peek */) const -{ +void POP3Message::extract( + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const bool /* peek */ +) const { + shared_ptr folder = m_folder.lock(); - if (!folder) + if (!folder) { throw exceptions::illegal_state("Folder closed"); - else if (!folder->getStore()) + } else if (!folder->getStore()) { throw exceptions::illegal_state("Store disconnected"); + } - if (start != 0 && length != static_cast (-1)) + if (start != 0 && length != static_cast (-1)) { throw exceptions::partial_fetch_not_supported(); + } // Emit the "RETR" command shared_ptr store = folder->m_store.lock(); POP3Command::RETR(m_num)->send(store->getConnection()); - try - { - POP3Response::readLargeResponse - (store->getConnection(), os, progress, m_size == static_cast (-1) ? 0 : m_size); - } - catch (exceptions::command_error& e) - { + try { + + POP3Response::readLargeResponse( + store->getConnection(), os, progress, + m_size == static_cast (-1) ? 0 : m_size + ); + + } catch (exceptions::command_error& e) { + throw exceptions::command_error("RETR", e.response()); } } -void POP3Message::extractPart - (const shared_ptr & /* p */, - utility::outputStream& /* os */, - utility::progressListener* /* progress */, - const size_t /* start */, const size_t /* length */, - const bool /* peek */) const -{ +void POP3Message::extractPart( + const shared_ptr & /* p */, + utility::outputStream& /* os */, + utility::progressListener* /* progress */, + const size_t /* start */, + const size_t /* length */, + const bool /* peek */ +) const { + throw exceptions::operation_not_supported(); } -void POP3Message::fetchPartHeader(const shared_ptr & /* p */) -{ +void POP3Message::fetchPartHeader(const shared_ptr & /* p */) { + throw exceptions::operation_not_supported(); } -void POP3Message::fetch(const shared_ptr & msgFolder, const fetchAttributes& options) -{ +void POP3Message::fetch( + const shared_ptr & msgFolder, + const fetchAttributes& options +) { + shared_ptr folder = m_folder.lock(); - if (folder != msgFolder) + if (folder != msgFolder) { throw exceptions::folder_not_found(); + } // STRUCTURE and FLAGS attributes are not supported by POP3 - if (options.has(fetchAttributes::STRUCTURE | fetchAttributes::FLAGS)) + if (options.has(fetchAttributes::STRUCTURE | fetchAttributes::FLAGS)) { throw exceptions::operation_not_supported(); + } // Check for the real need to fetch the full header static const int optionsRequiringHeader = fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | fetchAttributes::FULL_HEADER | fetchAttributes::IMPORTANCE; - if (!options.has(optionsRequiringHeader)) + if (!options.has(optionsRequiringHeader)) { return; + } // No need to differenciate between ENVELOPE, CONTENT_INFO, ... // since POP3 only permits to retrieve the whole header and not @@ -210,32 +234,34 @@ void POP3Message::fetch(const shared_ptr & msgFolder, const fetchAtt POP3Command::TOP(m_num, 0)->send(store->getConnection()); - try - { + try { + string buffer; utility::outputStreamStringAdapter bufferStream(buffer); - POP3Response::readLargeResponse(store->getConnection(), - bufferStream, /* progress */ NULL, /* predictedSize */ 0); + POP3Response::readLargeResponse( + store->getConnection(), + bufferStream, /* progress */ NULL, /* predictedSize */ 0 + ); m_header = make_shared
(); m_header->parse(buffer); - } - catch (exceptions::command_error& e) - { + + } catch (exceptions::command_error& e) { + throw exceptions::command_error("TOP", e.response()); } } -void POP3Message::setFlags(const int /* flags */, const int /* mode */) -{ +void POP3Message::setFlags(const int /* flags */, const int /* mode */) { + throw exceptions::operation_not_supported(); } -shared_ptr POP3Message::getParsedMessage() -{ +shared_ptr POP3Message::getParsedMessage() { + std::ostringstream oss; utility::outputStreamAdapter os(oss); diff --git a/src/vmime/net/pop3/POP3Message.hpp b/src/vmime/net/pop3/POP3Message.hpp index 7ac86a1b..3d6dc921 100644 --- a/src/vmime/net/pop3/POP3Message.hpp +++ b/src/vmime/net/pop3/POP3Message.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -45,9 +45,8 @@ class POP3Folder; /** POP3 message implementation. */ +class VMIME_EXPORT POP3Message : public message { -class VMIME_EXPORT POP3Message : public message -{ private: friend class POP3Folder; @@ -77,18 +76,22 @@ public: int getFlags() const; void setFlags(const int flags, const int mode = FLAG_MODE_SET); - void extract - (utility::outputStream& os, - utility::progressListener* progress = NULL, - const size_t start = 0, const size_t length = -1, - const bool peek = false) const; + void extract( + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; - void extractPart - (const shared_ptr & p, - utility::outputStream& os, - utility::progressListener* progress = NULL, - const size_t start = 0, const size_t length = -1, - const bool peek = false) const; + void extractPart( + const shared_ptr & p, + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; void fetchPartHeader(const shared_ptr & p); diff --git a/src/vmime/net/pop3/POP3Response.cpp b/src/vmime/net/pop3/POP3Response.cpp index 1d510fb3..725841e3 100644 --- a/src/vmime/net/pop3/POP3Response.cpp +++ b/src/vmime/net/pop3/POP3Response.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,17 +46,26 @@ namespace net { namespace pop3 { -POP3Response::POP3Response(const shared_ptr & sok, const shared_ptr & toh, const shared_ptr & tracer) - : m_socket(sok), m_timeoutHandler(toh), m_tracer(tracer) -{ +POP3Response::POP3Response( + const shared_ptr & sok, + const shared_ptr & toh, + const shared_ptr & tracer +) + : m_socket(sok), + m_timeoutHandler(toh), + m_tracer(tracer) { + } // static -shared_ptr POP3Response::readResponse(const shared_ptr & conn) -{ - shared_ptr resp = shared_ptr - (new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer())); +shared_ptr POP3Response::readResponse( + const shared_ptr & conn +) { + + shared_ptr resp = shared_ptr ( + new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()) + ); string buffer; resp->readResponseImpl(buffer, /* multiLine */ false); @@ -65,18 +74,22 @@ shared_ptr POP3Response::readResponse(const shared_ptr m_code = getResponseCode(buffer); stripResponseCode(buffer, resp->m_text); - if (resp->m_tracer) + if (resp->m_tracer) { resp->m_tracer->traceReceive(buffer); + } return resp; } // static -shared_ptr POP3Response::readMultilineResponse(const shared_ptr & conn) -{ - shared_ptr resp = shared_ptr - (new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer())); +shared_ptr POP3Response::readMultilineResponse( + const shared_ptr & conn +) { + + shared_ptr resp = shared_ptr ( + new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()) + ); string buffer; resp->readResponseImpl(buffer, /* multiLine */ true); @@ -91,32 +104,39 @@ shared_ptr POP3Response::readMultilineResponse(const shared_ptr < std::istringstream iss(nextLines); string line; - if (resp->m_tracer) + if (resp->m_tracer) { resp->m_tracer->traceReceive(firstLine); + } + + while (std::getline(iss, line, '\n')) { - while (std::getline(iss, line, '\n')) - { line = utility::stringUtils::trim(line); resp->m_lines.push_back(line); - if (resp->m_tracer) + if (resp->m_tracer) { resp->m_tracer->traceReceive(line); + } } - if (resp->m_tracer) + if (resp->m_tracer) { resp->m_tracer->traceReceive("."); + } return resp; } // static -shared_ptr POP3Response::readLargeResponse - (const shared_ptr & conn, utility::outputStream& os, - utility::progressListener* progress, const size_t predictedSize) -{ - shared_ptr resp = shared_ptr - (new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer())); +shared_ptr POP3Response::readLargeResponse( + const shared_ptr & conn, + utility::outputStream& os, + utility::progressListener* progress, + const size_t predictedSize +) { + + shared_ptr resp = shared_ptr ( + new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()) + ); string firstLine; const size_t length = resp->readResponseImpl(firstLine, os, progress, predictedSize); @@ -125,8 +145,7 @@ shared_ptr POP3Response::readLargeResponse resp->m_code = getResponseCode(firstLine); stripResponseCode(firstLine, resp->m_text); - if (resp->m_tracer) - { + if (resp->m_tracer) { resp->m_tracer->traceReceive(firstLine); resp->m_tracer->traceReceiveBytes(length - firstLine.length()); resp->m_tracer->traceReceive("."); @@ -136,60 +155,62 @@ shared_ptr POP3Response::readLargeResponse } -bool POP3Response::isSuccess() const -{ +bool POP3Response::isSuccess() const { + return m_code == CODE_OK; } -const string POP3Response::getFirstLine() const -{ +const string POP3Response::getFirstLine() const { + return m_firstLine; } -POP3Response::ResponseCode POP3Response::getCode() const -{ +POP3Response::ResponseCode POP3Response::getCode() const { + return m_code; } -const string POP3Response::getText() const -{ +const string POP3Response::getText() const { + return m_text; } -const string POP3Response::getLineAt(const size_t pos) const -{ +const string POP3Response::getLineAt(const size_t pos) const { + return m_lines[pos]; } -size_t POP3Response::getLineCount() const -{ +size_t POP3Response::getLineCount() const { + return m_lines.size(); } -void POP3Response::readResponseImpl(string& buffer, const bool multiLine) -{ +void POP3Response::readResponseImpl(string& buffer, const bool multiLine) { + bool foundTerminator = false; - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } buffer.clear(); char last1 = '\0', last2 = '\0'; - for ( ; !foundTerminator ; ) - { + for ( ; !foundTerminator ; ) { + // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) + if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { throw exceptions::operation_timed_out(); + } m_timeoutHandler->resetTimeOut(); } @@ -198,36 +219,38 @@ void POP3Response::readResponseImpl(string& buffer, const bool multiLine) string receiveBuffer; m_socket->receive(receiveBuffer); - if (receiveBuffer.empty()) // buffer is empty - { - if (m_socket->getStatus() & socket::STATUS_WANT_WRITE) + if (receiveBuffer.empty()) { // buffer is empty + + if (m_socket->getStatus() & socket::STATUS_WANT_WRITE) { m_socket->waitForWrite(); - else + } else { m_socket->waitForRead(); + } continue; } // We have received data: reset the time-out counter - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } // Check for transparent characters: '\n..' becomes '\n.' const char first = receiveBuffer[0]; - if (first == '.' && last2 == '\n' && last1 == '.') - { + if (first == '.' && last2 == '\n' && last1 == '.') { + receiveBuffer.erase(receiveBuffer.begin()); - } - else if (receiveBuffer.length() >= 2 && first == '.' && - receiveBuffer[1] == '.' && last1 == '\n') - { + + } else if (receiveBuffer.length() >= 2 && first == '.' && + receiveBuffer[1] == '.' && last1 == '\n') { + receiveBuffer.erase(receiveBuffer.begin()); } for (size_t trans ; - string::npos != (trans = receiveBuffer.find("\n..")) ; ) - { + string::npos != (trans = receiveBuffer.find("\n..")) ; ) { + receiveBuffer.replace(trans, 3, "\n."); } @@ -244,28 +267,35 @@ void POP3Response::readResponseImpl(string& buffer, const bool multiLine) // requires a multi-line response, the error response will // include only one line, so we stop waiting for a multi-line // terminator and check for a "normal" one. - if (multiLine && !foundTerminator && buffer.length() >= 4 && buffer[0] == '-') - { + if (multiLine && + !foundTerminator && + buffer.length() >= 4 && buffer[0] == '-') { + foundTerminator = checkTerminator(buffer, false); } } } -size_t POP3Response::readResponseImpl - (string& firstLine, utility::outputStream& os, - utility::progressListener* progress, const size_t predictedSize) -{ +size_t POP3Response::readResponseImpl( + string& firstLine, + utility::outputStream& os, + utility::progressListener* progress, + const size_t predictedSize +) { + size_t current = 0, total = predictedSize; string temp; bool codeDone = false; - if (progress) + if (progress) { progress->start(total); + } - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } utility::inputStreamSocketAdapter sis(*m_socket); utility::stopSequenceFilteredInputStream <5> sfis1(sis, "\r\n.\r\n"); @@ -274,31 +304,27 @@ size_t POP3Response::readResponseImpl utility::inputStream& is = dfis; - while (!is.eof()) - { + while (!is.eof()) { + // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) + if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { throw exceptions::operation_timed_out(); + } } // Receive data from the socket byte_t buffer[65536]; const size_t read = is.read(buffer, sizeof(buffer)); - if (read == 0) // buffer is empty - { - if (m_socket->getStatus() & socket::STATUS_WANT_WRITE) - { + if (read == 0) { // buffer is empty + + if (m_socket->getStatus() & socket::STATUS_WANT_WRITE) { m_socket->waitForWrite(); - } - else if (m_socket->getStatus() & socket::STATUS_WANT_READ) - { + } else if (m_socket->getStatus() & socket::STATUS_WANT_READ) { m_socket->waitForRead(); - } - else - { + } else { // Input stream needs more bytes to continue, but there // is enough data into socket buffer. Do not waitForRead(), // just retry read()ing on the stream. @@ -308,29 +334,30 @@ size_t POP3Response::readResponseImpl } // We have received data: reset the time-out counter - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } // Notify progress current += read; - if (progress) - { + if (progress) { total = std::max(total, current); progress->progress(current, total); } // If we don't have extracted the response code yet - if (!codeDone) - { + if (!codeDone) { + vmime::utility::stringUtils::appendBytesToString(temp, buffer, read); string responseData; - if (stripFirstLine(temp, responseData, &firstLine) == true) - { - if (getResponseCode(firstLine) != CODE_OK) + if (stripFirstLine(temp, responseData, &firstLine) == true) { + + if (getResponseCode(firstLine) != CODE_OK) { throw exceptions::command_error("?", firstLine); + } codeDone = true; @@ -339,61 +366,73 @@ size_t POP3Response::readResponseImpl continue; } - } - else - { + + } else { + // Inject the data into the output stream os.write(buffer, read); } } - if (progress) + if (progress) { progress->stop(total); + } return current; } // static -bool POP3Response::stripFirstLine - (const string& buffer, string& result, string* firstLine) -{ +bool POP3Response::stripFirstLine( + const string& buffer, + string& result, + string* firstLine +) { + const size_t end = buffer.find('\n'); - if (end != string::npos) - { - if (firstLine) *firstLine = utility::stringUtils::trim(buffer.substr(0, end)); + if (end != string::npos) { + + if (firstLine) { + *firstLine = utility::stringUtils::trim(buffer.substr(0, end)); + } + result = buffer.substr(end + 1); + return true; - } - else - { - if (firstLine) *firstLine = utility::stringUtils::trim(buffer); + + } else { + + if (firstLine) { + *firstLine = utility::stringUtils::trim(buffer); + } + result = ""; + return false; } } // static -POP3Response::ResponseCode POP3Response::getResponseCode(const string& buffer) -{ - if (buffer.length() >= 2) - { +POP3Response::ResponseCode POP3Response::getResponseCode(const string& buffer) { + + if (buffer.length() >= 2) { + // +[space] if (buffer[0] == '+' && - (buffer[1] == ' ' || buffer[1] == '\t')) - { + (buffer[1] == ' ' || buffer[1] == '\t')) { + return CODE_READY; } // +OK - if (buffer.length() >= 3) - { + if (buffer.length() >= 3) { + if (buffer[0] == '+' && (buffer[1] == 'O' || buffer[1] == 'o') && - (buffer[2] == 'K' || buffer[1] == 'k')) - { + (buffer[2] == 'K' || buffer[1] == 'k')) { + return CODE_OK; } } @@ -405,37 +444,38 @@ POP3Response::ResponseCode POP3Response::getResponseCode(const string& buffer) // static -void POP3Response::stripResponseCode(const string& buffer, string& result) -{ +void POP3Response::stripResponseCode(const string& buffer, string& result) { + const size_t pos = buffer.find_first_of(" \t"); - if (pos != string::npos) + if (pos != string::npos) { result = buffer.substr(pos + 1); - else + } else { result = buffer; + } } // static -bool POP3Response::checkTerminator(string& buffer, const bool multiLine) -{ +bool POP3Response::checkTerminator(string& buffer, const bool multiLine) { + // Multi-line response - if (multiLine) - { + if (multiLine) { + static const string term1("\r\n.\r\n"); static const string term2("\n.\n"); - return (checkOneTerminator(buffer, term1) || - checkOneTerminator(buffer, term2)); - } + return checkOneTerminator(buffer, term1) || + checkOneTerminator(buffer, term2); + // Normal response - else - { + } else { + static const string term1("\r\n"); static const string term2("\n"); - return (checkOneTerminator(buffer, term1) || - checkOneTerminator(buffer, term2)); + return checkOneTerminator(buffer, term1) || + checkOneTerminator(buffer, term2); } return false; @@ -443,11 +483,11 @@ bool POP3Response::checkTerminator(string& buffer, const bool multiLine) // static -bool POP3Response::checkOneTerminator(string& buffer, const string& term) -{ +bool POP3Response::checkOneTerminator(string& buffer, const string& term) { + if (buffer.length() >= term.length() && - std::equal(buffer.end() - term.length(), buffer.end(), term.begin())) - { + std::equal(buffer.end() - term.length(), buffer.end(), term.begin())) { + buffer.erase(buffer.end() - term.length(), buffer.end()); return true; } diff --git a/src/vmime/net/pop3/POP3Response.hpp b/src/vmime/net/pop3/POP3Response.hpp index 4f0221e6..69f8d5de 100644 --- a/src/vmime/net/pop3/POP3Response.hpp +++ b/src/vmime/net/pop3/POP3Response.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -56,13 +56,12 @@ class POP3Connection; /** A POP3 response, as sent by the server. */ -class VMIME_EXPORT POP3Response : public object -{ +class VMIME_EXPORT POP3Response : public object { + public: /** Possible response codes. */ - enum ResponseCode - { + enum ResponseCode { CODE_OK = 0, CODE_READY, CODE_ERR @@ -100,9 +99,12 @@ public: * @throws exceptions::operation_timed_out if no data * has been received within the granted time */ - static shared_ptr readLargeResponse - (const shared_ptr & conn, utility::outputStream& os, - utility::progressListener* progress, const size_t predictedSize); + static shared_ptr readLargeResponse( + const shared_ptr & conn, + utility::outputStream& os, + utility::progressListener* progress, + const size_t predictedSize + ); /** Returns whether the response is successful ("OK"). @@ -144,12 +146,20 @@ public: private: - POP3Response(const shared_ptr & sok, const shared_ptr & toh, const shared_ptr & tracer); + POP3Response( + const shared_ptr & sok, + const shared_ptr & toh, + const shared_ptr & tracer + ); void readResponseImpl(string& buffer, const bool multiLine); - size_t readResponseImpl - (string& firstLine, utility::outputStream& os, - utility::progressListener* progress, const size_t predictedSize); + + size_t readResponseImpl( + string& firstLine, + utility::outputStream& os, + utility::progressListener* progress, + const size_t predictedSize + ); static bool stripFirstLine(const string& buffer, string& result, string* firstLine); diff --git a/src/vmime/net/pop3/POP3SStore.cpp b/src/vmime/net/pop3/POP3SStore.cpp index 51e58f0e..81a50bc0 100644 --- a/src/vmime/net/pop3/POP3SStore.cpp +++ b/src/vmime/net/pop3/POP3SStore.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,19 +35,22 @@ namespace net { namespace pop3 { -POP3SStore::POP3SStore(const shared_ptr & sess, const shared_ptr & auth) - : POP3Store(sess, auth, true) -{ +POP3SStore::POP3SStore( + const shared_ptr & sess, + const shared_ptr & auth +) + : POP3Store(sess, auth, true) { + } -POP3SStore::~POP3SStore() -{ +POP3SStore::~POP3SStore() { + } -const string POP3SStore::getProtocolName() const -{ +const string POP3SStore::getProtocolName() const { + return "pop3s"; } @@ -58,14 +61,14 @@ const string POP3SStore::getProtocolName() const POP3ServiceInfos POP3SStore::sm_infos(true); -const serviceInfos& POP3SStore::getInfosInstance() -{ +const serviceInfos& POP3SStore::getInfosInstance() { + return sm_infos; } -const serviceInfos& POP3SStore::getInfos() const -{ +const serviceInfos& POP3SStore::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/pop3/POP3SStore.hpp b/src/vmime/net/pop3/POP3SStore.hpp index ad88fa10..76a6ee17 100644 --- a/src/vmime/net/pop3/POP3SStore.hpp +++ b/src/vmime/net/pop3/POP3SStore.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,12 +41,15 @@ namespace pop3 { /** POP3S store service. */ +class VMIME_EXPORT POP3SStore : public POP3Store { -class VMIME_EXPORT POP3SStore : public POP3Store -{ public: - POP3SStore(const shared_ptr & sess, const shared_ptr & auth); + POP3SStore( + const shared_ptr & sess, + const shared_ptr & auth + ); + ~POP3SStore(); const string getProtocolName() const; diff --git a/src/vmime/net/pop3/POP3ServiceInfos.cpp b/src/vmime/net/pop3/POP3ServiceInfos.cpp index 4760d4f2..4deee74d 100644 --- a/src/vmime/net/pop3/POP3ServiceInfos.cpp +++ b/src/vmime/net/pop3/POP3ServiceInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,24 +36,24 @@ namespace pop3 { POP3ServiceInfos::POP3ServiceInfos(const bool pop3s) - : m_pop3s(pop3s) -{ + : m_pop3s(pop3s) { + } -const string POP3ServiceInfos::getPropertyPrefix() const -{ - if (m_pop3s) +const string POP3ServiceInfos::getPropertyPrefix() const { + + if (m_pop3s) { return "store.pop3s."; - else + } else { return "store.pop3."; + } } -const POP3ServiceInfos::props& POP3ServiceInfos::getProperties() const -{ - static props pop3Props = - { +const POP3ServiceInfos::props& POP3ServiceInfos::getProperties() const { + + static props pop3Props = { // POP3-specific options property("options.apop", serviceInfos::property::TYPE_BOOLEAN, "true"), property("options.apop.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), @@ -75,8 +75,8 @@ const POP3ServiceInfos::props& POP3ServiceInfos::getProperties() const property(serviceInfos::property::SERVER_PORT, "110"), }; - static props pop3sProps = - { + static props pop3sProps = { + // POP3-specific options property("options.apop", serviceInfos::property::TYPE_BOOLEAN, "true"), property("options.apop.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), @@ -102,8 +102,8 @@ const POP3ServiceInfos::props& POP3ServiceInfos::getProperties() const } -const std::vector POP3ServiceInfos::getAvailableProperties() const -{ +const std::vector POP3ServiceInfos::getAvailableProperties() const { + std::vector list; const props& p = getProperties(); @@ -120,8 +120,7 @@ const std::vector POP3ServiceInfos::getAvailablePropert list.push_back(p.PROPERTY_AUTH_PASSWORD); #if VMIME_HAVE_TLS_SUPPORT - if (!m_pop3s) - { + if (!m_pop3s) { list.push_back(p.PROPERTY_CONNECTION_TLS); list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED); } diff --git a/src/vmime/net/pop3/POP3ServiceInfos.hpp b/src/vmime/net/pop3/POP3ServiceInfos.hpp index 710d8be3..590a6bea 100644 --- a/src/vmime/net/pop3/POP3ServiceInfos.hpp +++ b/src/vmime/net/pop3/POP3ServiceInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,15 +41,13 @@ namespace pop3 { /** Information about POP3 service. */ +class VMIME_EXPORT POP3ServiceInfos : public serviceInfos { -class VMIME_EXPORT POP3ServiceInfos : public serviceInfos -{ public: POP3ServiceInfos(const bool pop3s); - struct props - { + struct props { // POP3-specific options serviceInfos::property PROPERTY_OPTIONS_APOP; serviceInfos::property PROPERTY_OPTIONS_APOP_FALLBACK; diff --git a/src/vmime/net/pop3/POP3Store.cpp b/src/vmime/net/pop3/POP3Store.cpp index 020cc55e..b06640fe 100644 --- a/src/vmime/net/pop3/POP3Store.cpp +++ b/src/vmime/net/pop3/POP3Store.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,125 +42,150 @@ namespace net { namespace pop3 { -POP3Store::POP3Store(const shared_ptr & sess, const shared_ptr & auth, const bool secured) - : store(sess, getInfosInstance(), auth), m_isPOP3S(secured) -{ +POP3Store::POP3Store( + const shared_ptr & sess, + const shared_ptr & auth, + const bool secured +) + : store(sess, getInfosInstance(), auth), + m_isPOP3S(secured) { + } -POP3Store::~POP3Store() -{ - try - { - if (isConnected()) +POP3Store::~POP3Store() { + + try { + + if (isConnected()) { disconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -const string POP3Store::getProtocolName() const -{ +const string POP3Store::getProtocolName() const { + return "pop3"; } -shared_ptr POP3Store::getDefaultFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); +shared_ptr POP3Store::getDefaultFolder() { - return shared_ptr - (new POP3Folder(folder::path(folder::path::component("INBOX")), - dynamicCast (shared_from_this()))); + if (!isConnected()) { + throw exceptions::illegal_state("Not connected"); + } + + return shared_ptr ( + new POP3Folder( + folder::path(folder::path::component("INBOX")), + dynamicCast (shared_from_this()) + ) + ); } -shared_ptr POP3Store::getRootFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); +shared_ptr POP3Store::getRootFolder() { - return shared_ptr - (new POP3Folder(folder::path(), dynamicCast (shared_from_this()))); + if (!isConnected()) { + throw exceptions::illegal_state("Not connected"); + } + + return shared_ptr ( + new POP3Folder( + folder::path(), + dynamicCast (shared_from_this()) + ) + ); } -shared_ptr POP3Store::getFolder(const folder::path& path) -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); +shared_ptr POP3Store::getFolder(const folder::path& path) { - return shared_ptr - (new POP3Folder(path, dynamicCast (shared_from_this()))); + if (!isConnected()) { + throw exceptions::illegal_state("Not connected"); + } + + return shared_ptr ( + new POP3Folder( + path, + dynamicCast (shared_from_this()) + ) + ); } -bool POP3Store::isValidFolderName(const folder::path::component& /* name */) const -{ +bool POP3Store::isValidFolderName(const folder::path::component& /* name */) const { + return true; } -void POP3Store::connect() -{ - if (isConnected()) - throw exceptions::already_connected(); +void POP3Store::connect() { - m_connection = make_shared - (dynamicCast (shared_from_this()), getAuthenticator()); + if (isConnected()) { + throw exceptions::already_connected(); + } + + m_connection = make_shared ( + dynamicCast (shared_from_this()), getAuthenticator() + ); m_connection->connect(); } -bool POP3Store::isPOP3S() const -{ +bool POP3Store::isPOP3S() const { + return m_isPOP3S; } -bool POP3Store::isConnected() const -{ +bool POP3Store::isConnected() const { + return m_connection && m_connection->isConnected(); } -bool POP3Store::isSecuredConnection() const -{ - if (m_connection == NULL) +bool POP3Store::isSecuredConnection() const { + + if (!m_connection) { return false; + } return m_connection->isSecuredConnection(); } -shared_ptr POP3Store::getConnectionInfos() const -{ - if (m_connection == NULL) +shared_ptr POP3Store::getConnectionInfos() const { + + if (!m_connection) { return null; + } return m_connection->getConnectionInfos(); } -shared_ptr POP3Store::getConnection() -{ +shared_ptr POP3Store::getConnection() { + return m_connection; } -void POP3Store::disconnect() -{ - if (!isConnected()) +void POP3Store::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } for (std::list ::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { + it != m_folders.end() ; ++it) { + (*it)->onStoreDisconnected(); } @@ -172,36 +197,41 @@ void POP3Store::disconnect() } -void POP3Store::noop() -{ - if (!m_connection) +void POP3Store::noop() { + + if (!m_connection) { throw exceptions::not_connected(); + } POP3Command::NOOP()->send(m_connection); shared_ptr response = POP3Response::readResponse(m_connection); - if (!response->isSuccess()) + if (!response->isSuccess()) { throw exceptions::command_error("NOOP", response->getFirstLine()); + } } -void POP3Store::registerFolder(POP3Folder* folder) -{ +void POP3Store::registerFolder(POP3Folder* folder) { + m_folders.push_back(folder); } -void POP3Store::unregisterFolder(POP3Folder* folder) -{ +void POP3Store::unregisterFolder(POP3Folder* folder) { + std::list ::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); - if (it != m_folders.end()) m_folders.erase(it); + + if (it != m_folders.end()) { + m_folders.erase(it); + } } -int POP3Store::getCapabilities() const -{ - return (CAPABILITY_DELETE_MESSAGE); +int POP3Store::getCapabilities() const { + + return CAPABILITY_DELETE_MESSAGE; } @@ -211,14 +241,14 @@ int POP3Store::getCapabilities() const POP3ServiceInfos POP3Store::sm_infos(false); -const serviceInfos& POP3Store::getInfosInstance() -{ +const serviceInfos& POP3Store::getInfosInstance() { + return sm_infos; } -const serviceInfos& POP3Store::getInfos() const -{ +const serviceInfos& POP3Store::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/pop3/POP3Store.hpp b/src/vmime/net/pop3/POP3Store.hpp index 4737715a..140a1ab9 100644 --- a/src/vmime/net/pop3/POP3Store.hpp +++ b/src/vmime/net/pop3/POP3Store.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -51,15 +51,19 @@ class POP3Response; /** POP3 store service. */ +class VMIME_EXPORT POP3Store : public store { -class VMIME_EXPORT POP3Store : public store -{ friend class POP3Folder; friend class POP3Message; public: - POP3Store(const shared_ptr & sess, const shared_ptr & auth, const bool secured = false); + POP3Store( + const shared_ptr & sess, + const shared_ptr & auth, + const bool secured = false + ); + ~POP3Store(); const string getProtocolName() const; diff --git a/src/vmime/net/pop3/POP3Utils.cpp b/src/vmime/net/pop3/POP3Utils.cpp index cb17ea9b..b38161e8 100644 --- a/src/vmime/net/pop3/POP3Utils.cpp +++ b/src/vmime/net/pop3/POP3Utils.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,24 +39,27 @@ namespace pop3 { // static -void POP3Utils::parseMultiListOrUidlResponse(const shared_ptr & response, std::map & result) -{ +void POP3Utils::parseMultiListOrUidlResponse( + const shared_ptr & response, + std::map & result +) { + std::map ids; - for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) - { + for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) { + string line = response->getLineAt(i); string::iterator it = line.begin(); - while (it != line.end() && (*it == ' ' || *it == '\t')) + while (it != line.end() && (*it == ' ' || *it == '\t')) { ++it; + } + + if (it != line.end()) { - if (it != line.end()) - { size_t number = 0; - while (it != line.end() && (*it >= '0' && *it <= '9')) - { + while (it != line.end() && (*it >= '0' && *it <= '9')) { number = (number * 10) + (*it - '0'); ++it; } @@ -64,8 +67,7 @@ void POP3Utils::parseMultiListOrUidlResponse(const shared_ptr & re while (it != line.end() && !(*it == ' ' || *it == '\t')) ++it; while (it != line.end() && (*it == ' ' || *it == '\t')) ++it; - if (it != line.end()) - { + if (it != line.end()) { result.insert(std::map ::value_type(number, string(it, line.end()))); } } @@ -74,27 +76,30 @@ void POP3Utils::parseMultiListOrUidlResponse(const shared_ptr & re -class POP3MessageSetEnumerator : public messageSetEnumerator -{ +class POP3MessageSetEnumerator : public messageSetEnumerator { + public: POP3MessageSetEnumerator(const size_t msgCount) - : m_msgCount(msgCount) - { + : m_msgCount(msgCount) { } - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) { + size_t last = range.getLast(); - if (last == size_t(-1)) last = m_msgCount; - for (size_t i = range.getFirst() ; i <= last ; ++i) + if (last == size_t(-1)) { + last = m_msgCount; + } + + for (size_t i = range.getFirst() ; i <= last ; ++i) { list.push_back(i); + } } - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) - { + void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) { + // Not supported } @@ -109,8 +114,11 @@ private: // static -const std::vector POP3Utils::messageSetToNumberList(const messageSet& msgs, const size_t msgCount) -{ +const std::vector POP3Utils::messageSetToNumberList( + const messageSet& msgs, + const size_t msgCount +) { + POP3MessageSetEnumerator en(msgCount); msgs.enumerate(en); diff --git a/src/vmime/net/pop3/POP3Utils.hpp b/src/vmime/net/pop3/POP3Utils.hpp index b9b2d555..09d15d5b 100644 --- a/src/vmime/net/pop3/POP3Utils.hpp +++ b/src/vmime/net/pop3/POP3Utils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,8 +46,8 @@ namespace pop3 { class POP3Response; -class VMIME_EXPORT POP3Utils -{ +class VMIME_EXPORT POP3Utils { + public: /** Parse a response of type ([integer] [string] \n)*. @@ -63,8 +63,10 @@ public: * @param result points to an associative array which maps a message * number to its corresponding data (either UID or size) */ - static void parseMultiListOrUidlResponse - (const shared_ptr & response, std::map & result); + static void parseMultiListOrUidlResponse( + const shared_ptr & response, + std::map & result + ); /** Returns a list of message numbers given a message set. * @@ -72,7 +74,10 @@ public: * @param msgCount number of messages in folder * @return list of message numbers */ - static const std::vector messageSetToNumberList(const messageSet& msgs, const size_t msgCount); + static const std::vector messageSetToNumberList( + const messageSet& msgs, + const size_t msgCount + ); }; diff --git a/src/vmime/net/pop3/pop3.hpp b/src/vmime/net/pop3/pop3.hpp index 366b1e4a..ced3a97c 100644 --- a/src/vmime/net/pop3/pop3.hpp +++ b/src/vmime/net/pop3/pop3.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 diff --git a/src/vmime/net/securedConnectionInfos.hpp b/src/vmime/net/securedConnectionInfos.hpp index 8ed8b138..60258018 100644 --- a/src/vmime/net/securedConnectionInfos.hpp +++ b/src/vmime/net/securedConnectionInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,8 +40,8 @@ namespace net { /** Information about the secured connection used by a service. */ -class VMIME_EXPORT securedConnectionInfos : public connectionInfos -{ +class VMIME_EXPORT securedConnectionInfos : public connectionInfos { + }; diff --git a/src/vmime/net/sendmail/sendmail.hpp b/src/vmime/net/sendmail/sendmail.hpp index b3692526..a8d1412a 100644 --- a/src/vmime/net/sendmail/sendmail.hpp +++ b/src/vmime/net/sendmail/sendmail.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 diff --git a/src/vmime/net/sendmail/sendmailServiceInfos.cpp b/src/vmime/net/sendmail/sendmailServiceInfos.cpp index 21cac00c..b8654461 100644 --- a/src/vmime/net/sendmail/sendmailServiceInfos.cpp +++ b/src/vmime/net/sendmail/sendmailServiceInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,21 +35,20 @@ namespace net { namespace sendmail { -sendmailServiceInfos::sendmailServiceInfos() -{ +sendmailServiceInfos::sendmailServiceInfos() { + } -const string sendmailServiceInfos::getPropertyPrefix() const -{ +const string sendmailServiceInfos::getPropertyPrefix() const { + return "transport.sendmail."; } -const sendmailServiceInfos::props& sendmailServiceInfos::getProperties() const -{ - static props sendmailProps = - { +const sendmailServiceInfos::props& sendmailServiceInfos::getProperties() const { + + static props sendmailProps = { // Path to sendmail (override default) property("binpath", serviceInfos::property::TYPE_STRING, string(VMIME_SENDMAIL_PATH)) }; @@ -58,8 +57,8 @@ const sendmailServiceInfos::props& sendmailServiceInfos::getProperties() const } -const std::vector sendmailServiceInfos::getAvailableProperties() const -{ +const std::vector sendmailServiceInfos::getAvailableProperties() const { + std::vector list; const props& p = getProperties(); diff --git a/src/vmime/net/sendmail/sendmailServiceInfos.hpp b/src/vmime/net/sendmail/sendmailServiceInfos.hpp index de94e392..bfec2e0c 100644 --- a/src/vmime/net/sendmail/sendmailServiceInfos.hpp +++ b/src/vmime/net/sendmail/sendmailServiceInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,15 +41,13 @@ namespace sendmail { /** Information about sendmail service. */ +class VMIME_EXPORT sendmailServiceInfos : public serviceInfos { -class VMIME_EXPORT sendmailServiceInfos : public serviceInfos -{ public: sendmailServiceInfos(); - struct props - { + struct props { serviceInfos::property PROPERTY_BINPATH; }; diff --git a/src/vmime/net/sendmail/sendmailTransport.cpp b/src/vmime/net/sendmail/sendmailTransport.cpp index b911b129..e39cdd36 100644 --- a/src/vmime/net/sendmail/sendmailTransport.cpp +++ b/src/vmime/net/sendmail/sendmailTransport.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -58,36 +58,42 @@ namespace net { namespace sendmail { -sendmailTransport::sendmailTransport(const shared_ptr & sess, const shared_ptr & auth) - : transport(sess, getInfosInstance(), auth), m_connected(false) -{ +sendmailTransport::sendmailTransport( + const shared_ptr & sess, + const shared_ptr & auth +) + : transport(sess, getInfosInstance(), auth), + m_connected(false) { + } -sendmailTransport::~sendmailTransport() -{ - try - { - if (isConnected()) +sendmailTransport::~sendmailTransport() { + + try { + + if (isConnected()) { disconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -const string sendmailTransport::getProtocolName() const -{ +const string sendmailTransport::getProtocolName() const { + return "sendmail"; } -void sendmailTransport::connect() -{ - if (isConnected()) +void sendmailTransport::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } // Use the specified path for 'sendmail' or a default one if no path is specified m_sendmailPath = GET_PROPERTY(string, PROPERTY_BINPATH); @@ -96,55 +102,61 @@ void sendmailTransport::connect() } -bool sendmailTransport::isConnected() const -{ - return (m_connected); +bool sendmailTransport::isConnected() const { + + return m_connected; } -bool sendmailTransport::isSecuredConnection() const -{ +bool sendmailTransport::isSecuredConnection() const { + return false; } -shared_ptr sendmailTransport::getConnectionInfos() const -{ +shared_ptr sendmailTransport::getConnectionInfos() const { + return make_shared ("localhost", static_cast (0)); } -void sendmailTransport::disconnect() -{ - if (!isConnected()) +void sendmailTransport::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } internalDisconnect(); } -void sendmailTransport::internalDisconnect() -{ +void sendmailTransport::internalDisconnect() { + m_connected = false; } -void sendmailTransport::noop() -{ +void sendmailTransport::noop() { + // Do nothing } -void sendmailTransport::send - (const mailbox& expeditor, const mailboxList& recipients, - utility::inputStream& is, const size_t size, - utility::progressListener* progress, const mailbox& sender) -{ +void sendmailTransport::send( + const mailbox& expeditor, + const mailboxList& recipients, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress, + const mailbox& sender +) { + // If no recipient/expeditor was found, throw an exception - if (recipients.isEmpty()) + if (recipients.isEmpty()) { throw exceptions::no_recipient(); - else if (expeditor.isEmpty()) + } else if (expeditor.isEmpty()) { throw exceptions::no_expeditor(); + } // Construct the argument list std::vector args; @@ -152,38 +164,39 @@ void sendmailTransport::send args.push_back("-i"); args.push_back("-f"); - if (!sender.isEmpty()) + if (!sender.isEmpty()) { args.push_back(expeditor.getEmail().generate()); - else + } else { args.push_back(sender.getEmail().generate()); + } args.push_back("--"); - for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) + for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) { args.push_back(recipients.getMailboxAt(i)->getEmail().generate()); + } // Call sendmail - try - { + try { internalSend(args, is, size, progress); - } - catch (vmime::exception& e) - { + } catch (vmime::exception& e) { throw exceptions::command_error("SEND", "", "sendmail failed", e); } } -void sendmailTransport::internalSend - (const std::vector & args, utility::inputStream& is, - const size_t size, utility::progressListener* progress) -{ +void sendmailTransport::internalSend( + const std::vector & args, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress +) { + const utility::file::path path = vmime::platform::getHandler()-> getFileSystemFactory()->stringToPath(m_sendmailPath); shared_ptr proc = - vmime::platform::getHandler()-> - getChildProcessFactory()->create(path); + vmime::platform::getHandler()->getChildProcessFactory()->create(path); proc->start(args, utility::childProcess::FLAG_REDIRECT_STDIN); @@ -209,14 +222,14 @@ void sendmailTransport::internalSend sendmailServiceInfos sendmailTransport::sm_infos; -const serviceInfos& sendmailTransport::getInfosInstance() -{ +const serviceInfos& sendmailTransport::getInfosInstance() { + return sm_infos; } -const serviceInfos& sendmailTransport::getInfos() const -{ +const serviceInfos& sendmailTransport::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/sendmail/sendmailTransport.hpp b/src/vmime/net/sendmail/sendmailTransport.hpp index da419f95..76e95726 100644 --- a/src/vmime/net/sendmail/sendmailTransport.hpp +++ b/src/vmime/net/sendmail/sendmailTransport.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -45,12 +45,15 @@ namespace sendmail { /** Sendmail local transport service. */ +class VMIME_EXPORT sendmailTransport : public transport { -class VMIME_EXPORT sendmailTransport : public transport -{ public: - sendmailTransport(const shared_ptr & sess, const shared_ptr & auth); + sendmailTransport( + const shared_ptr & sess, + const shared_ptr & auth + ); + ~sendmailTransport(); const string getProtocolName() const; @@ -64,13 +67,14 @@ public: void noop(); - void send - (const mailbox& expeditor, - const mailboxList& recipients, - utility::inputStream& is, - const size_t size, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()); + void send( + const mailbox& expeditor, + const mailboxList& recipients, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox() + ); bool isSecuredConnection() const; shared_ptr getConnectionInfos() const; @@ -79,8 +83,12 @@ private: void internalDisconnect(); - void internalSend(const std::vector & args, utility::inputStream& is, - const size_t size, utility::progressListener* progress); + void internalSend( + const std::vector & args, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress + ); string m_sendmailPath; diff --git a/src/vmime/net/service.cpp b/src/vmime/net/service.cpp index 055f34fa..b43c3e2f 100644 --- a/src/vmime/net/service.cpp +++ b/src/vmime/net/service.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -48,18 +48,20 @@ namespace vmime { namespace net { -service::service(const shared_ptr & sess, const serviceInfos& /* infos */, - const shared_ptr & auth) - : m_session(sess), m_auth(auth) -{ - if (!auth) - { +service::service( + const shared_ptr & sess, + const serviceInfos& /* infos */, + const shared_ptr & auth +) + : m_session(sess), + m_auth(auth) { + + if (!auth) { + #if VMIME_HAVE_SASL_SUPPORT - m_auth = make_shared - (); + m_auth = make_shared (); #else - m_auth = make_shared - (); + m_auth = make_shared (); #endif // VMIME_HAVE_SASL_SUPPORT } @@ -73,89 +75,89 @@ service::service(const shared_ptr & sess, const serviceInfos& /* infos } -service::~service() -{ +service::~service() { + } -shared_ptr service::getSession() const -{ - return (m_session); +shared_ptr service::getSession() const { + + return m_session; } -shared_ptr service::getSession() -{ - return (m_session); +shared_ptr service::getSession() { + + return m_session; } -shared_ptr service::getAuthenticator() const -{ - return (m_auth); +shared_ptr service::getAuthenticator() const { + + return m_auth; } -shared_ptr service::getAuthenticator() -{ - return (m_auth); +shared_ptr service::getAuthenticator() { + + return m_auth; } -void service::setAuthenticator(const shared_ptr & auth) -{ +void service::setAuthenticator(const shared_ptr & auth) { + m_auth = auth; } #if VMIME_HAVE_TLS_SUPPORT -void service::setCertificateVerifier(const shared_ptr & cv) -{ +void service::setCertificateVerifier(const shared_ptr & cv) { + m_certVerifier = cv; } -shared_ptr service::getCertificateVerifier() -{ +shared_ptr service::getCertificateVerifier() { + return m_certVerifier; } #endif // VMIME_HAVE_TLS_SUPPORT -void service::setSocketFactory(const shared_ptr & sf) -{ +void service::setSocketFactory(const shared_ptr & sf) { + m_socketFactory = sf; } -shared_ptr service::getSocketFactory() -{ +shared_ptr service::getSocketFactory() { + return m_socketFactory; } -void service::setTracerFactory(const shared_ptr & tf) -{ +void service::setTracerFactory(const shared_ptr & tf) { + m_tracerFactory = tf; } -shared_ptr service::getTracerFactory() -{ +shared_ptr service::getTracerFactory() { + return m_tracerFactory; } -void service::setTimeoutHandlerFactory(const shared_ptr & thf) -{ +void service::setTimeoutHandlerFactory(const shared_ptr & thf) { + m_toHandlerFactory = thf; } -shared_ptr service::getTimeoutHandlerFactory() -{ +shared_ptr service::getTimeoutHandlerFactory() { + return m_toHandlerFactory; } diff --git a/src/vmime/net/service.hpp b/src/vmime/net/service.hpp index 1fa120d3..bbd2a03d 100644 --- a/src/vmime/net/service.hpp +++ b/src/vmime/net/service.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -55,20 +55,22 @@ namespace net { /** Base class for messaging services. */ +class VMIME_EXPORT service : public object, public enable_shared_from_this { -class VMIME_EXPORT service : public object, public enable_shared_from_this -{ protected: - service(const shared_ptr & sess, const serviceInfos& infos, const shared_ptr & auth); + service( + const shared_ptr & sess, + const serviceInfos& infos, + const shared_ptr & auth + ); public: virtual ~service(); /** Possible service types. */ - enum Type - { + enum Type { TYPE_STORE = 0, /**< The service is a message store. */ TYPE_TRANSPORT /**< The service sends messages. */ }; @@ -198,8 +200,7 @@ public: * @param value property value */ template - void setProperty(const string& name, const TYPE& value) - { + void setProperty(const string& name, const TYPE& value) { m_session->getProperties()[getInfos().getPropertyPrefix() + name] = value; } diff --git a/src/vmime/net/serviceFactory.cpp b/src/vmime/net/serviceFactory.cpp index dc129c63..72b96fef 100644 --- a/src/vmime/net/serviceFactory.cpp +++ b/src/vmime/net/serviceFactory.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,96 +39,103 @@ namespace vmime { namespace net { -serviceFactory::serviceFactory() -{ +serviceFactory::serviceFactory() { + } -serviceFactory::~serviceFactory() -{ +serviceFactory::~serviceFactory() { + } -shared_ptr serviceFactory::getInstance() -{ +shared_ptr serviceFactory::getInstance() { + static serviceFactory instance; return shared_ptr (&instance, noop_shared_ptr_deleter ()); } -shared_ptr serviceFactory::create - (const shared_ptr & sess, const string& protocol, - const shared_ptr & auth) -{ +shared_ptr serviceFactory::create( + const shared_ptr & sess, + const string& protocol, + const shared_ptr & auth +) { + shared_ptr rserv = getServiceByProtocol(protocol); - if (!rserv) + if (!rserv) { throw exceptions::no_factory_available("No service is registered for protocol '" + protocol + "'."); + } return rserv->create(sess, auth); } -shared_ptr serviceFactory::create - (const shared_ptr & sess, const utility::url& u, - const shared_ptr & auth) -{ +shared_ptr serviceFactory::create( + const shared_ptr & sess, + const utility::url& u, + const shared_ptr & auth +) { + shared_ptr serv = create(sess, u.getProtocol(), auth); sess->getProperties()[serv->getInfos().getPropertyPrefix() + "server.address"] = u.getHost(); - if (u.getPort() != utility::url::UNSPECIFIED_PORT) + if (u.getPort() != utility::url::UNSPECIFIED_PORT) { sess->getProperties()[serv->getInfos().getPropertyPrefix() + "server.port"] = u.getPort(); + } // Path portion of the URL is used to point a specific folder (empty = root). // In maildir, this is used to point to the root of the message repository. - if (!u.getPath().empty()) + if (!u.getPath().empty()) { sess->getProperties()[serv->getInfos().getPropertyPrefix() + "server.rootpath"] = u.getPath(); + } - if (!u.getUsername().empty()) - { + if (!u.getUsername().empty()) { sess->getProperties()[serv->getInfos().getPropertyPrefix() + "auth.username"] = u.getUsername(); sess->getProperties()[serv->getInfos().getPropertyPrefix() + "auth.password"] = u.getPassword(); } - return (serv); + return serv; } -shared_ptr serviceFactory::getServiceByProtocol(const string& protocol) const -{ +shared_ptr serviceFactory::getServiceByProtocol(const string& protocol) const { + const string name(utility::stringUtils::toLower(protocol)); for (std::vector >::const_iterator it = m_services.begin() ; - it != m_services.end() ; ++it) - { - if ((*it)->getName() == name) + it != m_services.end() ; ++it) { + + if ((*it)->getName() == name) { return (*it); + } } return null; } -size_t serviceFactory::getServiceCount() const -{ - return (m_services.size()); +size_t serviceFactory::getServiceCount() const { + + return m_services.size(); } -shared_ptr serviceFactory::getServiceAt(const size_t pos) const -{ - return (m_services[pos]); +shared_ptr serviceFactory::getServiceAt(const size_t pos) const { + + return m_services[pos]; } -const std::vector > serviceFactory::getServiceList() const -{ +const std::vector > serviceFactory::getServiceList() const { + std::vector > res; for (std::vector >::const_iterator it = m_services.begin() ; - it != m_services.end() ; ++it) - { + it != m_services.end() ; ++it) { + res.push_back(*it); } @@ -136,8 +143,8 @@ const std::vector > servic } -void serviceFactory::registerService(const shared_ptr & reg) -{ +void serviceFactory::registerService(const shared_ptr & reg) { + m_services.push_back(reg); } diff --git a/src/vmime/net/serviceFactory.hpp b/src/vmime/net/serviceFactory.hpp index cb778b91..8911e080 100644 --- a/src/vmime/net/serviceFactory.hpp +++ b/src/vmime/net/serviceFactory.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -58,8 +58,8 @@ class session; /** A factory to create 'service' objects for a specified protocol. */ -class VMIME_EXPORT serviceFactory -{ +class VMIME_EXPORT serviceFactory { + private: serviceFactory(); @@ -70,8 +70,8 @@ public: static shared_ptr getInstance(); /** Information about a registered service. */ - class registeredService : public object - { + class registeredService : public object { + friend class serviceFactory; protected: @@ -80,9 +80,10 @@ public: public: - virtual shared_ptr create - (const shared_ptr & sess, - const shared_ptr & auth) const = 0; + virtual shared_ptr create( + const shared_ptr & sess, + const shared_ptr & auth + ) const = 0; virtual int getType() const = 0; virtual const string& getName() const = 0; @@ -104,10 +105,11 @@ public: * @return a new service instance for the specified protocol, or NULL if no service * is registered for this protocol */ - shared_ptr create - (const shared_ptr & sess, - const string& protocol, - const shared_ptr & auth = null); + shared_ptr create( + const shared_ptr & sess, + const string& protocol, + const shared_ptr & auth = null + ); /** Create a new service instance from a URL. * @@ -118,10 +120,11 @@ public: * @return a new service instance for the specified protocol or NULL if no service * is registered for this protocol */ - shared_ptr create - (const shared_ptr & sess, - const utility::url& u, - const shared_ptr & auth = null); + shared_ptr create( + const shared_ptr & sess, + const utility::url& u, + const shared_ptr & auth = null + ); /** Return information about a registered protocol. * diff --git a/src/vmime/net/serviceInfos.cpp b/src/vmime/net/serviceInfos.cpp index b3fa7d03..6efab13f 100644 --- a/src/vmime/net/serviceInfos.cpp +++ b/src/vmime/net/serviceInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,31 +35,49 @@ namespace net { // Common properties -const serviceInfos::property serviceInfos::property::SERVER_ADDRESS - ("server.address", serviceInfos::property::TYPE_STRING); +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_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_ROOTPATH( + "server.rootpath", + serviceInfos::property::TYPE_STRING +); -const serviceInfos::property serviceInfos::property::AUTH_USERNAME - ("auth.username", serviceInfos::property::TYPE_STRING); +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::AUTH_PASSWORD( + "auth.password", + serviceInfos::property::TYPE_STRING +); -const serviceInfos::property serviceInfos::property::AUTH_ACCESS_TOKEN - ("auth.accesstoken", serviceInfos::property::TYPE_STRING); +const serviceInfos::property serviceInfos::property::AUTH_ACCESS_TOKEN( + "auth.accesstoken", + serviceInfos::property::TYPE_STRING +); #if VMIME_HAVE_TLS_SUPPORT -const serviceInfos::property serviceInfos::property::CONNECTION_TLS - ("connection.tls", serviceInfos::property::TYPE_BOOLEAN, "false"); +const serviceInfos::property serviceInfos::property::CONNECTION_TLS( + "connection.tls", + serviceInfos::property::TYPE_BOOLEAN, + "false" +); -const serviceInfos::property serviceInfos::property::CONNECTION_TLS_REQUIRED - ("connection.tls.required", serviceInfos::property::TYPE_BOOLEAN, "false"); +const serviceInfos::property serviceInfos::property::CONNECTION_TLS_REQUIRED( + "connection.tls.required", + serviceInfos::property::TYPE_BOOLEAN, + "false" +); #endif // VMIME_HAVE_TLS_SUPPORT @@ -67,29 +85,29 @@ const serviceInfos::property serviceInfos::property::CONNECTION_TLS_REQUIRED // serviceInfos -serviceInfos::serviceInfos() -{ +serviceInfos::serviceInfos() { + } -serviceInfos::serviceInfos(const serviceInfos&) -{ +serviceInfos::serviceInfos(const serviceInfos&) { + } -serviceInfos& serviceInfos::operator=(const serviceInfos&) -{ - return (*this); +serviceInfos& serviceInfos::operator=(const serviceInfos&) { + + return *this; } -serviceInfos::~serviceInfos() -{ +serviceInfos::~serviceInfos() { + } -bool serviceInfos::hasProperty(const shared_ptr & s, const property& p) const -{ +bool serviceInfos::hasProperty(const shared_ptr & s, const property& p) const { + return s->getProperties().hasProperty(getPropertyPrefix() + p.getName()); } @@ -97,18 +115,26 @@ bool serviceInfos::hasProperty(const shared_ptr & s, const property& p) // 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 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) -{ +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; @@ -116,10 +142,13 @@ serviceInfos::property::property } -serviceInfos::property::property - (const property& p, const string& newDefaultValue, - const int addFlags, const int 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; @@ -127,38 +156,38 @@ serviceInfos::property::property } -serviceInfos::property& serviceInfos::property::operator=(const property& p) -{ +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); + return *this; } -const string& serviceInfos::property::getName() const -{ - return (m_name); +const string& serviceInfos::property::getName() const { + + return m_name; } -const string& serviceInfos::property::getDefaultValue() const -{ - return (m_defaultValue); +const string& serviceInfos::property::getDefaultValue() const { + + return m_defaultValue; } -serviceInfos::property::Types serviceInfos::property::getType() const -{ - return (m_type); +serviceInfos::property::Types serviceInfos::property::getType() const { + + return m_type; } -int serviceInfos::property::getFlags() const -{ - return (m_flags); +int serviceInfos::property::getFlags() const { + + return m_flags; } diff --git a/src/vmime/net/serviceInfos.hpp b/src/vmime/net/serviceInfos.hpp index 63261867..ef7d0f45 100644 --- a/src/vmime/net/serviceInfos.hpp +++ b/src/vmime/net/serviceInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,9 +44,8 @@ namespace net { /** Stores information about a messaging service. */ +class VMIME_EXPORT serviceInfos { -class VMIME_EXPORT serviceInfos -{ friend class serviceFactory; protected: @@ -65,8 +64,8 @@ public: /** A service property. */ - class VMIME_EXPORT property - { + class VMIME_EXPORT property { + public: /** The common property 'server.address' which is @@ -114,8 +113,7 @@ public: /** Value types. */ - enum Types - { + enum Types { TYPE_INTEGER, /*< Integer number. */ TYPE_STRING, /*< Character string. */ TYPE_BOOLEAN, /*< Boolean (true or false). */ @@ -125,8 +123,7 @@ public: /** Property flags. */ - enum 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 @@ -143,7 +140,12 @@ public: * @param defaultValue default value * @param flags property attributes */ - property(const string& name, const Types type, const string& defaultValue = "", const int flags = FLAG_DEFAULT); + property( + const string& name, + const Types type, + const string& defaultValue = "", + const int flags = FLAG_DEFAULT + ); /** Construct a new property from an existing property. * @@ -151,7 +153,11 @@ public: * @param addFlags flags to add * @param removeFlags flags to remove */ - property(const property& p, const int addFlags = FLAG_NONE, const int removeFlags = FLAG_NONE); + property( + const property& p, + const int addFlags = FLAG_NONE, + const int removeFlags = FLAG_NONE + ); /** Construct a new property from an existing property. * @@ -160,7 +166,12 @@ public: * @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( + const property& p, + const string& newDefaultValue, + const int addFlags = FLAG_NONE, + const int removeFlags = FLAG_NONE + ); property& operator=(const property& p); @@ -221,13 +232,16 @@ public: * @return value of the property */ template - const TYPE getPropertyValue(const shared_ptr & s, const property& p) const - { - if (p.getFlags() & property::FLAG_REQUIRED) - return s->getProperties()[getPropertyPrefix() + p.getName()].template getValue (); + const TYPE getPropertyValue(const shared_ptr & s, const property& p) const { - return s->getProperties().template getProperty (getPropertyPrefix() + p.getName(), - propertySet::valueFromString (p.getDefaultValue())); + 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 diff --git a/src/vmime/net/serviceRegistration.inl b/src/vmime/net/serviceRegistration.inl index 5a897594..93651999 100644 --- a/src/vmime/net/serviceRegistration.inl +++ b/src/vmime/net/serviceRegistration.inl @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,35 +32,41 @@ namespace net { template -class registeredServiceImpl : public serviceFactory::registeredService -{ +class registeredServiceImpl : public serviceFactory::registeredService { + public: - registeredServiceImpl(const string& name, const int type) - : m_type(type), m_name(name), m_servInfos(S::getInfosInstance()) - { + registeredServiceImpl( + const string& name, + const int type + ) + : m_type(type), + m_name(name), + m_servInfos(S::getInfosInstance()) { + } - shared_ptr create - (const shared_ptr & sess, - const shared_ptr & auth) const - { + shared_ptr create( + const shared_ptr & sess, + const shared_ptr & auth + ) const { + return make_shared (sess, auth); } - const serviceInfos& getInfos() const - { - return (m_servInfos); + const serviceInfos& getInfos() const { + + return m_servInfos; } - const string& getName() const - { - return (m_name); + const string& getName() const { + + return m_name; } - int getType() const - { - return (m_type); + int getType() const { + + return m_type; } private: @@ -73,14 +79,15 @@ private: // Basic service registerer template -class serviceRegisterer -{ +class serviceRegisterer { + public: - serviceRegisterer(const string& protocol, const service::Type type) - { - serviceFactory::getInstance()->registerService - (make_shared >(protocol, type)); + serviceRegisterer(const string& protocol, const service::Type type) { + + serviceFactory::getInstance()->registerService( + make_shared >(protocol, type) + ); } }; diff --git a/src/vmime/net/session.cpp b/src/vmime/net/session.cpp index 9da2fc69..d4b13b47 100644 --- a/src/vmime/net/session.cpp +++ b/src/vmime/net/session.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,8 +38,7 @@ namespace vmime { namespace net { -session::session() -{ +session::session() { #if VMIME_HAVE_TLS_SUPPORT m_tlsProps = make_shared (); @@ -49,8 +48,7 @@ session::session() session::session(const propertySet& props) - : m_props(props) -{ + : m_props(props) { #if VMIME_HAVE_TLS_SUPPORT m_tlsProps = make_shared (); @@ -59,111 +57,123 @@ session::session(const propertySet& props) } -session::~session() -{ +session::~session() { + } // static -shared_ptr session::create() -{ +shared_ptr session::create() { + return shared_ptr (new session()); } // static -shared_ptr session::create(const propertySet& props) -{ +shared_ptr session::create(const propertySet& props) { + return shared_ptr (new session(props)); } -shared_ptr session::getTransport(const shared_ptr & auth) -{ - return (getTransport(m_props["transport.protocol"], auth)); +shared_ptr session::getTransport(const shared_ptr & auth) { + + return getTransport(m_props["transport.protocol"], auth); } -shared_ptr session::getTransport - (const string& protocol, const shared_ptr & auth) -{ +shared_ptr session::getTransport( + const string& protocol, + const shared_ptr & auth +) { + shared_ptr sess(dynamicCast (shared_from_this())); shared_ptr sv = serviceFactory::getInstance()->create(sess, protocol, auth); - if (!sv || sv->getType() != service::TYPE_TRANSPORT) + if (!sv || sv->getType() != service::TYPE_TRANSPORT) { return null; + } return dynamicCast (sv); } -shared_ptr session::getTransport - (const utility::url& url, const shared_ptr & auth) -{ +shared_ptr session::getTransport( + const utility::url& url, + const shared_ptr & auth +) { + shared_ptr sess(dynamicCast (shared_from_this())); shared_ptr sv = serviceFactory::getInstance()->create(sess, url, auth); - if (!sv || sv->getType() != service::TYPE_TRANSPORT) + if (!sv || sv->getType() != service::TYPE_TRANSPORT) { return null; + } return dynamicCast (sv); } -shared_ptr session::getStore(const shared_ptr & auth) -{ - return (getStore(m_props["store.protocol"], auth)); +shared_ptr session::getStore(const shared_ptr & auth) { + + return getStore(m_props["store.protocol"], auth); } -shared_ptr session::getStore - (const string& protocol, const shared_ptr & auth) -{ +shared_ptr session::getStore( + const string& protocol, + const shared_ptr & auth +) { + shared_ptr sess(dynamicCast (shared_from_this())); shared_ptr sv = serviceFactory::getInstance()->create(sess, protocol, auth); - if (!sv || sv->getType() != service::TYPE_STORE) + if (!sv || sv->getType() != service::TYPE_STORE) { return null; + } return dynamicCast (sv); } -shared_ptr session::getStore - (const utility::url& url, const shared_ptr & auth) -{ +shared_ptr session::getStore( + const utility::url& url, + const shared_ptr & auth +) { + shared_ptr sess(dynamicCast (shared_from_this())); shared_ptr sv = serviceFactory::getInstance()->create(sess, url, auth); - if (!sv || sv->getType() != service::TYPE_STORE) + if (!sv || sv->getType() != service::TYPE_STORE) { return null; + } return dynamicCast (sv); } -const propertySet& session::getProperties() const -{ - return (m_props); +const propertySet& session::getProperties() const { + + return m_props; } -propertySet& session::getProperties() -{ - return (m_props); +propertySet& session::getProperties() { + + return m_props; } #if VMIME_HAVE_TLS_SUPPORT -void session::setTLSProperties(const shared_ptr & tlsProps) -{ +void session::setTLSProperties(const shared_ptr & tlsProps) { + m_tlsProps = make_shared (*tlsProps); } -shared_ptr session::getTLSProperties() const -{ +shared_ptr session::getTLSProperties() const { + return m_tlsProps; } diff --git a/src/vmime/net/session.hpp b/src/vmime/net/session.hpp index 75858ef2..7ccd0be6 100644 --- a/src/vmime/net/session.hpp +++ b/src/vmime/net/session.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -53,9 +53,8 @@ class transport; /** An object that contains all the information needed * for connection to a service. */ +class VMIME_EXPORT session : public object, public enable_shared_from_this { -class VMIME_EXPORT session : public object, public enable_shared_from_this -{ public: /** Construct a new session. @@ -84,8 +83,9 @@ public: * @return a new transport service, or NULL if no service is registered for this * protocol or is not a transport protocol */ - shared_ptr getTransport - (const shared_ptr & auth = null); + shared_ptr getTransport( + const shared_ptr & auth = null + ); /** Return a transport service instance for the specified protocol. * @@ -96,9 +96,10 @@ public: * @return a new transport service, or NULL if no service is registered for this * protocol or is not a transport protocol */ - shared_ptr getTransport - (const string& protocol, - const shared_ptr & auth = null); + shared_ptr getTransport( + const string& protocol, + const shared_ptr & auth = null + ); /** Return a transport service instance for the specified URL. * @@ -109,9 +110,10 @@ public: * @return a new transport service, or NULL if no service is registered for this * protocol or is not a transport protocol */ - shared_ptr getTransport - (const utility::url& url, - const shared_ptr & auth = null); + shared_ptr getTransport( + const utility::url& url, + const shared_ptr & auth = null + ); /** Return a transport service instance for the protocol specified * in the session properties. @@ -124,7 +126,9 @@ public: * @return a new store service, or NULL if no service is registered for this * protocol or is not a store protocol */ - shared_ptr getStore(const shared_ptr & auth = null); + shared_ptr getStore( + const shared_ptr & auth = null + ); /** Return a store service instance for the specified protocol. * @@ -135,9 +139,10 @@ public: * @return a new store service, or NULL if no service is registered for this * protocol or is not a store protocol */ - shared_ptr getStore - (const string& protocol, - const shared_ptr & auth = null); + shared_ptr getStore( + const string& protocol, + const shared_ptr & auth = null + ); /** Return a store service instance for the specified URL. * @@ -148,9 +153,10 @@ public: * @return a new store service, or NULL if no service is registered for this * protocol or is not a store protocol */ - shared_ptr getStore - (const utility::url& url, - const shared_ptr & auth = null); + shared_ptr getStore( + const utility::url& url, + const shared_ptr & auth = null + ); /** Properties for the session and for the services. */ diff --git a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp index d1d58e4c..3b242d1b 100644 --- a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp +++ b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,21 +40,31 @@ namespace net { namespace smtp { -SMTPChunkingOutputStreamAdapter::SMTPChunkingOutputStreamAdapter - (const shared_ptr & conn, const size_t size, utility::progressListener* progress) - : m_connection(conn), m_bufferSize(0), m_chunkCount(0), - m_totalSize(size), m_totalSent(0), m_progress(progress) -{ - if (progress) +SMTPChunkingOutputStreamAdapter::SMTPChunkingOutputStreamAdapter( + const shared_ptr & conn, + const size_t size, + utility::progressListener* progress +) + : m_connection(conn), + m_bufferSize(0), + m_chunkCount(0), + m_totalSize(size), + m_totalSent(0), + m_progress(progress) { + + if (progress) { progress->start(size); + } } -void SMTPChunkingOutputStreamAdapter::sendChunk - (const byte_t* const data, const size_t count, const bool last) -{ - if (count == 0 && !last) - { +void SMTPChunkingOutputStreamAdapter::sendChunk( + const byte_t* const data, + const size_t count, + const bool last +) { + + if (count == 0 && !last) { // Nothing to send return; } @@ -65,45 +75,45 @@ void SMTPChunkingOutputStreamAdapter::sendChunk ++m_chunkCount; - if (m_progress) - { + if (m_progress) { + m_totalSent += count; m_totalSize = std::max(m_totalSize, m_totalSent); m_progress->progress(m_totalSent, m_totalSize); } - if (m_connection->getTracer()) + if (m_connection->getTracer()) { m_connection->getTracer()->traceSendBytes(count); + } // If PIPELINING is not supported, read one response for this BDAT command - if (!m_connection->hasExtension("PIPELINING")) - { + if (!m_connection->hasExtension("PIPELINING")) { + shared_ptr resp = m_connection->readResponse(); - if (resp->getCode() != 250) - { + if (resp->getCode() != 250) { m_connection->getTransport()->disconnect(); throw exceptions::command_error("BDAT", resp->getText()); } - } + // If PIPELINING is supported, read one response for each chunk (ie. number // of BDAT commands issued) after the last chunk has been sent - else if (last) - { + } else if (last) { + bool invalidReply = false; shared_ptr resp; - for (unsigned int i = 0 ; i < m_chunkCount ; ++i) - { + for (unsigned int i = 0 ; i < m_chunkCount ; ++i) { + resp = m_connection->readResponse(); - if (resp->getCode() != 250) + if (resp->getCode() != 250) { invalidReply = true; + } } - if (invalidReply) - { + if (invalidReply) { m_connection->getTransport()->disconnect(); throw exceptions::command_error("BDAT", resp->getText()); } @@ -111,14 +121,16 @@ void SMTPChunkingOutputStreamAdapter::sendChunk } -void SMTPChunkingOutputStreamAdapter::writeImpl - (const byte_t* const data, const size_t count) -{ +void SMTPChunkingOutputStreamAdapter::writeImpl( + const byte_t* const data, + const size_t count +) { + const byte_t* curData = data; size_t curCount = count; - while (curCount != 0) - { + while (curCount != 0) { + // Fill the buffer const size_t remaining = sizeof(m_buffer) - m_bufferSize; const size_t bytesToCopy = std::min(remaining, curCount); @@ -130,8 +142,8 @@ void SMTPChunkingOutputStreamAdapter::writeImpl curCount -= bytesToCopy; // If the buffer is full, send this chunk - if (m_bufferSize >= sizeof(m_buffer)) - { + if (m_bufferSize >= sizeof(m_buffer)) { + sendChunk(m_buffer, m_bufferSize, /* last */ false); m_bufferSize = 0; } @@ -139,21 +151,23 @@ void SMTPChunkingOutputStreamAdapter::writeImpl } -void SMTPChunkingOutputStreamAdapter::flush() -{ +void SMTPChunkingOutputStreamAdapter::flush() { + sendChunk(m_buffer, m_bufferSize, /* last */ true); m_bufferSize = 0; - if (m_progress) + if (m_progress) { m_progress->stop(m_totalSize); + } - if (m_connection->getTracer()) + if (m_connection->getTracer()) { m_connection->getTracer()->traceSendBytes(m_bufferSize); + } } -size_t SMTPChunkingOutputStreamAdapter::getBlockSize() -{ +size_t SMTPChunkingOutputStreamAdapter::getBlockSize() { + return sizeof(m_buffer); } diff --git a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp index 7bda1e73..4ef466a2 100644 --- a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp +++ b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -45,12 +45,15 @@ class SMTPConnection; /** An output stream adapter used with ESMTP CHUNKING extension. */ -class VMIME_EXPORT SMTPChunkingOutputStreamAdapter : public utility::outputStream -{ +class VMIME_EXPORT SMTPChunkingOutputStreamAdapter : public utility::outputStream { + public: - SMTPChunkingOutputStreamAdapter(const shared_ptr & conn, - const size_t size, utility::progressListener* progress); + SMTPChunkingOutputStreamAdapter( + const shared_ptr & conn, + const size_t size, + utility::progressListener* progress + ); void flush(); diff --git a/src/vmime/net/smtp/SMTPCommand.cpp b/src/vmime/net/smtp/SMTPCommand.cpp index acf59830..8581a994 100644 --- a/src/vmime/net/smtp/SMTPCommand.cpp +++ b/src/vmime/net/smtp/SMTPCommand.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,14 +42,15 @@ namespace smtp { SMTPCommand::SMTPCommand(const string& text, const string& traceText) - : m_text(text), m_traceText(traceText) + : m_text(text), + m_traceText(traceText) { } // static -shared_ptr SMTPCommand::EHLO(const string& hostname) -{ +shared_ptr SMTPCommand::EHLO(const string& hostname) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "EHLO " << hostname; @@ -59,8 +60,8 @@ shared_ptr SMTPCommand::EHLO(const string& hostname) // static -shared_ptr SMTPCommand::HELO(const string& hostname) -{ +shared_ptr SMTPCommand::HELO(const string& hostname) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "HELO " << hostname; @@ -70,8 +71,8 @@ shared_ptr SMTPCommand::HELO(const string& hostname) // static -shared_ptr SMTPCommand::AUTH(const string& mechName) -{ +shared_ptr SMTPCommand::AUTH(const string& mechName) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "AUTH " << mechName; @@ -81,8 +82,8 @@ shared_ptr SMTPCommand::AUTH(const string& mechName) // static -shared_ptr SMTPCommand::AUTH(const string& mechName, const std::string& initialResponse) -{ +shared_ptr SMTPCommand::AUTH(const string& mechName, const std::string& initialResponse) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "AUTH " << mechName << " " << initialResponse; @@ -92,61 +93,63 @@ shared_ptr SMTPCommand::AUTH(const string& mechName, const std::st // static -shared_ptr SMTPCommand::STARTTLS() -{ +shared_ptr SMTPCommand::STARTTLS() { + return createCommand("STARTTLS"); } // static -shared_ptr SMTPCommand::MAIL(const mailbox& mbox, const bool utf8) -{ +shared_ptr SMTPCommand::MAIL(const mailbox& mbox, const bool utf8) { + return MAIL(mbox, utf8, 0); } // static -shared_ptr SMTPCommand::MAIL(const mailbox& mbox, const bool utf8, const size_t size) -{ +shared_ptr SMTPCommand::MAIL(const mailbox& mbox, const bool utf8, const size_t size) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "MAIL FROM:<"; - if (utf8) - { + if (utf8) { + cmd << mbox.getEmail().toText().getConvertedText(vmime::charsets::UTF_8); - } - else - { + + } else { + vmime::utility::outputStreamAdapter cmd2(cmd); mbox.getEmail().generate(cmd2); } cmd << ">"; - if (utf8) + if (utf8) { cmd << " SMTPUTF8"; + } - if (size != 0) + if (size != 0) { cmd << " SIZE=" << size; + } return createCommand(cmd.str()); } // static -shared_ptr SMTPCommand::RCPT(const mailbox& mbox, const bool utf8) -{ +shared_ptr SMTPCommand::RCPT(const mailbox& mbox, const bool utf8) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "RCPT TO:<"; - if (utf8) - { + if (utf8) { + cmd << mbox.getEmail().toText().getConvertedText(vmime::charsets::UTF_8); - } - else - { + + } else { + vmime::utility::outputStreamAdapter cmd2(cmd); mbox.getEmail().generate(cmd2); } @@ -158,75 +161,78 @@ shared_ptr SMTPCommand::RCPT(const mailbox& mbox, const bool utf8) // static -shared_ptr SMTPCommand::RSET() -{ +shared_ptr SMTPCommand::RSET() { + return createCommand("RSET"); } // static -shared_ptr SMTPCommand::DATA() -{ +shared_ptr SMTPCommand::DATA() { + return createCommand("DATA"); } // static -shared_ptr SMTPCommand::BDAT(const size_t chunkSize, const bool last) -{ +shared_ptr SMTPCommand::BDAT(const size_t chunkSize, const bool last) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "BDAT " << chunkSize; - if (last) + if (last) { cmd << " LAST"; + } return createCommand(cmd.str()); } // static -shared_ptr SMTPCommand::NOOP() -{ +shared_ptr SMTPCommand::NOOP() { + return createCommand("NOOP"); } // static -shared_ptr SMTPCommand::QUIT() -{ +shared_ptr SMTPCommand::QUIT() { + return createCommand("QUIT"); } // static -shared_ptr SMTPCommand::createCommand(const string& text, const string& traceText) -{ - if (traceText.empty()) +shared_ptr SMTPCommand::createCommand(const string& text, const string& traceText) { + + if (traceText.empty()) { return shared_ptr (new SMTPCommand(text, text)); - else + } else { return shared_ptr (new SMTPCommand(text, traceText)); + } } -const string SMTPCommand::getText() const -{ +const string SMTPCommand::getText() const { + return m_text; } -const string SMTPCommand::getTraceText() const -{ +const string SMTPCommand::getTraceText() const { + return m_traceText; } -void SMTPCommand::writeToSocket(const shared_ptr & sok, shared_ptr tr) -{ +void SMTPCommand::writeToSocket(const shared_ptr & sok, shared_ptr tr) { + sok->send(m_text + "\r\n"); - if (tr) + if (tr) { tr->traceSend(m_traceText); + } } diff --git a/src/vmime/net/smtp/SMTPCommand.hpp b/src/vmime/net/smtp/SMTPCommand.hpp index bb52dbc4..137993c4 100644 --- a/src/vmime/net/smtp/SMTPCommand.hpp +++ b/src/vmime/net/smtp/SMTPCommand.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -54,8 +54,8 @@ namespace smtp { /** A SMTP command, as sent to server. */ -class VMIME_EXPORT SMTPCommand : public object -{ +class VMIME_EXPORT SMTPCommand : public object { + public: static shared_ptr HELO(const string& hostname); diff --git a/src/vmime/net/smtp/SMTPCommandSet.cpp b/src/vmime/net/smtp/SMTPCommandSet.cpp index 425b3535..eab7086a 100644 --- a/src/vmime/net/smtp/SMTPCommandSet.cpp +++ b/src/vmime/net/smtp/SMTPCommandSet.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,23 +42,24 @@ namespace smtp { SMTPCommandSet::SMTPCommandSet(const bool pipeline) - : SMTPCommand("", ""), m_pipeline(pipeline), - m_started(false), m_lastCommandSent() -{ + : SMTPCommand("", ""), + m_pipeline(pipeline), + m_started(false), + m_lastCommandSent() { + } // static -shared_ptr SMTPCommandSet::create(const bool pipeline) -{ +shared_ptr SMTPCommandSet::create(const bool pipeline) { + return shared_ptr (new SMTPCommandSet(pipeline)); } -void SMTPCommandSet::addCommand(const shared_ptr & cmd) -{ - if (m_started) - { +void SMTPCommandSet::addCommand(const shared_ptr & cmd) { + + if (m_started) { throw std::runtime_error("Could not add command to pipeline: " "one or more commands have already been sent to the server."); } @@ -67,34 +68,34 @@ void SMTPCommandSet::addCommand(const shared_ptr & cmd) } -void SMTPCommandSet::writeToSocket(const shared_ptr & sok, const shared_ptr & tr) -{ - if (m_pipeline) - { - if (!m_started) - { +void SMTPCommandSet::writeToSocket(const shared_ptr & sok, const shared_ptr & tr) { + + if (m_pipeline) { + + if (!m_started) { + // Send all commands at once for (std::list >::const_iterator it = m_commands.begin() ; - it != m_commands.end() ; ++it) - { + it != m_commands.end() ; ++it) { + shared_ptr cmd = *it; cmd->writeToSocket(sok, tr); } } - if (!m_commands.empty()) - { + if (!m_commands.empty()) { + // Advance the pointer to last command sent shared_ptr cmd = m_commands.front(); m_commands.pop_front(); m_lastCommandSent = cmd; } - } - else - { - if (!m_commands.empty()) - { + + } else { + + if (!m_commands.empty()) { + // Send only one command shared_ptr cmd = m_commands.front(); m_commands.pop_front(); @@ -109,14 +110,14 @@ void SMTPCommandSet::writeToSocket(const shared_ptr & sok, const shared_ } -const string SMTPCommandSet::getText() const -{ +const string SMTPCommandSet::getText() const { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); for (std::list >::const_iterator it = m_commands.begin() ; - it != m_commands.end() ; ++it) - { + it != m_commands.end() ; ++it) { + cmd << (*it)->getText() << "\r\n"; } @@ -124,14 +125,14 @@ const string SMTPCommandSet::getText() const } -const string SMTPCommandSet::getTraceText() const -{ +const string SMTPCommandSet::getTraceText() const { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); for (std::list >::const_iterator it = m_commands.begin() ; - it != m_commands.end() ; ++it) - { + it != m_commands.end() ; ++it) { + cmd << (*it)->getTraceText() << "\r\n"; } @@ -139,14 +140,14 @@ const string SMTPCommandSet::getTraceText() const } -bool SMTPCommandSet::isFinished() const -{ +bool SMTPCommandSet::isFinished() const { + return (m_pipeline && m_started) || (m_commands.size() == 0 && m_started); } -shared_ptr SMTPCommandSet::getLastCommandSent() const -{ +shared_ptr SMTPCommandSet::getLastCommandSent() const { + return m_lastCommandSent; } diff --git a/src/vmime/net/smtp/SMTPCommandSet.hpp b/src/vmime/net/smtp/SMTPCommandSet.hpp index af69366e..2fd977c9 100644 --- a/src/vmime/net/smtp/SMTPCommandSet.hpp +++ b/src/vmime/net/smtp/SMTPCommandSet.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,8 +44,8 @@ namespace smtp { /** A set of SMTP commands, which may be sent all at once * to the server if pipelining is supported. */ -class VMIME_EXPORT SMTPCommandSet : public SMTPCommand -{ +class VMIME_EXPORT SMTPCommandSet : public SMTPCommand { + public: /** Creates a new set of SMTP commands. diff --git a/src/vmime/net/smtp/SMTPConnection.cpp b/src/vmime/net/smtp/SMTPConnection.cpp index cad107cb..7680fecf 100644 --- a/src/vmime/net/smtp/SMTPConnection.cpp +++ b/src/vmime/net/smtp/SMTPConnection.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -67,37 +67,48 @@ namespace smtp { -SMTPConnection::SMTPConnection(const shared_ptr & transport, const shared_ptr & auth) - : m_transport(transport), m_auth(auth), m_socket(null), m_timeoutHandler(null), - m_authenticated(false), m_secured(false), m_extendedSMTP(false) -{ +SMTPConnection::SMTPConnection( + const shared_ptr & transport, + const shared_ptr & auth +) + : m_transport(transport), + m_auth(auth), + m_socket(null), + m_timeoutHandler(null), + m_authenticated(false), + m_secured(false), + m_extendedSMTP(false) { + static int connectionId = 0; - if (transport->getTracerFactory()) + if (transport->getTracerFactory()) { m_tracer = transport->getTracerFactory()->create(transport, ++connectionId); + } } -SMTPConnection::~SMTPConnection() -{ - try - { - if (isConnected()) +SMTPConnection::~SMTPConnection() { + + try { + + if (isConnected()) { disconnect(); - else if (m_socket) + } else if (m_socket) { internalDisconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -void SMTPConnection::connect() -{ - if (isConnected()) +void SMTPConnection::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS); const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT); @@ -105,29 +116,30 @@ void SMTPConnection::connect() shared_ptr transport = m_transport.lock(); // Create the time-out handler - if (transport->getTimeoutHandlerFactory()) + if (transport->getTimeoutHandlerFactory()) { m_timeoutHandler = transport->getTimeoutHandlerFactory()->create(); + } // Create and connect the socket m_socket = transport->getSocketFactory()->create(m_timeoutHandler); m_socket->setTracer(m_tracer); #if VMIME_HAVE_TLS_SUPPORT - if (transport->isSMTPS()) // dedicated port/SMTPS - { - shared_ptr tlsSession = tls::TLSSession::create - (transport->getCertificateVerifier(), - transport->getSession()->getTLSProperties()); + if (transport->isSMTPS()) { // dedicated port/SMTPS - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); + shared_ptr tlsSession = tls::TLSSession::create( + transport->getCertificateVerifier(), + transport->getSession()->getTLSProperties() + ); + + shared_ptr tlsSocket = tlsSession->getSocket(m_socket); m_socket = tlsSocket; m_secured = true; m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); - } - else + + } else #endif // VMIME_HAVE_TLS_SUPPORT { m_cntInfos = make_shared (address, port); @@ -142,8 +154,7 @@ void SMTPConnection::connect() shared_ptr resp; - if ((resp = readResponse())->getCode() != 220) - { + if ((resp = readResponse())->getCode() != 220) { internalDisconnect(); throw exceptions::connection_greeting_error(resp->getText()); } @@ -158,27 +169,24 @@ void SMTPConnection::connect() const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED) && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED); - if (!transport->isSMTPS() && tls) // only if not SMTPS - { - try - { + if (!transport->isSMTPS() && tls) { // only if not SMTPS + + try { + startTLS(); - } + // Non-fatal error - catch (exceptions::command_error&) - { - if (tlsRequired) - { + } catch (exceptions::command_error&) { + + if (tlsRequired) { throw; - } - else - { + } else { // TLS is not required, so don't bother } - } + // Fatal error - catch (...) - { + } catch (...) { + throw; } @@ -188,15 +196,16 @@ void SMTPConnection::connect() #endif // VMIME_HAVE_TLS_SUPPORT // Authentication - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_NEEDAUTH)) + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_NEEDAUTH)) { authenticate(); - else + } else { m_authenticated = true; + } } -void SMTPConnection::helo() -{ +void SMTPConnection::helo() { + // First, try Extended SMTP (ESMTP) // // eg: C: EHLO thismachine.ourdomain.com @@ -209,8 +218,8 @@ void SMTPConnection::helo() shared_ptr resp; - if ((resp = readResponse())->getCode() != 250) - { + if ((resp = readResponse())->getCode() != 250) { + // Next, try "Basic" SMTP // // eg: C: HELO thismachine.ourdomain.com @@ -218,24 +227,23 @@ void SMTPConnection::helo() sendRequest(SMTPCommand::HELO(platform::getHandler()->getHostName())); - if ((resp = readResponse())->getCode() != 250) - { + if ((resp = readResponse())->getCode() != 250) { internalDisconnect(); throw exceptions::connection_greeting_error(resp->getLastLine().getText()); } m_extendedSMTP = false; m_extensions.clear(); - } - else - { + + } else { + m_extendedSMTP = true; m_extensions.clear(); // Get supported extensions from SMTP response // One extension per line, format is: EXT PARAM1 PARAM2... - for (size_t i = 1, n = resp->getLineCount() ; i < n ; ++i) - { + for (size_t i = 1, n = resp->getLineCount() ; i < n ; ++i) { + const string line = resp->getLineAt(i).getText(); std::istringstream iss(line); @@ -248,14 +256,15 @@ void SMTPConnection::helo() string param; // Special case: some servers send "AUTH=MECH [MECH MECH...]" - if (ext.length() >= 5 && utility::stringUtils::toUpper(ext.substr(0, 5)) == "AUTH=") - { + if (ext.length() >= 5 && utility::stringUtils::toUpper(ext.substr(0, 5)) == "AUTH=") { + params.push_back(utility::stringUtils::toUpper(ext.substr(5))); ext = "AUTH"; } - while (iss >> param) + while (iss >> param) { params.push_back(utility::stringUtils::toUpper(param)); + } m_extensions[ext] = params; } @@ -263,30 +272,32 @@ void SMTPConnection::helo() } -bool SMTPConnection::hasExtension - (const std::string& extName, std::vector * params) const -{ +bool SMTPConnection::hasExtension( + const std::string& extName, + std::vector * params +) const { + std::map >::const_iterator it = m_extensions.find(extName); - if (it != m_extensions.end()) - { - if (params) + if (it != m_extensions.end()) { + + if (params) { *params = (*it).second; + } return true; - } - else - { + + } else { + return false; } } -void SMTPConnection::authenticate() -{ - if (!m_extendedSMTP) - { +void SMTPConnection::authenticate() { + + if (!m_extendedSMTP) { internalDisconnect(); throw exceptions::command_error("AUTH", "ESMTP not supported."); } @@ -295,17 +306,17 @@ void SMTPConnection::authenticate() #if VMIME_HAVE_SASL_SUPPORT // Try SASL authentication - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) - { - try - { + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) { + + try { + authenticateSASL(); m_authenticated = true; return; - } - catch (exception&) - { + + } catch (exception&) { + internalDisconnect(); throw; } @@ -313,30 +324,36 @@ void SMTPConnection::authenticate() #else // no SASL // allow AUTH PLAIN over TLS - it is a popular and simple mechanism - if (m_secured) - { + if (m_secured) { + std::vector authMechs; hasExtension("AUTH", &authMechs); - if (authMechs.empty()) + if (authMechs.empty()) { throw exceptions::authentication_error("No AUTH mechanism available."); + } const string plain("PLAIN"); - if (std::find(authMechs.begin(), authMechs.end(), plain) != authMechs.end()) - { + + if (std::find(authMechs.begin(), authMechs.end(), plain) != authMechs.end()) { + const string username = getAuthenticator()->getUsername(); const string password = getAuthenticator()->getPassword(); const string authToken = username + '\0' + username + '\0' + password; + auto encoder = new vmime::utility::encoder::b64Encoder(); utility::inputStreamStringAdapter in(authToken); string authTokenBase64; utility::outputStreamStringAdapter out(authTokenBase64); encoder->encode(in, out); + sendRequest(SMTPCommand::AUTH(plain, authTokenBase64)); + shared_ptr response = readResponse(); + const int code = response ? response->getCode() : -1; - if (code == 235) - { + + if (code == 235) { m_authenticated = true; return; } @@ -353,56 +370,61 @@ void SMTPConnection::authenticate() #if VMIME_HAVE_SASL_SUPPORT -void SMTPConnection::authenticateSASL() -{ - if (!dynamicCast (getAuthenticator())) +void SMTPConnection::authenticateSASL() { + + if (!dynamicCast (getAuthenticator())) { throw exceptions::authentication_error("No SASL authenticator available."); + } // Obtain SASL mechanisms supported by server from ESMTP extensions std::vector saslMechs; hasExtension("AUTH", &saslMechs); - if (saslMechs.empty()) + if (saslMechs.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } std::vector > mechList; shared_ptr saslContext = security::sasl::SASLContext::create(); - for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) - { - try - { + for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) { + + try { + mechList.push_back (saslContext->createMechanism(saslMechs[i])); - } - catch (exceptions::no_such_mechanism&) - { + + } catch (exceptions::no_such_mechanism&) { + // Ignore mechanism } } - if (mechList.empty()) + if (mechList.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } // Try to suggest a mechanism among all those supported shared_ptr suggestedMech = saslContext->suggestMechanism(mechList); - if (!suggestedMech) + if (!suggestedMech) { throw exceptions::authentication_error("Unable to suggest SASL mechanism."); + } // Allow application to choose which mechanisms to use mechList = dynamicCast (getAuthenticator())-> getAcceptableMechanisms(mechList, suggestedMech); - if (mechList.empty()) + if (mechList.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } // Try each mechanism in the list in turn - for (unsigned int i = 0 ; i < mechList.size() ; ++i) - { + for (unsigned int i = 0 ; i < mechList.size() ; ++i) { + shared_ptr mech = mechList[i]; shared_ptr saslSession = @@ -410,8 +432,8 @@ void SMTPConnection::authenticateSASL() saslSession->init(); - if (saslSession->getMechanism()->hasInitialResponse()) - { + if (saslSession->getMechanism()->hasInitialResponse()) { + byte_t* initialResp = 0; size_t initialRespLen = 0; @@ -420,100 +442,103 @@ void SMTPConnection::authenticateSASL() string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen)); delete [] initialResp; - if (encodedInitialResp.empty()) + if (encodedInitialResp.empty()) { sendRequest(SMTPCommand::AUTH(mech->getName(), "=")); - else + } else { sendRequest(SMTPCommand::AUTH(mech->getName(), encodedInitialResp)); - } - else - { + } + + } else { + sendRequest(SMTPCommand::AUTH(mech->getName())); } - for (bool cont = true ; cont ; ) - { + for (bool cont = true ; cont ; ) { + shared_ptr response = readResponse(); - switch (response->getCode()) - { - case 235: - { - m_socket = saslSession->getSecuredSocket(m_socket); - return; - } - case 334: - { - byte_t* challenge = 0; - size_t challengeLen = 0; + switch (response->getCode()) { - byte_t* resp = 0; - size_t respLen = 0; + case 235: { - try - { - // Extract challenge - saslContext->decodeB64(response->getText(), &challenge, &challengeLen); - - // Prepare response - saslSession->evaluateChallenge - (challenge, challengeLen, &resp, &respLen); - - // Send response - const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n"; - m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length()); - - if (m_tracer) - m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange"); + m_socket = saslSession->getSecuredSocket(m_socket); + return; } - catch (exceptions::sasl_exception& e) - { - if (challenge) - { - delete [] challenge; - challenge = NULL; + case 334: { + + byte_t* challenge = 0; + size_t challengeLen = 0; + + byte_t* resp = 0; + size_t respLen = 0; + + try { + + // Extract challenge + saslContext->decodeB64(response->getText(), &challenge, &challengeLen); + + // Prepare response + saslSession->evaluateChallenge(challenge, challengeLen, &resp, &respLen); + + // Send response + const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n"; + m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length()); + + if (m_tracer) { + m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange"); + } + + } catch (exceptions::sasl_exception& e) { + + if (challenge) { + delete [] challenge; + challenge = NULL; + } + + if (resp) { + delete [] resp; + resp = NULL; + } + + // Cancel SASL exchange + m_socket->send("*\r\n"); + + if (m_tracer) { + m_tracer->traceSend("*"); + } + + } catch (...) { + + if (challenge) { + delete [] challenge; + } + + if (resp) { + delete [] resp; + } + + throw; } - if (resp) - { - delete [] resp; - resp = NULL; + if (challenge) { + delete [] challenge; } - // Cancel SASL exchange - m_socket->send("*\r\n"); - - if (m_tracer) - m_tracer->traceSend("*"); - } - catch (...) - { - if (challenge) - delete [] challenge; - - if (resp) + if (resp) { delete [] resp; + } - throw; + break; } + default: - if (challenge) - delete [] challenge; - - if (resp) - delete [] resp; - - break; - } - default: - - cont = false; - break; + cont = false; + break; } } } - throw exceptions::authentication_error - ("Could not authenticate using SASL: all mechanisms failed."); + throw exceptions::authentication_error("Could not authenticate using SASL: all mechanisms failed."); } #endif // VMIME_HAVE_SASL_SUPPORT @@ -521,42 +546,44 @@ void SMTPConnection::authenticateSASL() #if VMIME_HAVE_TLS_SUPPORT -void SMTPConnection::startTLS() -{ - try - { +void SMTPConnection::startTLS() { + + try { + sendRequest(SMTPCommand::STARTTLS()); shared_ptr resp = readResponse(); - if (resp->getCode() != 220) - { - throw SMTPCommandError("STARTTLS", resp->getText(), - resp->getCode(), resp->getEnhancedCode()); + if (resp->getCode() != 220) { + + throw SMTPCommandError( + "STARTTLS", resp->getText(), resp->getCode(), resp->getEnhancedCode() + ); } - shared_ptr tlsSession = tls::TLSSession::create - (getTransport()->getCertificateVerifier(), - getTransport()->getSession()->getTLSProperties()); + shared_ptr tlsSession = tls::TLSSession::create( + getTransport()->getCertificateVerifier(), + getTransport()->getSession()->getTLSProperties() + ); - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); + shared_ptr tlsSocket = tlsSession->getSocket(m_socket); tlsSocket->handshake(); m_socket = tlsSocket; m_secured = true; - m_cntInfos = make_shared - (m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket); - } - catch (exceptions::command_error&) - { + m_cntInfos = make_shared ( + m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket + ); + + } catch (exceptions::command_error&) { + // Non-fatal error throw; - } - catch (exception&) - { + + } catch (exception&) { + // Fatal error internalDisconnect(); throw; @@ -566,28 +593,29 @@ void SMTPConnection::startTLS() #endif // VMIME_HAVE_TLS_SUPPORT -void SMTPConnection::disconnect() -{ - if (!isConnected()) +void SMTPConnection::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } internalDisconnect(); } -void SMTPConnection::internalDisconnect() -{ - if (isConnected()) - { - try - { +void SMTPConnection::internalDisconnect() { + + if (isConnected()) { + + try { + sendRequest(SMTPCommand::QUIT()); // Do not wait for server response. This is contrary to the RFC, but // some servers never send a response to a QUIT command. - } - catch (exception&) - { + + } catch (exception&) { + // Not important } } @@ -605,16 +633,17 @@ void SMTPConnection::internalDisconnect() } -void SMTPConnection::sendRequest(const shared_ptr & cmd) -{ +void SMTPConnection::sendRequest(const shared_ptr & cmd) { + cmd->writeToSocket(m_socket, m_tracer); } -shared_ptr SMTPConnection::readResponse() -{ - shared_ptr resp = SMTPResponse::readResponse - (m_tracer, m_socket, m_timeoutHandler, m_responseState); +shared_ptr SMTPConnection::readResponse() { + + shared_ptr resp = SMTPResponse::readResponse( + m_tracer, m_socket, m_timeoutHandler, m_responseState + ); m_responseState = resp->getCurrentState(); @@ -622,56 +651,56 @@ shared_ptr SMTPConnection::readResponse() } -bool SMTPConnection::isConnected() const -{ +bool SMTPConnection::isConnected() const { + return m_socket && m_socket->isConnected() && m_authenticated; } -bool SMTPConnection::isSecuredConnection() const -{ +bool SMTPConnection::isSecuredConnection() const { + return m_secured; } -shared_ptr SMTPConnection::getConnectionInfos() const -{ +shared_ptr SMTPConnection::getConnectionInfos() const { + return m_cntInfos; } -shared_ptr SMTPConnection::getTransport() -{ +shared_ptr SMTPConnection::getTransport() { + return m_transport.lock(); } -shared_ptr SMTPConnection::getSession() -{ +shared_ptr SMTPConnection::getSession() { + return m_transport.lock()->getSession(); } -shared_ptr SMTPConnection::getSocket() -{ +shared_ptr SMTPConnection::getSocket() { + return m_socket; } -shared_ptr SMTPConnection::getTracer() -{ +shared_ptr SMTPConnection::getTracer() { + return m_tracer; } -shared_ptr SMTPConnection::getTimeoutHandler() -{ +shared_ptr SMTPConnection::getTimeoutHandler() { + return m_timeoutHandler; } -shared_ptr SMTPConnection::getAuthenticator() -{ +shared_ptr SMTPConnection::getAuthenticator() { + return m_auth; } diff --git a/src/vmime/net/smtp/SMTPConnection.hpp b/src/vmime/net/smtp/SMTPConnection.hpp index 50f5daf2..d8a2375e 100644 --- a/src/vmime/net/smtp/SMTPConnection.hpp +++ b/src/vmime/net/smtp/SMTPConnection.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -61,12 +61,16 @@ class SMTPTransport; /** Manage connection to a SMTP server. */ -class VMIME_EXPORT SMTPConnection : public object -{ +class VMIME_EXPORT SMTPConnection : public object { + public: - SMTPConnection(const shared_ptr & transport, const shared_ptr & auth); - virtual ~SMTPConnection(); + SMTPConnection( + const shared_ptr & transport, + const shared_ptr & auth + ); + + ~SMTPConnection(); virtual void connect(); diff --git a/src/vmime/net/smtp/SMTPExceptions.cpp b/src/vmime/net/smtp/SMTPExceptions.cpp index 0c3112c0..641632c5 100644 --- a/src/vmime/net/smtp/SMTPExceptions.cpp +++ b/src/vmime/net/smtp/SMTPExceptions.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,52 +39,60 @@ namespace smtp { // SMTPCommandError // -SMTPCommandError::SMTPCommandError - (const string& command, const string& response, - const string& desc, const int statusCode, - const SMTPResponse::enhancedStatusCode& extendedStatusCode, - const exception& other) +SMTPCommandError::SMTPCommandError( + const string& command, + const string& response, + const string& desc, + const int statusCode, + const SMTPResponse::enhancedStatusCode& extendedStatusCode, + const exception& other +) : command_error(command, response, desc, other), - m_status(statusCode), m_exStatus(extendedStatusCode) -{ + m_status(statusCode), + m_exStatus(extendedStatusCode) { + } -SMTPCommandError::SMTPCommandError - (const string& command, const string& response, - const int statusCode, const SMTPResponse::enhancedStatusCode& extendedStatusCode, - const exception& other) +SMTPCommandError::SMTPCommandError( + const string& command, + const string& response, + const int statusCode, + const SMTPResponse::enhancedStatusCode& extendedStatusCode, + const exception& other +) : command_error(command, response, "", other), - m_status(statusCode), m_exStatus(extendedStatusCode) -{ + m_status(statusCode), + m_exStatus(extendedStatusCode) { + } -SMTPCommandError::~SMTPCommandError() throw() -{ +SMTPCommandError::~SMTPCommandError() throw() { + } -int SMTPCommandError::statusCode() const -{ +int SMTPCommandError::statusCode() const { + return m_status; } -const SMTPResponse::enhancedStatusCode SMTPCommandError::extendedStatusCode() const -{ +const SMTPResponse::enhancedStatusCode SMTPCommandError::extendedStatusCode() const { + return m_exStatus; } -exception* SMTPCommandError::clone() const -{ +exception* SMTPCommandError::clone() const { + return new SMTPCommandError(*this); } -const char* SMTPCommandError::name() const throw() -{ +const char* SMTPCommandError::name() const throw() { + return "SMTPCommandError"; } @@ -94,24 +102,24 @@ const char* SMTPCommandError::name() const throw() // SMTPMessageSizeExceedsMaxLimitsException::SMTPMessageSizeExceedsMaxLimitsException(const exception& other) - : net_exception("Message size exceeds maximum server limits (permanent error).", other) -{ + : net_exception("Message size exceeds maximum server limits (permanent error).", other) { + } -SMTPMessageSizeExceedsMaxLimitsException::~SMTPMessageSizeExceedsMaxLimitsException() throw() -{ +SMTPMessageSizeExceedsMaxLimitsException::~SMTPMessageSizeExceedsMaxLimitsException() throw() { + } -exception* SMTPMessageSizeExceedsMaxLimitsException::clone() const -{ +exception* SMTPMessageSizeExceedsMaxLimitsException::clone() const { + return new SMTPMessageSizeExceedsMaxLimitsException(*this); } -const char* SMTPMessageSizeExceedsMaxLimitsException::name() const throw() -{ +const char* SMTPMessageSizeExceedsMaxLimitsException::name() const throw() { + return "SMTPMessageSizeExceedsMaxLimitsException"; } @@ -121,24 +129,24 @@ const char* SMTPMessageSizeExceedsMaxLimitsException::name() const throw() // SMTPMessageSizeExceedsCurLimitsException::SMTPMessageSizeExceedsCurLimitsException(const exception& other) - : net_exception("Message size exceeds current server limits (temporary storage error).", other) -{ + : net_exception("Message size exceeds current server limits (temporary storage error).", other) { + } -SMTPMessageSizeExceedsCurLimitsException::~SMTPMessageSizeExceedsCurLimitsException() throw() -{ +SMTPMessageSizeExceedsCurLimitsException::~SMTPMessageSizeExceedsCurLimitsException() throw() { + } -exception* SMTPMessageSizeExceedsCurLimitsException::clone() const -{ +exception* SMTPMessageSizeExceedsCurLimitsException::clone() const { + return new SMTPMessageSizeExceedsCurLimitsException(*this); } -const char* SMTPMessageSizeExceedsCurLimitsException::name() const throw() -{ +const char* SMTPMessageSizeExceedsCurLimitsException::name() const throw() { + return "SMTPMessageSizeExceedsCurLimitsException"; } diff --git a/src/vmime/net/smtp/SMTPExceptions.hpp b/src/vmime/net/smtp/SMTPExceptions.hpp index 75842042..70f1e113 100644 --- a/src/vmime/net/smtp/SMTPExceptions.hpp +++ b/src/vmime/net/smtp/SMTPExceptions.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,19 +44,25 @@ namespace smtp { /** SMTP Command error: a SMTP command failed. */ +class VMIME_EXPORT SMTPCommandError : public exceptions::command_error { -class VMIME_EXPORT SMTPCommandError : public exceptions::command_error -{ public: - SMTPCommandError(const string& command, const string& response, - const string& desc, const int statusCode, + SMTPCommandError( + const string& command, + const string& response, + const string& desc, + const int statusCode, const SMTPResponse::enhancedStatusCode& extendedStatusCode, - const exception& other = NO_EXCEPTION); + const exception& other = NO_EXCEPTION + ); - SMTPCommandError(const string& command, const string& response, + SMTPCommandError( + const string& command, + const string& response, const int statusCode, const SMTPResponse::enhancedStatusCode& extendedStatusCode, - const exception& other = NO_EXCEPTION); + const exception& other = NO_EXCEPTION + ); ~SMTPCommandError() throw(); @@ -87,9 +93,8 @@ private: /** SMTP error: message size exceeds maximum server limits. * This is a permanent error. */ +class VMIME_EXPORT SMTPMessageSizeExceedsMaxLimitsException : public exceptions::net_exception { -class VMIME_EXPORT SMTPMessageSizeExceedsMaxLimitsException : public exceptions::net_exception -{ public: SMTPMessageSizeExceedsMaxLimitsException(const exception& other = NO_EXCEPTION); @@ -103,9 +108,8 @@ public: /** SMTP error: message size exceeds current server limits. * This is a temporary error (you may retry later). */ +class VMIME_EXPORT SMTPMessageSizeExceedsCurLimitsException : public exceptions::net_exception { -class VMIME_EXPORT SMTPMessageSizeExceedsCurLimitsException : public exceptions::net_exception -{ public: SMTPMessageSizeExceedsCurLimitsException(const exception& other = NO_EXCEPTION); diff --git a/src/vmime/net/smtp/SMTPResponse.cpp b/src/vmime/net/smtp/SMTPResponse.cpp index d1c25cf8..22347053 100644 --- a/src/vmime/net/smtp/SMTPResponse.cpp +++ b/src/vmime/net/smtp/SMTPResponse.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,50 +44,57 @@ namespace net { namespace smtp { -SMTPResponse::SMTPResponse - (const shared_ptr & tr, const shared_ptr & sok, - const shared_ptr & toh, const state& st) - : m_socket(sok), m_timeoutHandler(toh), m_tracer(tr), - m_responseBuffer(st.responseBuffer), m_responseContinues(false) -{ +SMTPResponse::SMTPResponse( + const shared_ptr & tr, + const shared_ptr & sok, + const shared_ptr & toh, + const state& st +) + : m_socket(sok), + m_timeoutHandler(toh), + m_tracer(tr), + m_responseBuffer(st.responseBuffer), + m_responseContinues(false) { + } SMTPResponse::SMTPResponse(const SMTPResponse&) - : vmime::object() -{ + : vmime::object() { + // Not used } -int SMTPResponse::getCode() const -{ +int SMTPResponse::getCode() const { + const int firstCode = m_lines[0].getCode(); - for (unsigned int i = 1 ; i < m_lines.size() ; ++i) - { + for (unsigned int i = 1 ; i < m_lines.size() ; ++i) { + // All response codes returned must be equal // or else this in an error... - if (m_lines[i].getCode() != firstCode) + if (m_lines[i].getCode() != firstCode) { return 0; + } } return firstCode; } -const SMTPResponse::enhancedStatusCode SMTPResponse::getEnhancedCode() const -{ +const SMTPResponse::enhancedStatusCode SMTPResponse::getEnhancedCode() const { + return m_lines[m_lines.size() - 1].getEnhancedCode(); } -const string SMTPResponse::getText() const -{ +const string SMTPResponse::getText() const { + string text = m_lines[0].getText(); - for (unsigned int i = 1 ; i < m_lines.size() ; ++i) - { + for (unsigned int i = 1 ; i < m_lines.size() ; ++i) { + text += '\n'; text += m_lines[i].getText(); } @@ -97,10 +104,13 @@ const string SMTPResponse::getText() const // static -shared_ptr SMTPResponse::readResponse - (const shared_ptr & tr, const shared_ptr & sok, - const shared_ptr & toh, const state& st) -{ +shared_ptr SMTPResponse::readResponse( + const shared_ptr & tr, + const shared_ptr & sok, + const shared_ptr & toh, + const state& st +) { + shared_ptr resp = shared_ptr (new SMTPResponse(tr, sok, toh, st)); @@ -110,54 +120,57 @@ shared_ptr SMTPResponse::readResponse } -void SMTPResponse::readResponse() -{ +void SMTPResponse::readResponse() { + responseLine line = getNextResponse(); m_lines.push_back(line); - while (m_responseContinues) - { + while (m_responseContinues) { line = getNextResponse(); m_lines.push_back(line); } } -const string SMTPResponse::readResponseLine() -{ +const string SMTPResponse::readResponseLine() { + string currentBuffer = m_responseBuffer; - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } + + while (true) { - while (true) - { // Get a line from the response buffer const size_t lineEnd = currentBuffer.find_first_of('\n'); - if (lineEnd != string::npos) - { + if (lineEnd != string::npos) { + size_t actualLineEnd = lineEnd; - if (actualLineEnd != 0 && currentBuffer[actualLineEnd - 1] == '\r') // CRLF case + if (actualLineEnd != 0 && currentBuffer[actualLineEnd - 1] == '\r') { // CRLF case actualLineEnd--; + } const string line(currentBuffer.begin(), currentBuffer.begin() + actualLineEnd); currentBuffer.erase(currentBuffer.begin(), currentBuffer.begin() + lineEnd + 1); m_responseBuffer = currentBuffer; - if (m_tracer) + if (m_tracer) { m_tracer->traceReceive(line); + } return line; } // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) + if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { throw exceptions::operation_timed_out(); + } m_timeoutHandler->resetTimeOut(); } @@ -166,8 +179,7 @@ const string SMTPResponse::readResponseLine() string receiveBuffer; m_socket->receive(receiveBuffer); - if (receiveBuffer.empty()) // buffer is empty - { + if (receiveBuffer.empty()) { // buffer is empty m_socket->waitForRead(); continue; } @@ -177,8 +189,8 @@ const string SMTPResponse::readResponseLine() } -const SMTPResponse::responseLine SMTPResponse::getNextResponse() -{ +const SMTPResponse::responseLine SMTPResponse::getNextResponse() { + string line = readResponseLine(); const int code = extractResponseCode(line); @@ -186,22 +198,23 @@ const SMTPResponse::responseLine SMTPResponse::getNextResponse() m_responseContinues = (line.length() >= 4 && line[3] == '-'); - if (line.length() > 4) + if (line.length() > 4) { text = utility::stringUtils::trim(line.substr(4)); - else + } else { text = ""; + } return responseLine(code, text, extractEnhancedCode(text)); } // static -int SMTPResponse::extractResponseCode(const string& response) -{ +int SMTPResponse::extractResponseCode(const string& response) { + int code = 0; - if (response.length() >= 3) - { + if (response.length() >= 3) { + code = (response[0] - '0') * 100 + (response[1] - '0') * 10 + (response[2] - '0'); @@ -212,23 +225,23 @@ int SMTPResponse::extractResponseCode(const string& response) // static -const SMTPResponse::enhancedStatusCode SMTPResponse::extractEnhancedCode(const string& responseText) -{ +const SMTPResponse::enhancedStatusCode SMTPResponse::extractEnhancedCode(const string& responseText) { + enhancedStatusCode enhCode; std::istringstream iss(responseText); iss.imbue(std::locale::classic()); - if (std::isdigit(iss.peek())) - { + if (std::isdigit(iss.peek())) { + iss >> enhCode.klass; - if (iss.get() == '.' && std::isdigit(iss.peek())) - { + if (iss.get() == '.' && std::isdigit(iss.peek())) { + iss >> enhCode.subject; - if (iss.get() == '.' && std::isdigit(iss.peek())) - { + if (iss.get() == '.' && std::isdigit(iss.peek())) { + iss >> enhCode.detail; return enhCode; } @@ -239,26 +252,26 @@ const SMTPResponse::enhancedStatusCode SMTPResponse::extractEnhancedCode(const s } -const SMTPResponse::responseLine SMTPResponse::getLineAt(const size_t pos) const -{ +const SMTPResponse::responseLine SMTPResponse::getLineAt(const size_t pos) const { + return m_lines[pos]; } -size_t SMTPResponse::getLineCount() const -{ +size_t SMTPResponse::getLineCount() const { + return m_lines.size(); } -const SMTPResponse::responseLine SMTPResponse::getLastLine() const -{ +const SMTPResponse::responseLine SMTPResponse::getLastLine() const { + return m_lines[m_lines.size() - 1]; } -const SMTPResponse::state SMTPResponse::getCurrentState() const -{ +const SMTPResponse::state SMTPResponse::getCurrentState() const { + state st; st.responseBuffer = m_responseBuffer; @@ -269,44 +282,50 @@ const SMTPResponse::state SMTPResponse::getCurrentState() const // SMTPResponse::responseLine -SMTPResponse::responseLine::responseLine(const int code, const string& text, const enhancedStatusCode& enhCode) - : m_code(code), m_text(text), m_enhCode(enhCode) -{ +SMTPResponse::responseLine::responseLine( + const int code, + const string& text, + const enhancedStatusCode& enhCode +) + : m_code(code), + m_text(text), + m_enhCode(enhCode) { + } -void SMTPResponse::responseLine::setCode(const int code) -{ +void SMTPResponse::responseLine::setCode(const int code) { + m_code = code; } -int SMTPResponse::responseLine::getCode() const -{ +int SMTPResponse::responseLine::getCode() const { + return m_code; } -void SMTPResponse::responseLine::setEnhancedCode(const enhancedStatusCode& enhCode) -{ +void SMTPResponse::responseLine::setEnhancedCode(const enhancedStatusCode& enhCode) { + m_enhCode = enhCode; } -const SMTPResponse::enhancedStatusCode SMTPResponse::responseLine::getEnhancedCode() const -{ +const SMTPResponse::enhancedStatusCode SMTPResponse::responseLine::getEnhancedCode() const { + return m_enhCode; } -void SMTPResponse::responseLine::setText(const string& text) -{ +void SMTPResponse::responseLine::setText(const string& text) { + m_text = text; } -const string SMTPResponse::responseLine::getText() const -{ +const string SMTPResponse::responseLine::getText() const { + return m_text; } @@ -316,19 +335,23 @@ const string SMTPResponse::responseLine::getText() const SMTPResponse::enhancedStatusCode::enhancedStatusCode() - : klass(0), subject(0), detail(0) -{ + : klass(0), + subject(0), + detail(0) { + } SMTPResponse::enhancedStatusCode::enhancedStatusCode(const enhancedStatusCode& enhCode) - : klass(enhCode.klass), subject(enhCode.subject), detail(enhCode.detail) -{ + : klass(enhCode.klass), + subject(enhCode.subject), + detail(enhCode.detail) { + } -std::ostream& operator<<(std::ostream& os, const SMTPResponse::enhancedStatusCode& code) -{ +std::ostream& operator<<(std::ostream& os, const SMTPResponse::enhancedStatusCode& code) { + os << code.klass << '.' << code.subject << '.' << code.detail; return os; } diff --git a/src/vmime/net/smtp/SMTPResponse.hpp b/src/vmime/net/smtp/SMTPResponse.hpp index fa19a1db..2eec7f4d 100644 --- a/src/vmime/net/smtp/SMTPResponse.hpp +++ b/src/vmime/net/smtp/SMTPResponse.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -49,19 +49,19 @@ namespace smtp { /** A SMTP response, as sent by the server. */ -class VMIME_EXPORT SMTPResponse : public object -{ +class VMIME_EXPORT SMTPResponse : public object { + public: /** Current state of response parser. */ - struct state - { + struct state { + string responseBuffer; }; /** Enhanced status code (as per RFC-3463). */ - struct enhancedStatusCode - { + struct enhancedStatusCode { + enhancedStatusCode(); enhancedStatusCode(const enhancedStatusCode& enhCode); @@ -71,8 +71,8 @@ public: }; /** An element of a SMTP response. */ - class responseLine - { + class responseLine { + public: responseLine(const int code, const string& text, const enhancedStatusCode& enhCode); @@ -104,9 +104,12 @@ public: * @throws exceptions::operation_timed_out if no data * has been received within the granted time */ - static shared_ptr readResponse - (const shared_ptr & tr, const shared_ptr & sok, - const shared_ptr & toh, const state& st); + static shared_ptr readResponse( + const shared_ptr & tr, + const shared_ptr & sok, + const shared_ptr & toh, + const state& st + ); /** Return the SMTP response code. * @@ -154,7 +157,13 @@ public: private: - SMTPResponse(const shared_ptr & tr, const shared_ptr & sok, const shared_ptr & toh, const state& st); + SMTPResponse( + const shared_ptr & tr, + const shared_ptr & sok, + const shared_ptr & toh, + const state& st + ); + SMTPResponse(const SMTPResponse&); void readResponse(); diff --git a/src/vmime/net/smtp/SMTPSTransport.cpp b/src/vmime/net/smtp/SMTPSTransport.cpp index 1a8a0804..5158aa98 100644 --- a/src/vmime/net/smtp/SMTPSTransport.cpp +++ b/src/vmime/net/smtp/SMTPSTransport.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,19 +35,22 @@ namespace net { namespace smtp { -SMTPSTransport::SMTPSTransport(const shared_ptr & sess, const shared_ptr & auth) - : SMTPTransport(sess, auth, true) -{ +SMTPSTransport::SMTPSTransport( + const shared_ptr & sess, + const shared_ptr & auth +) + : SMTPTransport(sess, auth, true) { + } -SMTPSTransport::~SMTPSTransport() -{ +SMTPSTransport::~SMTPSTransport() { + } -const string SMTPSTransport::getProtocolName() const -{ +const string SMTPSTransport::getProtocolName() const { + return "smtps"; } @@ -58,14 +61,14 @@ const string SMTPSTransport::getProtocolName() const SMTPServiceInfos SMTPSTransport::sm_infos(true); -const serviceInfos& SMTPSTransport::getInfosInstance() -{ +const serviceInfos& SMTPSTransport::getInfosInstance() { + return sm_infos; } -const serviceInfos& SMTPSTransport::getInfos() const -{ +const serviceInfos& SMTPSTransport::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/smtp/SMTPSTransport.hpp b/src/vmime/net/smtp/SMTPSTransport.hpp index 52dce1f2..f19b3c55 100644 --- a/src/vmime/net/smtp/SMTPSTransport.hpp +++ b/src/vmime/net/smtp/SMTPSTransport.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,12 +41,15 @@ namespace smtp { /** SMTPS transport service. */ +class VMIME_EXPORT SMTPSTransport : public SMTPTransport { -class VMIME_EXPORT SMTPSTransport : public SMTPTransport -{ public: - SMTPSTransport(const shared_ptr & sess, const shared_ptr & auth); + SMTPSTransport( + const shared_ptr & sess, + const shared_ptr & auth + ); + ~SMTPSTransport(); const string getProtocolName() const; diff --git a/src/vmime/net/smtp/SMTPServiceInfos.cpp b/src/vmime/net/smtp/SMTPServiceInfos.cpp index 532bb8b8..a2ee3d57 100644 --- a/src/vmime/net/smtp/SMTPServiceInfos.cpp +++ b/src/vmime/net/smtp/SMTPServiceInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,24 +36,24 @@ namespace smtp { SMTPServiceInfos::SMTPServiceInfos(const bool smtps) - : m_smtps(smtps) -{ + : m_smtps(smtps) { + } -const string SMTPServiceInfos::getPropertyPrefix() const -{ - if (m_smtps) +const string SMTPServiceInfos::getPropertyPrefix() const { + + if (m_smtps) { return "transport.smtps."; - else + } else { return "transport.smtp."; + } } -const SMTPServiceInfos::props& SMTPServiceInfos::getProperties() const -{ - static props smtpProps = - { +const SMTPServiceInfos::props& SMTPServiceInfos::getProperties() const { + + static props smtpProps = { // SMTP-specific options property("options.need-authentication", serviceInfos::property::TYPE_BOOLEAN, "false"), #if VMIME_HAVE_SASL_SUPPORT @@ -77,8 +77,7 @@ const SMTPServiceInfos::props& SMTPServiceInfos::getProperties() const property(serviceInfos::property::SERVER_PORT, "25"), }; - static props smtpsProps = - { + static props smtpsProps = { // SMTP-specific options property("options.need-authentication", serviceInfos::property::TYPE_BOOLEAN, "false"), #if VMIME_HAVE_SASL_SUPPORT @@ -106,8 +105,8 @@ const SMTPServiceInfos::props& SMTPServiceInfos::getProperties() const } -const std::vector SMTPServiceInfos::getAvailableProperties() const -{ +const std::vector SMTPServiceInfos::getAvailableProperties() const { + std::vector list; const props& p = getProperties(); @@ -123,8 +122,7 @@ const std::vector SMTPServiceInfos::getAvailablePropert list.push_back(p.PROPERTY_AUTH_PASSWORD); #if VMIME_HAVE_TLS_SUPPORT - if (!m_smtps) - { + if (!m_smtps) { list.push_back(p.PROPERTY_CONNECTION_TLS); list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED); } diff --git a/src/vmime/net/smtp/SMTPServiceInfos.hpp b/src/vmime/net/smtp/SMTPServiceInfos.hpp index f783194d..005a0a21 100644 --- a/src/vmime/net/smtp/SMTPServiceInfos.hpp +++ b/src/vmime/net/smtp/SMTPServiceInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,15 +41,13 @@ namespace smtp { /** Information about SMTP service. */ +class VMIME_EXPORT SMTPServiceInfos : public serviceInfos { -class VMIME_EXPORT SMTPServiceInfos : public serviceInfos -{ public: SMTPServiceInfos(const bool smtps); - struct props - { + struct props { // SMTP-specific options serviceInfos::property PROPERTY_OPTIONS_NEEDAUTH; #if VMIME_HAVE_SASL_SUPPORT diff --git a/src/vmime/net/smtp/SMTPTransport.cpp b/src/vmime/net/smtp/SMTPTransport.cpp index 27afcf6f..72cba7c7 100644 --- a/src/vmime/net/smtp/SMTPTransport.cpp +++ b/src/vmime/net/smtp/SMTPTransport.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -51,116 +51,126 @@ namespace net { namespace smtp { -SMTPTransport::SMTPTransport(const shared_ptr & sess, const shared_ptr & auth, const bool secured) - : transport(sess, getInfosInstance(), auth), m_isSMTPS(secured), m_needReset(false) -{ +SMTPTransport::SMTPTransport( + const shared_ptr & sess, + const shared_ptr & auth, + const bool secured +) + : transport(sess, getInfosInstance(), auth), + m_isSMTPS(secured), + m_needReset(false) { + } -SMTPTransport::~SMTPTransport() -{ - try - { - if (isConnected()) +SMTPTransport::~SMTPTransport() { + + try { + + if (isConnected()) { disconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -const string SMTPTransport::getProtocolName() const -{ +const string SMTPTransport::getProtocolName() const { + return "smtp"; } -bool SMTPTransport::isSMTPS() const -{ +bool SMTPTransport::isSMTPS() const { + return m_isSMTPS; } -void SMTPTransport::connect() -{ - if (isConnected()) - throw exceptions::already_connected(); +void SMTPTransport::connect() { - m_connection = make_shared - (dynamicCast (shared_from_this()), getAuthenticator()); + if (isConnected()) { + throw exceptions::already_connected(); + } + + m_connection = make_shared ( + dynamicCast (shared_from_this()), getAuthenticator() + ); m_connection->connect(); } -bool SMTPTransport::isConnected() const -{ +bool SMTPTransport::isConnected() const { + return m_connection && m_connection->isConnected(); } -bool SMTPTransport::isSecuredConnection() const -{ - if (m_connection == NULL) +bool SMTPTransport::isSecuredConnection() const { + + if (!m_connection) { return false; + } return m_connection->isSecuredConnection(); } -shared_ptr SMTPTransport::getConnectionInfos() const -{ - if (m_connection == NULL) +shared_ptr SMTPTransport::getConnectionInfos() const { + + if (!m_connection) { return null; + } return m_connection->getConnectionInfos(); } -shared_ptr SMTPTransport::getConnection() -{ +shared_ptr SMTPTransport::getConnection() { + return m_connection; } -void SMTPTransport::disconnect() -{ - if (!isConnected()) +void SMTPTransport::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } m_connection->disconnect(); m_connection = null; } -void SMTPTransport::noop() -{ - if (!isConnected()) +void SMTPTransport::noop() { + + if (!isConnected()) { throw exceptions::not_connected(); + } m_connection->sendRequest(SMTPCommand::NOOP()); shared_ptr resp = m_connection->readResponse(); - if (resp->getCode() != 250) - { - throw SMTPCommandError - ("NOOP", resp->getText(), resp->getCode(), resp->getEnhancedCode()); + if (resp->getCode() != 250) { + throw SMTPCommandError("NOOP", resp->getText(), resp->getCode(), resp->getEnhancedCode()); } } // static -bool SMTPTransport::mailboxNeedsUTF8(const mailbox& mb) -{ +bool SMTPTransport::mailboxNeedsUTF8(const mailbox& mb) { + bool all7bit = utility::stringUtils::is7bit(mb.getEmail().getLocalName().getBuffer()) && utility::stringUtils::is7bit(mb.getEmail().getDomainName().getBuffer()); - for (size_t i = 0, n = mb.getName().getWordCount() ; all7bit && i != n ; ++i) - { + for (size_t i = 0, n = mb.getName().getWordCount() ; all7bit && i != n ; ++i) { all7bit = utility::stringUtils::is7bit(mb.getName().getWordAt(i)->getBuffer()); } @@ -168,16 +178,19 @@ bool SMTPTransport::mailboxNeedsUTF8(const mailbox& mb) } -void SMTPTransport::sendEnvelope - (const mailbox& expeditor, const mailboxList& recipients, - const mailbox& sender, bool sendDATACommand, - const size_t size) -{ +void SMTPTransport::sendEnvelope( + const mailbox& expeditor, + const mailboxList& recipients, + const mailbox& sender, + bool sendDATACommand, + const size_t size +) { // If no recipient/expeditor was found, throw an exception - if (recipients.isEmpty()) + if (recipients.isEmpty()) { throw exceptions::no_recipient(); - else if (expeditor.isEmpty()) + } else if (expeditor.isEmpty()) { throw exceptions::no_expeditor(); + } const bool needReset = m_needReset; @@ -189,20 +202,22 @@ void SMTPTransport::sendEnvelope shared_ptr commands = SMTPCommandSet::create(hasPipelining); // Emit a "RSET" command if we previously sent a message on this connection - if (needReset) + if (needReset) { commands->addCommand(SMTPCommand::RSET()); + } // Check whether we need SMTPUTF8 const bool hasSMTPUTF8 = m_connection->hasExtension("SMTPUTF8"); bool needSMTPUTF8 = false; - if (!sender.isEmpty()) + if (!sender.isEmpty()) { needSMTPUTF8 = needSMTPUTF8 || mailboxNeedsUTF8(sender); - else + } else { needSMTPUTF8 = needSMTPUTF8 || mailboxNeedsUTF8(expeditor); + } + + for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) { - for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) - { const mailbox& mbox = *recipients.getMailboxAt(i); needSMTPUTF8 = needSMTPUTF8 || mailboxNeedsUTF8(mbox); } @@ -210,16 +225,16 @@ void SMTPTransport::sendEnvelope // Emit the "MAIL" command const bool hasSize = m_connection->hasExtension("SIZE"); - if (!sender.isEmpty()) - { + if (!sender.isEmpty()) { + commands->addCommand( SMTPCommand::MAIL( sender, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0 ) ); - } - else - { + + } else { + commands->addCommand( SMTPCommand::MAIL( expeditor, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0 @@ -231,119 +246,141 @@ void SMTPTransport::sendEnvelope m_needReset = true; // Emit a "RCPT TO" command for each recipient - for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) - { + for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) { + const mailbox& mbox = *recipients.getMailboxAt(i); commands->addCommand(SMTPCommand::RCPT(mbox, hasSMTPUTF8 && needSMTPUTF8)); } // Prepare sending of message data - if (sendDATACommand) + if (sendDATACommand) { commands->addCommand(SMTPCommand::DATA()); + } // Read response for "RSET" command - if (needReset) - { + if (needReset) { + commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer()); resp = m_connection->readResponse(); if (resp->getCode() != 250 && - resp->getCode() != 200) // RFC-876: << In reply to a RSET and/or a NOOP command, - // some servers reply "200" >> - { + resp->getCode() != 200) { // RFC-876: << In reply to a RSET and/or a NOOP command, + // some servers reply "200" >> + disconnect(); - throw SMTPCommandError - (commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode()); + throw SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ); } } // Read response for "MAIL" command commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer()); - if ((resp = m_connection->readResponse())->getCode() != 250) - { + if ((resp = m_connection->readResponse())->getCode() != 250) { + // SIZE extension: insufficient system storage - if (resp->getCode() == 452) - { - throw SMTPMessageSizeExceedsCurLimitsException - (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode())); - } + if (resp->getCode() == 452) { + + throw SMTPMessageSizeExceedsCurLimitsException( + SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ) + ); + // SIZE extension: message size exceeds fixed maximum message size - else if (resp->getCode() == 552) - { - throw SMTPMessageSizeExceedsMaxLimitsException - (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode())); - } + } else if (resp->getCode() == 552) { + + throw SMTPMessageSizeExceedsMaxLimitsException( + SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ) + ); + // Other error - else - { - throw SMTPCommandError - (commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode()); + } else { + + throw SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ); } } // Read responses for "RCPT TO" commands - for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) - { + for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) { + commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer()); resp = m_connection->readResponse(); if (resp->getCode() != 250 && - resp->getCode() != 251) - { + resp->getCode() != 251) { + // SIZE extension: insufficient system storage - if (resp->getCode() == 452) - { - throw SMTPMessageSizeExceedsCurLimitsException - (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode())); - } + if (resp->getCode() == 452) { + + throw SMTPMessageSizeExceedsCurLimitsException( + SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ) + ); + // SIZE extension: message size exceeds fixed maximum message size - else if (resp->getCode() == 552) - { - throw SMTPMessageSizeExceedsMaxLimitsException - (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode())); - } + } else if (resp->getCode() == 552) { + + throw SMTPMessageSizeExceedsMaxLimitsException( + SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ) + ); + // Other error - else - { - throw SMTPCommandError - (commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode()); + } else { + + throw SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ); } } } // Read response for "DATA" command - if (sendDATACommand) - { + if (sendDATACommand) { + commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer()); - if ((resp = m_connection->readResponse())->getCode() != 354) - { - throw SMTPCommandError - (commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode()); + if ((resp = m_connection->readResponse())->getCode() != 354) { + + throw SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ); } } } -void SMTPTransport::send - (const mailbox& expeditor, const mailboxList& recipients, - utility::inputStream& is, const size_t size, - utility::progressListener* progress, const mailbox& sender) -{ - if (!isConnected()) +void SMTPTransport::send( + const mailbox& expeditor, + const mailboxList& recipients, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress, + const mailbox& sender +) { + + if (!isConnected()) { throw exceptions::not_connected(); + } // Send message envelope sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ true, size); @@ -360,28 +397,30 @@ void SMTPTransport::send // Send end-of-data delimiter m_connection->getSocket()->send("\r\n.\r\n"); - if (m_connection->getTracer()) - { + if (m_connection->getTracer()) { m_connection->getTracer()->traceSendBytes(size); m_connection->getTracer()->traceSend("."); } shared_ptr resp; - if ((resp = m_connection->readResponse())->getCode() != 250) - { - throw SMTPCommandError - ("DATA", resp->getText(), resp->getCode(), resp->getEnhancedCode()); + if ((resp = m_connection->readResponse())->getCode() != 250) { + throw SMTPCommandError("DATA", resp->getText(), resp->getCode(), resp->getEnhancedCode()); } } -void SMTPTransport::send - (const shared_ptr & msg, const mailbox& expeditor, const mailboxList& recipients, - utility::progressListener* progress, const mailbox& sender) -{ - if (!isConnected()) +void SMTPTransport::send( + const shared_ptr & msg, + const mailbox& expeditor, + const mailboxList& recipients, + utility::progressListener* progress, + const mailbox& sender +) { + + if (!isConnected()) { throw exceptions::not_connected(); + } // Generate the message with Internationalized Email support, // if this is supported by the SMTP server @@ -392,9 +431,8 @@ void SMTPTransport::send // buffer then use the send() method which takes an inputStream if (!m_connection->hasExtension("CHUNKING") || !getInfos().getPropertyValue (getSession(), - dynamic_cast (getInfos()).getProperties().PROPERTY_OPTIONS_CHUNKING)) + dynamic_cast (getInfos()).getProperties().PROPERTY_OPTIONS_CHUNKING)) { - { std::ostringstream oss; utility::outputStreamAdapter ossAdapter(oss); @@ -411,8 +449,7 @@ void SMTPTransport::send // Send message envelope const size_t msgSize = msg->getGeneratedSize(ctx); - sendEnvelope(expeditor, recipients, sender, - /* sendDATACommand */ false, msgSize); + sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ false, msgSize); // Send the message by chunks SMTPChunkingOutputStreamAdapter chunkStream(m_connection, msgSize, progress); @@ -429,14 +466,14 @@ void SMTPTransport::send SMTPServiceInfos SMTPTransport::sm_infos(false); -const serviceInfos& SMTPTransport::getInfosInstance() -{ +const serviceInfos& SMTPTransport::getInfosInstance() { + return sm_infos; } -const serviceInfos& SMTPTransport::getInfos() const -{ +const serviceInfos& SMTPTransport::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/smtp/SMTPTransport.hpp b/src/vmime/net/smtp/SMTPTransport.hpp index a5f15ca6..67c63a55 100644 --- a/src/vmime/net/smtp/SMTPTransport.hpp +++ b/src/vmime/net/smtp/SMTPTransport.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -49,12 +49,16 @@ class SMTPCommand; /** SMTP transport service. */ +class VMIME_EXPORT SMTPTransport : public transport { -class VMIME_EXPORT SMTPTransport : public transport -{ public: - SMTPTransport(const shared_ptr & sess, const shared_ptr & auth, const bool secured = false); + SMTPTransport( + const shared_ptr & sess, + const shared_ptr & auth, + const bool secured = false + ); + ~SMTPTransport(); const string getProtocolName() const; @@ -68,20 +72,22 @@ public: void noop(); - void send - (const mailbox& expeditor, - const mailboxList& recipients, - utility::inputStream& is, - const size_t size, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()); + void send( + const mailbox& expeditor, + const mailboxList& recipients, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox() + ); - void send - (const shared_ptr & msg, - const mailbox& expeditor, - const mailboxList& recipients, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()); + void send( + const shared_ptr & msg, + const mailbox& expeditor, + const mailboxList& recipients, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox() + ); bool isSecuredConnection() const; shared_ptr getConnectionInfos() const; @@ -103,12 +109,13 @@ private: * @param sendDATACommand if true, the DATA command will be sent * @param size message size, in bytes (or 0, if not known) */ - void sendEnvelope - (const mailbox& expeditor, - const mailboxList& recipients, - const mailbox& sender, - bool sendDATACommand, - const size_t size); + void sendEnvelope( + const mailbox& expeditor, + const mailboxList& recipients, + const mailbox& sender, + bool sendDATACommand, + const size_t size + ); shared_ptr m_connection; diff --git a/src/vmime/net/smtp/smtp.hpp b/src/vmime/net/smtp/smtp.hpp index 2a9ee312..4c0b17d7 100644 --- a/src/vmime/net/smtp/smtp.hpp +++ b/src/vmime/net/smtp/smtp.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 diff --git a/src/vmime/net/socket.hpp b/src/vmime/net/socket.hpp index 4de45ca9..a236a9f3 100644 --- a/src/vmime/net/socket.hpp +++ b/src/vmime/net/socket.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,13 +43,11 @@ namespace net { /** Interface for connecting to servers. */ +class VMIME_EXPORT socket : public object { -class VMIME_EXPORT socket : public object -{ public: - enum Status - { + enum Status { STATUS_WOULDBLOCK = 0xf, /**< The operation would block. Retry later. */ STATUS_WANT_READ = 0x1, /**< The socket wants to read data, retry when data is available. */ STATUS_WANT_WRITE = 0x2 /**< The socket wants to write data, retry when data can be written. */ @@ -195,9 +193,8 @@ private: /** A class to create 'socket' objects. */ +class socketFactory : public object { -class socketFactory : public object -{ public: virtual ~socketFactory() { } diff --git a/src/vmime/net/store.hpp b/src/vmime/net/store.hpp index dfeb9a53..49b8ca3b 100644 --- a/src/vmime/net/store.hpp +++ b/src/vmime/net/store.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,13 +42,18 @@ namespace net { /** A store service. * Encapsulate protocols that provide access to user's mail drop. */ +class VMIME_EXPORT store : public service { -class VMIME_EXPORT store : public service -{ protected: - store(const shared_ptr & sess, const serviceInfos& infos, const shared_ptr & auth) - : service(sess, infos, auth) { } + store( + const shared_ptr & sess, + const serviceInfos& infos, + const shared_ptr & auth + ) + : service(sess, infos, auth) { + + } public: @@ -81,8 +86,7 @@ public: virtual bool isValidFolderName(const folder::path::component& name) const = 0; /** Store capabilities. */ - enum Capabilities - { + enum Capabilities { CAPABILITY_CREATE_FOLDER = (1 << 0), /**< Can create folders. */ CAPABILITY_RENAME_FOLDER = (1 << 1), /**< Can rename folders. */ CAPABILITY_ADD_MESSAGE = (1 << 2), /**< Can append message to folders. */ @@ -101,7 +105,10 @@ public: virtual int getCapabilities() const = 0; - Type getType() const { return (TYPE_STORE); } + Type getType() const { + + return TYPE_STORE; + } }; diff --git a/src/vmime/net/timeoutHandler.hpp b/src/vmime/net/timeoutHandler.hpp index 397cc796..fed1bc48 100644 --- a/src/vmime/net/timeoutHandler.hpp +++ b/src/vmime/net/timeoutHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,9 +42,8 @@ namespace net { * to stop operations that takes too much time to complete (ie. no data * received from the server for a long time if the network link is down). */ +class VMIME_EXPORT timeoutHandler : public object { -class VMIME_EXPORT timeoutHandler : public object -{ public: virtual ~timeoutHandler() { } @@ -71,9 +70,8 @@ public: /** A class to create 'timeoutHandler' objects. */ +class timeoutHandlerFactory : public object { -class timeoutHandlerFactory : public object -{ public: virtual ~timeoutHandlerFactory() { } diff --git a/src/vmime/net/tls/TLSProperties.cpp b/src/vmime/net/tls/TLSProperties.cpp index 1986db79..f7721d40 100644 --- a/src/vmime/net/tls/TLSProperties.cpp +++ b/src/vmime/net/tls/TLSProperties.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 diff --git a/src/vmime/net/tls/TLSProperties.hpp b/src/vmime/net/tls/TLSProperties.hpp index 0dbc8f05..94341cae 100644 --- a/src/vmime/net/tls/TLSProperties.hpp +++ b/src/vmime/net/tls/TLSProperties.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,8 +41,8 @@ namespace tls { /** Holds options for a TLS session. */ -class VMIME_EXPORT TLSProperties : public object -{ +class VMIME_EXPORT TLSProperties : public object { + public: TLSProperties(); @@ -50,8 +50,8 @@ public: /** Predefined generic cipher suites (work with all TLS libraries). */ - enum GenericCipherSuite - { + enum GenericCipherSuite { + CIPHERSUITE_HIGH, /**< High encryption cipher suites (> 128 bits). */ CIPHERSUITE_MEDIUM, /**< Medium encryption cipher suites (>= 128 bits). */ CIPHERSUITE_LOW, /**< Low encryption cipher suites (>= 64 bits). */ diff --git a/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp b/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp index 45b9527e..055dfea0 100644 --- a/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp +++ b/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,29 +36,34 @@ namespace net { namespace tls { -TLSSecuredConnectionInfos::TLSSecuredConnectionInfos - (const string& host, const port_t port, - const shared_ptr & tlsSession, const shared_ptr & tlsSocket) - : m_host(host), m_port(port), - m_tlsSession(tlsSession), m_tlsSocket(tlsSocket) -{ +TLSSecuredConnectionInfos::TLSSecuredConnectionInfos( + const string& host, + const port_t port, + const shared_ptr & tlsSession, + const shared_ptr & tlsSocket +) + : m_host(host), + m_port(port), + m_tlsSession(tlsSession), + m_tlsSocket(tlsSocket) { + } -const string TLSSecuredConnectionInfos::getHost() const -{ +const string TLSSecuredConnectionInfos::getHost() const { + return m_host; } -port_t TLSSecuredConnectionInfos::getPort() const -{ +port_t TLSSecuredConnectionInfos::getPort() const { + return m_port; } -shared_ptr TLSSecuredConnectionInfos::getPeerCertificates() const -{ +shared_ptr TLSSecuredConnectionInfos::getPeerCertificates() const { + return m_tlsSocket->getPeerCertificates(); } diff --git a/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp b/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp index 19e7a064..c65e9d26 100644 --- a/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp +++ b/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -47,12 +47,16 @@ class TLSSocket; /** Information about a TLS-secured connection used by a service. */ -class VMIME_EXPORT TLSSecuredConnectionInfos : public securedConnectionInfos -{ +class VMIME_EXPORT TLSSecuredConnectionInfos : public securedConnectionInfos { + public: - TLSSecuredConnectionInfos(const string& host, const port_t port, - const shared_ptr & tlsSession, const shared_ptr & tlsSocket); + TLSSecuredConnectionInfos( + const string& host, + const port_t port, + const shared_ptr & tlsSession, + const shared_ptr & tlsSocket + ); const string getHost() const; port_t getPort() const; diff --git a/src/vmime/net/tls/TLSSession.cpp b/src/vmime/net/tls/TLSSession.cpp index a46f07ca..ab8b7c3a 100644 --- a/src/vmime/net/tls/TLSSession.cpp +++ b/src/vmime/net/tls/TLSSession.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,8 +35,8 @@ namespace net { namespace tls { -TLSSession::TLSSession() -{ +TLSSession::TLSSession() { + } diff --git a/src/vmime/net/tls/TLSSession.hpp b/src/vmime/net/tls/TLSSession.hpp index 83a1623c..9e84fe76 100644 --- a/src/vmime/net/tls/TLSSession.hpp +++ b/src/vmime/net/tls/TLSSession.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,8 +46,8 @@ namespace tls { /** Describe a TLS connection between a client and a server. */ -class VMIME_EXPORT TLSSession : public object, public enable_shared_from_this -{ +class VMIME_EXPORT TLSSession : public object, public enable_shared_from_this { + public: /** Create and initialize a new TLS session. @@ -57,7 +57,10 @@ public: * @param props TLS properties for this session * @return a new TLS session */ - static shared_ptr create(const shared_ptr & cv, const shared_ptr & props); + static shared_ptr create( + const shared_ptr & cv, + const shared_ptr & props + ); /** Create a new socket that adds a TLS security layer around * an existing socket. You should create only one socket diff --git a/src/vmime/net/tls/TLSSocket.cpp b/src/vmime/net/tls/TLSSocket.cpp index 0419a571..fbca0820 100644 --- a/src/vmime/net/tls/TLSSocket.cpp +++ b/src/vmime/net/tls/TLSSocket.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 diff --git a/src/vmime/net/tls/TLSSocket.hpp b/src/vmime/net/tls/TLSSocket.hpp index 75b80116..ca50aa8e 100644 --- a/src/vmime/net/tls/TLSSocket.hpp +++ b/src/vmime/net/tls/TLSSocket.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -49,8 +49,8 @@ class TLSSession; /** Add a TLS security layer to an existing socket. */ -class VMIME_EXPORT TLSSocket : public socket -{ +class VMIME_EXPORT TLSSocket : public socket { + public: /** Create a new socket object that adds a security layer diff --git a/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp b/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp index 36ab7d7a..b2996fb3 100644 --- a/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp +++ b/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,63 +42,63 @@ namespace tls { TLSProperties::TLSProperties() - : m_data(make_shared ()) -{ + : m_data(make_shared ()) { + setCipherSuite(CIPHERSUITE_DEFAULT); } TLSProperties::TLSProperties(const TLSProperties& props) : object(), - m_data(make_shared ()) -{ + m_data(make_shared ()) { + *dynamicCast (m_data) = *dynamicCast (props.m_data); } -void TLSProperties::setCipherSuite(const GenericCipherSuite cipherSuite) -{ - switch (cipherSuite) - { - case CIPHERSUITE_HIGH: +void TLSProperties::setCipherSuite(const GenericCipherSuite cipherSuite) { - setCipherSuite("SECURE256:%SSL3_RECORD_VERSION"); - break; + switch (cipherSuite) { - case CIPHERSUITE_MEDIUM: + case CIPHERSUITE_HIGH: - setCipherSuite("SECURE128:%SSL3_RECORD_VERSION"); - break; + setCipherSuite("SECURE256:%SSL3_RECORD_VERSION"); + break; - case CIPHERSUITE_LOW: + case CIPHERSUITE_MEDIUM: - setCipherSuite("NORMAL:%SSL3_RECORD_VERSION"); - break; + setCipherSuite("SECURE128:%SSL3_RECORD_VERSION"); + break; - default: - case CIPHERSUITE_DEFAULT: + case CIPHERSUITE_LOW: - setCipherSuite("NORMAL:%SSL3_RECORD_VERSION"); - break; + setCipherSuite("NORMAL:%SSL3_RECORD_VERSION"); + break; + + default: + case CIPHERSUITE_DEFAULT: + + setCipherSuite("NORMAL:%SSL3_RECORD_VERSION"); + break; } } -void TLSProperties::setCipherSuite(const string& cipherSuite) -{ +void TLSProperties::setCipherSuite(const string& cipherSuite) { + dynamicCast (m_data)->cipherSuite = cipherSuite; } -const string TLSProperties::getCipherSuite() const -{ +const string TLSProperties::getCipherSuite() const { + return dynamicCast (m_data)->cipherSuite; } -TLSProperties_GnuTLS& TLSProperties_GnuTLS::operator=(const TLSProperties_GnuTLS& other) -{ +TLSProperties_GnuTLS& TLSProperties_GnuTLS::operator=(const TLSProperties_GnuTLS& other) { + cipherSuite = other.cipherSuite; return *this; diff --git a/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp b/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp index 2038778a..96bbaead 100644 --- a/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp +++ b/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,8 +44,8 @@ namespace net { namespace tls { -class TLSProperties_GnuTLS : public object -{ +class TLSProperties_GnuTLS : public object { + public: TLSProperties_GnuTLS& operator=(const TLSProperties_GnuTLS& other); diff --git a/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp b/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp index dccfb5ec..8586537e 100644 --- a/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp +++ b/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -82,10 +82,10 @@ namespace tls { #ifndef VMIME_BUILDING_DOC // Initialize GNU TLS library -struct TLSGlobal -{ - TLSGlobal() - { +struct TLSGlobal { + + TLSGlobal() { + #if VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL) #if VMIME_GNUTLS_NEEDS_GCRYPT gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); @@ -104,8 +104,8 @@ struct TLSGlobal gnutls_certificate_allocate_credentials(&certCred); } - ~TLSGlobal() - { + ~TLSGlobal() { + gnutls_anon_free_client_credentials(anonCred); gnutls_certificate_free_credentials(certCred); @@ -114,8 +114,8 @@ struct TLSGlobal #if VMIME_DEBUG && GNUTLS_DEBUG - static void TLSLogFunc(int level, const char *str) - { + static void TLSLogFunc(int level, const char *str) { + std::cerr << "GNUTLS: [" << level << "] " << str << std::endl; } @@ -134,21 +134,29 @@ static TLSGlobal g_gnutlsGlobal; // static -shared_ptr TLSSession::create(const shared_ptr & cv, const shared_ptr & props) -{ +shared_ptr TLSSession::create( + const shared_ptr & cv, + const shared_ptr & props +) { + return make_shared (cv, props); } -TLSSession_GnuTLS::TLSSession_GnuTLS(const shared_ptr & cv, const shared_ptr & props) - : m_certVerifier(cv), m_props(props) -{ +TLSSession_GnuTLS::TLSSession_GnuTLS( + const shared_ptr & cv, + const shared_ptr & props +) + : m_certVerifier(cv), + m_props(props) { + int res; m_gnutlsSession = new gnutls_session_t; - if (gnutls_init(m_gnutlsSession, GNUTLS_CLIENT) != 0) + if (gnutls_init(m_gnutlsSession, GNUTLS_CLIENT) != 0) { throw std::bad_alloc(); + } // Sets some default priority on the ciphers, key exchange methods, // macs and compression methods. @@ -156,8 +164,8 @@ TLSSession_GnuTLS::TLSSession_GnuTLS(const shared_ptr getCipherSuite().c_str(), NULL)) != 0) - { + (*m_gnutlsSession, m_props->getCipherSuite().c_str(), NULL)) != 0) { + throwTLSException("gnutls_priority_set_direct", res); } @@ -170,13 +178,10 @@ TLSSession_GnuTLS::TLSSession_GnuTLS(const shared_ptr TLSSession_GnuTLS::getSocket(const shared_ptr & sok) -{ +shared_ptr TLSSession_GnuTLS::getSocket(const shared_ptr & sok) { + return TLSSocket::wrap(dynamicCast (shared_from_this()), sok); } -shared_ptr TLSSession_GnuTLS::getCertificateVerifier() -{ +shared_ptr TLSSession_GnuTLS::getCertificateVerifier() { + return m_certVerifier; } -void TLSSession_GnuTLS::throwTLSException(const string& fname, const int code) -{ +void TLSSession_GnuTLS::throwTLSException(const string& fname, const int code) { + std::ostringstream msg; msg << fname + "() returned code "; diff --git a/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp b/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp index dd096ff3..2a7f9d7f 100644 --- a/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp +++ b/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,13 +46,17 @@ namespace net { namespace tls { -class TLSSession_GnuTLS : public TLSSession -{ +class TLSSession_GnuTLS : public TLSSession { + friend class TLSSocket_GnuTLS; public: - TLSSession_GnuTLS(const shared_ptr & cv, const shared_ptr & props); + TLSSession_GnuTLS( + const shared_ptr & cv, + const shared_ptr & props + ); + ~TLSSession_GnuTLS(); diff --git a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp index 31753590..93f1b763 100644 --- a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp +++ b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -50,17 +50,26 @@ namespace tls { // static -shared_ptr TLSSocket::wrap(const shared_ptr & session, const shared_ptr & sok) +shared_ptr TLSSocket::wrap( + const shared_ptr & session, + const shared_ptr & sok +) { - return make_shared - (dynamicCast (session), sok); + return make_shared (dynamicCast (session), sok); } -TLSSocket_GnuTLS::TLSSocket_GnuTLS(const shared_ptr & session, const shared_ptr & sok) - : m_session(session), m_wrapped(sok), m_connected(false), - m_ex(NULL), m_status(0), m_errno(0) -{ +TLSSocket_GnuTLS::TLSSocket_GnuTLS( + const shared_ptr & session, + const shared_ptr & sok +) + : m_session(session), + m_wrapped(sok), + m_connected(false), + m_ex(NULL), + m_status(0), + m_errno(0) { + gnutls_transport_set_ptr(*m_session->m_gnutlsSession, this); gnutls_transport_set_push_function(*m_session->m_gnutlsSession, gnutlsPushFunc); @@ -69,41 +78,38 @@ TLSSocket_GnuTLS::TLSSocket_GnuTLS(const shared_ptr & session } -TLSSocket_GnuTLS::~TLSSocket_GnuTLS() -{ +TLSSocket_GnuTLS::~TLSSocket_GnuTLS() { + resetException(); - try - { + try { disconnect(); - } - catch (...) - { + } catch (...) { // Don't throw exception in destructor } } -void TLSSocket_GnuTLS::connect(const string& address, const port_t port) -{ - try - { +void TLSSocket_GnuTLS::connect(const string& address, const port_t port) { + + try { + m_wrapped->connect(address, port); handshake(); - } - catch (...) - { + + } catch (...) { + disconnect(); throw; } } -void TLSSocket_GnuTLS::disconnect() -{ - if (m_connected) - { +void TLSSocket_GnuTLS::disconnect() { + + if (m_connected) { + gnutls_bye(*m_session->m_gnutlsSession, GNUTLS_SHUT_RDWR); m_wrapped->disconnect(); @@ -113,99 +119,101 @@ void TLSSocket_GnuTLS::disconnect() } -bool TLSSocket_GnuTLS::isConnected() const -{ +bool TLSSocket_GnuTLS::isConnected() const { + return m_wrapped->isConnected() && m_connected; } -size_t TLSSocket_GnuTLS::getBlockSize() const -{ +size_t TLSSocket_GnuTLS::getBlockSize() const { + return 16384; // 16 KB } -const string TLSSocket_GnuTLS::getPeerName() const -{ +const string TLSSocket_GnuTLS::getPeerName() const { + return m_wrapped->getPeerName(); } -const string TLSSocket_GnuTLS::getPeerAddress() const -{ +const string TLSSocket_GnuTLS::getPeerAddress() const { + return m_wrapped->getPeerAddress(); } -shared_ptr TLSSocket_GnuTLS::getTimeoutHandler() -{ +shared_ptr TLSSocket_GnuTLS::getTimeoutHandler() { + return m_wrapped->getTimeoutHandler(); } -void TLSSocket_GnuTLS::setTracer(const shared_ptr & tracer) -{ +void TLSSocket_GnuTLS::setTracer(const shared_ptr & tracer) { + m_wrapped->setTracer(tracer); } -shared_ptr TLSSocket_GnuTLS::getTracer() -{ +shared_ptr TLSSocket_GnuTLS::getTracer() { + return m_wrapped->getTracer(); } -bool TLSSocket_GnuTLS::waitForRead(const int msecs) -{ +bool TLSSocket_GnuTLS::waitForRead(const int msecs) { + return m_wrapped->waitForRead(msecs); } -bool TLSSocket_GnuTLS::waitForWrite(const int msecs) -{ +bool TLSSocket_GnuTLS::waitForWrite(const int msecs) { + return m_wrapped->waitForWrite(msecs); } -void TLSSocket_GnuTLS::receive(string& buffer) -{ +void TLSSocket_GnuTLS::receive(string& buffer) { + const size_t size = receiveRaw(m_buffer, sizeof(m_buffer)); buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size); } -void TLSSocket_GnuTLS::send(const string& buffer) -{ +void TLSSocket_GnuTLS::send(const string& buffer) { + sendRaw(reinterpret_cast (buffer.data()), buffer.length()); } -void TLSSocket_GnuTLS::send(const char* str) -{ +void TLSSocket_GnuTLS::send(const char* str) { + sendRaw(reinterpret_cast (str), ::strlen(str)); } -size_t TLSSocket_GnuTLS::receiveRaw(byte_t* buffer, const size_t count) -{ +size_t TLSSocket_GnuTLS::receiveRaw(byte_t* buffer, const size_t count) { + m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ); resetException(); - const ssize_t ret = gnutls_record_recv - (*m_session->m_gnutlsSession, - buffer, static_cast (count)); + const ssize_t ret = gnutls_record_recv( + *m_session->m_gnutlsSession, + buffer, static_cast (count) + ); throwException(); - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) + if (ret < 0) { + + if (ret == GNUTLS_E_AGAIN) { + + if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) { m_status |= STATUS_WANT_READ; - else + } else { m_status |= STATUS_WANT_WRITE; + } return 0; } @@ -217,36 +225,38 @@ size_t TLSSocket_GnuTLS::receiveRaw(byte_t* buffer, const size_t count) } -void TLSSocket_GnuTLS::sendRaw(const byte_t* buffer, const size_t count) -{ +void TLSSocket_GnuTLS::sendRaw(const byte_t* buffer, const size_t count) { + m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ); - for (size_t size = count ; size > 0 ; ) - { + for (size_t size = count ; size > 0 ; ) { + resetException(); - ssize_t ret = gnutls_record_send - (*m_session->m_gnutlsSession, - buffer, static_cast (size)); + ssize_t ret = gnutls_record_send( + *m_session->m_gnutlsSession, + buffer, static_cast (size) + ); throwException(); - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) + if (ret < 0) { + + if (ret == GNUTLS_E_AGAIN) { + + if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) { m_wrapped->waitForRead(); - else + } else { m_wrapped->waitForWrite(); + } continue; } TLSSession_GnuTLS::throwTLSException("gnutls_record_send", static_cast (ret)); - } - else - { + + } else { + buffer += ret; size -= ret; } @@ -254,26 +264,28 @@ void TLSSocket_GnuTLS::sendRaw(const byte_t* buffer, const size_t count) } -size_t TLSSocket_GnuTLS::sendRawNonBlocking(const byte_t* buffer, const size_t count) -{ +size_t TLSSocket_GnuTLS::sendRawNonBlocking(const byte_t* buffer, const size_t count) { + m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ); resetException(); - ssize_t ret = gnutls_record_send - (*m_session->m_gnutlsSession, - buffer, static_cast (count)); + ssize_t ret = gnutls_record_send( + *m_session->m_gnutlsSession, + buffer, static_cast (count) + ); throwException(); - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) + if (ret < 0) { + + if (ret == GNUTLS_E_AGAIN) { + + if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) { m_status |= STATUS_WANT_READ; - else + } else { m_status |= STATUS_WANT_WRITE; + } return 0; } @@ -285,68 +297,72 @@ size_t TLSSocket_GnuTLS::sendRawNonBlocking(const byte_t* buffer, const size_t c } -unsigned int TLSSocket_GnuTLS::getStatus() const -{ +unsigned int TLSSocket_GnuTLS::getStatus() const { + return m_status | m_wrapped->getStatus(); } -void TLSSocket_GnuTLS::handshake() -{ +void TLSSocket_GnuTLS::handshake() { + shared_ptr toHandler = m_wrapped->getTimeoutHandler(); - if (toHandler) + if (toHandler) { toHandler->resetTimeOut(); + } - if (getTracer()) + if (getTracer()) { getTracer()->traceSend("Beginning SSL/TLS handshake"); + } // Start handshaking process - try - { - while (true) - { + try { + + while (true) { + resetException(); const int ret = gnutls_handshake(*m_session->m_gnutlsSession); throwException(); - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) + if (ret < 0) { + + if (ret == GNUTLS_E_AGAIN) { + + if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) { m_wrapped->waitForRead(); - else + } else { m_wrapped->waitForWrite(); - } - else if (ret == GNUTLS_E_INTERRUPTED) - { + } + + } else if (ret == GNUTLS_E_INTERRUPTED) { + // Non-fatal error - } - else - { + + } else { + TLSSession_GnuTLS::throwTLSException("gnutls_handshake", ret); } - } - else - { + + } else { + // Successful handshake break; } } - } - catch (...) - { + + } catch (...) { + throw; } // Verify server's certificate(s) shared_ptr certs = getPeerCertificates(); - if (certs == NULL) + if (certs == NULL) { throw exceptions::tls_exception("No peer certificate."); + } m_session->getCertificateVerifier()->verify(certs, getPeerName()); @@ -354,35 +370,38 @@ void TLSSocket_GnuTLS::handshake() } -int TLSSocket_GnuTLS::gnutlsErrnoFunc(gnutls_transport_ptr_t trspt) -{ +int TLSSocket_GnuTLS::gnutlsErrnoFunc(gnutls_transport_ptr_t trspt) { + TLSSocket_GnuTLS* sok = reinterpret_cast (trspt); return sok->m_errno; } -ssize_t TLSSocket_GnuTLS::gnutlsPushFunc - (gnutls_transport_ptr_t trspt, const void* data, size_t len) -{ +ssize_t TLSSocket_GnuTLS::gnutlsPushFunc( + gnutls_transport_ptr_t trspt, + const void* data, + size_t len +) { + TLSSocket_GnuTLS* sok = reinterpret_cast (trspt); - try - { - const ssize_t ret = static_cast - (sok->m_wrapped->sendRawNonBlocking - (reinterpret_cast (data), len)); + try { + + const ssize_t ret = static_cast ( + sok->m_wrapped->sendRawNonBlocking(reinterpret_cast (data), len) + ); + + if (ret == 0) { - if (ret == 0) - { gnutls_transport_set_errno(*sok->m_session->m_gnutlsSession, EAGAIN); sok->m_errno = EAGAIN; return -1; } return ret; - } - catch (exception& e) - { + + } catch (exception& e) { + // Workaround for non-portable behaviour when throwing C++ exceptions // from C functions (GNU TLS) sok->m_ex = e.clone(); @@ -391,28 +410,31 @@ ssize_t TLSSocket_GnuTLS::gnutlsPushFunc } -ssize_t TLSSocket_GnuTLS::gnutlsPullFunc - (gnutls_transport_ptr_t trspt, void* data, size_t len) -{ +ssize_t TLSSocket_GnuTLS::gnutlsPullFunc( + gnutls_transport_ptr_t trspt, + void* data, + size_t len +) { + TLSSocket_GnuTLS* sok = reinterpret_cast (trspt); - try - { - const ssize_t n = static_cast - (sok->m_wrapped->receiveRaw - (reinterpret_cast (data), len)); + try { + + const ssize_t n = static_cast ( + sok->m_wrapped->receiveRaw(reinterpret_cast (data), len) + ); + + if (n == 0) { - if (n == 0) - { gnutls_transport_set_errno(*sok->m_session->m_gnutlsSession, EAGAIN); sok->m_errno = EAGAIN; return -1; } return n; - } - catch (exception& e) - { + + } catch (exception& e) { + // Workaround for non-portable behaviour when throwing C++ exceptions // from C functions (GNU TLS) sok->m_ex = e.clone(); @@ -421,74 +443,69 @@ ssize_t TLSSocket_GnuTLS::gnutlsPullFunc } -shared_ptr TLSSocket_GnuTLS::getPeerCertificates() -{ - if (getTracer()) +shared_ptr TLSSocket_GnuTLS::getPeerCertificates() { + + if (getTracer()) { getTracer()->traceSend("Getting peer certificates"); + } unsigned int certCount = 0; - const gnutls_datum_t* rawData = gnutls_certificate_get_peers - (*m_session->m_gnutlsSession, &certCount); + const gnutls_datum_t* rawData = gnutls_certificate_get_peers( + *m_session->m_gnutlsSession, &certCount + ); - if (rawData == NULL) + if (rawData == NULL) { return null; + } // Try X.509 gnutls_x509_crt_t* x509Certs = new gnutls_x509_crt_t[certCount]; - for (unsigned int i = 0; i < certCount; ++i) - { + for (unsigned int i = 0; i < certCount; ++i) { + gnutls_x509_crt_init(x509Certs + i); - int res = gnutls_x509_crt_import(x509Certs[i], rawData + i, - GNUTLS_X509_FMT_DER); + int res = gnutls_x509_crt_import(x509Certs[i], rawData + i, GNUTLS_X509_FMT_DER); - if (res < 0) - { + if (res < 0) { // XXX more fine-grained error reporting? delete [] x509Certs; return null; } } - { - std::vector > certs; - bool error = false; + std::vector > certs; + bool error = false; - for (unsigned int i = 0 ; i < certCount ; ++i) - { - size_t dataSize = 0; + for (unsigned int i = 0 ; i < certCount ; ++i) { - gnutls_x509_crt_export(x509Certs[i], - GNUTLS_X509_FMT_DER, NULL, &dataSize); + size_t dataSize = 0; - std::vector data(dataSize); + gnutls_x509_crt_export(x509Certs[i], GNUTLS_X509_FMT_DER, NULL, &dataSize); - gnutls_x509_crt_export(x509Certs[i], - GNUTLS_X509_FMT_DER, &data[0], &dataSize); + std::vector data(dataSize); - shared_ptr cert = - security::cert::X509Certificate::import(&data[0], dataSize); + gnutls_x509_crt_export(x509Certs[i], GNUTLS_X509_FMT_DER, &data[0], &dataSize); - if (cert != NULL) - certs.push_back(cert); - else - error = true; + shared_ptr cert = + security::cert::X509Certificate::import(&data[0], dataSize); - gnutls_x509_crt_deinit(x509Certs[i]); + if (cert != NULL) { + certs.push_back(cert); + } else { + error = true; } - delete [] x509Certs; - - if (error) - return null; - - return make_shared (certs); + gnutls_x509_crt_deinit(x509Certs[i]); } delete [] x509Certs; - return null; + if (error) { + return null; + } + + return make_shared (certs); } @@ -498,19 +515,17 @@ shared_ptr TLSSocket_GnuTLS::getPeerCertifica // gnutls_record_recv() calls TLSSocket::gnutlsPullFunc, and exceptions // thrown by the socket can not be caught. -void TLSSocket_GnuTLS::throwException() -{ - if (m_ex) - { +void TLSSocket_GnuTLS::throwException() { + + if (m_ex) { throw *m_ex; } } -void TLSSocket_GnuTLS::resetException() -{ - if (m_ex) - { +void TLSSocket_GnuTLS::resetException() { + + if (m_ex) { delete m_ex; m_ex = NULL; } diff --git a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp index a1d78e99..0ac3e700 100644 --- a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp +++ b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,8 +46,8 @@ class TLSSession; class TLSSession_GnuTLS; -class TLSSocket_GnuTLS : public TLSSocket -{ +class TLSSocket_GnuTLS : public TLSSocket { + public: TLSSocket_GnuTLS(const shared_ptr & session, const shared_ptr & sok); diff --git a/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp b/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp index 1bbb9ee5..74474480 100644 --- a/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp +++ b/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -52,34 +52,34 @@ namespace tls { shared_ptr * OpenSSLInitializer::sm_mutexes; -OpenSSLInitializer::autoInitializer::autoInitializer() -{ +OpenSSLInitializer::autoInitializer::autoInitializer() { + // The construction of this unique 'oneTimeInitializer' object will be triggered // by the 'autoInitializer' objects from the other translation units static OpenSSLInitializer::oneTimeInitializer oneTimeInitializer; } -OpenSSLInitializer::autoInitializer::~autoInitializer() -{ +OpenSSLInitializer::autoInitializer::~autoInitializer() { + } -OpenSSLInitializer::oneTimeInitializer::oneTimeInitializer() -{ +OpenSSLInitializer::oneTimeInitializer::oneTimeInitializer() { + initialize(); } -OpenSSLInitializer::oneTimeInitializer::~oneTimeInitializer() -{ +OpenSSLInitializer::oneTimeInitializer::~oneTimeInitializer() { + uninitialize(); } // static -void OpenSSLInitializer::initialize() -{ +void OpenSSLInitializer::initialize() { + #if OPENSSL_VERSION_NUMBER >= 0x0907000L OPENSSL_config(NULL); #endif @@ -95,8 +95,9 @@ void OpenSSLInitializer::initialize() int numMutexes = CRYPTO_num_locks(); sm_mutexes = new shared_ptr [numMutexes]; - for (int i = 0 ; i < numMutexes ; ++i) + for (int i = 0 ; i < numMutexes ; ++i) { sm_mutexes[i] = vmime::platform::getHandler()->createCriticalSection(); + } CRYPTO_set_locking_callback(&OpenSSLInitializer::lock); CRYPTO_set_id_callback(&OpenSSLInitializer::id); @@ -104,8 +105,8 @@ void OpenSSLInitializer::initialize() // static -void OpenSSLInitializer::uninitialize() -{ +void OpenSSLInitializer::uninitialize() { + EVP_cleanup(); ERR_free_strings(); @@ -117,18 +118,19 @@ void OpenSSLInitializer::uninitialize() // static -void OpenSSLInitializer::lock(int mode, int n, const char* /* file */, int /* line */) -{ - if (mode & CRYPTO_LOCK) +void OpenSSLInitializer::lock(int mode, int n, const char* /* file */, int /* line */) { + + if (mode & CRYPTO_LOCK) { sm_mutexes[n]->lock(); - else + } else { sm_mutexes[n]->unlock(); + } } // static -unsigned long OpenSSLInitializer::id() -{ +unsigned long OpenSSLInitializer::id() { + return vmime::platform::getHandler()->getThreadId(); } diff --git a/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp b/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp index d7595aa8..b07c2e61 100644 --- a/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp +++ b/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,15 +46,13 @@ namespace tls { /** Class responsible for setting up OpenSSL */ -class OpenSSLInitializer -{ +class OpenSSLInitializer { + public: /** Automatically initialize OpenSSL */ - class autoInitializer - { - public: + struct autoInitializer { autoInitializer(); ~autoInitializer(); @@ -62,9 +60,7 @@ public: protected: - class oneTimeInitializer - { - public: + struct oneTimeInitializer { oneTimeInitializer(); ~oneTimeInitializer(); @@ -82,8 +78,7 @@ protected: static shared_ptr getMutex(); - enum - { + enum { SEEDSIZE = 256 }; diff --git a/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp b/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp index 932477df..ea22f1cd 100644 --- a/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp +++ b/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,63 +40,63 @@ namespace tls { TLSProperties::TLSProperties() - : m_data(make_shared ()) -{ + : m_data(make_shared ()) { + setCipherSuite(CIPHERSUITE_DEFAULT); } TLSProperties::TLSProperties(const TLSProperties& props) : object(), - m_data(make_shared ()) -{ + m_data(make_shared ()) { + *dynamicCast (m_data) = *dynamicCast (props.m_data); } -void TLSProperties::setCipherSuite(const GenericCipherSuite cipherSuite) -{ - switch (cipherSuite) - { - case CIPHERSUITE_HIGH: +void TLSProperties::setCipherSuite(const GenericCipherSuite cipherSuite) { - setCipherSuite("HIGH:!ADH:@STRENGTH"); - break; + switch (cipherSuite) { - case CIPHERSUITE_MEDIUM: + case CIPHERSUITE_HIGH: - setCipherSuite("MEDIUM:!ADH:@STRENGTH"); - break; + setCipherSuite("HIGH:!ADH:@STRENGTH"); + break; - case CIPHERSUITE_LOW: + case CIPHERSUITE_MEDIUM: - setCipherSuite("LOW:!ADH:@STRENGTH"); - break; + setCipherSuite("MEDIUM:!ADH:@STRENGTH"); + break; - default: - case CIPHERSUITE_DEFAULT: + case CIPHERSUITE_LOW: - setCipherSuite("DEFAULT:!ADH:@STRENGTH"); - break; + setCipherSuite("LOW:!ADH:@STRENGTH"); + break; + + default: + case CIPHERSUITE_DEFAULT: + + setCipherSuite("DEFAULT:!ADH:@STRENGTH"); + break; } } -void TLSProperties::setCipherSuite(const string& cipherSuite) -{ +void TLSProperties::setCipherSuite(const string& cipherSuite) { + dynamicCast (m_data)->cipherSuite = cipherSuite; } -const string TLSProperties::getCipherSuite() const -{ +const string TLSProperties::getCipherSuite() const { + return dynamicCast (m_data)->cipherSuite; } -TLSProperties_OpenSSL& TLSProperties_OpenSSL::operator=(const TLSProperties_OpenSSL& other) -{ +TLSProperties_OpenSSL& TLSProperties_OpenSSL::operator=(const TLSProperties_OpenSSL& other) { + cipherSuite = other.cipherSuite; return *this; diff --git a/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp b/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp index 5d2f075a..8304df23 100644 --- a/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp +++ b/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,8 +44,8 @@ namespace net { namespace tls { -class TLSProperties_OpenSSL : public object -{ +class TLSProperties_OpenSSL : public object { + public: TLSProperties_OpenSSL& operator=(const TLSProperties_OpenSSL& other); diff --git a/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp index 961f6517..019341c7 100644 --- a/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp +++ b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,15 +46,23 @@ static OpenSSLInitializer::autoInitializer openSSLInitializer; // static -shared_ptr TLSSession::create(const shared_ptr & cv, const shared_ptr & props) -{ +shared_ptr TLSSession::create( + const shared_ptr & cv, + const shared_ptr & props +) { + return make_shared (cv, props); } -TLSSession_OpenSSL::TLSSession_OpenSSL(const shared_ptr & cv, const shared_ptr & props) - : m_sslctx(0), m_certVerifier(cv), m_props(props) -{ +TLSSession_OpenSSL::TLSSession_OpenSSL( + const shared_ptr & cv, + const shared_ptr & props +) + : m_sslctx(0), + m_certVerifier(cv), + m_props(props) { + m_sslctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_options(m_sslctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); SSL_CTX_set_mode(m_sslctx, SSL_MODE_AUTO_RETRY); @@ -64,36 +72,36 @@ TLSSession_OpenSSL::TLSSession_OpenSSL(const shared_ptr TLSSession_OpenSSL::getSocket(const shared_ptr & sok) -{ +shared_ptr TLSSession_OpenSSL::getSocket(const shared_ptr & sok) { + return TLSSocket::wrap(dynamicCast (shared_from_this()), sok); } -shared_ptr TLSSession_OpenSSL::getCertificateVerifier() -{ +shared_ptr TLSSession_OpenSSL::getCertificateVerifier() { + return m_certVerifier; } -void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile) -{ +void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile) { + ERR_clear_error(); - if (SSL_CTX_use_PrivateKey_file(m_sslctx, keyfile.c_str(), SSL_FILETYPE_PEM) != 1) - { + if (SSL_CTX_use_PrivateKey_file(m_sslctx, keyfile.c_str(), SSL_FILETYPE_PEM) != 1) { + unsigned long errCode = ERR_get_error(); char buffer[256]; ERR_error_string_n(errCode, buffer, sizeof(buffer)); @@ -106,12 +114,12 @@ void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile) } -void TLSSession_OpenSSL::useCertificateChainFile(const vmime::string& chainFile) -{ +void TLSSession_OpenSSL::useCertificateChainFile(const vmime::string& chainFile) { + ERR_clear_error(); - if (SSL_CTX_use_certificate_chain_file(m_sslctx, chainFile.c_str()) != 1) - { + if (SSL_CTX_use_certificate_chain_file(m_sslctx, chainFile.c_str()) != 1) { + unsigned long errCode = ERR_get_error(); char buffer[256]; ERR_error_string_n(errCode, buffer, sizeof(buffer)); @@ -124,8 +132,8 @@ void TLSSession_OpenSSL::useCertificateChainFile(const vmime::string& chainFile) } -SSL_CTX* TLSSession_OpenSSL::getContext() const -{ +SSL_CTX* TLSSession_OpenSSL::getContext() const { + return m_sslctx; } diff --git a/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp index c5c5da39..518216bc 100644 --- a/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp +++ b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -49,13 +49,17 @@ namespace net { namespace tls { -class TLSSession_OpenSSL : public TLSSession -{ +class TLSSession_OpenSSL : public TLSSession { + friend class TLSSocket_OpenSSL; public: - TLSSession_OpenSSL(const shared_ptr & cv, const shared_ptr & props); + TLSSession_OpenSSL( + const shared_ptr & cv, + const shared_ptr & props + ); + ~TLSSession_OpenSSL(); @@ -66,13 +70,11 @@ public: /** Set the private key to use if server requires a client certificate. * - * @param keyfile Path to the private key in PEM format - * @param passwd_callback If the private key is stored encrypted the + * @param keyfile path to the private key in PEM format */ void usePrivateKeyFile(const vmime::string& keyfile); - /** Supply the certificate chain to present if requested by - * server. + /** Supply the certificate chain to present if requested by server. * * @param chainFile File in PEM format holding certificate chain */ @@ -105,4 +107,3 @@ private: #endif // VMIME_BUILDING_DOC #endif // VMIME_NET_TLS_TLSSESSION_OPENSSL_HPP_INCLUDED - diff --git a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp index afc7e514..db782bb2 100644 --- a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp +++ b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -55,8 +55,7 @@ static OpenSSLInitializer::autoInitializer openSSLInitializer; #if OPENSSL_VERSION_NUMBER < 0x10100000L // static -BIO_METHOD TLSSocket_OpenSSL::sm_customBIOMethod = -{ +BIO_METHOD TLSSocket_OpenSSL::sm_customBIOMethod = { 100 | BIO_TYPE_SOURCE_SINK, "vmime::socket glue", TLSSocket_OpenSSL::bio_write, @@ -87,36 +86,42 @@ BIO_METHOD TLSSocket_OpenSSL::sm_customBIOMethod = // static -shared_ptr TLSSocket::wrap(const shared_ptr & session, const shared_ptr & sok) -{ - return make_shared - (dynamicCast (session), sok); +shared_ptr TLSSocket::wrap( + const shared_ptr & session, + const shared_ptr & sok +) { + + return make_shared (dynamicCast (session), sok); } -TLSSocket_OpenSSL::TLSSocket_OpenSSL(const shared_ptr & session, const shared_ptr & sok) - : m_session(session), m_wrapped(sok), m_connected(false), m_ssl(0), m_status(0), m_ex() -{ +TLSSocket_OpenSSL::TLSSocket_OpenSSL( + const shared_ptr & session, + const shared_ptr & sok +) + : m_session(session), + m_wrapped(sok), + m_connected(false), + m_ssl(0), + m_status(0), + m_ex() { + } -TLSSocket_OpenSSL::~TLSSocket_OpenSSL() -{ - try - { +TLSSocket_OpenSSL::~TLSSocket_OpenSSL() { + + try { disconnect(); - } - catch (...) - { + } catch (...) { // Don't throw in destructor } } -void TLSSocket_OpenSSL::createSSLHandle() -{ - if (m_wrapped->isConnected()) - { +void TLSSocket_OpenSSL::createSSLHandle() { + + if (m_wrapped->isConnected()) { #if OPENSSL_VERSION_NUMBER < 0x10100000L @@ -128,8 +133,7 @@ void TLSSocket_OpenSSL::createSSLHandle() BIO_METHOD* bioMeth = BIO_meth_new(BIO_TYPE_SOURCE_SINK | BIO_get_new_index(), "vmime::socket glue"); - if (!bioMeth) - { + if (!bioMeth) { BIO_meth_free(bioMeth); throw exceptions::tls_exception("BIO_meth_new() failed"); } @@ -147,15 +151,13 @@ void TLSSocket_OpenSSL::createSSLHandle() #endif - if (!sockBio) - { + if (!sockBio) { throw exceptions::tls_exception("BIO_new() failed"); } m_ssl = SSL_new(m_session->getContext()); - if (!m_ssl) - { + if (!m_ssl) { BIO_free(sockBio); throw exceptions::tls_exception("Cannot create SSL object"); } @@ -163,156 +165,156 @@ void TLSSocket_OpenSSL::createSSLHandle() SSL_set_bio(m_ssl, sockBio, sockBio); SSL_set_connect_state(m_ssl); SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY | SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - } - else - { + + } else { + throw exceptions::tls_exception("Unconnected socket error"); } } -void TLSSocket_OpenSSL::connect(const string& address, const port_t port) -{ - try - { +void TLSSocket_OpenSSL::connect(const string& address, const port_t port) { + + try { + m_wrapped->connect(address, port); createSSLHandle(); handshake(); - } - catch (...) - { + + } catch (...) { + disconnect(); throw; } } -void TLSSocket_OpenSSL::disconnect() -{ - if (m_ssl) - { +void TLSSocket_OpenSSL::disconnect() { + + if (m_ssl) { + // Don't shut down the socket more than once. int shutdownState = SSL_get_shutdown(m_ssl); bool shutdownSent = (shutdownState & SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN; - if (!shutdownSent) + if (!shutdownSent) { SSL_shutdown(m_ssl); + } SSL_free(m_ssl); m_ssl = 0; } - if (m_connected) - { + if (m_connected) { m_connected = false; m_wrapped->disconnect(); } } -bool TLSSocket_OpenSSL::isConnected() const -{ +bool TLSSocket_OpenSSL::isConnected() const { + return m_wrapped->isConnected() && m_connected; } -size_t TLSSocket_OpenSSL::getBlockSize() const -{ +size_t TLSSocket_OpenSSL::getBlockSize() const { + return 16384; // 16 KB } -const string TLSSocket_OpenSSL::getPeerName() const -{ +const string TLSSocket_OpenSSL::getPeerName() const { + return m_wrapped->getPeerName(); } -const string TLSSocket_OpenSSL::getPeerAddress() const -{ +const string TLSSocket_OpenSSL::getPeerAddress() const { + return m_wrapped->getPeerAddress(); } -shared_ptr TLSSocket_OpenSSL::getTimeoutHandler() -{ +shared_ptr TLSSocket_OpenSSL::getTimeoutHandler() { + return m_wrapped->getTimeoutHandler(); } -void TLSSocket_OpenSSL::setTracer(const shared_ptr & tracer) -{ +void TLSSocket_OpenSSL::setTracer(const shared_ptr & tracer) { + m_wrapped->setTracer(tracer); } -shared_ptr TLSSocket_OpenSSL::getTracer() -{ +shared_ptr TLSSocket_OpenSSL::getTracer() { + return m_wrapped->getTracer(); } -bool TLSSocket_OpenSSL::waitForRead(const int msecs) -{ +bool TLSSocket_OpenSSL::waitForRead(const int msecs) { + return m_wrapped->waitForRead(msecs); } -bool TLSSocket_OpenSSL::waitForWrite(const int msecs) -{ +bool TLSSocket_OpenSSL::waitForWrite(const int msecs) { + return m_wrapped->waitForWrite(msecs); } -void TLSSocket_OpenSSL::receive(string& buffer) -{ +void TLSSocket_OpenSSL::receive(string& buffer) { + const size_t size = receiveRaw(m_buffer, sizeof(m_buffer)); - if (size != 0) + if (size != 0) { buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size); - else + } else { buffer.clear(); + } } -void TLSSocket_OpenSSL::send(const string& buffer) -{ +void TLSSocket_OpenSSL::send(const string& buffer) { + sendRaw(reinterpret_cast (buffer.data()), buffer.length()); } -void TLSSocket_OpenSSL::send(const char* str) -{ +void TLSSocket_OpenSSL::send(const char* str) { + sendRaw(reinterpret_cast (str), ::strlen(str)); } -size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) -{ - if (!m_ssl) +size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) { + + if (!m_ssl) { throw exceptions::socket_not_connected_exception(); + } m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ); ERR_clear_error(); int rc = SSL_read(m_ssl, buffer, static_cast (count)); - if (m_ex.get()) + if (m_ex.get()) { internalThrow(); + } + + if (rc <= 0) { - if (rc <= 0) - { int error = SSL_get_error(m_ssl, rc); - if (error == SSL_ERROR_WANT_WRITE) - { + if (error == SSL_ERROR_WANT_WRITE) { m_status |= STATUS_WANT_WRITE; return 0; - } - else if (error == SSL_ERROR_WANT_READ) - { + } else if (error == SSL_ERROR_WANT_READ) { m_status |= STATUS_WANT_READ; return 0; } @@ -324,37 +326,35 @@ size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) } -void TLSSocket_OpenSSL::sendRaw(const byte_t* buffer, const size_t count) -{ - if (!m_ssl) +void TLSSocket_OpenSSL::sendRaw(const byte_t* buffer, const size_t count) { + + if (!m_ssl) { throw exceptions::socket_not_connected_exception(); + } m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ); - for (size_t size = count ; size > 0 ; ) - { + for (size_t size = count ; size > 0 ; ) { + ERR_clear_error(); int rc = SSL_write(m_ssl, buffer, static_cast (size)); - if (rc <= 0) - { + if (rc <= 0) { + int error = SSL_get_error(m_ssl, rc); - if (error == SSL_ERROR_WANT_READ) - { + if (error == SSL_ERROR_WANT_READ) { m_wrapped->waitForRead(); continue; - } - else if (error == SSL_ERROR_WANT_WRITE) - { + } else if (error == SSL_ERROR_WANT_WRITE) { m_wrapped->waitForWrite(); continue; } handleError(rc); - } - else - { + + } else { + buffer += rc; size -= rc; } @@ -362,30 +362,29 @@ void TLSSocket_OpenSSL::sendRaw(const byte_t* buffer, const size_t count) } -size_t TLSSocket_OpenSSL::sendRawNonBlocking(const byte_t* buffer, const size_t count) -{ - if (!m_ssl) +size_t TLSSocket_OpenSSL::sendRawNonBlocking(const byte_t* buffer, const size_t count) { + + if (!m_ssl) { throw exceptions::socket_not_connected_exception(); + } m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ); ERR_clear_error(); int rc = SSL_write(m_ssl, buffer, static_cast (count)); - if (m_ex.get()) + if (m_ex.get()) { internalThrow(); + } + + if (rc <= 0) { - if (rc <= 0) - { int error = SSL_get_error(m_ssl, rc); - if (error == SSL_ERROR_WANT_WRITE) - { + if (error == SSL_ERROR_WANT_WRITE) { m_status |= STATUS_WANT_WRITE; return 0; - } - else if (error == SSL_ERROR_WANT_READ) - { + } else if (error == SSL_ERROR_WANT_READ) { m_status |= STATUS_WANT_READ; return 0; } @@ -397,59 +396,65 @@ size_t TLSSocket_OpenSSL::sendRawNonBlocking(const byte_t* buffer, const size_t } -void TLSSocket_OpenSSL::handshake() -{ +void TLSSocket_OpenSSL::handshake() { + shared_ptr toHandler = m_wrapped->getTimeoutHandler(); - if (toHandler) + if (toHandler) { toHandler->resetTimeOut(); + } - if (getTracer()) + if (getTracer()) { getTracer()->traceSend("Beginning SSL/TLS handshake"); + } // Start handshaking process - if (!m_ssl) + if (!m_ssl) { createSSLHandle(); + } + + try { - try - { int rc; ERR_clear_error(); - while ((rc = SSL_do_handshake(m_ssl)) <= 0) - { + while ((rc = SSL_do_handshake(m_ssl)) <= 0) { + const int err = SSL_get_error(m_ssl, rc); - if (err == SSL_ERROR_WANT_READ) + if (err == SSL_ERROR_WANT_READ) { m_wrapped->waitForRead(); - else if (err == SSL_ERROR_WANT_WRITE) + } else if (err == SSL_ERROR_WANT_WRITE) { m_wrapped->waitForWrite(); - else + } else { handleError(rc); + } // Check whether the time-out delay is elapsed - if (toHandler && toHandler->isTimeOut()) - { - if (!toHandler->handleTimeOut()) + if (toHandler && toHandler->isTimeOut()) { + + if (!toHandler->handleTimeOut()) { throw exceptions::operation_timed_out(); + } toHandler->resetTimeOut(); } ERR_clear_error(); } - } - catch (...) - { + + } catch (...) { + throw; } // Verify server's certificate(s) shared_ptr certs = getPeerCertificates(); - if (certs == NULL) + if (!certs) { throw exceptions::tls_exception("No peer certificate."); + } m_session->getCertificateVerifier()->verify(certs, getPeerName()); @@ -457,121 +462,130 @@ void TLSSocket_OpenSSL::handshake() } -shared_ptr TLSSocket_OpenSSL::getPeerCertificates() -{ - if (getTracer()) +shared_ptr TLSSocket_OpenSSL::getPeerCertificates() { + + if (getTracer()) { getTracer()->traceSend("Getting peer certificates"); + } STACK_OF(X509)* chain = SSL_get_peer_cert_chain(m_ssl); - if (chain == NULL) + if (chain == NULL) { return null; + } int certCount = sk_X509_num(chain); - if (certCount == 0) + if (certCount == 0) { return null; + } bool error = false; std::vector > certs; - for (int i = 0; i < certCount && !error; i++) - { + for (int i = 0; i < certCount && !error; i++) { + shared_ptr cert = vmime::security::cert::X509Certificate_OpenSSL::importInternal(sk_X509_value(chain, i)); - if (cert) + if (cert) { certs.push_back(cert); - else + } else { error = true; + } } - if (error) + if (error) { return null; + } return make_shared (certs); } -void TLSSocket_OpenSSL::internalThrow() -{ - if (m_ex.get()) +void TLSSocket_OpenSSL::internalThrow() { + + if (m_ex.get()) { throw *m_ex; + } } -void TLSSocket_OpenSSL::handleError(int rc) -{ - if (rc > 0) return; +void TLSSocket_OpenSSL::handleError(int rc) { + + if (rc > 0) { + return; + } internalThrow(); int sslError = SSL_get_error(m_ssl, rc); long lastError = ERR_get_error(); - switch (sslError) - { - case SSL_ERROR_ZERO_RETURN: + switch (sslError) { - disconnect(); - return; + case SSL_ERROR_ZERO_RETURN: - case SSL_ERROR_SYSCALL: - { - if (lastError == 0) - { - if (rc == 0) - { - throw exceptions::tls_exception("SSL connection unexpectedly closed"); + disconnect(); + return; + + case SSL_ERROR_SYSCALL: { + + if (lastError == 0) { + + if (rc == 0) { + + throw exceptions::tls_exception("SSL connection unexpectedly closed"); + + } else { + + std::ostringstream oss; + oss << "The BIO reported an error: " << rc; + oss.flush(); + throw exceptions::tls_exception(oss.str()); + } } - else - { - std::ostringstream oss; - oss << "The BIO reported an error: " << rc; - oss.flush(); - throw exceptions::tls_exception(oss.str()); + + break; + } + + case SSL_ERROR_WANT_READ: + + BIO_set_retry_read(SSL_get_rbio(m_ssl)); + break; + + case SSL_ERROR_WANT_WRITE: + + BIO_set_retry_write(SSL_get_wbio(m_ssl)); + break; + + // This happens only for BIOs of type BIO_s_connect() or BIO_s_accept() + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + // SSL_CTX_set_client_cert_cb related, not used + case SSL_ERROR_WANT_X509_LOOKUP: + case SSL_ERROR_SSL: + default: + + if (lastError == 0) { + + throw exceptions::tls_exception("Unexpected SSL IO error"); + + } else { + + char buffer[256]; + ERR_error_string_n(lastError, buffer, sizeof(buffer)); + vmime::string msg(buffer); + throw exceptions::tls_exception(msg); } - } - break; - } - case SSL_ERROR_WANT_READ: - - BIO_set_retry_read(SSL_get_rbio(m_ssl)); - break; - - case SSL_ERROR_WANT_WRITE: - - BIO_set_retry_write(SSL_get_wbio(m_ssl)); - break; - - // This happens only for BIOs of type BIO_s_connect() or BIO_s_accept() - case SSL_ERROR_WANT_CONNECT: - case SSL_ERROR_WANT_ACCEPT: - // SSL_CTX_set_client_cert_cb related, not used - case SSL_ERROR_WANT_X509_LOOKUP: - case SSL_ERROR_SSL: - default: - - if (lastError == 0) - { - throw exceptions::tls_exception("Unexpected SSL IO error"); - } - else - { - char buffer[256]; - ERR_error_string_n(lastError, buffer, sizeof(buffer)); - vmime::string msg(buffer); - throw exceptions::tls_exception(msg); - } - - break; + break; } } -unsigned int TLSSocket_OpenSSL::getStatus() const -{ +unsigned int TLSSocket_OpenSSL::getStatus() const { + return m_status; } @@ -580,33 +594,35 @@ unsigned int TLSSocket_OpenSSL::getStatus() const // static -int TLSSocket_OpenSSL::bio_write(BIO* bio, const char* buf, int len) -{ +int TLSSocket_OpenSSL::bio_write(BIO* bio, const char* buf, int len) { + BIO_clear_retry_flags(bio); - if (buf == NULL || len <= 0) + if (buf == NULL || len <= 0) { return -1; + } TLSSocket_OpenSSL *sok = reinterpret_cast (BIO_get_data(bio)); - if (!BIO_get_init(bio) || !sok) + if (!BIO_get_init(bio) || !sok) { return -1; + } - try - { - const size_t n = sok->m_wrapped->sendRawNonBlocking - (reinterpret_cast (buf), len); + try { - if (n == 0 && sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) - { + const size_t n = sok->m_wrapped->sendRawNonBlocking( + reinterpret_cast (buf), len + ); + + if (n == 0 && sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) { BIO_set_retry_write(bio); return -1; } return static_cast (n); - } - catch (exception& e) - { + + } catch (exception& e) { + // Workaround for passing C++ exceptions from C BIO functions sok->m_ex.reset(e.clone()); return -1; @@ -615,33 +631,35 @@ int TLSSocket_OpenSSL::bio_write(BIO* bio, const char* buf, int len) // static -int TLSSocket_OpenSSL::bio_read(BIO* bio, char* buf, int len) -{ +int TLSSocket_OpenSSL::bio_read(BIO* bio, char* buf, int len) { + BIO_clear_retry_flags(bio); - if (buf == NULL || len <= 0) + if (buf == NULL || len <= 0) { return -1; + } TLSSocket_OpenSSL *sok = reinterpret_cast (BIO_get_data(bio)); - if (!BIO_get_init(bio) || !sok) + if (!BIO_get_init(bio) || !sok) { return -1; + } - try - { - const size_t n = sok->m_wrapped->receiveRaw - (reinterpret_cast (buf), len); + try { - if (n == 0 || sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) - { + const size_t n = sok->m_wrapped->receiveRaw( + reinterpret_cast (buf), len + ); + + if (n == 0 || sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) { BIO_set_retry_read(bio); return -1; } return static_cast (n); - } - catch (exception& e) - { + + } catch (exception& e) { + // Workaround for passing C++ exceptions from C BIO functions sok->m_ex.reset(e.clone()); return -1; @@ -650,50 +668,50 @@ int TLSSocket_OpenSSL::bio_read(BIO* bio, char* buf, int len) // static -int TLSSocket_OpenSSL::bio_puts(BIO* bio, const char* str) -{ +int TLSSocket_OpenSSL::bio_puts(BIO* bio, const char* str) { + return bio_write(bio, str, static_cast (strlen(str))); } // static -long TLSSocket_OpenSSL::bio_ctrl(BIO* bio, int cmd, long num, void* /* ptr */) -{ +long TLSSocket_OpenSSL::bio_ctrl(BIO* bio, int cmd, long num, void* /* ptr */) { + long ret = 1; - switch (cmd) - { - case BIO_CTRL_INFO: + switch (cmd) { - ret = 0; - break; + case BIO_CTRL_INFO: - case BIO_CTRL_GET_CLOSE: + ret = 0; + break; - ret = BIO_get_shutdown(bio); - break; + case BIO_CTRL_GET_CLOSE: - case BIO_CTRL_SET_CLOSE: + ret = BIO_get_shutdown(bio); + break; - BIO_set_shutdown(bio, static_cast (num)); - break; + case BIO_CTRL_SET_CLOSE: - case BIO_CTRL_PENDING: - case BIO_CTRL_WPENDING: + BIO_set_shutdown(bio, static_cast (num)); + break; - ret = 0; - break; + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: - case BIO_CTRL_DUP: - case BIO_CTRL_FLUSH: + ret = 0; + break; - ret = 1; - break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: - default: + ret = 1; + break; - ret = 0; - break; + default: + + ret = 0; + break; } return ret; @@ -701,8 +719,8 @@ long TLSSocket_OpenSSL::bio_ctrl(BIO* bio, int cmd, long num, void* /* ptr */) // static -int TLSSocket_OpenSSL::bio_create(BIO* bio) -{ +int TLSSocket_OpenSSL::bio_create(BIO* bio) { + BIO_set_init(bio, 0); BIO_set_num(bio, 0); BIO_set_data(bio, NULL); @@ -713,13 +731,13 @@ int TLSSocket_OpenSSL::bio_create(BIO* bio) // static -int TLSSocket_OpenSSL::bio_destroy(BIO* bio) -{ - if (bio == NULL) - return 0; +int TLSSocket_OpenSSL::bio_destroy(BIO* bio) { - if (BIO_get_shutdown(bio)) - { + if (!bio) { + return 0; + } + + if (BIO_get_shutdown(bio)) { BIO_set_data(bio, NULL); BIO_set_init(bio, 0); BIO_set_flags(bio, 0); diff --git a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp index 9f395051..e30df680 100644 --- a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp +++ b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -50,11 +50,15 @@ class TLSSession; class TLSSession_OpenSSL; -class TLSSocket_OpenSSL : public TLSSocket -{ +class TLSSocket_OpenSSL : public TLSSocket { + public: - TLSSocket_OpenSSL(const shared_ptr & session, const shared_ptr & sok); + TLSSocket_OpenSSL( + const shared_ptr & session, + const shared_ptr & sok + ); + ~TLSSocket_OpenSSL(); diff --git a/src/vmime/net/tracer.cpp b/src/vmime/net/tracer.cpp index b3610cdd..66afb360 100644 --- a/src/vmime/net/tracer.cpp +++ b/src/vmime/net/tracer.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard +// Copyright (C) 2002 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 @@ -37,13 +37,14 @@ namespace vmime { namespace net { -void tracer::traceReceiveBytes(const size_t count, const string& state) -{ +void tracer::traceReceiveBytes(const size_t count, const string& state) { + std::ostringstream oss; oss << "{..."; - if (!state.empty()) + if (!state.empty()) { oss << state << ": "; + } oss << count << " bytes of data...}"; @@ -51,13 +52,14 @@ void tracer::traceReceiveBytes(const size_t count, const string& state) } -void tracer::traceSendBytes(const size_t count, const string& state) -{ +void tracer::traceSendBytes(const size_t count, const string& state) { + std::ostringstream oss; oss << "{..."; - if (!state.empty()) + if (!state.empty()) { oss << state << ": "; + } oss << count << " bytes of data...}"; diff --git a/src/vmime/net/tracer.hpp b/src/vmime/net/tracer.hpp index 853455a3..74724630 100644 --- a/src/vmime/net/tracer.hpp +++ b/src/vmime/net/tracer.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard +// Copyright (C) 2002 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 @@ -44,12 +44,13 @@ class service; /** Base class for an object used to trace network communication * between the client and the server. */ +class VMIME_EXPORT tracer : public object { -class VMIME_EXPORT tracer : public object -{ public: - virtual ~tracer() { } + virtual ~tracer() { + + } /** Trace raw bytes which have been received. * @@ -79,15 +80,15 @@ public: }; - /** A class to create 'tracer' objects. */ +class VMIME_EXPORT tracerFactory : public object { -class VMIME_EXPORT tracerFactory : public object -{ public: - virtual ~tracerFactory() { } + virtual ~tracerFactory() { + + } /** Creates a tracer for the specified service. * diff --git a/src/vmime/net/transport.cpp b/src/vmime/net/transport.cpp index 1b69995c..f87648a3 100644 --- a/src/vmime/net/transport.cpp +++ b/src/vmime/net/transport.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,30 +43,34 @@ namespace vmime { namespace net { -transport::transport(const shared_ptr & sess, const serviceInfos& infos, const shared_ptr & auth) - : service(sess, infos, auth) -{ +transport::transport( + const shared_ptr & sess, + const serviceInfos& infos, + const shared_ptr & auth +) + : service(sess, infos, auth) { + } -shared_ptr transport::processHeaderField(const shared_ptr & field) -{ - if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::BCC)) - { +shared_ptr transport::processHeaderField(const shared_ptr & field) { + + if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::BCC)) { + // Remove Bcc headers from the message, as required by the RFC. // Some SMTP server automatically strip this header (Postfix, qmail), // and others have an option for this (Exim). return null; - } - else if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::RETURN_PATH)) - { + + } else if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::RETURN_PATH)) { + // RFC-2821: Return-Path header is added by the final transport system // that delivers the message to its recipient. Then, it should not be // transmitted to MSA. return null; - } - else if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::ORIGINAL_RECIPIENT)) - { + + } else if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::ORIGINAL_RECIPIENT)) { + // RFC-2298: Delivering MTA may add the Original-Recipient header and // discard existing one; so, no need to send it. return null; @@ -77,59 +81,71 @@ shared_ptr transport::processHeaderField(const shared_ptr & header) -{ - if (header->getFieldCount() == 0) +void transport::processHeader(const shared_ptr
& header) { + + if (header->getFieldCount() == 0) { return; + } // Remove/replace fields - for (size_t idx = header->getFieldCount() ; idx != 0 ; --idx) - { + for (size_t idx = header->getFieldCount() ; idx != 0 ; --idx) { + shared_ptr field = header->getFieldAt(idx - 1); shared_ptr newField = processHeaderField(field); - if (newField == NULL) + if (newField == NULL) { header->removeField(field); - else if (newField != field) + } else if (newField != field) { header->replaceField(field, newField); + } } // Add missing header fields // -- Date - if (!header->hasField(fields::DATE)) + if (!header->hasField(fields::DATE)) { header->Date()->setValue(datetime::now()); + } // -- Mime-Version - if (!header->hasField(fields::MIME_VERSION)) + if (!header->hasField(fields::MIME_VERSION)) { header->MimeVersion()->setValue(string(SUPPORTED_MIME_VERSION)); + } // -- Message-Id - if (!header->hasField(fields::MESSAGE_ID)) + if (!header->hasField(fields::MESSAGE_ID)) { header->MessageId()->setValue(messageId::generateId()); -} - - -static void extractMailboxes - (mailboxList& recipients, const addressList& list) -{ - for (size_t i = 0 ; i < list.getAddressCount() ; ++i) - { - shared_ptr mbox = dynamicCast (list.getAddressAt(i)->clone()); - - if (mbox != NULL) - recipients.appendMailbox(mbox); } } -void transport::send(const shared_ptr & msg, utility::progressListener* progress) -{ +static void extractMailboxes( + mailboxList& recipients, + const addressList& list +) { + + for (size_t i = 0 ; i < list.getAddressCount() ; ++i) { + + shared_ptr mbox = dynamicCast (list.getAddressAt(i)->clone()); + + if (mbox) { + recipients.appendMailbox(mbox); + } + } +} + + +void transport::send( + const shared_ptr & msg, + utility::progressListener* progress +) { + // Extract expeditor shared_ptr fromMbox = msg->getHeader()->findFieldValue (fields::FROM); - if (!fromMbox) + if (!fromMbox) { throw exceptions::no_expeditor(); + } mailbox expeditor = *fromMbox; @@ -139,10 +155,11 @@ void transport::send(const shared_ptr & msg, utility::progressLi mailbox sender; - if (!senderMbox) + if (!senderMbox) { sender = expeditor; - else + } else { sender = *senderMbox; + } // Extract recipients mailboxList recipients; @@ -151,22 +168,23 @@ void transport::send(const shared_ptr & msg, utility::progressLi shared_ptr addresses = msg->getHeader()->findFieldValue (fields::TO); - if (addresses) + if (addresses) { extractMailboxes(recipients, *addresses); + } // -- "Cc" field - addresses = - msg->getHeader()->findFieldValue (fields::CC); + addresses = msg->getHeader()->findFieldValue (fields::CC); - if (addresses) + if (addresses) { extractMailboxes(recipients, *addresses); + } // -- "Bcc" field - addresses = - msg->getHeader()->findFieldValue (fields::BCC); + addresses = msg->getHeader()->findFieldValue (fields::BCC); - if (addresses) + if (addresses) { extractMailboxes(recipients, *addresses); + } // Process message header by removing fields that should be removed // before transmitting the message to MSA, and adding missing fields @@ -177,18 +195,21 @@ void transport::send(const shared_ptr & msg, utility::progressLi // To avoid cloning message body (too much overhead), use processed // header during the time we are generating the message to a stream. // Revert it back to original header after. - struct XChangeMsgHeader - { - XChangeMsgHeader(const shared_ptr & _msg, - const shared_ptr & _hdr) - : msg(_msg), hdr(msg->getHeader()) - { + struct XChangeMsgHeader { + + XChangeMsgHeader( + const shared_ptr & _msg, + const shared_ptr & _hdr + ) + : msg(_msg), + hdr(msg->getHeader()) { + // Set new header msg->setHeader(_hdr); } - ~XChangeMsgHeader() - { + ~XChangeMsgHeader() { + // Revert original header msg->setHeader(hdr); } @@ -197,16 +218,21 @@ void transport::send(const shared_ptr & msg, utility::progressLi shared_ptr msg; shared_ptr hdr; + } headerExchanger(msg, hdr); send(msg, expeditor, recipients, progress, sender); } -void transport::send - (const shared_ptr & msg, const mailbox& expeditor, const mailboxList& recipients, - utility::progressListener* progress, const mailbox& sender) -{ +void transport::send( + const shared_ptr & msg, + const mailbox& expeditor, + const mailboxList& recipients, + utility::progressListener* progress, + const mailbox& sender +) { + // Generate the message, "stream" it and delegate the sending // to the generic send() function. std::ostringstream oss; @@ -222,9 +248,9 @@ void transport::send } -transport::Type transport::getType() const -{ - return (TYPE_TRANSPORT); +transport::Type transport::getType() const { + + return TYPE_TRANSPORT; } diff --git a/src/vmime/net/transport.hpp b/src/vmime/net/transport.hpp index a54f041e..2f9878d0 100644 --- a/src/vmime/net/transport.hpp +++ b/src/vmime/net/transport.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -51,12 +51,15 @@ namespace net { /** A transport service. * Encapsulate protocols that can send messages. */ +class VMIME_EXPORT transport : public service { -class VMIME_EXPORT transport : public service -{ protected: - transport(const shared_ptr & sess, const serviceInfos& infos, const shared_ptr & auth); + transport( + const shared_ptr & sess, + const serviceInfos& infos, + const shared_ptr & auth + ); public: @@ -67,7 +70,10 @@ public: * @param msg message to send * @param progress progress listener, or NULL if not used */ - virtual void send(const shared_ptr & msg, utility::progressListener* progress = NULL); + virtual void send( + const shared_ptr & msg, + utility::progressListener* progress = NULL + ); /** Send a message over this transport service. * @@ -78,13 +84,14 @@ public: * @param progress progress listener, or NULL if not used * @param sender envelope sender (if empty, expeditor will be used) */ - virtual void send - (const mailbox& expeditor, - const mailboxList& recipients, - utility::inputStream& is, - const size_t size, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()) = 0; + virtual void send( + const mailbox& expeditor, + const mailboxList& recipients, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox() + ) = 0; /** Send a message over this transport service. * The default implementation simply generates the whole message into @@ -96,12 +103,13 @@ public: * @param progress progress listener, or NULL if not used * @param sender envelope sender (if empty, expeditor will be used) */ - virtual void send - (const shared_ptr & msg, - const mailbox& expeditor, - const mailboxList& recipients, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()); + virtual void send( + const shared_ptr & msg, + const mailbox& expeditor, + const mailboxList& recipients, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox() + ); Type getType() const; diff --git a/src/vmime/object.cpp b/src/vmime/object.cpp index d07c3c19..f61b2ac9 100644 --- a/src/vmime/object.cpp +++ b/src/vmime/object.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -25,28 +25,27 @@ #include "vmime/object.hpp" -namespace vmime -{ +namespace vmime { -object::object() -{ +object::object() { + } -object::object(const object&) -{ +object::object(const object&) { + } -object& object::operator=(const object&) -{ +object& object::operator=(const object&) { + return *this; } -object::~object() -{ +object::~object() { + } diff --git a/src/vmime/object.hpp b/src/vmime/object.hpp index ecaafc1e..5869d383 100644 --- a/src/vmime/object.hpp +++ b/src/vmime/object.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,15 +28,13 @@ #include "vmime/types.hpp" -namespace vmime -{ +namespace vmime { /** Base object for all objects in the library. */ +class VMIME_EXPORT object { -class VMIME_EXPORT object -{ protected: object(); @@ -52,4 +50,3 @@ protected: #endif // VMIME_OBJECT_HPP_INCLUDED - diff --git a/src/vmime/parameter.cpp b/src/vmime/parameter.cpp index bba43f50..41b37a46 100644 --- a/src/vmime/parameter.cpp +++ b/src/vmime/parameter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,36 +31,38 @@ #include "vmime/utility/outputStreamStringAdapter.hpp" -namespace vmime -{ +namespace vmime { parameter::parameter(const string& name) - : m_name(name), m_value(make_shared ()) -{ + : m_name(name), + m_value(make_shared ()) { + } parameter::parameter(const string& name, const word& value) - : m_name(name), m_value(make_shared (value)) -{ + : m_name(name), + m_value(make_shared (value)) { + } parameter::parameter(const string& name, const string& value) - : m_name(name), m_value(make_shared (value)) -{ + : m_name(name), + m_value(make_shared (value)) { + } parameter::parameter(const parameter&) - : component() -{ + : component() { + } -shared_ptr parameter::clone() const -{ +shared_ptr parameter::clone() const { + shared_ptr p = make_shared (m_name); p->copyFrom(*this); @@ -68,8 +70,8 @@ shared_ptr parameter::clone() const } -void parameter::copyFrom(const component& other) -{ +void parameter::copyFrom(const component& other) { + const parameter& param = dynamic_cast (other); m_name = param.m_name; @@ -77,27 +79,27 @@ void parameter::copyFrom(const component& other) } -parameter& parameter::operator=(const parameter& other) -{ +parameter& parameter::operator=(const parameter& other) { + copyFrom(other); return (*this); } -const string& parameter::getName() const -{ +const string& parameter::getName() const { + return m_name; } -const word& parameter::getValue() const -{ +const word& parameter::getValue() const { + return *m_value; } -void parameter::setValue(const component& value) -{ +void parameter::setValue(const component& value) { + std::ostringstream oss; utility::outputStreamAdapter vos(oss); @@ -107,30 +109,39 @@ void parameter::setValue(const component& value) } -void parameter::setValue(const word& value) -{ +void parameter::setValue(const word& value) { + *m_value = value; } -void parameter::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void parameter::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + m_value->setBuffer(string(buffer.begin() + position, buffer.begin() + end)); - if (ctx.getInternationalizedEmailSupport()) + if (ctx.getInternationalizedEmailSupport()) { m_value->setCharset(charset(charsets::UTF_8)); - else + } else { m_value->setCharset(charset(charsets::US_ASCII)); + } - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void parameter::parse(const parsingContext& ctx, const std::vector & chunks) -{ +void parameter::parse( + const parsingContext& ctx, + const std::vector & chunks +) { + bool foundCharsetChunk = false; charset ch(charsets::US_ASCII); @@ -139,29 +150,30 @@ void parameter::parse(const parsingContext& ctx, const std::vector & std::ostringstream value; value.imbue(std::locale::classic()); - for (std::vector ::size_type i = 0 ; i < chunks.size() ; ++i) - { + for (std::vector ::size_type i = 0 ; i < chunks.size() ; ++i) { + const valueChunk& chunk = chunks[i]; // Decode following data - if (chunk.encoded) - { + if (chunk.encoded) { + const size_t len = chunk.data.length(); size_t pos = 0; // If this is the first encoded chunk, extract charset // and language information - if (!foundCharsetChunk) - { + if (!foundCharsetChunk) { + // Eg. "us-ascii'en'This%20is%20even%20more%20" size_t q = chunk.data.find_first_of('\''); - if (q != string::npos) - { + if (q != string::npos) { + const string chs = chunk.data.substr(0, q); - if (!chs.empty()) + if (!chs.empty()) { ch = charset(chs); + } ++q; pos = q; @@ -169,8 +181,8 @@ void parameter::parse(const parsingContext& ctx, const std::vector & q = chunk.data.find_first_of('\'', pos); - if (q != string::npos) - { + if (q != string::npos) { + // Extract language lang = chunk.data.substr(pos, q - pos); @@ -181,59 +193,59 @@ void parameter::parse(const parsingContext& ctx, const std::vector & foundCharsetChunk = true; } - for (size_t i = pos ; i < len ; ++i) - { + for (size_t i = pos ; i < len ; ++i) { + const char c = chunk.data[i]; - if (c == '%' && i + 2 < len) - { + if (c == '%' && i + 2 < len) { + unsigned int v = 0; // First char - switch (chunk.data[i + 1]) - { - case 'a': case 'A': v += 10; break; - case 'b': case 'B': v += 11; break; - case 'c': case 'C': v += 12; break; - case 'd': case 'D': v += 13; break; - case 'e': case 'E': v += 14; break; - case 'f': case 'F': v += 15; break; - default: // assume 0-9 + switch (chunk.data[i + 1]) { - v += (chunk.data[i + 1] - '0'); - break; + case 'a': case 'A': v += 10; break; + case 'b': case 'B': v += 11; break; + case 'c': case 'C': v += 12; break; + case 'd': case 'D': v += 13; break; + case 'e': case 'E': v += 14; break; + case 'f': case 'F': v += 15; break; + default: // assume 0-9 + + v += (chunk.data[i + 1] - '0'); + break; } v *= 16; // Second char - switch (chunk.data[i + 2]) - { - case 'a': case 'A': v += 10; break; - case 'b': case 'B': v += 11; break; - case 'c': case 'C': v += 12; break; - case 'd': case 'D': v += 13; break; - case 'e': case 'E': v += 14; break; - case 'f': case 'F': v += 15; break; - default: // assume 0-9 + switch (chunk.data[i + 2]) { - v += (chunk.data[i + 2] - '0'); - break; + case 'a': case 'A': v += 10; break; + case 'b': case 'B': v += 11; break; + case 'c': case 'C': v += 12; break; + case 'd': case 'D': v += 13; break; + case 'e': case 'E': v += 14; break; + case 'f': case 'F': v += 15; break; + default: // assume 0-9 + + v += (chunk.data[i + 2] - '0'); + break; } value << static_cast (v); i += 2; // skip next 2 chars - } - else - { + + } else { + value << c; } } - } + // Simply copy data, as it is not encoded - else - { + } else { + // This syntax is non-standard (expressly prohibited // by RFC-2047), but is used by Mozilla: // @@ -246,20 +258,20 @@ void parameter::parse(const parsingContext& ctx, const std::vector & vmime::text t; t.parse(ctx, chunk.data); - if (t.getWordCount() != 0) - { + if (t.getWordCount() != 0) { + value << t.getWholeBuffer(); - if (!foundCharsetChunk) - { + if (!foundCharsetChunk) { + // This is still wrong. Each word can have it's own charset, and can // be mixed (eg. iso-8859-1 and iso-2022-jp), but very unlikely. Real // fix is to have parameters store a vmime::text instead of a // vmime::word in m_value. But that changes the interface. - for (size_t i = 0 ; i < t.getWordCount() ; ++i) - { - if (t.getWordAt(i)->getCharset() != ch && ch == charsets::US_ASCII) - { + for (size_t i = 0 ; i < t.getWordCount() ; ++i) { + + if (t.getWordAt(i)->getCharset() != ch && ch == charsets::US_ASCII) { + ch = t.getWordAt(i)->getCharset(); break; } @@ -275,10 +287,13 @@ void parameter::parse(const parsingContext& ctx, const std::vector & } -void parameter::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void parameter::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + const string& name = m_name; const string& value = m_value->getBuffer(); @@ -305,8 +320,8 @@ void parameter::generateImpl size_t pos = curLinePos; - if (pos + name.length() + 10 + value.length() > ctx.getMaxLineLength()) - { + if (pos + name.length() + 10 + value.length() > ctx.getMaxLineLength()) { + sevenBitStream << NEW_LINE_SEQUENCE; pos = NEW_LINE_SEQUENCE_LENGTH; } @@ -316,54 +331,53 @@ void parameter::generateImpl size_t valueLength = 0; // Use worst-case length name.length()+2 for 'name=' part of line - for (size_t i = 0 ; (i < value.length()) && (pos + name.length() + 2 + valueLength < ctx.getMaxLineLength() - 4) ; ++i, ++valueLength) - { - switch (value[i]) - { - // Characters that need to be quoted _and_ escaped - case '"': - case '\\': - // Other characters that need quoting - case ' ': - case '\t': - case '(': - case ')': - case '<': - case '>': - case '@': - case ',': - case ';': - case ':': - case '/': - case '[': - case ']': - case '?': - case '=': + for (size_t i = 0 ; (i < value.length()) && (pos + name.length() + 2 + valueLength < ctx.getMaxLineLength() - 4) ; ++i, ++valueLength) { - needQuoting = true; - break; + switch (value[i]) { - default: + // Characters that need to be quoted _and_ escaped + case '"': + case '\\': + // Other characters that need quoting + case ' ': + case '\t': + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '/': + case '[': + case ']': + case '?': + case '=': - if (!parserHelpers::isAscii(value[i])) - { - needQuotedPrintable = true; needQuoting = true; - } + break; - break; + default: + + if (!parserHelpers::isAscii(value[i])) { + needQuotedPrintable = true; + needQuoting = true; + } + + break; } } const bool cutValue = (valueLength != value.length()); // has the value been cut? - if (needQuoting) - { + if (needQuoting) { + sevenBitStream << name << "=\""; pos += name.length() + 2; - } - else - { + + } else { + sevenBitStream << name << "="; pos += name.length() + 1; } @@ -377,51 +391,51 @@ void parameter::generateImpl bool extended = alwaysEncode; if ((needQuotedPrintable || cutValue || !m_value->getLanguage().empty()) && - genMode != generationContext::PARAMETER_VALUE_NO_ENCODING) - { + genMode != generationContext::PARAMETER_VALUE_NO_ENCODING) { + // Send the name in quoted-printable, so outlook express et.al. // will understand the real filename size_t oldLen = sevenBitBuffer.length(); m_value->generate(sevenBitStream); pos += sevenBitBuffer.length() - oldLen; extended = true; // also send with RFC-2231 encoding - } - else - { + + } else { + // Do not chop off this value, but just add the complete name as one header line. for (size_t i = 0, n = value.length(), curValueLength = 0 ; - i < n && curValueLength < valueLength ; ++i) - { + i < n && curValueLength < valueLength ; ++i) { + const char_t c = value[i]; - if (/* needQuoting && */ (c == '"' || c == '\\')) // 'needQuoting' is implicit - { + if (/* needQuoting && */ (c == '"' || c == '\\')) { // 'needQuoting' is implicit + sevenBitStream << '\\' << value[i]; // escape 'x' with '\x' pos += 2; - } - else if (parserHelpers::isAscii(c)) - { + + } else if (parserHelpers::isAscii(c)) { + sevenBitStream << value[i]; ++pos; ++curValueLength; - } - else - { + + } else { + extended = true; } } } // !needQuotedPrintable - if (needQuoting) - { + if (needQuoting) { + sevenBitStream << '"'; ++pos; } if (genMode == generationContext::PARAMETER_VALUE_RFC2047_ONLY || - genMode == generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047) - { + genMode == generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047) { + os << sevenBitBuffer; } @@ -429,16 +443,16 @@ void parameter::generateImpl // or is too long for a single line if ((extended || cutValue) && genMode != generationContext::PARAMETER_VALUE_NO_ENCODING && - genMode != generationContext::PARAMETER_VALUE_RFC2047_ONLY) - { + genMode != generationContext::PARAMETER_VALUE_RFC2047_ONLY) { + + + if (genMode == generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047) { - if (genMode == generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047) - { os << ';'; ++pos; - } - else - { + + } else { + // The data output to 'sevenBitBuffer' will be discarded in this case pos = curLinePos; } @@ -466,8 +480,8 @@ void parameter::generateImpl name.length() + 4 /* *0*= */ + 2 /* '' */ + m_value->getCharset().getName().length(); - if (pos + firstSectionLength + 5 >= ctx.getMaxLineLength()) - { + if (pos + firstSectionLength + 5 >= ctx.getMaxLineLength()) { + os << NEW_LINE_SEQUENCE; pos = NEW_LINE_SEQUENCE_LENGTH; } @@ -479,61 +493,60 @@ void parameter::generateImpl string currentSection; size_t currentSectionLength = firstSectionLength; - for (size_t i = 0 ; i < value.length() ; ++i) - { + for (size_t i = 0 ; i < value.length() ; ++i) { + // Check whether we should start a new line (taking into // account the next character will be encoded = worst case) - if (currentSectionLength + 3 >= ctx.getMaxLineLength()) - { + if (currentSectionLength + 3 >= ctx.getMaxLineLength()) { + sectionText.push_back(currentSection); sectionCount++; currentSection.clear(); - currentSectionLength = NEW_LINE_SEQUENCE_LENGTH - + name.length() + 6; + currentSectionLength = NEW_LINE_SEQUENCE_LENGTH + name.length() + 6; } // Output next character const char_t c = value[i]; bool encode = false; - switch (c) - { - // special characters - case ' ': - case '\t': - case '\r': - case '\n': - case '%': - case '"': - case ';': - case ',': - case '(': - case ')': - case '<': - case '>': - case '@': - case ':': - case '/': - case '[': - case ']': - case '?': - case '=': + switch (c) { - encode = true; - break; + // special characters + case ' ': + case '\t': + case '\r': + case '\n': + case '%': + case '"': + case ';': + case ',': + case '(': + case ')': + case '<': + case '>': + case '@': + case ':': + case '/': + case '[': + case ']': + case '?': + case '=': - default: + encode = true; + break; - encode = (!parserHelpers::isPrint(c) || - !parserHelpers::isAscii(c) || - alwaysEncode); + default: - break; + encode = (!parserHelpers::isPrint(c) || + !parserHelpers::isAscii(c) || + alwaysEncode); + + break; } - if (encode) // need encoding - { + if (encode) { // need encoding + const int h1 = static_cast (c) / 16; const int h2 = static_cast (c) % 16; @@ -543,9 +556,9 @@ void parameter::generateImpl pos += 3; currentSectionLength += 3; - } - else - { + + } else { + currentSection += value[i]; ++pos; @@ -553,44 +566,44 @@ void parameter::generateImpl } } - if (!currentSection.empty()) - { + if (!currentSection.empty()) { + sectionText.push_back(currentSection); sectionCount++; } // Output sections - for (int sectionNumber = 0 ; sectionNumber < sectionCount ; ++sectionNumber) - { + for (int sectionNumber = 0 ; sectionNumber < sectionCount ; ++sectionNumber) { + os << name; - if (sectionCount != 1) // no section specifier when only a single one - { + if (sectionCount != 1) { // no section specifier when only a single one + os << '*'; os << sectionNumber; } os << "*="; - if (sectionNumber == 0) - { + if (sectionNumber == 0) { + os << m_value->getCharset().getName(); os << '\'' << /* No language */ '\''; } os << sectionText[sectionNumber]; - if (sectionNumber + 1 < sectionCount) - { + if (sectionNumber + 1 < sectionCount) { + os << ';'; os << NEW_LINE_SEQUENCE; pos = NEW_LINE_SEQUENCE_LENGTH; } } - } - else if (!(genMode == generationContext::PARAMETER_VALUE_RFC2047_ONLY || - genMode == generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047)) - { + + } else if (!(genMode == generationContext::PARAMETER_VALUE_RFC2047_ONLY || + genMode == generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047)) { + // The value does not contain 8-bit characters and // is short enough for a single line. // "7bit/us-ascii" will suffice in this case. @@ -599,13 +612,14 @@ void parameter::generateImpl os << sevenBitBuffer; } - if (newLinePos) + if (newLinePos) { *newLinePos = pos; + } } -size_t parameter::getGeneratedSize(const generationContext& ctx) -{ +size_t parameter::getGeneratedSize(const generationContext& ctx) { + const string& name = m_name; const string& value = m_value->getBuffer(); @@ -638,8 +652,8 @@ size_t parameter::getGeneratedSize(const generationContext& ctx) } -const std::vector > parameter::getChildComponents() -{ +const std::vector > parameter::getChildComponents() { + std::vector > list; list.push_back(m_value); @@ -649,4 +663,3 @@ const std::vector > parameter::getChildComponents() } // vmime - diff --git a/src/vmime/parameter.hpp b/src/vmime/parameter.hpp index 92ac95d7..f965bade 100644 --- a/src/vmime/parameter.hpp +++ b/src/vmime/parameter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,12 +30,11 @@ #include "vmime/word.hpp" -namespace vmime -{ +namespace vmime { -class VMIME_EXPORT parameter : public component -{ +class VMIME_EXPORT parameter : public component { + friend class parameterizedHeaderField; private: @@ -73,8 +72,7 @@ public: * as defined in RFC-2231/3. This is used when * calling parse() on the parameter. */ - struct valueChunk - { + struct valueChunk { bool encoded; string data; }; @@ -121,8 +119,8 @@ public: * @return value */ template - const T getValueAs() const - { + const T getValueAs() const { + T ret; ret.parse(m_value->getBuffer()); @@ -144,22 +142,27 @@ public: protected: - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; private: - void parse(const parsingContext& ctx, const std::vector & chunks); + void parse( + const parsingContext& ctx, + const std::vector & chunks + ); string m_name; diff --git a/src/vmime/parameterizedHeaderField.cpp b/src/vmime/parameterizedHeaderField.cpp index 0d90692b..6815fad1 100644 --- a/src/vmime/parameterizedHeaderField.cpp +++ b/src/vmime/parameterizedHeaderField.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -26,17 +26,16 @@ #include "vmime/parserHelpers.hpp" -namespace vmime -{ +namespace vmime { -parameterizedHeaderField::parameterizedHeaderField() -{ +parameterizedHeaderField::parameterizedHeaderField() { + } -parameterizedHeaderField::~parameterizedHeaderField() -{ +parameterizedHeaderField::~parameterizedHeaderField() { + removeAllParameters(); } @@ -67,8 +66,8 @@ parameterizedHeaderField::~parameterizedHeaderField() #ifndef VMIME_BUILDING_DOC -struct paramInfo -{ +struct paramInfo { + bool extended; std::vector value; size_t start; @@ -78,10 +77,14 @@ struct paramInfo #endif // VMIME_BUILDING_DOC -void parameterizedHeaderField::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void parameterizedHeaderField::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + const char* const pend = buffer.data() + end; const char* const pstart = buffer.data() + position; const char* p = pstart; @@ -89,8 +92,7 @@ void parameterizedHeaderField::parseImpl // Skip non-significant whitespaces size_t valueStart = position; - while (p < pend && parserHelpers::isSpace(*p)) - { + while (p < pend && parserHelpers::isSpace(*p)) { ++p; ++valueStart; } @@ -98,15 +100,16 @@ void parameterizedHeaderField::parseImpl // Advance up to ';', if any size_t valueLength = 0; - while (p < pend && *p != ';' && (!parserHelpers::isSpace(*p))) // FIXME: support ";" inside quoted or RFC-2047-encoded text - { + while (p < pend && *p != ';' && (!parserHelpers::isSpace(*p))) { // FIXME: support ";" inside quoted or RFC-2047-encoded text + ++p; ++valueLength; } // Trim whitespaces at the end of the value - while (valueLength > 0 && parserHelpers::isSpace(buffer[valueStart + valueLength - 1])) + while (valueLength > 0 && parserHelpers::isSpace(buffer[valueStart + valueLength - 1])) { --valueLength; + } // Parse value getValue()->parse(ctx, buffer, valueStart, valueStart + valueLength); @@ -115,18 +118,19 @@ void parameterizedHeaderField::parseImpl removeAllParameters(); // If there is one or more parameters following... - if (p < pend) - { + if (p < pend) { + std::map params; - if (*p != ';') - { - while (p < pend && *p != ';') // FIXME: support ";" inside quoted or RFC-2047-encoded text + if (*p != ';') { + + while (p < pend && *p != ';') { // FIXME: support ";" inside quoted or RFC-2047-encoded text ++p; + } } - while (*p == ';') - { + while (*p == ';') { + // Skip ';' ++p; @@ -134,24 +138,26 @@ void parameterizedHeaderField::parseImpl const size_t attrStart = position + (p - pstart); - while (p < pend && !(*p == ';' || *p == '=')) + while (p < pend && !(*p == ';' || *p == '=')) { ++p; + } + + if (p >= pend || *p == ';') { - if (p >= pend || *p == ';') - { // Hmmmm... we didn't found an '=' sign. // This parameter may not be valid so try to advance // to the next one, if there is one. while (p < pend && *p != ';') ++p; - } - else - { + + } else { + // Extract the attribute name size_t attrEnd = position + (p - pstart); - while (attrEnd != attrStart && parserHelpers::isSpace(buffer[attrEnd - 1])) + while (attrEnd != attrStart && parserHelpers::isSpace(buffer[attrEnd - 1])) { --attrEnd; + } // Skip '=' ++p; @@ -163,8 +169,8 @@ void parameterizedHeaderField::parseImpl string value; // -- this is a quoted-string - if (*p == '"') - { + if (*p == '"') { + // Skip '"' ++p; @@ -175,74 +181,84 @@ void parameterizedHeaderField::parseImpl std::ostringstream ss; size_t start = position + (p - pstart); - for ( ; p < pend && !stop ; ++p) - { - if (escape) - { + for ( ; p < pend && !stop ; ++p) { + + if (escape) { + escape = false; start = position + (p - pstart); - } - else - { - switch (*p) - { - case '"': - { - ss << string(buffer.begin() + start, - buffer.begin() + position + (p - pstart)); - stop = true; - break; - } - case '\\': - { - ss << string(buffer.begin() + start, - buffer.begin() + position + (p - pstart)); + } else { - escape = true; - break; - } + switch (*p) { + + case '"': { + + ss << string( + buffer.begin() + start, + buffer.begin() + position + (p - pstart) + ); + + stop = true; + break; + } + case '\\': { + + ss << string( + buffer.begin() + start, + buffer.begin() + position + (p - pstart) + ); + + escape = true; + break; + } } } } - if (!stop) - { - ss << string(buffer.begin() + start, - buffer.begin() + position + (p - pstart)); + if (!stop) { + + ss << string( + buffer.begin() + start, + buffer.begin() + position + (p - pstart) + ); } value = ss.str(); - } + // -- the value is a simple token - else - { + } else { + const size_t valStart = position + (p - pstart); - while (p < pend && *p != ';') + while (p < pend && *p != ';') { ++p; + } size_t valEnd = position + (p - pstart); - while (valEnd != valStart && parserHelpers::isSpace(buffer[valEnd - 1])) + while (valEnd != valStart && parserHelpers::isSpace(buffer[valEnd - 1])) { --valEnd; + } - value = string(buffer.begin() + valStart, - buffer.begin() + valEnd); + value = string( + buffer.begin() + valStart, + buffer.begin() + valEnd + ); } // Don't allow ill-formed parameters - if (attrStart != attrEnd && value.length()) - { + if (attrStart != attrEnd && value.length()) { + string name(buffer.begin() + attrStart, buffer.begin() + attrEnd); // Check for RFC-2231 extended parameters bool extended = false; bool encoded = false; - if (name[name.length() - 1] == '*') - { + if (name[name.length() - 1] == '*') { + name.erase(name.end() - 1, name.end()); extended = true; @@ -252,15 +268,15 @@ void parameterizedHeaderField::parseImpl // Check for RFC-2231 multi-section parameters const size_t star = name.find_last_of('*'); - if (star != string::npos) - { + if (star != string::npos) { + bool allDigits = true; - for (size_t i = star + 1 ; allDigits && (i < name.length()) ; ++i) + for (size_t i = star + 1 ; allDigits && (i < name.length()) ; ++i) { allDigits = parserHelpers::isDigit(name[i]); + } - if (allDigits) - { + if (allDigits) { name.erase(name.begin() + star, name.end()); extended = true; } @@ -273,13 +289,13 @@ void parameterizedHeaderField::parseImpl // Add/replace/modify the parameter const std::map ::iterator it = params.find(name); - if (it != params.end()) - { + if (it != params.end()) { + paramInfo& info = (*it).second; // An extended parameter replaces a normal one - if (!info.extended) - { + if (!info.extended) { + info.extended = extended; info.value.clear(); info.start = attrStart; @@ -292,9 +308,9 @@ void parameterizedHeaderField::parseImpl info.value.push_back(chunk); info.end = position + (p - pstart); - } - else - { + + } else { + parameter::valueChunk chunk; chunk.encoded = encoded; chunk.data = value; @@ -316,8 +332,8 @@ void parameterizedHeaderField::parseImpl } for (std::map ::const_iterator it = params.begin() ; - it != params.end() ; ++it) - { + it != params.end() ; ++it) { + const paramInfo& info = (*it).second; // Append this parameter to the list @@ -330,15 +346,19 @@ void parameterizedHeaderField::parseImpl } } - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void parameterizedHeaderField::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void parameterizedHeaderField::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + size_t pos = curLinePos; // Parent header field @@ -346,16 +366,17 @@ void parameterizedHeaderField::generateImpl // Parameters for (std::vector >::const_iterator - it = m_params.begin() ; it != m_params.end() ; ++it) - { + it = m_params.begin() ; it != m_params.end() ; ++it) { + os << "; "; pos += 2; (*it)->generate(ctx, os, pos, &pos); } - if (newLinePos) + if (newLinePos) { *newLinePos = pos; + } } @@ -364,8 +385,8 @@ size_t parameterizedHeaderField::getGeneratedSize(const generationContext& ctx) size_t size = headerField::getGeneratedSize(ctx); for (std::vector >::const_iterator - it = m_params.begin() ; it != m_params.end() ; ++it) - { + it = m_params.begin() ; it != m_params.end() ; ++it) { + size += 2; // "; " size += (*it)->getGeneratedSize(ctx); } @@ -374,8 +395,8 @@ size_t parameterizedHeaderField::getGeneratedSize(const generationContext& ctx) } -void parameterizedHeaderField::copyFrom(const component& other) -{ +void parameterizedHeaderField::copyFrom(const component& other) { + headerField::copyFrom(other); const parameterizedHeaderField& source = dynamic_cast(other); @@ -383,22 +404,22 @@ void parameterizedHeaderField::copyFrom(const component& other) removeAllParameters(); for (std::vector >::const_iterator i = source.m_params.begin() ; - i != source.m_params.end() ; ++i) - { + i != source.m_params.end() ; ++i) { + appendParameter(vmime::clone(*i)); } } -parameterizedHeaderField& parameterizedHeaderField::operator=(const parameterizedHeaderField& other) -{ +parameterizedHeaderField& parameterizedHeaderField::operator=(const parameterizedHeaderField& other) { + copyFrom(other); - return (*this); + return *this; } -bool parameterizedHeaderField::hasParameter(const string& paramName) const -{ +bool parameterizedHeaderField::hasParameter(const string& paramName) const { + const string name = utility::stringUtils::toLower(paramName); std::vector >::const_iterator pos = m_params.begin(); @@ -406,12 +427,12 @@ bool parameterizedHeaderField::hasParameter(const string& paramName) const for ( ; pos != end && utility::stringUtils::toLower((*pos)->getName()) != name ; ++pos) {} - return (pos != end); + return pos != end; } -shared_ptr parameterizedHeaderField::findParameter(const string& paramName) const -{ +shared_ptr parameterizedHeaderField::findParameter(const string& paramName) const { + const string name = utility::stringUtils::toLower(paramName); // Find the first parameter that matches the specified name @@ -421,16 +442,17 @@ shared_ptr parameterizedHeaderField::findParameter(const string& par for ( ; pos != end && utility::stringUtils::toLower((*pos)->getName()) != name ; ++pos) {} // No parameter with this name can be found - if (pos == end) + if (pos == end) { return null; + } // Else, return a reference to the existing parameter - return (*pos); + return *pos; } -shared_ptr parameterizedHeaderField::getParameter(const string& paramName) -{ +shared_ptr parameterizedHeaderField::getParameter(const string& paramName) { + const string name = utility::stringUtils::toLower(paramName); // Find the first parameter that matches the specified name @@ -440,154 +462,171 @@ shared_ptr parameterizedHeaderField::getParameter(const string& para for ( ; pos != end && utility::stringUtils::toLower((*pos)->getName()) != name ; ++pos) {} // If no parameter with this name can be found, create a new one - if (pos == end) - { + if (pos == end) { + shared_ptr param = make_shared (paramName); appendParameter(param); // Return a reference to the new parameter - return (param); - } + return param; + // Else, return a reference to the existing parameter - else - { - return (*pos); + } else { + + return *pos; } } -void parameterizedHeaderField::appendParameter(const shared_ptr & param) -{ +void parameterizedHeaderField::appendParameter(const shared_ptr & param) { + m_params.push_back(param); } -void parameterizedHeaderField::insertParameterBefore(const shared_ptr & beforeParam, const shared_ptr & param) -{ - const std::vector >::iterator it = std::find - (m_params.begin(), m_params.end(), beforeParam); +void parameterizedHeaderField::insertParameterBefore( + const shared_ptr & beforeParam, + const shared_ptr & param +) { - if (it == m_params.end()) + const std::vector >::iterator it = + std::find(m_params.begin(), m_params.end(), beforeParam); + + if (it == m_params.end()) { throw std::out_of_range("Invalid position"); + } m_params.insert(it, param); } -void parameterizedHeaderField::insertParameterBefore(const size_t pos, const shared_ptr & param) -{ - if (pos >= m_params.size()) +void parameterizedHeaderField::insertParameterBefore( + const size_t pos, + const shared_ptr & param +) { + + if (pos >= m_params.size()) { throw std::out_of_range("Invalid position"); + } m_params.insert(m_params.begin() + pos, param); } -void parameterizedHeaderField::insertParameterAfter(const shared_ptr & afterParam, const shared_ptr & param) -{ - const std::vector >::iterator it = std::find - (m_params.begin(), m_params.end(), afterParam); +void parameterizedHeaderField::insertParameterAfter( + const shared_ptr & afterParam, + const shared_ptr & param +) { - if (it == m_params.end()) + const std::vector >::iterator it = + std::find(m_params.begin(), m_params.end(), afterParam); + + if (it == m_params.end()) { throw std::out_of_range("Invalid position"); + } m_params.insert(it + 1, param); } -void parameterizedHeaderField::insertParameterAfter(const size_t pos, const shared_ptr & param) -{ - if (pos >= m_params.size()) +void parameterizedHeaderField::insertParameterAfter( + const size_t pos, + const shared_ptr & param +) { + + if (pos >= m_params.size()) { throw std::out_of_range("Invalid position"); + } m_params.insert(m_params.begin() + pos + 1, param); } -void parameterizedHeaderField::removeParameter(const shared_ptr & param) -{ - const std::vector >::iterator it = std::find - (m_params.begin(), m_params.end(), param); +void parameterizedHeaderField::removeParameter(const shared_ptr & param) { - if (it == m_params.end()) + const std::vector >::iterator it = + std::find(m_params.begin(), m_params.end(), param); + + if (it == m_params.end()) { throw std::out_of_range("Invalid position"); + } m_params.erase(it); } -void parameterizedHeaderField::removeParameter(const size_t pos) -{ +void parameterizedHeaderField::removeParameter(const size_t pos) { + const std::vector >::iterator it = m_params.begin() + pos; m_params.erase(it); } -void parameterizedHeaderField::removeAllParameters() -{ +void parameterizedHeaderField::removeAllParameters() { + m_params.clear(); } -size_t parameterizedHeaderField::getParameterCount() const -{ - return (m_params.size()); +size_t parameterizedHeaderField::getParameterCount() const { + + return m_params.size(); } -bool parameterizedHeaderField::isEmpty() const -{ - return (m_params.empty()); +bool parameterizedHeaderField::isEmpty() const { + + return m_params.empty(); } -const shared_ptr parameterizedHeaderField::getParameterAt(const size_t pos) -{ - return (m_params[pos]); +const shared_ptr parameterizedHeaderField::getParameterAt(const size_t pos) { + + return m_params[pos]; } -const shared_ptr parameterizedHeaderField::getParameterAt(const size_t pos) const -{ - return (m_params[pos]); +const shared_ptr parameterizedHeaderField::getParameterAt(const size_t pos) const { + + return m_params[pos]; } -const std::vector > parameterizedHeaderField::getParameterList() const -{ +const std::vector > parameterizedHeaderField::getParameterList() const { + std::vector > list; list.reserve(m_params.size()); for (std::vector >::const_iterator it = m_params.begin() ; - it != m_params.end() ; ++it) - { + it != m_params.end() ; ++it) { + list.push_back(*it); } - return (list); + return list; } -const std::vector > parameterizedHeaderField::getParameterList() -{ - return (m_params); +const std::vector > parameterizedHeaderField::getParameterList() { + + return m_params; } -const std::vector > parameterizedHeaderField::getChildComponents() -{ +const std::vector > parameterizedHeaderField::getChildComponents() { + std::vector > list = headerField::getChildComponents(); for (std::vector >::iterator it = m_params.begin() ; - it != m_params.end() ; ++it) - { + it != m_params.end() ; ++it) { + list.push_back(*it); } - return (list); + return list; } diff --git a/src/vmime/parameterizedHeaderField.hpp b/src/vmime/parameterizedHeaderField.hpp index 113df16d..d884f1fb 100644 --- a/src/vmime/parameterizedHeaderField.hpp +++ b/src/vmime/parameterizedHeaderField.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,16 +31,14 @@ #include "vmime/exception.hpp" -namespace vmime -{ +namespace vmime { /** A header field that can also contain parameters (name=value pairs). * Parameters can be created using vmime::parameterFactory. */ +class VMIME_EXPORT parameterizedHeaderField : public headerField { -class VMIME_EXPORT parameterizedHeaderField : public headerField -{ friend class headerFieldFactory; protected: @@ -97,7 +95,10 @@ public: * @param param parameter to insert * @throw std::out_of_range if the parameter is not in the list */ - void insertParameterBefore(const shared_ptr & beforeParam, const shared_ptr & param); + void insertParameterBefore( + const shared_ptr & beforeParam, + const shared_ptr & param + ); /** Insert a new parameter before the specified position. * @@ -106,7 +107,10 @@ public: * @param param parameter to insert * @throw std::out_of_range if the position is out of range */ - void insertParameterBefore(const size_t pos, const shared_ptr & param); + void insertParameterBefore( + const size_t pos, + const shared_ptr & param + ); /** Insert a new parameter after the specified parameter. * @@ -114,7 +118,10 @@ public: * @param param parameter to insert * @throw std::out_of_range if the parameter is not in the list */ - void insertParameterAfter(const shared_ptr & afterParam, const shared_ptr & param); + void insertParameterAfter( + const shared_ptr & afterParam, + const shared_ptr & param + ); /** Insert a new parameter after the specified position. * @@ -122,7 +129,10 @@ public: * @param param parameter to insert * @throw std::out_of_range if the position is out of range */ - void insertParameterAfter(const size_t pos, const shared_ptr & param); + void insertParameterAfter( + const size_t pos, + const shared_ptr & param + ); /** Remove the specified parameter from the list. * @@ -189,18 +199,20 @@ private: protected: - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/parsedMessageAttachment.cpp b/src/vmime/parsedMessageAttachment.cpp index efe4a5b2..d50862ba 100644 --- a/src/vmime/parsedMessageAttachment.cpp +++ b/src/vmime/parsedMessageAttachment.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,38 +29,37 @@ #include "vmime/utility/outputStreamAdapter.hpp" -namespace vmime -{ +namespace vmime { parsedMessageAttachment::parsedMessageAttachment(const shared_ptr & msg) - : m_msg(msg) -{ + : m_msg(msg) { + } -const mediaType parsedMessageAttachment::getType() const -{ +const mediaType parsedMessageAttachment::getType() const { + return mediaType(mediaTypes::MESSAGE, mediaTypes::MESSAGE_RFC822); } -const text parsedMessageAttachment::getDescription() const -{ +const text parsedMessageAttachment::getDescription() const { + return text(); } -const word parsedMessageAttachment::getName() const -{ +const word parsedMessageAttachment::getName() const { + return word(); } -const shared_ptr parsedMessageAttachment::getData() const -{ - if (m_data == NULL) - { +const shared_ptr parsedMessageAttachment::getData() const { + + if (!m_data) { + std::ostringstream oss; utility::outputStreamAdapter os(oss); @@ -73,32 +72,32 @@ const shared_ptr parsedMessageAttachment::getData() const } -const encoding parsedMessageAttachment::getEncoding() const -{ +const encoding parsedMessageAttachment::getEncoding() const { + return encoding(encodingTypes::EIGHT_BIT); // not important } -shared_ptr parsedMessageAttachment::getPart() const -{ +shared_ptr parsedMessageAttachment::getPart() const { + return null; } -shared_ptr parsedMessageAttachment::getHeader() const -{ +shared_ptr parsedMessageAttachment::getHeader() const { + return null; } -shared_ptr parsedMessageAttachment::getMessage() const -{ +shared_ptr parsedMessageAttachment::getMessage() const { + return m_msg; } -void parsedMessageAttachment::generateIn(const shared_ptr & parent) const -{ +void parsedMessageAttachment::generateIn(const shared_ptr & parent) const { + // Create and append a new part for this attachment shared_ptr part = make_shared (); parent->getBody()->appendPart(part); @@ -113,4 +112,3 @@ void parsedMessageAttachment::generateIn(const shared_ptr & parent) co } // vmime - diff --git a/src/vmime/parsedMessageAttachment.hpp b/src/vmime/parsedMessageAttachment.hpp index 330cf869..2a5358e8 100644 --- a/src/vmime/parsedMessageAttachment.hpp +++ b/src/vmime/parsedMessageAttachment.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,14 +31,13 @@ #include "vmime/messageAttachment.hpp" -namespace vmime -{ +namespace vmime { /** A message attachment that can be generated into a message. */ -class VMIME_EXPORT parsedMessageAttachment : public messageAttachment -{ +class VMIME_EXPORT parsedMessageAttachment : public messageAttachment { + public: parsedMessageAttachment(const shared_ptr & msg); @@ -75,4 +74,3 @@ private: #endif // VMIME_PARSEDMESSAGEATTACHMENT_HPP_INCLUDED - diff --git a/src/vmime/parserHelpers.hpp b/src/vmime/parserHelpers.hpp index 430487b4..cba43c6c 100644 --- a/src/vmime/parserHelpers.hpp +++ b/src/vmime/parserHelpers.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,60 +32,59 @@ -namespace vmime -{ +namespace vmime { -class parserHelpers -{ +class parserHelpers { + public: - static bool isSpace(const char_t c) - { - return (c == ' ' || c == '\t' || c == '\n' || c == '\r'); + static bool isSpace(const char_t c) { + + return c == ' ' || c == '\t' || c == '\n' || c == '\r'; } - static bool isSpaceOrTab(const char_t c) - { - return (c == ' ' || c == '\t'); + static bool isSpaceOrTab(const char_t c) { + + return c == ' ' || c == '\t'; } - static bool isDigit(const char_t c) - { - return (c >= '0' && c <= '9'); + static bool isDigit(const char_t c) { + + return c >= '0' && c <= '9'; + } + + static bool isAlpha(const char_t c) { + + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } - static bool isAlpha(const char_t c) - { - return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); - } + static char_t toLower(const char_t c) { - - static char_t toLower(const char_t c) - { - if (c >= 'A' && c <= 'Z') + if (c >= 'A' && c <= 'Z') { return ('a' + (c - 'A')); - else + } else { return c; + } } // Checks whether a character is in the 7-bit US-ASCII charset - static bool isAscii(const char_t c) - { + static bool isAscii(const char_t c) { + const unsigned int x = static_cast (c); - return (x <= 127); + return x <= 127; } // Checks whether a character has a visual representation - static bool isPrint(const char_t c) - { + static bool isPrint(const char_t c) { + const unsigned int x = static_cast (c); - return (x >= 0x20 && x <= 0x7E); + return x >= 0x20 && x <= 0x7E; } @@ -99,22 +98,28 @@ public: * @return true if an EOL sequence has been found, or false if * no EOL sequence was found before the end of the buffer */ - static bool findEOL(const string& buffer, const size_t currentPos, const size_t end, size_t* eol) - { + static bool findEOL( + const string& buffer, + const size_t currentPos, + const size_t end, + size_t* eol + ) { + size_t pos = currentPos; - if (pos == end) + if (pos == end) { return false; + } + + while (pos < end) { + + if (buffer[pos] == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') { - while (pos < end) - { - if (buffer[pos] == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') - { *eol = pos + 2; return true; - } - else if (buffer[pos] == '\n') - { + + } else if (buffer[pos] == '\n') { + *eol = pos + 1; return true; } diff --git a/src/vmime/parsingContext.cpp b/src/vmime/parsingContext.cpp index c5da5151..0975e3d7 100644 --- a/src/vmime/parsingContext.cpp +++ b/src/vmime/parsingContext.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -24,35 +24,39 @@ #include "vmime/parsingContext.hpp" -namespace vmime -{ +namespace vmime { -parsingContext::parsingContext() : m_headerParseErrorRecovery(vmime::headerParseRecoveryMethod::SKIP_LINE) -{ +parsingContext::parsingContext() + : m_headerParseErrorRecovery(vmime::headerParseRecoveryMethod::SKIP_LINE) { + } parsingContext::parsingContext(const parsingContext& ctx) - : context(ctx), m_headerParseErrorRecovery(vmime::headerParseRecoveryMethod::SKIP_LINE) -{ + : context(ctx), + m_headerParseErrorRecovery(vmime::headerParseRecoveryMethod::SKIP_LINE) { + } -parsingContext& parsingContext::getDefaultContext() -{ +parsingContext& parsingContext::getDefaultContext() { + static parsingContext ctx; return ctx; } -headerParseRecoveryMethod::headerLineError parsingContext::getHeaderParseErrorRecoveryMethod() const -{ + +headerParseRecoveryMethod::headerLineError parsingContext::getHeaderParseErrorRecoveryMethod() const { + return m_headerParseErrorRecovery; } -void parsingContext::setHeaderParseErrorRecoveryMethod(headerParseRecoveryMethod::headerLineError recoveryMethod) -{ +void parsingContext::setHeaderParseErrorRecoveryMethod( + const headerParseRecoveryMethod::headerLineError recoveryMethod +) { + m_headerParseErrorRecovery = recoveryMethod; } diff --git a/src/vmime/parsingContext.hpp b/src/vmime/parsingContext.hpp index 1b1cd282..d13d94ef 100644 --- a/src/vmime/parsingContext.hpp +++ b/src/vmime/parsingContext.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,24 +28,23 @@ #include "vmime/context.hpp" -namespace vmime -{ +namespace vmime { - /** Provides runtime configurable options to provide flexibility in header parsing - */ - struct headerParseRecoveryMethod { - enum headerLineError { - SKIP_LINE = 0, - /* APPEND_TO_PREVIOUS_LINE = 1, */ - ASSUME_END_OF_HEADERS = 2 - }; +/** Provides runtime configurable options to provide flexibility in header parsing + */ +struct headerParseRecoveryMethod { + + enum headerLineError { + SKIP_LINE = 0, + /* APPEND_TO_PREVIOUS_LINE = 1, */ + ASSUME_END_OF_HEADERS = 2 }; +}; /** Holds configuration parameters used for parsing messages. */ +class VMIME_EXPORT parsingContext : public context { -class VMIME_EXPORT parsingContext : public context -{ public: parsingContext(); @@ -57,11 +56,13 @@ public: */ static parsingContext& getDefaultContext(); - /** Sets the recovery method when parsing a header encounters an error such as a failed fold or missing new line. + /** Sets the recovery method when parsing a header encounters an error + * such as a failed fold or missing new line. * - * @param recoveryMethod is one of vmime::headerParseRecoveryMethod. Defaults to vmime::headerParseRecoveryMethod::SKIP_LINE. + * @param recoveryMethod is one of vmime::headerParseRecoveryMethod. + * Defaults to vmime::headerParseRecoveryMethod::SKIP_LINE. */ - void setHeaderParseErrorRecoveryMethod(headerParseRecoveryMethod::headerLineError recoveryMethod); + void setHeaderParseErrorRecoveryMethod(const headerParseRecoveryMethod::headerLineError recoveryMethod); /** Return the recovery method when parsing a header encounters an error. * @@ -69,7 +70,6 @@ public: */ headerParseRecoveryMethod::headerLineError getHeaderParseErrorRecoveryMethod() const; - protected: headerParseRecoveryMethod::headerLineError m_headerParseErrorRecovery; diff --git a/src/vmime/path.cpp b/src/vmime/path.cpp index 3f1bc6af..f57d1285 100644 --- a/src/vmime/path.cpp +++ b/src/vmime/path.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -25,67 +25,69 @@ #include "vmime/parserHelpers.hpp" -namespace vmime -{ +namespace vmime { -path::path() -{ +path::path() { + } path::path(const string& localPart, const string& domain) - : m_localPart(localPart), m_domain(domain) -{ + : m_localPart(localPart), + m_domain(domain) { + } path::path(const path& p) - : headerFieldValue(), m_localPart(p.m_localPart), m_domain(p.m_domain) -{ + : headerFieldValue(), + m_localPart(p.m_localPart), + m_domain(p.m_domain) { + } -const string& path::getLocalPart() const -{ - return (m_localPart); +const string& path::getLocalPart() const { + + return m_localPart; } -void path::setLocalPart(const string& localPart) -{ +void path::setLocalPart(const string& localPart) { + m_localPart = localPart; } -const string& path::getDomain() const -{ - return (m_domain); +const string& path::getDomain() const { + + return m_domain; } -void path::setDomain(const string& domain) -{ +void path::setDomain(const string& domain) { + m_domain = domain; } -bool path::operator==(const path& p) const -{ - return (m_localPart == p.m_localPart && - m_domain == p.m_domain); +bool path::operator==(const path& p) const { + + return m_localPart == p.m_localPart && + m_domain == p.m_domain; } -bool path::operator!=(const path& p) const -{ - return (m_localPart != p.m_localPart || - m_domain != p.m_domain); +bool path::operator!=(const path& p) const { + + return m_localPart != p.m_localPart || + m_domain != p.m_domain; } -void path::copyFrom(const component& other) -{ +void path::copyFrom(const component& other) { + const path& p = dynamic_cast (other); m_localPart = p.m_localPart; @@ -93,96 +95,110 @@ void path::copyFrom(const component& other) } -shared_ptr path::clone() const -{ +shared_ptr path::clone() const { + return make_shared (*this); } -path& path::operator=(const path& other) -{ +path& path::operator=(const path& other) { + copyFrom(other); - return (*this); + return *this; } -const std::vector > path::getChildComponents() -{ +const std::vector > path::getChildComponents() { + return std::vector >(); } -void path::parseImpl - (const parsingContext& /* ctx */, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void path::parseImpl( + const parsingContext& /* ctx */, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + size_t pos = position; - while (pos < end && parserHelpers::isSpace(buffer[pos])) + while (pos < end && parserHelpers::isSpace(buffer[pos])) { ++pos; + } string addrSpec; - if (pos < end && buffer[pos] == '<') - { + if (pos < end && buffer[pos] == '<') { + // Skip '<' ++pos; - while (pos < end && parserHelpers::isSpace(buffer[pos])) + while (pos < end && parserHelpers::isSpace(buffer[pos])) { ++pos; + } const size_t addrStart = pos; - while (pos < end && buffer[pos] != '>') + while (pos < end && buffer[pos] != '>') { ++pos; + } size_t addrEnd = pos; - while (addrEnd > addrStart && parserHelpers::isSpace(buffer[addrEnd - 1])) + while (addrEnd > addrStart && parserHelpers::isSpace(buffer[addrEnd - 1])) { addrEnd--; + } addrSpec = string(buffer.begin() + addrStart, buffer.begin() + addrEnd); - } - else - { + + } else { + addrSpec = string(buffer.begin() + position, buffer.begin() + end); } const size_t at = addrSpec.find_first_of('@'); - if (at != string::npos) - { + if (at != string::npos) { + m_localPart = string(addrSpec.begin(), addrSpec.begin() + at); m_domain = string(addrSpec.begin() + at + 1, addrSpec.end()); - } - else - { + + } else { + m_localPart.clear(); m_domain = addrSpec; } - if (newPosition != NULL) + if (newPosition) { *newPosition = end; + } } -void path::generateImpl - (const generationContext& /* ctx */, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ - if (m_localPart.empty() && m_domain.empty()) - { +void path::generateImpl( + const generationContext& /* ctx */, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + + if (m_localPart.empty() && m_domain.empty()) { + os << "<>"; - if (newLinePos) + if (newLinePos) { *newLinePos = curLinePos + 2; - } - else - { + } + + } else { + os << "<" << m_localPart << "@" << m_domain << ">"; - if (newLinePos) + if (newLinePos) { *newLinePos = curLinePos + m_localPart.length() + m_domain.length() + 3; + } } } diff --git a/src/vmime/path.hpp b/src/vmime/path.hpp index 2ffa3c22..d63ee674 100644 --- a/src/vmime/path.hpp +++ b/src/vmime/path.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,15 +28,13 @@ #include "vmime/headerFieldValue.hpp" -namespace vmime -{ +namespace vmime { /** A path: a local part + '@' + a domain. */ +class VMIME_EXPORT path : public headerFieldValue { -class VMIME_EXPORT path : public headerFieldValue -{ public: path(); @@ -85,18 +83,20 @@ protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/plainTextPart.cpp b/src/vmime/plainTextPart.cpp index a9a245f4..859a67cc 100644 --- a/src/vmime/plainTextPart.cpp +++ b/src/vmime/plainTextPart.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,81 +30,90 @@ #include "vmime/emptyContentHandler.hpp" -namespace vmime -{ +namespace vmime { plainTextPart::plainTextPart() - : m_text(make_shared ()) -{ + : m_text(make_shared ()) { + } -plainTextPart::~plainTextPart() -{ +plainTextPart::~plainTextPart() { + } -const mediaType plainTextPart::getType() const -{ - return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); +const mediaType plainTextPart::getType() const { + + return mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN); } -size_t plainTextPart::getPartCount() const -{ - return (1); +size_t plainTextPart::getPartCount() const { + + return 1; } -void plainTextPart::generateIn(const shared_ptr & /* message */, const shared_ptr & parent) const -{ +void plainTextPart::generateIn( + const shared_ptr & /* message */, + const shared_ptr & parent +) const { + // Create a new part shared_ptr part = make_shared (); parent->getBody()->appendPart(part); // Set contents - part->getBody()->setContents(m_text, - mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN), m_charset, - encoding::decide(m_text, m_charset, encoding::USAGE_TEXT)); + part->getBody()->setContents( + m_text, + mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN), + m_charset, + encoding::decide(m_text, m_charset, encoding::USAGE_TEXT) + ); } -void plainTextPart::parse(const shared_ptr & /* message */, - const shared_ptr & /* parent */, const shared_ptr & textPart) -{ +void plainTextPart::parse( + const shared_ptr & /* message */, + const shared_ptr & /* parent */, + const shared_ptr & textPart +) { + m_text = vmime::clone(textPart->getBody()->getContents()); shared_ptr ctf = textPart->getHeader()->findField (fields::CONTENT_TYPE); - if (ctf && ctf->hasCharset()) + if (ctf && ctf->hasCharset()) { m_charset = ctf->getCharset(); - else + } else { m_charset = charset(); + } } -const charset& plainTextPart::getCharset() const -{ - return (m_charset); +const charset& plainTextPart::getCharset() const { + + return m_charset; } -void plainTextPart::setCharset(const charset& ch) -{ +void plainTextPart::setCharset(const charset& ch) { + m_charset = ch; } -const shared_ptr plainTextPart::getText() const -{ - return (m_text); +const shared_ptr plainTextPart::getText() const{ + + return m_text; } -void plainTextPart::setText(const shared_ptr & text) -{ +void plainTextPart::setText(const shared_ptr & text) { + m_text = vmime::clone(text); } diff --git a/src/vmime/plainTextPart.hpp b/src/vmime/plainTextPart.hpp index 8640dc48..8a0249ee 100644 --- a/src/vmime/plainTextPart.hpp +++ b/src/vmime/plainTextPart.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,15 +28,13 @@ #include "vmime/textPart.hpp" -namespace vmime -{ +namespace vmime { /** Text part of type 'text/plain'. */ +class VMIME_EXPORT plainTextPart : public textPart { -class VMIME_EXPORT plainTextPart : public textPart -{ public: plainTextPart(); @@ -52,8 +50,16 @@ public: size_t getPartCount() const; - void generateIn(const shared_ptr & message, const shared_ptr & parent) const; - void parse(const shared_ptr & message, const shared_ptr & parent, const shared_ptr & textPart); + void generateIn( + const shared_ptr & message, + const shared_ptr & parent + ) const; + + void parse( + const shared_ptr & message, + const shared_ptr & parent, + const shared_ptr & textPart + ); private: diff --git a/src/vmime/platform.cpp b/src/vmime/platform.cpp index 631d5bcf..f2f1e977 100644 --- a/src/vmime/platform.cpp +++ b/src/vmime/platform.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,21 +28,19 @@ #include "vmime/platforms/windows/windowsHandler.hpp" -namespace vmime -{ +namespace vmime { shared_ptr platform::sm_handler; -platform::handler::~handler() -{ +platform::handler::~handler() { + } // static -shared_ptr platform::getDefaultHandler() -{ +shared_ptr platform::getDefaultHandler() { #if VMIME_PLATFORM_IS_WINDOWS return make_shared (); @@ -56,17 +54,17 @@ shared_ptr platform::getDefaultHandler() // static -shared_ptr platform::getHandler() -{ +shared_ptr platform::getHandler() { + // If a custom platform handler is installed, return it - if (sm_handler) + if (sm_handler) { return sm_handler; + } // Else, use the default handler for this platform shared_ptr defaultHandler = getDefaultHandler(); - if (defaultHandler) - { + if (defaultHandler) { sm_handler = defaultHandler; return sm_handler; } diff --git a/src/vmime/platform.hpp b/src/vmime/platform.hpp index ac1834ac..03a7b234 100644 --- a/src/vmime/platform.hpp +++ b/src/vmime/platform.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,23 +43,20 @@ #include "vmime/utility/sync/criticalSection.hpp" -namespace vmime -{ +namespace vmime { /** Allow setting or getting the current platform handler. */ +class VMIME_EXPORT platform { -class VMIME_EXPORT platform -{ public: /** Takes care of all platform-dependent operations. It offers an interface to * access platform-dependent objects: sockets, date/time, file system, etc. */ + class VMIME_EXPORT handler : public object { - class VMIME_EXPORT handler : public object - { public: virtual ~handler(); @@ -142,8 +139,7 @@ public: template - static void setHandler() - { + static void setHandler() { sm_handler = vmime::make_shared (); } @@ -160,4 +156,3 @@ private: #endif // VMIME_PLATFORM_HPP_INCLUDED - diff --git a/src/vmime/platforms/posix/posixChildProcess.cpp b/src/vmime/platforms/posix/posixChildProcess.cpp index c498b7ca..4a9fef39 100644 --- a/src/vmime/platforms/posix/posixChildProcess.cpp +++ b/src/vmime/platforms/posix/posixChildProcess.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -47,8 +47,8 @@ namespace posix { // posixChildProcessFactory -shared_ptr posixChildProcessFactory::create(const utility::file::path& path) const -{ +shared_ptr posixChildProcessFactory::create(const utility::file::path& path) const { + return make_shared (path); } @@ -60,29 +60,28 @@ shared_ptr posixChildProcessFactory::create(const utilit // getPosixSignalMessage // Returns the name of a POSIX signal. -static const string getPosixSignalMessage(const int num) -{ - switch (num) - { - case SIGHUP: return "SIGHUP"; - case SIGINT: return "SIGINT"; - case SIGQUIT: return "SIGQUIT"; - case SIGILL: return "SIGILL"; - case SIGABRT: return "SIGABRT"; - case SIGFPE: return "SIGFPE"; - case SIGKILL: return "SIGKILL"; - case SIGSEGV: return "SIGSEGV"; - case SIGPIPE: return "SIGPIPE"; - case SIGALRM: return "SIGALRM"; - case SIGTERM: return "SIGTERM"; - case SIGUSR1: return "SIGUSR1"; - case SIGUSR2: return "SIGUSR2"; - case SIGCHLD: return "SIGCHLD"; - case SIGCONT: return "SIGCONT"; - case SIGSTOP: return "SIGSTOP"; - case SIGTSTP: return "SIGTSTP"; - case SIGTTIN: return "SIGTTIN"; - case SIGTTOU: return "SIGTTOU"; +static const string getPosixSignalMessage(const int num) { + + switch (num) { + case SIGHUP: return "SIGHUP"; + case SIGINT: return "SIGINT"; + case SIGQUIT: return "SIGQUIT"; + case SIGILL: return "SIGILL"; + case SIGABRT: return "SIGABRT"; + case SIGFPE: return "SIGFPE"; + case SIGKILL: return "SIGKILL"; + case SIGSEGV: return "SIGSEGV"; + case SIGPIPE: return "SIGPIPE"; + case SIGALRM: return "SIGALRM"; + case SIGTERM: return "SIGTERM"; + case SIGUSR1: return "SIGUSR1"; + case SIGUSR2: return "SIGUSR2"; + case SIGCHLD: return "SIGCHLD"; + case SIGCONT: return "SIGCONT"; + case SIGSTOP: return "SIGSTOP"; + case SIGTSTP: return "SIGTSTP"; + case SIGTTIN: return "SIGTTIN"; + case SIGTTOU: return "SIGTTOU"; } return "(unknown)"; @@ -92,8 +91,8 @@ static const string getPosixSignalMessage(const int num) // getPosixErrorMessage // Returns a message corresponding to an error code. -static const string getPosixErrorMessage(const int num) -{ +static const string getPosixErrorMessage(const int num) { + #ifdef strerror_r char res[256]; res[0] = '\0'; @@ -104,31 +103,31 @@ static const string getPosixErrorMessage(const int num) #else return string(strerror(num)); #endif + } // Output stream adapter for POSIX pipe -class outputStreamPosixPipeAdapter : public utility::outputStream -{ +class outputStreamPosixPipeAdapter : public utility::outputStream { + public: outputStreamPosixPipeAdapter(const int desc) - : m_desc(desc) - { + : m_desc(desc) { + } - void flush() - { + void flush() { + ::fsync(m_desc); } protected: - void writeImpl(const byte_t* const data, const size_t count) - { - if (::write(m_desc, data, count) == -1) - { + void writeImpl(const byte_t* const data, const size_t count) { + + if (::write(m_desc, data, count) == -1) { const string errorMsg = getPosixErrorMessage(errno); throw exceptions::system_error(errorMsg); } @@ -142,27 +141,26 @@ private: // Input stream adapter for POSIX pipe -class inputStreamPosixPipeAdapter : public utility::inputStream -{ +class inputStreamPosixPipeAdapter : public utility::inputStream { + public: inputStreamPosixPipeAdapter(const int desc) - : m_desc(desc) - { + : m_desc(desc) { } - bool eof() const - { - return (m_eof); + bool eof() const { + + return m_eof; } - void reset() - { + void reset() { + // Do nothing: unsupported } - size_t skip(const size_t count) - { + size_t skip(const size_t count) { + // TODO: not tested byte_t buffer[4096]; @@ -170,10 +168,9 @@ public: ssize_t bytesRead = 0; while ((bytesRead = ::read(m_desc, buffer, - std::min(sizeof(buffer), count - bytesSkipped))) != 0) - { - if (bytesRead == -1) - { + std::min(sizeof(buffer), count - bytesSkipped))) != 0) { + + if (bytesRead == -1) { const string errorMsg = getPosixErrorMessage(errno); throw exceptions::system_error(errorMsg); } @@ -184,12 +181,11 @@ public: return static_cast (bytesSkipped); } - size_t read(byte_t* const data, const size_t count) - { + size_t read(byte_t* const data, const size_t count) { + ssize_t bytesRead = 0; - if ((bytesRead = ::read(m_desc, data, count)) == -1) - { + if ((bytesRead = ::read(m_desc, data, count)) == -1) { const string errorMsg = getPosixErrorMessage(errno); throw exceptions::system_error(errorMsg); } @@ -214,9 +210,13 @@ private: // posixChildProcess posixChildProcess::posixChildProcess(const utility::file::path& path) - : m_processPath(path), m_started(false), - m_stdIn(null), m_stdOut(null), m_pid(0), m_argArray(NULL) -{ + : m_processPath(path), + m_started(false), + m_stdIn(null), + m_stdOut(null), + m_pid(0), + m_argArray(NULL) { + m_pipe[0] = 0; m_pipe[1] = 0; @@ -224,18 +224,21 @@ posixChildProcess::posixChildProcess(const utility::file::path& path) } -posixChildProcess::~posixChildProcess() -{ - if (m_started) +posixChildProcess::~posixChildProcess() { + + if (m_started) { sigprocmask(SIG_SETMASK, &m_oldProcMask, NULL); + } - if (m_pipe[0] != 0) + if (m_pipe[0] != 0) { close(m_pipe[0]); + } - if (m_pipe[1] != 0) + if (m_pipe[1] != 0) { close(m_pipe[1]); + } - delete [] (m_argArray); + delete [] m_argArray; } @@ -245,10 +248,11 @@ posixChildProcess::~posixChildProcess() // Original authors: Dan Winship // Copyright 2000 Ximian, Inc. (www.ximian.com) -void posixChildProcess::start(const std::vector & args, const int flags) -{ - if (m_started) +void posixChildProcess::start(const std::vector & args, const int flags) { + + if (m_started) { return; + } // Construct C-style argument array const char** argv = new const char*[args.size() + 2]; @@ -259,14 +263,14 @@ void posixChildProcess::start(const std::vector & args, const int flags) argv[0] = m_processPath.getLastComponent().getBuffer().c_str(); argv[args.size() + 1] = NULL; - for (unsigned int i = 0 ; i < m_argVector.size() ; ++i) + for (unsigned int i = 0 ; i < m_argVector.size() ; ++i) { argv[i + 1] = m_argVector[i].c_str(); + } // Create a pipe to communicate with the child process int fd[2]; - if (pipe(fd) == -1) - { + if (pipe(fd) == -1) { throw exceptions::system_error(getPosixErrorMessage(errno)); } @@ -284,8 +288,8 @@ void posixChildProcess::start(const std::vector & args, const int flags) // Spawn process const pid_t pid = fork(); - if (pid == -1) // error - { + if (pid == -1) { // error + const string errorMsg = getPosixErrorMessage(errno); sigprocmask(SIG_SETMASK, &m_oldProcMask, NULL); @@ -294,45 +298,47 @@ void posixChildProcess::start(const std::vector & args, const int flags) close(fd[1]); throw exceptions::system_error(errorMsg); - } - else if (pid == 0) // child process - { - if (flags & FLAG_REDIRECT_STDIN) - dup2(fd[0], STDIN_FILENO); - else - close(fd[0]); - if (flags & FLAG_REDIRECT_STDOUT) + } else if (pid == 0) { // child process + + if (flags & FLAG_REDIRECT_STDIN) { + dup2(fd[0], STDIN_FILENO); + } else { + close(fd[0]); + } + + if (flags & FLAG_REDIRECT_STDOUT) { dup2(fd[1], STDOUT_FILENO); - else + } else { close(fd[1]); + } posixFileSystemFactory* pfsf = new posixFileSystemFactory(); const string path = pfsf->pathToString(m_processPath); - delete (pfsf); + delete pfsf; execv(path.c_str(), const_cast (argv)); _exit(255); } - if (flags & FLAG_REDIRECT_STDIN) - { + if (flags & FLAG_REDIRECT_STDIN) { + m_stdIn = make_shared (m_pipe[1]); - } - else - { + + } else { + close(m_pipe[1]); m_pipe[1] = 0; } - if (flags & FLAG_REDIRECT_STDOUT) - { + if (flags & FLAG_REDIRECT_STDOUT) { + m_stdOut = make_shared (m_pipe[0]); - } - else - { + + } else { + close(m_pipe[0]); m_pipe[0] = 0; } @@ -342,48 +348,48 @@ void posixChildProcess::start(const std::vector & args, const int flags) } -shared_ptr posixChildProcess::getStdIn() -{ - return (m_stdIn); +shared_ptr posixChildProcess::getStdIn() { + + return m_stdIn; } -shared_ptr posixChildProcess::getStdOut() -{ - return (m_stdOut); +shared_ptr posixChildProcess::getStdOut() { + + return m_stdOut; } -void posixChildProcess::waitForFinish() -{ +void posixChildProcess::waitForFinish() { + // Close stdin pipe - if (m_pipe[1] != 0) - { + if (m_pipe[1] != 0) { close(m_pipe[1]); m_pipe[1] = 0; } int wstat; - while (waitpid(m_pid, &wstat, 0) == -1 && errno == EINTR) + while (waitpid(m_pid, &wstat, 0) == -1 && errno == EINTR) { ; + } + + if (!WIFEXITED(wstat)) { - if (!WIFEXITED(wstat)) - { throw exceptions::system_error("Process exited with signal " + getPosixSignalMessage(WTERMSIG(wstat))); - } - else if (WEXITSTATUS(wstat) != 0) - { - if (WEXITSTATUS(wstat) == 255) - { + + } else if (WEXITSTATUS(wstat) != 0) { + + if (WEXITSTATUS(wstat) == 255) { + scoped_ptr pfsf(new posixFileSystemFactory()); throw exceptions::system_error("Could not execute '" + pfsf->pathToString(m_processPath) + "'"); - } - else - { + + } else { + std::ostringstream oss; oss.imbue(std::locale::classic()); diff --git a/src/vmime/platforms/posix/posixChildProcess.hpp b/src/vmime/platforms/posix/posixChildProcess.hpp index 33f166f2..b831e8bb 100644 --- a/src/vmime/platforms/posix/posixChildProcess.hpp +++ b/src/vmime/platforms/posix/posixChildProcess.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,8 +42,8 @@ namespace platforms { namespace posix { -class posixChildProcess : public utility::childProcess -{ +class posixChildProcess : public utility::childProcess { + public: posixChildProcess(const utility::file::path& path); @@ -73,8 +73,8 @@ private: }; -class posixChildProcessFactory : public utility::childProcessFactory -{ +class posixChildProcessFactory : public utility::childProcessFactory { + public: shared_ptr create(const utility::file::path& path) const; diff --git a/src/vmime/platforms/posix/posixCriticalSection.cpp b/src/vmime/platforms/posix/posixCriticalSection.cpp index fb2c469c..2f25cfa4 100644 --- a/src/vmime/platforms/posix/posixCriticalSection.cpp +++ b/src/vmime/platforms/posix/posixCriticalSection.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,26 +35,26 @@ namespace platforms { namespace posix { -posixCriticalSection::posixCriticalSection() -{ +posixCriticalSection::posixCriticalSection() { + pthread_mutex_init(&m_cs, NULL); } -posixCriticalSection::~posixCriticalSection() -{ +posixCriticalSection::~posixCriticalSection() { + pthread_mutex_destroy(&m_cs); } -void posixCriticalSection::lock() -{ +void posixCriticalSection::lock() { + pthread_mutex_lock(&m_cs); } -void posixCriticalSection::unlock() -{ +void posixCriticalSection::unlock() { + pthread_mutex_unlock(&m_cs); } diff --git a/src/vmime/platforms/posix/posixCriticalSection.hpp b/src/vmime/platforms/posix/posixCriticalSection.hpp index 150799cd..9a4bed53 100644 --- a/src/vmime/platforms/posix/posixCriticalSection.hpp +++ b/src/vmime/platforms/posix/posixCriticalSection.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,8 +43,8 @@ namespace platforms { namespace posix { -class posixCriticalSection : public utility::sync::criticalSection -{ +class posixCriticalSection : public utility::sync::criticalSection { + public: posixCriticalSection(); diff --git a/src/vmime/platforms/posix/posixFile.cpp b/src/vmime/platforms/posix/posixFile.cpp index ea699ac4..9773b3a0 100644 --- a/src/vmime/platforms/posix/posixFile.cpp +++ b/src/vmime/platforms/posix/posixFile.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -53,61 +53,71 @@ namespace posix { // posixFileIterator // -posixFileIterator::posixFileIterator(const vmime::utility::file::path& path, const vmime::string& nativePath) - : m_path(path), m_nativePath(nativePath), m_dir(NULL), m_dirEntry(NULL) -{ - if ((m_dir = ::opendir(m_nativePath.c_str())) == NULL) +posixFileIterator::posixFileIterator( + const vmime::utility::file::path& path, + const vmime::string& nativePath +) + : m_path(path), + m_nativePath(nativePath), + m_dir(NULL), + m_dirEntry(NULL) { + + if ((m_dir = ::opendir(m_nativePath.c_str())) == NULL) { posixFileSystemFactory::reportError(path, errno); + } getNextElement(); } -posixFileIterator::~posixFileIterator() -{ - if (m_dir != NULL) - { - if (::closedir(m_dir) == -1) +posixFileIterator::~posixFileIterator() { + + if (m_dir) { + + if (::closedir(m_dir) == -1) { posixFileSystemFactory::reportError(m_path, errno); + } } } -bool posixFileIterator::hasMoreElements() const -{ +bool posixFileIterator::hasMoreElements() const { + return (m_dirEntry != NULL); } -shared_ptr posixFileIterator::nextElement() -{ - shared_ptr file = make_shared - (m_path / vmime::utility::file::path::component(m_dirEntry->d_name)); +shared_ptr posixFileIterator::nextElement() { + + shared_ptr file = make_shared ( + m_path / vmime::utility::file::path::component(m_dirEntry->d_name) + ); getNextElement(); - return (file); + return file; } -void posixFileIterator::getNextElement() -{ +void posixFileIterator::getNextElement() { + errno = 0; - while ((m_dirEntry = ::readdir(m_dir)) != NULL) - { + while ((m_dirEntry = ::readdir(m_dir)) != NULL) { + const char* name = m_dirEntry->d_name; const size_t len = ::strlen(name); if (!(len == 1 && name[0] == '.') && - !(len == 2 && name[0] == '.' && name[1] == '.')) - { + !(len == 2 && name[0] == '.' && name[1] == '.')) { + break; } } - if (errno) + if (errno) { posixFileSystemFactory::reportError(m_path, errno); + } } @@ -116,38 +126,45 @@ void posixFileIterator::getNextElement() // posixFileWriterOutputStream // -posixFileWriterOutputStream::posixFileWriterOutputStream(const vmime::utility::file::path& path, const int fd) - : m_path(path), m_fd(fd) -{ +posixFileWriterOutputStream::posixFileWriterOutputStream( + const vmime::utility::file::path& path, + const int fd +) + : m_path(path), + m_fd(fd) { + } -posixFileWriterOutputStream::~posixFileWriterOutputStream() -{ +posixFileWriterOutputStream::~posixFileWriterOutputStream() { + ::close(m_fd); } -void posixFileWriterOutputStream::writeImpl - (const byte_t* const data, const size_t count) -{ +void posixFileWriterOutputStream::writeImpl( + const byte_t* const data, + const size_t count +) { + const byte_t* array = data; size_t size = count; - while (1) - { + while (1) { + ssize_t ret = ::write(m_fd, array, size); - if (ret == -1) - { - if (errno == EINTR) + if (ret == -1) { + + if (errno == EINTR) { continue; + } posixFileSystemFactory::reportError(m_path, errno); break; - } - else if (size_t(ret) < size) - { + + } else if (size_t(ret) < size) { + array += ret; size -= ret; } @@ -157,10 +174,11 @@ void posixFileWriterOutputStream::writeImpl } -void posixFileWriterOutputStream::flush() -{ - if (::fsync(m_fd) == -1) +void posixFileWriterOutputStream::flush() { + + if (::fsync(m_fd) == -1) { posixFileSystemFactory::reportError(m_path, errno); + } } @@ -169,82 +187,97 @@ void posixFileWriterOutputStream::flush() // posixFileReaderInputStream // -posixFileReaderInputStream::posixFileReaderInputStream(const vmime::utility::file::path& path, const int fd) - : m_path(path), m_fd(fd), m_eof(false) -{ +posixFileReaderInputStream::posixFileReaderInputStream( + const vmime::utility::file::path& path, + const int fd +) + : m_path(path), + m_fd(fd), + m_eof(false) { + } -posixFileReaderInputStream::~posixFileReaderInputStream() -{ - if (::close(m_fd) == -1) +posixFileReaderInputStream::~posixFileReaderInputStream() { + + if (::close(m_fd) == -1) { posixFileSystemFactory::reportError(m_path, errno); + } } -bool posixFileReaderInputStream::eof() const -{ - return (m_eof); +bool posixFileReaderInputStream::eof() const { + + return m_eof; } -void posixFileReaderInputStream::reset() -{ - if (::lseek(m_fd, 0, SEEK_SET) == off_t(-1)) +void posixFileReaderInputStream::reset() { + + if (::lseek(m_fd, 0, SEEK_SET) == off_t(-1)) { posixFileSystemFactory::reportError(m_path, errno); + } m_eof = false; } -size_t posixFileReaderInputStream::read - (byte_t* const data, const size_t count) -{ +size_t posixFileReaderInputStream::read( + byte_t* const data, + const size_t count +) { + ssize_t c = 0; - if ((c = ::read(m_fd, data, count)) == -1) + if ((c = ::read(m_fd, data, count)) == -1) { posixFileSystemFactory::reportError(m_path, errno); + } - if (c == 0 && count != 0) + if (c == 0 && count != 0) { m_eof = true; + } return static_cast (c); } -size_t posixFileReaderInputStream::skip(const size_t count) -{ +size_t posixFileReaderInputStream::skip(const size_t count) { + const off_t curPos = ::lseek(m_fd, 0, SEEK_CUR); - if (curPos == off_t(-1)) + if (curPos == off_t(-1)) { posixFileSystemFactory::reportError(m_path, errno); + } const off_t newPos = ::lseek(m_fd, count, SEEK_CUR); - if (newPos == off_t(-1)) + if (newPos == off_t(-1)) { posixFileSystemFactory::reportError(m_path, errno); + } return static_cast (newPos - curPos); } -size_t posixFileReaderInputStream::getPosition() const -{ +size_t posixFileReaderInputStream::getPosition() const { + const off_t curPos = ::lseek(m_fd, 0, SEEK_CUR); - if (curPos == off_t(-1)) + if (curPos == off_t(-1)) { posixFileSystemFactory::reportError(m_path, errno); + } return static_cast (curPos); } -void posixFileReaderInputStream::seek(const size_t pos) -{ +void posixFileReaderInputStream::seek(const size_t pos) { + const off_t newPos = ::lseek(m_fd, pos, SEEK_SET); - if (newPos == off_t(-1)) + if (newPos == off_t(-1)) { posixFileSystemFactory::reportError(m_path, errno); + } } @@ -253,18 +286,23 @@ void posixFileReaderInputStream::seek(const size_t pos) // posixFileWriter // -posixFileWriter::posixFileWriter(const vmime::utility::file::path& path, const vmime::string& nativePath) - : m_path(path), m_nativePath(nativePath) -{ +posixFileWriter::posixFileWriter( + const vmime::utility::file::path& path, + const vmime::string& nativePath +) + : m_path(path), + m_nativePath(nativePath) { + } -shared_ptr posixFileWriter::getOutputStream() -{ +shared_ptr posixFileWriter::getOutputStream() { + int fd = 0; - if ((fd = ::open(m_nativePath.c_str(), O_WRONLY, 0660)) == -1) + if ((fd = ::open(m_nativePath.c_str(), O_WRONLY, 0660)) == -1) { posixFileSystemFactory::reportError(m_path, errno); + } return make_shared (m_path, fd); } @@ -275,18 +313,23 @@ shared_ptr posixFileWriter::getOutputStream() // posixFileReader // -posixFileReader::posixFileReader(const vmime::utility::file::path& path, const vmime::string& nativePath) - : m_path(path), m_nativePath(nativePath) -{ +posixFileReader::posixFileReader( + const vmime::utility::file::path& path, + const vmime::string& nativePath +) + : m_path(path), + m_nativePath(nativePath) { + } -shared_ptr posixFileReader::getInputStream() -{ +shared_ptr posixFileReader::getInputStream() { + int fd = 0; - if ((fd = ::open(m_nativePath.c_str(), O_RDONLY, 0640)) == -1) + if ((fd = ::open(m_nativePath.c_str(), O_RDONLY, 0640)) == -1) { posixFileSystemFactory::reportError(m_path, errno); + } return make_shared (m_path, fd); } @@ -298,40 +341,45 @@ shared_ptr posixFileReader::getInputStream() // posixFile::posixFile(const vmime::utility::file::path& path) - : m_path(path), m_nativePath(posixFileSystemFactory::pathToStringImpl(path)) -{ + : m_path(path), + m_nativePath(posixFileSystemFactory::pathToStringImpl(path)) { + } -void posixFile::createFile() -{ +void posixFile::createFile() { + int fd = 0; - if ((fd = ::open(m_nativePath.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660)) == -1) + if ((fd = ::open(m_nativePath.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660)) == -1) { posixFileSystemFactory::reportError(m_path, errno); + } - if (::fsync(fd) == -1) + if (::fsync(fd) == -1) { posixFileSystemFactory::reportError(m_path, errno); + } - if (::close(fd) == -1) + if (::close(fd) == -1) { posixFileSystemFactory::reportError(m_path, errno); + } } -void posixFile::createDirectory(const bool createAll) -{ +void posixFile::createDirectory(const bool createAll) { + createDirectoryImpl(m_path, m_path, createAll); } -bool posixFile::isFile() const -{ +bool posixFile::isFile() const { + struct stat buf; - if (::stat(m_nativePath.c_str(), &buf) == -1) - { - if (errno == ENOENT) + if (::stat(m_nativePath.c_str(), &buf) == -1) { + + if (errno == ENOENT) { return false; + } posixFileSystemFactory::reportError(m_path, errno); return false; @@ -341,14 +389,15 @@ bool posixFile::isFile() const } -bool posixFile::isDirectory() const -{ +bool posixFile::isDirectory() const { + struct stat buf; - if (::stat(m_nativePath.c_str(), &buf) == -1) - { - if (errno == ENOENT) + if (::stat(m_nativePath.c_str(), &buf) == -1) { + + if (errno == ENOENT) { return false; + } posixFileSystemFactory::reportError(m_path, errno); return false; @@ -358,149 +407,165 @@ bool posixFile::isDirectory() const } -bool posixFile::canRead() const -{ +bool posixFile::canRead() const { + struct stat buf; - if (::stat(m_nativePath.c_str(), &buf) == -1) - { - if (errno == ENOENT) + if (::stat(m_nativePath.c_str(), &buf) == -1) { + + if (errno == ENOENT) { return false; + } posixFileSystemFactory::reportError(m_path, errno); return false; } - return S_ISREG(buf.st_mode) && - ::access(m_nativePath.c_str(), R_OK | F_OK) == 0; + return S_ISREG(buf.st_mode) + && ::access(m_nativePath.c_str(), R_OK | F_OK) == 0; } -bool posixFile::canWrite() const -{ +bool posixFile::canWrite() const { + struct stat buf; - if (::stat(m_nativePath.c_str(), &buf) == -1) - { - if (errno == ENOENT) + if (::stat(m_nativePath.c_str(), &buf) == -1) { + + if (errno == ENOENT) { return false; + } posixFileSystemFactory::reportError(m_path, errno); return false; } - return S_ISREG(buf.st_mode) && - ::access(m_nativePath.c_str(), W_OK | F_OK) == 0; + return S_ISREG(buf.st_mode) + && ::access(m_nativePath.c_str(), W_OK | F_OK) == 0; } -posixFile::length_type posixFile::getLength() -{ +posixFile::length_type posixFile::getLength() { + struct stat buf; - if (::stat(m_nativePath.c_str(), &buf) == -1) + if (::stat(m_nativePath.c_str(), &buf) == -1) { posixFileSystemFactory::reportError(m_path, errno); + } return static_cast (buf.st_size); } -const posixFile::path& posixFile::getFullPath() const -{ - return (m_path); +const posixFile::path& posixFile::getFullPath() const { + + return m_path; } -bool posixFile::exists() const -{ +bool posixFile::exists() const { + struct stat buf; - return (::stat(m_nativePath.c_str(), &buf) == 0); + return ::stat(m_nativePath.c_str(), &buf) == 0; } -shared_ptr posixFile::getParent() const -{ - if (m_path.isEmpty()) +shared_ptr posixFile::getParent() const { + + if (m_path.isEmpty()) { return null; - else + } else { return make_shared (m_path.getParent()); + } } -void posixFile::rename(const path& newName) -{ +void posixFile::rename(const path& newName) { + const vmime::string newNativePath = posixFileSystemFactory::pathToStringImpl(newName); posixFile dest(newName); - if (isDirectory()) + if (isDirectory()) { dest.createDirectory(); - else + } else { dest.createFile(); + } - if (::rename(m_nativePath.c_str(), newNativePath.c_str()) == -1) + if (::rename(m_nativePath.c_str(), newNativePath.c_str()) == -1) { posixFileSystemFactory::reportError(m_path, errno); + } m_path = newName; m_nativePath = newNativePath; } -void posixFile::remove() -{ +void posixFile::remove() { + struct stat buf; - if (::stat(m_nativePath.c_str(), &buf) == -1) + if (::stat(m_nativePath.c_str(), &buf) == -1) { posixFileSystemFactory::reportError(m_path, errno); - - if (S_ISDIR(buf.st_mode)) - { - if (::rmdir(m_nativePath.c_str()) == -1) - posixFileSystemFactory::reportError(m_path, errno); } - else if (S_ISREG(buf.st_mode)) - { - if (::unlink(m_nativePath.c_str()) == -1) + + if (S_ISDIR(buf.st_mode)) { + + if (::rmdir(m_nativePath.c_str()) == -1) { posixFileSystemFactory::reportError(m_path, errno); + } + + } else if (S_ISREG(buf.st_mode)) { + + if (::unlink(m_nativePath.c_str()) == -1) { + posixFileSystemFactory::reportError(m_path, errno); + } } } -shared_ptr posixFile::getFileWriter() -{ +shared_ptr posixFile::getFileWriter() { + return make_shared (m_path, m_nativePath); } -shared_ptr posixFile::getFileReader() -{ +shared_ptr posixFile::getFileReader() { + return make_shared (m_path, m_nativePath); } -shared_ptr posixFile::getFiles() const -{ - if (!isDirectory()) +shared_ptr posixFile::getFiles() const { + + if (!isDirectory()) { throw vmime::exceptions::not_a_directory(m_path); + } return make_shared (m_path, m_nativePath); } -void posixFile::createDirectoryImpl(const vmime::utility::file::path& fullPath, - const vmime::utility::file::path& path, const bool recursive) -{ +void posixFile::createDirectoryImpl( + const vmime::utility::file::path& fullPath, + const vmime::utility::file::path& path, + const bool recursive +) { + const vmime::string nativePath = posixFileSystemFactory::pathToStringImpl(path); struct stat buf; - if (::stat(nativePath.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode)) + if (::stat(nativePath.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode)) { return; + } - if (!path.isEmpty() && recursive) + if (!path.isEmpty() && recursive) { createDirectoryImpl(fullPath, path.getParent(), true); + } - if (::mkdir(nativePath.c_str(), 0750) == -1) + if (::mkdir(nativePath.c_str(), 0750) == -1) { posixFileSystemFactory::reportError(fullPath, errno); + } } @@ -509,125 +574,139 @@ void posixFile::createDirectoryImpl(const vmime::utility::file::path& fullPath, // posixFileSystemFactory // -shared_ptr posixFileSystemFactory::create(const vmime::utility::file::path& path) const -{ +shared_ptr posixFileSystemFactory::create( + const vmime::utility::file::path& path +) const { + return make_shared (path); } -const vmime::utility::file::path posixFileSystemFactory::stringToPath(const vmime::string& str) const -{ - return (stringToPathImpl(str)); +const vmime::utility::file::path posixFileSystemFactory::stringToPath( + const vmime::string& str +) const { + + return stringToPathImpl(str); } -const vmime::string posixFileSystemFactory::pathToString(const vmime::utility::file::path& path) const -{ - return (pathToStringImpl(path)); +const vmime::string posixFileSystemFactory::pathToString( + const vmime::utility::file::path& path +) const { + + return pathToStringImpl(path); } -const vmime::utility::file::path posixFileSystemFactory::stringToPathImpl(const vmime::string& str) -{ +const vmime::utility::file::path posixFileSystemFactory::stringToPathImpl( + const vmime::string& str +) { + vmime::size_t offset = 0; vmime::size_t prev = 0; vmime::utility::file::path path; - while ((offset = str.find_first_of("/", offset)) != vmime::string::npos) - { - if (offset != prev) - { - path.appendComponent - (vmime::utility::file::path::component - (vmime::string(str.begin() + prev, str.begin() + offset))); + while ((offset = str.find_first_of("/", offset)) != vmime::string::npos) { + + if (offset != prev) { + + path.appendComponent( + vmime::utility::file::path::component( + vmime::string(str.begin() + prev, str.begin() + offset) + ) + ); } prev = offset + 1; offset++; } - if (prev < str.length()) - { - path.appendComponent - (vmime::utility::file::path::component - (vmime::string(str.begin() + prev, str.end()))); + if (prev < str.length()) { + + path.appendComponent( + vmime::utility::file::path::component( + vmime::string(str.begin() + prev, str.end()) + ) + ); } - return (path); + return path; } -const vmime::string posixFileSystemFactory::pathToStringImpl(const vmime::utility::file::path& path) -{ +const vmime::string posixFileSystemFactory::pathToStringImpl(const vmime::utility::file::path& path) { + vmime::string native = "/"; - for (size_t i = 0 ; i < path.getSize() ; ++i) - { - if (i > 0) + for (size_t i = 0 ; i < path.getSize() ; ++i) { + + if (i > 0) { native += "/"; + } native += path[i].getBuffer(); } - return (native); + return native; } -bool posixFileSystemFactory::isValidPathComponent(const vmime::utility::file::path::component& comp) const -{ - return (comp.getBuffer().find_first_of("/*") == vmime::string::npos); +bool posixFileSystemFactory::isValidPathComponent( + const vmime::utility::file::path::component& comp +) const { + + return comp.getBuffer().find_first_of("/*") == vmime::string::npos; } -bool posixFileSystemFactory::isValidPath(const vmime::utility::file::path& path) const -{ - for (size_t i = 0 ; i < path.getSize() ; ++i) - { - if (!isValidPathComponent(path[i])) +bool posixFileSystemFactory::isValidPath(const vmime::utility::file::path& path) const { + + for (size_t i = 0 ; i < path.getSize() ; ++i) { + + if (!isValidPathComponent(path[i])) { return false; + } } return true; } -void posixFileSystemFactory::reportError(const vmime::utility::path& path, const int err) -{ +void posixFileSystemFactory::reportError(const vmime::utility::path& path, const int err) { + vmime::string desc; - switch (err) - { - case EEXIST: desc = "EEXIST: file already exists."; break; - case EISDIR: desc = "EISDIR: path refers to a directory."; break; - case EACCES: desc = "EACCES: permission denied"; break; - case ENAMETOOLONG: desc = "ENAMETOOLONG: path too long."; break; - case ENOENT: desc = "ENOENT: a directory in the path does not exist."; break; - case ENOTDIR: desc = "ENOTDIR: path is not a directory."; break; - case EROFS: desc = "EROFS: read-only filesystem."; break; - case ELOOP: desc = "ELOOP: too many symbolic links."; break; - case ENOSPC: desc = "ENOSPC: no space left on device."; break; - case ENOMEM: desc = "ENOMEM: insufficient kernel memory."; break; - case EMFILE: desc = "ENFILE: limit on number of files open by the process has been reached."; break; - case ENFILE: desc = "ENFILE: limit on number of files open on the system has been reached."; break; + switch (err) { + case EEXIST: desc = "EEXIST: file already exists."; break; + case EISDIR: desc = "EISDIR: path refers to a directory."; break; + case EACCES: desc = "EACCES: permission denied"; break; + case ENAMETOOLONG: desc = "ENAMETOOLONG: path too long."; break; + case ENOENT: desc = "ENOENT: a directory in the path does not exist."; break; + case ENOTDIR: desc = "ENOTDIR: path is not a directory."; break; + case EROFS: desc = "EROFS: read-only filesystem."; break; + case ELOOP: desc = "ELOOP: too many symbolic links."; break; + case ENOSPC: desc = "ENOSPC: no space left on device."; break; + case ENOMEM: desc = "ENOMEM: insufficient kernel memory."; break; + case EMFILE: desc = "ENFILE: limit on number of files open by the process has been reached."; break; + case ENFILE: desc = "ENFILE: limit on number of files open on the system has been reached."; break; #ifndef AIX - case ENOTEMPTY: desc = "ENOTEMPTY: directory is not empty."; break; + case ENOTEMPTY: desc = "ENOTEMPTY: directory is not empty."; break; #endif - default: + default: - std::ostringstream oss; - oss << ::strerror(err) << "."; + std::ostringstream oss; + oss << ::strerror(err) << "."; - desc = oss.str(); - break; + desc = oss.str(); + break; } throw vmime::exceptions::filesystem_exception(desc, path); } - } // posix } // platforms } // vmime diff --git a/src/vmime/platforms/posix/posixFile.hpp b/src/vmime/platforms/posix/posixFile.hpp index 20a56699..d1fda9e8 100644 --- a/src/vmime/platforms/posix/posixFile.hpp +++ b/src/vmime/platforms/posix/posixFile.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,8 +43,8 @@ namespace platforms { namespace posix { -class posixFileWriterOutputStream : public vmime::utility::outputStream -{ +class posixFileWriterOutputStream : public vmime::utility::outputStream { + public: posixFileWriterOutputStream(const vmime::utility::file::path& path, const int fd); @@ -64,8 +64,8 @@ private: -class posixFileReaderInputStream : public vmime::utility::seekableInputStream -{ +class posixFileReaderInputStream : public vmime::utility::seekableInputStream { + public: posixFileReaderInputStream(const vmime::utility::file::path& path, const int fd); @@ -92,8 +92,8 @@ private: -class posixFileWriter : public vmime::utility::fileWriter -{ +class posixFileWriter : public vmime::utility::fileWriter { + public: posixFileWriter(const vmime::utility::file::path& path, const vmime::string& nativePath); @@ -108,8 +108,8 @@ private: -class posixFileReader : public vmime::utility::fileReader -{ +class posixFileReader : public vmime::utility::fileReader { + public: posixFileReader(const vmime::utility::file::path& path, const vmime::string& nativePath); @@ -124,8 +124,8 @@ private: -class posixFileIterator : public vmime::utility::fileIterator -{ +class posixFileIterator : public vmime::utility::fileIterator { + public: posixFileIterator(const vmime::utility::file::path& path, const vmime::string& nativePath); @@ -147,8 +147,8 @@ private: -class posixFile : public vmime::utility::file -{ +class posixFile : public vmime::utility::file { + public: posixFile(const vmime::utility::file::path& path); @@ -181,7 +181,11 @@ public: private: - static void createDirectoryImpl(const vmime::utility::file::path& fullPath, const vmime::utility::file::path& path, const bool recursive = false); + static void createDirectoryImpl( + const vmime::utility::file::path& fullPath, + const vmime::utility::file::path& path, + const bool recursive = false + ); private: @@ -191,8 +195,8 @@ private: -class posixFileSystemFactory : public vmime::utility::fileSystemFactory -{ +class posixFileSystemFactory : public vmime::utility::fileSystemFactory { + public: shared_ptr create(const vmime::utility::file::path& path) const; diff --git a/src/vmime/platforms/posix/posixHandler.cpp b/src/vmime/platforms/posix/posixHandler.cpp index e0263b2b..20c0f342 100644 --- a/src/vmime/platforms/posix/posixHandler.cpp +++ b/src/vmime/platforms/posix/posixHandler.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -68,27 +68,29 @@ #if VMIME_HAVE_PTHREAD -namespace -{ +namespace { + // This construction ensures mutex will be initialized in compile-time // and will be available any time in the runtime. pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; // Helper lock, to be exception safe all the time. - class PLockHelper - { + class PLockHelper { + public: - PLockHelper() - { - if (pthread_mutex_lock(&g_mutex) != 0) + PLockHelper() { + + if (pthread_mutex_lock(&g_mutex) != 0) { assert(!"unable to lock mutex - thread safety's void"); + } } - ~PLockHelper() - { - if (pthread_mutex_unlock(&g_mutex) != 0) + ~PLockHelper() { + + if (pthread_mutex_unlock(&g_mutex) != 0) { assert(!"unable to unlock mutex - application's dead..."); + } } private: @@ -108,8 +110,8 @@ namespace platforms { namespace posix { -posixHandler::posixHandler() -{ +posixHandler::posixHandler() { + #if VMIME_HAVE_MESSAGING_FEATURES m_socketFactory = make_shared (); #endif @@ -117,22 +119,23 @@ posixHandler::posixHandler() m_fileSysFactory = make_shared (); m_childProcFactory = make_shared (); #endif + } -posixHandler::~posixHandler() -{ +posixHandler::~posixHandler() { + } -unsigned long posixHandler::getUnixTime() const -{ +unsigned long posixHandler::getUnixTime() const { + return static_cast (::time(NULL)); } -const vmime::datetime posixHandler::getCurrentLocalTime() const -{ +const vmime::datetime posixHandler::getCurrentLocalTime() const { + const time_t t(::time(NULL)); // Get the local time @@ -168,20 +171,20 @@ const vmime::datetime posixHandler::getCurrentLocalTime() const } -const vmime::charset posixHandler::getLocalCharset() const -{ +const vmime::charset posixHandler::getLocalCharset() const { + const PLockHelper lock; return vmime::charset(::nl_langinfo(CODESET)); } -static inline bool isAcceptableHostname(const vmime::string& str) -{ +static inline bool isAcceptableHostname(const vmime::string& str) { + // At least, try to find something better than "localhost" if (utility::stringUtils::isStringEqualNoCase(str, "localhost", 9) || - utility::stringUtils::isStringEqualNoCase(str, "localhost.localdomain", 21)) - { + utility::stringUtils::isStringEqualNoCase(str, "localhost.localdomain", 21)) { + return false; } @@ -190,8 +193,8 @@ static inline bool isAcceptableHostname(const vmime::string& str) } -const vmime::string posixHandler::getHostName() const -{ +const vmime::string posixHandler::getHostName() const { + // Try to get official canonical name of this host struct addrinfo hints; memset(&hints, 0, sizeof hints); @@ -201,17 +204,16 @@ const vmime::string posixHandler::getHostName() const struct addrinfo* info; - if (getaddrinfo(NULL, "http", &hints, &info) == 0) - { + if (getaddrinfo(NULL, "http", &hints, &info) == 0) { + // First, try to get a Fully-Qualified Domain Name (FQDN) - for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) - { - if (p->ai_canonname) - { + for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) { + + if (p->ai_canonname) { + const string hn(p->ai_canonname); - if (utility::stringUtils::isValidFQDN(hn)) - { + if (utility::stringUtils::isValidFQDN(hn)) { freeaddrinfo(info); return hn; } @@ -219,14 +221,13 @@ const vmime::string posixHandler::getHostName() const } // Then, try to find an acceptable host name - for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) - { - if (p->ai_canonname) - { + for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) { + + if (p->ai_canonname) { + const string hn(p->ai_canonname); - if (isAcceptableHostname(hn)) - { + if (isAcceptableHostname(hn)) { freeaddrinfo(info); return hn; } @@ -241,21 +242,22 @@ const vmime::string posixHandler::getHostName() const ::gethostname(hostname, sizeof(hostname)); hostname[sizeof(hostname) - 1] = '\0'; - if (::strlen(hostname) == 0 || !isAcceptableHostname(hostname)) + if (::strlen(hostname) == 0 || !isAcceptableHostname(hostname)) { ::strcpy(hostname, "localhost.localdomain"); + } return hostname; } -unsigned int posixHandler::getProcessId() const -{ - return (::getpid()); +unsigned int posixHandler::getProcessId() const { + + return ::getpid(); } -unsigned int posixHandler::getThreadId() const -{ +unsigned int posixHandler::getThreadId() const { + #if VMIME_HAVE_GETTID return static_cast (::gettid()); #elif VMIME_HAVE_SYSCALL && VMIME_HAVE_SYSCALL_GETTID @@ -265,13 +267,14 @@ unsigned int posixHandler::getThreadId() const #else #error We have no implementation of getThreadId() for this platform! #endif + } #if VMIME_HAVE_MESSAGING_FEATURES -shared_ptr posixHandler::getSocketFactory() -{ +shared_ptr posixHandler::getSocketFactory() { + return m_socketFactory; } @@ -280,39 +283,40 @@ shared_ptr posixHandler::getSocketFactory() #if VMIME_HAVE_FILESYSTEM_FEATURES -shared_ptr posixHandler::getFileSystemFactory() -{ +shared_ptr posixHandler::getFileSystemFactory() { + return m_fileSysFactory; } -shared_ptr posixHandler::getChildProcessFactory() -{ +shared_ptr posixHandler::getChildProcessFactory() { + return m_childProcFactory; } #endif -void posixHandler::generateRandomBytes(unsigned char* buffer, const unsigned int count) -{ +void posixHandler::generateRandomBytes(unsigned char* buffer, const unsigned int count) { + int fd = open("/dev/urandom", O_RDONLY); - if (fd != -1) - { + if (fd != -1) { + read(fd, buffer, count); close(fd); - } - else // fallback - { - for (unsigned int i = 0 ; i < count ; ++i) + + } else { // fallback + + for (unsigned int i = 0 ; i < count ; ++i) { buffer[i] = static_cast (rand() % 255); + } } } -shared_ptr posixHandler::createCriticalSection() -{ +shared_ptr posixHandler::createCriticalSection() { + return make_shared (); } diff --git a/src/vmime/platforms/posix/posixHandler.hpp b/src/vmime/platforms/posix/posixHandler.hpp index d9eb4fbd..30417f17 100644 --- a/src/vmime/platforms/posix/posixHandler.hpp +++ b/src/vmime/platforms/posix/posixHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -48,8 +48,8 @@ namespace platforms { namespace posix { -class VMIME_EXPORT posixHandler : public vmime::platform::handler -{ +class VMIME_EXPORT posixHandler : public vmime::platform::handler { + public: posixHandler(); diff --git a/src/vmime/platforms/posix/posixSocket.cpp b/src/vmime/platforms/posix/posixSocket.cpp index e2bdd4b8..aec6a83e 100644 --- a/src/vmime/platforms/posix/posixSocket.cpp +++ b/src/vmime/platforms/posix/posixSocket.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -62,18 +62,17 @@ // Workaround for detection of strerror_r variants #if VMIME_HAVE_STRERROR_R -namespace -{ +namespace { + +char* vmime_strerror_r_result(int /* res */, char* buf) { -char* vmime_strerror_r_result(int /* res */, char* buf) -{ // XSI-compliant prototype: // int strerror_r(int errnum, char *buf, size_t buflen); return buf; } -char* vmime_strerror_r_result(char* res, char* /* buf */) -{ +char* vmime_strerror_r_result(char* res, char* /* buf */) { + // GNU-specific prototype: // char *strerror_r(int errnum, char *buf, size_t buflen); return res; @@ -95,29 +94,31 @@ namespace posix { // posixSocket::posixSocket(shared_ptr th) - : m_timeoutHandler(th), m_desc(-1), m_status(0) -{ + : m_timeoutHandler(th), + m_desc(-1), + m_status(0) { + } -posixSocket::~posixSocket() -{ - if (m_desc != -1) +posixSocket::~posixSocket() { + + if (m_desc != -1) { ::close(m_desc); + } } -void posixSocket::connect(const vmime::string& address, const vmime::port_t port) -{ +void posixSocket::connect(const vmime::string& address, const vmime::port_t port) { + // Close current connection, if any - if (m_desc != -1) - { + if (m_desc != -1) { ::close(m_desc); m_desc = -1; } - if (m_tracer) - { + if (m_tracer) { + std::ostringstream trace; trace << "Connecting to " << address << ", port " << port; @@ -136,20 +137,21 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port int sock = -1; int connectErrno = 0; - if (m_timeoutHandler != NULL) + if (m_timeoutHandler != NULL) { m_timeoutHandler->resetTimeOut(); + } for (struct ::addrinfo* curAddrInfo = addrInfo ; sock == -1 && curAddrInfo != NULL ; - curAddrInfo = curAddrInfo->ai_next, connectErrno = ETIMEDOUT) - { - if (curAddrInfo->ai_family != AF_INET && curAddrInfo->ai_family != AF_INET6) + curAddrInfo = curAddrInfo->ai_next, connectErrno = ETIMEDOUT) { + + if (curAddrInfo->ai_family != AF_INET && curAddrInfo->ai_family != AF_INET6) { continue; + } sock = ::socket(curAddrInfo->ai_family, curAddrInfo->ai_socktype, curAddrInfo->ai_protocol); - if (sock < 0) - { + if (sock < 0) { connectErrno = errno; continue; // try next } @@ -175,33 +177,33 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port #endif // VMIME_HAVE_SO_NOSIGPIPE - if (m_timeoutHandler != NULL) - { + if (m_timeoutHandler) { + ::fcntl(sock, F_SETFL, ::fcntl(sock, F_GETFL) | O_NONBLOCK); - if (::connect(sock, curAddrInfo->ai_addr, curAddrInfo->ai_addrlen) < 0) - { - switch (errno) - { - case 0: - case EINPROGRESS: - case EINTR: + if (::connect(sock, curAddrInfo->ai_addr, curAddrInfo->ai_addrlen) < 0) { + + switch (errno) { + + case 0: + case EINPROGRESS: + case EINTR: #if defined(EAGAIN) - case EAGAIN: + case EAGAIN: #endif // EAGAIN #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) - case EWOULDBLOCK: + case EWOULDBLOCK: #endif // EWOULDBLOCK - // Connection in progress - break; + // Connection in progress + break; - default: + default: - connectErrno = errno; - ::close(sock); - sock = -1; - continue; // try next + connectErrno = errno; + ::close(sock); + sock = -1; + continue; // try next } // Wait for socket to be connected. @@ -213,8 +215,8 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port timeval startTime = { 0, 0 }; gettimeofday(&startTime, /* timezone */ NULL); - do - { + do { + pollfd fds[1]; fds[0].fd = sock; fds[0].events = POLLIN | POLLOUT; @@ -222,33 +224,34 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port const int ret = ::poll(fds, sizeof(fds) / sizeof(fds[0]), pollTimeout); // Success - if (ret > 0) - { - if (fds[0].revents & (POLLIN | POLLOUT)) - { + if (ret > 0) { + + if (fds[0].revents & (POLLIN | POLLOUT)) { + int error = 0; socklen_t len = sizeof(error); - if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) - { + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + connectErrno = errno; - } - else - { - if (error != 0) + + } else { + + if (error != 0) { connectErrno = error; - else + } else { connected = true; + } } } break; - } + // Error - else if (ret < -1) - { - if (errno != EAGAIN && errno != EINTR) - { + } else if (ret < -1) { + + if (errno != EAGAIN && errno != EINTR) { + // Cancel connection connectErrno = errno; break; @@ -256,22 +259,22 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port } // Check for timeout - if (m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - { + if (m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { + // Cancel connection connectErrno = ETIMEDOUT; break; - } - else - { + + } else { + // Reset timeout and keep waiting for connection m_timeoutHandler->resetTimeOut(); } - } - else - { + + } else { + // Keep waiting for connection } @@ -279,33 +282,33 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port gettimeofday(&curTime, /* timezone */ NULL); if (curAddrInfo->ai_next != NULL && - curTime.tv_usec - startTime.tv_usec >= tryNextTimeout * 1000) - { + curTime.tv_usec - startTime.tv_usec >= tryNextTimeout * 1000) { + connectErrno = ETIMEDOUT; break; } } while (true); - if (!connected) - { + if (!connected) { + ::close(sock); sock = -1; continue; // try next } break; - } - else - { + + } else { + // Connection successful break; } - } - else - { - if (::connect(sock, curAddrInfo->ai_addr, curAddrInfo->ai_addrlen) < 0) - { + + } else { + + if (::connect(sock, curAddrInfo->ai_addr, curAddrInfo->ai_addrlen) < 0) { + connectErrno = errno; ::close(sock); sock = -1; @@ -316,16 +319,12 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port ::freeaddrinfo(addrInfo); - if (sock == -1) - { - try - { + if (sock == -1) { + + try { throwSocketError(connectErrno); - } - catch (exceptions::socket_exception& e) - { - throw vmime::exceptions::connection_error - ("Error while connecting socket.", e); + } catch (exceptions::socket_exception& e) { // wrap + throw vmime::exceptions::connection_error("Error while connecting socket.", e); } } @@ -342,12 +341,11 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port addr.sin_port = htons(static_cast (port)); addr.sin_addr.s_addr = ::inet_addr(address.c_str()); - if (addr.sin_addr.s_addr == static_cast (-1)) - { + if (addr.sin_addr.s_addr == static_cast (-1)) { + ::hostent* hostInfo = ::gethostbyname(address.c_str()); - if (hostInfo == NULL) - { + if (hostInfo == NULL) { // Error: cannot resolve address throw vmime::exceptions::connection_error("Cannot resolve address."); } @@ -360,34 +358,29 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port // Get a new socket m_desc = ::socket(AF_INET, SOCK_STREAM, 0); - if (m_desc == -1) - { - try - { + if (m_desc == -1) { + + try { throwSocketError(errno); - } - catch (exceptions::socket_exception& e) - { - throw vmime::exceptions::connection_error - ("Error while creating socket.", e); + } catch (exceptions::socket_exception& e) { // wrap + throw vmime::exceptions::connection_error("Error while creating socket.", e); } } // Start connection - if (::connect(m_desc, reinterpret_cast (&addr), sizeof(addr)) == -1) - { - try - { + if (::connect(m_desc, reinterpret_cast (&addr), sizeof(addr)) == -1) { + + try { + throwSocketError(errno); - } - catch (exceptions::socket_exception& e) - { + + } catch (exceptions::socket_exception& e) { // wrap + ::close(m_desc); m_desc = -1; // Error - throw vmime::exceptions::connection_error - ("Error while connecting socket.", e); + throw vmime::exceptions::connection_error("Error while connecting socket.", e); } } @@ -397,8 +390,12 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port } -void posixSocket::resolve(struct ::addrinfo** addrInfo, const vmime::string& address, const vmime::port_t port) -{ +void posixSocket::resolve( + struct ::addrinfo** addrInfo, + const vmime::string& address, + const vmime::port_t port +) { + char portStr[16]; snprintf(portStr, sizeof(portStr), "%u", static_cast (port)); @@ -425,73 +422,73 @@ void posixSocket::resolve(struct ::addrinfo** addrInfo, const vmime::string& add struct ::gaicb* gaiRequests = &gaiRequest; int gaiError; - if ((gaiError = getaddrinfo_a(GAI_NOWAIT, &gaiRequests, 1, NULL)) != 0) - { - throw vmime::exceptions::connection_error - ("getaddrinfo_a() failed: " + std::string(gai_strerror(gaiError))); + if ((gaiError = getaddrinfo_a(GAI_NOWAIT, &gaiRequests, 1, NULL)) != 0) { + + throw vmime::exceptions::connection_error( + "getaddrinfo_a() failed: " + std::string(gai_strerror(gaiError)) + ); } - if (m_timeoutHandler != NULL) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } + + while (true) { - while (true) - { struct timespec gaiTimeout; gaiTimeout.tv_sec = 1; // query timeout handler every second gaiTimeout.tv_nsec = 0; gaiError = gai_suspend(&gaiRequests, 1, &gaiTimeout); - if (gaiError == 0 || gaiError == EAI_ALLDONE) - { + if (gaiError == 0 || gaiError == EAI_ALLDONE) { + const int ret = gai_error(&gaiRequest); - if (ret != 0) - { - throw vmime::exceptions::connection_error - ("getaddrinfo_a() request failed: " + std::string(gai_strerror(ret))); - } - else - { + if (ret != 0) { + + throw vmime::exceptions::connection_error( + "getaddrinfo_a() request failed: " + std::string(gai_strerror(ret)) + ); + + } else { + *addrInfo = gaiRequest.ar_result; break; } - } - else if (gaiError != EAI_AGAIN) - { - if (gaiError == EAI_SYSTEM) - { + + } else if (gaiError != EAI_AGAIN) { + + if (gaiError == EAI_SYSTEM) { + const int ret = gai_error(&gaiRequest); - if (ret != EAI_INPROGRESS && errno != 0) - { - try - { + if (ret != EAI_INPROGRESS && errno != 0) { + + try { throwSocketError(errno); - } - catch (exceptions::socket_exception& e) - { - throw vmime::exceptions::connection_error - ("Error while connecting socket.", e); + } catch (exceptions::socket_exception& e) { // wrap + throw vmime::exceptions::connection_error("Error while connecting socket.", e); } } - } - else - { - throw vmime::exceptions::connection_error - ("gai_suspend() failed: " + std::string(gai_strerror(gaiError))); + + } else { + + throw vmime::exceptions::connection_error( + "gai_suspend() failed: " + std::string(gai_strerror(gaiError)) + ); } } // Check for timeout - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - { + if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { + throw exceptions::operation_timed_out(); - } - else - { + + } else { + // Reset timeout and keep waiting for connection m_timeoutHandler->resetTimeOut(); } @@ -500,8 +497,8 @@ void posixSocket::resolve(struct ::addrinfo** addrInfo, const vmime::string& add #else // !VMIME_HAVE_GETADDRINFO_A - if (::getaddrinfo(address.c_str(), portStr, &hints, addrInfo) != 0) - { + if (::getaddrinfo(address.c_str(), portStr, &hints, addrInfo) != 0) { + // Error: cannot resolve address throw vmime::exceptions::connection_error("Cannot resolve address."); } @@ -511,10 +508,11 @@ void posixSocket::resolve(struct ::addrinfo** addrInfo, const vmime::string& add } -bool posixSocket::isConnected() const -{ - if (m_desc == -1) +bool posixSocket::isConnected() const { + + if (m_desc == -1) { return false; + } char buff; @@ -522,12 +520,13 @@ bool posixSocket::isConnected() const } -void posixSocket::disconnect() -{ - if (m_desc != -1) - { - if (m_tracer) +void posixSocket::disconnect() { + + if (m_desc != -1) { + + if (m_tracer) { m_tracer->traceSend("Disconnecting"); + } ::shutdown(m_desc, SHUT_RDWR); ::close(m_desc); @@ -537,8 +536,7 @@ void posixSocket::disconnect() } -static bool isNumericAddress(const char* address) -{ +static bool isNumericAddress(const char* address) { #if VMIME_HAVE_GETADDRINFO @@ -548,13 +546,13 @@ static bool isNumericAddress(const char* address) hint.ai_family = AF_UNSPEC; hint.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(address, 0, &hint, &info) == 0) - { + if (getaddrinfo(address, 0, &hint, &info) == 0) { + freeaddrinfo(info); return true; - } - else - { + + } else { + return false; } @@ -567,22 +565,20 @@ static bool isNumericAddress(const char* address) } -const string posixSocket::getPeerAddress() const -{ +const string posixSocket::getPeerAddress() const { + // Get address of connected peer sockaddr peer; socklen_t peerLen = sizeof(peer); - if (getpeername(m_desc, &peer, &peerLen) != 0) - { + if (getpeername(m_desc, &peer, &peerLen) != 0) { throwSocketError(errno); } // Convert to numerical presentation format char buf[INET6_ADDRSTRLEN]; - if (!inet_ntop(peer.sa_family, &(reinterpret_cast (&peer))->sin_addr, buf, sizeof(buf))) - { + if (!inet_ntop(peer.sa_family, &(reinterpret_cast (&peer))->sin_addr, buf, sizeof(buf))) { throwSocketError(errno); } @@ -590,21 +586,19 @@ const string posixSocket::getPeerAddress() const } -const string posixSocket::getPeerName() const -{ +const string posixSocket::getPeerName() const { + // Get address of connected peer sockaddr peer; socklen_t peerLen = sizeof(peer); - if (getpeername(m_desc, &peer, &peerLen) != 0) - { + if (getpeername(m_desc, &peer, &peerLen) != 0) { throwSocketError(errno); } // If server address as specified when connecting is a numeric // address, try to get a host name for it - if (isNumericAddress(m_serverAddress.c_str())) - { + if (isNumericAddress(m_serverAddress.c_str())) { #if VMIME_HAVE_GETNAMEINFO @@ -613,8 +607,8 @@ const string posixSocket::getPeerName() const if (getnameinfo(reinterpret_cast (&peer), peerLen, host, sizeof(host), service, sizeof(service), - /* flags */ NI_NAMEREQD) == 0) - { + /* flags */ NI_NAMEREQD) == 0) { + return string(host); } @@ -623,8 +617,8 @@ const string posixSocket::getPeerName() const struct hostent *hp; if ((hp = gethostbyaddr(reinterpret_cast (&peer), - sizeof(peer), peer.sa_family)) != NULL) - { + sizeof(peer), peer.sa_family)) != NULL) { + return string(hp->h_name); } @@ -636,52 +630,56 @@ const string posixSocket::getPeerName() const } -size_t posixSocket::getBlockSize() const -{ +size_t posixSocket::getBlockSize() const { + return 16384; // 16 KB } -bool posixSocket::waitForData(const bool read, const bool write, const int msecs) -{ - for (int i = 0 ; i <= msecs / 10 ; ++i) - { +bool posixSocket::waitForData(const bool read, const bool write, const int msecs) { + + for (int i = 0 ; i <= msecs / 10 ; ++i) { + // Check whether data is available pollfd fds[1]; fds[0].fd = m_desc; fds[0].events = 0; - if (read) + if (read) { fds[0].events |= POLLIN; + } - if (write) + if (write) { fds[0].events |= POLLOUT; + } const int ret = ::poll(fds, sizeof(fds) / sizeof(fds[0]), 10 /* ms */); - if (ret < 0) - { - if (errno != EAGAIN && errno != EINTR) + if (ret < 0) { + + if (errno != EAGAIN && errno != EINTR) { throwSocketError(errno); - } - else if (ret > 0) - { - if (fds[0].revents & (POLLIN | POLLOUT)) + } + + } else if (ret > 0) { + + if (fds[0].revents & (POLLIN | POLLOUT)) { return true; + } } // No data available at this time // Check if we are timed out if (m_timeoutHandler && - m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - { + m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { + // Server did not react within timeout delay throw exceptions::operation_timed_out(); - } - else - { + + } else { + // Reset timeout m_timeoutHandler->resetTimeOut(); } @@ -692,32 +690,32 @@ bool posixSocket::waitForData(const bool read, const bool write, const int msecs } -bool posixSocket::waitForRead(const int msecs) -{ +bool posixSocket::waitForRead(const int msecs) { + return waitForData(/* read */ true, /* write */ false, msecs); } -bool posixSocket::waitForWrite(const int msecs) -{ +bool posixSocket::waitForWrite(const int msecs) { + return waitForData(/* read */ false, /* write */ true, msecs); } -void posixSocket::receive(vmime::string& buffer) -{ +void posixSocket::receive(vmime::string& buffer) { + const size_t size = receiveRaw(m_buffer, sizeof(m_buffer)); buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size); } -size_t posixSocket::receiveRaw(byte_t* buffer, const size_t count) -{ +size_t posixSocket::receiveRaw(byte_t* buffer, const size_t count) { + m_status &= ~STATUS_WOULDBLOCK; // Check whether data is available - if (!waitForRead(50 /* msecs */)) - { + if (!waitForRead(50 /* msecs */)) { + m_status |= STATUS_WOULDBLOCK; // Continue waiting for data @@ -727,22 +725,23 @@ size_t posixSocket::receiveRaw(byte_t* buffer, const size_t count) // Read available data ssize_t ret = ::recv(m_desc, buffer, count, 0); - if (ret < 0) - { - if (!IS_EAGAIN(errno)) + if (ret < 0) { + + if (!IS_EAGAIN(errno)) { throwSocketError(errno); + } // Check if we are timed out if (m_timeoutHandler && - m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - { + m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { + // Server did not react within timeout delay throwSocketError(errno); - } - else - { + + } else { + // Reset timeout m_timeoutHandler->resetTimeOut(); } @@ -752,43 +751,43 @@ size_t posixSocket::receiveRaw(byte_t* buffer, const size_t count) // No data available at this time return 0; - } - else if (ret == 0) - { + + } else if (ret == 0) { + // Host shutdown throwSocketError(ENOTCONN); - } - else - { + + } else { + // Data received, reset timeout - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } } return ret; } -void posixSocket::send(const vmime::string& buffer) -{ +void posixSocket::send(const vmime::string& buffer) { + sendRaw(reinterpret_cast (buffer.data()), buffer.length()); } -void posixSocket::send(const char* str) -{ +void posixSocket::send(const char* str) { + sendRaw(reinterpret_cast (str), ::strlen(str)); } -void posixSocket::sendRaw(const byte_t* buffer, const size_t count) -{ +void posixSocket::sendRaw(const byte_t* buffer, const size_t count) { + m_status &= ~STATUS_WOULDBLOCK; size_t size = count; - while (size > 0) - { + while (size > 0) { #if VMIME_HAVE_MSG_NOSIGNAL const ssize_t ret = ::send(m_desc, buffer, size, MSG_NOSIGNAL); @@ -796,28 +795,30 @@ void posixSocket::sendRaw(const byte_t* buffer, const size_t count) const ssize_t ret = ::send(m_desc, buffer, size, 0); #endif - if (ret <= 0) - { - if (ret < 0 && !IS_EAGAIN(errno)) + if (ret <= 0) { + + if (ret < 0 && !IS_EAGAIN(errno)) { throwSocketError(errno); + } waitForWrite(50 /* msecs */); - } - else - { + + } else { + buffer += ret; size -= ret; } } // Reset timeout - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } } -size_t posixSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) -{ +size_t posixSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) { + m_status &= ~STATUS_WOULDBLOCK; #if VMIME_HAVE_MSG_NOSIGNAL @@ -826,22 +827,23 @@ size_t posixSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) const ssize_t ret = ::send(m_desc, buffer, count, 0); #endif - if (ret <= 0) - { - if (ret < 0 && !IS_EAGAIN(errno)) + if (ret <= 0) { + + if (ret < 0 && !IS_EAGAIN(errno)) { throwSocketError(errno); + } // Check if we are timed out if (m_timeoutHandler && - m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - { + m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { + // Could not send data within timeout delay throw exceptions::operation_timed_out(); - } - else - { + + } else { + // Reset timeout m_timeoutHandler->resetTimeOut(); } @@ -854,51 +856,57 @@ size_t posixSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) } // Reset timeout - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } return ret; } -void posixSocket::throwSocketError(const int err) -{ +void posixSocket::throwSocketError(const int err) { + const char* msg = NULL; - switch (err) - { - case EACCES: msg = "EACCES: permission denied"; break; - case EAFNOSUPPORT: msg = "EAFNOSUPPORT: address family not supported"; break; - case EMFILE: msg = "EMFILE: process file table overflow"; break; - case ENFILE: msg = "ENFILE: system limit reached"; break; - case EPROTONOSUPPORT: msg = "EPROTONOSUPPORT: protocol not supported"; break; - case EAGAIN: msg = "EGAIN: blocking operation"; break; - case EBADF: msg = "EBADF: invalid descriptor"; break; - case ECONNRESET: msg = "ECONNRESET: connection reset by peer"; break; - case EFAULT: msg = "EFAULT: bad user space address"; break; - case EINTR: msg = "EINTR: signal occurred before transmission"; break; - case EINVAL: msg = "EINVAL: invalid argument"; break; - case EMSGSIZE: msg = "EMSGSIZE: message cannot be sent atomically"; break; - case ENOBUFS: msg = "ENOBUFS: output queue is full"; break; - case ENOMEM: msg = "ENOMEM: out of memory"; break; - case EPIPE: msg = "EPIPE: broken pipe"; break; - case ENOTCONN: msg = "ENOTCONN: not connected"; break; - case ECONNREFUSED: msg = "ECONNREFUSED: connection refused"; break; + switch (err) { + + case EACCES: msg = "EACCES: permission denied"; break; + case EAFNOSUPPORT: msg = "EAFNOSUPPORT: address family not supported"; break; + case EMFILE: msg = "EMFILE: process file table overflow"; break; + case ENFILE: msg = "ENFILE: system limit reached"; break; + case EPROTONOSUPPORT: msg = "EPROTONOSUPPORT: protocol not supported"; break; + case EAGAIN: msg = "EGAIN: blocking operation"; break; + case EBADF: msg = "EBADF: invalid descriptor"; break; + case ECONNRESET: msg = "ECONNRESET: connection reset by peer"; break; + case EFAULT: msg = "EFAULT: bad user space address"; break; + case EINTR: msg = "EINTR: signal occurred before transmission"; break; + case EINVAL: msg = "EINVAL: invalid argument"; break; + case EMSGSIZE: msg = "EMSGSIZE: message cannot be sent atomically"; break; + case ENOBUFS: msg = "ENOBUFS: output queue is full"; break; + case ENOMEM: msg = "ENOMEM: out of memory"; break; + case EPIPE: msg = "EPIPE: broken pipe"; break; + case ENOTCONN: msg = "ENOTCONN: not connected"; break; + case ECONNREFUSED: msg = "ECONNREFUSED: connection refused"; break; } - if (msg) - { + if (msg) { + throw exceptions::socket_exception(msg); - } - else - { + + } else { // Use strerror() to get string describing error number #if VMIME_HAVE_STRERROR_R char errbuf[512]; - throw exceptions::socket_exception(vmime_strerror_r_result(strerror_r(err, errbuf, sizeof(errbuf)), errbuf)); + + throw exceptions::socket_exception( + vmime_strerror_r_result( + strerror_r(err, errbuf, sizeof(errbuf)), + errbuf + ) + ); #else // !VMIME_HAVE_STRERROR_R @@ -911,26 +919,26 @@ void posixSocket::throwSocketError(const int err) } -unsigned int posixSocket::getStatus() const -{ +unsigned int posixSocket::getStatus() const { + return m_status; } -shared_ptr posixSocket::getTimeoutHandler() -{ +shared_ptr posixSocket::getTimeoutHandler() { + return m_timeoutHandler; } -void posixSocket::setTracer(const shared_ptr & tracer) -{ +void posixSocket::setTracer(const shared_ptr & tracer) { + m_tracer = tracer; } -shared_ptr posixSocket::getTracer() -{ +shared_ptr posixSocket::getTracer() { + return m_tracer; } @@ -940,15 +948,15 @@ shared_ptr posixSocket::getTracer() // posixSocketFactory // -shared_ptr posixSocketFactory::create() -{ +shared_ptr posixSocketFactory::create() { + shared_ptr th; return make_shared (th); } -shared_ptr posixSocketFactory::create(const shared_ptr & th) -{ +shared_ptr posixSocketFactory::create(const shared_ptr & th) { + return make_shared (th); } diff --git a/src/vmime/platforms/posix/posixSocket.hpp b/src/vmime/platforms/posix/posixSocket.hpp index f253c17b..7d732b74 100644 --- a/src/vmime/platforms/posix/posixSocket.hpp +++ b/src/vmime/platforms/posix/posixSocket.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,8 +42,8 @@ namespace platforms { namespace posix { -class posixSocket : public vmime::net::socket -{ +class posixSocket : public vmime::net::socket { + public: posixSocket(shared_ptr th); @@ -99,8 +99,8 @@ private: -class posixSocketFactory : public vmime::net::socketFactory -{ +class posixSocketFactory : public vmime::net::socketFactory { + public: shared_ptr create(); diff --git a/src/vmime/platforms/windows/windowsCodepages.hpp b/src/vmime/platforms/windows/windowsCodepages.hpp index e66b2303..1457c59a 100644 --- a/src/vmime/platforms/windows/windowsCodepages.hpp +++ b/src/vmime/platforms/windows/windowsCodepages.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,12 +39,10 @@ namespace platforms { namespace windows { -class windowsCodepages -{ -public: +struct windowsCodepages { + + static int getByName(const char* s8_Name) { - static int getByName(const char* s8_Name) - { if (stricmp(s8_Name, "ASMO-708") == 0) return 708; if (stricmp(s8_Name, "big5") == 0) return 950; if (stricmp(s8_Name, "cp1025") == 0) return 21025; diff --git a/src/vmime/platforms/windows/windowsCriticalSection.cpp b/src/vmime/platforms/windows/windowsCriticalSection.cpp index d6ef0c45..c0a0bec4 100644 --- a/src/vmime/platforms/windows/windowsCriticalSection.cpp +++ b/src/vmime/platforms/windows/windowsCriticalSection.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,26 +35,26 @@ namespace platforms { namespace windows { -windowsCriticalSection::windowsCriticalSection() -{ +windowsCriticalSection::windowsCriticalSection() { + InitializeCriticalSectionAndSpinCount(&m_cs, 0x400); } -windowsCriticalSection::~windowsCriticalSection() -{ +windowsCriticalSection::~windowsCriticalSection() { + DeleteCriticalSection(&m_cs); } -void windowsCriticalSection::lock() -{ +void windowsCriticalSection::lock() { + EnterCriticalSection(&m_cs); } -void windowsCriticalSection::unlock() -{ +void windowsCriticalSection::unlock() { + LeaveCriticalSection(&m_cs); } diff --git a/src/vmime/platforms/windows/windowsCriticalSection.hpp b/src/vmime/platforms/windows/windowsCriticalSection.hpp index 7ed07835..ffe82942 100644 --- a/src/vmime/platforms/windows/windowsCriticalSection.hpp +++ b/src/vmime/platforms/windows/windowsCriticalSection.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,8 +42,8 @@ namespace platforms { namespace windows { -class windowsCriticalSection : public utility::sync::criticalSection -{ +class windowsCriticalSection : public utility::sync::criticalSection { + public: windowsCriticalSection(); diff --git a/src/vmime/platforms/windows/windowsFile.cpp b/src/vmime/platforms/windows/windowsFile.cpp index b743641b..774731c7 100644 --- a/src/vmime/platforms/windows/windowsFile.cpp +++ b/src/vmime/platforms/windows/windowsFile.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,152 +41,179 @@ namespace platforms { namespace windows { -shared_ptr windowsFileSystemFactory::create(const vmime::utility::file::path& path) const -{ +shared_ptr windowsFileSystemFactory::create( + const vmime::utility::file::path& path +) const { + return make_shared (path); } -const vmime::utility::file::path windowsFileSystemFactory::stringToPath(const vmime::string& str) const -{ - return (stringToPathImpl(str)); +const vmime::utility::file::path windowsFileSystemFactory::stringToPath( + const vmime::string& str +) const { + + return stringToPathImpl(str); } -const vmime::string windowsFileSystemFactory::pathToString(const vmime::utility::file::path& path) const -{ - return (pathToStringImpl(path)); +const vmime::string windowsFileSystemFactory::pathToString( + const vmime::utility::file::path& path +) const { + + return pathToStringImpl(path); } -const vmime::utility::file::path windowsFileSystemFactory::stringToPathImpl(const vmime::string& str) -{ +const vmime::utility::file::path windowsFileSystemFactory::stringToPathImpl( + const vmime::string& str +) { + vmime::size_t offset = 0; vmime::size_t prev = 0; vmime::utility::file::path path; - while ((offset = str.find_first_of("\\", offset)) != vmime::string::npos) - { - if (offset != prev) - { - path.appendComponent - (vmime::utility::file::path::component - (vmime::string(str.begin() + prev, str.begin() + offset))); + while ((offset = str.find_first_of("\\", offset)) != vmime::string::npos) { + + if (offset != prev) { + + path.appendComponent( + vmime::utility::file::path::component( + vmime::string(str.begin() + prev, str.begin() + offset) + ) + ); } prev = offset + 1; offset++; } - if (prev < str.length()) - { - path.appendComponent - (vmime::utility::file::path::component - (vmime::string(str.begin() + prev, str.end()))); + if (prev < str.length()) { + + path.appendComponent( + vmime::utility::file::path::component( + vmime::string(str.begin() + prev, str.end()) + ) + ); } - return (path); + return path; } -const vmime::string windowsFileSystemFactory::pathToStringImpl(const vmime::utility::file::path& path) -{ +const vmime::string windowsFileSystemFactory::pathToStringImpl( + const vmime::utility::file::path& path +) { + vmime::string native = ""; - for (int i = 0 ; i < path.getSize() ; ++i) - { - if (i > 0) + for (int i = 0 ; i < path.getSize() ; ++i) { + + if (i > 0) { native += "\\"; + } native += path[i].getBuffer(); } - return (native); + return native; } -bool windowsFileSystemFactory::isValidPathComponent(const vmime::utility::file::path::component& comp) const -{ + +bool windowsFileSystemFactory::isValidPathComponent( + const vmime::utility::file::path::component& comp +) const { + return isValidPathComponent(comp, false); } + bool windowsFileSystemFactory::isValidPathComponent( const vmime::utility::file::path::component& comp, - bool firstComponent) const -{ + bool firstComponent +) const { + const string& buffer = comp.getBuffer(); // If first component, check if component is a drive - if (firstComponent && (buffer.length() == 2) && (buffer[1] == ':')) - { + if (firstComponent && (buffer.length() == 2) && (buffer[1] == ':')) { + char drive = tolower(buffer[0]); - if ((drive >= 'a') && (drive <= 'z')) + + if ((drive >= 'a') && (drive <= 'z')) { return true; + } } // Check for invalid characters - for (size_t i = 0 ; i < buffer.length() ; ++i) - { + for (size_t i = 0 ; i < buffer.length() ; ++i) { + const unsigned char c = buffer[i]; - switch (c) - { - // Reserved characters - case '<': case '>': case ':': - case '"': case '/': case '\\': - case '|': case '$': case '*': + switch (c) { - return false; + // Reserved characters + case '<': case '>': case ':': + case '"': case '/': case '\\': + case '|': case '$': case '*': - default: - - if (c <= 31) return false; + + default: + + if (c <= 31) { + return false; + } } } string upperBuffer = vmime::utility::stringUtils::toUpper(buffer); // Check for reserved names - if (upperBuffer.length() == 3) - { - if (upperBuffer == "CON" || buffer == "PRN" || buffer == "AUX" || buffer == "NUL") + if (upperBuffer.length() == 3) { + + if (upperBuffer == "CON" || buffer == "PRN" || buffer == "AUX" || buffer == "NUL") { return false; - } - else if (upperBuffer.length() == 4) - { + } + + } else if (upperBuffer.length() == 4) { + if ((upperBuffer.substr(0, 3) == "COM") && // COM0 to COM9 - (upperBuffer[3] >= '0') && (upperBuffer[3] <= '9')) - { + (upperBuffer[3] >= '0') && (upperBuffer[3] <= '9')) { + + return false; + + } else if ((upperBuffer.substr(0, 3) == "LPT") && // LPT0 to LPT9 + (upperBuffer[3] >= '0') && (upperBuffer[3] <= '9')) { + return false; } - else if ((upperBuffer.substr(0, 3) == "LPT") && // LPT0 to LPT9 - (upperBuffer[3] >= '0') && (upperBuffer[3] <= '9')) - { - return false; - } - } - return true; -} - - -bool windowsFileSystemFactory::isValidPath(const vmime::utility::file::path& path) const -{ - for (int i = 0 ; i < path.getSize() ; ++i) - { - if (!isValidPathComponent(path[i], (i==0))) - return false; } return true; } -void windowsFileSystemFactory::reportError(const vmime::utility::path& path, const int err) -{ +bool windowsFileSystemFactory::isValidPath(const vmime::utility::file::path& path) const { + + for (int i = 0 ; i < path.getSize() ; ++i) { + + if (!isValidPathComponent(path[i], (i == 0))) { + return false; + } + } + + return true; +} + + +void windowsFileSystemFactory::reportError(const vmime::utility::path& path, const int err) { + vmime::string desc; LPVOID lpMsgBuf; + if (FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | @@ -196,22 +223,27 @@ void windowsFileSystemFactory::reportError(const vmime::utility::path& path, con MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, - NULL )) - { - desc = (char*)lpMsgBuf; - LocalFree( lpMsgBuf ); + NULL)) { + + desc = (char*) lpMsgBuf; + LocalFree(lpMsgBuf); } throw vmime::exceptions::filesystem_exception(desc, path); } + + + windowsFile::windowsFile(const vmime::utility::file::path& path) -: m_path(path), m_nativePath(windowsFileSystemFactory::pathToStringImpl(path)) -{ + : m_path(path), + m_nativePath(windowsFileSystemFactory::pathToStringImpl(path)) { + } -void windowsFile::createFile() -{ + +void windowsFile::createFile() { + HANDLE hFile = CreateFile( m_nativePath.c_str(), GENERIC_WRITE, @@ -219,36 +251,49 @@ void windowsFile::createFile() NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, - NULL); - if (hFile == INVALID_HANDLE_VALUE) + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { windowsFileSystemFactory::reportError(m_path, GetLastError()); + } CloseHandle(hFile); } -void windowsFile::createDirectory(const bool createAll) -{ + +void windowsFile::createDirectory(const bool createAll) { + createDirectoryImpl(m_path, m_path, createAll); } -bool windowsFile::isFile() const -{ + +bool windowsFile::isFile() const { + DWORD dwFileAttribute = GetFileAttributes(m_nativePath.c_str()); - if (dwFileAttribute == INVALID_FILE_ATTRIBUTES) + + if (dwFileAttribute == INVALID_FILE_ATTRIBUTES) { return false; + } + return (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY) == 0; } -bool windowsFile::isDirectory() const -{ + +bool windowsFile::isDirectory() const { + DWORD dwFileAttribute = GetFileAttributes(m_nativePath.c_str()); - if (dwFileAttribute == INVALID_FILE_ATTRIBUTES) + + if (dwFileAttribute == INVALID_FILE_ATTRIBUTES) { return false; + } + return (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY; } -bool windowsFile::canRead() const -{ + +bool windowsFile::canRead() const { + HANDLE hFile = CreateFile( m_nativePath.c_str(), GENERIC_READ, @@ -256,15 +301,21 @@ bool windowsFile::canRead() const NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, - NULL); - if (hFile == INVALID_HANDLE_VALUE) + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { return false; + } + CloseHandle(hFile); + return true; } -bool windowsFile::canWrite() const -{ + +bool windowsFile::canWrite() const { + HANDLE hFile = CreateFile( m_nativePath.c_str(), GENERIC_WRITE, @@ -272,15 +323,21 @@ bool windowsFile::canWrite() const NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, - NULL); - if (hFile == INVALID_HANDLE_VALUE) + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { return false; + } + CloseHandle(hFile); + return true; } -windowsFile::length_type windowsFile::getLength() -{ + +windowsFile::length_type windowsFile::getLength() { + HANDLE hFile = CreateFile( m_nativePath.c_str(), GENERIC_READ, @@ -288,158 +345,212 @@ windowsFile::length_type windowsFile::getLength() NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, - NULL); - if (hFile == INVALID_HANDLE_VALUE) + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { windowsFileSystemFactory::reportError(m_path, GetLastError()); + } DWORD dwSize = GetFileSize(hFile, NULL); + CloseHandle(hFile); return dwSize; } -const vmime::utility::path& windowsFile::getFullPath() const -{ + +const vmime::utility::path& windowsFile::getFullPath() const { + return m_path; } -bool windowsFile::exists() const -{ + +bool windowsFile::exists() const { + WIN32_FIND_DATA findData; HANDLE hFind = FindFirstFile(m_nativePath.c_str(), &findData); - if (hFind != INVALID_HANDLE_VALUE) - { + + if (hFind != INVALID_HANDLE_VALUE) { FindClose(hFind); return true; } + return false; } -shared_ptr windowsFile::getParent() const -{ - if (m_path.isEmpty()) + +shared_ptr windowsFile::getParent() const { + + if (m_path.isEmpty()) { return null; - else + } else { return make_shared (m_path.getParent()); + } } -void windowsFile::rename(const path& newName) -{ + +void windowsFile::rename(const path& newName) { + const vmime::string newNativeName = windowsFileSystemFactory::pathToStringImpl(newName); - if (MoveFile(m_nativePath.c_str(), newNativeName.c_str())) - { + + if (MoveFile(m_nativePath.c_str(), newNativeName.c_str())) { + m_path = newName; m_nativePath = newNativeName; + + } else { + + windowsFileSystemFactory::reportError(m_path, GetLastError()); } - else - windowsFileSystemFactory::reportError(m_path, GetLastError()); } -void windowsFile::remove() -{ - if (!DeleteFile(m_nativePath.c_str())) + +void windowsFile::remove() { + + if (!DeleteFile(m_nativePath.c_str())) { windowsFileSystemFactory::reportError(m_path, GetLastError()); + } } -shared_ptr windowsFile::getFileWriter() -{ + +shared_ptr windowsFile::getFileWriter() { + return make_shared (m_path, m_nativePath); } -shared_ptr windowsFile::getFileReader() -{ + +shared_ptr windowsFile::getFileReader() { + return make_shared (m_path, m_nativePath); } -shared_ptr windowsFile::getFiles() const -{ + +shared_ptr windowsFile::getFiles() const { + return make_shared (m_path, m_nativePath); } -void windowsFile::createDirectoryImpl(const vmime::utility::file::path& fullPath, const vmime::utility::file::path& path, const bool recursive) -{ + +void windowsFile::createDirectoryImpl( + const vmime::utility::file::path& fullPath, + const vmime::utility::file::path& path, + const bool recursive +) { + const vmime::string nativePath = windowsFileSystemFactory::pathToStringImpl(path); windowsFile tmp(path); - if (tmp.isDirectory()) + + if (tmp.isDirectory()) { return; + } - if (!path.isEmpty() && recursive) + if (!path.isEmpty() && recursive) { createDirectoryImpl(fullPath, path.getParent(), true); + } - if (!CreateDirectory(nativePath.c_str(), NULL)) + if (!CreateDirectory(nativePath.c_str(), NULL)) { windowsFileSystemFactory::reportError(fullPath, GetLastError()); + } } -windowsFileIterator::windowsFileIterator(const vmime::utility::file::path& path, const vmime::string& nativePath) -: m_path(path), m_nativePath(nativePath), m_moreElements(false), m_hFind(INVALID_HANDLE_VALUE) -{ + + +windowsFileIterator::windowsFileIterator( + const vmime::utility::file::path& path, + const vmime::string& nativePath +) + : m_path(path), + m_nativePath(nativePath), + m_moreElements(false), + m_hFind(INVALID_HANDLE_VALUE) { + findFirst(); } -windowsFileIterator::~windowsFileIterator() -{ - if (m_hFind != INVALID_HANDLE_VALUE) + +windowsFileIterator::~windowsFileIterator() { + + if (m_hFind != INVALID_HANDLE_VALUE) { FindClose(m_hFind); + } } -bool windowsFileIterator::hasMoreElements() const -{ + +bool windowsFileIterator::hasMoreElements() const { + return m_moreElements; } -shared_ptr windowsFileIterator::nextElement() -{ - shared_ptr pFile = make_shared - (m_path / vmime::utility::file::path::component(m_findData.cFileName)); + +shared_ptr windowsFileIterator::nextElement() { + + shared_ptr pFile = make_shared ( + m_path / vmime::utility::file::path::component(m_findData.cFileName) + ); findNext(); return pFile; } -void windowsFileIterator::findFirst() -{ + +void windowsFileIterator::findFirst() { + m_hFind = FindFirstFile(m_nativePath.c_str(), &m_findData); - if (m_hFind == INVALID_HANDLE_VALUE) - { + + if (m_hFind == INVALID_HANDLE_VALUE) { m_moreElements = false; return; } m_moreElements = true; - if (isCurrentOrParentDir()) + + if (isCurrentOrParentDir()) { findNext(); + } } -void windowsFileIterator::findNext() -{ - do - { - if (!FindNextFile(m_hFind, &m_findData)) - { + +void windowsFileIterator::findNext() { + + do { + + if (!FindNextFile(m_hFind, &m_findData)) { m_moreElements = false; return; } - } - while (isCurrentOrParentDir()); + + } while (isCurrentOrParentDir()); } -bool windowsFileIterator::isCurrentOrParentDir() const -{ + +bool windowsFileIterator::isCurrentOrParentDir() const { + vmime::string s(m_findData.cFileName); - if ((s == ".") || (s == "..")) + + if ((s == ".") || (s == "..")) { return true; + } + return false; } -windowsFileReader::windowsFileReader(const vmime::utility::file::path& path, const vmime::string& nativePath) -: m_path(path), m_nativePath(nativePath) -{ + + +windowsFileReader::windowsFileReader( + const vmime::utility::file::path& path, + const vmime::string& nativePath +) + : m_path(path), + m_nativePath(nativePath) { + } -shared_ptr windowsFileReader::getInputStream() -{ + +shared_ptr windowsFileReader::getInputStream() { + HANDLE hFile = CreateFile( m_nativePath.c_str(), GENERIC_READ, @@ -447,74 +558,101 @@ shared_ptr windowsFileReader::getInputStream() NULL, OPEN_EXISTING, 0, - NULL); - if (hFile == INVALID_HANDLE_VALUE) + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { windowsFileSystemFactory::reportError(m_path, GetLastError()); + } + return make_shared (m_path, hFile); } -windowsFileReaderInputStream::windowsFileReaderInputStream(const vmime::utility::file::path& path, HANDLE hFile) -: m_path(path), m_hFile(hFile) -{ + +windowsFileReaderInputStream::windowsFileReaderInputStream( + const vmime::utility::file::path& path, + HANDLE hFile +) + : m_path(path), + m_hFile(hFile) { + } -windowsFileReaderInputStream::~windowsFileReaderInputStream() -{ +windowsFileReaderInputStream::~windowsFileReaderInputStream() { + CloseHandle(m_hFile); } -bool windowsFileReaderInputStream::eof() const -{ + +bool windowsFileReaderInputStream::eof() const { + DWORD dwSize = GetFileSize(m_hFile, NULL); DWORD dwPosition = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT); - return (dwSize == dwPosition); + + return dwSize == dwPosition; } -void windowsFileReaderInputStream::reset() -{ + +void windowsFileReaderInputStream::reset() { + SetFilePointer(m_hFile, 0, NULL, FILE_BEGIN); } -size_t windowsFileReaderInputStream::read(byte_t* const data, const size_t count) -{ + +size_t windowsFileReaderInputStream::read(byte_t* const data, const size_t count) { + DWORD dwBytesRead; - if (!ReadFile(m_hFile, (LPVOID)data, (DWORD)count, &dwBytesRead, NULL)) + + if (!ReadFile(m_hFile, (LPVOID) data, (DWORD) count, &dwBytesRead, NULL)) { windowsFileSystemFactory::reportError(m_path, GetLastError()); + } + return dwBytesRead; } -size_t windowsFileReaderInputStream::skip(const size_t count) -{ + +size_t windowsFileReaderInputStream::skip(const size_t count) { + DWORD dwCurPos = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT); - DWORD dwNewPos = SetFilePointer(m_hFile, (LONG)count, NULL, FILE_CURRENT); - return (dwNewPos - dwCurPos); + DWORD dwNewPos = SetFilePointer(m_hFile, (LONG) count, NULL, FILE_CURRENT); + + return dwNewPos - dwCurPos; } -size_t windowsFileReaderInputStream::getPosition() const -{ + +size_t windowsFileReaderInputStream::getPosition() const { + DWORD dwCurPos = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT); - if (dwCurPos == INVALID_SET_FILE_POINTER) + if (dwCurPos == INVALID_SET_FILE_POINTER) { windowsFileSystemFactory::reportError(m_path, GetLastError()); + } return static_cast (dwCurPos); } -void windowsFileReaderInputStream::seek(const size_t pos) -{ - DWORD dwNewPos = SetFilePointer(m_hFile, (LONG)pos, NULL, FILE_BEGIN); +void windowsFileReaderInputStream::seek(const size_t pos) { - if (dwNewPos == INVALID_SET_FILE_POINTER) + DWORD dwNewPos = SetFilePointer(m_hFile, (LONG) pos, NULL, FILE_BEGIN); + + if (dwNewPos == INVALID_SET_FILE_POINTER) { windowsFileSystemFactory::reportError(m_path, GetLastError()); + } } -windowsFileWriter::windowsFileWriter(const vmime::utility::file::path& path, const vmime::string& nativePath) -: m_path(path), m_nativePath(nativePath) -{ + + +windowsFileWriter::windowsFileWriter( + const vmime::utility::file::path& path, + const vmime::string& nativePath +) + : m_path(path), + m_nativePath(nativePath) { + } -shared_ptr windowsFileWriter::getOutputStream() -{ +shared_ptr windowsFileWriter::getOutputStream() { + HANDLE hFile = CreateFile( m_nativePath.c_str(), GENERIC_WRITE, @@ -522,32 +660,45 @@ shared_ptr windowsFileWriter::getOutputStream() NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, - NULL); - if (hFile == INVALID_HANDLE_VALUE) + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { windowsFileSystemFactory::reportError(m_path, GetLastError()); + } + return make_shared (m_path, hFile); } -windowsFileWriterOutputStream::windowsFileWriterOutputStream(const vmime::utility::file::path& path, HANDLE hFile) -: m_path(path), m_hFile(hFile) -{ + +windowsFileWriterOutputStream::windowsFileWriterOutputStream( + const vmime::utility::file::path& path, + HANDLE hFile +) + : m_path(path), + m_hFile(hFile) { + } -windowsFileWriterOutputStream::~windowsFileWriterOutputStream() -{ + +windowsFileWriterOutputStream::~windowsFileWriterOutputStream() { + CloseHandle(m_hFile); } -void windowsFileWriterOutputStream::writeImpl(const byte_t* const data, const size_t count) -{ + +void windowsFileWriterOutputStream::writeImpl(const byte_t* const data, const size_t count) { + DWORD dwBytesWritten; - if (!WriteFile(m_hFile, data, (DWORD)count, &dwBytesWritten, NULL)) + + if (!WriteFile(m_hFile, data, (DWORD) count, &dwBytesWritten, NULL)) { windowsFileSystemFactory::reportError(m_path, GetLastError()); + } } -void windowsFileWriterOutputStream::flush() -{ +void windowsFileWriterOutputStream::flush() { + // TODO } diff --git a/src/vmime/platforms/windows/windowsFile.hpp b/src/vmime/platforms/windows/windowsFile.hpp index 3543ee8a..dc4b5ed9 100644 --- a/src/vmime/platforms/windows/windowsFile.hpp +++ b/src/vmime/platforms/windows/windowsFile.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,8 +42,8 @@ namespace platforms { namespace windows { -class windowsFileSystemFactory : public vmime::utility::fileSystemFactory -{ +class windowsFileSystemFactory : public vmime::utility::fileSystemFactory { + public: shared_ptr create(const vmime::utility::file::path& path) const; @@ -63,8 +63,8 @@ public: }; -class windowsFile : public vmime::utility::file -{ +class windowsFile : public vmime::utility::file { + public: windowsFile(const vmime::utility::file::path& path); @@ -97,7 +97,11 @@ public: private: - static void createDirectoryImpl(const vmime::utility::file::path& fullPath, const vmime::utility::file::path& path, const bool recursive = false); + static void createDirectoryImpl( + const vmime::utility::file::path& fullPath, + const vmime::utility::file::path& path, + const bool recursive = false + ); private: @@ -106,8 +110,8 @@ private: }; -class windowsFileIterator : public vmime::utility::fileIterator -{ +class windowsFileIterator : public vmime::utility::fileIterator { + public: windowsFileIterator(const vmime::utility::file::path& path, const vmime::string& nativePath); @@ -132,8 +136,8 @@ private: }; -class windowsFileReader : public vmime::utility::fileReader -{ +class windowsFileReader : public vmime::utility::fileReader { + public: windowsFileReader(const vmime::utility::file::path& path, const vmime::string& nativePath); @@ -149,8 +153,8 @@ private: }; -class windowsFileReaderInputStream : public vmime::utility::inputStream -{ +class windowsFileReaderInputStream : public vmime::utility::inputStream { + public: windowsFileReaderInputStream(const vmime::utility::file::path& path, HANDLE hFile); @@ -172,8 +176,8 @@ private: }; -class windowsFileWriter : public vmime::utility::fileWriter -{ +class windowsFileWriter : public vmime::utility::fileWriter { + public: windowsFileWriter(const vmime::utility::file::path& path, const vmime::string& nativePath); @@ -189,8 +193,8 @@ private: }; -class windowsFileWriterOutputStream : public vmime::utility::outputStream -{ +class windowsFileWriterOutputStream : public vmime::utility::outputStream { + public: windowsFileWriterOutputStream(const vmime::utility::file::path& path, HANDLE hFile); diff --git a/src/vmime/platforms/windows/windowsHandler.cpp b/src/vmime/platforms/windows/windowsHandler.cpp index 294a62d9..551f6726 100644 --- a/src/vmime/platforms/windows/windowsHandler.cpp +++ b/src/vmime/platforms/windows/windowsHandler.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -51,8 +51,8 @@ namespace platforms { namespace windows { -windowsHandler::windowsHandler() -{ +windowsHandler::windowsHandler() { + WSAData wsaData; WSAStartup(MAKEWORD(1, 1), &wsaData); @@ -62,23 +62,24 @@ windowsHandler::windowsHandler() #if VMIME_HAVE_FILESYSTEM_FEATURES m_fileSysFactory = make_shared (); #endif + } -windowsHandler::~windowsHandler() -{ +windowsHandler::~windowsHandler() { + WSACleanup(); } -unsigned long windowsHandler::getUnixTime() const -{ +unsigned long windowsHandler::getUnixTime() const { + return static_cast (::time(NULL)); } -const vmime::datetime windowsHandler::getCurrentLocalTime() const -{ +const vmime::datetime windowsHandler::getCurrentLocalTime() const { + const time_t t(::time(NULL)); // Get the local time @@ -113,25 +114,30 @@ const vmime::datetime windowsHandler::getCurrentLocalTime() const const int diff = (const int)(::mktime(&local) - ::mktime(&gmt)); // Return the date - return vmime::datetime(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday, - local.tm_hour, local.tm_min, local.tm_sec, diff / 60); // minutes needed + return vmime::datetime( + local.tm_year + 1900, local.tm_mon + 1, local.tm_mday, + local.tm_hour, local.tm_min, local.tm_sec, diff / 60 // minutes needed + ); } -const vmime::charset windowsHandler::getLocalCharset() const -{ +const vmime::charset windowsHandler::getLocalCharset() const { + #if VMIME_HAVE_MLANG + char szCharset[256]; CoInitialize(NULL); { IMultiLanguage* pMultiLanguage; + CoCreateInstance( CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_IMultiLanguage, - (void**)&pMultiLanguage); + (void**) &pMultiLanguage + ); UINT codePage = GetACP(); MIMECPINFO cpInfo; @@ -139,98 +145,106 @@ const vmime::charset windowsHandler::getLocalCharset() const int nLengthW = lstrlenW(cpInfo.wszBodyCharset) + 1; - WideCharToMultiByte(codePage, 0, cpInfo.wszBodyCharset, nLengthW, szCharset, sizeof(szCharset), NULL, NULL ); + WideCharToMultiByte( + codePage, 0, cpInfo.wszBodyCharset, nLengthW, + szCharset, sizeof(szCharset), NULL, NULL + ); pMultiLanguage->Release(); - } CoUninitialize(); return vmime::charset(szCharset); + #else // VMIME_HAVE_MLANG + vmime::string ch = vmime::charsets::ISO8859_1; // default - switch (GetACP()) - { - case 437: ch = vmime::charsets::CP_437; break; - case 737: ch = vmime::charsets::CP_737; break; - case 775: ch = vmime::charsets::CP_775; break; - case 850: ch = vmime::charsets::CP_850; break; - case 852: ch = vmime::charsets::CP_852; break; - case 853: ch = vmime::charsets::CP_853; break; - case 855: ch = vmime::charsets::CP_855; break; - case 857: ch = vmime::charsets::CP_857; break; - case 858: ch = vmime::charsets::CP_858; break; - case 860: ch = vmime::charsets::CP_860; break; - case 861: ch = vmime::charsets::CP_861; break; - case 862: ch = vmime::charsets::CP_862; break; - case 863: ch = vmime::charsets::CP_863; break; - case 864: ch = vmime::charsets::CP_864; break; - case 865: ch = vmime::charsets::CP_865; break; - case 866: ch = vmime::charsets::CP_866; break; - case 869: ch = vmime::charsets::CP_869; break; - case 874: ch = vmime::charsets::CP_874; break; + switch (GetACP()) { - case 1125: ch = vmime::charsets::CP_1125; break; - case 1250: ch = vmime::charsets::CP_1250; break; - case 1251: ch = vmime::charsets::CP_1251; break; - case 1252: ch = vmime::charsets::CP_1252; break; - case 1253: ch = vmime::charsets::CP_1253; break; - case 1254: ch = vmime::charsets::CP_1254; break; - case 1255: ch = vmime::charsets::CP_1255; break; - case 1256: ch = vmime::charsets::CP_1256; break; - case 1257: ch = vmime::charsets::CP_1257; break; + case 437: ch = vmime::charsets::CP_437; break; + case 737: ch = vmime::charsets::CP_737; break; + case 775: ch = vmime::charsets::CP_775; break; + case 850: ch = vmime::charsets::CP_850; break; + case 852: ch = vmime::charsets::CP_852; break; + case 853: ch = vmime::charsets::CP_853; break; + case 855: ch = vmime::charsets::CP_855; break; + case 857: ch = vmime::charsets::CP_857; break; + case 858: ch = vmime::charsets::CP_858; break; + case 860: ch = vmime::charsets::CP_860; break; + case 861: ch = vmime::charsets::CP_861; break; + case 862: ch = vmime::charsets::CP_862; break; + case 863: ch = vmime::charsets::CP_863; break; + case 864: ch = vmime::charsets::CP_864; break; + case 865: ch = vmime::charsets::CP_865; break; + case 866: ch = vmime::charsets::CP_866; break; + case 869: ch = vmime::charsets::CP_869; break; + case 874: ch = vmime::charsets::CP_874; break; - case 28591: ch = vmime::charsets::ISO8859_1; break; - case 28592: ch = vmime::charsets::ISO8859_2; break; - case 28593: ch = vmime::charsets::ISO8859_3; break; - case 28594: ch = vmime::charsets::ISO8859_4; break; - case 28595: ch = vmime::charsets::ISO8859_5; break; - case 28596: ch = vmime::charsets::ISO8859_6; break; - case 28597: ch = vmime::charsets::ISO8859_7; break; - case 28598: ch = vmime::charsets::ISO8859_8; break; - case 28599: ch = vmime::charsets::ISO8859_9; break; - case 28605: ch = vmime::charsets::ISO8859_15; break; + case 1125: ch = vmime::charsets::CP_1125; break; + case 1250: ch = vmime::charsets::CP_1250; break; + case 1251: ch = vmime::charsets::CP_1251; break; + case 1252: ch = vmime::charsets::CP_1252; break; + case 1253: ch = vmime::charsets::CP_1253; break; + case 1254: ch = vmime::charsets::CP_1254; break; + case 1255: ch = vmime::charsets::CP_1255; break; + case 1256: ch = vmime::charsets::CP_1256; break; + case 1257: ch = vmime::charsets::CP_1257; break; - case 65000: ch = vmime::charsets::UTF_7; break; - case 65001: ch = vmime::charsets::UTF_8; break; + case 28591: ch = vmime::charsets::ISO8859_1; break; + case 28592: ch = vmime::charsets::ISO8859_2; break; + case 28593: ch = vmime::charsets::ISO8859_3; break; + case 28594: ch = vmime::charsets::ISO8859_4; break; + case 28595: ch = vmime::charsets::ISO8859_5; break; + case 28596: ch = vmime::charsets::ISO8859_6; break; + case 28597: ch = vmime::charsets::ISO8859_7; break; + case 28598: ch = vmime::charsets::ISO8859_8; break; + case 28599: ch = vmime::charsets::ISO8859_9; break; + case 28605: ch = vmime::charsets::ISO8859_15; break; + + case 65000: ch = vmime::charsets::UTF_7; break; + case 65001: ch = vmime::charsets::UTF_8; break; } - return (vmime::charset(ch)); + return vmime::charset(ch); + #endif + } -const vmime::string windowsHandler::getHostName() const -{ +const vmime::string windowsHandler::getHostName() const { + char hostname[1024]; DWORD hostnameLen; // First, try to get a Fully-Qualified Domain Name (FQDN) - for (int cnf = ComputerNameDnsHostname ; cnf <= ComputerNameDnsFullyQualified ; ++cnf) - { + for (int cnf = ComputerNameDnsHostname ; cnf <= ComputerNameDnsFullyQualified ; ++cnf) { + hostnameLen = sizeof(hostname); - if (GetComputerNameEx((COMPUTER_NAME_FORMAT) cnf, hostname, &hostnameLen)) - { + if (GetComputerNameEx((COMPUTER_NAME_FORMAT) cnf, hostname, &hostnameLen)) { + const vmime::string hostnameStr(hostname); - if (utility::stringUtils::isValidFQDN(hostnameStr)) + if (utility::stringUtils::isValidFQDN(hostnameStr)) { return hostnameStr; + } } } // Anything else will be OK, as long as it is a valid hostname - for (int cnf = 0 ; cnf < ComputerNameMax ; ++cnf) - { + for (int cnf = 0 ; cnf < ComputerNameMax ; ++cnf) { + hostnameLen = sizeof(hostname); - if (GetComputerNameEx((COMPUTER_NAME_FORMAT) cnf, hostname, &hostnameLen)) - { + if (GetComputerNameEx((COMPUTER_NAME_FORMAT) cnf, hostname, &hostnameLen)) { + const vmime::string hostnameStr(hostname); - if (utility::stringUtils::isValidHostname(hostnameStr)) + if (utility::stringUtils::isValidHostname(hostnameStr)) { return hostnameStr; + } } } @@ -238,22 +252,22 @@ const vmime::string windowsHandler::getHostName() const } -unsigned int windowsHandler::getProcessId() const -{ - return (static_cast (::GetCurrentProcessId())); +unsigned int windowsHandler::getProcessId() const { + + return static_cast (::GetCurrentProcessId()); } -unsigned int windowsHandler::getThreadId() const -{ +unsigned int windowsHandler::getThreadId() const { + return static_cast (::GetCurrentThreadId()); } #if VMIME_HAVE_MESSAGING_FEATURES -shared_ptr windowsHandler::getSocketFactory() -{ +shared_ptr windowsHandler::getSocketFactory() { + return m_socketFactory; } @@ -262,14 +276,14 @@ shared_ptr windowsHandler::getSocketFactory() #if VMIME_HAVE_FILESYSTEM_FEATURES -shared_ptr windowsHandler::getFileSystemFactory() -{ +shared_ptr windowsHandler::getFileSystemFactory() { + return m_fileSysFactory; } -shared_ptr windowsHandler::getChildProcessFactory() -{ +shared_ptr windowsHandler::getChildProcessFactory() { + // TODO: Not implemented return null; } @@ -277,8 +291,8 @@ shared_ptr windowsHandler::getChildProcess #endif -void windowsHandler::generateRandomBytes(unsigned char* buffer, const unsigned int count) -{ +void windowsHandler::generateRandomBytes(unsigned char* buffer, const unsigned int count) { + HCRYPTPROV cryptProvider = 0; CryptAcquireContext(&cryptProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); CryptGenRandom(cryptProvider, static_cast (count), static_cast (buffer)); @@ -286,8 +300,8 @@ void windowsHandler::generateRandomBytes(unsigned char* buffer, const unsigned i } -shared_ptr windowsHandler::createCriticalSection() -{ +shared_ptr windowsHandler::createCriticalSection() { + return make_shared (); } diff --git a/src/vmime/platforms/windows/windowsHandler.hpp b/src/vmime/platforms/windows/windowsHandler.hpp index b80f0de8..9dda256c 100644 --- a/src/vmime/platforms/windows/windowsHandler.hpp +++ b/src/vmime/platforms/windows/windowsHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -47,8 +47,8 @@ namespace platforms { namespace windows { -class VMIME_EXPORT windowsHandler : public vmime::platform::handler -{ +class VMIME_EXPORT windowsHandler : public vmime::platform::handler { + public: windowsHandler(); diff --git a/src/vmime/platforms/windows/windowsSocket.cpp b/src/vmime/platforms/windows/windowsSocket.cpp index 2fadc36e..3a93c53a 100644 --- a/src/vmime/platforms/windows/windowsSocket.cpp +++ b/src/vmime/platforms/windows/windowsSocket.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -47,27 +47,29 @@ namespace windows { // windowsSocket::windowsSocket(shared_ptr th) - : m_timeoutHandler(th), m_desc(INVALID_SOCKET), m_status(0) -{ + : m_timeoutHandler(th), + m_desc(INVALID_SOCKET), + m_status(0) { + WSAData wsaData; WSAStartup(MAKEWORD(1, 1), &wsaData); } -windowsSocket::~windowsSocket() -{ - if (m_desc != INVALID_SOCKET) +windowsSocket::~windowsSocket() { + + if (m_desc != INVALID_SOCKET) { ::closesocket(m_desc); + } WSACleanup(); } -void windowsSocket::connect(const vmime::string& address, const vmime::port_t port) -{ +void windowsSocket::connect(const vmime::string& address, const vmime::port_t port) { + // Close current connection, if any - if (m_desc != INVALID_SOCKET) - { + if (m_desc != INVALID_SOCKET) { ::closesocket(m_desc); m_desc = INVALID_SOCKET; } @@ -81,20 +83,19 @@ void windowsSocket::connect(const vmime::string& address, const vmime::port_t po addr.sin_port = htons(static_cast (port)); addr.sin_addr.s_addr = ::inet_addr(address.c_str()); - if (m_tracer) - { + if (m_tracer) { + std::ostringstream trace; trace << "Connecting to " << address << ", port " << port; m_tracer->traceSend(trace.str()); } - if (addr.sin_addr.s_addr == static_cast (-1)) - { + if (addr.sin_addr.s_addr == static_cast (-1)) { + ::hostent* hostInfo = ::gethostbyname(address.c_str()); - if (hostInfo == NULL) - { + if (!hostInfo) { // Error: cannot resolve address throw vmime::exceptions::connection_error("Cannot resolve address."); } @@ -107,36 +108,34 @@ void windowsSocket::connect(const vmime::string& address, const vmime::port_t po // Get a new socket m_desc = ::socket(AF_INET, SOCK_STREAM, 0); - if (m_desc == INVALID_SOCKET) - { - try - { + if (m_desc == INVALID_SOCKET) { + + try { + int err = WSAGetLastError(); throwSocketError(err); - } - catch (exceptions::socket_exception& e) - { - throw vmime::exceptions::connection_error - ("Error while creating socket.", e); + + } catch (exceptions::socket_exception& e) { + + throw vmime::exceptions::connection_error("Error while creating socket.", e); } } // Start connection - if (::connect(m_desc, reinterpret_cast (&addr), sizeof(addr)) == -1) - { - try - { + if (::connect(m_desc, reinterpret_cast (&addr), sizeof(addr)) == -1) { + + try { + int err = WSAGetLastError(); throwSocketError(err); - } - catch (exceptions::socket_exception& e) - { + + } catch (exceptions::socket_exception& e) { + ::closesocket(m_desc); m_desc = INVALID_SOCKET; // Error - throw vmime::exceptions::connection_error - ("Error while connecting socket.", e); + throw vmime::exceptions::connection_error("Error while connecting socket.", e); } } @@ -146,10 +145,11 @@ void windowsSocket::connect(const vmime::string& address, const vmime::port_t po } -bool windowsSocket::isConnected() const -{ - if (m_desc == INVALID_SOCKET) +bool windowsSocket::isConnected() const { + + if (m_desc == INVALID_SOCKET) { return false; + } char buff; @@ -157,12 +157,13 @@ bool windowsSocket::isConnected() const } -void windowsSocket::disconnect() -{ - if (m_desc != INVALID_SOCKET) - { - if (m_tracer) +void windowsSocket::disconnect() { + + if (m_desc != INVALID_SOCKET) { + + if (m_tracer) { m_tracer->traceSend("Disconnecting"); + } ::shutdown(m_desc, SD_BOTH); ::closesocket(m_desc); @@ -172,28 +173,28 @@ void windowsSocket::disconnect() } -static bool isNumericAddress(const char* address) -{ +static bool isNumericAddress(const char* address) { + struct addrinfo hint, *info = NULL; memset(&hint, 0, sizeof(hint)); hint.ai_family = AF_UNSPEC; hint.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(address, 0, &hint, &info) == 0) - { + if (getaddrinfo(address, 0, &hint, &info) == 0) { + freeaddrinfo(info); return true; - } - else - { + + } else { + return false; } } -const string windowsSocket::getPeerAddress() const -{ +const string windowsSocket::getPeerAddress() const { + // Get address of connected peer sockaddr peer; socklen_t peerLen = sizeof(peer); @@ -206,8 +207,8 @@ const string windowsSocket::getPeerAddress() const if (getnameinfo(reinterpret_cast (&peer), peerLen, host, sizeof(host), service, sizeof(service), - /* flags */ NI_NUMERICHOST) == 0) - { + /* flags */ NI_NUMERICHOST) == 0) { + return string(host); } @@ -215,8 +216,8 @@ const string windowsSocket::getPeerAddress() const } -const string windowsSocket::getPeerName() const -{ +const string windowsSocket::getPeerName() const { + // Get address of connected peer sockaddr peer; socklen_t peerLen = sizeof(peer); @@ -225,15 +226,15 @@ const string windowsSocket::getPeerName() const // If server address as specified when connecting is a numeric // address, try to get a host name for it - if (isNumericAddress(m_serverAddress.c_str())) - { + if (isNumericAddress(m_serverAddress.c_str())) { + char host[NI_MAXHOST + 1]; char service[NI_MAXSERV + 1]; if (getnameinfo(reinterpret_cast (&peer), peerLen, host, sizeof(host), service, sizeof(service), - /* flags */ NI_NAMEREQD) == 0) - { + /* flags */ NI_NAMEREQD) == 0) { + return string(host); } } @@ -242,38 +243,38 @@ const string windowsSocket::getPeerName() const } -size_t windowsSocket::getBlockSize() const -{ +size_t windowsSocket::getBlockSize() const { + return 16384; // 16 KB } -void windowsSocket::receive(vmime::string& buffer) -{ +void windowsSocket::receive(vmime::string& buffer) { + const size_t size = receiveRaw(m_buffer, sizeof(m_buffer)); buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size); } -size_t windowsSocket::receiveRaw(byte_t* buffer, const size_t count) -{ +size_t windowsSocket::receiveRaw(byte_t* buffer, const size_t count) { + m_status &= ~STATUS_WOULDBLOCK; // Check whether data is available - if (!waitForRead(50 /* msecs */)) - { + if (!waitForRead(50 /* msecs */)) { + // No data available at this time // Check if we are timed out if (m_timeoutHandler && - m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - { + m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { + // Server did not react within timeout delay throwSocketError(WSAETIMEDOUT); - } - else - { + + } else { + // Reset timeout m_timeoutHandler->resetTimeOut(); } @@ -286,101 +287,105 @@ size_t windowsSocket::receiveRaw(byte_t* buffer, const size_t count) // Read available data int ret = ::recv(m_desc, reinterpret_cast (buffer), count, 0); - if (ret == SOCKET_ERROR) - { + if (ret == SOCKET_ERROR) { + int err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK) + if (err != WSAEWOULDBLOCK) { throwSocketError(err); + } m_status |= STATUS_WOULDBLOCK; // Error or no data - return (0); - } - else if (ret == 0) - { + return 0; + + } else if (ret == 0) { + // Host shutdown throwSocketError(WSAENOTCONN); - } - else - { + + } else { + // Data received, reset timeout - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } return ret; } } -void windowsSocket::send(const vmime::string& buffer) -{ +void windowsSocket::send(const vmime::string& buffer) { + sendRaw(reinterpret_cast (buffer.data()), buffer.length()); } -void windowsSocket::send(const char* str) -{ +void windowsSocket::send(const char* str) { + sendRaw(reinterpret_cast (str), strlen(str)); } -void windowsSocket::sendRaw(const byte_t* buffer, const size_t count) -{ +void windowsSocket::sendRaw(const byte_t* buffer, const size_t count) { + m_status &= ~STATUS_WOULDBLOCK; size_t size = count; - while (size > 0) - { + while (size > 0) { + const int ret = ::send(m_desc, reinterpret_cast (buffer), size, 0); - if (ret == SOCKET_ERROR) - { + if (ret == SOCKET_ERROR) { + int err = WSAGetLastError(); - if (err != WSAEWOULDBLOCK) + if (err != WSAEWOULDBLOCK) { throwSocketError(err); + } waitForWrite(50 /* msecs */); - } - else - { + + } else { + buffer += ret; size -= ret; } } // Reset timeout - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } } -size_t windowsSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) -{ +size_t windowsSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) { + m_status &= ~STATUS_WOULDBLOCK; const int ret = ::send(m_desc, reinterpret_cast (buffer), count, 0); - if (ret == SOCKET_ERROR) - { + if (ret == SOCKET_ERROR) { + int err = WSAGetLastError(); - if (err == WSAEWOULDBLOCK) - { + if (err == WSAEWOULDBLOCK) { + // Check if we are timed out if (m_timeoutHandler && - m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - { + m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { + // Could not send data within timeout delay throwSocketError(err); - } - else - { + + } else { + // Reset timeout m_timeoutHandler->resetTimeOut(); } @@ -390,29 +395,30 @@ size_t windowsSocket::sendRawNonBlocking(const byte_t* buffer, const size_t coun // No data can be written at this time return 0; - } - else - { + + } else { + throwSocketError(err); } } // Reset timeout - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } return ret; } -unsigned int windowsSocket::getStatus() const -{ +unsigned int windowsSocket::getStatus() const { + return m_status; } -void windowsSocket::throwSocketError(const int err) -{ +void windowsSocket::throwSocketError(const int err) { + std::ostringstream oss; string msg; @@ -420,13 +426,13 @@ void windowsSocket::throwSocketError(const int err) if (::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, err, 0, (LPTSTR) &str, 0, NULL) == 0) - { + NULL, err, 0, (LPTSTR) &str, 0, NULL) == 0) { + // Failed getting message oss << "Unknown socket error (code " << err << ")"; - } - else - { + + } else { + oss << str; ::LocalFree(str); } @@ -437,10 +443,10 @@ void windowsSocket::throwSocketError(const int err) } -bool windowsSocket::waitForData(const bool read, const bool write, const int msecs) -{ - for (int i = 0 ; i <= msecs / 10 ; ++i) - { +bool windowsSocket::waitForData(const bool read, const bool write, const int msecs) { + + for (int i = 0 ; i <= msecs / 10 ; ++i) { + // Check whether data is available fd_set fds; FD_ZERO(&fds); @@ -452,28 +458,28 @@ bool windowsSocket::waitForData(const bool read, const bool write, const int mse int ret = ::select(m_desc + 1, read ? &fds : NULL, write ? &fds : NULL, NULL, &tv); - if (ret == SOCKET_ERROR) - { + if (ret == SOCKET_ERROR) { + int err = WSAGetLastError(); throwSocketError(err); - } - else if (ret > 0) - { + + } else if (ret > 0) { + return true; } // No data available at this time // Check if we are timed out if (m_timeoutHandler && - m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - { + m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { + // Server did not react within timeout delay throw exceptions::operation_timed_out(); - } - else - { + + } else { + // Reset timeout m_timeoutHandler->resetTimeOut(); } @@ -484,32 +490,32 @@ bool windowsSocket::waitForData(const bool read, const bool write, const int mse } -bool windowsSocket::waitForRead(const int msecs) -{ +bool windowsSocket::waitForRead(const int msecs) { + return waitForData(/* read */ true, /* write */ false, msecs); } -bool windowsSocket::waitForWrite(const int msecs) -{ +bool windowsSocket::waitForWrite(const int msecs) { + return waitForData(/* read */ false, /* write */ true, msecs); } -shared_ptr windowsSocket::getTimeoutHandler() -{ +shared_ptr windowsSocket::getTimeoutHandler() { + return m_timeoutHandler; } -void windowsSocket::setTracer(const shared_ptr & tracer) -{ +void windowsSocket::setTracer(const shared_ptr & tracer) { + m_tracer = tracer; } -shared_ptr windowsSocket::getTracer() -{ +shared_ptr windowsSocket::getTracer() { + return m_tracer; } @@ -519,17 +525,19 @@ shared_ptr windowsSocket::getTracer() // posixSocketFactory // -shared_ptr windowsSocketFactory::create() -{ +shared_ptr windowsSocketFactory::create() { + shared_ptr th; return make_shared (th); } -shared_ptr windowsSocketFactory::create(const shared_ptr & th) -{ + +shared_ptr windowsSocketFactory::create(const shared_ptr & th) { + return make_shared (th); } + } // posix } // platforms } // vmime diff --git a/src/vmime/platforms/windows/windowsSocket.hpp b/src/vmime/platforms/windows/windowsSocket.hpp index 84fbdfc0..ddb82da5 100644 --- a/src/vmime/platforms/windows/windowsSocket.hpp +++ b/src/vmime/platforms/windows/windowsSocket.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,8 +40,8 @@ namespace platforms { namespace windows { -class windowsSocket : public vmime::net::socket -{ +class windowsSocket : public vmime::net::socket { + public: windowsSocket(); @@ -98,8 +98,8 @@ private: -class windowsSocketFactory : public vmime::net::socketFactory -{ +class windowsSocketFactory : public vmime::net::socketFactory { + public: shared_ptr create(); diff --git a/src/vmime/propertySet.cpp b/src/vmime/propertySet.cpp index c22e79a6..e0d48488 100644 --- a/src/vmime/propertySet.cpp +++ b/src/vmime/propertySet.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -25,82 +25,87 @@ #include "vmime/parserHelpers.hpp" -namespace vmime -{ +namespace vmime { -propertySet::propertySet() -{ +propertySet::propertySet() { + } -propertySet::propertySet(const string& props) -{ +propertySet::propertySet(const string& props) { + parse(props); } propertySet::propertySet(const propertySet& set) - : object() -{ - for (std::list >::const_iterator it = set.m_props.begin() ; it != set.m_props.end() ; ++it) + : object() { + + for (std::list >::const_iterator it = set.m_props.begin() ; + it != set.m_props.end() ; ++it) { + m_props.push_back(make_shared (**it)); + } } -propertySet::~propertySet() -{ +propertySet::~propertySet() { + removeAllProperties(); } -propertySet& propertySet::operator=(const propertySet& set) -{ +propertySet& propertySet::operator=(const propertySet& set) { + removeAllProperties(); - for (std::list >::const_iterator it = set.m_props.begin() ; it != set.m_props.end() ; ++it) - m_props.push_back(make_shared (**it)); + for (std::list >::const_iterator it = set.m_props.begin() ; + it != set.m_props.end() ; ++it) { - return (*this); + m_props.push_back(make_shared (**it)); + } + + return *this; } -void propertySet::setFromString(const string& props) -{ +void propertySet::setFromString(const string& props) { + parse(props); } -void propertySet::removeAllProperties() -{ +void propertySet::removeAllProperties() { + m_props.clear(); } -void propertySet::removeProperty(const string& name) -{ - std::list >::iterator it = std::find_if - (m_props.begin(), m_props.end(), propFinder(name)); +void propertySet::removeProperty(const string& name) { - if (it != m_props.end()) + std::list >::iterator it = + std::find_if(m_props.begin(), m_props.end(), propFinder(name)); + + if (it != m_props.end()) { m_props.erase(it); + } } -void propertySet::parse(const string& props) -{ +void propertySet::parse(const string& props) { + const string::const_iterator end = props.end(); string::const_iterator pos = props.begin(); - for ( ; pos != end ; ) - { + for ( ; pos != end ; ) { + // Skip white-spaces for ( ; pos != end && parserHelpers::isSpace(*pos) ; ++pos) {} - if (pos != end) - { - if (*pos == ';') - { + if (pos != end) { + + if (*pos == ';') { ++pos; continue; } @@ -117,48 +122,50 @@ void propertySet::parse(const string& props) const string option(optStart, optEnd); string value = "1"; - if (pos != end) - { + if (pos != end) { + ++pos; // skip '=' // Extract the value for ( ; pos != end && parserHelpers::isSpace(*pos) ; ++pos) {} - if (pos != end) - { + if (pos != end) { + // A quoted-string - if (*pos == '"' || *pos == '\'') - { + if (*pos == '"' || *pos == '\'') { + value.reserve(50); const char quoteChar = *pos; bool theEnd = false; bool escape = false; - for ( ; (pos != end) && !theEnd ; ++pos) - { - if (escape) - { + for ( ; (pos != end) && !theEnd ; ++pos) { + + if (escape) { + value += *pos; escape = false; - } - else - { - if (*pos == '\\') + + } else { + + if (*pos == '\\') { escape = true; - else if (*pos == quoteChar) + } else if (*pos == quoteChar) { theEnd = true; - else + } else { value += *pos; + } } } - if (pos != end) + if (pos != end) { ++pos; - } + } + // Simple value - else - { + } else { + const string::const_iterator valStart = pos; for ( ; pos != end && !parserHelpers::isSpace(*pos) ; ++pos) {} @@ -169,8 +176,9 @@ void propertySet::parse(const string& props) // Advance to the next ';' for ( ; pos != end && (*pos != ';') ; ++pos) {} - if (pos != end) + if (pos != end) { ++pos; // skip ';' + } } } @@ -180,70 +188,72 @@ void propertySet::parse(const string& props) } -shared_ptr propertySet::find(const string& name) const -{ - std::list >::const_iterator it = std::find_if - (m_props.begin(), m_props.end(), propFinder(name)); +shared_ptr propertySet::find(const string& name) const { - return (it != m_props.end() ? *it : null); + std::list >::const_iterator it = + std::find_if(m_props.begin(), m_props.end(), propFinder(name)); + + return it != m_props.end() ? *it : null; } -shared_ptr propertySet::findOrCreate(const string& name) -{ - std::list >::const_iterator it = std::find_if - (m_props.begin(), m_props.end(), propFinder(name)); +shared_ptr propertySet::findOrCreate(const string& name) { + + std::list >::const_iterator it = + std::find_if(m_props.begin(), m_props.end(), propFinder(name)); + + if (it != m_props.end()) { + + return *it; + + } else { - if (it != m_props.end()) - { - return (*it); - } - else - { shared_ptr prop = make_shared (name, ""); m_props.push_back(prop); - return (prop); + return prop; } } -propertySet::propertyProxy propertySet::operator[](const string& name) -{ - return (propertyProxy(name, this)); +propertySet::propertyProxy propertySet::operator[](const string& name) { + + return propertyProxy(name, this); } -const propertySet::constPropertyProxy propertySet::operator[](const string& name) const -{ - return (constPropertyProxy(name, this)); +const propertySet::constPropertyProxy propertySet::operator[](const string& name) const { + + return constPropertyProxy(name, this); } -bool propertySet::hasProperty(const string& name) const -{ - return (find(name) != NULL); +bool propertySet::hasProperty(const string& name) const { + + return find(name) != NULL; } -const std::vector > propertySet::getPropertyList() const -{ +const std::vector > propertySet::getPropertyList() const { + std::vector > res; - for (list_type::const_iterator it = m_props.begin() ; it != m_props.end() ; ++it) + for (list_type::const_iterator it = m_props.begin() ; it != m_props.end() ; ++it) { res.push_back(*it); + } - return (res); + return res; } -const std::vector > propertySet::getPropertyList() -{ +const std::vector > propertySet::getPropertyList() { + std::vector > res; - for (list_type::const_iterator it = m_props.begin() ; it != m_props.end() ; ++it) + for (list_type::const_iterator it = m_props.begin() ; it != m_props.end() ; ++it) { res.push_back(*it); + } - return (res); + return res; } @@ -252,40 +262,43 @@ const std::vector > propertySet::getProperty // propertySet::property::property(const string& name, const string& value) - : m_name(name), m_value(value) -{ + : m_name(name), + m_value(value) { + } propertySet::property::property(const string& name) - : m_name(name) -{ + : m_name(name) { + } propertySet::property::property(const property& prop) - : object(), m_name(prop.m_name), m_value(prop.m_value) -{ + : object(), + m_name(prop.m_name), + m_value(prop.m_value) { + } -const string& propertySet::property::getName() const -{ - return (m_name); +const string& propertySet::property::getName() const { + + return m_name; } #ifndef _MSC_VER -const string& propertySet::property::getValue() const -{ - return (m_value); +const string& propertySet::property::getValue() const { + + return m_value; } -void propertySet::property::setValue(const string& value) -{ +void propertySet::property::setValue(const string& value) { + m_value = value; } @@ -296,33 +309,35 @@ void propertySet::property::setValue(const string& value) #ifndef VMIME_INLINE_TEMPLATE_SPECIALIZATION template <> -void propertySet::property::setValue(const string& value) -{ +void propertySet::property::setValue(const string& value) { + m_value = value; } template <> -void propertySet::property::setValue(const bool& value) -{ +void propertySet::property::setValue(const bool& value) { + m_value = value ? "true" : "false"; } template <> -string propertySet::property::getValue() const -{ - return (m_value); +string propertySet::property::getValue() const { + + return m_value; } template <> -bool propertySet::property::getValue() const -{ - if (utility::stringUtils::toLower(m_value) == "true") +bool propertySet::property::getValue() const { + + if (utility::stringUtils::toLower(m_value) == "true") { + return true; - else - { + + } else { + int val = 0; std::istringstream iss(m_value); @@ -330,7 +345,7 @@ bool propertySet::property::getValue() const iss >> val; - return (!iss.fail() && val != 0); + return !iss.fail() && val != 0; } } @@ -338,26 +353,28 @@ bool propertySet::property::getValue() const template <> -string propertySet::valueFromString(const string& value) -{ +string propertySet::valueFromString(const string& value) { + return value; } template <> -string propertySet::valueToString(const string& value) -{ +string propertySet::valueToString(const string& value) { + return value; } template <> -bool propertySet::valueFromString(const string& value) -{ - if (utility::stringUtils::toLower(value) == "true") +bool propertySet::valueFromString(const string& value) { + + if (utility::stringUtils::toLower(value) == "true") { + return true; - else - { + + } else { + int val = 0; std::istringstream iss(value); @@ -365,15 +382,15 @@ bool propertySet::valueFromString(const string& value) iss >> val; - return (!iss.fail() && val != 0); + return !iss.fail() && val != 0; } } template <> -string propertySet::valueToString(const bool& value) -{ - return (value ? "true" : "false"); +string propertySet::valueToString(const bool& value) { + + return value ? "true" : "false"; } #endif // VMIME_INLINE_TEMPLATE_SPECIALIZATION diff --git a/src/vmime/propertySet.hpp b/src/vmime/propertySet.hpp index fb22b437..681097d9 100644 --- a/src/vmime/propertySet.hpp +++ b/src/vmime/propertySet.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,21 +36,19 @@ #include "vmime/utility/stringUtils.hpp" -namespace vmime -{ +namespace vmime { /** Manage a list of (name,value) pairs. */ +class VMIME_EXPORT propertySet : public object { -class VMIME_EXPORT propertySet : public object -{ public: /** A property holds a (name,value) pair. */ - class property : public object - { + class property : public object { + public: property(const string& name, const string& value); @@ -86,8 +84,8 @@ public: * * @param value new value for property */ - template void setValue(const TYPE& value) - { + template void setValue(const TYPE& value) { + std::ostringstream oss; oss.imbue(std::locale::classic()); // no formatting @@ -103,8 +101,8 @@ public: * converted using std::istringstream) * @return current value of the property */ - template TYPE getValue() const - { + template TYPE getValue() const { + TYPE val = TYPE(); std::istringstream iss(m_value); @@ -112,8 +110,9 @@ public: iss >> val; - if (iss.fail()) + if (iss.fail()) { throw exceptions::invalid_property_type(); + } return (val); } @@ -122,30 +121,32 @@ public: #ifdef VMIME_INLINE_TEMPLATE_SPECIALIZATION template <> - void propertySet::property::setValue(const string& value) - { + void propertySet::property::setValue(const string& value) { + m_value = value; } template <> - void propertySet::property::setValue(const bool& value) - { + void propertySet::property::setValue(const bool& value) { + m_value = value ? "true" : "false"; } template <> - string propertySet::property::getValue() const - { + string propertySet::property::getValue() const { + return (m_value); } template <> - bool propertySet::property::getValue() const - { - if (utility::stringUtils::toLower(m_value) == "true") + bool propertySet::property::getValue() const { + + if (utility::stringUtils::toLower(m_value) == "true") { + return true; - else - { + + } else { + int val = 0; std::istringstream iss(m_value); @@ -153,7 +154,7 @@ public: iss >> val; - return (!iss.fail() && val != 0); + return !iss.fail() && val != 0; } } @@ -167,37 +168,38 @@ public: protected: - class propertyProxy - { + class propertyProxy { + public: propertyProxy(const string& name, propertySet* set) - : m_name(name), m_set(set) - { + : m_name(name), + m_set(set) { + } template - propertyProxy& operator=(const TYPE& value) - { + propertyProxy& operator=(const TYPE& value) { + m_set->setProperty(m_name, value); - return (*this); + return *this; } template - void setValue(const TYPE& value) - { + void setValue(const TYPE& value) { + m_set->setProperty(m_name, value); } template - const TYPE getValue() const - { - return (m_set->getProperty (m_name)); + const TYPE getValue() const { + + return m_set->getProperty (m_name); } - operator string() const - { - return (m_set->getProperty (m_name)); + operator string() const { + + return m_set->getProperty (m_name); } private: @@ -206,24 +208,25 @@ protected: propertySet* m_set; }; - class constPropertyProxy - { + class constPropertyProxy { + public: constPropertyProxy(const string& name, const propertySet* set) - : m_name(name), m_set(set) - { + : m_name(name), + m_set(set) { + } template - const TYPE getValue() const - { - return (m_set->getProperty (m_name)); + const TYPE getValue() const { + + return m_set->getProperty (m_name); } - operator string() const - { - return (m_set->getProperty (m_name)); + operator string() const { + + return m_set->getProperty (m_name); } private: @@ -274,12 +277,11 @@ public: * @return value of the specified property */ template - const TYPE getProperty(const string& name) const - { + const TYPE getProperty(const string& name) const { + const shared_ptr prop = find(name); if (!prop) throw exceptions::no_such_property(name); - //return (prop->getValue ()); // BUG: with g++ < 3.4 return (prop->template getValue ()); } @@ -293,11 +295,10 @@ public: * if if does not exist */ template - const TYPE getProperty(const string& name, const TYPE defaultValue) const - { + const TYPE getProperty(const string& name, const TYPE defaultValue) const { + const shared_ptr prop = find(name); - //return (prop ? prop->getValue () : defaultValue); // BUG: with g++ < 3.4 - return (prop ? prop->template getValue () : defaultValue); + return prop ? prop->template getValue () : defaultValue; } /** Change the value of the specified property or create @@ -307,8 +308,8 @@ public: * @param value property value */ template - void setProperty(const string& name, const TYPE& value) - { + void setProperty(const string& name, const TYPE& value) { + findOrCreate(name)->setValue(value); } @@ -335,14 +336,14 @@ private: void parse(const string& props); - class propFinder : public std::unary_function , bool> - { + class propFinder : public std::unary_function , bool> { + public: propFinder(const string& name) : m_name(utility::stringUtils::toLower(name)) { } - bool operator()(const shared_ptr & p) const - { + bool operator()(const shared_ptr & p) const { + return (utility::stringUtils::toLower(p->getName()) == m_name); } @@ -360,8 +361,8 @@ private: public: template - static TYPE valueFromString(const string& value) - { + static TYPE valueFromString(const string& value) { + TYPE v = TYPE(); std::istringstream iss(value); @@ -373,8 +374,8 @@ public: } template - static string valueToString(const TYPE& value) - { + static string valueToString(const TYPE& value) { + std::ostringstream oss(value); oss.imbue(std::locale::classic()); // no formatting @@ -386,24 +387,26 @@ public: #ifdef VMIME_INLINE_TEMPLATE_SPECIALIZATION template <> - static string valueFromString(const string& value) - { + static string valueFromString(const string& value) { + return value; } template <> - static string valueToString(const string& value) - { + static string valueToString(const string& value) { + return value; } template <> - static bool valueFromString(const string& value) - { - if (utility::stringUtils::toLower(value) == "true") + static bool valueFromString(const string& value) { + + if (utility::stringUtils::toLower(value) == "true") { + return true; - else - { + + } else { + int val = 0; std::istringstream iss(value); @@ -411,14 +414,14 @@ public: iss >> val; - return (!iss.fail() && val != 0); + return !iss.fail() && val != 0; } } template <> - static string valueToString(const bool& value) - { - return (value ? "true" : "false"); + static string valueToString(const bool& value) { + + return value ? "true" : "false"; } #endif // VMIME_INLINE_TEMPLATE_SPECIALIZATION diff --git a/src/vmime/relay.cpp b/src/vmime/relay.cpp index 2f4cf350..b0a6b60f 100644 --- a/src/vmime/relay.cpp +++ b/src/vmime/relay.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,18 +29,17 @@ #include -namespace vmime -{ +namespace vmime { -relay::relay() -{ +relay::relay() { + } relay::relay(const relay& r) - : headerFieldValue() -{ + : headerFieldValue() { + copyFrom(r); } @@ -58,34 +57,39 @@ relay::relay(const relay& r) ["for" addr-spec] ; initial form */ -void relay::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void relay::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + const char* const pend = buffer.data() + end; const char* const pstart = buffer.data() + position; const char* p = pend - 1; // Find the beginning of the date part - while (p >= pstart && *p != ';') + while (p >= pstart && *p != ';') { --p; + } + + if (p >= pstart) { - if (p >= pstart) - { // Parse the date/time part m_date.parse(ctx, buffer, position + (p - pstart) + 1, end); // Parse the components - std::istringstream iss(string - (buffer.begin() + position, buffer.begin() + position + (p - pstart))); + std::istringstream iss( + string(buffer.begin() + position, buffer.begin() + position + (p - pstart)) + ); iss.imbue(std::locale::classic()); string word; std::vector previous; - enum Parts - { + enum Parts { Part_None, Part_From, // The "from" part Part_By, // The "by" part @@ -100,19 +104,19 @@ void relay::parseImpl bool cont = true; bool inComment = false; - while (cont) - { + while (cont) { + Parts newPart = Part_None; - if ((cont = !(iss >> word).fail())) - { + if ((cont = !(iss >> word).fail())) { + // A little hack for handling comments - if (inComment) - { + if (inComment) { + size_t par = word.find(')'); - if (par != string::npos) - { + if (par != string::npos) { + previous.push_back(string(word.begin(), word.begin() + par + 1)); word.erase(word.begin(), word.begin() + par + 1); inComment = false; @@ -121,71 +125,71 @@ void relay::parseImpl bool keyword = false; - if (!inComment) - { - if (utility::stringUtils::isStringEqualNoCase(word, "from", 4)) - { + if (!inComment) { + + if (utility::stringUtils::isStringEqualNoCase(word, "from", 4)) { + newPart = Part_From; keyword = true; - } - else if (utility::stringUtils::isStringEqualNoCase(word, "by", 2)) - { + + } else if (utility::stringUtils::isStringEqualNoCase(word, "by", 2)) { + newPart = Part_By; keyword = true; - } - else if (utility::stringUtils::isStringEqualNoCase(word, "via", 2)) - { + + } else if (utility::stringUtils::isStringEqualNoCase(word, "via", 2)) { + newPart = Part_Via; keyword = true; - } - else if (utility::stringUtils::isStringEqualNoCase(word, "with", 2)) - { + + } else if (utility::stringUtils::isStringEqualNoCase(word, "with", 2)) { + newPart = Part_With; keyword = true; - } - else if (utility::stringUtils::isStringEqualNoCase(word, "id", 2)) - { + + } else if (utility::stringUtils::isStringEqualNoCase(word, "id", 2)) { + newPart = Part_Id; keyword = true; - } - else if (utility::stringUtils::isStringEqualNoCase(word, "for", 2)) - { + + } else if (utility::stringUtils::isStringEqualNoCase(word, "for", 2)) { + newPart = Part_For; keyword = true; } } - if (!keyword) - { - if (word.find('(') != string::npos) + if (!keyword) { + + if (word.find('(') != string::npos) { inComment = true; + } previous.push_back(word); } } - if (!cont || newPart != Part_None) - { - if (part != Part_None) - { + if (!cont || newPart != Part_None) { + + if (part != Part_None) { + std::ostringstream value; for (std::vector ::const_iterator - it = previous.begin() ; it != previous.end() ; ++it) - { + it = previous.begin() ; it != previous.end() ; ++it) { + if (it != previous.begin()) value << " "; value << *it; } - switch (part) - { - case Part_From: m_from = value.str(); break; - case Part_By: m_by = value.str(); break; - case Part_Via: m_via = value.str(); break; - case Part_With: m_with.push_back(value.str()); break; - case Part_Id: m_id = value.str(); break; - case Part_For: m_for = value.str(); break; - default: break; // Should never happen... + switch (part) { + case Part_From: m_from = value.str(); break; + case Part_By: m_by = value.str(); break; + case Part_Via: m_via = value.str(); break; + case Part_With: m_with.push_back(value.str()); break; + case Part_Id: m_id = value.str(); break; + case Part_For: m_for = value.str(); break; + default: break; // Should never happen... } } @@ -197,15 +201,19 @@ void relay::parseImpl setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void relay::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void relay::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + std::ostringstream oss; int count = 0; @@ -214,8 +222,8 @@ void relay::generateImpl if (m_via.length()) oss << (count++ > 0 ? " " : "") << "via " << m_via; for (std::vector ::const_iterator - it = m_with.begin() ; it != m_with.end() ; ++it) - { + it = m_with.begin() ; it != m_with.end() ; ++it) { + oss << (count++ > 0 ? " " : "") << "with " << *it; } @@ -227,13 +235,12 @@ void relay::generateImpl vmime::utility::outputStreamAdapter dos(oss); m_date.generate(ctx, dos, 0, NULL); - text(oss.str()).encodeAndFold(ctx, os, - curLinePos, newLinePos, text::FORCE_NO_ENCODING); + text(oss.str()).encodeAndFold(ctx, os, curLinePos, newLinePos, text::FORCE_NO_ENCODING); } -void relay::copyFrom(const component& other) -{ +void relay::copyFrom(const component& other) { + const relay& r = dynamic_cast (other); m_from = r.m_from; @@ -249,105 +256,105 @@ void relay::copyFrom(const component& other) } -relay& relay::operator=(const relay& other) -{ +relay& relay::operator=(const relay& other) { + copyFrom(other); - return (*this); + return *this; } -shared_ptr relay::clone() const -{ +shared_ptr relay::clone() const { + return make_shared (*this); } -const string& relay::getFrom() const -{ - return (m_from); +const string& relay::getFrom() const { + + return m_from; } -void relay::setFrom(const string& from) -{ +void relay::setFrom(const string& from) { + m_from = from; } -const string& relay::getVia() const -{ - return (m_via); +const string& relay::getVia() const { + + return m_via; } -void relay::setVia(const string& via) -{ +void relay::setVia(const string& via) { + m_via = via; } -const string& relay::getBy() const -{ - return (m_by); +const string& relay::getBy() const { + + return m_by; } -void relay::setBy(const string& by) -{ +void relay::setBy(const string& by) { + m_by = by; } -const string& relay::getId() const -{ - return (m_id); +const string& relay::getId() const { + + return m_id; } -void relay::setId(const string& id) -{ +void relay::setId(const string& id) { + m_id = id; } -const string& relay::getFor() const -{ - return (m_for); +const string& relay::getFor() const { + + return m_for; } -void relay::setFor(const string& for_) -{ +void relay::setFor(const string& for_) { + m_for = for_; } -const datetime& relay::getDate() const -{ - return (m_date); +const datetime& relay::getDate() const { + + return m_date; } -void relay::setDate(const datetime& date) -{ +void relay::setDate(const datetime& date) { + m_date = date; } -const std::vector & relay::getWithList() const -{ - return (m_with); +const std::vector & relay::getWithList() const { + + return m_with; } -std::vector & relay::getWithList() -{ - return (m_with); +std::vector & relay::getWithList() { + + return m_with; } -const std::vector > relay::getChildComponents() -{ +const std::vector > relay::getChildComponents() { + // TODO: should fields inherit from 'component'? (using typeAdapter) return std::vector >(); } diff --git a/src/vmime/relay.hpp b/src/vmime/relay.hpp index 35949ff1..f4676026 100644 --- a/src/vmime/relay.hpp +++ b/src/vmime/relay.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,15 +31,13 @@ #include "vmime/dateTime.hpp" -namespace vmime -{ +namespace vmime { /** Trace information about a relay (basic type). */ +class VMIME_EXPORT relay : public headerFieldValue { -class VMIME_EXPORT relay : public headerFieldValue -{ public: relay(); @@ -87,18 +85,20 @@ private: protected: - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; }; diff --git a/src/vmime/security/authenticator.hpp b/src/vmime/security/authenticator.hpp index c73229dd..03bca733 100644 --- a/src/vmime/security/authenticator.hpp +++ b/src/vmime/security/authenticator.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -60,8 +60,8 @@ namespace security { * WARNING: an authenticator should be used with one and ONLY ONE messaging * service at a time. */ -class VMIME_EXPORT authenticator : public object -{ +class VMIME_EXPORT authenticator : public object { + public: /** Return the authentication identity (usually, this @@ -134,4 +134,3 @@ public: #endif // VMIME_HAVE_MESSAGING_FEATURES #endif // VMIME_SECURITY_AUTHENTICATOR_HPP_INCLUDED - diff --git a/src/vmime/security/cert/X509Certificate.cpp b/src/vmime/security/cert/X509Certificate.cpp index e4b14682..128fac17 100644 --- a/src/vmime/security/cert/X509Certificate.cpp +++ b/src/vmime/security/cert/X509Certificate.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,24 +38,24 @@ namespace security { namespace cert { -X509Certificate::~X509Certificate() -{ +X509Certificate::~X509Certificate() { + } -void X509Certificate::checkValidity() -{ +void X509Certificate::checkValidity() { + const datetime now = datetime::now(); - if (now < getActivationDate()) - { + if (now < getActivationDate()) { + certificateNotYetValidException ex; ex.setCertificate(dynamicCast (shared_from_this())); throw ex; - } - else if (now > getExpirationDate()) - { + + } else if (now > getExpirationDate()) { + certificateExpiredException ex; ex.setCertificate(dynamicCast (shared_from_this())); diff --git a/src/vmime/security/cert/X509Certificate.hpp b/src/vmime/security/cert/X509Certificate.hpp index acf4ae21..5434b45e 100644 --- a/src/vmime/security/cert/X509Certificate.hpp +++ b/src/vmime/security/cert/X509Certificate.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -47,22 +47,20 @@ namespace cert { /** Identity certificate based on X.509 standard. */ -class VMIME_EXPORT X509Certificate : public certificate -{ +class VMIME_EXPORT X509Certificate : public certificate { + public: ~X509Certificate(); /** Supported encodings for X.509 certificates. */ - enum Format - { + enum Format { FORMAT_DER, /**< DER encoding */ FORMAT_PEM /**< PEM encoding */ }; /** Supported digest algorithms (used for fingerprint). */ - enum DigestAlgorithm - { + enum DigestAlgorithm { DIGEST_MD5, /**< MD5 digest */ DIGEST_SHA1 /**< SHA1 digest */ }; @@ -85,22 +83,27 @@ public: */ static shared_ptr import(const byte_t* data, const size_t length); - /** Imports a DER or PEM encoded X.509 certificate. + /** Import sveral DER or PEM encoded X.509 certificates. * * @param is input stream to read data from * @param certs the resulting list of certificates */ - static void import(utility::inputStream& is, - std::vector >& certs); + static void import( + utility::inputStream& is, + std::vector >& certs + ); - /** Imports a DER or PEM encoded X.509 certificate. + /** Import several DER or PEM encoded X.509 certificates. * * @param data points to raw data * @param length size of data * @param certs the resulting list of certificates */ - static void import(const byte_t* data, const size_t length, - std::vector >& certs); + static void import( + const byte_t* data, + const size_t length, + std::vector >& certs + ); /** Exports this X.509 certificate to the specified format. * @@ -147,9 +150,10 @@ public: * not match the identities in the certificate * @return true if the match is successful, false otherwise */ - virtual bool verifyHostName - (const string& hostname, - std::vector * nonMatchingNames = NULL) const = 0; + virtual bool verifyHostName( + const string& hostname, + std::vector * nonMatchingNames = NULL + ) const = 0; /** Gets the expiration date of this certificate. This is the date * at which this certificate will not be valid anymore. diff --git a/src/vmime/security/cert/certificate.hpp b/src/vmime/security/cert/certificate.hpp index 9d17ad8b..ed0f175b 100644 --- a/src/vmime/security/cert/certificate.hpp +++ b/src/vmime/security/cert/certificate.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,8 +35,8 @@ namespace cert { /** Identity certificate for a peer. */ -class VMIME_EXPORT certificate : public object, public enable_shared_from_this -{ +class VMIME_EXPORT certificate : public object, public enable_shared_from_this { + public: /** Returns the encoded form of this certificate (for example, diff --git a/src/vmime/security/cert/certificateChain.cpp b/src/vmime/security/cert/certificateChain.cpp index 1731f873..c506913a 100644 --- a/src/vmime/security/cert/certificateChain.cpp +++ b/src/vmime/security/cert/certificateChain.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,19 +30,19 @@ namespace cert { certificateChain::certificateChain(const std::vector >& certs) - : m_certs(certs) -{ + : m_certs(certs) { + } -size_t certificateChain::getCount() const -{ +size_t certificateChain::getCount() const { + return m_certs.size(); } -const shared_ptr & certificateChain::getAt(const size_t index) -{ +const shared_ptr & certificateChain::getAt(const size_t index) { + return m_certs[index]; } diff --git a/src/vmime/security/cert/certificateChain.hpp b/src/vmime/security/cert/certificateChain.hpp index 7846a200..f8c363e8 100644 --- a/src/vmime/security/cert/certificateChain.hpp +++ b/src/vmime/security/cert/certificateChain.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,8 +38,8 @@ namespace cert { /** An ordered list of certificates, from the subject certificate to * the issuer certificate. */ -class VMIME_EXPORT certificateChain : public object -{ +class VMIME_EXPORT certificateChain : public object { + public: /** Construct a new certificateChain object given an ordered list diff --git a/src/vmime/security/cert/certificateException.cpp b/src/vmime/security/cert/certificateException.cpp index c28a13fe..51a4f03b 100644 --- a/src/vmime/security/cert/certificateException.cpp +++ b/src/vmime/security/cert/certificateException.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,42 +36,42 @@ namespace cert { certificateException::certificateException() - : exception("A problem occurred with a certificate.") -{ + : exception("A problem occurred with a certificate.") { + } certificateException::certificateException(const std::string& what) - : exception(what) -{ + : exception(what) { + } -certificateException::~certificateException() throw() -{ +certificateException::~certificateException() throw() { + } -exception* certificateException::clone() const -{ +exception* certificateException::clone() const { + return new certificateException(what()); } -void certificateException::setCertificate(const shared_ptr & cert) -{ +void certificateException::setCertificate(const shared_ptr & cert) { + m_cert = cert; } -shared_ptr certificateException::getCertificate() -{ +shared_ptr certificateException::getCertificate() { + return m_cert; } -shared_ptr certificateException::getCertificate() const -{ +shared_ptr certificateException::getCertificate() const { + return m_cert; } diff --git a/src/vmime/security/cert/certificateException.hpp b/src/vmime/security/cert/certificateException.hpp index fc4ea520..9dd5443b 100644 --- a/src/vmime/security/cert/certificateException.hpp +++ b/src/vmime/security/cert/certificateException.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,8 +43,8 @@ namespace cert { /** Thrown to indicate a problem with a certificate or certificate verification. */ -class VMIME_EXPORT certificateException : public exception -{ +class VMIME_EXPORT certificateException : public exception { + public: /** Constructs a certificateException with no detail message. diff --git a/src/vmime/security/cert/certificateExpiredException.cpp b/src/vmime/security/cert/certificateExpiredException.cpp index c450f6be..1aa248ec 100644 --- a/src/vmime/security/cert/certificateExpiredException.cpp +++ b/src/vmime/security/cert/certificateExpiredException.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,8 +36,8 @@ namespace cert { certificateExpiredException::certificateExpiredException() - : certificateException("The certificate has expired.") -{ + : certificateException("The certificate has expired.") { + } diff --git a/src/vmime/security/cert/certificateExpiredException.hpp b/src/vmime/security/cert/certificateExpiredException.hpp index 7560741b..4db0a1e0 100644 --- a/src/vmime/security/cert/certificateExpiredException.hpp +++ b/src/vmime/security/cert/certificateExpiredException.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,8 +43,8 @@ namespace cert { /** Thrown when the current date and time is after the validity period * specified in the certificate. */ -class VMIME_EXPORT certificateExpiredException : public certificateException -{ +class VMIME_EXPORT certificateExpiredException : public certificateException { + public: /** Constructs a certificateExpiredException with no detail message. diff --git a/src/vmime/security/cert/certificateIssuerVerificationException.cpp b/src/vmime/security/cert/certificateIssuerVerificationException.cpp index 1e57b6d2..adf50490 100644 --- a/src/vmime/security/cert/certificateIssuerVerificationException.cpp +++ b/src/vmime/security/cert/certificateIssuerVerificationException.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,13 +36,13 @@ namespace cert { certificateIssuerVerificationException::certificateIssuerVerificationException() - : certificateException("Certificate subject/issuer verification failed.") -{ + : certificateException("Certificate subject/issuer verification failed.") { + } -exception* certificateIssuerVerificationException::clone() const -{ +exception* certificateIssuerVerificationException::clone() const { + return new certificateIssuerVerificationException(); } diff --git a/src/vmime/security/cert/certificateIssuerVerificationException.hpp b/src/vmime/security/cert/certificateIssuerVerificationException.hpp index 3d3f9a1d..e22bd924 100644 --- a/src/vmime/security/cert/certificateIssuerVerificationException.hpp +++ b/src/vmime/security/cert/certificateIssuerVerificationException.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,8 +43,8 @@ namespace cert { /** Thrown when a certificate in a certificate chain cannot be verified * against the next certificate in the chain (the issuer). */ -class VMIME_EXPORT certificateIssuerVerificationException : public certificateException -{ +class VMIME_EXPORT certificateIssuerVerificationException : public certificateException { + public: /** Constructs a certificateIssuerVerificationException with no detail message. diff --git a/src/vmime/security/cert/certificateNotTrustedException.cpp b/src/vmime/security/cert/certificateNotTrustedException.cpp index 12b932e6..a5ebb993 100644 --- a/src/vmime/security/cert/certificateNotTrustedException.cpp +++ b/src/vmime/security/cert/certificateNotTrustedException.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,13 +36,13 @@ namespace cert { certificateNotTrustedException::certificateNotTrustedException() - : certificateException("Cannot verify certificate against trusted certificates.") -{ + : certificateException("Cannot verify certificate against trusted certificates.") { + } -exception* certificateNotTrustedException::clone() const -{ +exception* certificateNotTrustedException::clone() const { + return new certificateNotTrustedException(); } diff --git a/src/vmime/security/cert/certificateNotTrustedException.hpp b/src/vmime/security/cert/certificateNotTrustedException.hpp index 35881cc3..8cdb2f04 100644 --- a/src/vmime/security/cert/certificateNotTrustedException.hpp +++ b/src/vmime/security/cert/certificateNotTrustedException.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,8 +43,8 @@ namespace cert { /** Thrown when a certificate cannot be verified against root and/or * trusted certificates. */ -class VMIME_EXPORT certificateNotTrustedException : public certificateException -{ +class VMIME_EXPORT certificateNotTrustedException : public certificateException { + public: /** Constructs a certificateNotTrustedException with no detail message. diff --git a/src/vmime/security/cert/certificateNotYetValidException.cpp b/src/vmime/security/cert/certificateNotYetValidException.cpp index da712b35..ed8ca79e 100644 --- a/src/vmime/security/cert/certificateNotYetValidException.cpp +++ b/src/vmime/security/cert/certificateNotYetValidException.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,13 +36,13 @@ namespace cert { certificateNotYetValidException::certificateNotYetValidException() - : certificateException("The certificate is not yet valid.") -{ + : certificateException("The certificate is not yet valid.") { + } -exception* certificateNotYetValidException::clone() const -{ +exception* certificateNotYetValidException::clone() const { + return new certificateNotYetValidException(); } diff --git a/src/vmime/security/cert/certificateNotYetValidException.hpp b/src/vmime/security/cert/certificateNotYetValidException.hpp index e412f466..8f321eb2 100644 --- a/src/vmime/security/cert/certificateNotYetValidException.hpp +++ b/src/vmime/security/cert/certificateNotYetValidException.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,8 +43,8 @@ namespace cert { /** Thrown when the current date and time is before the validity period * specified in the certificate. */ -class VMIME_EXPORT certificateNotYetValidException : public certificateException -{ +class VMIME_EXPORT certificateNotYetValidException : public certificateException { + public: /** Constructs a certificateNotYetValidException with no detail message. diff --git a/src/vmime/security/cert/certificateVerifier.hpp b/src/vmime/security/cert/certificateVerifier.hpp index eb6ff5eb..7e2913ad 100644 --- a/src/vmime/security/cert/certificateVerifier.hpp +++ b/src/vmime/security/cert/certificateVerifier.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,8 +42,8 @@ namespace cert { /** Verify that a certificate path issued by a server can be trusted. */ -class VMIME_EXPORT certificateVerifier : public object -{ +class VMIME_EXPORT certificateVerifier : public object { + public: /** Verify that the specified certificate chain is trusted. diff --git a/src/vmime/security/cert/defaultCertificateVerifier.cpp b/src/vmime/security/cert/defaultCertificateVerifier.cpp index 39391231..33162a0a 100644 --- a/src/vmime/security/cert/defaultCertificateVerifier.cpp +++ b/src/vmime/security/cert/defaultCertificateVerifier.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,55 +39,61 @@ namespace security { namespace cert { -defaultCertificateVerifier::defaultCertificateVerifier() -{ +defaultCertificateVerifier::defaultCertificateVerifier() { + } -defaultCertificateVerifier::~defaultCertificateVerifier() -{ +defaultCertificateVerifier::~defaultCertificateVerifier() { + } defaultCertificateVerifier::defaultCertificateVerifier(const defaultCertificateVerifier&) - : certificateVerifier() -{ + : certificateVerifier() { + // Not used } -void defaultCertificateVerifier::verify - (const shared_ptr & chain, const string& hostname) -{ - if (chain->getCount() == 0) +void defaultCertificateVerifier::verify( + const shared_ptr & chain, + const string& hostname +) { + + if (chain->getCount() == 0) { return; + } const string type = chain->getAt(0)->getType(); - if (type == "X.509") + if (type == "X.509") { verifyX509(chain, hostname); - else + } else { throw unsupportedCertificateTypeException(type); + } } -void defaultCertificateVerifier::verifyX509 - (const shared_ptr & chain, const string& hostname) -{ +void defaultCertificateVerifier::verifyX509( + const shared_ptr & chain, + const string& hostname +) { + // For every certificate in the chain, verify that the certificate // has been issued by the next certificate in the chain - if (chain->getCount() >= 2) - { - for (size_t i = 0 ; i < chain->getCount() - 1 ; ++i) - { + if (chain->getCount() >= 2) { + + for (size_t i = 0 ; i < chain->getCount() - 1 ; ++i) { + shared_ptr cert = dynamicCast (chain->getAt(i)); shared_ptr next = dynamicCast (chain->getAt(i + 1)); - if (!cert->checkIssuer(next)) - { + if (!cert->checkIssuer(next)) { + certificateIssuerVerificationException ex; ex.setCertificate(cert); @@ -98,8 +104,8 @@ void defaultCertificateVerifier::verifyX509 // For every certificate in the chain, verify that the certificate // is valid at the current time - for (size_t i = 0 ; i < chain->getCount() ; ++i) - { + for (size_t i = 0 ; i < chain->getCount() ; ++i) { + shared_ptr cert = dynamicCast (chain->getAt(i)); @@ -115,12 +121,13 @@ void defaultCertificateVerifier::verifyX509 bool trusted = false; - for (size_t i = 0 ; !trusted && i < m_x509RootCAs.size() ; ++i) - { + for (size_t i = 0 ; !trusted && i < m_x509RootCAs.size() ; ++i) { + shared_ptr rootCa = m_x509RootCAs[i]; - if (lastCert->verify(rootCa)) + if (lastCert->verify(rootCa)) { trusted = true; + } } // -- Next, if the issuer certificate cannot be verified against @@ -129,16 +136,17 @@ void defaultCertificateVerifier::verifyX509 shared_ptr firstCert = dynamicCast (chain->getAt(0)); - for (size_t i = 0 ; !trusted && i < m_x509TrustedCerts.size() ; ++i) - { + for (size_t i = 0 ; !trusted && i < m_x509TrustedCerts.size() ; ++i) { + shared_ptr cert = m_x509TrustedCerts[i]; - if (firstCert->equals(cert)) + if (firstCert->equals(cert)) { trusted = true; + } } - if (!trusted) - { + if (!trusted) { + certificateNotTrustedException ex; ex.setCertificate(firstCert); @@ -146,8 +154,8 @@ void defaultCertificateVerifier::verifyX509 } // Ensure the first certificate's subject name matches server hostname - if (!firstCert->verifyHostName(hostname)) - { + if (!firstCert->verifyHostName(hostname)) { + serverIdentityException ex; ex.setCertificate(firstCert); @@ -156,16 +164,18 @@ void defaultCertificateVerifier::verifyX509 } -void defaultCertificateVerifier::setX509RootCAs - (const std::vector >& caCerts) -{ +void defaultCertificateVerifier::setX509RootCAs( + const std::vector >& caCerts +) { + m_x509RootCAs = caCerts; } -void defaultCertificateVerifier::setX509TrustedCerts - (const std::vector >& trustedCerts) -{ +void defaultCertificateVerifier::setX509TrustedCerts( + const std::vector >& trustedCerts +) { + m_x509TrustedCerts = trustedCerts; } diff --git a/src/vmime/security/cert/defaultCertificateVerifier.hpp b/src/vmime/security/cert/defaultCertificateVerifier.hpp index cd57c5c1..4aa4445c 100644 --- a/src/vmime/security/cert/defaultCertificateVerifier.hpp +++ b/src/vmime/security/cert/defaultCertificateVerifier.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,8 +44,8 @@ class X509Certificate; /** Default implementation for certificate verification. */ -class VMIME_EXPORT defaultCertificateVerifier : public certificateVerifier -{ +class VMIME_EXPORT defaultCertificateVerifier : public certificateVerifier { + private: defaultCertificateVerifier(const defaultCertificateVerifier&); diff --git a/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp b/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp index e23abc6d..3dfa1c6f 100644 --- a/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp +++ b/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,15 +44,15 @@ namespace cert { #ifndef VMIME_BUILDING_DOC -struct GnuTLSX509CertificateInternalData -{ - GnuTLSX509CertificateInternalData() - { +struct GnuTLSX509CertificateInternalData { + + GnuTLSX509CertificateInternalData() { + gnutls_x509_crt_init(&cert); } - ~GnuTLSX509CertificateInternalData() - { + ~GnuTLSX509CertificateInternalData() { + gnutls_x509_crt_deinit(cert); } @@ -69,38 +69,39 @@ struct GnuTLSX509CertificateInternalData X509Certificate_GnuTLS::X509Certificate_GnuTLS() - : m_data(new GnuTLSX509CertificateInternalData) -{ + : m_data(new GnuTLSX509CertificateInternalData) { + } X509Certificate_GnuTLS::X509Certificate_GnuTLS(const X509Certificate&) - : X509Certificate(), m_data(NULL) -{ + : X509Certificate(), m_data(NULL) { + // Not used } -X509Certificate_GnuTLS::~X509Certificate_GnuTLS() -{ +X509Certificate_GnuTLS::~X509Certificate_GnuTLS() { + delete m_data; } -void* X509Certificate_GnuTLS::getInternalData() -{ +void* X509Certificate_GnuTLS::getInternalData() { + return &m_data->cert; } // static -shared_ptr X509Certificate::import(utility::inputStream& is) -{ +shared_ptr X509Certificate::import( + utility::inputStream& is +) { + byteArray bytes; byte_t chunk[4096]; - while (!is.eof()) - { + while (!is.eof()) { const size_t len = is.read(chunk, sizeof(chunk)); bytes.insert(bytes.end(), chunk, chunk + len); } @@ -110,9 +111,11 @@ shared_ptr X509Certificate::import(utility::inputStream& is) // static -shared_ptr X509Certificate::import - (const byte_t* data, const size_t length) -{ +shared_ptr X509Certificate::import( + const byte_t* data, + const size_t length +) { + gnutls_datum_t buffer; buffer.data = const_cast (data); buffer.size = static_cast (length); @@ -120,28 +123,31 @@ shared_ptr X509Certificate::import // Try DER format shared_ptr derCert = make_shared (); - if (gnutls_x509_crt_import(derCert->m_data->cert, &buffer, GNUTLS_X509_FMT_DER) >= 0) + if (gnutls_x509_crt_import(derCert->m_data->cert, &buffer, GNUTLS_X509_FMT_DER) >= 0) { return derCert; + } // Try PEM format shared_ptr pemCert = make_shared (); - if (gnutls_x509_crt_import(pemCert->m_data->cert, &buffer, GNUTLS_X509_FMT_PEM) >= 0) + if (gnutls_x509_crt_import(pemCert->m_data->cert, &buffer, GNUTLS_X509_FMT_PEM) >= 0) { return pemCert; + } return null; } // static -void X509Certificate::import(utility::inputStream& is, - std::vector >& certs) -{ +void X509Certificate::import( + utility::inputStream& is, + std::vector >& certs +) { + byteArray bytes; byte_t chunk[4096]; - while (!is.eof()) - { + while (!is.eof()) { const size_t len = is.read(chunk, sizeof(chunk)); bytes.insert(bytes.end(), chunk, chunk + len); } @@ -151,9 +157,12 @@ void X509Certificate::import(utility::inputStream& is, // static -void X509Certificate::import(const byte_t* data, const size_t length, - std::vector >& certs) -{ +void X509Certificate::import( + const byte_t* data, + const size_t length, + std::vector >& certs +) { + gnutls_datum_t buffer; buffer.data = const_cast (data); buffer.size = static_cast (length); @@ -162,13 +171,16 @@ void X509Certificate::import(const byte_t* data, const size_t length, gnutls_x509_crt_t x509[1024]; // Try DER format - if (gnutls_x509_crt_list_import(x509, &size, &buffer, GNUTLS_X509_FMT_DER, 0) < 0) + if (gnutls_x509_crt_list_import(x509, &size, &buffer, GNUTLS_X509_FMT_DER, 0) < 0) { // Try PEM format - if (gnutls_x509_crt_list_import(x509, &size, &buffer, GNUTLS_X509_FMT_PEM, 0) < 0) + if (gnutls_x509_crt_list_import(x509, &size, &buffer, GNUTLS_X509_FMT_PEM, 0) < 0) { return; + } + } + + for (unsigned int i = 0 ; i < size ; i += 1) { - for (unsigned int i = 0; i < size; i += 1) { auto c = make_shared (); c->m_data->swap(x509[i]); certs.push_back(c); @@ -176,16 +188,17 @@ void X509Certificate::import(const byte_t* data, const size_t length, } -void X509Certificate_GnuTLS::write - (utility::outputStream& os, const Format format) const -{ +void X509Certificate_GnuTLS::write( + utility::outputStream& os, + const Format format +) const { + size_t dataSize = 0; gnutls_x509_crt_fmt_t fmt = GNUTLS_X509_FMT_DER; - switch (format) - { - case FORMAT_DER: fmt = GNUTLS_X509_FMT_DER; break; - case FORMAT_PEM: fmt = GNUTLS_X509_FMT_PEM; break; + switch (format) { + case FORMAT_DER: fmt = GNUTLS_X509_FMT_DER; break; + case FORMAT_PEM: fmt = GNUTLS_X509_FMT_PEM; break; } gnutls_x509_crt_export(m_data->cert, fmt, NULL, &dataSize); @@ -198,8 +211,8 @@ void X509Certificate_GnuTLS::write } -const byteArray X509Certificate_GnuTLS::getSerialNumber() const -{ +const byteArray X509Certificate_GnuTLS::getSerialNumber() const { + char serial[64]; size_t serialSize = sizeof(serial); @@ -209,40 +222,43 @@ const byteArray X509Certificate_GnuTLS::getSerialNumber() const } -bool X509Certificate_GnuTLS::checkIssuer(const shared_ptr & issuer_) const -{ +bool X509Certificate_GnuTLS::checkIssuer(const shared_ptr & issuer_) const { + shared_ptr issuer = dynamicCast (issuer_); - return (gnutls_x509_crt_check_issuer - (m_data->cert, issuer->m_data->cert) >= 1); + return gnutls_x509_crt_check_issuer(m_data->cert, issuer->m_data->cert) >= 1; } -bool X509Certificate_GnuTLS::verify(const shared_ptr & caCert_) const -{ +bool X509Certificate_GnuTLS::verify(const shared_ptr & caCert_) const { + shared_ptr caCert = dynamicCast (caCert_); unsigned int verify = 0; - const int res = gnutls_x509_crt_verify - (m_data->cert, &(caCert->m_data->cert), 1, - GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, - &verify); + const int res = gnutls_x509_crt_verify( + m_data->cert, &(caCert->m_data->cert), 1, + GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, + &verify + ); - return (res == 0 && verify == 0); + return res == 0 && verify == 0; } -bool X509Certificate_GnuTLS::verifyHostName - (const string& hostname, std::vector * nonMatchingNames) const -{ - if (gnutls_x509_crt_check_hostname(m_data->cert, hostname.c_str()) != 0) - return true; +bool X509Certificate_GnuTLS::verifyHostName( + const string& hostname, + std::vector * nonMatchingNames +) const { + + if (gnutls_x509_crt_check_hostname(m_data->cert, hostname.c_str()) != 0) { + return true; + } + + if (nonMatchingNames) { - if (nonMatchingNames) - { const int MAX_CN = 256; const char* OID_X520_COMMON_NAME = "2.5.4.3"; @@ -251,16 +267,18 @@ bool X509Certificate_GnuTLS::verifyHostName dnsNameLength = sizeof(dnsName); - if (gnutls_x509_crt_get_dn_by_oid(m_data->cert, OID_X520_COMMON_NAME, 0, 0, dnsName, &dnsNameLength) >= 0) + if (gnutls_x509_crt_get_dn_by_oid(m_data->cert, OID_X520_COMMON_NAME, 0, 0, dnsName, &dnsNameLength) >= 0) { nonMatchingNames->push_back(dnsName); + } + + for (int i = 0, ret = 0 ; ret >= 0 ; ++i) { - for (int i = 0, ret = 0 ; ret >= 0 ; ++i) - { dnsNameLength = sizeof(dnsName); ret = gnutls_x509_crt_get_subject_alt_name(m_data->cert, i, dnsName, &dnsNameLength, NULL); - if (ret == GNUTLS_SAN_DNSNAME) + if (ret == GNUTLS_SAN_DNSNAME) { nonMatchingNames->push_back(dnsName); + } } } @@ -268,47 +286,45 @@ bool X509Certificate_GnuTLS::verifyHostName } -const datetime X509Certificate_GnuTLS::getActivationDate() const -{ +const datetime X509Certificate_GnuTLS::getActivationDate() const { + const time_t t = gnutls_x509_crt_get_activation_time(m_data->cert); return datetime(t); } -const datetime X509Certificate_GnuTLS::getExpirationDate() const -{ +const datetime X509Certificate_GnuTLS::getExpirationDate() const { + const time_t t = gnutls_x509_crt_get_expiration_time(m_data->cert); return datetime(t); } -const byteArray X509Certificate_GnuTLS::getFingerprint(const DigestAlgorithm algo) const -{ +const byteArray X509Certificate_GnuTLS::getFingerprint(const DigestAlgorithm algo) const { + gnutls_digest_algorithm_t galgo; - switch (algo) - { - case DIGEST_MD5: + switch (algo) { - galgo = GNUTLS_DIG_MD5; - break; + case DIGEST_MD5: - default: - case DIGEST_SHA1: + galgo = GNUTLS_DIG_MD5; + break; - galgo = GNUTLS_DIG_SHA; - break; + default: + case DIGEST_SHA1: + + galgo = GNUTLS_DIG_SHA; + break; } size_t bufferSize = 0; - gnutls_x509_crt_get_fingerprint - (m_data->cert, galgo, NULL, &bufferSize); + gnutls_x509_crt_get_fingerprint(m_data->cert, galgo, NULL, &bufferSize); std::vector buffer(bufferSize); - if (gnutls_x509_crt_get_fingerprint - (m_data->cert, galgo, &buffer[0], &bufferSize) == 0) - { + if (gnutls_x509_crt_get_fingerprint(m_data->cert, galgo, &buffer[0], &bufferSize) == 0) { + byteArray res; res.insert(res.end(), &buffer[0], &buffer[0] + bufferSize); @@ -319,8 +335,8 @@ const byteArray X509Certificate_GnuTLS::getFingerprint(const DigestAlgorithm alg } -const byteArray X509Certificate_GnuTLS::getEncoded() const -{ +const byteArray X509Certificate_GnuTLS::getEncoded() const { + byteArray bytes; utility::outputStreamByteArrayAdapter os(bytes); @@ -330,37 +346,39 @@ const byteArray X509Certificate_GnuTLS::getEncoded() const } -const string X509Certificate_GnuTLS::getIssuerString() const -{ +const string X509Certificate_GnuTLS::getIssuerString() const { + char buffer[4096]; size_t bufferSize = sizeof(buffer); - if (gnutls_x509_crt_get_issuer_dn(m_data->cert, buffer, &bufferSize) != GNUTLS_E_SUCCESS) + if (gnutls_x509_crt_get_issuer_dn(m_data->cert, buffer, &bufferSize) != GNUTLS_E_SUCCESS) { return ""; + } return buffer; } -const string X509Certificate_GnuTLS::getType() const -{ +const string X509Certificate_GnuTLS::getType() const { + return "X.509"; } -int X509Certificate_GnuTLS::getVersion() const -{ +int X509Certificate_GnuTLS::getVersion() const { + return gnutls_x509_crt_get_version(m_data->cert); } -bool X509Certificate_GnuTLS::equals(const shared_ptr & other) const -{ +bool X509Certificate_GnuTLS::equals(const shared_ptr & other) const { + shared_ptr otherX509 = dynamicCast (other); - if (!otherX509) + if (!otherX509) { return false; + } const byteArray fp1 = getFingerprint(DIGEST_MD5); const byteArray fp2 = otherX509->getFingerprint(DIGEST_MD5); diff --git a/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp b/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp index f06955bf..c7c6c482 100644 --- a/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp +++ b/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,8 +39,8 @@ namespace security { namespace cert { -class X509Certificate_GnuTLS : public X509Certificate -{ +class X509Certificate_GnuTLS : public X509Certificate { + friend class X509Certificate; X509Certificate_GnuTLS(const X509Certificate&); @@ -61,9 +61,10 @@ public: bool verify(const shared_ptr & caCert) const; - bool verifyHostName - (const string& hostname, - std::vector * nonMatchingNames = NULL) const; + bool verifyHostName( + const string& hostname, + std::vector * nonMatchingNames = NULL + ) const; const datetime getExpirationDate() const; const datetime getActivationDate() const; diff --git a/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp b/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp index 9ce09592..268a42c2 100644 --- a/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp +++ b/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -65,12 +65,12 @@ static net::tls::OpenSSLInitializer::autoInitializer openSSLInitializer; #ifndef VMIME_BUILDING_DOC -class monthMap -{ +class monthMap { + public: - monthMap() - { + monthMap() { + m_monthMap["jan"] = vmime::datetime::JAN; m_monthMap["feb"] = vmime::datetime::FEB; m_monthMap["mar"] = vmime::datetime::MAR; @@ -85,15 +85,16 @@ public: m_monthMap["dec"] = vmime::datetime::DEC; } - int getMonth(vmime::string mstr) - { + int getMonth(vmime::string mstr) { + std::transform(mstr.begin(), mstr.end(), mstr.begin(), ::tolower); std::map ::const_iterator c_it = m_monthMap.find(mstr); - if (c_it != m_monthMap.end()) + if (c_it != m_monthMap.end()) { return c_it->second; + } return -1; } @@ -107,17 +108,18 @@ static monthMap sg_monthMap; -struct OpenSSLX509CertificateInternalData -{ - OpenSSLX509CertificateInternalData() - { +struct OpenSSLX509CertificateInternalData { + + OpenSSLX509CertificateInternalData() { + cert = 0; } - ~OpenSSLX509CertificateInternalData() - { - if (cert) + ~OpenSSLX509CertificateInternalData() { + + if (cert) { X509_free(cert); + } } X509* cert; @@ -125,14 +127,14 @@ struct OpenSSLX509CertificateInternalData // Workaround for i2v() taking either a const or a non-const 'method' on some platforms -STACK_OF(CONF_VALUE)* call_i2v(const X509V3_EXT_METHOD* m, void* p1, STACK_OF(CONF_VALUE)* p2) -{ +STACK_OF(CONF_VALUE)* call_i2v(const X509V3_EXT_METHOD* m, void* p1, STACK_OF(CONF_VALUE)* p2) { + return m->i2v(m, p1, p2); } -STACK_OF(CONF_VALUE)* call_i2v(X509V3_EXT_METHOD* m, void* p1, STACK_OF(CONF_VALUE)* p2) -{ +STACK_OF(CONF_VALUE)* call_i2v(X509V3_EXT_METHOD* m, void* p1, STACK_OF(CONF_VALUE)* p2) { + return m->i2v(m, p1, p2); } @@ -141,55 +143,55 @@ STACK_OF(CONF_VALUE)* call_i2v(X509V3_EXT_METHOD* m, void* p1, STACK_OF(CONF_VAL X509Certificate_OpenSSL::X509Certificate_OpenSSL() - : m_data(new OpenSSLX509CertificateInternalData) -{ + : m_data(new OpenSSLX509CertificateInternalData) { + } X509Certificate_OpenSSL::X509Certificate_OpenSSL(X509* cert) - : m_data(new OpenSSLX509CertificateInternalData) -{ + : m_data(new OpenSSLX509CertificateInternalData) { + m_data->cert = X509_dup(cert); } X509Certificate_OpenSSL::X509Certificate_OpenSSL(const X509Certificate_OpenSSL&) - : X509Certificate(), m_data(NULL) -{ + : X509Certificate(), m_data(NULL) { + // Not used } -X509Certificate_OpenSSL::~X509Certificate_OpenSSL() -{ +X509Certificate_OpenSSL::~X509Certificate_OpenSSL() { + delete m_data; } -void* X509Certificate_OpenSSL::getInternalData() -{ +void* X509Certificate_OpenSSL::getInternalData() { + return &m_data->cert; } // static -shared_ptr X509Certificate_OpenSSL::importInternal(X509* cert) -{ - if (cert) +shared_ptr X509Certificate_OpenSSL::importInternal(X509* cert) { + + if (cert) { return make_shared (reinterpret_cast (cert)); + } return null; } // static -shared_ptr X509Certificate::import(utility::inputStream& is) -{ +shared_ptr X509Certificate::import(utility::inputStream& is) { + byteArray bytes; byte_t chunk[4096]; - while (!is.eof()) - { + while (!is.eof()) { const size_t len = is.read(chunk, sizeof(chunk)); bytes.insert(bytes.end(), chunk, chunk + len); } @@ -199,15 +201,16 @@ shared_ptr X509Certificate::import(utility::inputStream& is) // static -shared_ptr X509Certificate::import - (const byte_t* data, const size_t length) -{ +shared_ptr X509Certificate::import( + const byte_t* data, + const size_t length +) { + shared_ptr cert = make_shared (); BIO* membio = BIO_new_mem_buf(const_cast (data), static_cast (length)); - if (!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0)) - { + if (!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0)) { BIO_vfree(membio); return null; } @@ -219,14 +222,15 @@ shared_ptr X509Certificate::import // static -void X509Certificate::import(utility::inputStream& is, - std::vector >& certs) -{ +void X509Certificate::import( + utility::inputStream& is, + std::vector >& certs +) { + byteArray bytes; byte_t chunk[4096]; - while (!is.eof()) - { + while (!is.eof()) { const size_t len = is.read(chunk, sizeof(chunk)); bytes.insert(bytes.end(), chunk, chunk + len); } @@ -236,16 +240,23 @@ void X509Certificate::import(utility::inputStream& is, // static -void X509Certificate::import(const byte_t* data, const size_t length, - std::vector >& certs) -{ +void X509Certificate::import( + const byte_t* data, + const size_t length, + std::vector >& certs +) { BIO* membio = BIO_new_mem_buf(const_cast (data), static_cast (length)); shared_ptr cert = null; while (true) { + cert = make_shared (); - if (!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0)) break; + + if (!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0)) { + break; + } + certs.push_back(cert); } @@ -253,37 +264,41 @@ void X509Certificate::import(const byte_t* data, const size_t length, } -void X509Certificate_OpenSSL::write - (utility::outputStream& os, const Format format) const -{ +void X509Certificate_OpenSSL::write( + utility::outputStream& os, + const Format format +) const { + BIO* membio = 0; long dataSize = 0; unsigned char* out = 0; - if (format == FORMAT_DER) - { - if ((dataSize = i2d_X509(m_data->cert, &out)) < 0) + if (format == FORMAT_DER) { + + if ((dataSize = i2d_X509(m_data->cert, &out)) < 0) { goto err; + } os.write(reinterpret_cast (out), dataSize); os.flush(); OPENSSL_free(out); - } - else if (format == FORMAT_PEM) - { + + } else if (format == FORMAT_PEM) { + membio = BIO_new(BIO_s_mem()); BIO_set_close(membio, BIO_CLOSE); - if (!PEM_write_bio_X509(membio, m_data->cert)) + if (!PEM_write_bio_X509(membio, m_data->cert)) { goto pem_err; + } dataSize = BIO_get_mem_data(membio, &out); os.write(reinterpret_cast (out), dataSize); os.flush(); BIO_vfree(membio); - } - else - { + + } else { + throw unsupportedCertificateTypeException("Unknown format"); } @@ -291,8 +306,9 @@ void X509Certificate_OpenSSL::write pem_err: { - if (membio) + if (membio) { BIO_vfree(membio); + } } err: @@ -300,14 +316,13 @@ err: char errstr[256]; long ec = ERR_get_error(); ERR_error_string(ec, errstr); - throw certificateException( - "OpenSSLX509Certificate_OpenSSL::write exception - " + string(errstr)); + throw certificateException("OpenSSLX509Certificate_OpenSSL::write exception - " + string(errstr)); } } -const byteArray X509Certificate_OpenSSL::getSerialNumber() const -{ +const byteArray X509Certificate_OpenSSL::getSerialNumber() const { + ASN1_INTEGER *serial = X509_get_serialNumber(m_data->cert); BIGNUM *bnser = ASN1_INTEGER_to_BN(serial, NULL); int n = BN_num_bytes(bnser); @@ -320,8 +335,8 @@ const byteArray X509Certificate_OpenSSL::getSerialNumber() const } -bool X509Certificate_OpenSSL::checkIssuer(const shared_ptr & cert_) const -{ +bool X509Certificate_OpenSSL::checkIssuer(const shared_ptr & cert_) const { + shared_ptr cert = dynamicCast (cert_); @@ -347,8 +362,8 @@ bool X509Certificate_OpenSSL::checkIssuer(const shared_ptr & caCert_) const -{ +bool X509Certificate_OpenSSL::verify(const shared_ptr & caCert_) const { + shared_ptr caCert = dynamicCast (caCert_); @@ -358,25 +373,25 @@ bool X509Certificate_OpenSSL::verify(const shared_ptr & c X509_STORE *store = X509_STORE_new(); - if (store) - { + if (store) { + X509_STORE_CTX *verifyCtx = X509_STORE_CTX_new(); - if (verifyCtx) - { - if (X509_STORE_add_cert(store, caCert->m_data->cert)) - { + if (verifyCtx) { + + if (X509_STORE_add_cert(store, caCert->m_data->cert)) { + X509_STORE_CTX_init(verifyCtx, store, m_data->cert, NULL); int ret = X509_verify_cert(verifyCtx); - if (ret == 1) - { + if (ret == 1) { + verified = true; error = false; - } - else if (ret == 0) - { + + } else if (ret == 0) { + verified = false; error = false; } @@ -395,8 +410,8 @@ bool X509Certificate_OpenSSL::verify(const shared_ptr & c // static -bool X509Certificate_OpenSSL::cnMatch(const char* cnBuf, const char* host) -{ +bool X509Certificate_OpenSSL::cnMatch(const char* cnBuf, const char* host) { + // Right-to-left match, looking for a '*' wildcard const bool hasWildcard = (strlen(cnBuf) > 1 && cnBuf[0] == '*' && cnBuf[1] == '.'); const char* cnBufReverseEndPtr = (cnBuf + (hasWildcard ? 2 : 0)); @@ -405,29 +420,34 @@ bool X509Certificate_OpenSSL::cnMatch(const char* cnBuf, const char* host) bool matches = true; - while (matches && --hostPtr >= host && --cnPtr >= cnBufReverseEndPtr) + while (matches && --hostPtr >= host && --cnPtr >= cnBufReverseEndPtr) { matches = (toupper(*hostPtr) == toupper(*cnPtr)); + } return matches; } -bool X509Certificate_OpenSSL::verifyHostName - (const string& hostname, std::vector * nonMatchingNames) const -{ +bool X509Certificate_OpenSSL::verifyHostName( + const string& hostname, + std::vector * nonMatchingNames +) const { + // First, check subject common name against hostname char CNBuffer[1024]; CNBuffer[sizeof(CNBuffer) - 1] = '\0'; X509_NAME* xname = X509_get_subject_name(m_data->cert); - if (X509_NAME_get_text_by_NID(xname, NID_commonName, CNBuffer, sizeof(CNBuffer)) != -1) - { - if (cnMatch(CNBuffer, hostname.c_str())) - return true; + if (X509_NAME_get_text_by_NID(xname, NID_commonName, CNBuffer, sizeof(CNBuffer)) != -1) { - if (nonMatchingNames) + if (cnMatch(CNBuffer, hostname.c_str())) { + return true; + } + + if (nonMatchingNames) { nonMatchingNames->push_back(CNBuffer); + } } // Now, look in subject alternative names @@ -436,34 +456,34 @@ bool X509Certificate_OpenSSL::verifyHostName STACK_OF(GENERAL_NAME)* altNames = static_cast (X509_get_ext_d2i(m_data->cert, NID_subject_alt_name, NULL, NULL)); - if (altNames == NULL) + if (altNames == NULL) { return false; + } // Check each name within the extension - for (int i = 0, n = sk_GENERAL_NAME_num(altNames) ; i < n ; ++i) - { + for (int i = 0, n = sk_GENERAL_NAME_num(altNames) ; i < n ; ++i) { + const GENERAL_NAME* currentName = sk_GENERAL_NAME_value(altNames, i); - if (currentName->type == GEN_DNS) - { + if (currentName->type == GEN_DNS) { + // Current name is a DNS name, let's check it char *DNSName = (char *) ASN1_STRING_data(currentName->d.dNSName); // Make sure there isn't an embedded NUL character in the DNS name - if (ASN1_STRING_length(currentName->d.dNSName) != strlen(DNSName)) - { + if (ASN1_STRING_length(currentName->d.dNSName) != strlen(DNSName)) { // Malformed certificate break; } - if (cnMatch(DNSName, hostname.c_str())) - { + if (cnMatch(DNSName, hostname.c_str())) { verify = true; break; } - if (nonMatchingNames) + if (nonMatchingNames) { nonMatchingNames->push_back(DNSName); + } } } @@ -473,8 +493,8 @@ bool X509Certificate_OpenSSL::verifyHostName } -const datetime X509Certificate_OpenSSL::convertX509Date(void* time) const -{ +const datetime X509Certificate_OpenSSL::convertX509Date(void* time) const { + char* buffer; BIO* out = BIO_new(BIO_s_mem()); BIO_set_close(out, BIO_CLOSE); @@ -491,15 +511,16 @@ const datetime X509Certificate_OpenSSL::convertX509Date(void* time) const BIO_free(out); delete [] dest; - if (t.size() > 0) - { + if (t.size() > 0) { + char month[4] = {0}; char zone[4] = {0}; int day, hour, minute, second, year; int nrconv = sscanf(t.c_str(), "%s %2d %02d:%02d:%02d %d%s", month, &day, &hour, &minute, &second,&year,zone); - if (nrconv >= 6) + if (nrconv >= 6) { return datetime(year, sg_monthMap.getMonth(vmime::string(month)), day, hour, minute, second); + } } // let datetime try and parse it @@ -507,20 +528,20 @@ const datetime X509Certificate_OpenSSL::convertX509Date(void* time) const } -const datetime X509Certificate_OpenSSL::getActivationDate() const -{ +const datetime X509Certificate_OpenSSL::getActivationDate() const { + return convertX509Date(X509_get_notBefore(m_data->cert)); } -const datetime X509Certificate_OpenSSL::getExpirationDate() const -{ +const datetime X509Certificate_OpenSSL::getExpirationDate() const { + return convertX509Date(X509_get_notAfter(m_data->cert)); } -const byteArray X509Certificate_OpenSSL::getFingerprint(const DigestAlgorithm algo) const -{ +const byteArray X509Certificate_OpenSSL::getFingerprint(const DigestAlgorithm algo) const { + BIO *out; int j; unsigned int n; @@ -528,29 +549,28 @@ const byteArray X509Certificate_OpenSSL::getFingerprint(const DigestAlgorithm al unsigned char * fingerprint; unsigned char md[EVP_MAX_MD_SIZE]; - switch (algo) - { - case DIGEST_MD5: + switch (algo) { - digest = EVP_md5(); - break; + case DIGEST_MD5: - default: - case DIGEST_SHA1: + digest = EVP_md5(); + break; - digest = EVP_sha1(); - break; + default: + case DIGEST_SHA1: + + digest = EVP_sha1(); + break; } out = BIO_new(BIO_s_mem()); BIO_set_close(out, BIO_CLOSE); - if (X509_digest(m_data->cert, digest, md, &n)) - { - for (j=0; j<(int)n; j++) - { - BIO_printf (out, "%02X",md[j]); - if (j+1 != (int)n) BIO_printf(out, ":"); + if (X509_digest(m_data->cert, digest, md, &n)) { + + for (j = 0 ; j < (int) n ; j++) { + BIO_printf(out, "%02X", md[j]); + if (j + 1 != (int) n) BIO_printf(out, ":"); } } @@ -568,8 +588,8 @@ const byteArray X509Certificate_OpenSSL::getFingerprint(const DigestAlgorithm al } -const byteArray X509Certificate_OpenSSL::getEncoded() const -{ +const byteArray X509Certificate_OpenSSL::getEncoded() const { + byteArray bytes; utility::outputStreamByteArrayAdapter os(bytes); @@ -579,8 +599,8 @@ const byteArray X509Certificate_OpenSSL::getEncoded() const } -const string X509Certificate_OpenSSL::getIssuerString() const -{ +const string X509Certificate_OpenSSL::getIssuerString() const { + // Get issuer for this cert BIO* out = BIO_new(BIO_s_mem()); X509_NAME_print_ex(out, X509_get_issuer_name(m_data->cert), 0, XN_FLAG_RFC2253); @@ -595,25 +615,26 @@ const string X509Certificate_OpenSSL::getIssuerString() const } -const string X509Certificate_OpenSSL::getType() const -{ +const string X509Certificate_OpenSSL::getType() const { + return "X.509"; } -int X509Certificate_OpenSSL::getVersion() const -{ - return (int)X509_get_version(m_data->cert); +int X509Certificate_OpenSSL::getVersion() const { + + return (int) X509_get_version(m_data->cert); } -bool X509Certificate_OpenSSL::equals(const shared_ptr & other) const -{ +bool X509Certificate_OpenSSL::equals(const shared_ptr & other) const { + shared_ptr otherX509 = dynamicCast (other); - if (!otherX509) + if (!otherX509) { return false; + } const byteArray fp1 = getFingerprint(DIGEST_MD5); const byteArray fp2 = otherX509->getFingerprint(DIGEST_MD5); diff --git a/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp b/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp index 89b54a9a..c0ebf3c3 100644 --- a/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp +++ b/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,8 +41,8 @@ namespace security { namespace cert { -class X509Certificate_OpenSSL : public X509Certificate -{ +class X509Certificate_OpenSSL : public X509Certificate { + friend class X509Certificate; X509Certificate_OpenSSL(const X509Certificate_OpenSSL&); @@ -64,9 +64,10 @@ public: bool verify(const shared_ptr & caCert) const; - bool verifyHostName - (const string& hostname, - std::vector * nonMatchingNames = NULL) const; + bool verifyHostName( + const string& hostname, + std::vector * nonMatchingNames = NULL + ) const; const datetime getExpirationDate() const; const datetime getActivationDate() const; diff --git a/src/vmime/security/cert/serverIdentityException.cpp b/src/vmime/security/cert/serverIdentityException.cpp index 585d1021..fcbe571f 100644 --- a/src/vmime/security/cert/serverIdentityException.cpp +++ b/src/vmime/security/cert/serverIdentityException.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,13 +36,13 @@ namespace cert { serverIdentityException::serverIdentityException() - : certificateException("Server identity cannot be verified.") -{ + : certificateException("Server identity cannot be verified.") { + } -exception* serverIdentityException::clone() const -{ +exception* serverIdentityException::clone() const { + return new serverIdentityException(); } diff --git a/src/vmime/security/cert/serverIdentityException.hpp b/src/vmime/security/cert/serverIdentityException.hpp index 47feced7..358553ed 100644 --- a/src/vmime/security/cert/serverIdentityException.hpp +++ b/src/vmime/security/cert/serverIdentityException.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,8 +43,8 @@ namespace cert { /** Thrown when the subject name of a certificate does not match * the hostname of the server. */ -class VMIME_EXPORT serverIdentityException : public certificateException -{ +class VMIME_EXPORT serverIdentityException : public certificateException { + public: /** Constructs a serverIdentityException with no detail message. diff --git a/src/vmime/security/cert/unsupportedCertificateTypeException.cpp b/src/vmime/security/cert/unsupportedCertificateTypeException.cpp index b27bb8be..57656512 100644 --- a/src/vmime/security/cert/unsupportedCertificateTypeException.cpp +++ b/src/vmime/security/cert/unsupportedCertificateTypeException.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,18 +37,18 @@ namespace cert { unsupportedCertificateTypeException::unsupportedCertificateTypeException(const string& type) : certificateException(string("Unsupported certificate type: '") + type + "'."), - m_type(type) -{ + m_type(type) { + } -unsupportedCertificateTypeException::~unsupportedCertificateTypeException() throw() -{ +unsupportedCertificateTypeException::~unsupportedCertificateTypeException() throw() { + } -exception* unsupportedCertificateTypeException::clone() const -{ +exception* unsupportedCertificateTypeException::clone() const { + return new unsupportedCertificateTypeException(m_type); } diff --git a/src/vmime/security/cert/unsupportedCertificateTypeException.hpp b/src/vmime/security/cert/unsupportedCertificateTypeException.hpp index 356ac32b..725035f7 100644 --- a/src/vmime/security/cert/unsupportedCertificateTypeException.hpp +++ b/src/vmime/security/cert/unsupportedCertificateTypeException.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,8 +42,8 @@ namespace cert { /** Thrown when a certificate is of unsupported format. */ -class VMIME_EXPORT unsupportedCertificateTypeException : public certificateException -{ +class VMIME_EXPORT unsupportedCertificateTypeException : public certificateException { + public: /** Constructs a unsupportedCertificateTypeException. diff --git a/src/vmime/security/defaultAuthenticator.cpp b/src/vmime/security/defaultAuthenticator.cpp index 5503de5f..b2b249c6 100644 --- a/src/vmime/security/defaultAuthenticator.cpp +++ b/src/vmime/security/defaultAuthenticator.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,85 +38,88 @@ namespace vmime { namespace security { -defaultAuthenticator::defaultAuthenticator() -{ +defaultAuthenticator::defaultAuthenticator() { + } -defaultAuthenticator::~defaultAuthenticator() -{ +defaultAuthenticator::~defaultAuthenticator() { + } -const string defaultAuthenticator::getUsername() const -{ +const string defaultAuthenticator::getUsername() const { + shared_ptr service = m_service.lock(); const string prefix = service->getInfos().getPropertyPrefix(); const propertySet& props = service->getSession()->getProperties(); - if (props.hasProperty(prefix + net::serviceInfos::property::AUTH_USERNAME.getName())) + if (props.hasProperty(prefix + net::serviceInfos::property::AUTH_USERNAME.getName())) { return props[prefix + net::serviceInfos::property::AUTH_USERNAME.getName()]; + } throw exceptions::no_auth_information(); } -const string defaultAuthenticator::getPassword() const -{ +const string defaultAuthenticator::getPassword() const { + shared_ptr service = m_service.lock(); const string prefix = service->getInfos().getPropertyPrefix(); const propertySet& props = service->getSession()->getProperties(); - if (props.hasProperty(prefix + net::serviceInfos::property::AUTH_PASSWORD.getName())) + if (props.hasProperty(prefix + net::serviceInfos::property::AUTH_PASSWORD.getName())) { return props[prefix + net::serviceInfos::property::AUTH_PASSWORD.getName()]; + } throw exceptions::no_auth_information(); } -const string defaultAuthenticator::getAccessToken() const -{ +const string defaultAuthenticator::getAccessToken() const { + shared_ptr service = m_service.lock(); const string prefix = service->getInfos().getPropertyPrefix(); const propertySet& props = service->getSession()->getProperties(); - if (props.hasProperty(prefix + net::serviceInfos::property::AUTH_ACCESS_TOKEN.getName())) + if (props.hasProperty(prefix + net::serviceInfos::property::AUTH_ACCESS_TOKEN.getName())) { return props[prefix + net::serviceInfos::property::AUTH_ACCESS_TOKEN.getName()]; + } throw exceptions::no_auth_information(); } -const string defaultAuthenticator::getHostname() const -{ +const string defaultAuthenticator::getHostname() const { + return platform::getHandler()->getHostName(); } -const string defaultAuthenticator::getAnonymousToken() const -{ +const string defaultAuthenticator::getAnonymousToken() const { + return "anonymous@" + platform::getHandler()->getHostName(); } -const string defaultAuthenticator::getServiceName() const -{ +const string defaultAuthenticator::getServiceName() const { + // Information cannot be provided throw exceptions::no_auth_information(); } -void defaultAuthenticator::setService(const shared_ptr & serv) -{ +void defaultAuthenticator::setService(const shared_ptr & serv) { + m_service = serv; } -weak_ptr defaultAuthenticator::getService() const -{ +weak_ptr defaultAuthenticator::getService() const { + return m_service; } @@ -126,4 +129,3 @@ weak_ptr defaultAuthenticator::getService() const #endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/vmime/security/defaultAuthenticator.hpp b/src/vmime/security/defaultAuthenticator.hpp index d5b4d787..e053f9ef 100644 --- a/src/vmime/security/defaultAuthenticator.hpp +++ b/src/vmime/security/defaultAuthenticator.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,8 +41,8 @@ namespace security { /** An authenticator that can provide some basic information by * reading in the messaging session properties. */ -class VMIME_EXPORT defaultAuthenticator : public authenticator -{ +class VMIME_EXPORT defaultAuthenticator : public authenticator { + public: defaultAuthenticator(); @@ -71,4 +71,3 @@ private: #endif // VMIME_HAVE_MESSAGING_FEATURES #endif // VMIME_SECURITY_DEFAULTAUTHENTICATOR_HPP_INCLUDED - diff --git a/src/vmime/security/digest/md5/md5MessageDigest.cpp b/src/vmime/security/digest/md5/md5MessageDigest.cpp index a83f0623..9a07b57b 100644 --- a/src/vmime/security/digest/md5/md5MessageDigest.cpp +++ b/src/vmime/security/digest/md5/md5MessageDigest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -59,20 +59,20 @@ namespace digest { namespace md5 { -md5MessageDigest::md5MessageDigest() -{ +md5MessageDigest::md5MessageDigest() { + init(); } -void md5MessageDigest::reset() -{ +void md5MessageDigest::reset() { + init(); } -void md5MessageDigest::init() -{ +void md5MessageDigest::init() { + m_hash[0] = 0x67452301; m_hash[1] = 0xefcdab89; m_hash[2] = 0x98badcfe; @@ -83,69 +83,68 @@ void md5MessageDigest::init() } -static void copyUint8Array(vmime_uint8* dest, const vmime_uint8* src, size_t count) -{ - for ( ; count >= 4 ; count -= 4, dest += 4, src += 4) - { +static void copyUint8Array(vmime_uint8* dest, const vmime_uint8* src, size_t count) { + + for ( ; count >= 4 ; count -= 4, dest += 4, src += 4) { dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; dest[3] = src[3]; } - for ( ; count ; --count, ++dest, ++src) + for ( ; count ; --count, ++dest, ++src) { dest[0] = src[0]; + } } -static inline vmime_uint32 swapUint32(const vmime_uint32 D) -{ +static inline vmime_uint32 swapUint32(const vmime_uint32 D) { + return ((D << 24) | ((D << 8) & 0x00FF0000) | ((D >> 8) & 0x0000FF00) | (D >> 24)); } -static inline void swapUint32Array(vmime_uint32* buf, size_t words) -{ - for ( ; words >= 4 ; words -= 4, buf += 4) - { +static inline void swapUint32Array(vmime_uint32* buf, size_t words) { + + for ( ; words >= 4 ; words -= 4, buf += 4) { buf[0] = swapUint32(buf[0]); buf[1] = swapUint32(buf[1]); buf[2] = swapUint32(buf[2]); buf[3] = swapUint32(buf[3]); } - for ( ; words ; --words, ++buf) + for ( ; words ; --words, ++buf) { buf[0] = swapUint32(buf[0]); + } } -void md5MessageDigest::update(const byte_t b) -{ +void md5MessageDigest::update(const byte_t b) { + update(&b, 1); } -void md5MessageDigest::update(const string& s) -{ +void md5MessageDigest::update(const string& s) { + update(reinterpret_cast (s.data()), s.length()); } -void md5MessageDigest::update(const byte_t* data, const size_t offset, const size_t len) -{ +void md5MessageDigest::update(const byte_t* data, const size_t offset, const size_t len) { + update(data + offset, len); } -void md5MessageDigest::update(const byte_t* data, const size_t length) -{ +void md5MessageDigest::update(const byte_t* data, const size_t length) { + const size_t avail = 64 - (m_byteCount & 0x3f); size_t len = length; m_byteCount += len; - if (avail > len) - { + if (avail > len) { copyUint8Array(m_block.b8 + (64 - avail), data, len); return; } @@ -156,8 +155,8 @@ void md5MessageDigest::update(const byte_t* data, const size_t length) data += avail; len -= avail; - while (len >= 64) - { + while (len >= 64) { + copyUint8Array(m_block.b8, data, 64); transformHelper(); @@ -169,30 +168,33 @@ void md5MessageDigest::update(const byte_t* data, const size_t length) } -void md5MessageDigest::finalize(const string& s) -{ +void md5MessageDigest::finalize(const string& s) { + update(s); finalize(); } -void md5MessageDigest::finalize(const byte_t* buffer, const size_t len) -{ +void md5MessageDigest::finalize(const byte_t* buffer, const size_t len) { + update(buffer, len); finalize(); } -void md5MessageDigest::finalize(const byte_t* buffer, - const size_t offset, const size_t len) -{ +void md5MessageDigest::finalize( + const byte_t* buffer, + const size_t offset, + const size_t len +) { + update(buffer, offset, len); finalize(); } -void md5MessageDigest::finalize() -{ +void md5MessageDigest::finalize() { + const long offset = m_byteCount & 0x3f; vmime_uint8* p = m_block.b8 + offset; @@ -200,8 +202,8 @@ void md5MessageDigest::finalize() *p++ = 0x80; - if (padding < 0) - { + if (padding < 0) { + memset(p, 0x00, padding + 8); transformHelper(); p = m_block.b8; @@ -227,8 +229,8 @@ void md5MessageDigest::finalize() } -void md5MessageDigest::transformHelper() -{ +void md5MessageDigest::transformHelper() { + #if VMIME_BYTE_ORDER_BIG_ENDIAN swapUint32Array(m_block.b32, 64 / 4); #endif @@ -236,8 +238,8 @@ void md5MessageDigest::transformHelper() } -void md5MessageDigest::transform() -{ +void md5MessageDigest::transform() { + const vmime_uint32* const in = m_block.b32; vmime_uint32 a = m_hash[0]; @@ -328,14 +330,14 @@ void md5MessageDigest::transform() } -size_t md5MessageDigest::getDigestLength() const -{ +size_t md5MessageDigest::getDigestLength() const { + return 16; } -const byte_t* md5MessageDigest::getDigest() const -{ +const byte_t* md5MessageDigest::getDigest() const { + return reinterpret_cast (m_hash); } diff --git a/src/vmime/security/digest/md5/md5MessageDigest.hpp b/src/vmime/security/digest/md5/md5MessageDigest.hpp index ef94f5c8..bdb730a7 100644 --- a/src/vmime/security/digest/md5/md5MessageDigest.hpp +++ b/src/vmime/security/digest/md5/md5MessageDigest.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,8 +34,8 @@ namespace digest { namespace md5 { -class md5MessageDigest : public messageDigest -{ +class md5MessageDigest : public messageDigest { + public: md5MessageDigest(); @@ -63,8 +63,7 @@ protected: vmime_uint32 m_hash[4]; - union BlockType - { + union BlockType { vmime_uint32 b32[16]; vmime_uint8 b8[64]; }; diff --git a/src/vmime/security/digest/messageDigest.cpp b/src/vmime/security/digest/messageDigest.cpp index 18fc8628..d7e394fc 100644 --- a/src/vmime/security/digest/messageDigest.cpp +++ b/src/vmime/security/digest/messageDigest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,8 +31,8 @@ namespace security { namespace digest { -const string messageDigest::getHexDigest() const -{ +const string messageDigest::getHexDigest() const { + const byte_t* hash = getDigest(); const size_t len = getDigestLength(); @@ -41,8 +41,7 @@ const string messageDigest::getHexDigest() const std::ostringstream oss; oss.imbue(std::locale::classic()); - for (size_t i = 0 ; i < len ; ++i) - { + for (size_t i = 0 ; i < len ; ++i) { oss << hex[(hash[i] & 0xf0) >> 4]; oss << hex[(hash[i] & 0x0f)]; } diff --git a/src/vmime/security/digest/messageDigest.hpp b/src/vmime/security/digest/messageDigest.hpp index d17dfbc2..04138103 100644 --- a/src/vmime/security/digest/messageDigest.hpp +++ b/src/vmime/security/digest/messageDigest.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,9 +37,8 @@ namespace digest { /** Computes message digests using standard algorithms, * such as MD5 or SHA. */ +class VMIME_EXPORT messageDigest : public object { -class VMIME_EXPORT messageDigest : public object -{ public: /** Updates the digest using the specified string. @@ -68,9 +67,11 @@ public: * @param offset offset to start from in the array of bytes * @param len number of bytes to use, starting at offset */ - virtual void update(const byte_t* buffer, - const size_t offset, - const size_t len) = 0; + virtual void update( + const byte_t* buffer, + const size_t offset, + const size_t len + ) = 0; /** Completes the hash computation by performing final operations * such as padding. @@ -87,16 +88,20 @@ public: * such as padding. This is equivalent to calling update() and * then finalize(). */ - virtual void finalize(const byte_t* buffer, - const size_t len) = 0; + virtual void finalize( + const byte_t* buffer, + const size_t len + ) = 0; /** Completes the hash computation by performing final operations * such as padding. This is equivalent to calling update() and * then finalize(). */ - virtual void finalize(const byte_t* buffer, - const size_t offset, - const size_t len) = 0; + virtual void finalize( + const byte_t* buffer, + const size_t offset, + const size_t len + ) = 0; /** Returns the length of the hash. * This is the length of the array returned by getDigest(). @@ -135,4 +140,3 @@ public: #endif // VMIME_SECURITY_DIGEST_MESSAGEDIGEST_HPP_INCLUDED - diff --git a/src/vmime/security/digest/messageDigestFactory.cpp b/src/vmime/security/digest/messageDigestFactory.cpp index 2831c5a1..2e499684 100644 --- a/src/vmime/security/digest/messageDigestFactory.cpp +++ b/src/vmime/security/digest/messageDigestFactory.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,44 +33,42 @@ namespace security { namespace digest { -messageDigestFactory::messageDigestFactory() -{ +messageDigestFactory::messageDigestFactory() { + registerAlgorithm ("md5"); registerAlgorithm ("sha1"); } -messageDigestFactory::~messageDigestFactory() -{ +messageDigestFactory::~messageDigestFactory() { + } -messageDigestFactory* messageDigestFactory::getInstance() -{ +messageDigestFactory* messageDigestFactory::getInstance() { + static messageDigestFactory instance; - return (&instance); + return &instance; } -shared_ptr messageDigestFactory::create(const string& name) -{ - const MapType::const_iterator it = m_algos.find - (utility::stringUtils::toLower(name)); +shared_ptr messageDigestFactory::create(const string& name) { - if (it != m_algos.end()) + const MapType::const_iterator it = m_algos.find(utility::stringUtils::toLower(name)); + + if (it != m_algos.end()) { return (*it).second->create(); + } throw exceptions::no_digest_algorithm_available(name); } -const std::vector messageDigestFactory::getSupportedAlgorithms() const -{ +const std::vector messageDigestFactory::getSupportedAlgorithms() const { + std::vector res; - for (MapType::const_iterator it = m_algos.begin() ; - it != m_algos.end() ; ++it) - { + for (MapType::const_iterator it = m_algos.begin() ; it != m_algos.end() ; ++it) { res.push_back((*it).first); } @@ -81,4 +79,3 @@ const std::vector messageDigestFactory::getSupportedAlgorithms() const } // digest } // security } // vmime - diff --git a/src/vmime/security/digest/messageDigestFactory.hpp b/src/vmime/security/digest/messageDigestFactory.hpp index 15fd8a28..56a0cfe1 100644 --- a/src/vmime/security/digest/messageDigestFactory.hpp +++ b/src/vmime/security/digest/messageDigestFactory.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,8 +38,8 @@ namespace digest { /** Creates instances of message digest algorithms. */ -class VMIME_EXPORT messageDigestFactory -{ +class VMIME_EXPORT messageDigestFactory { + private: messageDigestFactory(); @@ -51,20 +51,15 @@ public: private: - class digestAlgorithmFactory : public object - { - public: + struct digestAlgorithmFactory : public object { virtual shared_ptr create() const = 0; }; template - class digestAlgorithmFactoryImpl : public digestAlgorithmFactory - { - public: + struct digestAlgorithmFactoryImpl : public digestAlgorithmFactory { - shared_ptr create() const - { + shared_ptr create() const { return vmime::make_shared (); } }; @@ -80,10 +75,14 @@ public: * @param name algorithm name */ template - void registerAlgorithm(const string& name) - { - m_algos.insert(MapType::value_type(utility::stringUtils::toLower(name), - vmime::make_shared >())); + void registerAlgorithm(const string& name) { + + m_algos.insert( + MapType::value_type( + utility::stringUtils::toLower(name), + vmime::make_shared >() + ) + ); } /** Create a new algorithm instance from its name. @@ -109,4 +108,3 @@ public: #endif // VMIME_SECURITY_DIGEST_MESSAGEDIGESTFACTORY_HPP_INCLUDED - diff --git a/src/vmime/security/digest/sha1/sha1MessageDigest.cpp b/src/vmime/security/digest/sha1/sha1MessageDigest.cpp index 9367008b..c098f144 100644 --- a/src/vmime/security/digest/sha1/sha1MessageDigest.cpp +++ b/src/vmime/security/digest/sha1/sha1MessageDigest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -58,20 +58,20 @@ namespace sha1 { #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); -sha1MessageDigest::sha1MessageDigest() -{ +sha1MessageDigest::sha1MessageDigest() { + init(); } -void sha1MessageDigest::reset() -{ +void sha1MessageDigest::reset() { + init(); } -void sha1MessageDigest::init() -{ +void sha1MessageDigest::init() { + m_state[0] = 0x67452301; m_state[1] = 0xefcdab89; m_state[2] = 0x98badcfe; @@ -83,48 +83,50 @@ void sha1MessageDigest::init() } -void sha1MessageDigest::update(const byte_t b) -{ +void sha1MessageDigest::update(const byte_t b) { + update(&b, 1); } -void sha1MessageDigest::update(const string& s) -{ +void sha1MessageDigest::update(const string& s) { + update(reinterpret_cast (s.data()), s.length()); } -void sha1MessageDigest::update(const byte_t* buffer, const size_t offset, const size_t len) -{ +void sha1MessageDigest::update(const byte_t* buffer, const size_t offset, const size_t len) { + update(buffer + offset, len); } -void sha1MessageDigest::update(const byte_t* buffer, const size_t len) -{ +void sha1MessageDigest::update(const byte_t* buffer, const size_t len) { + unsigned int i, j; j = (m_count[0] >> 3) & 63; - if ((m_count[0] += static_cast (len << 3)) < static_cast (len << 3)) + if ((m_count[0] += static_cast (len << 3)) < static_cast (len << 3)) { m_count[1]++; + } m_count[1] += static_cast (len >> 29); - if ((j + len) > 63) - { + if ((j + len) > 63) { + memcpy(&m_buffer[j], buffer, (i = 64 - j)); transform(m_state, m_buffer); - for ( ; i + 63 < len ; i += 64) + for ( ; i + 63 < len ; i += 64) { transform(m_state, &buffer[i]); + } j = 0; - } - else - { + + } else { + i = 0; } @@ -132,29 +134,31 @@ void sha1MessageDigest::update(const byte_t* buffer, const size_t len) } -void sha1MessageDigest::finalize() -{ +void sha1MessageDigest::finalize() { + unsigned int i, j; unsigned char finalcount[8]; - for (i = 0 ; i < 8 ; i++) - { - finalcount[i] = static_cast - ((m_count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); // Endian independent + for (i = 0 ; i < 8 ; i++) { + + finalcount[i] = static_cast ( + (m_count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255 // Endian independent + ); } update(reinterpret_cast ("\200"), 1); - while ((m_count[0] & 504) != 448) + while ((m_count[0] & 504) != 448) { update(reinterpret_cast ("\0"), 1); + } update(finalcount, 8); // Should cause a transform() - for (i = 0 ; i < 20 ; i++) - { - m_digest[i] = static_cast - ((m_state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + for (i = 0 ; i < 20 ; i++) { + + m_digest[i] = static_cast ( + (m_state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255 + ); } // Wipe variables @@ -167,22 +171,25 @@ void sha1MessageDigest::finalize() } -void sha1MessageDigest::finalize(const string& s) -{ +void sha1MessageDigest::finalize(const string& s) { + finalize(reinterpret_cast (s.data()), s.length()); } -void sha1MessageDigest::finalize(const byte_t* buffer, const size_t len) -{ +void sha1MessageDigest::finalize(const byte_t* buffer, const size_t len) { + update(buffer, len); finalize(); } -void sha1MessageDigest::finalize(const byte_t* buffer, - const size_t offset, const size_t len) -{ +void sha1MessageDigest::finalize( + const byte_t* buffer, + const size_t offset, + const size_t len +) { + finalize(buffer + offset, len); } @@ -190,13 +197,14 @@ void sha1MessageDigest::finalize(const byte_t* buffer, /** Hash a single 512-bit block. * This is the core of the algorithm. */ -void sha1MessageDigest::transform - (unsigned int state[5], const unsigned char buffer[64]) -{ +void sha1MessageDigest::transform( + unsigned int state[5], + const unsigned char buffer[64] +) { + unsigned int a, b, c, d, e; - typedef union - { + typedef union { unsigned char c[64]; unsigned int l[16]; } CHAR64LONG16; @@ -250,14 +258,14 @@ void sha1MessageDigest::transform } -size_t sha1MessageDigest::getDigestLength() const -{ +size_t sha1MessageDigest::getDigestLength() const { + return 20; } -const byte_t* sha1MessageDigest::getDigest() const -{ +const byte_t* sha1MessageDigest::getDigest() const { + return m_digest; } @@ -266,5 +274,3 @@ const byte_t* sha1MessageDigest::getDigest() const } // digest } // security } // vmime - - diff --git a/src/vmime/security/digest/sha1/sha1MessageDigest.hpp b/src/vmime/security/digest/sha1/sha1MessageDigest.hpp index 1eb09c2f..19062365 100644 --- a/src/vmime/security/digest/sha1/sha1MessageDigest.hpp +++ b/src/vmime/security/digest/sha1/sha1MessageDigest.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,8 +34,8 @@ namespace digest { namespace sha1 { -class sha1MessageDigest : public messageDigest -{ +class sha1MessageDigest : public messageDigest { + public: sha1MessageDigest(); diff --git a/src/vmime/security/sasl/SASLAuthenticator.hpp b/src/vmime/security/sasl/SASLAuthenticator.hpp index d4dc113c..a75bfa0f 100644 --- a/src/vmime/security/sasl/SASLAuthenticator.hpp +++ b/src/vmime/security/sasl/SASLAuthenticator.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -50,8 +50,8 @@ class SASLSession; * Usually, you should not inherit from this class, but instead from the * more convenient defaultSASLAuthenticator class. */ -class VMIME_EXPORT SASLAuthenticator : public authenticator -{ +class VMIME_EXPORT SASLAuthenticator : public authenticator { + public: /** This method is called to allow the client to choose the @@ -64,9 +64,10 @@ public: * @return ordered list of mechanism to use among the available * mechanisms (from the first to try to the last) */ - virtual const std::vector > getAcceptableMechanisms - (const std::vector >& available, - const shared_ptr & suggested) const = 0; + virtual const std::vector > getAcceptableMechanisms( + const std::vector >& available, + const shared_ptr & suggested + ) const = 0; /** Set the SASL session which is using this authenticator. * @@ -93,4 +94,3 @@ public: #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT #endif // VMIME_SECURITY_SASL_SASLAUTHENTICATOR_HPP_INCLUDED - diff --git a/src/vmime/security/sasl/SASLContext.cpp b/src/vmime/security/sasl/SASLContext.cpp index 09ffed05..21745414 100644 --- a/src/vmime/security/sasl/SASLContext.cpp +++ b/src/vmime/security/sasl/SASLContext.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -49,63 +49,70 @@ namespace security { namespace sasl { -SASLContext::SASLContext() -{ - if (gsasl_init(&m_gsaslContext) != GSASL_OK) +SASLContext::SASLContext() { + + if (gsasl_init(&m_gsaslContext) != GSASL_OK) { throw std::bad_alloc(); + } } -SASLContext::~SASLContext() -{ +SASLContext::~SASLContext() { + gsasl_done(m_gsaslContext); } // static -shared_ptr SASLContext::create() -{ +shared_ptr SASLContext::create() { + return shared_ptr (new SASLContext()); } -shared_ptr SASLContext::createSession - (const string& serviceName, - const shared_ptr & auth, const shared_ptr & mech) -{ +shared_ptr SASLContext::createSession( + const string& serviceName, + const shared_ptr & auth, + const shared_ptr & mech +) { + return SASLSession::create (serviceName, dynamicCast (shared_from_this()), auth, mech); } -shared_ptr SASLContext::createMechanism(const string& name) -{ - return SASLMechanismFactory::getInstance()->create - (dynamicCast (shared_from_this()), name); +shared_ptr SASLContext::createMechanism(const string& name) { + + return SASLMechanismFactory::getInstance()->create( + dynamicCast (shared_from_this()), name + ); } -shared_ptr SASLContext::suggestMechanism - (const std::vector >& mechs) -{ - if (mechs.empty()) +shared_ptr SASLContext::suggestMechanism( + const std::vector >& mechs +) { + + if (mechs.empty()) { return null; + } std::ostringstream oss; - for (unsigned int i = 0 ; i < mechs.size() ; ++i) + for (unsigned int i = 0 ; i < mechs.size() ; ++i) { oss << mechs[i]->getName() << " "; + } const string mechList = oss.str(); - const char* suggested = gsasl_client_suggest_mechanism - (m_gsaslContext, mechList.c_str()); + const char* suggested = gsasl_client_suggest_mechanism(m_gsaslContext, mechList.c_str()); - if (suggested) - { - for (unsigned int i = 0 ; i < mechs.size() ; ++i) - { - if (mechs[i]->getName() == suggested) + if (suggested) { + + for (unsigned int i = 0 ; i < mechs.size() ; ++i) { + + if (mechs[i]->getName() == suggested) { return mechs[i]; + } } } @@ -113,8 +120,8 @@ shared_ptr SASLContext::suggestMechanism } -void SASLContext::decodeB64(const string& input, byte_t** output, size_t* outputLen) -{ +void SASLContext::decodeB64(const string& input, byte_t** output, size_t* outputLen) { + string res; utility::inputStreamStringAdapter is(input); @@ -134,8 +141,8 @@ void SASLContext::decodeB64(const string& input, byte_t** output, size_t* output } -const string SASLContext::encodeB64(const byte_t* input, const size_t inputLen) -{ +const string SASLContext::encodeB64(const byte_t* input, const size_t inputLen) { + string res; utility::inputStreamByteBufferAdapter is(input, inputLen); @@ -150,8 +157,8 @@ const string SASLContext::encodeB64(const byte_t* input, const size_t inputLen) } -const string SASLContext::getErrorMessage(const string& fname, const int code) -{ +const string SASLContext::getErrorMessage(const string& fname, const int code) { + string msg = fname + "() returned "; #define ERROR(x) \ @@ -159,45 +166,45 @@ const string SASLContext::getErrorMessage(const string& fname, const int code) switch (code) { - ERROR(GSASL_NEEDS_MORE) - ERROR(GSASL_UNKNOWN_MECHANISM) - ERROR(GSASL_MECHANISM_CALLED_TOO_MANY_TIMES) - ERROR(GSASL_MALLOC_ERROR) - ERROR(GSASL_BASE64_ERROR) - ERROR(GSASL_CRYPTO_ERROR) - ERROR(GSASL_SASLPREP_ERROR) - ERROR(GSASL_MECHANISM_PARSE_ERROR) - ERROR(GSASL_AUTHENTICATION_ERROR) - ERROR(GSASL_INTEGRITY_ERROR) - ERROR(GSASL_NO_CLIENT_CODE) - ERROR(GSASL_NO_SERVER_CODE) - ERROR(GSASL_NO_CALLBACK) - ERROR(GSASL_NO_ANONYMOUS_TOKEN) - ERROR(GSASL_NO_AUTHID) - ERROR(GSASL_NO_AUTHZID) - ERROR(GSASL_NO_PASSWORD) - ERROR(GSASL_NO_PASSCODE) - ERROR(GSASL_NO_PIN) - ERROR(GSASL_NO_SERVICE) - ERROR(GSASL_NO_HOSTNAME) - ERROR(GSASL_GSSAPI_RELEASE_BUFFER_ERROR) - ERROR(GSASL_GSSAPI_IMPORT_NAME_ERROR) - ERROR(GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR) - ERROR(GSASL_GSSAPI_ACCEPT_SEC_CONTEXT_ERROR) - ERROR(GSASL_GSSAPI_UNWRAP_ERROR) - ERROR(GSASL_GSSAPI_WRAP_ERROR) - ERROR(GSASL_GSSAPI_ACQUIRE_CRED_ERROR) - ERROR(GSASL_GSSAPI_DISPLAY_NAME_ERROR) - ERROR(GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR) - ERROR(GSASL_KERBEROS_V5_INIT_ERROR) - ERROR(GSASL_KERBEROS_V5_INTERNAL_ERROR) - ERROR(GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE) - ERROR(GSASL_SECURID_SERVER_NEED_NEW_PIN) + ERROR(GSASL_NEEDS_MORE) + ERROR(GSASL_UNKNOWN_MECHANISM) + ERROR(GSASL_MECHANISM_CALLED_TOO_MANY_TIMES) + ERROR(GSASL_MALLOC_ERROR) + ERROR(GSASL_BASE64_ERROR) + ERROR(GSASL_CRYPTO_ERROR) + ERROR(GSASL_SASLPREP_ERROR) + ERROR(GSASL_MECHANISM_PARSE_ERROR) + ERROR(GSASL_AUTHENTICATION_ERROR) + ERROR(GSASL_INTEGRITY_ERROR) + ERROR(GSASL_NO_CLIENT_CODE) + ERROR(GSASL_NO_SERVER_CODE) + ERROR(GSASL_NO_CALLBACK) + ERROR(GSASL_NO_ANONYMOUS_TOKEN) + ERROR(GSASL_NO_AUTHID) + ERROR(GSASL_NO_AUTHZID) + ERROR(GSASL_NO_PASSWORD) + ERROR(GSASL_NO_PASSCODE) + ERROR(GSASL_NO_PIN) + ERROR(GSASL_NO_SERVICE) + ERROR(GSASL_NO_HOSTNAME) + ERROR(GSASL_GSSAPI_RELEASE_BUFFER_ERROR) + ERROR(GSASL_GSSAPI_IMPORT_NAME_ERROR) + ERROR(GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR) + ERROR(GSASL_GSSAPI_ACCEPT_SEC_CONTEXT_ERROR) + ERROR(GSASL_GSSAPI_UNWRAP_ERROR) + ERROR(GSASL_GSSAPI_WRAP_ERROR) + ERROR(GSASL_GSSAPI_ACQUIRE_CRED_ERROR) + ERROR(GSASL_GSSAPI_DISPLAY_NAME_ERROR) + ERROR(GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR) + ERROR(GSASL_KERBEROS_V5_INIT_ERROR) + ERROR(GSASL_KERBEROS_V5_INTERNAL_ERROR) + ERROR(GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE) + ERROR(GSASL_SECURID_SERVER_NEED_NEW_PIN) - default: + default: - msg += "unknown error"; - break; + msg += "unknown error"; + break; } #undef ERROR @@ -212,4 +219,3 @@ const string SASLContext::getErrorMessage(const string& fname, const int code) #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT - diff --git a/src/vmime/security/sasl/SASLContext.hpp b/src/vmime/security/sasl/SASLContext.hpp index 58d6a932..93d80ff9 100644 --- a/src/vmime/security/sasl/SASLContext.hpp +++ b/src/vmime/security/sasl/SASLContext.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,8 +44,8 @@ namespace sasl { /** An SASL client context. */ -class VMIME_EXPORT SASLContext : public object, public enable_shared_from_this -{ +class VMIME_EXPORT SASLContext : public object, public enable_shared_from_this { + friend class SASLSession; friend class builtinSASLMechanism; @@ -66,9 +66,11 @@ public: * @param mech SASL mechanism * @return a new SASL session */ - shared_ptr createSession - (const string& serviceName, - const shared_ptr & auth, const shared_ptr & mech); + shared_ptr createSession( + const string& serviceName, + const shared_ptr & auth, + const shared_ptr & mech + ); /** Create an instance of an SASL mechanism. * @@ -86,8 +88,9 @@ public: * @return suggested mechanism (usually the safest mechanism * supported by both the client and the server) */ - shared_ptr suggestMechanism - (const std::vector >& mechs); + shared_ptr suggestMechanism( + const std::vector >& mechs + ); /** Helper function for decoding Base64-encoded challenge. * @@ -131,4 +134,3 @@ private: #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT #endif // VMIME_SECURITY_SASL_SASLCONTEXT_HPP_INCLUDED - diff --git a/src/vmime/security/sasl/SASLMechanism.hpp b/src/vmime/security/sasl/SASLMechanism.hpp index 8e842c4f..a6e056df 100644 --- a/src/vmime/security/sasl/SASLMechanism.hpp +++ b/src/vmime/security/sasl/SASLMechanism.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,8 +44,8 @@ class SASLSession; /** An SASL mechanism. */ -class VMIME_EXPORT SASLMechanism : public object -{ +class VMIME_EXPORT SASLMechanism : public object { + public: /** Return the name of this mechanism. @@ -73,10 +73,13 @@ public: * authentication (in this case, the values in 'response' and * 'responseLen' are undetermined) */ - virtual bool step - (const shared_ptr & sess, - const byte_t* challenge, const size_t challengeLen, - byte_t** response, size_t* responseLen) = 0; + virtual bool step( + const shared_ptr & sess, + const byte_t* challenge, + const size_t challengeLen, + byte_t** response, + size_t* responseLen + ) = 0; /** Check whether authentication has completed. If false, more * calls to evaluateChallenge() are needed to complete the @@ -109,9 +112,13 @@ public: * the encoding of data (in this case, the values in 'output' and * 'outputLen' are undetermined) */ - virtual void encode(const shared_ptr & sess, - const byte_t* input, const size_t inputLen, - byte_t** output, size_t* outputLen) = 0; + virtual void encode( + const shared_ptr & sess, + const byte_t* input, + const size_t inputLen, + byte_t** output, + size_t* outputLen + ) = 0; /** Decode data according to negotiated SASL mechanism. This * might mean that data is integrity or privacy protected. @@ -126,9 +133,13 @@ public: * the encoding of data (in this case, the values in 'output' and * 'outputLen' are undetermined) */ - virtual void decode(const shared_ptr & sess, - const byte_t* input, const size_t inputLen, - byte_t** output, size_t* outputLen) = 0; + virtual void decode( + const shared_ptr & sess, + const byte_t* input, + const size_t inputLen, + byte_t** output, + size_t* outputLen + ) = 0; }; @@ -140,4 +151,3 @@ public: #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT #endif // VMIME_SECURITY_SASL_SASLMECHANISM_HPP_INCLUDED - diff --git a/src/vmime/security/sasl/SASLMechanismFactory.cpp b/src/vmime/security/sasl/SASLMechanismFactory.cpp index 5ded627a..a2fbedbc 100644 --- a/src/vmime/security/sasl/SASLMechanismFactory.cpp +++ b/src/vmime/security/sasl/SASLMechanismFactory.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -47,68 +47,73 @@ namespace security { namespace sasl { -SASLMechanismFactory::SASLMechanismFactory() -{ - if (gsasl_init(&m_gsaslContext) != GSASL_OK) +SASLMechanismFactory::SASLMechanismFactory() { + + if (gsasl_init(&m_gsaslContext) != GSASL_OK) { throw std::bad_alloc(); + } } -SASLMechanismFactory::~SASLMechanismFactory() -{ +SASLMechanismFactory::~SASLMechanismFactory() { + gsasl_done(m_gsaslContext); } // static -SASLMechanismFactory* SASLMechanismFactory::getInstance() -{ +SASLMechanismFactory* SASLMechanismFactory::getInstance() { + static SASLMechanismFactory instance; return &instance; } -shared_ptr SASLMechanismFactory::create - (const shared_ptr & ctx, const string& name_) -{ +shared_ptr SASLMechanismFactory::create( + const shared_ptr & ctx, + const string& name_ +) { + const string name(utility::stringUtils::toUpper(name_)); // Check for registered mechanisms MapType::iterator it = m_mechs.find(name); - if (it != m_mechs.end()) + if (it != m_mechs.end()) { return (*it).second->create(ctx, name); + } // Check for built-in mechanisms - if (isBuiltinMechanism(name)) + if (isBuiltinMechanism(name)) { return make_shared (ctx, name); + } throw exceptions::no_such_mechanism(name); return null; } -const std::vector SASLMechanismFactory::getSupportedMechanisms() const -{ +const std::vector SASLMechanismFactory::getSupportedMechanisms() const { + std::vector list; // Registered mechanisms for (MapType::const_iterator it = m_mechs.begin() ; - it != m_mechs.end() ; ++it) - { + it != m_mechs.end() ; ++it) { + list.push_back((*it).first); } // Built-in mechanisms char* out = 0; - if (gsasl_client_mechlist(m_gsaslContext, &out) == GSASL_OK) - { + if (gsasl_client_mechlist(m_gsaslContext, &out) == GSASL_OK) { + // 'out' contains SASL mechanism names, separated by spaces - for (char *start = out, *p = out ; ; ++p) - { - if (*p == ' ' || !*p) - { + for (char *start = out, *p = out ; ; ++p) { + + if (*p == ' ' || !*p) { + list.push_back(string(start, p)); start = p + 1; @@ -124,14 +129,14 @@ const std::vector SASLMechanismFactory::getSupportedMechanisms() const } -bool SASLMechanismFactory::isMechanismSupported(const string& name) const -{ +bool SASLMechanismFactory::isMechanismSupported(const string& name) const { + return isBuiltinMechanism(name) || m_mechs.find(name) != m_mechs.end(); } -bool SASLMechanismFactory::isBuiltinMechanism(const string& name) const -{ +bool SASLMechanismFactory::isBuiltinMechanism(const string& name) const { + return gsasl_client_support_p(m_gsaslContext, name.c_str()) != 0; } @@ -142,4 +147,3 @@ bool SASLMechanismFactory::isBuiltinMechanism(const string& name) const #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT - diff --git a/src/vmime/security/sasl/SASLMechanismFactory.hpp b/src/vmime/security/sasl/SASLMechanismFactory.hpp index d83b37a1..af76c96d 100644 --- a/src/vmime/security/sasl/SASLMechanismFactory.hpp +++ b/src/vmime/security/sasl/SASLMechanismFactory.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -49,29 +49,29 @@ class SASLContext; /** Constructs SASL mechanism objects. */ -class VMIME_EXPORT SASLMechanismFactory : public object -{ +class VMIME_EXPORT SASLMechanismFactory : public object { + private: SASLMechanismFactory(); ~SASLMechanismFactory(); - class registeredMechanism : public object - { - public: + struct registeredMechanism : public object { - virtual shared_ptr create - (const shared_ptr & ctx, const string& name) = 0; + virtual shared_ptr create( + const shared_ptr & ctx, const string& name + ) = 0; }; template - class registeredMechanismImpl : public registeredMechanism - { - public: + struct registeredMechanismImpl : public registeredMechanism { + + shared_ptr create( + const shared_ptr & ctx, + const string& name + ) { - shared_ptr create(const shared_ptr & ctx, const string& name) - { return vmime::make_shared (ctx, name); } }; @@ -89,10 +89,14 @@ public: * @param name mechanism name */ template - void registerMechanism(const string& name) - { - m_mechs.insert(MapType::value_type(name, - vmime::make_shared >())); + void registerMechanism(const string& name) { + + m_mechs.insert( + MapType::value_type( + name, + vmime::make_shared >() + ) + ); } /** Create a mechanism object given its name. @@ -149,4 +153,3 @@ private: #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT #endif // VMIME_SECURITY_SASL_SASLMECHANISMFACTORY_HPP_INCLUDED - diff --git a/src/vmime/security/sasl/SASLSession.cpp b/src/vmime/security/sasl/SASLSession.cpp index 28446fe3..7498b461 100644 --- a/src/vmime/security/sasl/SASLSession.cpp +++ b/src/vmime/security/sasl/SASLSession.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,13 +43,22 @@ namespace security { namespace sasl { -SASLSession::SASLSession(const string& serviceName, const shared_ptr & ctx, - const shared_ptr & auth, const shared_ptr & mech) - : m_serviceName(serviceName), m_context(ctx), m_auth(auth), - m_mech(mech), m_gsaslContext(0), m_gsaslSession(0) -{ - if (gsasl_init(&m_gsaslContext) != GSASL_OK) +SASLSession::SASLSession( + const string& serviceName, + const shared_ptr & ctx, + const shared_ptr & auth, + const shared_ptr & mech +) + : m_serviceName(serviceName), + m_context(ctx), + m_auth(auth), + m_mech(mech), + m_gsaslContext(0), + m_gsaslSession(0) { + + if (gsasl_init(&m_gsaslContext) != GSASL_OK) { throw std::bad_alloc(); + } gsasl_client_start(m_gsaslContext, mech->getName().c_str(), &m_gsaslSession); @@ -58,8 +67,8 @@ SASLSession::SASLSession(const string& serviceName, const shared_ptr SASLSession::create - (const string& serviceName, const shared_ptr & ctx, - const shared_ptr & auth, const shared_ptr & mech) -{ +shared_ptr SASLSession::create( + const string& serviceName, + const shared_ptr & ctx, + const shared_ptr & auth, + const shared_ptr & mech +) { + return shared_ptr (new SASLSession(serviceName, ctx, auth, mech)); } -void SASLSession::init() -{ +void SASLSession::init() { + shared_ptr saslAuth = dynamicCast (m_auth); - if (saslAuth) - { + if (saslAuth) { saslAuth->setSASLMechanism(m_mech); saslAuth->setSASLSession(dynamicCast (shared_from_this())); } } -shared_ptr SASLSession::getAuthenticator() -{ +shared_ptr SASLSession::getAuthenticator() { + return m_auth; } -shared_ptr SASLSession::getMechanism() -{ +shared_ptr SASLSession::getMechanism() { + return m_mech; } -shared_ptr SASLSession::getContext() -{ +shared_ptr SASLSession::getContext() { + return m_context; } -bool SASLSession::evaluateChallenge - (const byte_t* challenge, const size_t challengeLen, - byte_t** response, size_t* responseLen) -{ - return m_mech->step(dynamicCast (shared_from_this()), - challenge, challengeLen, response, responseLen); +bool SASLSession::evaluateChallenge( + const byte_t* challenge, + const size_t challengeLen, + byte_t** response, + size_t* responseLen +) { + + return m_mech->step( + dynamicCast (shared_from_this()), + challenge, challengeLen, response, responseLen + ); } -shared_ptr SASLSession::getSecuredSocket(const shared_ptr & sok) -{ +shared_ptr SASLSession::getSecuredSocket(const shared_ptr & sok) { + return make_shared (dynamicCast (shared_from_this()), sok); } -const string SASLSession::getServiceName() const -{ +const string SASLSession::getServiceName() const { + return m_serviceName; } // static -int SASLSession::gsaslCallback - (Gsasl* ctx, Gsasl_session* sctx, Gsasl_property prop) -{ +int SASLSession::gsaslCallback( + Gsasl* ctx, + Gsasl_session* sctx, + Gsasl_property prop +) { + SASLSession* sess = reinterpret_cast (gsasl_callback_hook_get(ctx)); - if (!sess) return GSASL_AUTHENTICATION_ERROR; + + if (!sess) { + return GSASL_AUTHENTICATION_ERROR; + } shared_ptr auth = sess->getAuthenticator(); - try - { + try { + string res; - switch (prop) - { - case GSASL_AUTHID: + switch (prop) { - res = auth->getUsername(); - break; + case GSASL_AUTHID: - case GSASL_PASSWORD: + res = auth->getUsername(); + break; - res = auth->getPassword(); - break; + case GSASL_PASSWORD: - case GSASL_ANONYMOUS_TOKEN: + res = auth->getPassword(); + break; - res = auth->getAnonymousToken(); - break; + case GSASL_ANONYMOUS_TOKEN: - case GSASL_HOSTNAME: + res = auth->getAnonymousToken(); + break; - res = auth->getHostname(); - break; + case GSASL_HOSTNAME: - case GSASL_SERVICE: + res = auth->getHostname(); + break; - res = auth->getServiceName(); - break; + case GSASL_SERVICE: - case GSASL_AUTHZID: - case GSASL_GSSAPI_DISPLAY_NAME: - case GSASL_PASSCODE: - case GSASL_SUGGESTED_PIN: - case GSASL_PIN: - case GSASL_REALM: + res = auth->getServiceName(); + break; - default: + case GSASL_AUTHZID: + case GSASL_GSSAPI_DISPLAY_NAME: + case GSASL_PASSCODE: + case GSASL_SUGGESTED_PIN: + case GSASL_PIN: + case GSASL_REALM: - return GSASL_NO_CALLBACK; + default: + + return GSASL_NO_CALLBACK; } gsasl_property_set(sctx, prop, res.c_str()); return GSASL_OK; - } - //catch (exceptions::no_auth_information&) - catch (...) - { + + } catch (...) { + return GSASL_NO_CALLBACK; } } @@ -198,4 +219,3 @@ int SASLSession::gsaslCallback #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT - diff --git a/src/vmime/security/sasl/SASLSession.hpp b/src/vmime/security/sasl/SASLSession.hpp index 65387bd3..7fc7225c 100644 --- a/src/vmime/security/sasl/SASLSession.hpp +++ b/src/vmime/security/sasl/SASLSession.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -49,8 +49,8 @@ class SASLContext; /** An SASL client session. */ -class VMIME_EXPORT SASLSession : public object, public enable_shared_from_this -{ +class VMIME_EXPORT SASLSession : public object, public enable_shared_from_this { + friend class builtinSASLMechanism; friend class SASLSocket; @@ -65,9 +65,12 @@ public: * @param auth authenticator to use for this session * @param mech SASL mechanism */ - static shared_ptr create - (const string& serviceName, const shared_ptr & ctx, - const shared_ptr & auth, const shared_ptr & mech); + static shared_ptr create( + const string& serviceName, + const shared_ptr & ctx, + const shared_ptr & auth, + const shared_ptr & mech + ); /** Initialize this SASL session. This must be called before * calling any other method on this object (except accessors). @@ -112,9 +115,12 @@ public: * authentication (in this case, the values in 'response' and * 'responseLen' are undetermined) */ - bool evaluateChallenge - (const byte_t* challenge, const size_t challengeLen, - byte_t** response, size_t* responseLen); + bool evaluateChallenge( + const byte_t* challenge, + const size_t challengeLen, + byte_t** response, + size_t* responseLen + ); /** Return a socket in which transmitted data is integrity * and/or privacy protected, depending on the QOP (Quality of @@ -135,9 +141,12 @@ public: private: - SASLSession - (const string& serviceName, const shared_ptr & ctx, - const shared_ptr & auth, const shared_ptr & mech); + SASLSession( + const string& serviceName, + const shared_ptr & ctx, + const shared_ptr & auth, + const shared_ptr & mech + ); const string m_serviceName; @@ -169,4 +178,3 @@ private: #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT #endif // VMIME_SECURITY_SASL_SASLSESSION_HPP_INCLUDED - diff --git a/src/vmime/security/sasl/SASLSocket.cpp b/src/vmime/security/sasl/SASLSocket.cpp index 4312ab35..0dbafd80 100644 --- a/src/vmime/security/sasl/SASLSocket.cpp +++ b/src/vmime/security/sasl/SASLSocket.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,110 +46,119 @@ namespace sasl { -SASLSocket::SASLSocket(const shared_ptr & sess, const shared_ptr & wrapped) - : m_session(sess), m_wrapped(wrapped), - m_pendingBuffer(0), m_pendingPos(0), m_pendingLen(0) -{ +SASLSocket::SASLSocket( + const shared_ptr & sess, + const shared_ptr & wrapped +) + : m_session(sess), + m_wrapped(wrapped), + m_pendingBuffer(0), + m_pendingPos(0), + m_pendingLen(0) { + } -SASLSocket::~SASLSocket() -{ - if (m_pendingBuffer) +SASLSocket::~SASLSocket() { + + if (m_pendingBuffer) { delete [] m_pendingBuffer; + } } -void SASLSocket::connect(const string& address, const port_t port) -{ +void SASLSocket::connect(const string& address, const port_t port) { + m_wrapped->connect(address, port); } -void SASLSocket::disconnect() -{ +void SASLSocket::disconnect() { + m_wrapped->disconnect(); } -bool SASLSocket::isConnected() const -{ +bool SASLSocket::isConnected() const { + return m_wrapped->isConnected(); } -size_t SASLSocket::getBlockSize() const -{ +size_t SASLSocket::getBlockSize() const { + return m_wrapped->getBlockSize(); } -const string SASLSocket::getPeerName() const -{ +const string SASLSocket::getPeerName() const { + return m_wrapped->getPeerName(); } -const string SASLSocket::getPeerAddress() const -{ +const string SASLSocket::getPeerAddress() const { + return m_wrapped->getPeerAddress(); } -shared_ptr SASLSocket::getTimeoutHandler() -{ +shared_ptr SASLSocket::getTimeoutHandler() { + return m_wrapped->getTimeoutHandler(); } -void SASLSocket::setTracer(const shared_ptr & tracer) -{ +void SASLSocket::setTracer(const shared_ptr & tracer) { + m_wrapped->setTracer(tracer); } -shared_ptr SASLSocket::getTracer() -{ +shared_ptr SASLSocket::getTracer() { + return m_wrapped->getTracer(); } -bool SASLSocket::waitForRead(const int msecs) -{ +bool SASLSocket::waitForRead(const int msecs) { + return m_wrapped->waitForRead(msecs); } -bool SASLSocket::waitForWrite(const int msecs) -{ +bool SASLSocket::waitForWrite(const int msecs) { + return m_wrapped->waitForWrite(msecs); } -void SASLSocket::receive(string& buffer) -{ +void SASLSocket::receive(string& buffer) { + const size_t n = receiveRaw(m_recvBuffer, sizeof(m_recvBuffer)); buffer = utility::stringUtils::makeStringFromBytes(m_recvBuffer, n); } -size_t SASLSocket::receiveRaw(byte_t* buffer, const size_t count) -{ - if (m_pendingLen != 0) - { +size_t SASLSocket::receiveRaw(byte_t* buffer, const size_t count) { + + if (m_pendingLen != 0) { + const size_t copyLen = (count >= m_pendingLen ? m_pendingLen : count); - std::copy(m_pendingBuffer + m_pendingPos, - m_pendingBuffer + m_pendingPos + copyLen, - buffer); + std::copy( + m_pendingBuffer + m_pendingPos, + m_pendingBuffer + m_pendingPos + copyLen, + buffer + ); m_pendingLen -= copyLen; m_pendingPos += copyLen; - if (m_pendingLen == 0) - { + if (m_pendingLen == 0) { + delete [] m_pendingBuffer; m_pendingBuffer = 0; @@ -165,13 +174,12 @@ size_t SASLSocket::receiveRaw(byte_t* buffer, const size_t count) byte_t* output = 0; size_t outputLen = 0; - m_session->getMechanism()->decode - (m_session, buffer, n, &output, &outputLen); + m_session->getMechanism()->decode(m_session, buffer, n, &output, &outputLen); // If we can not copy all decoded data into the output buffer, put // remaining data into a pending buffer for next calls to receive() - if (outputLen > count) - { + if (outputLen > count) { + std::copy(output, output + count, buffer); m_pendingBuffer = output; @@ -179,9 +187,9 @@ size_t SASLSocket::receiveRaw(byte_t* buffer, const size_t count) m_pendingPos = count; return count; - } - else - { + + } else { + std::copy(output, output + outputLen, buffer); delete [] output; @@ -191,32 +199,33 @@ size_t SASLSocket::receiveRaw(byte_t* buffer, const size_t count) } -void SASLSocket::send(const string& buffer) -{ +void SASLSocket::send(const string& buffer) { + sendRaw(reinterpret_cast (buffer.data()), buffer.length()); } -void SASLSocket::send(const char* str) -{ +void SASLSocket::send(const char* str) { + sendRaw(reinterpret_cast (str), strlen(str)); } -void SASLSocket::sendRaw(const byte_t* buffer, const size_t count) -{ +void SASLSocket::sendRaw(const byte_t* buffer, const size_t count) { + byte_t* output = 0; size_t outputLen = 0; - m_session->getMechanism()->encode - (m_session, buffer, count, &output, &outputLen); + m_session->getMechanism()->encode( + m_session, buffer, count, &output, &outputLen + ); + + try { - try - { m_wrapped->sendRaw(output, outputLen); - } - catch (...) - { + + } catch (...) { + delete [] output; throw; } @@ -225,22 +234,21 @@ void SASLSocket::sendRaw(const byte_t* buffer, const size_t count) } -size_t SASLSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) -{ +size_t SASLSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) { + byte_t* output = 0; size_t outputLen = 0; - m_session->getMechanism()->encode - (m_session, buffer, count, &output, &outputLen); + m_session->getMechanism()->encode(m_session, buffer, count, &output, &outputLen); size_t bytesSent = 0; - try - { + try { + bytesSent = m_wrapped->sendRawNonBlocking(output, outputLen); - } - catch (...) - { + + } catch (...) { + delete [] output; throw; } @@ -251,8 +259,8 @@ size_t SASLSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) } -unsigned int SASLSocket::getStatus() const -{ +unsigned int SASLSocket::getStatus() const { + return m_wrapped->getStatus(); } @@ -263,4 +271,3 @@ unsigned int SASLSocket::getStatus() const #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT - diff --git a/src/vmime/security/sasl/SASLSocket.hpp b/src/vmime/security/sasl/SASLSocket.hpp index 7a732394..ac0e89e9 100644 --- a/src/vmime/security/sasl/SASLSocket.hpp +++ b/src/vmime/security/sasl/SASLSocket.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,11 +46,15 @@ class SASLSession; /** A socket which provides data integrity and/or privacy protection. */ -class VMIME_EXPORT SASLSocket : public net::socket -{ +class VMIME_EXPORT SASLSocket : public net::socket { + public: - SASLSocket(const shared_ptr & sess, const shared_ptr & wrapped); + SASLSocket( + const shared_ptr & sess, + const shared_ptr & wrapped + ); + ~SASLSocket(); void connect(const string& address, const port_t port); @@ -102,4 +106,3 @@ private: #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT #endif // VMIME_SECURITY_SASL_SASLSOCKET_HPP_INCLUDED - diff --git a/src/vmime/security/sasl/XOAuth2SASLAuthenticator.cpp b/src/vmime/security/sasl/XOAuth2SASLAuthenticator.cpp index fe36bbab..ecc715a1 100644 --- a/src/vmime/security/sasl/XOAuth2SASLAuthenticator.cpp +++ b/src/vmime/security/sasl/XOAuth2SASLAuthenticator.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,48 +40,47 @@ namespace sasl { XOAuth2SASLAuthenticator::XOAuth2SASLAuthenticator(const Mode mode) - : m_mode(mode) -{ + : m_mode(mode) { + } -XOAuth2SASLAuthenticator::~XOAuth2SASLAuthenticator() -{ +XOAuth2SASLAuthenticator::~XOAuth2SASLAuthenticator() { + } const std::vector > - XOAuth2SASLAuthenticator::getAcceptableMechanisms - (const std::vector >& available, - const shared_ptr & suggested) const -{ - if (m_mode == MODE_EXCLUSIVE) - { + XOAuth2SASLAuthenticator::getAcceptableMechanisms( + const std::vector >& available, + const shared_ptr & suggested + ) const { + + if (m_mode == MODE_EXCLUSIVE) { + std::vector > mechs; - for (size_t i = available.size() ; i != 0 ; --i) - { + for (size_t i = available.size() ; i != 0 ; --i) { + shared_ptr mech = available[i - 1]; - if ("XOAUTH2" == mech->getName()) - { + if ("XOAUTH2" == mech->getName()) { // Only allow XOAuth2 mechs.push_back(mech); } } return mechs; - } - else - { + + } else { + shared_ptr newSuggested(suggested); - for (size_t i = available.size() ; i != 0 ; --i) - { + for (size_t i = available.size() ; i != 0 ; --i) { + shared_ptr mech = available[i - 1]; - if ("XOAUTH2" == mech->getName()) - { + if ("XOAUTH2" == mech->getName()) { // Suggest using XOAuth2 newSuggested = mech; } diff --git a/src/vmime/security/sasl/XOAuth2SASLAuthenticator.hpp b/src/vmime/security/sasl/XOAuth2SASLAuthenticator.hpp index 84fa8917..e4d3d837 100644 --- a/src/vmime/security/sasl/XOAuth2SASLAuthenticator.hpp +++ b/src/vmime/security/sasl/XOAuth2SASLAuthenticator.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,12 +43,11 @@ namespace sasl { * for XOAuth2 authentication mechanisms (username and access token). * This authenticator force using the XOAUTH2 mechanism. */ -class VMIME_EXPORT XOAuth2SASLAuthenticator : public defaultSASLAuthenticator -{ +class VMIME_EXPORT XOAuth2SASLAuthenticator : public defaultSASLAuthenticator { + public: - enum Mode - { + enum Mode { MODE_SUGGEST, /**< Try XOAUTH2 before other mechanisms. */ MODE_EXCLUSIVE /**< Use XOAUTH2 and nothing else. */ }; @@ -57,9 +56,10 @@ public: XOAuth2SASLAuthenticator(const Mode mode); ~XOAuth2SASLAuthenticator(); - const std::vector > getAcceptableMechanisms - (const std::vector >& available, - const shared_ptr & suggested) const; + const std::vector > getAcceptableMechanisms( + const std::vector >& available, + const shared_ptr & suggested + ) const; private: @@ -75,4 +75,3 @@ private: #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT #endif // VMIME_SECURITY_SASL_XOAUTH2SASLAUTHENTICATOR_HPP_INCLUDED - diff --git a/src/vmime/security/sasl/XOAuth2SASLMechanism.cpp b/src/vmime/security/sasl/XOAuth2SASLMechanism.cpp index c699fa83..e5ecd4bd 100644 --- a/src/vmime/security/sasl/XOAuth2SASLMechanism.cpp +++ b/src/vmime/security/sasl/XOAuth2SASLMechanism.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,28 +42,35 @@ namespace security { namespace sasl { -XOAuth2SASLMechanism::XOAuth2SASLMechanism(const shared_ptr & ctx, const string& /* name */) - : m_context(ctx), m_complete(false) -{ +XOAuth2SASLMechanism::XOAuth2SASLMechanism( + const shared_ptr & ctx, + const string& /* name */ +) + : m_context(ctx), + m_complete(false) { + } -XOAuth2SASLMechanism::~XOAuth2SASLMechanism() -{ +XOAuth2SASLMechanism::~XOAuth2SASLMechanism() { + } -const string XOAuth2SASLMechanism::getName() const -{ +const string XOAuth2SASLMechanism::getName() const { + return "XOAUTH2"; } -bool XOAuth2SASLMechanism::step - (const shared_ptr & sess, - const byte_t* /* challenge */, const size_t /* challengeLen */, - byte_t** response, size_t* responseLen) -{ +bool XOAuth2SASLMechanism::step( + const shared_ptr & sess, + const byte_t* /* challenge */, + const size_t /* challengeLen */, + byte_t** response, + size_t* responseLen +) { + // Build initial response // // The SASL XOAUTH2 initial client response has the following format: @@ -94,23 +101,26 @@ bool XOAuth2SASLMechanism::step } -bool XOAuth2SASLMechanism::isComplete() const -{ +bool XOAuth2SASLMechanism::isComplete() const { + return m_complete; } -bool XOAuth2SASLMechanism::hasInitialResponse() const -{ +bool XOAuth2SASLMechanism::hasInitialResponse() const { + return true; } -void XOAuth2SASLMechanism::encode - (const shared_ptr & /* sess */, - const byte_t* input, const size_t inputLen, - byte_t** output, size_t* outputLen) -{ +void XOAuth2SASLMechanism::encode( + const shared_ptr & /* sess */, + const byte_t* input, + const size_t inputLen, + byte_t** output, + size_t* outputLen +) { + // No encoding performed, just copy input bytes byte_t* res = new byte_t[inputLen]; std::copy(input, input + inputLen, res); @@ -120,11 +130,14 @@ void XOAuth2SASLMechanism::encode } -void XOAuth2SASLMechanism::decode - (const shared_ptr & /* sess */, - const byte_t* input, const size_t inputLen, - byte_t** output, size_t* outputLen) -{ +void XOAuth2SASLMechanism::decode( + const shared_ptr & /* sess */, + const byte_t* input, + const size_t inputLen, + byte_t** output, + size_t* outputLen +) { + // No decoding performed, just copy input bytes byte_t* res = new byte_t[inputLen]; std::copy(input, input + inputLen, res); diff --git a/src/vmime/security/sasl/XOAuth2SASLMechanism.hpp b/src/vmime/security/sasl/XOAuth2SASLMechanism.hpp index 5a49267e..eacbb0ae 100644 --- a/src/vmime/security/sasl/XOAuth2SASLMechanism.hpp +++ b/src/vmime/security/sasl/XOAuth2SASLMechanism.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,8 +44,8 @@ class SASLContext; /** SASL XOAUTH2 mechanism, used by GMail. */ -class VMIME_EXPORT XOAuth2SASLMechanism : public SASLMechanism -{ +class VMIME_EXPORT XOAuth2SASLMechanism : public SASLMechanism { + public: XOAuth2SASLMechanism(const shared_ptr & ctx, const string& name); @@ -54,21 +54,33 @@ public: const string getName() const; - bool step(const shared_ptr & sess, - const byte_t* challenge, const size_t challengeLen, - byte_t** response, size_t* responseLen); + bool step( + const shared_ptr & sess, + const byte_t* challenge, + const size_t challengeLen, + byte_t** response, + size_t* responseLen + ); bool isComplete() const; bool hasInitialResponse() const; - void encode(const shared_ptr & sess, - const byte_t* input, const size_t inputLen, - byte_t** output, size_t* outputLen); + void encode( + const shared_ptr & sess, + const byte_t* input, + const size_t inputLen, + byte_t** output, + size_t* outputLen + ); - void decode(const shared_ptr & sess, - const byte_t* input, const size_t inputLen, - byte_t** output, size_t* outputLen); + void decode( + const shared_ptr & sess, + const byte_t* input, + const size_t inputLen, + byte_t** output, + size_t* outputLen + ); private: @@ -88,4 +100,3 @@ private: #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT #endif // VMIME_SECURITY_SASL_XOAUTH2SASLMECHANISM_HPP_INCLUDED - diff --git a/src/vmime/security/sasl/builtinSASLMechanism.cpp b/src/vmime/security/sasl/builtinSASLMechanism.cpp index cbbb98c3..846e2ccf 100644 --- a/src/vmime/security/sasl/builtinSASLMechanism.cpp +++ b/src/vmime/security/sasl/builtinSASLMechanism.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -45,113 +45,130 @@ namespace security { namespace sasl { -builtinSASLMechanism::builtinSASLMechanism(const shared_ptr & ctx, const string& name) - : m_context(ctx), m_name(name), m_complete(false) -{ +builtinSASLMechanism::builtinSASLMechanism( + const shared_ptr & ctx, + const string& name +) + : m_context(ctx), + m_name(name), + m_complete(false) { + } -builtinSASLMechanism::~builtinSASLMechanism() -{ +builtinSASLMechanism::~builtinSASLMechanism() { + } -const string builtinSASLMechanism::getName() const -{ +const string builtinSASLMechanism::getName() const { + return m_name; } -bool builtinSASLMechanism::step - (const shared_ptr & sess, const byte_t* challenge, const size_t challengeLen, - byte_t** response, size_t* responseLen) -{ +bool builtinSASLMechanism::step( + const shared_ptr & sess, + const byte_t* challenge, + const size_t challengeLen, + byte_t** response, + size_t* responseLen +) { + char* output = 0; size_t outputLen = 0; - const int result = gsasl_step(sess->m_gsaslSession, + const int result = gsasl_step( + sess->m_gsaslSession, reinterpret_cast (challenge), challengeLen, - &output, &outputLen); + &output, &outputLen + ); + + if (result == GSASL_OK || result == GSASL_NEEDS_MORE) { - if (result == GSASL_OK || result == GSASL_NEEDS_MORE) - { byte_t* res = new byte_t[outputLen]; - for (size_t i = 0 ; i < outputLen ; ++i) + for (size_t i = 0 ; i < outputLen ; ++i) { res[i] = output[i]; + } *response = res; *responseLen = outputLen; gsasl_free(output); - } - else - { + + } else { + *response = 0; *responseLen = 0; } - if (result == GSASL_OK) - { + if (result == GSASL_OK) { + // Authentication process completed m_complete = true; return true; - } - else if (result == GSASL_NEEDS_MORE) - { + + } else if (result == GSASL_NEEDS_MORE) { + // Continue authentication process return false; - } - else if (result == GSASL_MALLOC_ERROR) - { + + } else if (result == GSASL_MALLOC_ERROR) { + throw std::bad_alloc(); - } - else - { - throw exceptions::sasl_exception("Error when processing challenge: " - + SASLContext::getErrorMessage("gsasl_step", result)); + + } else { + + throw exceptions::sasl_exception( + "Error when processing challenge: " + + SASLContext::getErrorMessage("gsasl_step", result) + ); } } -bool builtinSASLMechanism::isComplete() const -{ +bool builtinSASLMechanism::isComplete() const { + return m_complete; } -bool builtinSASLMechanism::hasInitialResponse() const -{ +bool builtinSASLMechanism::hasInitialResponse() const { + // It seems GNU SASL does not support initial response return false; } -void builtinSASLMechanism::encode - (const shared_ptr & sess, const byte_t* input, const size_t inputLen, - byte_t** output, size_t* outputLen) -{ +void builtinSASLMechanism::encode( + const shared_ptr & sess, + const byte_t* input, + const size_t inputLen, + byte_t** output, + size_t* outputLen +) { + char* coutput = 0; size_t coutputLen = 0; - if (gsasl_encode(sess->m_gsaslSession, - reinterpret_cast (input), inputLen, - &coutput, &coutputLen) != GSASL_OK) - { + if (gsasl_encode(sess->m_gsaslSession, reinterpret_cast (input), inputLen, + &coutput, &coutputLen) != GSASL_OK) { + throw exceptions::sasl_exception("Encoding error."); } - try - { + try { + byte_t* res = new byte_t[coutputLen]; std::copy(coutput, coutput + coutputLen, res); *output = res; *outputLen = static_cast (coutputLen); - } - catch (...) - { + + } catch (...) { + gsasl_free(coutput); throw; } @@ -160,19 +177,22 @@ void builtinSASLMechanism::encode } -void builtinSASLMechanism::decode - (const shared_ptr & sess, const byte_t* input, const size_t inputLen, - byte_t** output, size_t* outputLen) -{ +void builtinSASLMechanism::decode( + const shared_ptr & sess, + const byte_t* input, + const size_t inputLen, + byte_t** output, + size_t* outputLen +) { + char* coutput = 0; size_t coutputLen = 0; - try - { - if (gsasl_decode(sess->m_gsaslSession, - reinterpret_cast (input), inputLen, - &coutput, &coutputLen) != GSASL_OK) - { + try { + + if (gsasl_decode(sess->m_gsaslSession, reinterpret_cast (input), inputLen, + &coutput, &coutputLen) != GSASL_OK) { + throw exceptions::sasl_exception("Decoding error."); } @@ -182,9 +202,9 @@ void builtinSASLMechanism::decode *output = res; *outputLen = static_cast (coutputLen); - } - catch (...) - { + + } catch (...) { + gsasl_free(coutput); throw; } @@ -199,4 +219,3 @@ void builtinSASLMechanism::decode #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT - diff --git a/src/vmime/security/sasl/builtinSASLMechanism.hpp b/src/vmime/security/sasl/builtinSASLMechanism.hpp index a82c74af..2e412d6c 100644 --- a/src/vmime/security/sasl/builtinSASLMechanism.hpp +++ b/src/vmime/security/sasl/builtinSASLMechanism.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -45,8 +45,8 @@ class SASLContext; /** A built-in authentication mechanism that relies on * the GNU SASL library. */ -class VMIME_EXPORT builtinSASLMechanism : public SASLMechanism -{ +class VMIME_EXPORT builtinSASLMechanism : public SASLMechanism { + public: builtinSASLMechanism(const shared_ptr & ctx, const string& name); @@ -55,21 +55,32 @@ public: const string getName() const; - bool step(const shared_ptr & sess, - const byte_t* challenge, const size_t challengeLen, - byte_t** response, size_t* responseLen); + bool step( + const shared_ptr & sess, + const byte_t* challenge, + const size_t challengeLen, + byte_t** response, size_t* responseLen + ); bool isComplete() const; bool hasInitialResponse() const; - void encode(const shared_ptr & sess, - const byte_t* input, const size_t inputLen, - byte_t** output, size_t* outputLen); + void encode( + const shared_ptr & sess, + const byte_t* input, + const size_t inputLen, + byte_t** output, + size_t* outputLen + ); - void decode(const shared_ptr & sess, - const byte_t* input, const size_t inputLen, - byte_t** output, size_t* outputLen); + void decode( + const shared_ptr & sess, + const byte_t* input, + const size_t inputLen, + byte_t** output, + size_t* outputLen + ); private: @@ -92,4 +103,3 @@ private: #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT #endif // VMIME_SECURITY_SASL_BUILTINSASLMECHANISM_HPP_INCLUDED - diff --git a/src/vmime/security/sasl/defaultSASLAuthenticator.cpp b/src/vmime/security/sasl/defaultSASLAuthenticator.cpp index 2dbc0399..ebd7e682 100644 --- a/src/vmime/security/sasl/defaultSASLAuthenticator.cpp +++ b/src/vmime/security/sasl/defaultSASLAuthenticator.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,111 +41,112 @@ namespace security { namespace sasl { -defaultSASLAuthenticator::defaultSASLAuthenticator() -{ +defaultSASLAuthenticator::defaultSASLAuthenticator() { + } -defaultSASLAuthenticator::~defaultSASLAuthenticator() -{ +defaultSASLAuthenticator::~defaultSASLAuthenticator() { + } -const std::vector > - defaultSASLAuthenticator::getAcceptableMechanisms - (const std::vector >& available, - const shared_ptr & suggested) const -{ - if (suggested) - { +const std::vector > defaultSASLAuthenticator::getAcceptableMechanisms( + const std::vector >& available, + const shared_ptr & suggested +) const { + + if (suggested) { + std::vector > res; res.push_back(suggested); - for (unsigned int i = 0 ; i < available.size() ; ++i) - { - if (available[i]->getName() != suggested->getName()) + for (unsigned int i = 0 ; i < available.size() ; ++i) { + + if (available[i]->getName() != suggested->getName()) { res.push_back(available[i]); + } } return res; - } - else - { + + } else { + return available; } } -const string defaultSASLAuthenticator::getUsername() const -{ +const string defaultSASLAuthenticator::getUsername() const { + return m_default.getUsername(); } -const string defaultSASLAuthenticator::getPassword() const -{ +const string defaultSASLAuthenticator::getPassword() const { + return m_default.getPassword(); } -const string defaultSASLAuthenticator::getAccessToken() const -{ +const string defaultSASLAuthenticator::getAccessToken() const { + return m_default.getAccessToken(); } -const string defaultSASLAuthenticator::getHostname() const -{ +const string defaultSASLAuthenticator::getHostname() const { + return m_default.getHostname(); } -const string defaultSASLAuthenticator::getAnonymousToken() const -{ +const string defaultSASLAuthenticator::getAnonymousToken() const { + return m_default.getAnonymousToken(); } -const string defaultSASLAuthenticator::getServiceName() const -{ +const string defaultSASLAuthenticator::getServiceName() const { + return m_saslSession.lock()->getServiceName(); } -void defaultSASLAuthenticator::setService(const shared_ptr & serv) -{ +void defaultSASLAuthenticator::setService(const shared_ptr & serv) { + m_service = serv; m_default.setService(serv); } -weak_ptr defaultSASLAuthenticator::getService() const -{ +weak_ptr defaultSASLAuthenticator::getService() const { + return m_service; } -void defaultSASLAuthenticator::setSASLSession(const shared_ptr & sess) -{ +void defaultSASLAuthenticator::setSASLSession(const shared_ptr & sess) { + m_saslSession = sess; } -shared_ptr defaultSASLAuthenticator::getSASLSession() const -{ +shared_ptr defaultSASLAuthenticator::getSASLSession() const { + return m_saslSession.lock(); } -void defaultSASLAuthenticator::setSASLMechanism(const shared_ptr & mech) -{ +void defaultSASLAuthenticator::setSASLMechanism(const shared_ptr & mech) { + m_saslMech = mech; } -shared_ptr defaultSASLAuthenticator::getSASLMechanism() const -{ +shared_ptr defaultSASLAuthenticator::getSASLMechanism() const { + return m_saslMech; } @@ -156,4 +157,3 @@ shared_ptr defaultSASLAuthenticator::getSASLMechanism() const #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT - diff --git a/src/vmime/security/sasl/defaultSASLAuthenticator.hpp b/src/vmime/security/sasl/defaultSASLAuthenticator.hpp index f73849be..368e9eff 100644 --- a/src/vmime/security/sasl/defaultSASLAuthenticator.hpp +++ b/src/vmime/security/sasl/defaultSASLAuthenticator.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,16 +43,17 @@ namespace sasl { /** An authenticator that is capable of providing information * for simple authentication mechanisms (username and password). */ -class VMIME_EXPORT defaultSASLAuthenticator : public SASLAuthenticator -{ +class VMIME_EXPORT defaultSASLAuthenticator : public SASLAuthenticator { + public: defaultSASLAuthenticator(); ~defaultSASLAuthenticator(); - const std::vector > getAcceptableMechanisms - (const std::vector >& available, - const shared_ptr & suggested) const; + const std::vector > getAcceptableMechanisms( + const std::vector >& available, + const shared_ptr & suggested + ) const; const string getUsername() const; const string getPassword() const; @@ -88,4 +89,3 @@ private: #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT #endif // VMIME_SECURITY_SASL_DEFAULTSASLAUTHENTICATOR_HPP_INCLUDED - diff --git a/src/vmime/streamContentHandler.cpp b/src/vmime/streamContentHandler.cpp index 230a802a..e35bcd7c 100644 --- a/src/vmime/streamContentHandler.cpp +++ b/src/vmime/streamContentHandler.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,77 +29,91 @@ #include "vmime/utility/streamUtils.hpp" -namespace vmime -{ +namespace vmime { streamContentHandler::streamContentHandler() - : m_encoding(NO_ENCODING), m_stream(null), m_length(0) -{ + : m_encoding(NO_ENCODING), + m_stream(null), + m_length(0) { + } -streamContentHandler::streamContentHandler(const shared_ptr & is, - const size_t length, const vmime::encoding& enc) -{ +streamContentHandler::streamContentHandler( + const shared_ptr & is, + const size_t length, + const vmime::encoding& enc +) { + setData(is, length, enc); } -streamContentHandler::~streamContentHandler() -{ +streamContentHandler::~streamContentHandler() { + } streamContentHandler::streamContentHandler(const streamContentHandler& cts) - : contentHandler(), m_contentType(cts.m_contentType), m_encoding(cts.m_encoding), - m_stream(cts.m_stream), m_length(cts.m_length) -{ + : contentHandler(), + m_contentType(cts.m_contentType), + m_encoding(cts.m_encoding), + m_stream(cts.m_stream), + m_length(cts.m_length) { + } -shared_ptr streamContentHandler::clone() const -{ +shared_ptr streamContentHandler::clone() const { + return make_shared (*this); } -streamContentHandler& streamContentHandler::operator=(const streamContentHandler& cts) -{ +streamContentHandler& streamContentHandler::operator=(const streamContentHandler& cts) { + m_contentType = cts.m_contentType; m_encoding = cts.m_encoding; m_stream = cts.m_stream; m_length = cts.m_length; - return (*this); + return *this; } -void streamContentHandler::setData(const shared_ptr & is, - const size_t length, const vmime::encoding& enc) -{ +void streamContentHandler::setData( + const shared_ptr & is, + const size_t length, + const vmime::encoding& enc +) { + m_encoding = enc; m_length = length; m_stream = is; } -void streamContentHandler::generate(utility::outputStream& os, const vmime::encoding& enc, - const size_t maxLineLength) const -{ - if (!m_stream) +void streamContentHandler::generate( + utility::outputStream& os, + const vmime::encoding& enc, + const size_t maxLineLength +) const { + + if (!m_stream) { return; + } // Managed data is already encoded - if (isEncoded()) - { + if (isEncoded()) { + // The data is already encoded but the encoding specified for // the generation is different from the current one. We need // to re-encode data: decode from input buffer to temporary // buffer, and then re-encode to output stream... - if (m_encoding != enc) - { + if (m_encoding != enc) { + shared_ptr theDecoder = m_encoding.getEncoder(); shared_ptr theEncoder = enc.getEncoder(); @@ -117,18 +131,18 @@ void streamContentHandler::generate(utility::outputStream& os, const vmime::enco utility::inputStreamStringAdapter tempIn(str); theEncoder->encode(tempIn, os); - } + // No encoding to perform - else - { + } else { + m_stream->reset(); // may not work... utility::bufferedStreamCopy(*m_stream, os); } - } + // Need to encode data before - else - { + } else { + shared_ptr theEncoder = enc.getEncoder(); theEncoder->getProperties()["maxlinelength"] = maxLineLength; theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT); @@ -140,25 +154,29 @@ void streamContentHandler::generate(utility::outputStream& os, const vmime::enco } -void streamContentHandler::extract(utility::outputStream& os, - utility::progressListener* progress) const -{ - if (!m_stream) +void streamContentHandler::extract( + utility::outputStream& os, + utility::progressListener* progress +) const { + + if (!m_stream) { return; + } // No decoding to perform - if (!isEncoded()) - { + if (!isEncoded()) { + m_stream->reset(); // may not work... - if (progress) + if (progress) { utility::bufferedStreamCopy(*m_stream, os, getLength(), progress); - else + } else { utility::bufferedStreamCopy(*m_stream, os); - } + } + // Need to decode data - else - { + } else { + shared_ptr theDecoder = m_encoding.getEncoder(); m_stream->reset(); // may not work... @@ -170,63 +188,68 @@ void streamContentHandler::extract(utility::outputStream& os, } -void streamContentHandler::extractRaw(utility::outputStream& os, - utility::progressListener* progress) const -{ - if (!m_stream) +void streamContentHandler::extractRaw( + utility::outputStream& os, + utility::progressListener* progress +) const { + + if (!m_stream) { return; + } m_stream->reset(); // may not work... - if (progress) + if (progress) { utility::bufferedStreamCopy(*m_stream, os, getLength(), progress); - else + } else { utility::bufferedStreamCopy(*m_stream, os); + } } -size_t streamContentHandler::getLength() const -{ - return (m_length); +size_t streamContentHandler::getLength() const { + + return m_length; } -bool streamContentHandler::isEmpty() const -{ - return (m_length == 0 || !m_stream); +bool streamContentHandler::isEmpty() const { + + return m_length == 0 || !m_stream; } -bool streamContentHandler::isEncoded() const -{ - return (m_encoding != NO_ENCODING); +bool streamContentHandler::isEncoded() const { + + return m_encoding != NO_ENCODING; } -const vmime::encoding& streamContentHandler::getEncoding() const -{ - return (m_encoding); +const vmime::encoding& streamContentHandler::getEncoding() const { + + return m_encoding; } -bool streamContentHandler::isBuffered() const -{ - if (dynamicCast (m_stream) != NULL) +bool streamContentHandler::isBuffered() const { + + if (dynamicCast (m_stream)) { return true; + } // FIXME: some streams can be resetted return false; } -void streamContentHandler::setContentTypeHint(const mediaType& type) -{ +void streamContentHandler::setContentTypeHint(const mediaType& type) { + m_contentType = type; } -const mediaType streamContentHandler::getContentTypeHint() const -{ +const mediaType streamContentHandler::getContentTypeHint() const { + return m_contentType; } diff --git a/src/vmime/streamContentHandler.hpp b/src/vmime/streamContentHandler.hpp index db1e8052..6964a1c1 100644 --- a/src/vmime/streamContentHandler.hpp +++ b/src/vmime/streamContentHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,15 +28,13 @@ #include "vmime/contentHandler.hpp" -namespace vmime -{ +namespace vmime { /** A content handler which obtains its data from a stream. */ +class VMIME_EXPORT streamContentHandler : public contentHandler { -class VMIME_EXPORT streamContentHandler : public contentHandler -{ public: /** Creates a new empty content handler. No data can be extracted until @@ -57,10 +55,11 @@ public: * * @return a reference to a new content handler */ - streamContentHandler - (const shared_ptr & is, - const size_t length, - const vmime::encoding& enc = NO_ENCODING); + streamContentHandler( + const shared_ptr & is, + const size_t length, + const vmime::encoding& enc = NO_ENCODING + ); ~streamContentHandler(); @@ -78,13 +77,18 @@ public: * @param enc set to anything other than NO_ENCODING if the data obtained * from the stream is already encoded with the specified encoding */ - void setData - (const shared_ptr & is, - const size_t length, - const vmime::encoding& enc = NO_ENCODING); + void setData( + const shared_ptr & is, + const size_t length, + const vmime::encoding& enc = NO_ENCODING + ); - void generate(utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength = lineLengthLimits::infinite) const; + void generate( + utility::outputStream& os, + const vmime::encoding& enc, + const size_t maxLineLength = lineLengthLimits::infinite + ) const; void extract(utility::outputStream& os, utility::progressListener* progress = NULL) const; void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const; diff --git a/src/vmime/stringContentHandler.cpp b/src/vmime/stringContentHandler.cpp index 9a66663c..616c2f55 100644 --- a/src/vmime/stringContentHandler.cpp +++ b/src/vmime/stringContentHandler.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,103 +28,126 @@ #include "vmime/utility/outputStreamAdapter.hpp" -namespace vmime -{ +namespace vmime { -stringContentHandler::stringContentHandler() -{ +stringContentHandler::stringContentHandler() { + } -stringContentHandler::stringContentHandler(const string& buffer, const vmime::encoding& enc) - : m_encoding(enc), m_string(buffer) -{ +stringContentHandler::stringContentHandler( + const string& buffer, + const vmime::encoding& enc +) + : m_encoding(enc), + m_string(buffer) { + } -stringContentHandler::stringContentHandler(const stringContentHandler& cts) - : contentHandler(), m_contentType(cts.m_contentType), - m_encoding(cts.m_encoding), m_string(cts.m_string) -{ +stringContentHandler::stringContentHandler( + const stringContentHandler& cts +) + : contentHandler(), + m_contentType(cts.m_contentType), + m_encoding(cts.m_encoding), + m_string(cts.m_string) { + } -stringContentHandler::stringContentHandler(const utility::stringProxy& str, const vmime::encoding& enc) - : m_encoding(enc), m_string(str) -{ +stringContentHandler::stringContentHandler( + const utility::stringProxy& str, + const vmime::encoding& enc +) + : m_encoding(enc), + m_string(str) { + } -stringContentHandler::stringContentHandler(const string& buffer, const size_t start, - const size_t end, const vmime::encoding& enc) - : m_encoding(enc), m_string(buffer, start, end) -{ +stringContentHandler::stringContentHandler( + const string& buffer, + const size_t start, + const size_t end, + const vmime::encoding& enc +) + : m_encoding(enc), + m_string(buffer, start, end) { + } -stringContentHandler::~stringContentHandler() -{ +stringContentHandler::~stringContentHandler() { + } -shared_ptr stringContentHandler::clone() const -{ +shared_ptr stringContentHandler::clone() const { + return make_shared (*this); } -stringContentHandler& stringContentHandler::operator=(const stringContentHandler& cts) -{ +stringContentHandler& stringContentHandler::operator=(const stringContentHandler& cts) { + m_contentType = cts.m_contentType; m_encoding = cts.m_encoding; m_string = cts.m_string; - return (*this); + return *this; } -void stringContentHandler::setData(const utility::stringProxy& str, const vmime::encoding& enc) -{ +void stringContentHandler::setData(const utility::stringProxy& str, const vmime::encoding& enc) { + m_encoding = enc; m_string = str; } -void stringContentHandler::setData(const string& buffer, const vmime::encoding& enc) -{ +void stringContentHandler::setData(const string& buffer, const vmime::encoding& enc) { + m_encoding = enc; m_string.set(buffer); } -void stringContentHandler::setData(const string& buffer, const size_t start, - const size_t end, const vmime::encoding& enc) -{ +void stringContentHandler::setData( + const string& buffer, + const size_t start, + const size_t end, + const vmime::encoding& enc +) { + m_encoding = enc; m_string.set(buffer, start, end); } -stringContentHandler& stringContentHandler::operator=(const string& buffer) -{ +stringContentHandler& stringContentHandler::operator=(const string& buffer) { + setData(buffer, NO_ENCODING); - return (*this); + return *this; } -void stringContentHandler::generate(utility::outputStream& os, - const vmime::encoding& enc, const size_t maxLineLength) const -{ +void stringContentHandler::generate( + utility::outputStream& os, + const vmime::encoding& enc, + const size_t maxLineLength +) const { + // Managed data is already encoded - if (isEncoded()) - { + if (isEncoded()) { + // The data is already encoded but the encoding specified for // the generation is different from the current one. We need // to re-encode data: decode from input buffer to temporary // buffer, and then re-encode to output stream... - if (m_encoding != enc) - { + if (m_encoding != enc) { + shared_ptr theDecoder = m_encoding.getEncoder(); shared_ptr theEncoder = enc.getEncoder(); @@ -142,16 +165,16 @@ void stringContentHandler::generate(utility::outputStream& os, utility::inputStreamStringAdapter tempIn(str); theEncoder->encode(tempIn, os); - } + // No encoding to perform - else - { + } else { + m_string.extract(os); } - } + // Need to encode data before - else - { + } else { + shared_ptr theEncoder = enc.getEncoder(); theEncoder->getProperties()["maxlinelength"] = maxLineLength; theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT); @@ -163,17 +186,19 @@ void stringContentHandler::generate(utility::outputStream& os, } -void stringContentHandler::extract(utility::outputStream& os, - utility::progressListener* progress) const -{ +void stringContentHandler::extract( + utility::outputStream& os, + utility::progressListener* progress +) const { + // No decoding to perform - if (!isEncoded()) - { + if (!isEncoded()) { + m_string.extract(os, 0, m_string.length(), progress); - } + // Need to decode data - else - { + } else { + shared_ptr theDecoder = m_encoding.getEncoder(); utility::inputStreamStringProxyAdapter in(m_string); @@ -184,51 +209,53 @@ void stringContentHandler::extract(utility::outputStream& os, } -void stringContentHandler::extractRaw(utility::outputStream& os, - utility::progressListener* progress) const -{ +void stringContentHandler::extractRaw( + utility::outputStream& os, + utility::progressListener* progress +) const { + m_string.extract(os, 0, m_string.length(), progress); } -size_t stringContentHandler::getLength() const -{ - return (m_string.length()); +size_t stringContentHandler::getLength() const { + + return m_string.length(); } -bool stringContentHandler::isEmpty() const -{ - return (m_string.length() == 0); +bool stringContentHandler::isEmpty() const { + + return m_string.length() == 0; } -bool stringContentHandler::isEncoded() const -{ - return (m_encoding != NO_ENCODING); +bool stringContentHandler::isEncoded() const { + + return m_encoding != NO_ENCODING; } -const vmime::encoding& stringContentHandler::getEncoding() const -{ - return (m_encoding); +const vmime::encoding& stringContentHandler::getEncoding() const { + + return m_encoding; } -bool stringContentHandler::isBuffered() const -{ +bool stringContentHandler::isBuffered() const { + return true; } -void stringContentHandler::setContentTypeHint(const mediaType& type) -{ +void stringContentHandler::setContentTypeHint(const mediaType& type) { + m_contentType = type; } -const mediaType stringContentHandler::getContentTypeHint() const -{ +const mediaType stringContentHandler::getContentTypeHint() const { + return m_contentType; } diff --git a/src/vmime/stringContentHandler.hpp b/src/vmime/stringContentHandler.hpp index e9d34405..1a1bd1e9 100644 --- a/src/vmime/stringContentHandler.hpp +++ b/src/vmime/stringContentHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,8 +28,7 @@ #include "vmime/contentHandler.hpp" -namespace vmime -{ +namespace vmime { class VMIME_EXPORT stringContentHandler : public contentHandler @@ -37,9 +36,23 @@ class VMIME_EXPORT stringContentHandler : public contentHandler public: stringContentHandler(); - stringContentHandler(const string& buffer, const vmime::encoding& enc = NO_ENCODING); - stringContentHandler(const utility::stringProxy& str, const vmime::encoding& enc = NO_ENCODING); - stringContentHandler(const string& buffer, const size_t start, const size_t end, const vmime::encoding& enc = NO_ENCODING); + + stringContentHandler( + const string& buffer, + const vmime::encoding& enc = NO_ENCODING + ); + + stringContentHandler( + const utility::stringProxy& str, + const vmime::encoding& enc = NO_ENCODING + ); + + stringContentHandler( + const string& buffer, + const size_t start, + const size_t end, + const vmime::encoding& enc = NO_ENCODING + ); ~stringContentHandler(); @@ -58,13 +71,30 @@ public: // encoding/decoding will be performed on generate()/extract()). Note that the // data may be re-encoded (that is, decoded and encoded) if the encoding passed // to generate() is different from this one... - void setData(const utility::stringProxy& str, const vmime::encoding& enc = NO_ENCODING); - void setData(const string& buffer, const vmime::encoding& enc = NO_ENCODING); - void setData(const string& buffer, const size_t start, const size_t end, const vmime::encoding& enc = NO_ENCODING); + void setData( + const utility::stringProxy& str, + const vmime::encoding& enc = NO_ENCODING + ); + + void setData( + const string& buffer, + const vmime::encoding& enc = NO_ENCODING + ); + + void setData( + const string& buffer, + const size_t start, + const size_t end, + const vmime::encoding& enc = NO_ENCODING + ); stringContentHandler& operator=(const string& buffer); - void generate(utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength = lineLengthLimits::infinite) const; + void generate( + utility::outputStream& os, + const vmime::encoding& enc, + const size_t maxLineLength = lineLengthLimits::infinite + ) const; void extract(utility::outputStream& os, utility::progressListener* progress = NULL) const; void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const; diff --git a/src/vmime/text.cpp b/src/vmime/text.cpp index 28fda3ad..86ba44f1 100644 --- a/src/vmime/text.cpp +++ b/src/vmime/text.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -27,220 +27,238 @@ #include "vmime/encoding.hpp" -namespace vmime -{ +namespace vmime { -text::text() -{ +text::text() { + } text::text(const text& t) - : headerFieldValue() -{ + : headerFieldValue() { + copyFrom(t); } -text::text(const string& t, const charset& ch) -{ +text::text(const string& t, const charset& ch) { + createFromString(t, ch); } -text::text(const string& t) -{ +text::text(const string& t) { + createFromString(t, charset::getLocalCharset()); } -text::text(const word& w) -{ +text::text(const word& w) { + appendWord(make_shared (w)); } -text::~text() -{ +text::~text() { + removeAllWords(); } -void text::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void text::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + removeAllWords(); size_t newPos; - const std::vector > words = word::parseMultiple(ctx, buffer, position, end, &newPos); + const std::vector > words = + word::parseMultiple(ctx, buffer, position, end, &newPos); copy_vector(words, m_words); setParsedBounds(position, newPos); - if (newPosition) + if (newPosition) { *newPosition = newPos; + } } -void text::generateImpl - (const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void text::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + encodeAndFold(ctx, os, curLinePos, newLinePos, 0); } -void text::copyFrom(const component& other) -{ +void text::copyFrom(const component& other) { + const text& t = dynamic_cast (other); removeAllWords(); - for (std::vector >::const_iterator i = t.m_words.begin() ; i != t.m_words.end() ; ++i) + for (std::vector >::const_iterator i = t.m_words.begin() ; + i != t.m_words.end() ; ++i) { + m_words.push_back(make_shared (**i)); + } } -text& text::operator=(const component& other) -{ +text& text::operator=(const component& other) { + copyFrom(other); - return (*this); + return *this; } -text& text::operator=(const text& other) -{ +text& text::operator=(const text& other) { + copyFrom(other); - return (*this); + return *this; } -bool text::operator==(const text& t) const -{ - if (getWordCount() == t.getWordCount()) - { +bool text::operator==(const text& t) const { + + if (getWordCount() == t.getWordCount()) { + bool equal = true; std::vector >::const_iterator i = m_words.begin(); std::vector >::const_iterator j = t.m_words.begin(); - for ( ; equal && i != m_words.end() ; ++i, ++j) + for ( ; equal && i != m_words.end() ; ++i, ++j) { equal = (**i == **j); + } - return (equal); + return equal; } - return (false); + return false; } -bool text::operator!=(const text& t) const -{ +bool text::operator!=(const text& t) const { + return !(*this == t); } -const string text::getConvertedText(const charset& dest, const charsetConverterOptions& opts) const -{ +const string text::getConvertedText( + const charset& dest, + const charsetConverterOptions& opts +) const { + string out; - for (std::vector >::const_iterator i = m_words.begin() ; i != m_words.end() ; ++i) - out += (*i)->getConvertedText(dest, opts); + for (std::vector >::const_iterator i = m_words.begin() ; + i != m_words.end() ; ++i) { - return (out); + out += (*i)->getConvertedText(dest, opts); + } + + return out; } -void text::appendWord(const shared_ptr & w) -{ +void text::appendWord(const shared_ptr & w) { + m_words.push_back(w); } -void text::insertWordBefore(const size_t pos, const shared_ptr & w) -{ +void text::insertWordBefore(const size_t pos, const shared_ptr & w) { + m_words.insert(m_words.begin() + pos, w); } -void text::insertWordAfter(const size_t pos, const shared_ptr & w) -{ +void text::insertWordAfter(const size_t pos, const shared_ptr & w) { + m_words.insert(m_words.begin() + pos + 1, w); } -void text::removeWord(const size_t pos) -{ +void text::removeWord(const size_t pos) { + const std::vector >::iterator it = m_words.begin() + pos; m_words.erase(it); } -void text::removeAllWords() -{ +void text::removeAllWords() { + m_words.clear(); } -size_t text::getWordCount() const -{ - return (m_words.size()); +size_t text::getWordCount() const { + + return m_words.size(); } -bool text::isEmpty() const -{ - return (m_words.empty()); +bool text::isEmpty() const { + + return m_words.empty(); } -const shared_ptr text::getWordAt(const size_t pos) -{ - return (m_words[pos]); +const shared_ptr text::getWordAt(const size_t pos) { + + return m_words[pos]; } -const shared_ptr text::getWordAt(const size_t pos) const -{ - return (m_words[pos]); +const shared_ptr text::getWordAt(const size_t pos) const { + + return m_words[pos]; } -const std::vector > text::getWordList() const -{ +const std::vector > text::getWordList() const { + std::vector > list; list.reserve(m_words.size()); for (std::vector >::const_iterator it = m_words.begin() ; - it != m_words.end() ; ++it) - { + it != m_words.end() ; ++it) { + list.push_back(*it); } - return (list); + return list; } -const std::vector > text::getWordList() -{ - return (m_words); +const std::vector > text::getWordList() { + + return m_words; } -shared_ptr text::clone() const -{ +shared_ptr text::clone() const { + return make_shared (*this); } -shared_ptr text::newFromString(const string& in, const charset& ch) -{ +shared_ptr text::newFromString(const string& in, const charset& ch) { + shared_ptr t = make_shared (); t->createFromString(in, ch); @@ -249,8 +267,8 @@ shared_ptr text::newFromString(const string& in, const charset& ch) } -void text::createFromString(const string& in, const charset& ch) -{ +void text::createFromString(const string& in, const charset& ch) { + size_t asciiCount = 0; size_t asciiPercent = 0; @@ -263,46 +281,45 @@ void text::createFromString(const string& in, const charset& ch) encoding recommendedEnc; const bool alwaysEncode = ch.getRecommendedEncoding(recommendedEnc); - if (!alwaysEncode) - { + if (!alwaysEncode) { asciiCount = utility::stringUtils::countASCIIchars(in.begin(), in.end()); asciiPercent = (in.length() == 0 ? 100 : (100 * asciiCount) / in.length()); } // If there are "too much" non-ASCII chars, encode everything - if (alwaysEncode || asciiPercent < 60) // less than 60% ASCII chars - { + if (alwaysEncode || asciiPercent < 60) { // less than 60% ASCII chars + appendWord(make_shared (in, ch)); - } + // Else, only encode words which need it - else - { + } else { + bool is8bit = false; // is the current word 8-bit? bool prevIs8bit = false; // is previous word 8-bit? unsigned int count = 0; // total number of words - for (size_t end = in.size(), pos = 0, start = 0 ; ; ) - { - if (pos == end || parserHelpers::isSpace(in[pos])) - { + for (size_t end = in.size(), pos = 0, start = 0 ; ; ) { + + if (pos == end || parserHelpers::isSpace(in[pos])) { + const string chunk(in.begin() + start, in.begin() + pos); - if (pos != end) + if (pos != end) { ++pos; + } + + if (is8bit) { + + if (count && prevIs8bit) { - if (is8bit) - { - if (count && prevIs8bit) - { // No need to create a new encoded word, just append // the current word to the previous one. shared_ptr w = getWordAt(getWordCount() - 1); w->getBuffer() += " " + chunk; - } - else - { - if (count) - { + + } else { + + if (count) { shared_ptr w = getWordAt(getWordCount() - 1); w->getBuffer() += ' '; } @@ -312,37 +329,37 @@ void text::createFromString(const string& in, const charset& ch) prevIs8bit = true; ++count; } - } - else - { - if (count && !prevIs8bit) - { + + } else { + + if (count && !prevIs8bit) { + shared_ptr w = getWordAt(getWordCount() - 1); w->getBuffer() += " " + chunk; - } - else - { - appendWord(make_shared - (chunk, charset(charsets::US_ASCII))); + + } else { + + appendWord(make_shared (chunk, charset(charsets::US_ASCII))); prevIs8bit = false; ++count; } } - if (pos == end) + if (pos == end) { break; + } is8bit = false; start = pos; - } - else if (!parserHelpers::isAscii(in[pos])) - { + + } else if (!parserHelpers::isAscii(in[pos])) { + is8bit = true; ++pos; - } - else - { + + } else { + ++pos; } } @@ -350,26 +367,33 @@ void text::createFromString(const string& in, const charset& ch) } -void text::encodeAndFold - (const generationContext& ctx, utility::outputStream& os, - const size_t firstLineOffset, size_t* lastLineLength, const int flags) const -{ +void text::encodeAndFold( + const generationContext& ctx, + utility::outputStream& os, + const size_t firstLineOffset, + size_t* lastLineLength, + const int flags +) const { + size_t curLineLength = firstLineOffset; word::generatorState state; - for (size_t wi = 0 ; wi < getWordCount() ; ++wi) - { - getWordAt(wi)->generate(ctx, os, curLineLength, - &curLineLength, flags, &state); + for (size_t wi = 0 ; wi < getWordCount() ; ++wi) { + + getWordAt(wi)->generate( + ctx, os, curLineLength, + &curLineLength, flags, &state + ); } - if (lastLineLength) + if (lastLineLength) { *lastLineLength = curLineLength; + } } -shared_ptr text::decodeAndUnfold(const string& in) -{ +shared_ptr text::decodeAndUnfold(const string& in) { + shared_ptr t = make_shared (); decodeAndUnfold(parsingContext::getDefaultContext(), in, t.get()); @@ -378,8 +402,8 @@ shared_ptr text::decodeAndUnfold(const string& in) } -shared_ptr text::decodeAndUnfold(const parsingContext& ctx, const string& in) -{ +shared_ptr text::decodeAndUnfold(const parsingContext& ctx, const string& in) { + shared_ptr t = make_shared (); decodeAndUnfold(ctx, in, t.get()); @@ -388,15 +412,15 @@ shared_ptr text::decodeAndUnfold(const parsingContext& ctx, const string& } -text* text::decodeAndUnfold(const string& in, text* generateInExisting) -{ +text* text::decodeAndUnfold(const string& in, text* generateInExisting) { + return decodeAndUnfold(parsingContext::getDefaultContext(), in, generateInExisting); } -text* text::decodeAndUnfold(const parsingContext& ctx, const string& in, text* generateInExisting) -{ - text* out = (generateInExisting != NULL) ? generateInExisting : new text(); +text* text::decodeAndUnfold(const parsingContext& ctx, const string& in, text* generateInExisting) { + + text* out = generateInExisting ? generateInExisting : new text(); out->removeAllWords(); @@ -405,55 +429,56 @@ text* text::decodeAndUnfold(const parsingContext& ctx, const string& in, text* g copy_vector(words, out->m_words); - return (out); + return out; } // static -void text::fixBrokenWords(std::vector >& words) -{ - if (words.size() < 2) +void text::fixBrokenWords(std::vector >& words) { + + if (words.size() < 2) { return; + } // Fix words which encode a non-integral number of characters. // This is not RFC-compliant, but we should be able to recover from it. - for (size_t i = 0, n = words.size() ; i < n - 1 ; ++i) - { + for (size_t i = 0, n = words.size() ; i < n - 1 ; ++i) { + shared_ptr w1 = words[i]; // Check whether the word is valid bool valid = false; - try - { + try { + valid = w1->getCharset().isValidText(w1->getBuffer(), NULL); - } - catch (vmime::exceptions::charset_conv_error& e) - { + + } catch (vmime::exceptions::charset_conv_error& e) { + // Unknown charset or unexpected conversion error: assume word is valid valid = true; } // If the current word is not valid, try to grab some bytes // from the next words, to see whether it becomes valid. - if (!valid) - { + if (!valid) { + string buffer(w1->getBuffer()); size_t mergeWords = 1; // number of adjacent words to merge - for (size_t j = i + 1 ; j < n ; ++j) - { + for (size_t j = i + 1 ; j < n ; ++j) { + shared_ptr nextWord = words[j]; - if (nextWord->getCharset() != w1->getCharset()) + if (nextWord->getCharset() != w1->getCharset()) { break; + } buffer += nextWord->getBuffer(); ++mergeWords; } - if (mergeWords == 1) - { + if (mergeWords == 1) { // No adjacent word with same charset found continue; } @@ -467,15 +492,15 @@ void text::fixBrokenWords(std::vector >& words) words[i + 1]->setBuffer(string(buffer.begin() + firstInvalidByte, buffer.end())); // Remove unused words - for (size_t j = 0 ; j < mergeWords - 2 ; ++j) - { + for (size_t j = 0 ; j < mergeWords - 2 ; ++j) { + words.erase(words.begin() + i + 2); --n; } // If the next word is now empty, remove it - if (words[i + 1]->getBuffer().empty()) - { + if (words[i + 1]->getBuffer().empty()) { + words.erase(words.begin() + i + 1); --n; } @@ -484,23 +509,23 @@ void text::fixBrokenWords(std::vector >& words) } -const std::vector > text::getChildComponents() -{ +const std::vector > text::getChildComponents() { + std::vector > list; copy_vector(m_words, list); - return (list); + return list; } -const string text::getWholeBuffer() const -{ +const string text::getWholeBuffer() const { + string res; for (std::vector >::const_iterator it = m_words.begin() ; - it != m_words.end() ; ++it) - { + it != m_words.end() ; ++it) { + res += (*it)->getBuffer(); } diff --git a/src/vmime/text.hpp b/src/vmime/text.hpp index b11454cb..143f5270 100644 --- a/src/vmime/text.hpp +++ b/src/vmime/text.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,15 +30,13 @@ #include "vmime/word.hpp" -namespace vmime -{ +namespace vmime { /** List of encoded-words, as defined in RFC-2047 (basic type). */ +class VMIME_EXPORT text : public headerFieldValue { -class VMIME_EXPORT text : public headerFieldValue -{ public: text(); @@ -138,8 +136,10 @@ public: * @param opts options for charset conversion * @return text decoded in the specified charset */ - const string getConvertedText(const charset& dest, - const charsetConverterOptions& opts = charsetConverterOptions()) const; + const string getConvertedText( + const charset& dest, + const charsetConverterOptions& opts = charsetConverterOptions() + ) const; /** Return the unconverted (raw) data of all words. This is the * concatenation of the results returned by getBuffer() on @@ -188,8 +188,8 @@ public: /** Flags used by "encodeAndFold" function. */ - enum EncodeAndFoldFlags - { + enum EncodeAndFoldFlags { + // NOTE: If both "FORCE_NO_ENCODING" and "FORCE_ENCODING" are // specified, "FORCE_NO_ENCODING" is used by default. @@ -208,8 +208,13 @@ public: * @param lastLineLength will receive the length of the last line written * @param flags encoding flags (see EncodeAndFoldFlags) */ - void encodeAndFold(const generationContext& ctx, utility::outputStream& os, - const size_t firstLineOffset, size_t* lastLineLength, const int flags) const; + void encodeAndFold( + const generationContext& ctx, + utility::outputStream& os, + const size_t firstLineOffset, + size_t* lastLineLength, + const int flags + ) const; /** Decode and unfold text (RFC-2047), using the default parsing context. * @@ -247,7 +252,11 @@ public: * resulting object into an existing object. * @return new text object or existing object if generateInExisting != NULL */ - static text* decodeAndUnfold(const parsingContext& ctx, const string& in, text* generateInExisting); + static text* decodeAndUnfold( + const parsingContext& ctx, + const string& in, + text* generateInExisting + ); protected: @@ -255,18 +264,20 @@ protected: // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; private: diff --git a/src/vmime/textPart.hpp b/src/vmime/textPart.hpp index 4be0535d..e34a169a 100644 --- a/src/vmime/textPart.hpp +++ b/src/vmime/textPart.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,15 +32,13 @@ #include "vmime/contentHandler.hpp" -namespace vmime -{ +namespace vmime { /** Generic text part. */ +class VMIME_EXPORT textPart : public object { -class VMIME_EXPORT textPart : public object -{ friend class textPartFactory; friend class messageBuilder; // for generateIn, getPartCount friend class messageParser; // for parse @@ -94,7 +92,10 @@ public: * @param message the message * @param parent body part into which generate this part */ - virtual void generateIn(const shared_ptr & message, const shared_ptr & parent) const = 0; + virtual void generateIn( + const shared_ptr & message, + const shared_ptr & parent + ) const = 0; /** Parse the text part(s) from the specified message. * @@ -102,7 +103,11 @@ public: * @param parent part containing the text part * @param textPart actual text part */ - virtual void parse(const shared_ptr & message, const shared_ptr & parent, const shared_ptr & textPart) = 0; + virtual void parse( + const shared_ptr & message, + const shared_ptr & parent, + const shared_ptr & textPart + ) = 0; }; diff --git a/src/vmime/textPartFactory.cpp b/src/vmime/textPartFactory.cpp index 846a6605..2c58888a 100644 --- a/src/vmime/textPartFactory.cpp +++ b/src/vmime/textPartFactory.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,37 +29,36 @@ #include "vmime/htmlTextPart.hpp" -namespace vmime -{ +namespace vmime { -textPartFactory::textPartFactory() -{ - // Register some default names +textPartFactory::textPartFactory() { + registerType (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); registerType (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML)); } -textPartFactory::~textPartFactory() -{ +textPartFactory::~textPartFactory() { + } -textPartFactory* textPartFactory::getInstance() -{ +textPartFactory* textPartFactory::getInstance() { + static textPartFactory instance; - return (&instance); + return &instance; } shared_ptr textPartFactory::create(const mediaType& type) { for (MapType::const_iterator it = m_map.begin() ; - it != m_map.end() ; ++it) - { - if ((*it).first == type) + it != m_map.end() ; ++it) { + + if ((*it).first == type) { return ((*it).second)(); + } } throw exceptions::no_factory_available("No 'textPart' class registered for media type '" + type.generate() + "'."); diff --git a/src/vmime/textPartFactory.hpp b/src/vmime/textPartFactory.hpp index f5ce3774..322c6161 100644 --- a/src/vmime/textPartFactory.hpp +++ b/src/vmime/textPartFactory.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,12 +29,11 @@ #include "vmime/mediaType.hpp" -namespace vmime -{ +namespace vmime { -class VMIME_EXPORT textPartFactory -{ +class VMIME_EXPORT textPartFactory { + protected: textPartFactory(); @@ -47,12 +46,11 @@ protected: #ifndef VMIME_BUILDING_DOC template - class registerer - { + class registerer { public: - static shared_ptr creator() - { + static shared_ptr creator() { + // Allocate a new object return vmime::make_shared (); } @@ -64,8 +62,8 @@ public: static textPartFactory* getInstance(); template - void registerType(const mediaType& type) - { + void registerType(const mediaType& type) { + m_map.push_back(MapType::value_type(type, ®isterer::creator)); } diff --git a/src/vmime/types.hpp b/src/vmime/types.hpp index 7f2a0354..35278838 100644 --- a/src/vmime/types.hpp +++ b/src/vmime/types.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,8 +38,8 @@ #ifndef VMIME_BUILDING_DOC -namespace vmime -{ +namespace vmime { + using std::shared_ptr; using std::weak_ptr; using std::make_shared; @@ -52,8 +52,7 @@ namespace vmime * only for the singleton classes allocated on the stack. */ template - struct noop_shared_ptr_deleter - { + struct noop_shared_ptr_deleter { void operator()(T*) const {} }; @@ -63,8 +62,8 @@ namespace vmime #endif // VMIME_BUILDING_DOC -namespace vmime -{ +namespace vmime { + typedef std::string string; typedef unsigned short port_t; diff --git a/src/vmime/utility/childProcess.hpp b/src/vmime/utility/childProcess.hpp index 4898e3f7..b72ab850 100644 --- a/src/vmime/utility/childProcess.hpp +++ b/src/vmime/utility/childProcess.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,16 +38,14 @@ namespace utility { /** Spawn a process and redirect its standard input * and/or standard output. */ +class VMIME_EXPORT childProcess : public object { -class VMIME_EXPORT childProcess : public object -{ public: virtual ~childProcess() { } /** Flags used with start(). */ - enum Flags - { + enum Flags { FLAG_REDIRECT_STDIN = (1 << 0), FLAG_REDIRECT_STDOUT = (1 << 1) }; @@ -84,9 +82,8 @@ public: /** Create 'childProcess' objects. */ +class childProcessFactory : public object { -class childProcessFactory : public object -{ public: virtual ~childProcessFactory() { } @@ -104,4 +101,3 @@ public: #endif // VMIME_UTILITY_CHILDPROCESS_HPP_INCLUDED - diff --git a/src/vmime/utility/datetimeUtils.cpp b/src/vmime/utility/datetimeUtils.cpp index 2b55177e..b1a6c552 100644 --- a/src/vmime/utility/datetimeUtils.cpp +++ b/src/vmime/utility/datetimeUtils.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,130 +32,103 @@ namespace utility { #ifndef VMIME_BUILDING_DOC -static inline void nextMonth(datetime& d) -{ - if (d.getMonth() >= 12) - { +static inline void nextMonth(datetime& d) { + + if (d.getMonth() >= 12) { d.setMonth(1); d.setYear(d.getYear() + 1); - } - else - { + } else { d.setMonth(d.getMonth() + 1); } } -static inline void prevMonth(datetime& d) -{ - if (d.getMonth() <= 1) - { +static inline void prevMonth(datetime& d) { + + if (d.getMonth() <= 1) { d.setYear(d.getYear() - 1); d.setMonth(12); - } - else - { + } else { d.setMonth(d.getMonth() - 1); } } -static inline void nextDay(datetime& d) -{ +static inline void nextDay(datetime& d) { - if (d.getDay() >= datetimeUtils::getDaysInMonth(d.getYear(), d.getMonth())) - { + if (d.getDay() >= datetimeUtils::getDaysInMonth(d.getYear(), d.getMonth())) { d.setDay(1); nextMonth(d); - } - else - { + } else { d.setDay(d.getDay() + 1); } } -static inline void prevDay(datetime& d) -{ - if (d.getDay() <= 1) - { +static inline void prevDay(datetime& d) { + + if (d.getDay() <= 1) { prevMonth(d); d.setDay(datetimeUtils::getDaysInMonth(d.getYear(), d.getMonth())); - } - else - { + } else { d.setDay(d.getDay() - 1); } } -static inline void nextHour(datetime& d) -{ - if (d.getHour() >= 23) - { +static inline void nextHour(datetime& d) { + + if (d.getHour() >= 23) { d.setHour(0); nextDay(d); - } - else - { + } else { d.setHour(d.getHour() + 1); } } -static inline void prevHour(datetime& d) -{ - if (d.getHour() <= 0) - { +static inline void prevHour(datetime& d) { + + if (d.getHour() <= 0) { d.setHour(23); prevDay(d); - } - else - { + } else { d.setHour(d.getHour() - 1); } } -static inline void addHoursAndMinutes(datetime& d, const int h, const int m) -{ +static inline void addHoursAndMinutes(datetime& d, const int h, const int m) { + d.setMinute(d.getMinute() + m); - if (d.getMinute() >= 60) - { + if (d.getMinute() >= 60) { d.setMinute(d.getMinute() - 60); nextHour(d); } d.setHour(d.getHour() + h); - if (d.getHour() >= 24) - { + if (d.getHour() >= 24) { d.setHour(d.getHour() - 24); nextDay(d); } } -static inline void substractHoursAndMinutes(datetime& d, const int h, const int m) -{ - if (m > d.getMinute()) - { +static inline void substractHoursAndMinutes(datetime& d, const int h, const int m) { + + if (m > d.getMinute()) { d.setMinute(60 - (m - d.getMinute())); prevHour(d); - } - else - { + } else { d.setMinute(d.getMinute() - m); } - if (h > d.getHour()) - { + if (h > d.getHour()) { d.setHour(24 - (h - d.getHour())); prevDay(d); - } - else - { + } else { d.setHour(d.getHour() - h); } } @@ -163,10 +136,11 @@ static inline void substractHoursAndMinutes(datetime& d, const int h, const int #endif // VMIME_BUILDING_DOC -const datetime datetimeUtils::toUniversalTime(const datetime& date) -{ - if (date.getZone() == datetime::GMT) +const datetime datetimeUtils::toUniversalTime(const datetime& date) { + + if (date.getZone() == datetime::GMT) { return date; // no conversion needed + } datetime nd(date); nd.setZone(datetime::GMT); @@ -175,21 +149,23 @@ const datetime datetimeUtils::toUniversalTime(const datetime& date) const int h = (z < 0) ? (-z / 60) : (z / 60); const int m = (z < 0) ? (-z - h * 60) : (z - h * 60); - if (z < 0) // GMT-hhmm: add hours and minutes to date + if (z < 0) { // GMT-hhmm: add hours and minutes to date addHoursAndMinutes(nd, h, m); - else // GMT+hhmm: substract hours and minutes from date + } else { // GMT+hhmm: substract hours and minutes from date substractHoursAndMinutes(nd, h, m); + } - return (nd); + return nd; } -const datetime datetimeUtils::toLocalTime(const datetime& date, const int zone) -{ +const datetime datetimeUtils::toLocalTime(const datetime& date, const int zone) { + datetime utcDate(date); - if (utcDate.getZone() != datetime::GMT) + if (utcDate.getZone() != datetime::GMT) { utcDate = toUniversalTime(date); // convert to UT before + } datetime nd(utcDate); nd.setZone(zone); @@ -197,53 +173,57 @@ const datetime datetimeUtils::toLocalTime(const datetime& date, const int zone) const int h = (zone < 0) ? (-zone / 60) : (zone / 60); const int m = (zone < 0) ? (-zone - h * 60) : (zone - h * 60); - if (zone < 0) // GMT+hhmm: substract hours and minutes from date + if (zone < 0) { // GMT+hhmm: substract hours and minutes from date substractHoursAndMinutes(nd, h, m); - else // GMT-hhmm: add hours and minutes to date + } else { // GMT-hhmm: add hours and minutes to date addHoursAndMinutes(nd, h, m); + } - return (nd); + return nd; } -bool datetimeUtils::isLeapYear(const int year) -{ +bool datetimeUtils::isLeapYear(const int year) { + // From RFC 3339 - Appendix C. Leap Years: return ((year % 4) == 0 && (year % 100 != 0 || year % 400 == 0)); } -int datetimeUtils::getDaysInMonth(const int year, const int month) -{ - static const int daysInMonth[12] = - { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - static const int daysInMonthLeapYear[12] = - { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +int datetimeUtils::getDaysInMonth(const int year, const int month) { - if (month < 1 || month > 12) + static const int daysInMonth[12] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + static const int daysInMonthLeapYear[12] = { + 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + + if (month < 1 || month > 12) { throw std::out_of_range("Invalid month number"); + } - return (isLeapYear(year) ? daysInMonthLeapYear[month - 1] : daysInMonth[month - 1]); + return isLeapYear(year) ? daysInMonthLeapYear[month - 1] : daysInMonth[month - 1]; } -int datetimeUtils::getDayOfWeek(const int year, const int month, const int day) -{ +int datetimeUtils::getDayOfWeek(const int year, const int month, const int day) { + int y = year; int m = month; - if (month < 1 || month > 12) + if (month < 1 || month > 12) { throw std::out_of_range("Invalid month number"); - else if (day < 1 || day > getDaysInMonth(year, month)) + } else if (day < 1 || day > getDaysInMonth(year, month)) { throw std::out_of_range("Invalid day number"); + } // From RFC-3339 - Appendix B. Day of the Week // Adjust months so February is the last one m -= 2; - if (m < 1) - { + if (m < 1) { m += 12; --y; } @@ -252,25 +232,27 @@ int datetimeUtils::getDayOfWeek(const int year, const int month, const int day) const int cent = y / 100; y %= 100; - return (((26 * m - 2) / 10 + day + y + (y >> 2) + (cent >> 2) + 5 * cent) % 7); + return ((26 * m - 2) / 10 + day + y + (y >> 2) + (cent >> 2) + 5 * cent) % 7; } -int datetimeUtils::getWeekOfYear(const int year, const int month, const int day, const bool iso) -{ +int datetimeUtils::getWeekOfYear(const int year, const int month, const int day, const bool iso) { + // Algorithm from http://personal.ecu.edu/mccartyr/ISOwdALG.txt const bool leapYear = ((year % 4) == 0 && (year % 100) != 0) || (year % 400) == 0; const bool leapYear_1 = (((year - 1) % 4) == 0 && ((year - 1) % 100) != 0) || ((year - 1) % 400) == 0; // 4. Find the DayOfYearNumber for Y M D - static const int DAY_OF_YEAR_NUMBER_MAP[12] = - { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + static const int DAY_OF_YEAR_NUMBER_MAP[12] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 + }; int DayOfYearNumber = day + DAY_OF_YEAR_NUMBER_MAP[month - 1]; - if (leapYear && month > 2) + if (leapYear && month > 2) { DayOfYearNumber += 1; + } // 5. Find the Jan1Weekday for Y (Monday=1, Sunday=7) const int YY = (year - 1) % 100; @@ -285,45 +267,47 @@ int datetimeUtils::getWeekOfYear(const int year, const int month, const int day, // 7. Find if Y M D falls in YearNumber Y-1, WeekNumber 52 or 53 int YearNumber = 0, WeekNumber = 0; - if (DayOfYearNumber <= (8 - Jan1Weekday) && Jan1Weekday > 4) - { + if (DayOfYearNumber <= (8 - Jan1Weekday) && Jan1Weekday > 4) { + YearNumber = year - 1; - if (Jan1Weekday == 5 || (Jan1Weekday == 6 && leapYear_1)) + if (Jan1Weekday == 5 || (Jan1Weekday == 6 && leapYear_1)) { WeekNumber = 53; - else + } else { WeekNumber = 52; - } - else - { + } + + } else { + YearNumber = year; } // 8. Find if Y M D falls in YearNumber Y+1, WeekNumber 1 - if (YearNumber == year) - { + if (YearNumber == year) { + const int I = (leapYear ? 366 : 365); - if ((I - DayOfYearNumber) < (4 - Weekday)) - { + if ((I - DayOfYearNumber) < (4 - Weekday)) { YearNumber = year + 1; WeekNumber = 1; } } // 9. Find if Y M D falls in YearNumber Y, WeekNumber 1 through 53 - if (YearNumber == year) - { + if (YearNumber == year) { + const int J = DayOfYearNumber + (7 - Weekday) + (Jan1Weekday - 1); WeekNumber = J / 7; - if (Jan1Weekday > 4) + if (Jan1Weekday > 4) { WeekNumber -= 1; + } } - if (!iso && (WeekNumber == 1 && month == 12)) + if (!iso && (WeekNumber == 1 && month == 12)) { WeekNumber = 53; + } return WeekNumber; } diff --git a/src/vmime/utility/datetimeUtils.hpp b/src/vmime/utility/datetimeUtils.hpp index a7291bb8..b762a6e6 100644 --- a/src/vmime/utility/datetimeUtils.hpp +++ b/src/vmime/utility/datetimeUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,9 +34,8 @@ namespace utility { /** Miscellaneous functions related to date/time. */ +class VMIME_EXPORT datetimeUtils { -class VMIME_EXPORT datetimeUtils -{ public: /** Test whether the specified year is a leap year. diff --git a/src/vmime/utility/encoder/b64Encoder.cpp b/src/vmime/utility/encoder/b64Encoder.cpp index ddaa62f8..ef4e581e 100644 --- a/src/vmime/utility/encoder/b64Encoder.cpp +++ b/src/vmime/utility/encoder/b64Encoder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,18 +30,18 @@ namespace utility { namespace encoder { -b64Encoder::b64Encoder() -{ +b64Encoder::b64Encoder() { + } -const std::vector b64Encoder::getAvailableProperties() const -{ +const std::vector b64Encoder::getAvailableProperties() const { + std::vector list(encoder::getAvailableProperties()); list.push_back("maxlinelength"); - return (list); + return list; } @@ -49,8 +49,7 @@ const std::vector b64Encoder::getAvailableProperties() const const unsigned char b64Encoder::sm_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; -const unsigned char b64Encoder::sm_decodeMap[256] = -{ +const unsigned char b64Encoder::sm_decodeMap[256] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0x00 - 0x0f 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0x10 - 0x1f 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3e,0xff,0xff,0xff,0x3f, // 0x20 - 0x2f @@ -75,9 +74,12 @@ const unsigned char b64Encoder::sm_decodeMap[256] = -size_t b64Encoder::encode(utility::inputStream& in, - utility::outputStream& out, utility::progressListener* progress) -{ +size_t b64Encoder::encode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress +) { + in.reset(); // may not work... const size_t propMaxLineLength = @@ -99,72 +101,77 @@ size_t b64Encoder::encode(utility::inputStream& in, size_t curCol = 0; - if (progress) + if (progress) { progress->start(0); + } + + while (bufferPos < bufferLength || !in.eof()) { + + if (bufferPos >= bufferLength) { - while (bufferPos < bufferLength || !in.eof()) - { - if (bufferPos >= bufferLength) - { bufferLength = in.read(buffer, sizeof(buffer)); bufferPos = 0; - if (bufferLength == 0) + if (bufferLength == 0) { break; + } } // Get 3 bytes of data int count = 0; - while (count < 3 && bufferPos < bufferLength) + while (count < 3 && bufferPos < bufferLength) { bytes[count++] = buffer[bufferPos++]; + } + + while (count < 3) { - while (count < 3) - { // There may be more data in the next chunk... - if (bufferPos >= bufferLength) - { + if (bufferPos >= bufferLength) { + bufferLength = in.read(buffer, sizeof(buffer)); bufferPos = 0; - if (bufferLength == 0) + if (bufferLength == 0) { break; + } } - while (count < 3 && bufferPos < bufferLength) + while (count < 3 && bufferPos < bufferLength) { bytes[count++] = buffer[bufferPos++]; + } } // Encode data - switch (count) - { - case 1: + switch (count) { - output[0] = sm_alphabet[(bytes[0] & 0xFC) >> 2]; - output[1] = sm_alphabet[(bytes[0] & 0x03) << 4]; - output[2] = sm_alphabet[64]; // padding - output[3] = sm_alphabet[64]; // padding + case 1: - break; + output[0] = sm_alphabet[(bytes[0] & 0xFC) >> 2]; + output[1] = sm_alphabet[(bytes[0] & 0x03) << 4]; + output[2] = sm_alphabet[64]; // padding + output[3] = sm_alphabet[64]; // padding - case 2: + break; - output[0] = sm_alphabet[(bytes[0] & 0xFC) >> 2]; - output[1] = sm_alphabet[((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xF0) >> 4)]; - output[2] = sm_alphabet[(bytes[1] & 0x0F) << 2]; - output[3] = sm_alphabet[64]; // padding + case 2: - break; + output[0] = sm_alphabet[(bytes[0] & 0xFC) >> 2]; + output[1] = sm_alphabet[((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xF0) >> 4)]; + output[2] = sm_alphabet[(bytes[1] & 0x0F) << 2]; + output[3] = sm_alphabet[64]; // padding - default: - case 3: + break; - output[0] = sm_alphabet[(bytes[0] & 0xFC) >> 2]; - output[1] = sm_alphabet[((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xF0) >> 4)]; - output[2] = sm_alphabet[((bytes[1] & 0x0F) << 2) | ((bytes[2] & 0xC0) >> 6)]; - output[3] = sm_alphabet[(bytes[2] & 0x3F)]; + default: + case 3: - break; + output[0] = sm_alphabet[(bytes[0] & 0xFC) >> 2]; + output[1] = sm_alphabet[((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xF0) >> 4)]; + output[2] = sm_alphabet[((bytes[1] & 0x0F) << 2) | ((bytes[2] & 0xC0) >> 6)]; + output[3] = sm_alphabet[(bytes[2] & 0x3F)]; + + break; } // Write encoded data to output stream @@ -174,26 +181,30 @@ size_t b64Encoder::encode(utility::inputStream& in, total += 4; curCol += 4; - if (cutLines && curCol + 2 /* \r\n */ + 4 /* next bytes */ >= maxLineLength) - { + if (cutLines && curCol + 2 /* \r\n */ + 4 /* next bytes */ >= maxLineLength) { out.write("\r\n", 2); curCol = 0; } - if (progress) + if (progress) { progress->progress(inTotal, inTotal); + } } - if (progress) + if (progress) { progress->stop(inTotal); + } - return (total); + return total; } -size_t b64Encoder::decode(utility::inputStream& in, - utility::outputStream& out, utility::progressListener* progress) -{ +size_t b64Encoder::decode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress +) { + in.reset(); // may not work... // Process the data @@ -207,73 +218,78 @@ size_t b64Encoder::decode(utility::inputStream& in, byte_t bytes[4]; byte_t output[3]; - if (progress) + if (progress) { progress->start(0); + } + + while (bufferPos < bufferLength || !in.eof()) { - while (bufferPos < bufferLength || !in.eof()) - { bytes[0] = '='; bytes[1] = '='; bytes[2] = '='; bytes[3] = '='; // Need to get more data? - if (bufferPos >= bufferLength) - { + if (bufferPos >= bufferLength) { + bufferLength = in.read(buffer, sizeof(buffer)); bufferPos = 0; // No more data - if (bufferLength == 0) + if (bufferLength == 0) { break; + } } // 4 bytes of input provide 3 bytes of output, so // get the next 4 bytes from the input stream. int count = 0; - while (count < 4 && bufferPos < bufferLength) - { + while (count < 4 && bufferPos < bufferLength) { + const byte_t c = buffer[bufferPos++]; - if (!parserHelpers::isSpace(c)) + if (!parserHelpers::isSpace(c)) { bytes[count++] = c; + } } - if (count != 4) - { - while (count < 4 && !in.eof()) - { + if (count != 4) { + + while (count < 4 && !in.eof()) { + // Data continues on the next chunk bufferLength = in.read(buffer, sizeof(buffer)); bufferPos = 0; - while (count < 4 && bufferPos < bufferLength) - { + while (count < 4 && bufferPos < bufferLength) { + const byte_t c = buffer[bufferPos++]; - if (!parserHelpers::isSpace(c)) + if (!parserHelpers::isSpace(c)) { bytes[count++] = c; + } } } } - if (count != 4) // input length is not a multiple of 4 bytes + if (count != 4) { // input length is not a multiple of 4 bytes break; + } // Decode the bytes byte_t c1 = bytes[0]; byte_t c2 = bytes[1]; - if (c1 == '=' || c2 == '=') // end + if (c1 == '=' || c2 == '=') { // end break; + } output[0] = static_cast ((sm_decodeMap[c1] << 2) | ((sm_decodeMap[c2] & 0x30) >> 4)); c1 = bytes[2]; - if (c1 == '=') // end - { + if (c1 == '=') { // end B64_WRITE(out, output, 1); total += 1; break; @@ -283,8 +299,7 @@ size_t b64Encoder::decode(utility::inputStream& in, c2 = bytes[3]; - if (c2 == '=') // end - { + if (c2 == '=') { // end B64_WRITE(out, output, 2); total += 2; break; @@ -296,19 +311,21 @@ size_t b64Encoder::decode(utility::inputStream& in, total += 3; inTotal += count; - if (progress) + if (progress) { progress->progress(inTotal, inTotal); + } } - if (progress) + if (progress) { progress->stop(inTotal); + } - return (total); + return total; } -size_t b64Encoder::getEncodedSize(const size_t n) const -{ +size_t b64Encoder::getEncodedSize(const size_t n) const { + const size_t propMaxLineLength = getProperties().getProperty ("maxlinelength", static_cast (-1)); @@ -321,8 +338,8 @@ size_t b64Encoder::getEncodedSize(const size_t n) const } -size_t b64Encoder::getDecodedSize(const size_t n) const -{ +size_t b64Encoder::getDecodedSize(const size_t n) const { + // 4 bytes of input provide 3 bytes of output return (n * 3) / 4; } diff --git a/src/vmime/utility/encoder/b64Encoder.hpp b/src/vmime/utility/encoder/b64Encoder.hpp index 2d23d9e3..c5be2c38 100644 --- a/src/vmime/utility/encoder/b64Encoder.hpp +++ b/src/vmime/utility/encoder/b64Encoder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,15 +35,23 @@ namespace encoder { /** Base64 encoder. */ +class VMIME_EXPORT b64Encoder : public encoder { -class VMIME_EXPORT b64Encoder : public encoder -{ public: b64Encoder(); - size_t encode(utility::inputStream& in, utility::outputStream& out, utility::progressListener* progress = NULL); - size_t decode(utility::inputStream& in, utility::outputStream& out, utility::progressListener* progress = NULL); + size_t encode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress = NULL + ); + + size_t decode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress = NULL + ); const std::vector getAvailableProperties() const; diff --git a/src/vmime/utility/encoder/binaryEncoder.cpp b/src/vmime/utility/encoder/binaryEncoder.cpp index 7d7c40d1..b30bb7bb 100644 --- a/src/vmime/utility/encoder/binaryEncoder.cpp +++ b/src/vmime/utility/encoder/binaryEncoder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,8 +29,8 @@ namespace utility { namespace encoder { -binaryEncoder::binaryEncoder() -{ +binaryEncoder::binaryEncoder() { + } diff --git a/src/vmime/utility/encoder/binaryEncoder.hpp b/src/vmime/utility/encoder/binaryEncoder.hpp index 1c831939..331014e3 100644 --- a/src/vmime/utility/encoder/binaryEncoder.hpp +++ b/src/vmime/utility/encoder/binaryEncoder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,9 +35,8 @@ namespace encoder { /** Binary encoder. */ +class VMIME_EXPORT binaryEncoder : public noopEncoder { -class VMIME_EXPORT binaryEncoder : public noopEncoder -{ public: binaryEncoder(); diff --git a/src/vmime/utility/encoder/eightBitEncoder.cpp b/src/vmime/utility/encoder/eightBitEncoder.cpp index 4ab07f06..a9669319 100644 --- a/src/vmime/utility/encoder/eightBitEncoder.cpp +++ b/src/vmime/utility/encoder/eightBitEncoder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,8 +29,8 @@ namespace utility { namespace encoder { -eightBitEncoder::eightBitEncoder() -{ +eightBitEncoder::eightBitEncoder() { + } diff --git a/src/vmime/utility/encoder/eightBitEncoder.hpp b/src/vmime/utility/encoder/eightBitEncoder.hpp index ee50ca95..c400f512 100644 --- a/src/vmime/utility/encoder/eightBitEncoder.hpp +++ b/src/vmime/utility/encoder/eightBitEncoder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,9 +35,8 @@ namespace encoder { /** 8-bit encoder. */ +class VMIME_EXPORT eightBitEncoder : public noopEncoder { -class VMIME_EXPORT eightBitEncoder : public noopEncoder -{ public: eightBitEncoder(); diff --git a/src/vmime/utility/encoder/encoder.cpp b/src/vmime/utility/encoder/encoder.cpp index b4b13249..634adf0d 100644 --- a/src/vmime/utility/encoder/encoder.cpp +++ b/src/vmime/utility/encoder/encoder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,44 +30,44 @@ namespace utility { namespace encoder { -encoder::encoder() -{ +encoder::encoder() { + } -encoder::~encoder() -{ +encoder::~encoder() { + } -const propertySet& encoder::getProperties() const -{ - return (m_props); +const propertySet& encoder::getProperties() const { + + return m_props; } -propertySet& encoder::getProperties() -{ - return (m_props); +propertySet& encoder::getProperties() { + + return m_props; } -const propertySet& encoder::getResults() const -{ - return (m_results); +const propertySet& encoder::getResults() const { + + return m_results; } -propertySet& encoder::getResults() -{ - return (m_results); +propertySet& encoder::getResults() { + + return m_results; } -const std::vector encoder::getAvailableProperties() const -{ +const std::vector encoder::getAvailableProperties() const { + std::vector list; - return (list); + return list; } diff --git a/src/vmime/utility/encoder/encoder.hpp b/src/vmime/utility/encoder/encoder.hpp index 34cd10b7..134e813e 100644 --- a/src/vmime/utility/encoder/encoder.hpp +++ b/src/vmime/utility/encoder/encoder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,9 +38,8 @@ namespace encoder { /** Encode/decode data in different encodings. */ +class VMIME_EXPORT encoder : public object { -class VMIME_EXPORT encoder : public object -{ public: encoder(); @@ -54,7 +53,11 @@ public: * want to receive progress notifications * @return number of bytes written into output stream */ - virtual size_t encode(utility::inputStream& in, utility::outputStream& out, utility::progressListener* progress = NULL) = 0; + virtual size_t encode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress = NULL + ) = 0; /** Decode data. * @@ -64,7 +67,11 @@ public: * want to receive progress notifications * @return number of bytes written into output stream */ - virtual size_t decode(utility::inputStream& in, utility::outputStream& out, utility::progressListener* progress = NULL) = 0; + virtual size_t decode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress = NULL + ) = 0; /** Return the properties of the encoder. * diff --git a/src/vmime/utility/encoder/encoderFactory.cpp b/src/vmime/utility/encoder/encoderFactory.cpp index 01ac7753..df655ae0 100644 --- a/src/vmime/utility/encoder/encoderFactory.cpp +++ b/src/vmime/utility/encoder/encoderFactory.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,8 +37,8 @@ namespace utility { namespace encoder { -encoderFactory::encoderFactory() -{ +encoderFactory::encoderFactory() { + // Register some default encoders registerName ("base64"); registerName ("quoted-printable"); @@ -58,83 +58,88 @@ encoderFactory::encoderFactory() } -encoderFactory::~encoderFactory() -{ +encoderFactory::~encoderFactory() { + } -shared_ptr encoderFactory::getInstance() -{ +shared_ptr encoderFactory::getInstance() { + static encoderFactory instance; return shared_ptr (&instance, noop_shared_ptr_deleter ()); } -shared_ptr encoderFactory::create(const string& name) -{ - try - { - return (getEncoderByName(name)->create()); - } - catch (exceptions::no_encoder_available &) { +shared_ptr encoderFactory::create(const string& name) { - if (m_defaultEncoder) + try { + + return (getEncoderByName(name)->create()); + + } catch (exceptions::no_encoder_available &) { + + if (m_defaultEncoder) { return m_defaultEncoder; + } throw; } } -const shared_ptr encoderFactory::getEncoderByName(const string& name) const -{ +const shared_ptr + encoderFactory::getEncoderByName(const string& name) const { + const string lcName(utility::stringUtils::toLower(name)); for (std::vector >::const_iterator it = m_encoders.begin() ; - it != m_encoders.end() ; ++it) - { - if ((*it)->getName() == lcName) + it != m_encoders.end() ; ++it) { + + if ((*it)->getName() == lcName) { return (*it); + } } throw exceptions::no_encoder_available(name); } -size_t encoderFactory::getEncoderCount() const -{ - return (m_encoders.size()); +size_t encoderFactory::getEncoderCount() const { + + return m_encoders.size(); } -const shared_ptr encoderFactory::getEncoderAt(const size_t pos) const -{ - return (m_encoders[pos]); +const shared_ptr + encoderFactory::getEncoderAt(const size_t pos) const { + + return m_encoders[pos]; } -const std::vector > encoderFactory::getEncoderList() const -{ +const std::vector > + encoderFactory::getEncoderList() const { + std::vector > res; for (std::vector >::const_iterator it = m_encoders.begin() ; - it != m_encoders.end() ; ++it) - { + it != m_encoders.end() ; ++it) { + res.push_back(*it); } - return (res); + return res; } -void encoderFactory::setDefaultEncoder(const shared_ptr & enc) -{ +void encoderFactory::setDefaultEncoder(const shared_ptr & enc) { + m_defaultEncoder = enc; } -shared_ptr encoderFactory::getDefaultEncoder() const -{ +shared_ptr encoderFactory::getDefaultEncoder() const { + return m_defaultEncoder; } diff --git a/src/vmime/utility/encoder/encoderFactory.hpp b/src/vmime/utility/encoder/encoderFactory.hpp index 91121ad5..e475f8e8 100644 --- a/src/vmime/utility/encoder/encoderFactory.hpp +++ b/src/vmime/utility/encoder/encoderFactory.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,7 +36,6 @@ namespace encoder { /** A factory to create 'encoder' objects for the specified encoding. */ - class VMIME_EXPORT encoderFactory { private: @@ -49,8 +48,8 @@ public: static shared_ptr getInstance(); /** Information about a registered encoder. */ - class VMIME_EXPORT registeredEncoder : public object - { + class VMIME_EXPORT registeredEncoder : public object { + protected: virtual ~registeredEncoder() { } @@ -65,20 +64,20 @@ public: private: template - class registeredEncoderImpl : public registeredEncoder - { + class registeredEncoderImpl : public registeredEncoder { + public: registeredEncoderImpl(const string& name) : m_name(name) { } - shared_ptr create() const - { + shared_ptr create() const { + return vmime::make_shared (); } - const string& getName() const - { - return (m_name); + const string& getName() const { + + return m_name; } private: @@ -97,9 +96,11 @@ public: * @param name encoding name */ template - void registerName(const string& name) - { - m_encoders.push_back(vmime::make_shared >(utility::stringUtils::toLower(name))); + void registerName(const string& name) { + + m_encoders.push_back( + vmime::make_shared >(utility::stringUtils::toLower(name)) + ); } /** Create a new encoder instance from an encoding name. diff --git a/src/vmime/utility/encoder/noopEncoder.cpp b/src/vmime/utility/encoder/noopEncoder.cpp index 3d991b5d..30cc6c16 100644 --- a/src/vmime/utility/encoder/noopEncoder.cpp +++ b/src/vmime/utility/encoder/noopEncoder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,14 +31,17 @@ namespace utility { namespace encoder { -noopEncoder::noopEncoder() -{ +noopEncoder::noopEncoder() { + } -size_t noopEncoder::encode(utility::inputStream& in, - utility::outputStream& out, utility::progressListener* progress) -{ +size_t noopEncoder::encode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress +) { + in.reset(); // may not work... // No encoding performed @@ -53,31 +56,35 @@ size_t noopEncoder::encode(utility::inputStream& in, } -size_t noopEncoder::decode(utility::inputStream& in, - utility::outputStream& out, utility::progressListener* progress) -{ +size_t noopEncoder::decode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress +) { + in.reset(); // may not work... // No decoding performed size_t res = 0; - if (progress) + if (progress) { res = utility::bufferedStreamCopy(in, out, 0, progress); - else + } else { res = utility::bufferedStreamCopy(in, out); + } return res; } -size_t noopEncoder::getEncodedSize(const size_t n) const -{ +size_t noopEncoder::getEncodedSize(const size_t n) const { + return n; } -size_t noopEncoder::getDecodedSize(const size_t n) const -{ +size_t noopEncoder::getDecodedSize(const size_t n) const { + return n; } diff --git a/src/vmime/utility/encoder/noopEncoder.hpp b/src/vmime/utility/encoder/noopEncoder.hpp index 6314812b..91944dee 100644 --- a/src/vmime/utility/encoder/noopEncoder.hpp +++ b/src/vmime/utility/encoder/noopEncoder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,15 +35,23 @@ namespace encoder { /** Default, no-op encoder (simple copy, no encoding/decoding is performed). */ +class VMIME_EXPORT noopEncoder : public encoder { -class VMIME_EXPORT noopEncoder : public encoder -{ public: noopEncoder(); - size_t encode(utility::inputStream& in, utility::outputStream& out, utility::progressListener* progress = NULL); - size_t decode(utility::inputStream& in, utility::outputStream& out, utility::progressListener* progress = NULL); + size_t encode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress = NULL + ); + + size_t decode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress = NULL + ); size_t getEncodedSize(const size_t n) const; size_t getDecodedSize(const size_t n) const; diff --git a/src/vmime/utility/encoder/qpEncoder.cpp b/src/vmime/utility/encoder/qpEncoder.cpp index d4844ce7..4aeb6400 100644 --- a/src/vmime/utility/encoder/qpEncoder.cpp +++ b/src/vmime/utility/encoder/qpEncoder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,13 +30,13 @@ namespace utility { namespace encoder { -qpEncoder::qpEncoder() -{ +qpEncoder::qpEncoder() { + } -const std::vector qpEncoder::getAvailableProperties() const -{ +const std::vector qpEncoder::getAvailableProperties() const { + std::vector list(encoder::getAvailableProperties()); list.push_back("maxlinelength"); @@ -46,7 +46,7 @@ const std::vector qpEncoder::getAvailableProperties() const list.push_back("rfc2047"); // for header fields encoding (RFC #2047) - return (list); + return list; } @@ -69,8 +69,7 @@ const unsigned char qpEncoder::sm_hexDigits[] = "0123456789ABCDEF"; // This is a quick lookup table: // '1' means "encode", '0' means "no encoding" // -const vmime_uint8 qpEncoder::sm_RFC2047EncodeTable[] = -{ +const vmime_uint8 qpEncoder::sm_RFC2047EncodeTable[] = { /* 0 NUL */ 1, /* 1 SOH */ 1, /* 2 STX */ 1, /* 3 ETX */ 1, /* 4 EOT */ 1, /* 5 ENQ */ 1, /* 6 ACK */ 1, /* 7 BEL */ 1, /* 8 BS */ 1, /* 9 TAB */ 1, /* 10 LF */ 1, /* 11 VT */ 1, /* 12 FF */ 1, /* 13 CR */ 1, /* 14 SO */ 1, /* 15 SI */ 1, /* 16 DLE */ 1, /* 17 DC1 */ 1, @@ -97,8 +96,7 @@ const vmime_uint8 qpEncoder::sm_RFC2047EncodeTable[] = // Hex-decoding table -const vmime_uint8 qpEncoder::sm_hexDecodeTable[256] = -{ +const vmime_uint8 qpEncoder::sm_hexDecodeTable[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -119,30 +117,30 @@ const vmime_uint8 qpEncoder::sm_hexDecodeTable[256] = // static -bool qpEncoder::RFC2047_isEncodingNeededForChar(const byte_t c) -{ - return (c >= 128 || sm_RFC2047EncodeTable[c] != 0); +bool qpEncoder::RFC2047_isEncodingNeededForChar(const byte_t c) { + + return c >= 128 || sm_RFC2047EncodeTable[c] != 0; } // static -int qpEncoder::RFC2047_getEncodedLength(const byte_t c) -{ - if (c >= 128 || sm_RFC2047EncodeTable[c] != 0) - { - if (c == 32) // space - { +int qpEncoder::RFC2047_getEncodedLength(const byte_t c) { + + if (c >= 128 || sm_RFC2047EncodeTable[c] != 0) { + + if (c == 32) { // space + // Encoded as "_" return 1; - } - else - { + + } else { + // Hex encoding return 3; } - } - else - { + + } else { + return 1; // no encoding } } @@ -162,9 +160,12 @@ int qpEncoder::RFC2047_getEncodedLength(const byte_t c) #endif // VMIME_BUILDING_DOC -size_t qpEncoder::encode(utility::inputStream& in, - utility::outputStream& out, utility::progressListener* progress) -{ +size_t qpEncoder::encode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress +) { + in.reset(); // may not work... const size_t propMaxLineLength = @@ -189,14 +190,15 @@ size_t qpEncoder::encode(utility::inputStream& in, size_t total = 0; size_t inTotal = 0; - if (progress) + if (progress) { progress->start(0); + } + + while (bufferPos < bufferLength || !in.eof()) { - while (bufferPos < bufferLength || !in.eof()) - { // Flush current output buffer - if (outBufferPos + 6 >= static_cast (sizeof(outBuffer))) - { + if (outBufferPos + 6 >= static_cast (sizeof(outBuffer))) { + QP_WRITE(out, outBuffer, outBufferPos); total += outBufferPos; @@ -204,146 +206,146 @@ size_t qpEncoder::encode(utility::inputStream& in, } // Need to get more data? - if (bufferPos >= bufferLength) - { + if (bufferPos >= bufferLength) { + bufferLength = in.read(buffer, sizeof(buffer)); bufferPos = 0; // No more data - if (bufferLength == 0) + if (bufferLength == 0) { break; + } } // Get the next char and encode it const byte_t c = buffer[bufferPos++]; - if (rfc2047) - { - if (c >= 128 || sm_RFC2047EncodeTable[c] != 0) - { - if (c == 32) // space - { + if (rfc2047) { + + if (c >= 128 || sm_RFC2047EncodeTable[c] != 0) { + + if (c == 32) { // space + // RFC-2047, Page 5, 4.2. The "Q" encoding: // << The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be // represented as "_" (underscore, ASCII 95.). >> outBuffer[outBufferPos++] = '_'; ++curCol; - } - else - { + + } else { + // Other characters: '=' + hexadecimal encoding QP_ENCODE_HEX(c); } - } - else - { + + } else { + // No encoding outBuffer[outBufferPos++] = c; ++curCol; } - } - else - { - switch (c) - { - case 46: // . - { - if (curCol == 0) - { - // If a '.' appears at the beginning of a line, we encode it to - // to avoid problems with SMTP servers... ("\r\n.\r\n" means the - // end of data transmission). - QP_ENCODE_HEX('.'); - continue; - } - outBuffer[outBufferPos++] = '.'; - ++curCol; - break; - } - case 32: // space - { - // Need to get more data? - if (bufferPos >= bufferLength) - { - bufferLength = in.read(buffer, sizeof(buffer)); - bufferPos = 0; - } + } else { - // Spaces cannot appear at the end of a line. So, encode the space. - if (bufferPos >= bufferLength || - (buffer[bufferPos] == '\r' || buffer[bufferPos] == '\n')) - { - QP_ENCODE_HEX(' '); - } - else - { - outBuffer[outBufferPos++] = ' '; + switch (c) { + + case 46: { // . + + if (curCol == 0) { + // If a '.' appears at the beginning of a line, we encode it to + // to avoid problems with SMTP servers... ("\r\n.\r\n" means the + // end of data transmission). + QP_ENCODE_HEX('.'); + continue; + } + + outBuffer[outBufferPos++] = '.'; ++curCol; + break; } + case 32: { // space - break; - } - case 9: // TAB - { - QP_ENCODE_HEX(c); - break; - } - case 13: // CR - case 10: // LF - { - // RFC-2045/6.7(4) + // Need to get more data? + if (bufferPos >= bufferLength) { + bufferLength = in.read(buffer, sizeof(buffer)); + bufferPos = 0; + } - // Text data - if (text && !rfc2047) - { - outBuffer[outBufferPos++] = c; - ++curCol; + // Spaces cannot appear at the end of a line. So, encode the space. + if (bufferPos >= bufferLength || + (buffer[bufferPos] == '\r' || buffer[bufferPos] == '\n')) { - if (c == 10) - curCol = 0; // reset current line length + QP_ENCODE_HEX(' '); + + } else { + + outBuffer[outBufferPos++] = ' '; + ++curCol; + } + + break; } - // Binary data - else - { + case 9: { // TAB + QP_ENCODE_HEX(c); + break; } + case 13: // CR + case 10: { // LF - break; - } - case 61: // = - { - QP_ENCODE_HEX('='); - break; - } - /* - Rule #2: (Literal representation) Octets with decimal values of 33 - through 60 inclusive, and 62 through 126, inclusive, MAY be - represented as the ASCII characters which correspond to those - octets (EXCLAMATION POINT through LESS THAN, and GREATER THAN - through TILDE, respectively). - */ - default: + // RFC-2045/6.7(4) - //if ((c >= 33 && c <= 60) || (c >= 62 && c <= 126)) - if (c >= 33 && c <= 126 && c != 61 && c != 63) - { - outBuffer[outBufferPos++] = c; - ++curCol; - } - // Other characters: '=' + hexadecimal encoding - else - { - QP_ENCODE_HEX(c); + // Text data + if (text && !rfc2047) { + + outBuffer[outBufferPos++] = c; + ++curCol; + + if (c == 10) { + curCol = 0; // reset current line length + } + + // Binary data + } else { + + QP_ENCODE_HEX(c); + } + + break; } + case 61: { // = - break; + QP_ENCODE_HEX('='); + break; + } + /* + Rule #2: (Literal representation) Octets with decimal values of 33 + through 60 inclusive, and 62 through 126, inclusive, MAY be + represented as the ASCII characters which correspond to those + octets (EXCLAMATION POINT through LESS THAN, and GREATER THAN + through TILDE, respectively). + */ + default: + + //if ((c >= 33 && c <= 60) || (c >= 62 && c <= 126)) + if (c >= 33 && c <= 126 && c != 61 && c != 63) { + + outBuffer[outBufferPos++] = c; + ++curCol; + + // Other characters: '=' + hexadecimal encoding + } else { + + QP_ENCODE_HEX(c); + } + + break; } // switch (c) // Soft line break : "=\r\n" - if (cutLines && curCol >= maxLineLength - 1) - { + if (cutLines && curCol >= maxLineLength - 1) { + outBuffer[outBufferPos] = '='; outBuffer[outBufferPos + 1] = '\r'; outBuffer[outBufferPos + 2] = '\n'; @@ -356,27 +358,31 @@ size_t qpEncoder::encode(utility::inputStream& in, ++inTotal; - if (progress) + if (progress) { progress->progress(inTotal, inTotal); + } } // Flush remaining output buffer - if (outBufferPos != 0) - { + if (outBufferPos != 0) { QP_WRITE(out, outBuffer, outBufferPos); total += outBufferPos; } - if (progress) + if (progress) { progress->stop(inTotal); + } - return (total); + return total; } -size_t qpEncoder::decode(utility::inputStream& in, - utility::outputStream& out, utility::progressListener* progress) -{ +size_t qpEncoder::decode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress +) { + in.reset(); // may not work... // Process the data @@ -392,11 +398,11 @@ size_t qpEncoder::decode(utility::inputStream& in, size_t total = 0; size_t inTotal = 0; - while (bufferPos < bufferLength || !in.eof()) - { + while (bufferPos < bufferLength || !in.eof()) { + // Flush current output buffer - if (outBufferPos >= sizeof(outBuffer)) - { + if (outBufferPos >= sizeof(outBuffer)) { + QP_WRITE(out, outBuffer, outBufferPos); total += outBufferPos; @@ -404,14 +410,15 @@ size_t qpEncoder::decode(utility::inputStream& in, } // Need to get more data? - if (bufferPos >= bufferLength) - { + if (bufferPos >= bufferLength) { + bufferLength = in.read(buffer, sizeof(buffer)); bufferPos = 0; // No more data - if (bufferLength == 0) + if (bufferLength == 0) { break; + } } // Decode the next sequence (hex-encoded byte or printable character) @@ -419,125 +426,124 @@ size_t qpEncoder::decode(utility::inputStream& in, ++inTotal; - switch (c) - { - case '=': - { - if (bufferPos >= bufferLength) - { - bufferLength = in.read(buffer, sizeof(buffer)); - bufferPos = 0; + switch (c) { + + case '=': { + + if (bufferPos >= bufferLength) { + bufferLength = in.read(buffer, sizeof(buffer)); + bufferPos = 0; + } + + if (bufferPos < bufferLength) { + + c = buffer[bufferPos++]; + + ++inTotal; + + switch (c) { + + // Ignore soft line break ("=\r\n" or "=\n") + case '\r': + + // Read one byte more + if (bufferPos >= bufferLength) { + bufferLength = in.read(buffer, sizeof(buffer)); + bufferPos = 0; + } + + if (bufferPos < bufferLength) { + ++bufferPos; + ++inTotal; + } + + break; + + case '\n': + + break; + + // Hex-encoded char + default: + { + // We need another byte... + if (bufferPos >= bufferLength) { + bufferLength = in.read(buffer, sizeof(buffer)); + bufferPos = 0; + } + + if (bufferPos < bufferLength) { + + const byte_t next = buffer[bufferPos++]; + + ++inTotal; + + const byte_t value = static_cast ( + sm_hexDecodeTable[c] * 16 + sm_hexDecodeTable[next] + ); + + outBuffer[outBufferPos++] = value; + + } else { + + // Premature end-of-data + } + + break; + } + + } + + } else { + + // Premature end-of-data + } + + break; } + case '_': { - if (bufferPos < bufferLength) - { - c = buffer[bufferPos++]; - - ++inTotal; - - switch (c) - { - // Ignore soft line break ("=\r\n" or "=\n") - case '\r': - - // Read one byte more - if (bufferPos >= bufferLength) - { - bufferLength = in.read(buffer, sizeof(buffer)); - bufferPos = 0; - } - - if (bufferPos < bufferLength) - { - ++bufferPos; - ++inTotal; - } - - break; - - case '\n': - - break; - - // Hex-encoded char - default: - { - // We need another byte... - if (bufferPos >= bufferLength) - { - bufferLength = in.read(buffer, sizeof(buffer)); - bufferPos = 0; - } - - if (bufferPos < bufferLength) - { - const byte_t next = buffer[bufferPos++]; - - ++inTotal; - - const byte_t value = static_cast - (sm_hexDecodeTable[c] * 16 + sm_hexDecodeTable[next]); - - outBuffer[outBufferPos++] = value; - } - else - { - // Premature end-of-data - } + if (rfc2047) { + // RFC-2047, Page 5, 4.2. The "Q" encoding: + // << Note that the "_" always represents hexadecimal 20, even if the SPACE + // character occupies a different code position in the character set in use. >> + outBuffer[outBufferPos++] = 0x20; break; } - } - } - else - { - // Premature end-of-data + outBuffer[outBufferPos++] = c; + break; } + default: { - break; - } - case '_': - { - if (rfc2047) - { - // RFC-2047, Page 5, 4.2. The "Q" encoding: - // << Note that the "_" always represents hexadecimal 20, even if the SPACE - // character occupies a different code position in the character set in use. >> - outBuffer[outBufferPos++] = 0x20; + outBuffer[outBufferPos++] = c; break; } - outBuffer[outBufferPos++] = c; - break; - } - default: - { - outBuffer[outBufferPos++] = c; } - } - - if (progress) + if (progress) { progress->progress(inTotal, inTotal); + } } // Flush remaining output buffer - if (outBufferPos != 0) - { + if (outBufferPos != 0) { QP_WRITE(out, outBuffer, outBufferPos); total += outBufferPos; } - if (progress) + if (progress) { progress->stop(inTotal); + } - return (total); + return total; } -size_t qpEncoder::getEncodedSize(const size_t n) const -{ +size_t qpEncoder::getEncodedSize(const size_t n) const { + const size_t propMaxLineLength = getProperties().getProperty ("maxlinelength", static_cast (-1)); @@ -550,8 +556,8 @@ size_t qpEncoder::getEncodedSize(const size_t n) const } -size_t qpEncoder::getDecodedSize(const size_t n) const -{ +size_t qpEncoder::getDecodedSize(const size_t n) const { + // Worst case: 1 byte of input equals 1 byte of output return n; } diff --git a/src/vmime/utility/encoder/qpEncoder.hpp b/src/vmime/utility/encoder/qpEncoder.hpp index c666795b..21263a6b 100644 --- a/src/vmime/utility/encoder/qpEncoder.hpp +++ b/src/vmime/utility/encoder/qpEncoder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,15 +35,23 @@ namespace encoder { /** Quoted-printable encoder. */ +class VMIME_EXPORT qpEncoder : public encoder { -class VMIME_EXPORT qpEncoder : public encoder -{ public: qpEncoder(); - size_t encode(utility::inputStream& in, utility::outputStream& out, utility::progressListener* progress = NULL); - size_t decode(utility::inputStream& in, utility::outputStream& out, utility::progressListener* progress = NULL); + size_t encode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress = NULL + ); + + size_t decode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress = NULL + ); const std::vector getAvailableProperties() const; diff --git a/src/vmime/utility/encoder/sevenBitEncoder.cpp b/src/vmime/utility/encoder/sevenBitEncoder.cpp index 7c76d73f..999b11e5 100644 --- a/src/vmime/utility/encoder/sevenBitEncoder.cpp +++ b/src/vmime/utility/encoder/sevenBitEncoder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,8 +29,8 @@ namespace utility { namespace encoder { -sevenBitEncoder::sevenBitEncoder() -{ +sevenBitEncoder::sevenBitEncoder() { + } diff --git a/src/vmime/utility/encoder/sevenBitEncoder.hpp b/src/vmime/utility/encoder/sevenBitEncoder.hpp index d260cc7b..37f84a61 100644 --- a/src/vmime/utility/encoder/sevenBitEncoder.hpp +++ b/src/vmime/utility/encoder/sevenBitEncoder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,7 +35,6 @@ namespace encoder { /** 7-bit encoder. */ - class VMIME_EXPORT sevenBitEncoder : public noopEncoder { public: diff --git a/src/vmime/utility/encoder/uuEncoder.cpp b/src/vmime/utility/encoder/uuEncoder.cpp index 5ee2c2b1..24dcdc8b 100644 --- a/src/vmime/utility/encoder/uuEncoder.cpp +++ b/src/vmime/utility/encoder/uuEncoder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,16 +30,16 @@ namespace utility { namespace encoder { -uuEncoder::uuEncoder() -{ +uuEncoder::uuEncoder() { + getProperties()["mode"] = 644; getProperties()["filename"] = "no_name"; getProperties()["maxlinelength"] = 46; } -const std::vector uuEncoder::getAvailableProperties() const -{ +const std::vector uuEncoder::getAvailableProperties() const { + std::vector list(encoder::getAvailableProperties()); list.push_back("maxlinelength"); @@ -47,26 +47,29 @@ const std::vector uuEncoder::getAvailableProperties() const list.push_back("mode"); list.push_back("filename"); - return (list); + return list; } // This is the character encoding function to make a character printable -static inline byte_t UUENCODE(const unsigned int c) -{ +static inline byte_t UUENCODE(const unsigned int c) { + return static_cast ((c & 077) + ' '); } // Single character decoding -static inline unsigned int UUDECODE(const unsigned int c) -{ +static inline unsigned int UUDECODE(const unsigned int c) { + return (c - ' ') & 077; } -size_t uuEncoder::encode(utility::inputStream& in, - utility::outputStream& out, utility::progressListener* progress) -{ +size_t uuEncoder::encode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress +) { + in.reset(); // may not work... const string propFilename = getProperties().getProperty ("filename", ""); @@ -81,8 +84,7 @@ size_t uuEncoder::encode(utility::inputStream& in, // Output the prelude text ("begin [mode] [filename]") out << "begin"; - if (!propFilename.empty()) - { + if (!propFilename.empty()) { out << " " << propMode << " " << propFilename; total += 2 + propMode.length() + propFilename.length(); } @@ -94,11 +96,12 @@ size_t uuEncoder::encode(utility::inputStream& in, byte_t inBuffer[64]; byte_t outBuffer[64]; - if (progress) + if (progress) { progress->start(0); + } + + while (!in.eof()) { - while (!in.eof()) - { // Process up to 45 characters per line std::fill(inBuffer, inBuffer + sizeof(inBuffer), 0); @@ -108,8 +111,8 @@ size_t uuEncoder::encode(utility::inputStream& in, size_t j = 1; - for (size_t i = 0 ; i < inLength ; i += 3, j += 4) - { + for (size_t i = 0 ; i < inLength ; i += 3, j += 4) { + const byte_t c1 = inBuffer[i]; const byte_t c2 = inBuffer[i + 1]; const byte_t c3 = inBuffer[i + 2]; @@ -128,23 +131,28 @@ size_t uuEncoder::encode(utility::inputStream& in, total += j + 2; inTotal += inLength; - if (progress) + if (progress) { progress->progress(inTotal, inTotal); + } } out << "end\r\n"; total += 5; - if (progress) + if (progress) { progress->stop(inTotal); + } - return (total); + return total; } -size_t uuEncoder::decode(utility::inputStream& in, - utility::outputStream& out, utility::progressListener* progress) -{ +size_t uuEncoder::decode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress +) { + in.reset(); // may not work... // Process the data @@ -158,128 +166,131 @@ size_t uuEncoder::decode(utility::inputStream& in, std::fill(inBuffer, inBuffer + sizeof(inBuffer), 0); - if (progress) + if (progress) { progress->start(0); + } + + while (!stop && !in.eof()) { - while (!stop && !in.eof()) - { // Get the line length byte_t lengthChar; - if (in.read(&lengthChar, 1) == 0) + if (in.read(&lengthChar, 1) == 0) { break; + } const size_t outLength = UUDECODE(lengthChar); const size_t inLength = std::min((outLength * 4) / 3, static_cast (64)); size_t inPos = 0; - switch (lengthChar) - { - case ' ': - case '\t': - case '\r': - case '\n': - { - // Ignore - continue; - } - case 'b': - { - // Read 5 characters more to check for begin ("begin ...\r\n" or "begin ...\n") - inPos = in.read(inBuffer, 5); + switch (lengthChar) { - if (inPos == 5 && - inBuffer[0] == 'e' && - inBuffer[1] == 'g' && - inBuffer[2] == 'i' && - inBuffer[3] == 'n' && - parserHelpers::isSpace(inBuffer[4])) - { - inTotal += 5; - - byte_t c = 0; - - size_t count = 0; - byte_t buffer[512]; - - while (count < sizeof(buffer) - 1 && in.read(&c, 1) == 1) - { - if (c == '\n') - break; - - buffer[count++] = c; - } - - inTotal += count; - - if (c != '\n') - { - // OOPS! Weird line. Don't try to decode more... - - if (progress) - progress->stop(inTotal); - - return (total); - } - - // Parse filename and mode - if (count > 0) - { - buffer[count] = '\0'; - - byte_t* p = buffer; - - while (*p && parserHelpers::isSpace(*p)) ++p; - - byte_t* modeStart = buffer; - - while (*p && !parserHelpers::isSpace(*p)) ++p; - - getResults()["mode"] = string(modeStart, p); - - while (*p && parserHelpers::isSpace(*p)) ++p; - - byte_t* filenameStart = buffer; - - while (*p && !(*p == '\r' || *p == '\n')) ++p; - - getResults()["filename"] = string(filenameStart, p); - } - // No filename or mode specified - else - { - getResults()["filename"] = "untitled"; - getResults()["mode"] = 644; - } + case ' ': + case '\t': + case '\r': + case '\n': { + // Ignore continue; } + case 'b': { - break; - } - case 'e': - { - // Read 3 characters more to check for end ("end\r\n" or "end\n") - inPos = in.read(inBuffer, 3); + // Read 5 characters more to check for begin ("begin ...\r\n" or "begin ...\n") + inPos = in.read(inBuffer, 5); - if (inPos == 3 && - inBuffer[0] == 'n' && - inBuffer[1] == 'd' && - (inBuffer[2] == '\r' || inBuffer[2] == '\n')) - { - stop = true; - inTotal += 3; - continue; + if (inPos == 5 && + inBuffer[0] == 'e' && + inBuffer[1] == 'g' && + inBuffer[2] == 'i' && + inBuffer[3] == 'n' && + parserHelpers::isSpace(inBuffer[4])) { + + inTotal += 5; + + byte_t c = 0; + + size_t count = 0; + byte_t buffer[512]; + + while (count < sizeof(buffer) - 1 && in.read(&c, 1) == 1) { + + if (c == '\n') { + break; + } + + buffer[count++] = c; + } + + inTotal += count; + + if (c != '\n') { + + // OOPS! Weird line. Don't try to decode more... + + if (progress) { + progress->stop(inTotal); + } + + return total; + } + + // Parse filename and mode + if (count > 0) { + + buffer[count] = '\0'; + + byte_t* p = buffer; + + while (*p && parserHelpers::isSpace(*p)) ++p; + + byte_t* modeStart = buffer; + + while (*p && !parserHelpers::isSpace(*p)) ++p; + + getResults()["mode"] = string(modeStart, p); + + while (*p && parserHelpers::isSpace(*p)) ++p; + + byte_t* filenameStart = buffer; + + while (*p && !(*p == '\r' || *p == '\n')) ++p; + + getResults()["filename"] = string(filenameStart, p); + + // No filename or mode specified + } else { + + getResults()["filename"] = "untitled"; + getResults()["mode"] = 644; + } + + continue; + } + + break; } + case 'e': { - break; - } + // Read 3 characters more to check for end ("end\r\n" or "end\n") + inPos = in.read(inBuffer, 3); + + if (inPos == 3 && + inBuffer[0] == 'n' && + inBuffer[1] == 'd' && + (inBuffer[2] == '\r' || inBuffer[2] == '\n')) { + + stop = true; + inTotal += 3; + continue; + } + + break; + } } // Read encoded data - if (in.read(inBuffer + inPos, inLength - inPos) != inLength - inPos) - { + if (in.read(inBuffer + inPos, inLength - inPos) != inLength - inPos) { // Premature end of data break; } @@ -287,8 +298,8 @@ size_t uuEncoder::decode(utility::inputStream& in, inTotal += (inLength - inPos); // Decode data - for (size_t i = 0, j = 0 ; i < inLength ; i += 4, j += 3) - { + for (size_t i = 0, j = 0 ; i < inLength ; i += 4, j += 3) { + const byte_t c1 = inBuffer[i]; const byte_t c2 = inBuffer[i + 1]; const byte_t c3 = inBuffer[i + 2]; @@ -296,12 +307,15 @@ size_t uuEncoder::decode(utility::inputStream& in, const size_t n = std::min(inLength - i, static_cast (3)); - if (n >= 3) + if (n >= 3) { outBuffer[j + 2] = static_cast (UUDECODE(c3) << 6 | UUDECODE(c4)); - if (n >= 2) + } + if (n >= 2) { outBuffer[j + 1] = static_cast (UUDECODE(c2) << 4 | UUDECODE(c3) >> 2); - if (n >= 1) + } + if (n >= 1) { outBuffer[j] = static_cast (UUDECODE(c1) << 2 | UUDECODE(c2) >> 4); + } total += n; } @@ -310,19 +324,21 @@ size_t uuEncoder::decode(utility::inputStream& in, std::fill(inBuffer, inBuffer + sizeof(inBuffer), 0); - if (progress) + if (progress) { progress->progress(inTotal, inTotal); + } } - if (progress) + if (progress) { progress->stop(inTotal); + } - return (total); + return total; } -size_t uuEncoder::getEncodedSize(const size_t n) const -{ +size_t uuEncoder::getEncodedSize(const size_t n) const { + // 3 bytes of input provide 4 bytes of output. // Count CRLF (2 bytes) for each line of 45 characters. // Also reserve some space for header and footer. @@ -330,8 +346,8 @@ size_t uuEncoder::getEncodedSize(const size_t n) const } -size_t uuEncoder::getDecodedSize(const size_t n) const -{ +size_t uuEncoder::getDecodedSize(const size_t n) const { + // 4 bytes of input provide 3 bytes of output return (n * 3) / 4; } diff --git a/src/vmime/utility/encoder/uuEncoder.hpp b/src/vmime/utility/encoder/uuEncoder.hpp index 7365263c..841cf660 100644 --- a/src/vmime/utility/encoder/uuEncoder.hpp +++ b/src/vmime/utility/encoder/uuEncoder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,15 +35,23 @@ namespace encoder { /** UUEncode encoder. */ +class VMIME_EXPORT uuEncoder : public encoder { -class VMIME_EXPORT uuEncoder : public encoder -{ public: uuEncoder(); - size_t encode(utility::inputStream& in, utility::outputStream& out, utility::progressListener* progress = NULL); - size_t decode(utility::inputStream& in, utility::outputStream& out, utility::progressListener* progress = NULL); + size_t encode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress = NULL + ); + + size_t decode( + utility::inputStream& in, + utility::outputStream& out, + utility::progressListener* progress = NULL + ); const std::vector getAvailableProperties() const; diff --git a/src/vmime/utility/file.hpp b/src/vmime/utility/file.hpp index c0ba2c5b..6e0605e1 100644 --- a/src/vmime/utility/file.hpp +++ b/src/vmime/utility/file.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,9 +43,8 @@ class file; /** File list iterator (see file::getFiles). */ +class VMIME_EXPORT fileIterator : public object { -class VMIME_EXPORT fileIterator : public object -{ public: virtual ~fileIterator() { } @@ -67,9 +66,8 @@ public: /** Write to a file. */ +class VMIME_EXPORT fileWriter : public object { -class VMIME_EXPORT fileWriter : public object -{ public: virtual ~fileWriter() { } @@ -80,9 +78,8 @@ public: /** Read from a file. */ +class VMIME_EXPORT fileReader : public object { -class VMIME_EXPORT fileReader : public object -{ public: virtual ~fileReader() { } @@ -93,9 +90,8 @@ public: /** Abstract representation of a file or directory. */ +class VMIME_EXPORT file : public object { -class VMIME_EXPORT file : public object -{ public: typedef utility::path path; @@ -213,9 +209,8 @@ private: /** Constructs 'file' objects. */ +class VMIME_EXPORT fileSystemFactory : public object { -class VMIME_EXPORT fileSystemFactory : public object -{ public: virtual ~fileSystemFactory() { } diff --git a/src/vmime/utility/filteredStream.cpp b/src/vmime/utility/filteredStream.cpp index 99ba13fd..d5ec17b7 100644 --- a/src/vmime/utility/filteredStream.cpp +++ b/src/vmime/utility/filteredStream.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,16 +32,16 @@ namespace utility { // filteredInputStream -size_t filteredInputStream::getBlockSize() -{ +size_t filteredInputStream::getBlockSize() { + return std::min(inputStream::getBlockSize(), getPreviousInputStream().getBlockSize()); } // filteredOutputStream -size_t filteredOutputStream::getBlockSize() -{ +size_t filteredOutputStream::getBlockSize() { + return std::min(outputStream::getBlockSize(), getNextOutputStream().getBlockSize()); } @@ -49,25 +49,27 @@ size_t filteredOutputStream::getBlockSize() // dotFilteredInputStream dotFilteredInputStream::dotFilteredInputStream(inputStream& is) - : m_stream(is), m_previousChar2('\0'), m_previousChar1('\0') -{ + : m_stream(is), + m_previousChar2('\0'), + m_previousChar1('\0') { + } -inputStream& dotFilteredInputStream::getPreviousInputStream() -{ - return (m_stream); +inputStream& dotFilteredInputStream::getPreviousInputStream() { + + return m_stream; } -bool dotFilteredInputStream::eof() const -{ - return (m_stream.eof()); +bool dotFilteredInputStream::eof() const { + + return m_stream.eof(); } -void dotFilteredInputStream::reset() -{ +void dotFilteredInputStream::reset() { + m_previousChar2 = '\0'; m_previousChar1 = '\0'; @@ -75,8 +77,8 @@ void dotFilteredInputStream::reset() } -size_t dotFilteredInputStream::read(byte_t* const data, const size_t count) -{ +size_t dotFilteredInputStream::read(byte_t* const data, const size_t count) { + const size_t read = m_stream.read(data, count); const byte_t* readPtr = data; @@ -90,16 +92,16 @@ size_t dotFilteredInputStream::read(byte_t* const data, const size_t count) byte_t prevChar1 = m_previousChar1; // Replace "\n.." with "\n." - while (readPtr < end) - { - if (*readPtr == '.' && prevChar2 == '\n' && prevChar1 == '.') - { + while (readPtr < end) { + + if (*readPtr == '.' && prevChar2 == '\n' && prevChar1 == '.') { + // Ignore last dot prevChar2 = '\0'; prevChar1 = '.'; - } - else - { + + } else { + *writePtr = *readPtr; ++writePtr; @@ -115,12 +117,12 @@ size_t dotFilteredInputStream::read(byte_t* const data, const size_t count) m_previousChar2 = prevChar2; m_previousChar1 = prevChar1; - return (written); + return written; } -size_t dotFilteredInputStream::skip(const size_t /* count */) -{ +size_t dotFilteredInputStream::skip(const size_t /* count */) { + // Skipping bytes is not supported return 0; } @@ -129,31 +131,33 @@ size_t dotFilteredInputStream::skip(const size_t /* count */) // dotFilteredOutputStream dotFilteredOutputStream::dotFilteredOutputStream(outputStream& os) - : m_stream(os), m_previousChar('\0'), m_start(true) -{ + : m_stream(os), + m_previousChar('\0'), + m_start(true) { + } -outputStream& dotFilteredOutputStream::getNextOutputStream() -{ - return (m_stream); +outputStream& dotFilteredOutputStream::getNextOutputStream() { + + return m_stream; } -void dotFilteredOutputStream::writeImpl - (const byte_t* const data, const size_t count) -{ - if (count == 0) +void dotFilteredOutputStream::writeImpl(const byte_t* const data, const size_t count) { + + if (count == 0) { return; + } const byte_t* pos = data; const byte_t* end = data + count; const byte_t* start = data; - if (m_previousChar == '.') - { - if (data[0] == '\n' || data[0] == '\r') - { + if (m_previousChar == '.') { + + if (data[0] == '\n' || data[0] == '\r') { + m_stream.write(".", 1); // extra m_stream.write(data, 1); @@ -162,26 +166,26 @@ void dotFilteredOutputStream::writeImpl } // Replace "\n." with "\n.." - while ((pos = std::find(pos, end, '.')) != end) - { - const byte_t previousChar = - (pos == data ? m_previousChar : *(pos - 1)); + while ((pos = std::find(pos, end, '.')) != end) { + + const byte_t previousChar = (pos == data ? m_previousChar : *(pos - 1)); + + if (previousChar == '\n') { - if (previousChar == '\n') - { m_stream.write(start, pos - start); m_stream.write("..", 2); start = pos + 1; - } - else if (pos == data && m_start) // at the beginning of content - { + + } else if (pos == data && m_start) { // at the beginning of content + m_stream.write(start, pos - start); - if (pos + 1 < end && (*(pos + 1) == '\n' || *(pos + 1) == '\r')) + if (pos + 1 < end && (*(pos + 1) == '\n' || *(pos + 1) == '\r')) { m_stream.write("..", 2); - else + } else { m_stream.write(".", 1); + } start = pos + 1; } @@ -195,15 +199,15 @@ void dotFilteredOutputStream::writeImpl } -void dotFilteredOutputStream::flush() -{ +void dotFilteredOutputStream::flush() { + // Do nothing m_stream.flush(); } -size_t dotFilteredOutputStream::getBlockSize() -{ +size_t dotFilteredOutputStream::getBlockSize() { + return m_stream.getBlockSize(); } @@ -211,22 +215,23 @@ size_t dotFilteredOutputStream::getBlockSize() // CRLFToLFFilteredOutputStream CRLFToLFFilteredOutputStream::CRLFToLFFilteredOutputStream(outputStream& os) - : m_stream(os), m_previousChar('\0') -{ + : m_stream(os), + m_previousChar('\0') { + } -outputStream& CRLFToLFFilteredOutputStream::getNextOutputStream() -{ - return (m_stream); +outputStream& CRLFToLFFilteredOutputStream::getNextOutputStream() { + + return m_stream; } -void CRLFToLFFilteredOutputStream::writeImpl - (const byte_t* const data, const size_t count) -{ - if (count == 0) +void CRLFToLFFilteredOutputStream::writeImpl(const byte_t* const data, const size_t count) { + + if (count == 0) { return; + } const byte_t* pos = data; const byte_t* end = data + count; @@ -235,25 +240,24 @@ void CRLFToLFFilteredOutputStream::writeImpl // Warning: if the whole buffer finishes with '\r', this // last character will not be written back if flush() is // not called - if (m_previousChar == '\r') - { - if (*pos != '\n') - { + if (m_previousChar == '\r') { + + if (*pos != '\n') { m_stream.write("\r", 1); // write back \r m_previousChar = *pos; } } // Replace "\r\n" (CRLF) with "\n" (LF) - while ((pos = std::find(pos, end, '\n')) != end) - { - const byte_t previousChar = - (pos == data ? m_previousChar : *(pos - 1)); + while ((pos = std::find(pos, end, '\n')) != end) { - if (previousChar == '\r') - { - if (pos != start) + const byte_t previousChar = (pos == data ? m_previousChar : *(pos - 1)); + + if (previousChar == '\r') { + + if (pos != start) { m_stream.write(start, pos - 1 - start); // do not write \r + } m_stream.write("\n", 1); @@ -263,29 +267,29 @@ void CRLFToLFFilteredOutputStream::writeImpl ++pos; } - if (data[count - 1] == '\r') - { + if (data[count - 1] == '\r') { + m_stream.write(start, end - start - 1); m_previousChar = '\r'; - } - else - { + + } else { + m_stream.write(start, end - start); m_previousChar = data[count - 1]; } } -void CRLFToLFFilteredOutputStream::flush() -{ +void CRLFToLFFilteredOutputStream::flush() { + m_stream.flush(); // TODO } -size_t CRLFToLFFilteredOutputStream::getBlockSize() -{ +size_t CRLFToLFFilteredOutputStream::getBlockSize() { + return m_stream.getBlockSize(); } @@ -293,22 +297,23 @@ size_t CRLFToLFFilteredOutputStream::getBlockSize() // LFToCRLFFilteredOutputStream LFToCRLFFilteredOutputStream::LFToCRLFFilteredOutputStream(outputStream& os) - : m_stream(os), m_previousChar('\0') -{ + : m_stream(os), + m_previousChar('\0') { + } -outputStream& LFToCRLFFilteredOutputStream::getNextOutputStream() -{ - return (m_stream); +outputStream& LFToCRLFFilteredOutputStream::getNextOutputStream() { + + return m_stream; } -void LFToCRLFFilteredOutputStream::writeImpl - (const byte_t* const data, const size_t count) +void LFToCRLFFilteredOutputStream::writeImpl(const byte_t* const data, const size_t count) { - if (count == 0) + if (count == 0) { return; + } string buffer; buffer.reserve(count); @@ -318,31 +323,30 @@ void LFToCRLFFilteredOutputStream::writeImpl byte_t previousChar = m_previousChar; - while (pos < end) - { - switch (*pos) - { - case '\r': + while (pos < end) { - buffer.append(1, '\r'); - buffer.append(1, '\n'); + switch (*pos) { - break; + case '\r': - case '\n': - - if (previousChar != '\r') - { buffer.append(1, '\r'); buffer.append(1, '\n'); - } - break; + break; - default: + case '\n': - buffer.append(1, *pos); - break; + if (previousChar != '\r') { + buffer.append(1, '\r'); + buffer.append(1, '\n'); + } + + break; + + default: + + buffer.append(1, *pos); + break; } previousChar = *pos; @@ -355,14 +359,14 @@ void LFToCRLFFilteredOutputStream::writeImpl } -void LFToCRLFFilteredOutputStream::flush() -{ +void LFToCRLFFilteredOutputStream::flush() { + m_stream.flush(); } -size_t LFToCRLFFilteredOutputStream::getBlockSize() -{ +size_t LFToCRLFFilteredOutputStream::getBlockSize() { + return m_stream.getBlockSize(); } @@ -370,11 +374,9 @@ size_t LFToCRLFFilteredOutputStream::getBlockSize() // stopSequenceFilteredInputStream <1> template <> -size_t stopSequenceFilteredInputStream <1>::read - (byte_t* const data, const size_t count) -{ - if (eof() || m_stream.eof()) - { +size_t stopSequenceFilteredInputStream <1>::read(byte_t* const data, const size_t count) { + + if (eof() || m_stream.eof()) { m_eof = true; return 0; } @@ -384,18 +386,17 @@ size_t stopSequenceFilteredInputStream <1>::read byte_t* pos = std::find(data, end, m_sequence[0]); - if (pos == end) - { - return (read); - } - else - { + if (pos == end) { + + return read; + + } else { + m_found = 1; - return (pos - data); + return pos - data; } } } // utility } // vmime - diff --git a/src/vmime/utility/filteredStream.hpp b/src/vmime/utility/filteredStream.hpp index e01e5e9d..2414c54d 100644 --- a/src/vmime/utility/filteredStream.hpp +++ b/src/vmime/utility/filteredStream.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,9 +37,7 @@ namespace utility { /** A stream whose input is filtered. */ - -class VMIME_EXPORT filteredInputStream : public inputStream -{ +class VMIME_EXPORT filteredInputStream : public inputStream { public: virtual size_t getBlockSize(); @@ -54,9 +52,8 @@ public: /** A stream whose output is filtered. */ +class VMIME_EXPORT filteredOutputStream : public outputStream { -class VMIME_EXPORT filteredOutputStream : public outputStream -{ public: virtual size_t getBlockSize(); @@ -72,9 +69,8 @@ public: /** A filtered input stream which replaces "\n.." * sequences with "\n." sequences. */ +class VMIME_EXPORT dotFilteredInputStream : public filteredInputStream { -class VMIME_EXPORT dotFilteredInputStream : public filteredInputStream -{ public: /** Construct a new filter for the specified input stream. @@ -105,9 +101,8 @@ private: /** A filtered output stream which replaces "\n." * sequences with "\n.." sequences. */ +class VMIME_EXPORT dotFilteredOutputStream : public filteredOutputStream { -class VMIME_EXPORT dotFilteredOutputStream : public filteredOutputStream -{ public: /** Construct a new filter for the specified output stream. @@ -137,9 +132,8 @@ private: /** A filtered output stream which replaces CRLF sequences * with single LF characters. */ +class VMIME_EXPORT CRLFToLFFilteredOutputStream : public filteredOutputStream { -class VMIME_EXPORT CRLFToLFFilteredOutputStream : public filteredOutputStream -{ public: /** Construct a new filter for the specified output stream. @@ -160,7 +154,7 @@ protected: private: - outputStream& m_stream; + outputStream& m_stream; byte_t m_previousChar; }; @@ -168,9 +162,8 @@ private: /** A filtered output stream which replaces CR or LF characters * with CRLF sequences. */ +class VMIME_EXPORT LFToCRLFFilteredOutputStream : public filteredOutputStream { -class VMIME_EXPORT LFToCRLFFilteredOutputStream : public filteredOutputStream -{ public: /** Construct a new filter for the specified output stream. @@ -199,10 +192,9 @@ private: /** A filtered input stream which stops when a specified sequence * is found (eof() method will return 'true'). */ - template -class VMIME_EXPORT stopSequenceFilteredInputStream : public filteredInputStream -{ +class VMIME_EXPORT stopSequenceFilteredInputStream : public filteredInputStream { + public: /** Construct a new filter for the specified input stream. @@ -211,8 +203,11 @@ public: * @param sequence sequence on which to stop */ stopSequenceFilteredInputStream(inputStream& is, const byte_t* sequence) - : m_stream(is), m_sequence(sequence), m_found(0), m_eof(false) - { + : m_stream(is), + m_sequence(sequence), + m_found(0), + m_eof(false) { + } /** Construct a new filter for the specified input stream. @@ -221,49 +216,53 @@ public: * @param sequence sequence on which to stop */ stopSequenceFilteredInputStream(inputStream& is, const char* sequence) - : m_stream(is), m_sequence(reinterpret_cast (sequence)), - m_found(0), m_eof(false) - { + : m_stream(is), + m_sequence(reinterpret_cast (sequence)), + m_found(0), + m_eof(false) { + } - inputStream& getPreviousInputStream() - { - return (m_stream); + inputStream& getPreviousInputStream() { + + return m_stream; } - bool eof() const - { - return (m_found == COUNT || m_eof); + bool eof() const { + + return m_found == COUNT || m_eof; } - void reset() - { + void reset() { + m_found = 0; m_stream.reset(); } - size_t read(byte_t* const data, const size_t count) - { - // Read buffer must be at least 'COUNT' size + 1 byte - if (eof() || count <= COUNT) - return 0; + size_t read(byte_t* const data, const size_t count) { + + // Read buffer must be at least 'COUNT' size + 1 byte + if (eof() || count <= COUNT) { + return 0; + } + + if (m_stream.eof()) { + + if (m_found != 0) { - if (m_stream.eof()) - { - if (m_found != 0) - { const size_t found = m_found; - for (size_t f = 0 ; f < found ; ++f) + for (size_t f = 0 ; f < found ; ++f) { data[f] = m_sequence[f]; + } m_found = 0; m_eof = true; - return (found); - } - else - { + return found; + + } else { + m_eof = true; return 0; } @@ -274,72 +273,71 @@ public: byte_t* end = data + read; byte_t* pos = data; - while (pos < end) - { + while (pos < end) { + // Very simple case, search for the whole sequence - if (m_found == 0) - { - while (pos < end) - { + if (m_found == 0) { + + while (pos < end) { + pos = std::find(pos, end, m_sequence[0]); - if (pos == end) - return (read); + if (pos == end) { + return read; + } m_found = 1; ++pos; - while (pos < end && m_found < COUNT && m_sequence[m_found] == *pos) - { + while (pos < end && m_found < COUNT && m_sequence[m_found] == *pos) { ++m_found; ++pos; } // Didn't found whole sequence - if (m_found != COUNT) - { + if (m_found != COUNT) { + // We reached the end of the buffer - if (pos == end) - { - return (read - m_found); - } + if (pos == end) { + + return read - m_found; + // Common prefix but not whole sequence - else - { + } else { + m_found = 0; } - } + // Whole sequence found - else - { + } else { + // End of stream - return (pos - data - m_found); + return pos - data - m_found; } } - } + // More complex case: search for a sequence which has begun // in a previous buffer - else - { + } else { + // Search for the end of the previously started sequence - while (pos < end && m_found < COUNT && m_sequence[m_found] == *pos) - { + while (pos < end && m_found < COUNT && m_sequence[m_found] == *pos) { ++m_found; ++pos; } - if (m_found != COUNT) - { + if (m_found != COUNT) { + // End of buffer - if (pos == end) - { + if (pos == end) { + // No data: this buffer is a sub-sequence of the // searched sequence return 0; - } + // Common prefix - else - { + } else { + // We have to reinject the incomplete sequence into // the stream data @@ -349,8 +347,8 @@ public: byte_t* newEnd = data + read + m_found - n; byte_t* oldEnd = data + read; - for (size_t i = 0 ; i < read - n ; ++i) - { + for (size_t i = 0 ; i < read - n ; ++i) { + --newEnd; --oldEnd; @@ -358,17 +356,18 @@ public: } // -- copy the prefix just before data - for (size_t f = 0 ; f < m_found ; ++f) + for (size_t f = 0 ; f < m_found ; ++f) { data[f] = m_sequence[f]; + } read += m_found - n; end += m_found - n; m_found = 0; } - } - else - { + + } else { + return 0; // no more data } } @@ -377,8 +376,8 @@ public: return read; } - size_t skip(const size_t /* count */) - { + size_t skip(const size_t /* count */) { + // Not supported return 0; } @@ -395,8 +394,7 @@ private: template <> -size_t stopSequenceFilteredInputStream <1>::read - (byte_t* const data, const size_t count); +size_t stopSequenceFilteredInputStream <1>::read(byte_t* const data, const size_t count); } // utility diff --git a/src/vmime/utility/inputStream.cpp b/src/vmime/utility/inputStream.cpp index a7d6bc0f..916d8baa 100644 --- a/src/vmime/utility/inputStream.cpp +++ b/src/vmime/utility/inputStream.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 diff --git a/src/vmime/utility/inputStream.hpp b/src/vmime/utility/inputStream.hpp index 809996ce..0e1c2df8 100644 --- a/src/vmime/utility/inputStream.hpp +++ b/src/vmime/utility/inputStream.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,9 +34,8 @@ namespace utility { /** Simple input stream. */ +class VMIME_EXPORT inputStream : public stream { -class VMIME_EXPORT inputStream : public stream -{ public: /** Test for end of stream (no more data to read). diff --git a/src/vmime/utility/inputStreamAdapter.cpp b/src/vmime/utility/inputStreamAdapter.cpp index c0b06be4..28be1038 100644 --- a/src/vmime/utility/inputStreamAdapter.cpp +++ b/src/vmime/utility/inputStreamAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,50 +29,51 @@ namespace utility { inputStreamAdapter::inputStreamAdapter(std::istream& is) - : m_stream(is) -{ + : m_stream(is) { + } -bool inputStreamAdapter::eof() const -{ - return (m_stream.eof()); +bool inputStreamAdapter::eof() const { + + return m_stream.eof(); } -void inputStreamAdapter::reset() -{ +void inputStreamAdapter::reset() { + m_stream.exceptions(std::ios_base::badbit); m_stream.seekg(0, std::ios::beg); m_stream.clear(); } -size_t inputStreamAdapter::read - (byte_t* const data, const size_t count) -{ +size_t inputStreamAdapter::read(byte_t* const data, const size_t count) { + m_stream.exceptions(std::ios_base::badbit); m_stream.read(reinterpret_cast (data), count); - return (m_stream.gcount()); + + return m_stream.gcount(); } -size_t inputStreamAdapter::skip(const size_t count) -{ +size_t inputStreamAdapter::skip(const size_t count) { + m_stream.exceptions(std::ios_base::badbit); m_stream.ignore(count); - return (m_stream.gcount()); + + return m_stream.gcount(); } -size_t inputStreamAdapter::getPosition() const -{ +size_t inputStreamAdapter::getPosition() const { + return m_stream.tellg(); } -void inputStreamAdapter::seek(const size_t pos) -{ +void inputStreamAdapter::seek(const size_t pos) { + m_stream.clear(); m_stream.seekg(pos, std::ios_base::beg); } diff --git a/src/vmime/utility/inputStreamAdapter.hpp b/src/vmime/utility/inputStreamAdapter.hpp index dd761736..340765c3 100644 --- a/src/vmime/utility/inputStreamAdapter.hpp +++ b/src/vmime/utility/inputStreamAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,9 +36,8 @@ namespace utility { /** An adapter class for C++ standard input streams. */ +class VMIME_EXPORT inputStreamAdapter : public seekableInputStream { -class VMIME_EXPORT inputStreamAdapter : public seekableInputStream -{ public: /** @param is input stream to wrap diff --git a/src/vmime/utility/inputStreamByteBufferAdapter.cpp b/src/vmime/utility/inputStreamByteBufferAdapter.cpp index c270ea56..927215c3 100644 --- a/src/vmime/utility/inputStreamByteBufferAdapter.cpp +++ b/src/vmime/utility/inputStreamByteBufferAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,37 +29,38 @@ namespace utility { inputStreamByteBufferAdapter::inputStreamByteBufferAdapter(const byte_t* buffer, const size_t length) - : m_buffer(buffer), m_length(length), m_pos(0) -{ + : m_buffer(buffer), + m_length(length), + m_pos(0) { + } -bool inputStreamByteBufferAdapter::eof() const -{ +bool inputStreamByteBufferAdapter::eof() const { + return m_pos >= m_length; } -void inputStreamByteBufferAdapter::reset() -{ +void inputStreamByteBufferAdapter::reset() { + m_pos = 0; } -size_t inputStreamByteBufferAdapter::read - (byte_t* const data, const size_t count) -{ +size_t inputStreamByteBufferAdapter::read(byte_t* const data, const size_t count) { + const size_t remaining = m_length - m_pos; - if (remaining < count) - { + if (remaining < count) { + std::copy(m_buffer + m_pos, m_buffer + m_pos + remaining, data); m_pos += remaining; return remaining; - } - else - { + + } else { + std::copy(m_buffer + m_pos, m_buffer + m_pos + count, data); m_pos += count; @@ -68,36 +69,36 @@ size_t inputStreamByteBufferAdapter::read } -size_t inputStreamByteBufferAdapter::skip(const size_t count) -{ +size_t inputStreamByteBufferAdapter::skip(const size_t count) { + const size_t remaining = m_length - m_pos; - if (remaining < count) - { + if (remaining < count) { + m_pos += remaining; return remaining; - } - else - { + + } else { + m_pos += count; return count; } } -size_t inputStreamByteBufferAdapter::getPosition() const -{ +size_t inputStreamByteBufferAdapter::getPosition() const { + return m_pos; } -void inputStreamByteBufferAdapter::seek(const size_t pos) -{ - if (pos <= m_length) +void inputStreamByteBufferAdapter::seek(const size_t pos) { + + if (pos <= m_length) { m_pos = pos; + } } } // utility } // vmime - diff --git a/src/vmime/utility/inputStreamByteBufferAdapter.hpp b/src/vmime/utility/inputStreamByteBufferAdapter.hpp index f201f433..c9094c79 100644 --- a/src/vmime/utility/inputStreamByteBufferAdapter.hpp +++ b/src/vmime/utility/inputStreamByteBufferAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,9 +34,8 @@ namespace utility { /** An adapter class for reading from an array of bytes. */ +class VMIME_EXPORT inputStreamByteBufferAdapter : public seekableInputStream { -class VMIME_EXPORT inputStreamByteBufferAdapter : public seekableInputStream -{ public: inputStreamByteBufferAdapter(const byte_t* buffer, size_t length); @@ -62,4 +61,3 @@ private: #endif // VMIME_UTILITY_INPUTSTREAMBYTEBUFFERADAPTER_HPP_INCLUDED - diff --git a/src/vmime/utility/inputStreamPointerAdapter.cpp b/src/vmime/utility/inputStreamPointerAdapter.cpp index 6bf0461a..3f468d4f 100644 --- a/src/vmime/utility/inputStreamPointerAdapter.cpp +++ b/src/vmime/utility/inputStreamPointerAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,18 +29,20 @@ namespace utility { inputStreamPointerAdapter::inputStreamPointerAdapter(std::istream* is, const bool own) - : inputStreamAdapter(*is), m_stream(is), m_own(own) -{ + : inputStreamAdapter(*is), + m_stream(is), + m_own(own) { + } -inputStreamPointerAdapter::~inputStreamPointerAdapter() -{ - if (m_own) - delete (m_stream); +inputStreamPointerAdapter::~inputStreamPointerAdapter() { + + if (m_own) { + delete m_stream; + } } } // utility } // vmime - diff --git a/src/vmime/utility/inputStreamPointerAdapter.hpp b/src/vmime/utility/inputStreamPointerAdapter.hpp index 4fc606a9..e48f9ce4 100644 --- a/src/vmime/utility/inputStreamPointerAdapter.hpp +++ b/src/vmime/utility/inputStreamPointerAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,9 +36,8 @@ namespace utility { /** An adapter class for pointer to C++ standard input stream. */ +class VMIME_EXPORT inputStreamPointerAdapter : public inputStreamAdapter { -class VMIME_EXPORT inputStreamPointerAdapter : public inputStreamAdapter -{ public: /** @param is input stream to wrap @@ -60,4 +59,3 @@ private: #endif // VMIME_UTILITY_INPUTSTREAMPOINTERADAPTER_HPP_INCLUDED - diff --git a/src/vmime/utility/inputStreamSocketAdapter.cpp b/src/vmime/utility/inputStreamSocketAdapter.cpp index d78855eb..515906bb 100644 --- a/src/vmime/utility/inputStreamSocketAdapter.cpp +++ b/src/vmime/utility/inputStreamSocketAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,41 +35,39 @@ namespace utility { inputStreamSocketAdapter::inputStreamSocketAdapter(net::socket& sok) - : m_socket(sok) -{ + : m_socket(sok) { + } -bool inputStreamSocketAdapter::eof() const -{ +bool inputStreamSocketAdapter::eof() const { + // Can't know... return false; } -void inputStreamSocketAdapter::reset() -{ +void inputStreamSocketAdapter::reset() { + // Not supported } -size_t inputStreamSocketAdapter::read - (byte_t* const data, const size_t count) -{ +size_t inputStreamSocketAdapter::read(byte_t* const data, const size_t count) { + return m_socket.receiveRaw(data, count); } -size_t inputStreamSocketAdapter::skip - (const size_t /* count */) -{ +size_t inputStreamSocketAdapter::skip(const size_t /* count */) { + // Not supported return 0; } -size_t inputStreamSocketAdapter::getBlockSize() -{ +size_t inputStreamSocketAdapter::getBlockSize() { + return m_socket.getBlockSize(); } @@ -79,4 +77,3 @@ size_t inputStreamSocketAdapter::getBlockSize() #endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/vmime/utility/inputStreamSocketAdapter.hpp b/src/vmime/utility/inputStreamSocketAdapter.hpp index a990f628..1650037b 100644 --- a/src/vmime/utility/inputStreamSocketAdapter.hpp +++ b/src/vmime/utility/inputStreamSocketAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,9 +44,8 @@ namespace utility { /** An input stream that is connected to a socket. */ +class VMIME_EXPORT inputStreamSocketAdapter : public inputStream { -class VMIME_EXPORT inputStreamSocketAdapter : public inputStream -{ public: inputStreamSocketAdapter(net::socket& sok); @@ -74,4 +73,3 @@ private: #endif // VMIME_UTILITY_INPUTSTREAMSOCKETADAPTER_HPP_INCLUDED - diff --git a/src/vmime/utility/inputStreamStringAdapter.cpp b/src/vmime/utility/inputStreamStringAdapter.cpp index 9b897b97..bf09a9b8 100644 --- a/src/vmime/utility/inputStreamStringAdapter.cpp +++ b/src/vmime/utility/inputStreamStringAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,79 +29,91 @@ namespace utility { inputStreamStringAdapter::inputStreamStringAdapter(const string& buffer) - : m_buffer(buffer), m_begin(0), m_end(buffer.length()), m_pos(0) -{ + : m_buffer(buffer), + m_begin(0), + m_end(buffer.length()), + m_pos(0) { + } -inputStreamStringAdapter::inputStreamStringAdapter(const string& buffer, - const size_t begin, const size_t end) - : m_buffer(buffer), m_begin(begin), m_end(end), m_pos(begin) -{ +inputStreamStringAdapter::inputStreamStringAdapter( + const string& buffer, + const size_t begin, + const size_t end +) + : m_buffer(buffer), + m_begin(begin), + m_end(end), + m_pos(begin) { + } -bool inputStreamStringAdapter::eof() const -{ - return (m_pos >= m_end); +bool inputStreamStringAdapter::eof() const { + + return m_pos >= m_end; } -void inputStreamStringAdapter::reset() -{ +void inputStreamStringAdapter::reset() { + m_pos = m_begin; } -size_t inputStreamStringAdapter::read - (byte_t* const data, const size_t count) -{ - if (m_pos + count >= m_end) - { +size_t inputStreamStringAdapter::read(byte_t* const data, const size_t count) { + + if (m_pos + count >= m_end) { + const size_t remaining = m_end - m_pos; std::copy(m_buffer.begin() + m_pos, m_buffer.end(), data); m_pos = m_end; - return (remaining); - } - else - { + + return remaining; + + } else { + std::copy(m_buffer.begin() + m_pos, m_buffer.begin() + m_pos + count, data); m_pos += count; - return (count); + + return count; } } -size_t inputStreamStringAdapter::skip(const size_t count) -{ - if (m_pos + count >= m_end) - { +size_t inputStreamStringAdapter::skip(const size_t count) { + + if (m_pos + count >= m_end) { + const size_t remaining = m_end - m_pos; m_pos = m_end; - return (remaining); - } - else - { + + return remaining; + + } else { + m_pos += count; - return (count); + + return count; } } -size_t inputStreamStringAdapter::getPosition() const -{ +size_t inputStreamStringAdapter::getPosition() const { + return m_pos - m_begin; } -void inputStreamStringAdapter::seek(const size_t pos) -{ - if (m_begin + pos <= m_end) +void inputStreamStringAdapter::seek(const size_t pos) { + + if (m_begin + pos <= m_end) { m_pos = m_begin + pos; + } } } // utility } // vmime - diff --git a/src/vmime/utility/inputStreamStringAdapter.hpp b/src/vmime/utility/inputStreamStringAdapter.hpp index 4ee597e6..2c2cbb84 100644 --- a/src/vmime/utility/inputStreamStringAdapter.hpp +++ b/src/vmime/utility/inputStreamStringAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,9 +34,8 @@ namespace utility { /** An adapter class for string input. */ +class VMIME_EXPORT inputStreamStringAdapter : public seekableInputStream { -class VMIME_EXPORT inputStreamStringAdapter : public seekableInputStream -{ public: inputStreamStringAdapter(const string& buffer); @@ -65,4 +64,3 @@ private: #endif // VMIME_UTILITY_INPUTSTREAMSTRINGADAPTER_HPP_INCLUDED - diff --git a/src/vmime/utility/inputStreamStringProxyAdapter.cpp b/src/vmime/utility/inputStreamStringProxyAdapter.cpp index 5513de80..743e0d7f 100644 --- a/src/vmime/utility/inputStreamStringProxyAdapter.cpp +++ b/src/vmime/utility/inputStreamStringProxyAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,73 +30,75 @@ namespace utility { inputStreamStringProxyAdapter::inputStreamStringProxyAdapter(const stringProxy& buffer) - : m_buffer(buffer), m_pos(0) -{ + : m_buffer(buffer), + m_pos(0) { + } -bool inputStreamStringProxyAdapter::eof() const -{ - return (m_pos >= m_buffer.length()); +bool inputStreamStringProxyAdapter::eof() const { + + return m_pos >= m_buffer.length(); } -void inputStreamStringProxyAdapter::reset() -{ +void inputStreamStringProxyAdapter::reset() { + m_pos = 0; } -size_t inputStreamStringProxyAdapter::read - (byte_t* const data, const size_t count) -{ +size_t inputStreamStringProxyAdapter::read(byte_t* const data, const size_t count) { + const size_t remaining = m_buffer.length() - m_pos; - if (count > remaining) - { + if (count > remaining) { + std::copy(m_buffer.it_begin() + m_pos, m_buffer.it_end(), data); m_pos = m_buffer.length(); - return (remaining); - } - else - { + + return remaining; + + } else { + std::copy(m_buffer.it_begin() + m_pos, m_buffer.it_begin() + m_pos + count, data); m_pos += count; - return (count); + + return count; } } -size_t inputStreamStringProxyAdapter::skip(const size_t count) -{ +size_t inputStreamStringProxyAdapter::skip(const size_t count) { + const size_t remaining = m_buffer.length() - m_pos; - if (count > remaining) - { + if (count > remaining) { + m_pos = m_buffer.length(); - return (remaining); - } - else - { + return remaining; + + } else { + m_pos += count; - return (count); + return count; } } -size_t inputStreamStringProxyAdapter::getPosition() const -{ +size_t inputStreamStringProxyAdapter::getPosition() const { + return m_pos; } -void inputStreamStringProxyAdapter::seek(const size_t pos) -{ - if (pos <= m_buffer.length()) +void inputStreamStringProxyAdapter::seek(const size_t pos) { + + if (pos <= m_buffer.length()) { m_pos = pos; + } } } // utility } // vmime - diff --git a/src/vmime/utility/inputStreamStringProxyAdapter.hpp b/src/vmime/utility/inputStreamStringProxyAdapter.hpp index 02dc2056..4d0496b1 100644 --- a/src/vmime/utility/inputStreamStringProxyAdapter.hpp +++ b/src/vmime/utility/inputStreamStringProxyAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,9 +37,8 @@ class stringProxy; /** An adapter class for stringProxy input. */ +class VMIME_EXPORT inputStreamStringProxyAdapter : public seekableInputStream { -class VMIME_EXPORT inputStreamStringProxyAdapter : public seekableInputStream -{ public: /** @param buffer stringProxy object to wrap @@ -67,4 +66,3 @@ private: #endif // VMIME_UTILITY_INPUTSTREAMSTRINGPROXYADAPTER_HPP_INCLUDED - diff --git a/src/vmime/utility/outputStream.cpp b/src/vmime/utility/outputStream.cpp index 070e28c5..b07fb073 100644 --- a/src/vmime/utility/outputStream.cpp +++ b/src/vmime/utility/outputStream.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,18 +28,17 @@ namespace vmime { namespace utility { -void outputStream::write(const byte_t* const data, const size_t count) -{ +void outputStream::write(const byte_t* const data, const size_t count) { + writeImpl(data, count); } -void outputStream::write(const char* const data, const size_t count) -{ +void outputStream::write(const char* const data, const size_t count) { + writeImpl(reinterpret_cast (data), count); } } // utility } // vmime - diff --git a/src/vmime/utility/outputStream.hpp b/src/vmime/utility/outputStream.hpp index 62ee7336..318c1dd4 100644 --- a/src/vmime/utility/outputStream.hpp +++ b/src/vmime/utility/outputStream.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,9 +39,8 @@ namespace utility { /** Simple output stream. */ +class VMIME_EXPORT outputStream : public stream { -class VMIME_EXPORT outputStream : public stream -{ public: /** Write data to the stream. @@ -65,8 +64,8 @@ public: * null (value is induced by compiler) */ template - void write(const char (&data)[N]) - { + void write(const char (&data)[N]) { + write(data, N - 1); } @@ -95,27 +94,27 @@ VMIME_EXPORT outputStream& operator<<(outputStream& os, const byte_t c); #if defined(_MSC_VER) && (_MSC_VER <= 1200) // Internal compiler error with VC++6 -inline outputStream& operator<<(outputStream& os, const char* str) -{ +inline outputStream& operator<<(outputStream& os, const char* str) { + os.write(reinterpret_cast (str), ::strlen(str)); - return (os); + return os; } #else template -outputStream& operator<<(outputStream& os, const char (&str)[N]) -{ +outputStream& operator<<(outputStream& os, const char (&str)[N]) { + os.write(reinterpret_cast (str), N - 1); - return (os); + return os; } #endif // defined(_MSC_VER) && (_MSC_VER <= 1200) template -outputStream& operator<<(outputStream& os, const T& t) -{ +outputStream& operator<<(outputStream& os, const T& t) { + std::ostringstream oss; oss.imbue(std::locale::classic()); // no formatting @@ -123,14 +122,12 @@ outputStream& operator<<(outputStream& os, const T& t) os << oss.str(); - return (os); + return os; } - } // utility } // vmime #endif // VMIME_UTILITY_OUTPUTSTREAM_HPP_INCLUDED - diff --git a/src/vmime/utility/outputStreamAdapter.cpp b/src/vmime/utility/outputStreamAdapter.cpp index ed90c7d3..74556919 100644 --- a/src/vmime/utility/outputStreamAdapter.cpp +++ b/src/vmime/utility/outputStreamAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,21 +29,20 @@ namespace utility { outputStreamAdapter::outputStreamAdapter(std::ostream& os) - : m_stream(os) -{ + : m_stream(os) { + } -void outputStreamAdapter::writeImpl - (const byte_t* const data, const size_t count) -{ +void outputStreamAdapter::writeImpl(const byte_t* const data, const size_t count) { + m_stream.exceptions(std::ios_base::badbit); m_stream.write(reinterpret_cast (data), count); } -void outputStreamAdapter::flush() -{ +void outputStreamAdapter::flush() { + m_stream.exceptions(std::ios_base::badbit); m_stream.flush(); } @@ -51,4 +50,3 @@ void outputStreamAdapter::flush() } // utility } // vmime - diff --git a/src/vmime/utility/outputStreamAdapter.hpp b/src/vmime/utility/outputStreamAdapter.hpp index f0125584..35c5cdea 100644 --- a/src/vmime/utility/outputStreamAdapter.hpp +++ b/src/vmime/utility/outputStreamAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,9 +36,8 @@ namespace utility { /** An adapter class for C++ standard output streams. */ +class VMIME_EXPORT outputStreamAdapter : public outputStream { -class VMIME_EXPORT outputStreamAdapter : public outputStream -{ public: /** @param os output stream to wrap @@ -62,4 +61,3 @@ private: #endif // VMIME_UTILITY_OUTPUTSTREAMADAPTER_HPP_INCLUDED - diff --git a/src/vmime/utility/outputStreamByteArrayAdapter.cpp b/src/vmime/utility/outputStreamByteArrayAdapter.cpp index 1bed735b..a38bd799 100644 --- a/src/vmime/utility/outputStreamByteArrayAdapter.cpp +++ b/src/vmime/utility/outputStreamByteArrayAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,24 +29,22 @@ namespace utility { outputStreamByteArrayAdapter::outputStreamByteArrayAdapter(byteArray& array) - : m_array(array) -{ + : m_array(array) { + } -void outputStreamByteArrayAdapter::writeImpl - (const byte_t* const data, const size_t count) -{ +void outputStreamByteArrayAdapter::writeImpl(const byte_t* const data, const size_t count) { + m_array.insert(m_array.end(), data, data + count); } -void outputStreamByteArrayAdapter::flush() -{ +void outputStreamByteArrayAdapter::flush() { + // Do nothing } } // utility } // vmime - diff --git a/src/vmime/utility/outputStreamByteArrayAdapter.hpp b/src/vmime/utility/outputStreamByteArrayAdapter.hpp index a2178a9c..f36ff9c2 100644 --- a/src/vmime/utility/outputStreamByteArrayAdapter.hpp +++ b/src/vmime/utility/outputStreamByteArrayAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,9 +34,8 @@ namespace utility { /** An adapter class for byte array output. */ +class VMIME_EXPORT outputStreamByteArrayAdapter : public outputStream { -class VMIME_EXPORT outputStreamByteArrayAdapter : public outputStream -{ public: outputStreamByteArrayAdapter(byteArray& array); @@ -58,4 +57,3 @@ private: #endif // VMIME_UTILITY_OUTPUTSTREAMBYTEARRAYADAPTER_HPP_INCLUDED - diff --git a/src/vmime/utility/outputStreamSocketAdapter.cpp b/src/vmime/utility/outputStreamSocketAdapter.cpp index 03194497..cd82c447 100644 --- a/src/vmime/utility/outputStreamSocketAdapter.cpp +++ b/src/vmime/utility/outputStreamSocketAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,34 +35,31 @@ namespace utility { outputStreamSocketAdapter::outputStreamSocketAdapter(net::socket& sok) - : m_socket(sok) -{ + : m_socket(sok) { + } -void outputStreamSocketAdapter::writeImpl - (const byte_t* const data, const size_t count) -{ +void outputStreamSocketAdapter::writeImpl(const byte_t* const data, const size_t count) { + m_socket.sendRaw(data, count); } -void outputStreamSocketAdapter::flush() -{ +void outputStreamSocketAdapter::flush() { + // Do nothing } -size_t outputStreamSocketAdapter::getBlockSize() -{ +size_t outputStreamSocketAdapter::getBlockSize() { + return m_socket.getBlockSize(); } - } // utility } // vmime #endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/vmime/utility/outputStreamSocketAdapter.hpp b/src/vmime/utility/outputStreamSocketAdapter.hpp index 6cd00626..4fb199ba 100644 --- a/src/vmime/utility/outputStreamSocketAdapter.hpp +++ b/src/vmime/utility/outputStreamSocketAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,9 +44,8 @@ namespace utility { /** An output stream that is connected to a socket. */ +class VMIME_EXPORT outputStreamSocketAdapter : public outputStream { -class VMIME_EXPORT outputStreamSocketAdapter : public outputStream -{ public: outputStreamSocketAdapter(net::socket& sok); @@ -75,4 +74,3 @@ private: #endif // VMIME_UTILITY_OUTPUTSTREAMSOCKETADAPTER_HPP_INCLUDED - diff --git a/src/vmime/utility/outputStreamStringAdapter.cpp b/src/vmime/utility/outputStreamStringAdapter.cpp index 7105480c..12c809c4 100644 --- a/src/vmime/utility/outputStreamStringAdapter.cpp +++ b/src/vmime/utility/outputStreamStringAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,24 +31,22 @@ namespace utility { outputStreamStringAdapter::outputStreamStringAdapter(string& buffer) - : m_buffer(buffer) -{ + : m_buffer(buffer) { + } -void outputStreamStringAdapter::writeImpl - (const byte_t* const data, const size_t count) -{ +void outputStreamStringAdapter::writeImpl(const byte_t* const data, const size_t count) { + vmime::utility::stringUtils::appendBytesToString(m_buffer, data, count); } -void outputStreamStringAdapter::flush() -{ +void outputStreamStringAdapter::flush() { + // Do nothing } } // utility } // vmime - diff --git a/src/vmime/utility/outputStreamStringAdapter.hpp b/src/vmime/utility/outputStreamStringAdapter.hpp index 89516827..a29e2cb1 100644 --- a/src/vmime/utility/outputStreamStringAdapter.hpp +++ b/src/vmime/utility/outputStreamStringAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,9 +34,8 @@ namespace utility { /** An adapter class for string output. */ +class VMIME_EXPORT outputStreamStringAdapter : public outputStream { -class VMIME_EXPORT outputStreamStringAdapter : public outputStream -{ public: outputStreamStringAdapter(string& buffer); @@ -58,4 +57,3 @@ private: #endif // VMIME_UTILITY_OUTPUTSTREAMSTRINGADAPTER_HPP_INCLUDED - diff --git a/src/vmime/utility/parserInputStreamAdapter.cpp b/src/vmime/utility/parserInputStreamAdapter.cpp index ee6a58dd..98bbe607 100644 --- a/src/vmime/utility/parserInputStreamAdapter.cpp +++ b/src/vmime/utility/parserInputStreamAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,44 +29,43 @@ namespace utility { parserInputStreamAdapter::parserInputStreamAdapter(const shared_ptr & stream) - : m_stream(stream) -{ + : m_stream(stream) { + } -bool parserInputStreamAdapter::eof() const -{ +bool parserInputStreamAdapter::eof() const { + return m_stream->eof(); } -void parserInputStreamAdapter::reset() -{ +void parserInputStreamAdapter::reset() { + m_stream->reset(); } -size_t parserInputStreamAdapter::read - (byte_t* const data, const size_t count) -{ +size_t parserInputStreamAdapter::read(byte_t* const data, const size_t count) { + return m_stream->read(data, count); } -shared_ptr parserInputStreamAdapter::getUnderlyingStream() -{ +shared_ptr parserInputStreamAdapter::getUnderlyingStream() { + return m_stream; } -const string parserInputStreamAdapter::extract(const size_t begin, const size_t end) const -{ +const string parserInputStreamAdapter::extract(const size_t begin, const size_t end) const { + const size_t initialPos = m_stream->getPosition(); byte_t *buffer = NULL; - try - { + try { + buffer = new byte_t[end - begin + 1]; m_stream->seek(begin); @@ -80,9 +79,9 @@ const string parserInputStreamAdapter::extract(const size_t begin, const size_t delete [] buffer; return str; - } - catch (...) - { + + } catch (...) { + delete [] buffer; m_stream->seek(initialPos); @@ -91,21 +90,24 @@ const string parserInputStreamAdapter::extract(const size_t begin, const size_t } -size_t parserInputStreamAdapter::findNext - (const string& token, const size_t startPosition) -{ +size_t parserInputStreamAdapter::findNext( + const string& token, + const size_t startPosition +) { + static const unsigned int BUFFER_SIZE = 4096; // Token must not be longer than BUFFER_SIZE/2 - if (token.empty() || token.length() > BUFFER_SIZE / 2) + if (token.empty() || token.length() > BUFFER_SIZE / 2) { return npos; + } const size_t initialPos = getPosition(); seek(startPosition); - try - { + try { + byte_t findBuffer[BUFFER_SIZE]; byte_t* findBuffer1 = findBuffer; byte_t* findBuffer2 = findBuffer + (BUFFER_SIZE / 2); @@ -118,19 +120,20 @@ size_t parserInputStreamAdapter::findNext // Fill in initial buffer findBufferLen = read(findBuffer, BUFFER_SIZE); - while (findBufferLen != 0) - { + while (findBufferLen != 0) { + // Find token for (byte_t *begin = findBuffer, *end = findBuffer + findBufferLen - token.length() ; - begin <= end ; ++begin) - { + begin <= end ; ++begin) { + if (begin[0] == token[0] && (token.length() == 1 || memcmp(static_cast (&begin[1]), static_cast (token.data() + 1), - token.length() - 1) == 0)) - { + token.length() - 1) == 0)) { + seek(initialPos); + return startPosition + findBufferOffset + (begin - findBuffer); } } @@ -139,16 +142,17 @@ size_t parserInputStreamAdapter::findNext memcpy(findBuffer1, findBuffer2, (BUFFER_SIZE / 2)); // Read more bytes - if (findBufferLen < BUFFER_SIZE && (eof() || isEOF)) - { + if (findBufferLen < BUFFER_SIZE && (eof() || isEOF)) { + break; - } - else - { + + } else { + const size_t bytesRead = read(findBuffer2, BUFFER_SIZE / 2); - if (bytesRead == 0) + if (bytesRead == 0) { isEOF = true; + } findBufferLen = (BUFFER_SIZE / 2) + bytesRead; findBufferOffset += (BUFFER_SIZE / 2); @@ -156,9 +160,9 @@ size_t parserInputStreamAdapter::findNext } seek(initialPos); - } - catch (...) - { + + } catch (...) { + seek(initialPos); throw; } @@ -169,4 +173,3 @@ size_t parserInputStreamAdapter::findNext } // utility } // vmime - diff --git a/src/vmime/utility/parserInputStreamAdapter.hpp b/src/vmime/utility/parserInputStreamAdapter.hpp index f6e360cb..e448d29c 100644 --- a/src/vmime/utility/parserInputStreamAdapter.hpp +++ b/src/vmime/utility/parserInputStreamAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,9 +36,8 @@ namespace utility { /** An adapter class used for parsing from an input stream. */ +class VMIME_EXPORT parserInputStreamAdapter : public seekableInputStream { -class VMIME_EXPORT parserInputStreamAdapter : public seekableInputStream -{ public: /** @param stream input stream to wrap @@ -51,18 +50,18 @@ public: void reset(); size_t read(byte_t* const data, const size_t count); - void seek(const size_t pos) - { + void seek(const size_t pos) { + m_stream->seek(pos); } - size_t skip(const size_t count) - { + size_t skip(const size_t count) { + return m_stream->skip(count); } - size_t getPosition() const - { + size_t getPosition() const { + return m_stream->getPosition(); } @@ -71,21 +70,21 @@ public: * * @return byte at the current position */ - byte_t peekByte() const - { + byte_t peekByte() const { + const size_t initialPos = m_stream->getPosition(); - try - { + try { + byte_t buffer[1]; const size_t readBytes = m_stream->read(buffer, 1); m_stream->seek(initialPos); return (readBytes == 1 ? buffer[0] : static_cast (0)); - } - catch (...) - { + + } catch (...) { + m_stream->seek(initialPos); throw; } @@ -96,12 +95,12 @@ public: * * @return byte at the current position */ - byte_t getByte() - { + byte_t getByte() { + byte_t buffer[1]; const size_t readBytes = m_stream->read(buffer, 1); - return (readBytes == 1 ? buffer[0] : static_cast (0)); + return readBytes == 1 ? buffer[0] : static_cast (0); } /** Check whether the bytes following the current position match @@ -112,22 +111,21 @@ public: * @return true if the next bytes match the pattern, false otherwise */ template - bool matchBytes(const T* bytes, const size_t length) const - { + bool matchBytes(const T* bytes, const size_t length) const { + const size_t initialPos = m_stream->getPosition(); - try - { + try { + byte_t buffer[32]; const size_t readBytes = m_stream->read(buffer, length); m_stream->seek(initialPos); - return readBytes == length && - ::memcmp(bytes, buffer, length) == 0; - } - catch (...) - { + return readBytes == length && ::memcmp(bytes, buffer, length) == 0; + + } catch (...) { + m_stream->seek(initialPos); throw; } @@ -145,13 +143,14 @@ public: * @return number of bytes skipped */ template - size_t skipIf(PREDICATE pred, const size_t endPosition) - { + size_t skipIf(PREDICATE pred, const size_t endPosition) { + const size_t initialPos = getPosition(); size_t pos = initialPos; - while (!m_stream->eof() && pos < endPosition && pred(getByte())) + while (!m_stream->eof() && pos < endPosition && pred(getByte())) { ++pos; + } m_stream->seek(pos); @@ -171,4 +170,3 @@ private: #endif // VMIME_UTILITY_PARSERINPUTSTREAMADAPTER_HPP_INCLUDED - diff --git a/src/vmime/utility/path.cpp b/src/vmime/utility/path.cpp index 7ce028ff..0c70f116 100644 --- a/src/vmime/utility/path.cpp +++ b/src/vmime/utility/path.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,276 +30,288 @@ namespace vmime { namespace utility { -path::path() -{ +path::path() { + } -path::path(const component& c) -{ +path::path(const component& c) { + m_list.push_back(c); } path::path(const path& p) - : object() -{ + : object() { + m_list.resize(p.m_list.size()); std::copy(p.m_list.begin(), p.m_list.end(), m_list.begin()); } -path::path(const string& s) -{ +path::path(const string& s) { + m_list.push_back(component(s)); } -path path::operator/(const path& p) const -{ +path path::operator/(const path& p) const { + path pr(*this); pr /= p; - return (pr); + return pr; } -path path::operator/(const component& c) const -{ +path path::operator/(const component& c) const { + path pr(*this); pr /= c; - return (pr); + return pr; } -path& path::operator/=(const path& p) -{ +path& path::operator/=(const path& p) { + const list::size_type size = m_list.size(); m_list.resize(size + p.m_list.size()); std::copy(p.m_list.begin(), p.m_list.end(), m_list.begin() + size); - return (*this); + return *this; } -path& path::operator/=(const component& c) -{ +path& path::operator/=(const component& c) { + m_list.push_back(c); - return (*this); + return *this; } -path path::getParent() const -{ +path path::getParent() const { + path p; - if (!isEmpty()) - { + if (!isEmpty()) { p.m_list.resize(m_list.size() - 1); std::copy(m_list.begin(), m_list.end() - 1, p.m_list.begin()); } - return (p); + return p; } -path& path::operator=(const path& p) -{ +path& path::operator=(const path& p) { + m_list.resize(p.m_list.size()); std::copy(p.m_list.begin(), p.m_list.end(), m_list.begin()); - return (*this); + return *this; } -path& path::operator=(const component& c) -{ +path& path::operator=(const component& c) { + m_list.resize(1); m_list[0] = c; - return (*this); + return *this; } -bool path::operator==(const path& p) const -{ - if (m_list.size() != p.m_list.size()) +bool path::operator==(const path& p) const { + + if (m_list.size() != p.m_list.size()) { return (false); + } list::const_iterator i = m_list.begin(); list::const_iterator j = p.m_list.begin(); bool equal = true; - for ( ; equal && i != m_list.end() ; ++i, ++j) + for ( ; equal && i != m_list.end() ; ++i, ++j) { equal = ((*i).isEquivalent(*j)); + } - return (equal); + return equal; } -bool path::operator!=(const path& p) const -{ - return (!(*this == p)); +bool path::operator!=(const path& p) const { + + return !(*this == p); } -bool path::isEmpty() const -{ - return (m_list.empty()); +bool path::isEmpty() const { + + return m_list.empty(); } -bool path::isRoot() const -{ - return (m_list.empty()); +bool path::isRoot() const { + + return m_list.empty(); } -const path::component path::getLastComponent() const -{ - return (m_list[m_list.size() - 1]); +const path::component path::getLastComponent() const { + + return m_list[m_list.size() - 1]; } -path::component& path::getLastComponent() -{ - return (m_list[m_list.size() - 1]); +path::component& path::getLastComponent() { + + return m_list[m_list.size() - 1]; } -size_t path::getSize() const -{ - return (m_list.size()); +size_t path::getSize() const { + + return m_list.size(); } -const path::component& path::operator[](const size_t x) const -{ - return (m_list[x]); +const path::component& path::operator[](const size_t x) const { + + return m_list[x]; } -path::component& path::operator[](const size_t x) -{ - return (m_list[x]); +path::component& path::operator[](const size_t x) { + + return m_list[x]; } -bool path::isDirectParentOf(const path& p) const -{ - if (p.getSize() != getSize() + 1) - return (false); +bool path::isDirectParentOf(const path& p) const { + + if (p.getSize() != getSize() + 1) { + return false; + } bool equal = true; - for (list::size_type i = 0 ; equal && i < m_list.size() ; ++i) + for (list::size_type i = 0 ; equal && i < m_list.size() ; ++i) { equal = (m_list[i].isEquivalent(p.m_list[i])); + } - return (equal); + return equal; } -bool path::isParentOf(const path& p) const -{ - if (p.getSize() < getSize() + 1) - return (false); +bool path::isParentOf(const path& p) const { + + if (p.getSize() < getSize() + 1) { + return false; + } bool equal = true; - for (list::size_type i = 0 ; equal && i < m_list.size() ; ++i) + for (list::size_type i = 0 ; equal && i < m_list.size() ; ++i) { equal = (m_list[i].isEquivalent(p.m_list[i])); + } - return (equal); + return equal; } -void path::renameParent(const path& oldPath, const path& newPath) -{ - if (isEmpty() || oldPath.getSize() > getSize()) +void path::renameParent(const path& oldPath, const path& newPath) { + + if (isEmpty() || oldPath.getSize() > getSize()) { return; + } bool equal = true; list::size_type i; - for (i = 0 ; equal && i < oldPath.m_list.size() ; ++i) + for (i = 0 ; equal && i < oldPath.m_list.size() ; ++i) { equal = (m_list[i].isEquivalent(oldPath.m_list[i])); + } if (i != oldPath.m_list.size()) return; list newList; - for (list::size_type j = 0 ; j < newPath.m_list.size() ; ++j) + for (list::size_type j = 0 ; j < newPath.m_list.size() ; ++j) { newList.push_back(newPath.m_list[j]); + } - for (list::size_type j = i ; j < m_list.size() ; ++j) + for (list::size_type j = i ; j < m_list.size() ; ++j) { newList.push_back(m_list[j]); + } m_list.resize(newList.size()); std::copy(newList.begin(), newList.end(), m_list.begin()); } -void path::appendComponent(const path::component& c) -{ +void path::appendComponent(const path::component& c) { + m_list.push_back(c); } -const path::component& path::getComponentAt(const size_t pos) const -{ - return (m_list[pos]); +const path::component& path::getComponentAt(const size_t pos) const { + + return m_list[pos]; } -path::component& path::getComponentAt(const size_t pos) -{ - return (m_list[pos]); +path::component& path::getComponentAt(const size_t pos) { + + return m_list[pos]; } // static -path path::fromString(const string& str, const string& sep, const charset& cset) -{ +path path::fromString(const string& str, const string& sep, const charset& cset) { + path p; size_t start = 0; size_t end = 0; - do - { + do { + end = str.find(sep, start); string comp; - if (end == string::npos) + if (end == string::npos) { comp = str.substr(start); - else + } else { comp = str.substr(start, end - start); + } // Skip leading or trailing separators - if (comp.length()) + if (comp.length()) { p.appendComponent(component(comp, cset)); + } start = end + 1; - } - while (end != string::npos); + + } while (end != string::npos); return p; } -const string path::toString(const string& sep, const charset& cset) const -{ +const string path::toString(const string& sep, const charset& cset) const { + string str; - for (size_t i = 0 ; i < m_list.size() ; ++i) - { - if (i != 0) + for (size_t i = 0 ; i < m_list.size() ; ++i) { + + if (i != 0) { str += sep; + } str += m_list[i].getConvertedText(cset); } diff --git a/src/vmime/utility/path.hpp b/src/vmime/utility/path.hpp index 310fa24b..f1f15148 100644 --- a/src/vmime/utility/path.hpp +++ b/src/vmime/utility/path.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,9 +37,8 @@ namespace utility { /** Abstract representation of a path (filesystem, mailbox, etc). */ +class VMIME_EXPORT path : public object { -class VMIME_EXPORT path : public object -{ public: typedef vmime::word component; diff --git a/src/vmime/utility/progressListener.cpp b/src/vmime/utility/progressListener.cpp index 6764c563..cc4969c6 100644 --- a/src/vmime/utility/progressListener.cpp +++ b/src/vmime/utility/progressListener.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,38 +30,44 @@ namespace utility { // progressListenerSizeAdapter -progressListenerSizeAdapter::progressListenerSizeAdapter - (progressListener* list, const size_t total) - : m_wrapped(list), m_total(total) -{ +progressListenerSizeAdapter::progressListenerSizeAdapter( + progressListener* list, + const size_t total +) + : m_wrapped(list), + m_total(total) { + } -void progressListenerSizeAdapter::start(const size_t predictedTotal) -{ - if (m_wrapped) +void progressListenerSizeAdapter::start(const size_t predictedTotal) { + + if (m_wrapped) { m_wrapped->start(predictedTotal); + } } -void progressListenerSizeAdapter::progress(const size_t current, const size_t currentTotal) -{ - if (m_wrapped) - { - if (currentTotal > m_total) +void progressListenerSizeAdapter::progress(const size_t current, const size_t currentTotal) { + + if (m_wrapped) { + + if (currentTotal > m_total) { m_total = currentTotal; + } m_wrapped->progress(current, m_total); } } -void progressListenerSizeAdapter::stop(const size_t total) -{ - if (m_wrapped) - { - if (total > m_total) +void progressListenerSizeAdapter::stop(const size_t total) { + + if (m_wrapped) { + + if (total > m_total) { m_total = total; + } m_wrapped->stop(m_total); } @@ -70,4 +76,3 @@ void progressListenerSizeAdapter::stop(const size_t total) } // utility } // vmime - diff --git a/src/vmime/utility/progressListener.hpp b/src/vmime/utility/progressListener.hpp index e86fb808..18b4e4dd 100644 --- a/src/vmime/utility/progressListener.hpp +++ b/src/vmime/utility/progressListener.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,9 +36,8 @@ namespace utility { /** An interface to implement if you want to be notified * of a state of progress by some objects. */ +class VMIME_EXPORT progressListener { -class VMIME_EXPORT progressListener -{ protected: virtual ~progressListener() { } @@ -71,9 +70,8 @@ public: /** A progress listener used when total size is known by the * receiver, but not by the notifier. */ +class VMIME_EXPORT progressListenerSizeAdapter : public progressListener { -class VMIME_EXPORT progressListenerSizeAdapter : public progressListener -{ public: /** Construct a new progressListenerSizeAdapter object. @@ -99,4 +97,3 @@ private: #endif // VMIME_UTILITY_PROGRESSLISTENER_HPP_INCLUDED - diff --git a/src/vmime/utility/random.cpp b/src/vmime/utility/random.cpp index 97d12ddc..055122b5 100644 --- a/src/vmime/utility/random.cpp +++ b/src/vmime/utility/random.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,19 +31,20 @@ namespace vmime { namespace utility { -static unsigned int getRandomSeed() -{ +static unsigned int getRandomSeed() { + unsigned int seed; - platform::getHandler()->generateRandomBytes - (reinterpret_cast (&seed), sizeof(seed)); + platform::getHandler()->generateRandomBytes( + reinterpret_cast (&seed), sizeof(seed) + ); return seed; } -unsigned int random::getNext() -{ +unsigned int random::getNext() { + static unsigned int next = getRandomSeed(); // Park and Miller's minimal standard generator: @@ -54,35 +55,34 @@ unsigned int random::getNext() } -unsigned int random::getTime() -{ +unsigned int random::getTime() { + return static_cast ((platform::getHandler()->getUnixTime())); } -unsigned int random::getProcess() -{ - return (platform::getHandler()->getProcessId()); +unsigned int random::getProcess() { + + return platform::getHandler()->getProcessId(); } -const string random::getString(const size_t length, const string& randomChars) -{ +const string random::getString(const size_t length, const string& randomChars) { + string res; res.resize(length); const unsigned int x = static_cast (randomChars.length()); size_t c = 0; - while (c < length) - { - for (unsigned int n = random::getNext() ; n != 0 && c < length ; n /= x) - { + while (c < length) { + + for (unsigned int n = random::getNext() ; n != 0 && c < length ; n /= x) { res[c++] = randomChars[n % x]; } } - return (res); + return res; } diff --git a/src/vmime/utility/random.hpp b/src/vmime/utility/random.hpp index b667c3a2..21f4949e 100644 --- a/src/vmime/utility/random.hpp +++ b/src/vmime/utility/random.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,9 +34,8 @@ namespace utility { /** Pseudo-random number generator. */ +class random { -class random -{ public: /** Return a new random number. @@ -65,8 +64,10 @@ public: * @param randomChars list of characters to use * @return random string */ - static const string getString(const size_t length, const string& randomChars - = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); + static const string getString( + const size_t length, + const string& randomChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + ); }; diff --git a/src/vmime/utility/seekableInputStream.hpp b/src/vmime/utility/seekableInputStream.hpp index f56af9c4..181e904a 100644 --- a/src/vmime/utility/seekableInputStream.hpp +++ b/src/vmime/utility/seekableInputStream.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,9 +34,8 @@ namespace utility { /** An input stream that allows seeking within the input. */ +class VMIME_EXPORT seekableInputStream : public inputStream { -class VMIME_EXPORT seekableInputStream : public inputStream -{ public: /** Returns the current position in this stream. @@ -61,4 +60,3 @@ public: #endif // VMIME_UTILITY_SEEKABLEINPUTSTREAM_HPP_INCLUDED - diff --git a/src/vmime/utility/seekableInputStreamRegionAdapter.cpp b/src/vmime/utility/seekableInputStreamRegionAdapter.cpp index 6306d3dc..32723661 100644 --- a/src/vmime/utility/seekableInputStreamRegionAdapter.cpp +++ b/src/vmime/utility/seekableInputStreamRegionAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,39 +28,44 @@ namespace vmime { namespace utility { -seekableInputStreamRegionAdapter::seekableInputStreamRegionAdapter - (const shared_ptr & stream, const size_t begin, const size_t length) - : m_stream(stream), m_begin(begin), m_length(length), m_position(0) -{ +seekableInputStreamRegionAdapter::seekableInputStreamRegionAdapter( + const shared_ptr & stream, + const size_t begin, + const size_t length +) + : m_stream(stream), + m_begin(begin), + m_length(length), + m_position(0) { + } -bool seekableInputStreamRegionAdapter::eof() const -{ +bool seekableInputStreamRegionAdapter::eof() const { + return m_position >= m_length; } -void seekableInputStreamRegionAdapter::reset() -{ +void seekableInputStreamRegionAdapter::reset() { + m_position = 0; } -size_t seekableInputStreamRegionAdapter::read - (byte_t* const data, const size_t count) -{ +size_t seekableInputStreamRegionAdapter::read(byte_t* const data, const size_t count) { + m_stream->seek(m_begin + m_position); size_t readBytes = 0; - if (m_position + count >= m_length) - { + if (m_position + count >= m_length) { + const size_t remaining = m_length - m_position; readBytes = m_stream->read(data, remaining); - } - else - { + + } else { + readBytes = m_stream->read(data, count); } @@ -70,37 +75,37 @@ size_t seekableInputStreamRegionAdapter::read } -size_t seekableInputStreamRegionAdapter::skip(const size_t count) -{ - if (m_position + count >= m_length) - { +size_t seekableInputStreamRegionAdapter::skip(const size_t count) { + + if (m_position + count >= m_length) { + const size_t remaining = m_length - m_position; m_position += remaining; return remaining; - } - else - { + + } else { + m_position += count; return count; } } -size_t seekableInputStreamRegionAdapter::getPosition() const -{ +size_t seekableInputStreamRegionAdapter::getPosition() const { + return m_position; } -void seekableInputStreamRegionAdapter::seek(const size_t pos) -{ - if (pos > m_length) +void seekableInputStreamRegionAdapter::seek(const size_t pos) { + + if (pos > m_length) { m_position = m_length; - else + } else { m_position = pos; + } } } // utility } // vmime - diff --git a/src/vmime/utility/seekableInputStreamRegionAdapter.hpp b/src/vmime/utility/seekableInputStreamRegionAdapter.hpp index 70ab8ff3..8406b29e 100644 --- a/src/vmime/utility/seekableInputStreamRegionAdapter.hpp +++ b/src/vmime/utility/seekableInputStreamRegionAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,9 +34,8 @@ namespace utility { /** An adapter for reading a limited region of a seekable input stream. */ +class VMIME_EXPORT seekableInputStreamRegionAdapter : public seekableInputStream { -class VMIME_EXPORT seekableInputStreamRegionAdapter : public seekableInputStream -{ public: /** Creates a new adapter for a seekableInputStream. @@ -45,8 +44,11 @@ public: * @param begin start position in source stream * @param length region length in source stream */ - seekableInputStreamRegionAdapter(const shared_ptr & stream, - const size_t begin, const size_t length); + seekableInputStreamRegionAdapter( + const shared_ptr & stream, + const size_t begin, + const size_t length + ); bool eof() const; void reset(); @@ -69,4 +71,3 @@ private: #endif // VMIME_UTILITY_SEEKABLEINPUTSTREAMREGIONADAPTER_HPP_INCLUDED - diff --git a/src/vmime/utility/stream.cpp b/src/vmime/utility/stream.cpp index 232b23c7..96f99cbb 100644 --- a/src/vmime/utility/stream.cpp +++ b/src/vmime/utility/stream.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,12 +29,11 @@ namespace vmime { namespace utility { -size_t stream::getBlockSize() -{ +size_t stream::getBlockSize() { + return 32768; // 32 KB } } // utility } // vmime - diff --git a/src/vmime/utility/stream.hpp b/src/vmime/utility/stream.hpp index 980a2407..9aa13923 100644 --- a/src/vmime/utility/stream.hpp +++ b/src/vmime/utility/stream.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,12 +36,10 @@ namespace vmime { namespace utility { - /** Base class for input/output stream. */ +class VMIME_EXPORT stream : public object, private noncopyable { -class VMIME_EXPORT stream : public object, private noncopyable -{ public: virtual ~stream() { } diff --git a/src/vmime/utility/streamUtils.cpp b/src/vmime/utility/streamUtils.cpp index f3cc69ef..793973c2 100644 --- a/src/vmime/utility/streamUtils.cpp +++ b/src/vmime/utility/streamUtils.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,29 +32,33 @@ namespace vmime { namespace utility { -outputStream& operator<<(outputStream& os, const byte_t c) -{ +outputStream& operator<<(outputStream& os, const byte_t c) { + os.write(&c, 1); - return (os); + return os; } -outputStream& operator<<(outputStream& os, const string& str) -{ +outputStream& operator<<(outputStream& os, const string& str) { + os.write(str.data(), str.length()); - return (os); + return os; } -size_t bufferedStreamCopy(inputStream& is, outputStream& os) -{ +size_t bufferedStreamCopy(inputStream& is, outputStream& os) { + return bufferedStreamCopy(is, os, 0, NULL); } -size_t bufferedStreamCopyRange(inputStream& is, outputStream& os, - const size_t start, const size_t length) -{ +size_t bufferedStreamCopyRange( + inputStream& is, + outputStream& os, + const size_t start, + const size_t length +) { + const size_t blockSize = std::min(is.getBlockSize(), os.getBlockSize()); @@ -65,13 +69,12 @@ size_t bufferedStreamCopyRange(inputStream& is, outputStream& os, byte_t* buffer = &vbuffer.front(); size_t total = 0; - while (!is.eof() && total < length) - { + while (!is.eof() && total < length) { + const size_t remaining = std::min(length - total, blockSize); const size_t read = is.read(buffer, remaining); - if (read != 0) - { + if (read != 0) { os.write(buffer, read); total += read; } @@ -81,9 +84,13 @@ size_t bufferedStreamCopyRange(inputStream& is, outputStream& os, } -size_t bufferedStreamCopy(inputStream& is, outputStream& os, - const size_t length, progressListener* progress) -{ +size_t bufferedStreamCopy( + inputStream& is, + outputStream& os, + const size_t length, + progressListener* progress +) { + const size_t blockSize = std::min(is.getBlockSize(), os.getBlockSize()); @@ -92,30 +99,32 @@ size_t bufferedStreamCopy(inputStream& is, outputStream& os, byte_t* buffer = &vbuffer.front(); size_t total = 0; - if (progress != NULL) + if (progress != NULL) { progress->start(length); + } + + while (!is.eof()) { - while (!is.eof()) - { const size_t read = is.read(buffer, blockSize); - if (read != 0) - { + if (read != 0) { + os.write(buffer, read); total += read; - if (progress != NULL) + if (progress != NULL) { progress->progress(total, std::max(total, length)); + } } } - if (progress != NULL) + if (progress != NULL) { progress->stop(total); + } - return (total); + return total; } } // utility } // vmime - diff --git a/src/vmime/utility/streamUtils.hpp b/src/vmime/utility/streamUtils.hpp index 406b6b64..5d81fbe2 100644 --- a/src/vmime/utility/streamUtils.hpp +++ b/src/vmime/utility/streamUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,7 +41,6 @@ namespace utility { * @param os output stream (destination for data) * @return number of bytes copied */ - VMIME_EXPORT size_t bufferedStreamCopy(inputStream& is, outputStream& os); /** Copy data from one stream into another stream using a buffered method @@ -53,9 +52,12 @@ VMIME_EXPORT size_t bufferedStreamCopy(inputStream& is, outputStream& os); * @param length maximum number of bytes to copy * @return number of bytes copied */ - -VMIME_EXPORT size_t bufferedStreamCopyRange(inputStream& is, outputStream& os, - const size_t start, const size_t length); +VMIME_EXPORT size_t bufferedStreamCopyRange( + inputStream& is, + outputStream& os, + const size_t start, + const size_t length +); /** Copy data from one stream into another stream using a buffered method * and notify progress state of the operation. @@ -66,9 +68,12 @@ VMIME_EXPORT size_t bufferedStreamCopyRange(inputStream& is, outputStream& os, * @param progress listener to notify * @return number of bytes copied */ - -VMIME_EXPORT size_t bufferedStreamCopy(inputStream& is, outputStream& os, - const size_t length, progressListener* progress); +VMIME_EXPORT size_t bufferedStreamCopy( + inputStream& is, + outputStream& os, + const size_t length, + progressListener* progress +); } // utility @@ -76,4 +81,3 @@ VMIME_EXPORT size_t bufferedStreamCopy(inputStream& is, outputStream& os, #endif // VMIME_UTILITY_STREAMUTILS_HPP_INCLUDED - diff --git a/src/vmime/utility/stringProxy.cpp b/src/vmime/utility/stringProxy.cpp index 67c96816..57d44069 100644 --- a/src/vmime/utility/stringProxy.cpp +++ b/src/vmime/utility/stringProxy.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,116 +34,128 @@ namespace utility { stringProxy::stringProxy() - : m_start(0), m_end(0) -{ + : m_start(0), + m_end(0) { + } stringProxy::stringProxy(const stringProxy& s) - : m_buffer(s.m_buffer), m_start(s.m_start), m_end(s.m_end) -{ + : m_buffer(s.m_buffer), + m_start(s.m_start), + m_end(s.m_end) { + } stringProxy::stringProxy(const string& s, const size_t start, const size_t end) - : m_buffer(s), m_start(start), - m_end(end == std::numeric_limits ::max() ? s.length() : end) -{ + : m_buffer(s), + m_start(start), + m_end(end == std::numeric_limits ::max() ? s.length() : end) { + } -void stringProxy::set(const string& s, const size_t start, const size_t end) -{ +void stringProxy::set(const string& s, const size_t start, const size_t end) { + m_buffer = s; m_start = start; - if (end == std::numeric_limits ::max()) + if (end == std::numeric_limits ::max()) { m_end = s.length(); - else + } else { m_end = end; + } } -void stringProxy::detach() -{ +void stringProxy::detach() { + m_buffer.clear(); m_start = m_end = 0; } -stringProxy& stringProxy::operator=(const stringProxy& s) -{ +stringProxy& stringProxy::operator=(const stringProxy& s) { + m_buffer = s.m_buffer; m_start = s.m_start; m_end = s.m_end; - return (*this); + return *this; } -stringProxy& stringProxy::operator=(const string& s) -{ +stringProxy& stringProxy::operator=(const string& s) { + m_buffer = s; m_start = 0; m_end = s.length(); - return (*this); + return *this; } -void stringProxy::extract(outputStream& os, const size_t start, const size_t end, - utility::progressListener* progress) const -{ +void stringProxy::extract( + outputStream& os, + const size_t start, + const size_t end, + utility::progressListener* progress +) const { + size_t len = 0; - if (end == std::numeric_limits ::max()) + if (end == std::numeric_limits ::max()) { len = m_end - start - m_start; - else if (end > start) + } else if (end > start) { len = end - start; + } - if (progress) + if (progress) { progress->start(len); + } os.write(m_buffer.data() + m_start + start, len); - if (progress) - { + if (progress) { progress->progress(len, len); progress->stop(len); } } -size_t stringProxy::length() const -{ - return (m_end - m_start); +size_t stringProxy::length() const { + + return m_end - m_start; } -size_t stringProxy::start() const -{ - return (m_start); +size_t stringProxy::start() const { + + return m_start; } -size_t stringProxy::end() const -{ - return (m_end); +size_t stringProxy::end() const { + + return m_end; } -std::ostream& operator<<(std::ostream& os, const stringProxy& s) -{ +std::ostream& operator<<(std::ostream& os, const stringProxy& s) { + outputStreamAdapter adapter(os); s.extract(adapter); - return (os); + + return os; } -outputStream& operator<<(outputStream& os, const stringProxy& s) -{ +outputStream& operator<<(outputStream& os, const stringProxy& s) { + s.extract(os); - return (os); + + return os; } diff --git a/src/vmime/utility/stringProxy.hpp b/src/vmime/utility/stringProxy.hpp index e5efa135..ac883c02 100644 --- a/src/vmime/utility/stringProxy.hpp +++ b/src/vmime/utility/stringProxy.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,9 +41,8 @@ namespace utility { * advantage of the COW (copy-on-write) system that might * be used in "std::string" implementation. */ +class VMIME_EXPORT stringProxy { -class VMIME_EXPORT stringProxy -{ public: // Consruction @@ -60,7 +59,12 @@ public: // Extract some portion (or whole) of the string // and output it into a stream. - void extract(outputStream& os, const size_t start = 0, const size_t end = std::numeric_limits ::max(), utility::progressListener* progress = NULL) const; + void extract( + outputStream& os, + const size_t start = 0, + const size_t end = std::numeric_limits ::max(), + utility::progressListener* progress = NULL + ) const; // Return the "virtual" length of the string size_t length() const; diff --git a/src/vmime/utility/stringUtils.cpp b/src/vmime/utility/stringUtils.cpp index 9567eac6..5f3c727a 100644 --- a/src/vmime/utility/stringUtils.cpp +++ b/src/vmime/utility/stringUtils.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,30 +29,32 @@ namespace vmime { namespace utility { -bool stringUtils::isStringEqualNoCase - (const string& s1, const char* s2, const size_t n) -{ +bool stringUtils::isStringEqualNoCase(const string& s1, const char* s2, const size_t n) { + // 'n' is the number of characters to compare // 's2' must be in lowercase letters only - if (s1.length() < n) + if (s1.length() < n) { return (false); + } const std::ctype & fac = std::use_facet >(std::locale::classic()); bool equal = true; - for (size_t i = 0 ; equal && i < n ; ++i) + for (size_t i = 0 ; equal && i < n ; ++i) { equal = (fac.tolower(static_cast (s1[i])) == s2[i]); + } - return (equal); + return equal; } -bool stringUtils::isStringEqualNoCase(const string& s1, const string& s2) -{ - if (s1.length() != s2.length()) - return (false); +bool stringUtils::isStringEqualNoCase(const string& s1, const string& s2) { + + if (s1.length() != s2.length()) { + return false; + } const std::ctype & fac = std::use_facet >(std::locale::classic()); @@ -60,19 +62,24 @@ bool stringUtils::isStringEqualNoCase(const string& s1, const string& s2) bool equal = true; const string::const_iterator end = s1.end(); - for (string::const_iterator i = s1.begin(), j = s2.begin(); i != end ; ++i, ++j) + for (string::const_iterator i = s1.begin(), j = s2.begin(); i != end ; ++i, ++j) { equal = (fac.tolower(static_cast (*i)) == fac.tolower(static_cast (*j))); + } - return (equal); + return equal; } -bool stringUtils::isStringEqualNoCase - (const string::const_iterator begin, const string::const_iterator end, - const char* s, const size_t n) -{ - if (static_cast (end - begin) < n) - return (false); +bool stringUtils::isStringEqualNoCase( + const string::const_iterator begin, + const string::const_iterator end, + const char* s, + const size_t n +) { + + if (static_cast (end - begin) < n) { + return false; + } const std::ctype & fac = std::use_facet >(std::locale::classic()); @@ -81,91 +88,98 @@ bool stringUtils::isStringEqualNoCase char* c = const_cast(s); size_t r = n; - for (string::const_iterator i = begin ; equal && r && *c ; ++i, ++c, --r) + for (string::const_iterator i = begin ; equal && r && *c ; ++i, ++c, --r) { equal = (fac.tolower(static_cast (*i)) == static_cast (*c)); + } - return (r == 0 && equal); + return r == 0 && equal; } -const string stringUtils::toLower(const string& str) -{ +const string stringUtils::toLower(const string& str) { + const std::ctype & fac = std::use_facet >(std::locale::classic()); string out; out.resize(str.size()); - for (size_t i = 0, len = str.length() ; i < len ; ++i) + for (size_t i = 0, len = str.length() ; i < len ; ++i) { out[i] = fac.tolower(static_cast (str[i])); + } return out; } -const string stringUtils::toUpper(const string& str) -{ +const string stringUtils::toUpper(const string& str) { + const std::ctype & fac = std::use_facet >(std::locale::classic()); string out; out.resize(str.size()); - for (size_t i = 0, len = str.length() ; i < len ; ++i) + for (size_t i = 0, len = str.length() ; i < len ; ++i) { out[i] = fac.toupper(static_cast (str[i])); + } return out; } -const string stringUtils::trim(const string& str) -{ +const string stringUtils::trim(const string& str) { + string::const_iterator b = str.begin(); string::const_iterator e = str.end(); - if (b != e) - { + if (b != e) { + for ( ; b != e && parserHelpers::isSpace(*b) ; ++b) {} for ( ; e != b && parserHelpers::isSpace(*(e - 1)) ; --e) {} } - return (string(b, e)); + return string(b, e); } -size_t stringUtils::countASCIIchars - (const string::const_iterator begin, const string::const_iterator end) -{ +size_t stringUtils::countASCIIchars( + const string::const_iterator begin, + const string::const_iterator end +) { + size_t count = 0; - for (string::const_iterator i = begin ; i != end ; ++i) - { - if (parserHelpers::isAscii(*i)) - { - if (*i != '=' || ((i + 1) != end && *(i + 1) != '?')) // To avoid bad behaviour... + for (string::const_iterator i = begin ; i != end ; ++i) { + + if (parserHelpers::isAscii(*i)) { + + if (*i != '=' || ((i + 1) != end && *(i + 1) != '?')) { // To avoid bad behaviour... ++count; + } } } - return (count); + return count; } -bool stringUtils::is7bit(const string& str) -{ +bool stringUtils::is7bit(const string& str) { + return countASCIIchars(str.begin(), str.end()) == str.length(); } -size_t stringUtils::findFirstNonASCIIchar - (const string::const_iterator begin, const string::const_iterator end) -{ +size_t stringUtils::findFirstNonASCIIchar( + const string::const_iterator begin, + const string::const_iterator end +) { + size_t pos = string::npos; - for (string::const_iterator i = begin ; i != end ; ++i) - { - if (!parserHelpers::isAscii(*i)) - { + for (string::const_iterator i = begin ; i != end ; ++i) { + + if (!parserHelpers::isAscii(*i)) { pos = i - begin; break; } @@ -175,34 +189,36 @@ size_t stringUtils::findFirstNonASCIIchar } -const string stringUtils::unquote(const string& str) -{ - if (str.length() < 2) - return str; +const string stringUtils::unquote(const string& str) { - if (str[0] != '"' || str[str.length() - 1] != '"') + if (str.length() < 2) { return str; + } + + if (str[0] != '"' || str[str.length() - 1] != '"') { + return str; + } string res; res.reserve(str.length()); bool escaped = false; - for (string::const_iterator it = str.begin() + 1, end = str.end() - 1 ; it != end ; ++it) - { + for (string::const_iterator it = str.begin() + 1, end = str.end() - 1 ; it != end ; ++it) { + const char c = *it; - if (escaped) - { + if (escaped) { + res += c; escaped = false; - } - else if (!escaped && c == '\\') - { + + } else if (!escaped && c == '\\') { + escaped = true; - } - else - { + + } else { + res += c; } } @@ -211,20 +227,23 @@ const string stringUtils::unquote(const string& str) } -bool stringUtils::needQuoting(const string& str, const string& specialChars) -{ +bool stringUtils::needQuoting(const string& str, const string& specialChars) { + return str.find_first_of(specialChars.c_str()) != string::npos; } -string stringUtils::quote - (const string& str, const string& escapeSpecialChars, const string& escapeChar) -{ +string stringUtils::quote( + const string& str, + const string& escapeSpecialChars, + const string& escapeChar +) { + std::ostringstream oss; size_t lastPos = 0, pos = 0; - while ((pos = str.find_first_of(escapeSpecialChars, lastPos)) != string::npos) - { + while ((pos = str.find_first_of(escapeSpecialChars, lastPos)) != string::npos) { + oss << str.substr(lastPos, pos - lastPos) << escapeChar << str[pos]; @@ -238,22 +257,22 @@ string stringUtils::quote } -bool stringUtils::isValidHostname(const vmime::string& hostname) -{ +bool stringUtils::isValidHostname(const vmime::string& hostname) { + short numberOfDots = 0; return isValidFQDNImpl(hostname, &numberOfDots); } -bool stringUtils::isValidFQDN(const vmime::string& fqdn) -{ +bool stringUtils::isValidFQDN(const vmime::string& fqdn) { + short numberOfDots = 0; return isValidFQDNImpl(fqdn, &numberOfDots) && numberOfDots >= 2; } -bool stringUtils::isValidFQDNImpl(const vmime::string& fqdn, short* numberOfDots) -{ +bool stringUtils::isValidFQDNImpl(const vmime::string& fqdn, short* numberOfDots) { + bool alphanumOnly = true; bool invalid = false; bool previousIsDot = true; // dot is not allowed as the first char @@ -261,8 +280,8 @@ bool stringUtils::isValidFQDNImpl(const vmime::string& fqdn, short* numberOfDots *numberOfDots = 0; - for (size_t i = 0, n = fqdn.length() ; alphanumOnly && !invalid && i < n ; ++i) - { + for (size_t i = 0, n = fqdn.length() ; alphanumOnly && !invalid && i < n ; ++i) { + const char c = fqdn[i]; alphanumOnly = ( @@ -273,36 +292,35 @@ bool stringUtils::isValidFQDNImpl(const vmime::string& fqdn, short* numberOfDots || (c == '-') ); - if (c == '-') - { - if (previousIsDot) - { + if (c == '-') { + + if (previousIsDot) { invalid = true; // dash is not allowed as the first char } previousIsDot = false; previousIsDash = true; - } - else if (c == '.') - { - if (previousIsDash) - { + + } else if (c == '.') { + + if (previousIsDash) { + invalid = true; // dash is not allowed as the first char - } - else if (previousIsDot) - { + + } else if (previousIsDot) { + invalid = true; // consecutive dots are not allowed - } - else - { + + } else { + ++*numberOfDots; previousIsDot = true; } previousIsDash = false; - } - else - { + + } else { + previousIsDot = false; previousIsDash = false; } diff --git a/src/vmime/utility/stringUtils.hpp b/src/vmime/utility/stringUtils.hpp index 012b08e5..46789406 100644 --- a/src/vmime/utility/stringUtils.hpp +++ b/src/vmime/utility/stringUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,9 +37,8 @@ namespace utility { /** Miscellaneous functions related to strings. */ +class VMIME_EXPORT stringUtils { -class VMIME_EXPORT stringUtils -{ public: /** Makes a string from bytes. @@ -48,8 +47,8 @@ public: * @param count number of bytes to use from buffer * @return a string object containing a copy of the specified data */ - static const string makeStringFromBytes(const byte_t* data, const size_t count) - { + static const string makeStringFromBytes(const byte_t* data, const size_t count) { + return string(reinterpret_cast (data), count); } @@ -58,8 +57,8 @@ public: * @param str string * @return pointer to the first byte of the string */ - static const byte_t* bytesFromString(const string& str) - { + static const byte_t* bytesFromString(const string& str) { + return reinterpret_cast (str.data()); } @@ -68,8 +67,8 @@ public: * @param str string * @return pointer to the first byte of the string */ - static const byte_t* bytesFromString(const char* str) - { + static const byte_t* bytesFromString(const char* str) { + return reinterpret_cast (str); } @@ -80,8 +79,8 @@ public: * @param count number of bytes to use from buffer * @return a reference to modified string */ - static string& appendBytesToString(string& str, const byte_t* data, const size_t count) - { + static string& appendBytesToString(string& str, const byte_t* data, const size_t count) { + str.append(reinterpret_cast (data), count); return str; } @@ -114,7 +113,12 @@ public: * @param n length of the second string * @return true if the two strings compare equally, false otherwise */ - static bool isStringEqualNoCase(const string::const_iterator begin, const string::const_iterator end, const char* s, const size_t n); + static bool isStringEqualNoCase( + const string::const_iterator begin, + const string::const_iterator end, + const char* s, + const size_t n + ); /** Transform all the characters in a string to lower-case. * \warning Use this with ASCII-only strings. @@ -146,7 +150,10 @@ public: * @param end end position * @return number of ASCII characters */ - static size_t countASCIIchars(const string::const_iterator begin, const string::const_iterator end); + static size_t countASCIIchars( + const string::const_iterator begin, + const string::const_iterator end + ); /** Returns whether the specified string is composed exclusively * of 7-bit ASCII characters. @@ -162,7 +169,10 @@ public: * @param end end position * @return position since begin, or string::npos */ - static size_t findFirstNonASCIIchar(const string::const_iterator begin, const string::const_iterator end); + static size_t findFirstNonASCIIchar( + const string::const_iterator begin, + const string::const_iterator end + ); /** Convert the specified value to a string value. * @@ -170,14 +180,14 @@ public: * @return value converted from type 'TYPE' */ template - static const string toString(const TYPE& value) - { + static const string toString(const TYPE& value) { + std::ostringstream oss; oss.imbue(std::locale::classic()); oss << value; - return (oss.str()); + return oss.str(); } /** Convert the specified string value to a value of @@ -187,8 +197,8 @@ public: * @return value converted into type 'TYPE' */ template - static const TYPE fromString(const string& value) - { + static const TYPE fromString(const string& value) { + TYPE ret; std::istringstream iss(value); @@ -196,7 +206,7 @@ public: iss >> ret; - return (ret); + return ret; } /** Unquote the specified string and transform escaped characters. @@ -213,8 +223,10 @@ public: * string to be quoted * @return true if the string needs to be quoted, false otherwise */ - static bool needQuoting(const string& str, - const string& specialChars = " \t\"(),:;<>@[\\]"); + static bool needQuoting( + const string& str, + const string& specialChars = " \t\"(),:;<>@[\\]" + ); /** Quotes the specified string. * @@ -223,7 +235,11 @@ public: * @param escapeChar character that will be used for escaping (eg. '\') * @return quoted string */ - static string quote(const string& str, const string& escapeSpecialChars, const string& escapeChar); + static string quote( + const string& str, + const string& escapeSpecialChars, + const string& escapeChar + ); /** Return whether the specified string is a valid host name * or domain name. diff --git a/src/vmime/utility/sync/autoLock.hpp b/src/vmime/utility/sync/autoLock.hpp index a0ac90f6..a3d3a7cb 100644 --- a/src/vmime/utility/sync/autoLock.hpp +++ b/src/vmime/utility/sync/autoLock.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,20 +35,19 @@ namespace sync { /** Critical section wrapper class */ - template -class VMIME_EXPORT autoLock : public object -{ +class VMIME_EXPORT autoLock : public object { + public: autoLock(const shared_ptr & mutex) - : m_mutex(mutex) - { + : m_mutex(mutex) { + m_mutex->lock(); } - ~autoLock() - { + ~autoLock() { + m_mutex->unlock(); } diff --git a/src/vmime/utility/sync/criticalSection.cpp b/src/vmime/utility/sync/criticalSection.cpp index f2512d14..a1013cd9 100644 --- a/src/vmime/utility/sync/criticalSection.cpp +++ b/src/vmime/utility/sync/criticalSection.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,13 +29,13 @@ namespace utility { namespace sync { -criticalSection::criticalSection() -{ +criticalSection::criticalSection() { + } -criticalSection::~criticalSection() -{ +criticalSection::~criticalSection() { + } diff --git a/src/vmime/utility/sync/criticalSection.hpp b/src/vmime/utility/sync/criticalSection.hpp index 9703d73c..1e7008c6 100644 --- a/src/vmime/utility/sync/criticalSection.hpp +++ b/src/vmime/utility/sync/criticalSection.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,9 +35,8 @@ namespace sync { /** Critical section class. */ +class VMIME_EXPORT criticalSection : public object { -class VMIME_EXPORT criticalSection : public object -{ public: virtual ~criticalSection(); diff --git a/src/vmime/utility/url.cpp b/src/vmime/utility/url.cpp index 4d7e2920..59cb1f51 100644 --- a/src/vmime/utility/url.cpp +++ b/src/vmime/utility/url.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,28 +44,38 @@ const string url::PROTOCOL_FTP = "ftp"; -url::url(const string& s) -{ +url::url(const string& s) { + parse(s); } -url::url(const url& u) -{ +url::url(const url& u) { + operator=(u); } -url::url(const string& protocol, const string& host, const port_t port, - const string& path, const string& username, const string& password) - : m_protocol(protocol), m_username(username), m_password(password), - m_host(host), m_port(port), m_path(path) -{ +url::url( + const string& protocol, + const string& host, + const port_t port, + const string& path, + const string& username, + const string& password +) + : m_protocol(protocol), + m_username(username), + m_password(password), + m_host(host), + m_port(port), + m_path(path) { + } -url& url::operator=(const url& u) -{ +url& url::operator=(const url& u) { + m_protocol = u.m_protocol; m_username = u.m_username; @@ -78,37 +88,37 @@ url& url::operator=(const url& u) m_params = u.m_params; - return (*this); + return *this; } -url& url::operator=(const string& s) -{ +url& url::operator=(const string& s) { + parse(s); - return (*this); + return *this; } -url::operator string() const -{ +url::operator string() const { + return build(); } -const string url::build() const -{ +const string url::build() const { + std::ostringstream oss; oss.imbue(std::locale::classic()); oss << m_protocol << "://"; - if (!m_username.empty()) - { + if (!m_username.empty()) { + oss << urlUtils::encode(m_username); - if (!m_password.empty()) - { + if (!m_password.empty()) { + oss << ":"; oss << urlUtils::encode(m_password); } @@ -118,31 +128,33 @@ const string url::build() const oss << urlUtils::encode(m_host); - if (m_port != UNSPECIFIED_PORT) - { + if (m_port != UNSPECIFIED_PORT) { + oss << ":"; oss << m_port; } - if (!m_path.empty()) - { + if (!m_path.empty()) { + oss << "/"; oss << urlUtils::encode(m_path); } - if (!m_params.empty()) - { - if (m_path.empty()) + if (!m_params.empty()) { + + if (m_path.empty()) { oss << "/"; + } oss << "?"; for (std::map ::const_iterator it = m_params.begin() ; - it != m_params.end() ; ++it) - { - if (it != m_params.begin()) + it != m_params.end() ; ++it) { + + if (it != m_params.begin()) { oss << "&"; + } oss << urlUtils::encode((*it).first); oss << "="; @@ -150,22 +162,28 @@ const string url::build() const } } - return (oss.str()); + return oss.str(); } -void url::parse(const string& str) -{ +void url::parse(const string& str) { + // Protocol const size_t protoEnd = str.find("://"); - if (protoEnd == string::npos) throw exceptions::malformed_url("No protocol separator"); + + if (protoEnd == string::npos) { + throw exceptions::malformed_url("No protocol separator"); + } const string proto = utility::stringUtils::toLower(string(str.begin(), str.begin() + protoEnd)); // Username/password size_t slashPos = str.find('/', protoEnd + 3); - if (slashPos == string::npos) slashPos = str.length(); + + if (slashPos == string::npos) { + slashPos = str.length(); + } size_t atPos = str.rfind('@', slashPos); string hostPart; @@ -173,32 +191,32 @@ void url::parse(const string& str) string username; string password; - if (proto == PROTOCOL_FILE) - { + if (proto == PROTOCOL_FILE) { + // No user name, password and host part. slashPos = protoEnd + 3; - } - else - { - if (atPos != string::npos && atPos < slashPos) - { + + } else { + + if (atPos != string::npos && atPos < slashPos) { + const string userPart(str.begin() + protoEnd + 3, str.begin() + atPos); const size_t colonPos = userPart.find(':'); - if (colonPos == string::npos) - { + if (colonPos == string::npos) { + username = userPart; - } - else - { + + } else { + username = string(userPart.begin(), userPart.begin() + colonPos); password = string(userPart.begin() + colonPos + 1, userPart.end()); } hostPart = string(str.begin() + atPos + 1, str.begin() + slashPos); - } - else - { + + } else { + hostPart = string(str.begin() + protoEnd + 3, str.begin() + slashPos); } } @@ -209,12 +227,12 @@ void url::parse(const string& str) string host; string port; - if (colonPos == string::npos) - { + if (colonPos == string::npos) { + host = utility::stringUtils::trim(hostPart); - } - else - { + + } else { + host = utility::stringUtils::trim(string(hostPart.begin(), hostPart.begin() + colonPos)); port = utility::stringUtils::trim(string(hostPart.begin() + colonPos + 1, hostPart.end())); } @@ -225,35 +243,40 @@ void url::parse(const string& str) size_t paramSep = path.find_first_of('?'); - if (paramSep != string::npos) - { + if (paramSep != string::npos) { + params = string(path.begin() + paramSep + 1, path.end()); path.erase(path.begin() + paramSep, path.end()); } - if (path == "/") + if (path == "/") { path.clear(); + } // Some sanity check - if (proto.empty()) + if (proto.empty()) { + throw exceptions::malformed_url("No protocol specified"); - else if (host.empty()) - { + + } else if (host.empty()) { + // Accept empty host (eg. "file:///home/vincent/mydoc") - if (proto != PROTOCOL_FILE) + if (proto != PROTOCOL_FILE) { throw exceptions::malformed_url("No host specified"); + } } bool onlyDigit = true; for (string::const_iterator it = port.begin() ; - onlyDigit && it != port.end() ; ++it) - { + onlyDigit && it != port.end() ; ++it) { + onlyDigit = parserHelpers::isDigit(*it); } - if (!onlyDigit) + if (!onlyDigit) { throw exceptions::malformed_url("Port can only contain digits"); + } std::istringstream iss(port); iss.imbue(std::locale::classic()); @@ -261,36 +284,36 @@ void url::parse(const string& str) port_t portNum = 0; iss >> portNum; - if (portNum == 0) + if (portNum == 0) { portNum = UNSPECIFIED_PORT; + } // Extract parameters m_params.clear(); - if (!params.empty()) - { + if (!params.empty()) { + size_t pos = 0; - do - { + do { + const size_t start = pos; pos = params.find_first_of('&', pos); const size_t equal = params.find_first_of('=', start); - const size_t end = - (pos == string::npos ? params.length() : pos); + const size_t end = (pos == string::npos ? params.length() : pos); string name; string value; - if (equal == string::npos || equal > pos) // no value - { + if (equal == string::npos || equal > pos) { // no value + name = string(params.begin() + start, params.begin() + end); value = name; - } - else - { + + } else { + name = string(params.begin() + start, params.begin() + equal); value = string(params.begin() + equal + 1, params.begin() + end); } @@ -300,10 +323,11 @@ void url::parse(const string& str) m_params[name] = value; - if (pos != string::npos) + if (pos != string::npos) { ++pos; - } - while (pos != string::npos); + } + + } while (pos != string::npos); } // Now, save URL parts @@ -319,87 +343,87 @@ void url::parse(const string& str) } -const string& url::getProtocol() const -{ - return (m_protocol); +const string& url::getProtocol() const { + + return m_protocol; } -void url::setProtocol(const string& protocol) -{ +void url::setProtocol(const string& protocol) { + m_protocol = protocol; } -const string& url::getUsername() const -{ - return (m_username); +const string& url::getUsername() const { + + return m_username; } -void url::setUsername(const string& username) -{ +void url::setUsername(const string& username) { + m_username = username; } -const string& url::getPassword() const -{ - return (m_password); +const string& url::getPassword() const { + + return m_password; } -void url::setPassword(const string& password) -{ +void url::setPassword(const string& password) { + m_password = password; } -const string& url::getHost() const -{ - return (m_host); +const string& url::getHost() const { + + return m_host; } -void url::setHost(const string& host) -{ +void url::setHost(const string& host) { + m_host = host; } -port_t url::getPort() const -{ - return (m_port); +port_t url::getPort() const { + + return m_port; } -void url::setPort(const port_t port) -{ +void url::setPort(const port_t port) { + m_port = port; } -const string& url::getPath() const -{ - return (m_path); +const string& url::getPath() const { + + return m_path; } -void url::setPath(const string& path) -{ +void url::setPath(const string& path) { + m_path = path; } -const std::map & url::getParams() const -{ - return (m_params); +const std::map & url::getParams() const { + + return m_params; } -std::map & url::getParams() -{ - return (m_params); +std::map & url::getParams() { + + return m_params; } diff --git a/src/vmime/utility/url.hpp b/src/vmime/utility/url.hpp index 84aba618..8dfa3c45 100644 --- a/src/vmime/utility/url.hpp +++ b/src/vmime/utility/url.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,10 +36,12 @@ namespace utility { /** This class represents a Uniform Resource Locator (a pointer * to a "resource" on the World Wide Web). + * + * Format: + * "protocol://[username[:password]@]host[:port][/path]" */ +class VMIME_EXPORT url { -class VMIME_EXPORT url -{ public: /** Means "port not specified" (use default port). */ @@ -77,8 +79,14 @@ public: * @param username optional user name * @param password optional user password */ - url(const string& protocol, const string& host, const port_t port = UNSPECIFIED_PORT, - const string& path = "", const string& username = "", const string& password = ""); + url( + const string& protocol, + const string& host, + const port_t port = UNSPECIFIED_PORT, + const string& path = "", + const string& username = "", + const string& password = "" + ); /** Return the protocol of the URL (eg: "http"). @@ -182,8 +190,6 @@ private: const string build() const; void parse(const string& str); - // Format: - // "protocol://[username[:password]@]host[:port][/path]" string m_protocol; diff --git a/src/vmime/utility/urlUtils.cpp b/src/vmime/utility/urlUtils.cpp index 20818764..cf51a506 100644 --- a/src/vmime/utility/urlUtils.cpp +++ b/src/vmime/utility/urlUtils.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -29,8 +29,8 @@ namespace vmime { namespace utility { -const string urlUtils::encode(const string& s) -{ +const string urlUtils::encode(const string& s) { + static const string RESERVED_CHARS = /* reserved */ "$&+,/:;=?@" /* unsafe */ "<>#%{}[]|\\^\"~`"; @@ -38,18 +38,18 @@ const string urlUtils::encode(const string& s) string result; result.reserve(s.length()); - for (string::const_iterator it = s.begin() ; it != s.end() ; ++it) - { + for (string::const_iterator it = s.begin() ; it != s.end() ; ++it) { + const char c = *it; if (parserHelpers::isPrint(c) && !parserHelpers::isSpace(c) && static_cast (c) <= 127 && - RESERVED_CHARS.find(c) == string::npos) - { + RESERVED_CHARS.find(c) == string::npos) { + result += c; - } - else - { + + } else { + char hex[4]; const unsigned char k = static_cast (c); @@ -62,70 +62,70 @@ const string urlUtils::encode(const string& s) } } - return (result); + return result; } -const string urlUtils::decode(const string& s) -{ +const string urlUtils::decode(const string& s) { + string result; result.reserve(s.length()); - for (string::const_iterator it = s.begin() ; it != s.end() ; ) - { + for (string::const_iterator it = s.begin() ; it != s.end() ; ) { + const char c = *it; - switch (c) - { - case '%': - { - ++it; // skip '%' + switch (c) { - const char_t p = (it != s.end() ? *(it++) : 0); - const char_t q = (it != s.end() ? *(it++) : 0); + case '%': { - unsigned int r = 0; + ++it; // skip '%' - switch (p) - { - case 0: r = '%'; break; - case 'a': case 'A': r = 10; break; - case 'b': case 'B': r = 11; break; - case 'c': case 'C': r = 12; break; - case 'd': case 'D': r = 13; break; - case 'e': case 'E': r = 14; break; - case 'f': case 'F': r = 15; break; - default: r = p - '0'; break; - } + const char_t p = (it != s.end() ? *(it++) : 0); + const char_t q = (it != s.end() ? *(it++) : 0); - if (q != 0) - { - r *= 16; + unsigned int r = 0; - switch (q) - { - case 'a': case 'A': r += 10; break; - case 'b': case 'B': r += 11; break; - case 'c': case 'C': r += 12; break; - case 'd': case 'D': r += 13; break; - case 'e': case 'E': r += 14; break; - case 'f': case 'F': r += 15; break; - default: r += q - '0'; break; + switch (p) { + + case 0: r = '%'; break; + case 'a': case 'A': r = 10; break; + case 'b': case 'B': r = 11; break; + case 'c': case 'C': r = 12; break; + case 'd': case 'D': r = 13; break; + case 'e': case 'E': r = 14; break; + case 'f': case 'F': r = 15; break; + default: r = p - '0'; break; } + + if (q != 0) { + + r *= 16; + + switch (q) { + + case 'a': case 'A': r += 10; break; + case 'b': case 'B': r += 11; break; + case 'c': case 'C': r += 12; break; + case 'd': case 'D': r += 13; break; + case 'e': case 'E': r += 14; break; + case 'f': case 'F': r += 15; break; + default: r += q - '0'; break; + } + } + + result += static_cast (r); + break; } + default: - result += static_cast (r); - break; - } - default: - - result += c; - ++it; - break; + result += c; + ++it; + break; } } - return (result); + return result; } diff --git a/src/vmime/utility/urlUtils.hpp b/src/vmime/utility/urlUtils.hpp index c21e7aa4..54ffa2ac 100644 --- a/src/vmime/utility/urlUtils.hpp +++ b/src/vmime/utility/urlUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,9 +35,8 @@ namespace utility { /** Miscellaneous functions related to URLs. */ +class VMIME_EXPORT urlUtils { -class VMIME_EXPORT urlUtils -{ public: /** Encode extended characters in a URL string (ASCII characters diff --git a/src/vmime/vmime.hpp b/src/vmime/vmime.hpp index 456daea3..16d64a2a 100644 --- a/src/vmime/vmime.hpp +++ b/src/vmime/vmime.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 diff --git a/src/vmime/word.cpp b/src/vmime/word.cpp index d2d53b2b..b8061eee 100644 --- a/src/vmime/word.cpp +++ b/src/vmime/word.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,45 +37,55 @@ #include "vmime/wordEncoder.hpp" -namespace vmime -{ +namespace vmime { word::word() - : m_charset(charset::getLocalCharset()) -{ + : m_charset(charset::getLocalCharset()) { + } word::word(const word& w) - : headerFieldValue(), m_buffer(w.m_buffer), - m_charset(w.m_charset), m_lang(w.m_lang) -{ + : headerFieldValue(), + m_buffer(w.m_buffer), + m_charset(w.m_charset), + m_lang(w.m_lang) { + } word::word(const string& buffer) // Defaults to local charset - : m_buffer(buffer), m_charset(charset::getLocalCharset()) -{ + : m_buffer(buffer), + m_charset(charset::getLocalCharset()) { + } word::word(const string& buffer, const charset& charset) - : m_buffer(buffer), m_charset(charset) -{ + : m_buffer(buffer), + m_charset(charset) { + } word::word(const string& buffer, const charset& charset, const string& lang) - : m_buffer(buffer), m_charset(charset), m_lang(lang) -{ + : m_buffer(buffer), + m_charset(charset), + m_lang(lang) { + } -shared_ptr word::parseNext - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition, parserState* state) -{ +shared_ptr word::parseNext( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition, + parserState* state +) { + size_t pos = position; // Ignore white-spaces: @@ -85,10 +95,11 @@ shared_ptr word::parseNext // Always ignore newlines string whiteSpaces; - while (pos < end && parserHelpers::isSpace(buffer[pos])) - { - if (buffer[pos] != '\r' && buffer[pos] != '\n') // do not include newlines + while (pos < end && parserHelpers::isSpace(buffer[pos])) { + + if (buffer[pos] != '\r' && buffer[pos] != '\n') { // do not include newlines whiteSpaces += buffer[pos]; + } ++pos; } @@ -99,53 +110,56 @@ shared_ptr word::parseNext const charset defaultCharset = ctx.getInternationalizedEmailSupport() ? charset(charsets::UTF_8) : charset(charsets::US_ASCII); - while (pos < end) - { + while (pos < end) { + // End of line: does not occur in the middle of an encoded word. This is // used to remove folding white-spaces from unencoded text. - if (buffer[pos] == '\n') - { + if (buffer[pos] == '\n') { + size_t endPos = pos; - if (pos > position && buffer[pos - 1] == '\r') - { + if (pos > position && buffer[pos - 1] == '\r') { ++pos; --endPos; } - while (pos != end && parserHelpers::isSpace(buffer[pos])) + while (pos != end && parserHelpers::isSpace(buffer[pos])) { ++pos; + } unencoded += buffer.substr(startPos, endPos - startPos); - if (pos != end) // ignore white-spaces at end + if (pos != end) { // ignore white-spaces at end unencoded += ' '; + } startPos = pos; continue; - } + // Start of an encoded word - else if (pos + 8 < end && // 8 = "=?(.+)?(.+)?(.*)?=" - buffer[pos] == '=' && buffer[pos + 1] == '?') - { + } else if (pos + 8 < end && // 8 = "=?(.+)?(.+)?(.*)?=" + buffer[pos] == '=' && buffer[pos + 1] == '?') { + // Check whether there is some unencoded text before unencoded += buffer.substr(startPos, pos - startPos); - if (!unencoded.empty()) - { - if (state->prevIsEncoded && !state->isFirst) + if (!unencoded.empty()) { + + if (state->prevIsEncoded && !state->isFirst) { unencoded = whiteSpaces + unencoded; + } shared_ptr w = make_shared (unencoded, defaultCharset); w->setParsedBounds(position, pos); - if (newPosition) + if (newPosition) { *newPosition = pos; + } state->prevIsEncoded = false; state->isFirst = false; - return (w); + return w; } // ...else find the finish sequence '?=' and return an encoded word @@ -153,32 +167,33 @@ shared_ptr word::parseNext pos += 2; - while (pos < end && buffer[pos] != '?') + while (pos < end && buffer[pos] != '?') { ++pos; + } + + if (pos < end) { - if (pos < end) - { ++pos; // skip '?' between charset and encoding - while (pos < end && buffer[pos] != '?') + while (pos < end && buffer[pos] != '?') { ++pos; + } - if (pos < end) - { + if (pos < end) { ++pos; // skip '?' between encoding and encoded data } } - while (pos < end) - { - if (buffer[pos] == '\n') - { + while (pos < end) { + + if (buffer[pos] == '\n') { + // End of line not allowed in the middle of an encoded word: // treat this text as unencoded text (see *). break; - } - else if (buffer[pos] == '?' && pos + 1 < end && buffer[pos + 1] == '=') - { + + } else if (buffer[pos] == '?' && pos + 1 < end && buffer[pos + 1] == '=') { + // Found the finish sequence break; } @@ -186,59 +201,67 @@ shared_ptr word::parseNext ++pos; } - if (pos == end) // not a valid word (no finish sequence) + if (pos == end) { // not a valid word (no finish sequence) continue; - else if (buffer[pos] == '\n') // (*) + } else if (buffer[pos] == '\n') { // (*) continue; + } pos += 2; // ?= shared_ptr w = make_shared (); w->parseWithState(ctx, buffer, wordStart, pos, NULL, state); - if (newPosition) + if (newPosition) { *newPosition = pos; + } state->prevIsEncoded = true; state->isFirst = false; - return (w); + return w; } ++pos; } - if (startPos != end) - { - if (state->prevIsEncoded && !state->isFirst) + if (startPos != end) { + + if (state->prevIsEncoded && !state->isFirst) { unencoded = whiteSpaces + unencoded; + } unencoded += buffer.substr(startPos, end - startPos); } // Treat unencoded text at the end of the buffer - if (!unencoded.empty()) - { + if (!unencoded.empty()) { + shared_ptr w = make_shared (unencoded, defaultCharset); w->setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } state->prevIsEncoded = false; state->isFirst = false; - return (w); + return w; } - return (null); + return null; } -const std::vector > word::parseMultiple - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +const std::vector > word::parseMultiple( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + std::vector > res; shared_ptr w; @@ -246,31 +269,42 @@ const std::vector > word::parseMultiple parserState state; - while ((w = word::parseNext(ctx, buffer, pos, end, &pos, &state)) != NULL) + while ((w = word::parseNext(ctx, buffer, pos, end, &pos, &state))) { res.push_back(w); + } - if (newPosition) + if (newPosition) { *newPosition = pos; + } - return (res); + return res; } -void word::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ +void word::parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition +) { + parseWithState(ctx, buffer, position, end, newPosition, NULL); } -void word::parseWithState - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition, parserState* state) -{ +void word::parseWithState( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition, + parserState* state +) { + if (position + 6 < end && // 6 = "=?(.+)?(.*)?=" - buffer[position] == '=' && buffer[position + 1] == '?') - { + buffer[position] == '=' && buffer[position + 1] == '?') { + string::const_iterator p = buffer.begin() + position + 2; const string::const_iterator pend = buffer.begin() + end; @@ -278,52 +312,52 @@ void word::parseWithState for ( ; p != pend && *p != '?' ; ++p) {} - if (p != pend) // a charset is specified - { + if (p != pend) { // a charset is specified + const string::const_iterator charsetEnd = p; const string::const_iterator encPos = ++p; // skip '?' for ( ; p != pend && *p != '?' ; ++p) {} - if (p != pend) // an encoding is specified - { + if (p != pend) { // an encoding is specified + //const string::const_iterator encEnd = p; const string::const_iterator dataPos = ++p; // skip '?' for ( ; p != pend && !(*p == '?' && *(p + 1) == '=') ; ++p) {} - if (p != pend) // some data is specified - { + if (p != pend) { // some data is specified + const string::const_iterator dataEnd = p; p += 2; // skip '?=' scoped_ptr theEncoder; // Base-64 encoding - if (*encPos == 'B' || *encPos == 'b') - { + if (*encPos == 'B' || *encPos == 'b') { + theEncoder.reset(new utility::encoder::b64Encoder()); - } + // Quoted-Printable encoding - else if (*encPos == 'Q' || *encPos == 'q') - { + } else if (*encPos == 'Q' || *encPos == 'q') { + theEncoder.reset(new utility::encoder::qpEncoder()); theEncoder->getProperties()["rfc2047"] = true; } - if (theEncoder) - { + if (theEncoder) { + // Extract charset and language const string charsetAndLang(charsetPos, charsetEnd); const string::size_type asteriskPos = charsetAndLang.find('*'); - if (asteriskPos != string::npos) - { + if (asteriskPos != string::npos) { + m_charset = charset(string(charsetAndLang.begin(), charsetAndLang.begin() + asteriskPos)); m_lang = string(charsetAndLang.begin() + asteriskPos + 1, charsetAndLang.end()); - } - else - { + + } else { + m_charset = charset(charsetAndLang); m_lang.clear(); } @@ -332,8 +366,8 @@ void word::parseWithState string encodedBuffer(dataPos, dataEnd); string decodedBuffer; - if (state && !state->undecodedBytes.empty()) - { + if (state && !state->undecodedBytes.empty()) { + encodedBuffer = state->undecodedBytes + encodedBuffer; state->undecodedBytes.clear(); } @@ -347,22 +381,24 @@ void word::parseWithState setParsedBounds(position, p - buffer.begin()); - if (newPosition) + if (newPosition) { *newPosition = (p - buffer.begin()); + } // For Base64 encoding, ensure all bytes have been decoded. // If there are remaining bytes, keep them for the next run. // // This allows decoding some insanities like: // =?utf-8?B?5Lit5?= =?utf-8?B?paH?= - if (*encPos == 'B' || *encPos == 'b') - { + if (*encPos == 'B' || *encPos == 'b') { + const size_t actualEncodedLen = encodedBuffer.length(); const size_t theoricalEncodedLen = ((decodedLen + ((decodedLen % 3) ? (3 - (decodedLen % 3)) : 0) ) / 3) * 4; - if (state && actualEncodedLen != theoricalEncodedLen) + if (state && actualEncodedLen != theoricalEncodedLen) { state->undecodedBytes.assign(dataPos + theoricalEncodedLen, dataEnd); + } } return; @@ -379,74 +415,86 @@ void word::parseWithState setParsedBounds(position, end); - if (newPosition) + if (newPosition) { *newPosition = end; + } } -void word::generateImpl(const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ +void word::generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos +) const { + generate(ctx, os, curLinePos, newLinePos, 0, NULL); } -void word::generate(const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos, const int flags, - generatorState* state) const -{ +void word::generate( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos, + const int flags, + generatorState* state +) const { + size_t curLineLength = curLinePos; generatorState defaultGeneratorState; - if (state == NULL) + if (!state) { state = &defaultGeneratorState; + } // Find out if encoding is forced or required by contents + charset bool encodingNeeded = false; - if ((flags & text::FORCE_NO_ENCODING) != 0) + if ((flags & text::FORCE_NO_ENCODING) != 0) { encodingNeeded = false; - else if ((flags & text::FORCE_ENCODING) != 0) + } else if ((flags & text::FORCE_ENCODING) != 0) { encodingNeeded = true; - else // auto-detect + } else { // auto-detect encodingNeeded = wordEncoder::isEncodingNeeded(ctx, m_buffer, m_charset, m_lang); + } // If text does not need to be encoded, quote the buffer (no folding is performed). if (!encodingNeeded && (flags & text::QUOTE_IF_NEEDED) && - utility::stringUtils::needQuoting(m_buffer)) - { + utility::stringUtils::needQuoting(m_buffer)) { + const string quoted = utility::stringUtils::quote(m_buffer, "\\\"", "\\"); os << '"' << quoted << '"'; curLineLength += 1 + quoted.length() + 1; - } + // If possible and requested (with flag), quote the buffer (no folding is performed). // Quoting is possible if and only if: // - the buffer does not need to be encoded // - the buffer does not contain quoting character (") // - there is enough remaining space on the current line to hold the whole buffer - else if (!encodingNeeded && - (flags & text::QUOTE_IF_POSSIBLE) && - m_buffer.find('"') == string::npos && - (curLineLength + 2 /* 2 x " */ + m_buffer.length()) < ctx.getMaxLineLength()) - { + } else if (!encodingNeeded && + (flags & text::QUOTE_IF_POSSIBLE) && + m_buffer.find('"') == string::npos && + (curLineLength + 2 /* 2 x " */ + m_buffer.length()) < ctx.getMaxLineLength()) { + os << '"' << m_buffer << '"'; curLineLength += 2 + m_buffer.length(); - } + // We will fold lines without encoding them. - else if (!encodingNeeded) - { + } else if (!encodingNeeded) { + string buffer; - if (ctx.getInternationalizedEmailSupport()) - { + if (ctx.getInternationalizedEmailSupport()) { + // Convert the buffer to UTF-8 charset::convert(m_buffer, buffer, m_charset, charsets::UTF_8); - } - else - { + + } else { + // Leave the buffer as-is buffer = m_buffer; } @@ -462,23 +510,23 @@ void word::generate(const generationContext& ctx, utility::outputStream& os, size_t maxRunLength = 0; size_t curRunLength = 0; - for (string::const_iterator p = buffer.begin(), end = buffer.end() ; p != end ; ++p) - { - if (parserHelpers::isSpace(*p)) - { + for (string::const_iterator p = buffer.begin(), end = buffer.end() ; p != end ; ++p) { + + if (parserHelpers::isSpace(*p)) { + maxRunLength = std::max(maxRunLength, curRunLength); curRunLength = 0; - } - else - { + + } else { + curRunLength++; } } maxRunLength = std::max(maxRunLength, curRunLength); - if (((flags & text::FORCE_NO_ENCODING) == 0) && maxRunLength >= ctx.getMaxLineLength() - 3) - { + if (((flags & text::FORCE_NO_ENCODING) == 0) && maxRunLength >= ctx.getMaxLineLength() - 3) { + // Generate with encoding forced generate(ctx, os, curLinePos, newLinePos, flags | text::FORCE_ENCODING, state); return; @@ -494,46 +542,47 @@ void word::generate(const generationContext& ctx, utility::outputStream& os, bool finished = false; bool newLine = false; - while (!finished) - { - for ( ; p != end ; ++p, ++curLineLength) - { + while (!finished) { + + for ( ; p != end ; ++p, ++curLineLength) { + // Exceeded maximum line length, but we have found a white-space // where we can cut the line... - if (curLineLength >= ctx.getMaxLineLength() && lastWSpos != end) + if (curLineLength >= ctx.getMaxLineLength() && lastWSpos != end) { break; + } - if (*p == ' ' || *p == '\t') - { + if (*p == ' ' || *p == '\t') { // Remember the position of this white-space character lastWSpos = p; } } - if (p != end) + if (p != end) { ++curLineLength; + } + + if (p == end || lastWSpos == end) { - if (p == end || lastWSpos == end) - { // If we are here, it means that we have found no whitespace // before the first "maxLineLength" characters. In this case, // we write the full line no matter of the max line length... if (!newLine && p != end && lastWSpos == end && - !state->isFirstWord && curLineStart == buffer.begin()) - { + !state->isFirstWord && curLineStart == buffer.begin()) { + // Here, we are continuing on the line of previous encoded // word, but there is not even enough space to put the // first word of this line, so we start a new line. - if (flags & text::NO_NEW_LINE_SEQUENCE) - { + if (flags & text::NO_NEW_LINE_SEQUENCE) { + os << CRLF; curLineLength = 0; state->lastCharIsSpace = true; - } - else - { + + } else { + os << NEW_LINE_SEQUENCE; curLineLength = NEW_LINE_SEQUENCE_LENGTH; @@ -543,32 +592,38 @@ void word::generate(const generationContext& ctx, utility::outputStream& os, p = curLineStart; lastWSpos = end; newLine = true; - } - else - { - if (!state->isFirstWord && state->prevWordIsEncoded && !state->lastCharIsSpace && !parserHelpers::isSpace(*curLineStart)) + + } else { + + if (!state->isFirstWord && + state->prevWordIsEncoded && + !state->lastCharIsSpace && + !parserHelpers::isSpace(*curLineStart)) { + os << " "; // Separate from previous word + } os << string(curLineStart, p); - if (p != buffer.begin() && parserHelpers::isSpace(*(p - 1))) + if (p != buffer.begin() && parserHelpers::isSpace(*(p - 1))) { state->lastCharIsSpace = true; - else + } else { state->lastCharIsSpace = false; - - if (p == end) - { - finished = true; } - else - { - if (flags & text::NO_NEW_LINE_SEQUENCE) - { + + if (p == end) { + + finished = true; + + } else { + + if (flags & text::NO_NEW_LINE_SEQUENCE) { + os << CRLF; curLineLength = 0; - } - else - { + + } else { + os << NEW_LINE_SEQUENCE; curLineLength = NEW_LINE_SEQUENCE_LENGTH; } @@ -578,34 +633,37 @@ void word::generate(const generationContext& ctx, utility::outputStream& os, newLine = true; } } - } - else - { + + } else { + // In this case, there will not be enough space on the line for all the // characters _after_ the last white-space; so we cut the line at this // last white-space. -#if 1 - if (curLineLength != NEW_LINE_SEQUENCE_LENGTH && !state->isFirstWord && state->prevWordIsEncoded) + if (curLineLength != NEW_LINE_SEQUENCE_LENGTH && + !state->isFirstWord && + state->prevWordIsEncoded) { + os << " "; // Separate from previous word -#endif + } os << string(curLineStart, lastWSpos); - if (lastWSpos > curLineStart && parserHelpers::isSpace(*(lastWSpos - 1))) + if (lastWSpos > curLineStart && parserHelpers::isSpace(*(lastWSpos - 1))) { state->lastCharIsSpace = true; - else + } else { state->lastCharIsSpace = false; + } + + if (flags & text::NO_NEW_LINE_SEQUENCE) { - if (flags & text::NO_NEW_LINE_SEQUENCE) - { os << CRLF; curLineLength = 0; state->lastCharIsSpace = true; - } - else - { + + } else { + os << NEW_LINE_SEQUENCE; curLineLength = NEW_LINE_SEQUENCE_LENGTH; @@ -619,7 +677,7 @@ void word::generate(const generationContext& ctx, utility::outputStream& os, newLine = true; } } - } + /* RFC #2047: 4. Encodings @@ -632,8 +690,8 @@ void word::generate(const generationContext& ctx, utility::outputStream& os, MUST be able to accept either encoding for any character set which it supports. */ - else - { + } else { + // We will encode _AND_ fold lines /* @@ -668,25 +726,25 @@ void word::generate(const generationContext& ctx, utility::outputStream& os, // characters can be encoded, start a new line. bool startNewLine = true; - if (curLineLength + 2 < maxLineLength2) - { + if (curLineLength + 2 < maxLineLength2) { + const size_t remainingSpaceOnLine = maxLineLength2 - curLineLength - 2; - if (remainingSpaceOnLine < minWordLength + 10) - { + if (remainingSpaceOnLine < minWordLength + 10) { + // Space for no more than 10 encoded chars! // It is not worth while to continue on this line... startNewLine = true; - } - else - { + + } else { + // OK, there is enough usable space on the current line. startNewLine = false; } } - if (startNewLine) - { + if (startNewLine) { + os << NEW_LINE_SEQUENCE; curLineLength = NEW_LINE_SEQUENCE_LENGTH; @@ -694,16 +752,16 @@ void word::generate(const generationContext& ctx, utility::outputStream& os, } // Encode and fold input buffer - if (!startNewLine && !state->isFirstWord && !state->lastCharIsSpace) - { + if (!startNewLine && !state->isFirstWord && !state->lastCharIsSpace) { + os << " "; // Separate from previous word ++curLineLength; state->lastCharIsSpace = true; } - for (unsigned int i = 0 ; ; ++i) - { + for (unsigned int i = 0 ; ; ++i) { + // Compute the number of encoded chars that will fit on this line const size_t fit = maxLineLength2 - minWordLength - (i == 0 ? curLineLength : NEW_LINE_SEQUENCE_LENGTH); @@ -711,12 +769,13 @@ void word::generate(const generationContext& ctx, utility::outputStream& os, // Get the next encoded chunk const string chunk = wordEnc.getNextChunk(fit); - if (chunk.empty()) + if (chunk.empty()) { break; + } // Start a new encoded word - if (i != 0) - { + if (i != 0) { + os << NEW_LINE_SEQUENCE; curLineLength = NEW_LINE_SEQUENCE_LENGTH; } @@ -735,33 +794,36 @@ void word::generate(const generationContext& ctx, utility::outputStream& os, } } - if (newLinePos) + if (newLinePos) { *newLinePos = curLineLength; + } state->isFirstWord = false; } -word& word::operator=(const word& w) -{ +word& word::operator=(const word& w) { + m_buffer = w.m_buffer; m_charset = w.m_charset; m_lang = w.m_lang; - return (*this); + + return *this; } -word& word::operator=(const string& s) -{ +word& word::operator=(const string& s) { + m_buffer = s; m_charset = charset::getLocalCharset(); m_lang.clear(); - return (*this); + + return *this; } -void word::copyFrom(const component& other) -{ +void word::copyFrom(const component& other) { + const word& w = dynamic_cast (other); m_buffer = w.m_buffer; @@ -770,102 +832,106 @@ void word::copyFrom(const component& other) } -bool word::operator==(const word& w) const -{ - return (m_charset == w.m_charset && m_buffer == w.m_buffer && m_lang == w.m_lang); +bool word::operator==(const word& w) const { + + return m_charset == w.m_charset && m_buffer == w.m_buffer && m_lang == w.m_lang; } -bool word::operator!=(const word& w) const -{ - return (m_charset != w.m_charset || m_buffer != w.m_buffer || m_lang != w.m_lang); +bool word::operator!=(const word& w) const { + + return m_charset != w.m_charset || m_buffer != w.m_buffer || m_lang != w.m_lang; } -bool word::isEquivalent(const word& other) const -{ +bool word::isEquivalent(const word& other) const { + return getConvertedText(charset(charsets::UTF_8)) == other.getConvertedText(charset(charsets::UTF_8)); } -const string word::getConvertedText(const charset& dest, const charsetConverterOptions& opts) const -{ - if (dest == m_charset) +const string word::getConvertedText( + const charset& dest, + const charsetConverterOptions& opts +) const { + + if (dest == m_charset) { return m_buffer; // no conversion needed + } string out; - try - { + try { + charset::convert(m_buffer, out, m_charset, dest, opts); - } - catch (vmime::exceptions::charset_conv_error& e) - { + + } catch (vmime::exceptions::charset_conv_error& e) { + // Do not fail if charset is not recognized: // copy 'word' as raw text out = m_buffer; } - return (out); + return out; } -shared_ptr word::clone() const -{ +shared_ptr word::clone() const { + return make_shared (m_buffer, m_charset); } -const charset& word::getCharset() const -{ - return (m_charset); +const charset& word::getCharset() const { + + return m_charset; } -void word::setCharset(const charset& ch) -{ +void word::setCharset(const charset& ch) { + m_charset = ch; } -const string word::getLanguage() const -{ +const string word::getLanguage() const { + return m_lang; } -void word::setLanguage(const string& lang) -{ +void word::setLanguage(const string& lang) { + m_lang = lang; } -const string& word::getBuffer() const -{ - return (m_buffer); +const string& word::getBuffer() const { + + return m_buffer; } -string& word::getBuffer() -{ - return (m_buffer); +string& word::getBuffer() { + + return m_buffer; } -bool word::isEmpty() const -{ +bool word::isEmpty() const { + return m_buffer.empty(); } -void word::setBuffer(const string& buffer) -{ +void word::setBuffer(const string& buffer) { + m_buffer = buffer; } -const std::vector > word::getChildComponents() -{ +const std::vector > word::getChildComponents() { + return std::vector >(); } diff --git a/src/vmime/word.hpp b/src/vmime/word.hpp index e7d12715..1565a0be 100644 --- a/src/vmime/word.hpp +++ b/src/vmime/word.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -30,16 +30,14 @@ #include "vmime/charsetConverterOptions.hpp" -namespace vmime -{ +namespace vmime { /** A class that encapsulates an encoded-word (RFC-2047): * some text encoded into one specified charset. */ +class VMIME_EXPORT word : public headerFieldValue { -class VMIME_EXPORT word : public headerFieldValue -{ friend class text; public: @@ -145,8 +143,10 @@ public: * @param opts options for charset conversion * @return word converted to the specified charset */ - const string getConvertedText(const charset& dest, - const charsetConverterOptions& opts = charsetConverterOptions()) const; + const string getConvertedText( + const charset& dest, + const charsetConverterOptions& opts = charsetConverterOptions() + ) const; /** Replace data in this word by data in other word. * @@ -162,13 +162,15 @@ public: #ifndef VMIME_BUILDING_DOC - class generatorState - { + class generatorState { + public: generatorState() - : isFirstWord(true), prevWordIsEncoded(false), lastCharIsSpace(false) - { + : isFirstWord(true), + prevWordIsEncoded(false), + lastCharIsSpace(false) { + } bool isFirstWord; @@ -176,13 +178,14 @@ public: bool lastCharIsSpace; }; - class parserState - { + class parserState { + public: parserState() - : prevIsEncoded(false), isFirst(true) - { + : prevIsEncoded(false), + isFirst(true) { + } bool prevIsEncoded; @@ -194,59 +197,65 @@ public: protected: - void parseImpl - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition = NULL); + void parseImpl( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition = NULL + ); - void generateImpl - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos = 0, - size_t* newLinePos = NULL) const; + void generateImpl( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos = 0, + size_t* newLinePos = NULL + ) const; - void parseWithState - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition, - parserState* state); + void parseWithState( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition, + parserState* state + ); public: using component::generate; #ifndef VMIME_BUILDING_DOC - void generate - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos, - size_t* newLinePos, - const int flags, - generatorState* state) const; + void generate( + const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos, + const int flags, + generatorState* state + ) const; #endif const std::vector > getChildComponents(); private: - static shared_ptr parseNext - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition, - parserState* state); + static shared_ptr parseNext( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition, + parserState* state + ); - static const std::vector > parseMultiple - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition); + static const std::vector > parseMultiple( + const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition + ); // The "m_buffer" of this word holds the data, and this data is encoded diff --git a/src/vmime/wordEncoder.cpp b/src/vmime/wordEncoder.cpp index b40f5371..4f47d047 100644 --- a/src/vmime/wordEncoder.cpp +++ b/src/vmime/wordEncoder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,53 +37,64 @@ #include "vmime/utility/inputStreamStringAdapter.hpp" -namespace vmime -{ +namespace vmime { -wordEncoder::wordEncoder(const string& buffer, const charset& charset, const Encoding encoding) - : m_buffer(buffer), m_pos(0), m_length(buffer.length()), m_charset(charset), m_encoding(encoding) -{ - try - { +wordEncoder::wordEncoder( + const string& buffer, + const charset& charset, + const Encoding encoding +) + : m_buffer(buffer), + m_pos(0), + m_length(buffer.length()), + m_charset(charset), + m_encoding(encoding) { + + try { + string utf8Buffer; - vmime::charset::convert - (buffer, utf8Buffer, charset, vmime::charset(charsets::UTF_8)); + vmime::charset::convert( + buffer, utf8Buffer, charset, vmime::charset(charsets::UTF_8) + ); m_buffer = utf8Buffer; m_length = utf8Buffer.length(); m_simple = false; - } - catch (exceptions::charset_conv_error&) - { + + } catch (exceptions::charset_conv_error&) { + // Ignore exception. // We will fall back on simple encoding. m_simple = true; } - if (m_encoding == ENCODING_AUTO) + if (m_encoding == ENCODING_AUTO) { m_encoding = guessBestEncoding(buffer, charset); - - if (m_encoding == ENCODING_B64) - { - m_encoder = make_shared (); } - else // ENCODING_QP - { + + if (m_encoding == ENCODING_B64) { + + m_encoder = make_shared (); + + } else { // ENCODING_QP + m_encoder = make_shared (); m_encoder->getProperties()["rfc2047"] = true; } } -static size_t getUTF8CharLength - (const string& buffer, const size_t pos, const size_t length) -{ +static size_t getUTF8CharLength( + const string& buffer, + const size_t pos, + const size_t length +) { + // Gives the number of extra bytes in a UTF8 char, given the leading char - static const unsigned char UTF8_EXTRA_BYTES[256] = - { + static const unsigned char UTF8_EXTRA_BYTES[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -105,31 +116,33 @@ static size_t getUTF8CharLength const unsigned char c = buffer[pos]; const unsigned char n = UTF8_EXTRA_BYTES[c]; - if (n < length - pos) + if (n < length - pos) { return n + 1; - else + } else { return 1; + } } -const string wordEncoder::getNextChunk(const size_t maxLength) -{ +const string wordEncoder::getNextChunk(const size_t maxLength) { + const size_t remaining = m_length - m_pos; - if (remaining == 0) + if (remaining == 0) { return string(); + } vmime::string chunk; vmime::utility::outputStreamStringAdapter chunkStream(chunk); // Simple encoding - if (m_simple) - { + if (m_simple) { + // WARNING! Simple encoding can encode a non-integral number of // characters and then may generate incorrectly-formed words! - if (m_encoding == ENCODING_B64) - { + if (m_encoding == ENCODING_B64) { + // Here, we have a formula to compute the maximum number of source // bytes to encode knowing the maximum number of encoded chars. In // Base64 encoding, 3 bytes of input provide 4 bytes of output. @@ -141,17 +154,17 @@ const string wordEncoder::getNextChunk(const size_t maxLength) m_encoder->encode(in, chunkStream); m_pos += inputCount; - } - else // ENCODING_QP - { + + } else { // ENCODING_QP + // Compute exactly how much input bytes are needed to have an output // string length of less than 'maxLength' bytes. In Quoted-Printable // encoding, encoded bytes take 3 bytes. size_t inputCount = 0; size_t outputCount = 0; - while ((inputCount == 0 || outputCount < maxLength) && (inputCount < remaining)) - { + while ((inputCount == 0 || outputCount < maxLength) && (inputCount < remaining)) { + const unsigned char c = m_buffer[m_pos + inputCount]; inputCount++; @@ -164,24 +177,26 @@ const string wordEncoder::getNextChunk(const size_t maxLength) m_encoder->encode(in, chunkStream); m_pos += inputCount; } - } + // Fully RFC-compliant encoding - else - { + } else { + shared_ptr conv = charsetConverter::create(charsets::UTF_8, m_charset); size_t inputCount = 0; size_t outputCount = 0; string encodeBuffer; - while ((inputCount == 0 || outputCount < maxLength) && (inputCount < remaining)) - { + while ((inputCount == 0 || outputCount < maxLength) && (inputCount < remaining)) { + // Get the next UTF8 character const size_t inputCharLength = getUTF8CharLength(m_buffer, m_pos + inputCount, m_length); - const string inputChar(m_buffer.begin() + m_pos + inputCount, - m_buffer.begin() + m_pos + inputCount + inputCharLength); + const string inputChar( + m_buffer.begin() + m_pos + inputCount, + m_buffer.begin() + m_pos + inputCount + inputCharLength + ); // Convert back to original encoding string encodeBytes; @@ -190,15 +205,17 @@ const string wordEncoder::getNextChunk(const size_t maxLength) encodeBuffer += encodeBytes; // Compute number of output bytes - if (m_encoding == ENCODING_B64) - { - outputCount = std::max(static_cast (4), - (encodeBuffer.length() * 4) / 3); - } - else // ENCODING_QP - { - for (size_t i = 0, n = encodeBytes.length() ; i < n ; ++i) - { + if (m_encoding == ENCODING_B64) { + + outputCount = std::max( + static_cast (4), + (encodeBuffer.length() * 4) / 3 + ); + + } else { // ENCODING_QP + + for (size_t i = 0, n = encodeBytes.length() ; i < n ; ++i) { + const unsigned char c = encodeBytes[i]; outputCount += utility::encoder::qpEncoder::RFC2047_getEncodedLength(c); } @@ -218,60 +235,71 @@ const string wordEncoder::getNextChunk(const size_t maxLength) } -wordEncoder::Encoding wordEncoder::getEncoding() const -{ +wordEncoder::Encoding wordEncoder::getEncoding() const { + return m_encoding; } // static -bool wordEncoder::isEncodingNeeded - (const generationContext& ctx, const string& buffer, - const charset& charset, const string& lang) -{ - if (!ctx.getInternationalizedEmailSupport()) - { +bool wordEncoder::isEncodingNeeded( + const generationContext& ctx, + const string& buffer, + const charset& charset, + const string& lang +) { + + if (!ctx.getInternationalizedEmailSupport()) { + // Charset-specific encoding encoding recEncoding; - if (charset.getRecommendedEncoding(recEncoding)) + if (charset.getRecommendedEncoding(recEncoding)) { return true; + } // No encoding is needed if the buffer only contains ASCII chars - if (utility::stringUtils::findFirstNonASCIIchar(buffer.begin(), buffer.end()) != string::npos) + if (utility::stringUtils::findFirstNonASCIIchar(buffer.begin(), buffer.end()) != string::npos) { return true; + } } // Force encoding when there are only ASCII chars, but there is // also at least one of '\n' or '\r' (header fields) - if (buffer.find_first_of("\n\r") != string::npos) + if (buffer.find_first_of("\n\r") != string::npos) { return true; + } // If any RFC-2047 sequence is found in the buffer, encode it - if (buffer.find("=?") != string::npos || buffer.find("?=") != string::npos) + if (buffer.find("=?") != string::npos || buffer.find("?=") != string::npos) { return true; + } // If a language is specified, force encoding - if (!lang.empty()) + if (!lang.empty()) { return true; + } return false; } // static -wordEncoder::Encoding wordEncoder::guessBestEncoding - (const string& buffer, const charset& charset) -{ +wordEncoder::Encoding wordEncoder::guessBestEncoding( + const string& buffer, + const charset& charset +) { + // Charset-specific encoding encoding recEncoding; - if (charset.getRecommendedEncoding(recEncoding)) - { - if (recEncoding == encoding(encodingTypes::QUOTED_PRINTABLE)) + if (charset.getRecommendedEncoding(recEncoding)) { + + if (recEncoding == encoding(encodingTypes::QUOTED_PRINTABLE)) { return ENCODING_QP; - else + } else { return ENCODING_B64; + } } // Use Base64 if more than 40% non-ASCII, or Quoted-Printable else (default) @@ -279,14 +307,14 @@ wordEncoder::Encoding wordEncoder::guessBestEncoding utility::stringUtils::countASCIIchars(buffer.begin(), buffer.end()); const size_t asciiPercent = - (buffer.length() == 0 ? 100 : (100 * asciiCount) / buffer.length()); + buffer.length() == 0 ? 100 : (100 * asciiCount) / buffer.length(); - if (asciiPercent < 60) + if (asciiPercent < 60) { return ENCODING_B64; - else + } else { return ENCODING_QP; + } } } // vmime - diff --git a/src/vmime/wordEncoder.hpp b/src/vmime/wordEncoder.hpp index 8abd3d3c..e37bbe76 100644 --- a/src/vmime/wordEncoder.hpp +++ b/src/vmime/wordEncoder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -28,8 +28,7 @@ #include "vmime/charset.hpp" -namespace vmime -{ +namespace vmime { namespace utility { @@ -41,23 +40,25 @@ class encoder; } // utility -/** Encodes words following RFC-2047. +/** Encodes words according to RFC-2047. */ +class VMIME_EXPORT wordEncoder { -class VMIME_EXPORT wordEncoder -{ public: /** Available encodings for RFC-2047. */ - enum Encoding - { + enum Encoding { ENCODING_AUTO, ENCODING_QP, ENCODING_B64 }; - wordEncoder(const string& buffer, const charset& charset, const Encoding encoding = ENCODING_AUTO); + wordEncoder( + const string& buffer, + const charset& charset, + const Encoding encoding = ENCODING_AUTO + ); /** Return the next chunk in the word. @@ -81,8 +82,12 @@ public: * @param lang language code, in the format specified by RFC-1766 * @return true if encoding is needed, false otherwise. */ - static bool isEncodingNeeded(const generationContext& ctx, const string& buffer, - const charset& charset, const string& lang); + static bool isEncodingNeeded( + const generationContext& ctx, + const string& buffer, + const charset& charset, + const string& lang + ); /** Guess the best RFC-2047 encoding to use for the specified buffer. * @@ -111,4 +116,3 @@ private: #endif // VMIME_WORDENCODER_HPP_INCLUDED - diff --git a/tests/misc/importanceHelperTest.cpp b/tests/misc/importanceHelperTest.cpp index 53c5c679..d04d730b 100644 --- a/tests/misc/importanceHelperTest.cpp +++ b/tests/misc/importanceHelperTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -47,8 +47,8 @@ VMIME_TEST_SUITE_BEGIN(importanceHelperTest) // resetImportance - void testResetImportance() - { + void testResetImportance() { + vmime::shared_ptr hdr = vmime::make_shared (); hdr->getField("Importance")->setValue("xxx"); @@ -66,9 +66,12 @@ VMIME_TEST_SUITE_BEGIN(importanceHelperTest) // setImportance - void testSetImportanceImpl(const vmime::misc::importanceHelper::Importance i, - const std::string& ImportanceValue, const std::string& XPriorityValue) - { + void testSetImportanceImpl( + const vmime::misc::importanceHelper::Importance i, + const std::string& ImportanceValue, + const std::string& XPriorityValue + ) { + vmime::shared_ptr hdr = vmime::make_shared (); vmime::misc::importanceHelper::setImportanceHeader(hdr, i); @@ -80,43 +83,56 @@ VMIME_TEST_SUITE_BEGIN(importanceHelperTest) VASSERT_EQ("4", XPriorityValue, hdr->findField("X-Priority")->getValue()->generate()); } - void testSetImportance1() - { - testSetImportanceImpl(vmime::misc::importanceHelper::IMPORTANCE_HIGHEST, - "high", "1 (Highest)"); + void testSetImportance1() { + + testSetImportanceImpl( + vmime::misc::importanceHelper::IMPORTANCE_HIGHEST, + "high", "1 (Highest)" + ); } - void testSetImportance2() - { - testSetImportanceImpl(vmime::misc::importanceHelper::IMPORTANCE_HIGH, - "high", "2 (High)"); + void testSetImportance2() { + + testSetImportanceImpl( + vmime::misc::importanceHelper::IMPORTANCE_HIGH, + "high", "2 (High)" + ); } - void testSetImportance3() - { - testSetImportanceImpl(vmime::misc::importanceHelper::IMPORTANCE_NORMAL, - "normal", "3 (Normal)"); + void testSetImportance3() { + + testSetImportanceImpl( + vmime::misc::importanceHelper::IMPORTANCE_NORMAL, + "normal", "3 (Normal)" + ); } - void testSetImportance4() - { - testSetImportanceImpl(vmime::misc::importanceHelper::IMPORTANCE_LOW, - "low", "4 (Low)"); + void testSetImportance4() { + + testSetImportanceImpl( + vmime::misc::importanceHelper::IMPORTANCE_LOW, + "low", "4 (Low)" + ); } - void testSetImportance5() - { - testSetImportanceImpl(vmime::misc::importanceHelper::IMPORTANCE_LOWEST, - "low", "5 (Lowest)"); + void testSetImportance5() { + + testSetImportanceImpl( + vmime::misc::importanceHelper::IMPORTANCE_LOWEST, + "low", "5 (Lowest)" + ); } // getImportance - void testGetImportanceImpl(const vmime::misc::importanceHelper::Importance i1, + void testGetImportanceImpl( + const vmime::misc::importanceHelper::Importance i1, const vmime::misc::importanceHelper::Importance i2, - const std::string& ImportanceValue, const std::string& XPriorityValue) - { + const std::string& ImportanceValue, + const std::string& XPriorityValue + ) { + vmime::shared_ptr hdr1 = vmime::make_shared (); hdr1->getField("Importance")->setValue(ImportanceValue); @@ -128,35 +144,48 @@ VMIME_TEST_SUITE_BEGIN(importanceHelperTest) VASSERT_EQ("2", i2, vmime::misc::importanceHelper::getImportanceHeader(hdr2)); } - void testGetImportance1() - { - testGetImportanceImpl(vmime::misc::importanceHelper::IMPORTANCE_HIGHEST, - vmime::misc::importanceHelper::IMPORTANCE_HIGHEST, "high", "1 (Highest)"); + void testGetImportance1() { + + testGetImportanceImpl( + vmime::misc::importanceHelper::IMPORTANCE_HIGHEST, + vmime::misc::importanceHelper::IMPORTANCE_HIGHEST, + "high", "1 (Highest)"); } - void testGetImportance2() - { - testGetImportanceImpl(vmime::misc::importanceHelper::IMPORTANCE_HIGHEST, - vmime::misc::importanceHelper::IMPORTANCE_HIGH, "high", "2 (High)"); + void testGetImportance2() { + + testGetImportanceImpl( + vmime::misc::importanceHelper::IMPORTANCE_HIGHEST, + vmime::misc::importanceHelper::IMPORTANCE_HIGH, + "high", "2 (High)" + ); } - void testGetImportance3() - { - testGetImportanceImpl(vmime::misc::importanceHelper::IMPORTANCE_NORMAL, - vmime::misc::importanceHelper::IMPORTANCE_NORMAL, "normal", "3 (Normal)"); + void testGetImportance3() { + + testGetImportanceImpl( + vmime::misc::importanceHelper::IMPORTANCE_NORMAL, + vmime::misc::importanceHelper::IMPORTANCE_NORMAL, + "normal", "3 (Normal)" + ); } - void testGetImportance4() - { - testGetImportanceImpl(vmime::misc::importanceHelper::IMPORTANCE_LOWEST, - vmime::misc::importanceHelper::IMPORTANCE_LOW, "low", "4 (Low)"); + void testGetImportance4() { + + testGetImportanceImpl( + vmime::misc::importanceHelper::IMPORTANCE_LOWEST, + vmime::misc::importanceHelper::IMPORTANCE_LOW, + "low", "4 (Low)" + ); } - void testGetImportance5() - { - testGetImportanceImpl(vmime::misc::importanceHelper::IMPORTANCE_LOWEST, - vmime::misc::importanceHelper::IMPORTANCE_LOWEST, "low", "5 (Lowest)"); + void testGetImportance5() { + + testGetImportanceImpl( + vmime::misc::importanceHelper::IMPORTANCE_LOWEST, + vmime::misc::importanceHelper::IMPORTANCE_LOWEST, + "low", "5 (Lowest)" + ); } VMIME_TEST_SUITE_END - diff --git a/tests/net/folderAttributesTest.cpp b/tests/net/folderAttributesTest.cpp index 06235399..da0e025d 100644 --- a/tests/net/folderAttributesTest.cpp +++ b/tests/net/folderAttributesTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard +// Copyright (C) 2002 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 @@ -40,8 +40,8 @@ VMIME_TEST_SUITE_BEGIN(folderAttributesTest) VMIME_TEST_LIST_END - void testConstruct() - { + void testConstruct() { + vmime::net::folderAttributes attr; // Default values @@ -52,8 +52,8 @@ VMIME_TEST_SUITE_BEGIN(folderAttributesTest) VASSERT_EQ("special-use", vmime::net::folderAttributes::SPECIALUSE_NONE, attr.getSpecialUse()); } - void testConstructCopy() - { + void testConstructCopy() { + std::vector userFlags; userFlags.push_back("\\XMyFlag1"); userFlags.push_back("\\XMyFlag2"); @@ -70,24 +70,24 @@ VMIME_TEST_SUITE_BEGIN(folderAttributesTest) VASSERT("user-flags", attr2.getUserFlags() == attr.getUserFlags()); } - void testSetType() - { + void testSetType() { + vmime::net::folderAttributes attr; attr.setType(vmime::net::folderAttributes::TYPE_CONTAINS_FOLDERS); VASSERT_EQ("eq", vmime::net::folderAttributes::TYPE_CONTAINS_FOLDERS, attr.getType()); } - void testSetFlags() - { + void testSetFlags() { + vmime::net::folderAttributes attr; attr.setFlags(vmime::net::folderAttributes::FLAG_HAS_CHILDREN); VASSERT_EQ("eq", vmime::net::folderAttributes::FLAG_HAS_CHILDREN, attr.getFlags()); } - void testHasFlag() - { + void testHasFlag() { + vmime::net::folderAttributes attr; attr.setFlags(vmime::net::folderAttributes::FLAG_HAS_CHILDREN); @@ -95,8 +95,8 @@ VMIME_TEST_SUITE_BEGIN(folderAttributesTest) VASSERT("has-not", !attr.hasFlag(vmime::net::folderAttributes::FLAG_NO_OPEN)); } - void testSetUserFlags() - { + void testSetUserFlags() { + std::vector userFlags; userFlags.push_back("\\XMyFlag1"); userFlags.push_back("\\XMyFlag2"); @@ -108,8 +108,8 @@ VMIME_TEST_SUITE_BEGIN(folderAttributesTest) VASSERT("eq", attr.getUserFlags() == userFlags); } - void testHasUserFlag() - { + void testHasUserFlag() { + std::vector userFlags; userFlags.push_back("\\XMyFlag1"); userFlags.push_back("\\XMyFlag2"); @@ -123,8 +123,8 @@ VMIME_TEST_SUITE_BEGIN(folderAttributesTest) VASSERT("has-not", !attr.hasUserFlag("\\XMyFlag4")); } - void testSetSpecialUse() - { + void testSetSpecialUse() { + const int use = vmime::net::folderAttributes::SPECIALUSE_JUNK | vmime::net::folderAttributes::SPECIALUSE_TRASH; diff --git a/tests/net/imap/IMAPCommandTest.cpp b/tests/net/imap/IMAPCommandTest.cpp index f274bb27..cf3446d7 100644 --- a/tests/net/imap/IMAPCommandTest.cpp +++ b/tests/net/imap/IMAPCommandTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard +// Copyright (C) 2002 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 @@ -60,24 +60,24 @@ VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) VMIME_TEST_LIST_END - void testCreateCommand() - { + void testCreateCommand() { + vmime::shared_ptr cmd = IMAPCommand::createCommand("MY_COMMAND"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MY_COMMAND", cmd->getText()); } - void testCreateCommandParams() - { + void testCreateCommandParams() { + vmime::shared_ptr cmd = IMAPCommand::createCommand("MY_COMMAND param1 param2"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MY_COMMAND param1 param2", cmd->getText()); } - void testLOGIN() - { + void testLOGIN() { + vmime::shared_ptr cmd = IMAPCommand::LOGIN("username", "password"); VASSERT_NOT_NULL("Not null", cmd); @@ -85,24 +85,24 @@ VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) VASSERT_EQ("Trace Text", "LOGIN {username} {password}", cmd->getTraceText()); } - void testAUTHENTICATE() - { + void testAUTHENTICATE() { + vmime::shared_ptr cmd = IMAPCommand::AUTHENTICATE("saslmechanism"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "AUTHENTICATE saslmechanism", cmd->getText()); } - void testAUTHENTICATE_InitialResponse() - { + void testAUTHENTICATE_InitialResponse() { + vmime::shared_ptr cmd = IMAPCommand::AUTHENTICATE("saslmechanism", "initial-response"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "AUTHENTICATE saslmechanism initial-response", cmd->getText()); } - void testLIST() - { + void testLIST() { + vmime::shared_ptr cmd = IMAPCommand::LIST("ref-name", "mailbox-name"); VASSERT_NOT_NULL("Not null", cmd); @@ -114,47 +114,52 @@ VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) VASSERT_EQ("Text", "LIST \"ref name\" mailbox-name", cmdQuote->getText()); } - void testSELECT() - { + void testSELECT() { + std::vector params; params.push_back("param-1"); params.push_back("param-2"); - vmime::shared_ptr cmdRO = IMAPCommand::SELECT - (/* readOnly */ true, "mailbox-name", std::vector ()); + vmime::shared_ptr cmdRO = IMAPCommand::SELECT( + /* readOnly */ true, "mailbox-name", std::vector () + ); VASSERT_NOT_NULL("Not null", cmdRO); VASSERT_EQ("Text", "EXAMINE mailbox-name", cmdRO->getText()); - vmime::shared_ptr cmdROQuote = IMAPCommand::SELECT - (/* readOnly */ true, "mailbox name", std::vector ()); + vmime::shared_ptr cmdROQuote = IMAPCommand::SELECT( + /* readOnly */ true, "mailbox name", std::vector () + ); VASSERT_NOT_NULL("Not null", cmdROQuote); VASSERT_EQ("Text", "EXAMINE \"mailbox name\"", cmdROQuote->getText()); - vmime::shared_ptr cmdRW = IMAPCommand::SELECT - (/* readOnly */ false, "mailbox-name", std::vector ()); + vmime::shared_ptr cmdRW = IMAPCommand::SELECT( + /* readOnly */ false, "mailbox-name", std::vector () + ); VASSERT_NOT_NULL("Not null", cmdRW); VASSERT_EQ("Text", "SELECT mailbox-name", cmdRW->getText()); - vmime::shared_ptr cmdRWParams = IMAPCommand::SELECT - (/* readOnly */ false, "mailbox-name", params); + vmime::shared_ptr cmdRWParams = IMAPCommand::SELECT( + /* readOnly */ false, "mailbox-name", params + ); VASSERT_NOT_NULL("Not null", cmdRWParams); VASSERT_EQ("Text", "SELECT mailbox-name (param-1 param-2)", cmdRWParams->getText()); - vmime::shared_ptr cmdRWQuote = IMAPCommand::SELECT - (/* readOnly */ false, "mailbox name", std::vector ()); + vmime::shared_ptr cmdRWQuote = IMAPCommand::SELECT( + /* readOnly */ false, "mailbox name", std::vector () + ); VASSERT_NOT_NULL("Not null", cmdRWQuote); VASSERT_EQ("Text", "SELECT \"mailbox name\"", cmdRWQuote->getText()); } - void testSTATUS() - { + void testSTATUS() { + std::vector attribs; attribs.push_back("attrib-1"); attribs.push_back("attrib-2"); @@ -174,8 +179,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) VASSERT_EQ("Text", "STATUS \"mailbox name\" (attrib-1 attrib-2)", cmdQuote->getText()); } - void testCREATE() - { + void testCREATE() { + std::vector params; params.push_back("param-1"); params.push_back("param-2"); @@ -202,8 +207,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) VASSERT_EQ("Text", "CREATE mailbox-name", cmdNoParam->getText()); } - void testDELETE() - { + void testDELETE() { + vmime::shared_ptr cmd = IMAPCommand::DELETE("mailbox-name"); @@ -218,8 +223,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) VASSERT_EQ("Text", "DELETE \"mailbox name\"", cmdQuote->getText()); } - void testRENAME() - { + void testRENAME() { + vmime::shared_ptr cmd = IMAPCommand::RENAME("mailbox-name", "new-mailbox-name"); @@ -234,8 +239,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) VASSERT_EQ("Text", "RENAME \"mailbox name\" \"new mailbox name\"", cmdQuote->getText()); } - void testFETCH() - { + void testFETCH() { + std::vector params; params.push_back("param-1"); params.push_back("param-2"); @@ -269,57 +274,63 @@ VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) VASSERT_EQ("Text", "UID FETCH 42:47 (param-1 param-2)", cmdUIDs->getText()); } - void testSTORE() - { + void testSTORE() { + std::vector flags; flags.push_back("flag-1"); flags.push_back("flag-2"); - vmime::shared_ptr cmdNum = IMAPCommand::STORE - (vmime::net::messageSet::byNumber(42), vmime::net::message::FLAG_MODE_SET, flags); + vmime::shared_ptr cmdNum = IMAPCommand::STORE( + vmime::net::messageSet::byNumber(42), vmime::net::message::FLAG_MODE_SET, flags + ); VASSERT_NOT_NULL("Not null", cmdNum); VASSERT_EQ("Text", "STORE 42 FLAGS (flag-1 flag-2)", cmdNum->getText()); - vmime::shared_ptr cmdNums = IMAPCommand::STORE - (vmime::net::messageSet::byNumber(42, 47), vmime::net::message::FLAG_MODE_SET, flags); + vmime::shared_ptr cmdNums = IMAPCommand::STORE( + vmime::net::messageSet::byNumber(42, 47), vmime::net::message::FLAG_MODE_SET, flags + ); VASSERT_NOT_NULL("Not null", cmdNums); VASSERT_EQ("Text", "STORE 42:47 FLAGS (flag-1 flag-2)", cmdNums->getText()); - vmime::shared_ptr cmdUID = IMAPCommand::STORE - (vmime::net::messageSet::byUID(42), vmime::net::message::FLAG_MODE_SET, flags); + vmime::shared_ptr cmdUID = IMAPCommand::STORE( + vmime::net::messageSet::byUID(42), vmime::net::message::FLAG_MODE_SET, flags + ); VASSERT_NOT_NULL("Not null", cmdUID); VASSERT_EQ("Text", "UID STORE 42 FLAGS (flag-1 flag-2)", cmdUID->getText()); - vmime::shared_ptr cmdUIDs = IMAPCommand::STORE - (vmime::net::messageSet::byUID(42, 47), vmime::net::message::FLAG_MODE_SET, flags); + vmime::shared_ptr cmdUIDs = IMAPCommand::STORE( + vmime::net::messageSet::byUID(42, 47), vmime::net::message::FLAG_MODE_SET, flags + ); VASSERT_NOT_NULL("Not null", cmdUIDs); VASSERT_EQ("Text", "UID STORE 42:47 FLAGS (flag-1 flag-2)", cmdUIDs->getText()); - vmime::shared_ptr cmdAdd = IMAPCommand::STORE - (vmime::net::messageSet::byUID(42, 47), vmime::net::message::FLAG_MODE_ADD, flags); + vmime::shared_ptr cmdAdd = IMAPCommand::STORE( + vmime::net::messageSet::byUID(42, 47), vmime::net::message::FLAG_MODE_ADD, flags + ); VASSERT_NOT_NULL("Not null", cmdAdd); VASSERT_EQ("Text", "UID STORE 42:47 +FLAGS (flag-1 flag-2)", cmdAdd->getText()); - vmime::shared_ptr cmdRem = IMAPCommand::STORE - (vmime::net::messageSet::byUID(42, 47), vmime::net::message::FLAG_MODE_REMOVE, flags); + vmime::shared_ptr cmdRem = IMAPCommand::STORE( + vmime::net::messageSet::byUID(42, 47), vmime::net::message::FLAG_MODE_REMOVE, flags + ); VASSERT_NOT_NULL("Not null", cmdRem); VASSERT_EQ("Text", "UID STORE 42:47 -FLAGS (flag-1 flag-2)", cmdRem->getText()); } - void testAPPEND() - { + void testAPPEND() { + std::vector flags; flags.push_back("flag-1"); flags.push_back("flag-2"); @@ -347,8 +358,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) VASSERT_EQ("Text", "APPEND \"mailbox name\" (flag-1 flag-2) \"15-Mar-2014 23:11:47 +0200\" {1234}", cmdDate->getText()); } - void testCOPY() - { + void testCOPY() { + vmime::shared_ptr cmdNum = IMAPCommand::COPY(vmime::net::messageSet::byNumber(42), "mailbox-name"); @@ -384,8 +395,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) VASSERT_EQ("Text", "COPY 42:47 \"mailbox name\"", cmdQuote->getText()); } - void testSEARCH() - { + void testSEARCH() { + std::vector searchKeys; searchKeys.push_back("search-key-1"); searchKeys.push_back("search-key-2"); @@ -406,57 +417,58 @@ VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) VASSERT_EQ("Text", "SEARCH CHARSET test-charset search-key-1 search-key-2", cmdCset->getText()); } - void testSTARTTLS() - { + void testSTARTTLS() { + vmime::shared_ptr cmd = IMAPCommand::STARTTLS(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "STARTTLS", cmd->getText()); } - void testCAPABILITY() - { + void testCAPABILITY() { + vmime::shared_ptr cmd = IMAPCommand::CAPABILITY(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "CAPABILITY", cmd->getText()); } - void testNOOP() - { + void testNOOP() { + vmime::shared_ptr cmd = IMAPCommand::NOOP(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "NOOP", cmd->getText()); } - void testEXPUNGE() - { + void testEXPUNGE() { + vmime::shared_ptr cmd = IMAPCommand::EXPUNGE(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "EXPUNGE", cmd->getText()); } - void testCLOSE() - { + void testCLOSE() { + vmime::shared_ptr cmd = IMAPCommand::CLOSE(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "CLOSE", cmd->getText()); } - void testLOGOUT() - { + void testLOGOUT() { + vmime::shared_ptr cmd = IMAPCommand::LOGOUT(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "LOGOUT", cmd->getText()); } - void testSend() - { - vmime::shared_ptr cmd = IMAPCommand::createCommand("MY_COMMAND param1 param2"); + void testSend() { + + vmime::shared_ptr cmd = + IMAPCommand::createCommand("MY_COMMAND param1 param2"); vmime::shared_ptr sess = vmime::net::session::create(); diff --git a/tests/net/imap/IMAPParserTest.cpp b/tests/net/imap/IMAPParserTest.cpp index 5d810a8f..974dc241 100644 --- a/tests/net/imap/IMAPParserTest.cpp +++ b/tests/net/imap/IMAPParserTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,8 +39,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) // For Apple iCloud IMAP server - void testExtraSpaceInCapaResponse() - { + void testExtraSpaceInCapaResponse() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); @@ -49,7 +49,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) socket->localSend( "* CAPABILITY IMAP4rev1 AUTH=ATOKEN AUTH=PLAIN \r\n" // extra space at end - "a001 OK Capability completed.\r\n"); + "a001 OK Capability completed.\r\n" + ); vmime::shared_ptr parser = vmime::make_shared (); @@ -65,15 +66,16 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) socket->localSend( "* CAPABILITY IMAP4rev1 AUTH=ATOKEN AUTH=PLAIN \r\n" // extra space at end - "a002 OK Capability completed.\r\n"); + "a002 OK Capability completed.\r\n" + ); parser->setStrict(true); VASSERT_THROW("strict mode", parser->readResponse(/* literalHandler */ NULL), vmime::exceptions::invalid_response); } // For Apple iCloud/Exchange IMAP server - void testContinueReqWithoutSpace() - { + void testContinueReqWithoutSpace() { + // continue_req ::= "+" SPACE (resp_text / base64) // // Some servers do not send SPACE when response text is empty. @@ -114,8 +116,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) // that is running the Exchange Server 2007 IMAP4 service, a corrupted // response is sent as a reply // --> http://support.microsoft.com/kb/975918/en-us - void testNILValueInBodyFldEnc() - { + void testNILValueInBodyFldEnc() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); @@ -145,13 +147,13 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) } // "body_fld_lang" is optional after "body_fld_dsp" in "body_ext_mpart" (Yahoo) - void testFETCHResponse_optional_body_fld_lang() - { + void testFETCHResponse_optional_body_fld_lang() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); vmime::shared_ptr tag = - vmime::make_shared (); + vmime::make_shared (); const char* resp = "* 1 FETCH (UID 7 RFC822.SIZE 694142 BODYSTRUCTURE (((\"text\" \"plain\" (\"charset\" \"utf-8\") NIL NIL \"7bit\" 0 0 NIL NIL NIL NIL)(\"text\" \"html\" (\"charset\" \"utf-8\") NIL NIL \"7bit\" 193 0 NIL NIL NIL NIL) \"alternative\" (\"boundary\" \"----=_Part_536_109505883.1410847112666\") NIL)(\"image\" \"jpeg\" NIL \"<4db20d0e-e9f8-729b-aaf7-688b5956d0bc@yahoo.com>\" NIL \"base64\" 351784 NIL (\"attachment\" (\"name\" \"att2\" \"filename\" \"9.jpg\")) NIL NIL)(\"image\" \"jpeg\" NIL \"<542417d7-c0ed-db72-f9fc-d9ab2c7e0a6f@yahoo.com>\" NIL \"base64\" 337676 NIL (\"attachment\" (\"name\" \"att3\" \"filename\" \"10.jpg\")) NIL NIL) \"mixed\" (\"boundary\" \"----=_Part_537_1371134700.1410847112668\") NIL) RFC822.HEADER {3}\r\nx\r\n)\r\na001 OK FETCH complete\r\n"; @@ -169,8 +171,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPParserTest) // Support for NIL boundary, for mail.ru IMAP server: // https://www.ietf.org/mail-archive/web/imapext/current/msg05442.html - void testFETCHBodyStructure_NIL_body_fld_param_value() - { + void testFETCHBodyStructure_NIL_body_fld_param_value() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); diff --git a/tests/net/imap/IMAPTagTest.cpp b/tests/net/imap/IMAPTagTest.cpp index db04537a..c8e09b6b 100644 --- a/tests/net/imap/IMAPTagTest.cpp +++ b/tests/net/imap/IMAPTagTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,16 +36,16 @@ VMIME_TEST_SUITE_BEGIN(imapTagTest) VMIME_TEST_LIST_END - void testConstruct() - { + void testConstruct() { + vmime::shared_ptr tag = vmime::make_shared (); VASSERT_EQ("init", "a001", static_cast (*tag)); } - void testIncrement() - { + void testIncrement() { + vmime::shared_ptr tag = vmime::make_shared (); @@ -59,13 +59,14 @@ VMIME_TEST_SUITE_BEGIN(imapTagTest) VASSERT_EQ("init", "a004", static_cast (*tag)); } - void testReset() - { + void testReset() { + vmime::shared_ptr tag = vmime::make_shared (); - for (int i = tag->number() ; i < tag->maximumNumber() ; ++i) + for (int i = tag->number() ; i < tag->maximumNumber() ; ++i) { (*tag)++; + } VASSERT_EQ("last", "Z999", static_cast (*tag)); @@ -74,13 +75,14 @@ VMIME_TEST_SUITE_BEGIN(imapTagTest) VASSERT_EQ("reset", "a001", static_cast (*tag)); } - void testNumber() - { + void testNumber() { + vmime::shared_ptr tag = vmime::make_shared (); - for (int i = 0 ; i < 41 ; ++i) + for (int i = 0 ; i < 41 ; ++i) { (*tag)++; + } VASSERT_EQ("number", 42, tag->number()); } diff --git a/tests/net/imap/IMAPUtilsTest.cpp b/tests/net/imap/IMAPUtilsTest.cpp index db88b539..b707fd06 100644 --- a/tests/net/imap/IMAPUtilsTest.cpp +++ b/tests/net/imap/IMAPUtilsTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard +// Copyright (C) 2002 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 @@ -46,8 +46,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPUtilsTest) VMIME_TEST_LIST_END - void testQuoteString() - { + void testQuoteString() { + VASSERT_EQ("unquoted", "ascii", IMAPUtils::quoteString("ascii")); VASSERT_EQ("space", "\"ascii with space\"", IMAPUtils::quoteString("ascii with space")); @@ -63,8 +63,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPUtilsTest) } - void testToModifiedUTF7() - { + void testToModifiedUTF7() { + #define FC(x) vmime::net::folder::path::component(x, vmime::charsets::UTF_8) // Example strings from RFC-1642 (modified for IMAP UTF-7) @@ -80,8 +80,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPUtilsTest) #undef FC } - void testFromModifiedUTF7() - { + void testFromModifiedUTF7() { + #define FC(x) vmime::net::folder::path::component(x, vmime::charsets::UTF_8) // Example strings from RFC-1642 (modified for IMAP UTF-7) @@ -97,8 +97,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPUtilsTest) #undef FC } - void testConvertAddressList() - { + void testConvertAddressList() { + IMAPParser parser; IMAPParser::address_list addrList; @@ -117,8 +117,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPUtilsTest) VASSERT_EQ("mbox-2", "name2", mboxList.getMailboxAt(1)->getName().getWholeBuffer()); } - void testMessageFlagList() - { + void testMessageFlagList() { + int flags = 0; std::vector flagList; @@ -158,14 +158,14 @@ VMIME_TEST_SUITE_BEGIN(IMAPUtilsTest) VASSERT("2.found2", std::find(flagList.begin(), flagList.end(), "\\Seen") != flagList.end()); } - void testDateTime() - { + void testDateTime() { + vmime::datetime dt(2014, 3, 17, 23, 26, 22, vmime::datetime::GMT2); VASSERT_EQ("datetime", "\"17-Mar-2014 23:26:22 +0200\"", IMAPUtils::dateTime(dt)); } - void testPathToString() - { + void testPathToString() { + #define FC(x) vmime::net::folder::path::component(x, vmime::charsets::UTF_8) vmime::net::folder::path path; @@ -177,8 +177,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPUtilsTest) #undef FC } - void testStringToPath() - { + void testStringToPath() { + #define FC(x) vmime::net::folder::path::component(x, vmime::charsets::UTF_8) vmime::net::folder::path path = IMAPUtils::stringToPath('/', "Hi Mum &Jjo-!/&ZeVnLIqe-"); @@ -190,8 +190,8 @@ VMIME_TEST_SUITE_BEGIN(IMAPUtilsTest) #undef FC } - void testBuildFetchCommand() - { + void testBuildFetchCommand() { + vmime::shared_ptr cnt; vmime::net::messageSet msgs = vmime::net::messageSet::byNumber(42); diff --git a/tests/net/maildir/maildirStoreTest.cpp b/tests/net/maildir/maildirStoreTest.cpp index 11868c9d..1f418e81 100644 --- a/tests/net/maildir/maildirStoreTest.cpp +++ b/tests/net/maildir/maildirStoreTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,8 +37,8 @@ typedef vmime::net::folder::path fpath; typedef vmime::net::folder::path::component fpathc; -const fpath operator/(const fpath& path, const std::string& c) -{ +const fpath operator/(const fpath& path, const std::string& c) { + return path / fpathc(c); } @@ -65,8 +65,7 @@ static const vmime::string TEST_MESSAGE_1 = */ // KMail format -static const vmime::string TEST_MAILDIR_KMAIL[] = // directories to create -{ +static const vmime::string TEST_MAILDIR_KMAIL[] = { // directories to create "/Folder", "/Folder/new", "/Folder/tmp", @@ -92,15 +91,13 @@ static const vmime::string TEST_MAILDIR_KMAIL[] = // directories to create "*" // end }; -static const vmime::string TEST_MAILDIRFILES_KMAIL[] = // files to create and their contents -{ +static const vmime::string TEST_MAILDIRFILES_KMAIL[] = { // files to create and their contents "/.Folder.directory/.SubFolder.directory/SubSubFolder2/cur/1043236113.351.EmqD:S", TEST_MESSAGE_1, "*" // end }; // Courier format -static const vmime::string TEST_MAILDIR_COURIER[] = // directories to create -{ +static const vmime::string TEST_MAILDIR_COURIER[] = { // directories to create "/.Folder", "/.Folder/new", "/.Folder/tmp", @@ -125,8 +122,7 @@ static const vmime::string TEST_MAILDIR_COURIER[] = // directories to create "*" // end }; -static const vmime::string TEST_MAILDIRFILES_COURIER[] = // files to create and their contents -{ +static const vmime::string TEST_MAILDIRFILES_COURIER[] = { // files to create and their contents "/.Folder/maildirfolder", "", "/.Folder.SubFolder/maildirfolder", "", "/.Folder.SubFolder.SubSubFolder1/maildirfolder", "", @@ -169,22 +165,22 @@ VMIME_TEST_SUITE_BEGIN(maildirStoreTest) public: - maildirStoreTest() - { + maildirStoreTest() { + // Temporary directory m_tempPath = fspath() / fspathc("tmp") // Use /tmp / fspathc("vmime" + vmime::utility::stringUtils::toString(std::time(NULL)) + vmime::utility::stringUtils::toString(std::rand())); } - void tearDown() - { + void tearDown() { + // In case of an uncaught exception destroyMaildir(); } - void testDetectFormat_KMail() - { + void testDetectFormat_KMail() { + createMaildir(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); vmime::shared_ptr store = @@ -195,8 +191,8 @@ public: destroyMaildir(); } - void testDetectFormat_Courier() - { + void testDetectFormat_Courier() { + createMaildir(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); vmime::shared_ptr store = @@ -208,18 +204,18 @@ public: } - void testListRootFolders_KMail() - { + void testListRootFolders_KMail() { + testListRootFoldersImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); } - void testListRootFolders_Courier() - { + void testListRootFolders_Courier() { + testListRootFoldersImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); } - void testListRootFoldersImpl(const vmime::string* const dirs, const vmime::string* const files) - { + void testListRootFoldersImpl(const vmime::string* const dirs, const vmime::string* const files) { + createMaildir(dirs, files); // Connect to store @@ -238,18 +234,18 @@ public: } - void testListAllFolders_KMail() - { + void testListAllFolders_KMail() { + testListAllFoldersImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); } - void testListAllFolders_Courier() - { + void testListAllFolders_Courier() { + testListAllFoldersImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); } - void testListAllFoldersImpl(const vmime::string* const dirs, const vmime::string* const files) - { + void testListAllFoldersImpl(const vmime::string* const dirs, const vmime::string* const files) { + createMaildir(dirs, files); // Connect to store @@ -271,25 +267,26 @@ public: } - void testListMessages_KMail() - { + void testListMessages_KMail() { + testListMessagesImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); } - void testListMessages_Courier() - { + void testListMessages_Courier() { + testListMessagesImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); } - void testListMessagesImpl(const vmime::string* const dirs, const vmime::string* const files) - { + void testListMessagesImpl(const vmime::string* const dirs, const vmime::string* const files) { + createMaildir(dirs, files); vmime::shared_ptr store = createAndConnectStore(); vmime::shared_ptr rootFolder = store->getRootFolder(); - vmime::shared_ptr folder = store->getFolder - (fpath() / "Folder" / "SubFolder" / "SubSubFolder2"); + vmime::shared_ptr folder = store->getFolder( + fpath() / "Folder" / "SubFolder" / "SubSubFolder2" + ); vmime::size_t count, unseen; folder->status(count, unseen); @@ -316,14 +313,14 @@ public: } - void testRenameFolder_KMail() - { - try - { + void testRenameFolder_KMail() { + + try { + testRenameFolderImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); - } - catch (vmime::exception& e) - { + + } catch (vmime::exception& e) { + std::cerr << e; throw e; } @@ -331,27 +328,27 @@ public: void testRenameFolder_Courier() { - try - { + try { + testRenameFolderImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); - } - catch (vmime::exception& e) - { + + } catch (vmime::exception& e) { + std::cerr << e; throw e; } } - void testRenameFolderImpl(const vmime::string* const dirs, const vmime::string* const files) - { + void testRenameFolderImpl(const vmime::string* const dirs, const vmime::string* const files) { + createMaildir(dirs, files); vmime::shared_ptr store = createAndConnectStore(); vmime::shared_ptr rootFolder = store->getRootFolder(); // Rename "Folder/SubFolder" to "Folder/foo" - vmime::shared_ptr folder = store->getFolder - (fpath() / "Folder" / "SubFolder"); + vmime::shared_ptr folder = + store->getFolder(fpath() / "Folder" / "SubFolder"); folder->rename(fpath() / "Folder" / "foo"); @@ -373,26 +370,26 @@ public: } - void testDestroyFolder_KMail() - { + void testDestroyFolder_KMail() { + testDestroyFolderImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); } - void testDestroyFolder_Courier() - { + void testDestroyFolder_Courier() { + testDestroyFolderImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); } - void testDestroyFolderImpl(const vmime::string* const dirs, const vmime::string* const files) - { + void testDestroyFolderImpl(const vmime::string* const dirs, const vmime::string* const files) { + createMaildir(dirs, files); vmime::shared_ptr store = createAndConnectStore(); vmime::shared_ptr rootFolder = store->getRootFolder(); // Destroy "Folder/SubFolder" (total: 3 folders) - vmime::shared_ptr folder = store->getFolder - (fpath() / "Folder" / "SubFolder"); + vmime::shared_ptr folder = + store->getFolder(fpath() / "Folder" / "SubFolder"); folder->destroy(); @@ -411,18 +408,18 @@ public: } - void testFolderExists_KMail() - { + void testFolderExists_KMail() { + testFolderExistsImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); } - void testFolderExists_Courier() - { + void testFolderExists_Courier() { + testFolderExistsImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); } - void testFolderExistsImpl(const vmime::string* const dirs, const vmime::string* const files) - { + void testFolderExistsImpl(const vmime::string* const dirs, const vmime::string* const files) { + createMaildir(dirs, files); vmime::shared_ptr store = createAndConnectStore(); @@ -437,18 +434,18 @@ public: } - void testCreateFolder_KMail() - { + void testCreateFolder_KMail() { + testCreateFolderImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); } - void testCreateFolder_Courier() - { + void testCreateFolder_Courier() { + testCreateFolderImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); } - void testCreateFolderImpl(const vmime::string* const dirs, const vmime::string* const files) - { + void testCreateFolderImpl(const vmime::string* const dirs, const vmime::string* const files) { + createMaildir(dirs, files); vmime::shared_ptr store = createAndConnectStore(); @@ -471,8 +468,8 @@ private: vmime::utility::file::path m_tempPath; - vmime::shared_ptr createAndConnectStore() - { + vmime::shared_ptr createAndConnectStore() { + vmime::shared_ptr session = vmime::net::session::create(); vmime::shared_ptr store = @@ -483,21 +480,23 @@ private: return store; } - const vmime::shared_ptr findFolder - (const std::vector >& folders, - const vmime::net::folder::path& path) - { - for (size_t i = 0, n = folders.size() ; i < n ; ++i) - { - if (folders[i]->getFullPath() == path) + const vmime::shared_ptr findFolder( + const std::vector >& folders, + const vmime::net::folder::path& path + ) { + + for (size_t i = 0, n = folders.size() ; i < n ; ++i) { + + if (folders[i]->getFullPath() == path) { return folders[i]; + } } return vmime::null; } - const vmime::utility::url getStoreURL() - { + const vmime::utility::url getStoreURL() { + vmime::shared_ptr fsf = vmime::platform::getHandler()->getFileSystemFactory(); @@ -507,22 +506,22 @@ private: return url; } - void createMaildir(const vmime::string* const dirs, const vmime::string* const files) - { + void createMaildir(const vmime::string* const dirs, const vmime::string* const files) { + vmime::shared_ptr fsf = vmime::platform::getHandler()->getFileSystemFactory(); vmime::shared_ptr rootDir = fsf->create(m_tempPath); rootDir->createDirectory(false); - for (vmime::string const* dir = dirs ; *dir != "*" ; ++dir) - { + for (vmime::string const* dir = dirs ; *dir != "*" ; ++dir) { + vmime::shared_ptr fdir = fsf->create(m_tempPath / fsf->stringToPath(*dir)); fdir->createDirectory(false); } - for (vmime::string const* file = files ; *file != "*" ; file += 2) - { + for (vmime::string const* file = files ; *file != "*" ; file += 2) { + const vmime::string& contents = *(file + 1); vmime::shared_ptr ffile = fsf->create(m_tempPath / fsf->stringToPath(*file)); @@ -539,53 +538,47 @@ private: } - void destroyMaildir() - { + void destroyMaildir() { + vmime::shared_ptr fsf = vmime::platform::getHandler()->getFileSystemFactory(); recursiveDelete(fsf->create(m_tempPath)); } - void recursiveDelete(vmime::shared_ptr dir) - { - if (!dir->exists() || !dir->isDirectory()) + void recursiveDelete(vmime::shared_ptr dir) { + + if (!dir->exists() || !dir->isDirectory()) { return; + } vmime::shared_ptr files = dir->getFiles(); // First, delete files and subdirectories in this directory - while (files->hasMoreElements()) - { + while (files->hasMoreElements()) { + vmime::shared_ptr file = files->nextElement(); - if (file->isDirectory()) - { + if (file->isDirectory()) { + recursiveDelete(file); - } - else - { - try - { + + } else { + + try { file->remove(); - } - catch (vmime::exceptions::filesystem_exception&) - { + } catch (vmime::exceptions::filesystem_exception&) { // Ignore } } } // Then, delete this (empty) directory - try - { + try { dir->remove(); - } - catch (vmime::exceptions::filesystem_exception&) - { + } catch (vmime::exceptions::filesystem_exception&) { // Ignore } } VMIME_TEST_SUITE_END - diff --git a/tests/net/maildir/maildirUtilsTest.cpp b/tests/net/maildir/maildirUtilsTest.cpp index 3538d4a8..9deeebfa 100644 --- a/tests/net/maildir/maildirUtilsTest.cpp +++ b/tests/net/maildir/maildirUtilsTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,11 +36,13 @@ VMIME_TEST_SUITE_BEGIN(maildirUtilsTest) VMIME_TEST_LIST_END - void testMessageSetToNumberList() - { + void testMessageSetToNumberList() { + const std::vector msgNums = - maildirUtils::messageSetToNumberList - (vmime::net::messageSet::byNumber(5, -1), /* msgCount */ 8); + maildirUtils::messageSetToNumberList( + vmime::net::messageSet::byNumber(5, -1), + /* msgCount */ 8 + ); VASSERT_EQ("Count", 4, msgNums.size()); VASSERT_EQ("1", 5, msgNums[0]); @@ -50,4 +52,3 @@ VMIME_TEST_SUITE_BEGIN(maildirUtilsTest) } VMIME_TEST_SUITE_END - diff --git a/tests/net/messageSetTest.cpp b/tests/net/messageSetTest.cpp index 4d129663..dee5dc81 100644 --- a/tests/net/messageSetTest.cpp +++ b/tests/net/messageSetTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,47 +46,51 @@ VMIME_TEST_SUITE_BEGIN(messageSetTest) VMIME_TEST_LIST_END - class messageSetStringEnumerator : public vmime::net::messageSetEnumerator - { + class messageSetStringEnumerator : public vmime::net::messageSetEnumerator { + public: messageSetStringEnumerator() - : m_first(true) - { + : m_first(true) { + } - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { - if (!m_first) - m_oss << ","; + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) { - if (range.getFirst() == range.getLast()) + if (!m_first) { + m_oss << ","; + } + + if (range.getFirst() == range.getLast()) { m_oss << range.getFirst(); - else if (range.getLast() == size_t(-1)) + } else if (range.getLast() == size_t(-1)) { m_oss << range.getFirst() << ":(LAST)"; - else + } else { m_oss << range.getFirst() << ":" << range.getLast(); + } m_first = false; } - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& range) - { - if (!m_first) - m_oss << ","; + void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& range) { - if (range.getFirst() == range.getLast()) + if (!m_first) { + m_oss << ","; + } + + if (range.getFirst() == range.getLast()) { m_oss << range.getFirst(); - else if (range.getLast() == size_t(-1)) + } else if (range.getLast() == size_t(-1)) { m_oss << range.getFirst() << ":(LAST)"; - else + } else { m_oss << range.getFirst() << ":" << range.getLast(); + } m_first = false; } - const std::string str() const - { + const std::string str() const { + return m_oss.str(); } @@ -97,8 +101,8 @@ VMIME_TEST_SUITE_BEGIN(messageSetTest) }; - const std::string enumerateAsString(const vmime::net::messageSet& set) - { + const std::string enumerateAsString(const vmime::net::messageSet& set) { + messageSetStringEnumerator en; set.enumerate(en); @@ -106,33 +110,33 @@ VMIME_TEST_SUITE_BEGIN(messageSetTest) } - void testNumberSet_Single() - { + void testNumberSet_Single() { + VASSERT_EQ("str", "42", enumerateAsString(vmime::net::messageSet::byNumber(42))); } - void testNumberSet_Range() - { + void testNumberSet_Range() { + VASSERT_EQ("str", "42:100", enumerateAsString(vmime::net::messageSet::byNumber(42, 100))); } - void testNumberSet_InvalidRange() - { + void testNumberSet_InvalidRange() { + VASSERT_THROW("first > last", vmime::net::messageSet::byNumber(100, 42), std::invalid_argument); } - void testNumberSet_InvalidFirst() - { + void testNumberSet_InvalidFirst() { + VASSERT_THROW("first == -1", vmime::net::messageSet::byNumber(-1, 42), std::invalid_argument); } - void testNumberSet_InfiniteRange() - { + void testNumberSet_InfiniteRange() { + VASSERT_EQ("str", "42:(LAST)", enumerateAsString(vmime::net::messageSet::byNumber(42, -1))); } - void testNumberSet_Multiple() - { + void testNumberSet_Multiple() { + std::vector numbers; numbers.push_back(1); // test grouping 1:3 numbers.push_back(89); // test sorting @@ -151,23 +155,23 @@ VMIME_TEST_SUITE_BEGIN(messageSetTest) } - void testUIDSet_Single() - { + void testUIDSet_Single() { + VASSERT_EQ("str", "abcdef", enumerateAsString(vmime::net::messageSet::byUID("abcdef"))); } - void testUIDSet_Range() - { + void testUIDSet_Range() { + VASSERT_EQ("str", "abc:def", enumerateAsString(vmime::net::messageSet::byUID("abc:def"))); } - void testUIDSet_InfiniteRange() - { + void testUIDSet_InfiniteRange() { + VASSERT_EQ("str", "abc:*", enumerateAsString(vmime::net::messageSet::byUID("abc", "*"))); } - void testUIDSet_MultipleNumeric() - { + void testUIDSet_MultipleNumeric() { + std::vector uids; uids.push_back("1"); // test grouping 1:3 uids.push_back("89"); // test sorting @@ -185,8 +189,8 @@ VMIME_TEST_SUITE_BEGIN(messageSetTest) VASSERT_EQ("str", "1:3,42,53:57,89,99", enumerateAsString(vmime::net::messageSet::byUID(uids))); } - void testUIDSet_MultipleNonNumeric() - { + void testUIDSet_MultipleNonNumeric() { + std::vector uids; uids.push_back("12"); uids.push_back("34"); @@ -196,8 +200,8 @@ VMIME_TEST_SUITE_BEGIN(messageSetTest) VASSERT_EQ("str", "12,34,ab56,78cd", enumerateAsString(vmime::net::messageSet::byUID(uids))); } - void testIsNumberSet() - { + void testIsNumberSet() { + VASSERT_TRUE("number1", vmime::net::messageSet::byNumber(42).isNumberSet()); VASSERT_FALSE("uid1", vmime::net::messageSet::byUID("42").isNumberSet()); @@ -205,8 +209,8 @@ VMIME_TEST_SUITE_BEGIN(messageSetTest) VASSERT_FALSE("uid2", vmime::net::messageSet::byUID("42", "*").isNumberSet()); } - void testIsUIDSet() - { + void testIsUIDSet() { + VASSERT_FALSE("number1", vmime::net::messageSet::byNumber(42).isUIDSet()); VASSERT_TRUE("uid1", vmime::net::messageSet::byUID("42").isUIDSet()); @@ -214,8 +218,8 @@ VMIME_TEST_SUITE_BEGIN(messageSetTest) VASSERT_TRUE("uid2", vmime::net::messageSet::byUID("42", "*").isUIDSet()); } - void testMixedRanges() - { + void testMixedRanges() { + vmime::net::messageSet set = vmime::net::messageSet::byNumber(1, 5); set.addRange(vmime::net::numberMessageRange(6, 8)); diff --git a/tests/net/pop3/POP3CommandTest.cpp b/tests/net/pop3/POP3CommandTest.cpp index 139e948b..3ed579ee 100644 --- a/tests/net/pop3/POP3CommandTest.cpp +++ b/tests/net/pop3/POP3CommandTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -58,174 +58,177 @@ VMIME_TEST_SUITE_BEGIN(POP3CommandTest) VMIME_TEST_LIST_END - void testCreateCommand() - { + void testCreateCommand() { + vmime::shared_ptr cmd = POP3Command::createCommand("MY_COMMAND"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MY_COMMAND", cmd->getText()); } - void testCreateCommandParams() - { + void testCreateCommandParams() { + vmime::shared_ptr cmd = POP3Command::createCommand("MY_COMMAND param1 param2"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MY_COMMAND param1 param2", cmd->getText()); } - void testCAPA() - { + void testCAPA() { + vmime::shared_ptr cmd = POP3Command::CAPA(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "CAPA", cmd->getText()); } - void testNOOP() - { + void testNOOP() { + vmime::shared_ptr cmd = POP3Command::NOOP(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "NOOP", cmd->getText()); } - void testAUTH() - { + void testAUTH() { + vmime::shared_ptr cmd = POP3Command::AUTH("saslmechanism"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "AUTH saslmechanism", cmd->getText()); } - void testAUTH_InitialResponse() - { + void testAUTH_InitialResponse() { + vmime::shared_ptr cmd = POP3Command::AUTH("saslmechanism", "initial-response"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "AUTH saslmechanism initial-response", cmd->getText()); } - void testSTLS() - { + void testSTLS() { + vmime::shared_ptr cmd = POP3Command::STLS(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "STLS", cmd->getText()); } - void testAPOP() - { + void testAPOP() { + vmime::shared_ptr cmd = POP3Command::APOP("user", "digest"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "APOP user digest", cmd->getText()); } - void testUSER() - { + void testUSER() { + vmime::shared_ptr cmd = POP3Command::USER("user"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "USER user", cmd->getText()); } - void testPASS() - { + void testPASS() { + vmime::shared_ptr cmd = POP3Command::PASS("pass"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "PASS pass", cmd->getText()); } - void testSTAT() - { + void testSTAT() { + vmime::shared_ptr cmd = POP3Command::STAT(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "STAT", cmd->getText()); } - void testLIST() - { + void testLIST() { + vmime::shared_ptr cmd = POP3Command::LIST(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "LIST", cmd->getText()); } - void testLISTMessage() - { + void testLISTMessage() { + vmime::shared_ptr cmd = POP3Command::LIST(42); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "LIST 42", cmd->getText()); } - void testUIDL() - { + void testUIDL() { + vmime::shared_ptr cmd = POP3Command::UIDL(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "UIDL", cmd->getText()); } - void testUIDLMessage() - { + void testUIDLMessage() { + vmime::shared_ptr cmd = POP3Command::UIDL(42); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "UIDL 42", cmd->getText()); } - void testDELE() - { + void testDELE() { + vmime::shared_ptr cmd = POP3Command::DELE(42); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "DELE 42", cmd->getText()); } - void testRETR() - { + void testRETR() { + vmime::shared_ptr cmd = POP3Command::RETR(42); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "RETR 42", cmd->getText()); } - void testTOP() - { + void testTOP() { + vmime::shared_ptr cmd = POP3Command::TOP(42, 567); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "TOP 42 567", cmd->getText()); } - void testRSET() - { + void testRSET() { + vmime::shared_ptr cmd = POP3Command::RSET(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "RSET", cmd->getText()); } - void testQUIT() - { + void testQUIT() { + vmime::shared_ptr cmd = POP3Command::QUIT(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "QUIT", cmd->getText()); } - void testWriteToSocket() - { + void testWriteToSocket() { + vmime::shared_ptr cmd = POP3Command::createCommand("MY_COMMAND param1 param2"); vmime::shared_ptr sok = vmime::make_shared (); - vmime::shared_ptr conn = vmime::make_shared - (vmime::dynamicCast (sok), - vmime::shared_ptr ()); + + vmime::shared_ptr conn = + vmime::make_shared ( + vmime::dynamicCast (sok), + vmime::shared_ptr () + ); cmd->send(conn); diff --git a/tests/net/pop3/POP3ResponseTest.cpp b/tests/net/pop3/POP3ResponseTest.cpp index 2d3b3d32..8fecb749 100644 --- a/tests/net/pop3/POP3ResponseTest.cpp +++ b/tests/net/pop3/POP3ResponseTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -45,13 +45,15 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest) VMIME_TEST_LIST_END - void testSingleLineResponseOK() - { + void testSingleLineResponseOK() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); - vmime::shared_ptr conn = vmime::make_shared - (vmime::dynamicCast (socket), toh); + vmime::shared_ptr conn = + vmime::make_shared ( + vmime::dynamicCast (socket), toh + ); socket->localSend("+OK Response Text\r\n"); @@ -65,13 +67,15 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest) VASSERT_EQ("First Line", "+OK Response Text", resp->getFirstLine()); } - void testSingleLineResponseERR() - { + void testSingleLineResponseERR() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); - vmime::shared_ptr conn = vmime::make_shared - (vmime::dynamicCast (socket), toh); + vmime::shared_ptr conn = + vmime::make_shared ( + vmime::dynamicCast (socket), toh + ); socket->localSend("-ERR Response Text\r\n"); @@ -85,13 +89,15 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest) VASSERT_EQ("First Line", "-ERR Response Text", resp->getFirstLine()); } - void testSingleLineResponseReady() - { + void testSingleLineResponseReady() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); - vmime::shared_ptr conn = vmime::make_shared - (vmime::dynamicCast (socket), toh); + vmime::shared_ptr conn = + vmime::make_shared ( + vmime::dynamicCast (socket), toh + ); socket->localSend("+ challenge_string\r\n"); @@ -105,8 +111,8 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest) VASSERT_EQ("First Line", "+ challenge_string", resp->getFirstLine()); } - void testSingleLineResponseInvalid() - { + void testSingleLineResponseInvalid() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); @@ -125,13 +131,15 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest) VASSERT_EQ("First Line", "Invalid Response Text", resp->getFirstLine()); } - void testSingleLineResponseLF() - { + void testSingleLineResponseLF() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); - vmime::shared_ptr conn = vmime::make_shared - (vmime::dynamicCast (socket), toh); + vmime::shared_ptr conn = + vmime::make_shared ( + vmime::dynamicCast (socket), toh + ); socket->localSend("+OK Response terminated by LF\n"); @@ -145,13 +153,15 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest) VASSERT_EQ("First Line", "+OK Response terminated by LF", resp->getFirstLine()); } - void testMultiLineResponse() - { + void testMultiLineResponse() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); - vmime::shared_ptr conn = vmime::make_shared - (vmime::dynamicCast (socket), toh); + vmime::shared_ptr conn = + vmime::make_shared ( + vmime::dynamicCast (socket), toh + ); socket->localSend("+OK Response Text\r\n"); socket->localSend("Line 1\r\n"); @@ -170,13 +180,15 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest) VASSERT_EQ("Line 2", "Line 2", resp->getLineAt(1)); } - void testMultiLineResponseLF() - { + void testMultiLineResponseLF() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); - vmime::shared_ptr conn = vmime::make_shared - (vmime::dynamicCast (socket), toh); + vmime::shared_ptr conn = + vmime::make_shared ( + vmime::dynamicCast (socket), toh + ); socket->localSend("+OK Response Text\n"); socket->localSend("Line 1\n"); @@ -195,18 +207,21 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest) VASSERT_EQ("Line 2", "Line 2", resp->getLineAt(1)); } - void testLargeResponse() - { + void testLargeResponse() { + std::ostringstream data; - for (unsigned int i = 0 ; i < 5000 ; ++i) + for (unsigned int i = 0 ; i < 5000 ; ++i) { data << "VMIME.VMIME\nVMIME\r\nVMIME_VMIME"; + } vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); - vmime::shared_ptr conn = vmime::make_shared - (vmime::dynamicCast (socket), toh); + vmime::shared_ptr conn = + vmime::make_shared ( + vmime::dynamicCast (socket), toh + ); socket->localSend("+OK Large Response Follows\n"); socket->localSend(data.str()); @@ -227,4 +242,3 @@ VMIME_TEST_SUITE_BEGIN(POP3ResponseTest) } VMIME_TEST_SUITE_END - diff --git a/tests/net/pop3/POP3StoreTest.cpp b/tests/net/pop3/POP3StoreTest.cpp index a6818d46..5d9e3c20 100644 --- a/tests/net/pop3/POP3StoreTest.cpp +++ b/tests/net/pop3/POP3StoreTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -37,8 +37,8 @@ VMIME_TEST_SUITE_BEGIN(POP3StoreTest) VMIME_TEST_LIST_END - void testCreateFromURL() - { + void testCreateFromURL() { + vmime::shared_ptr sess = vmime::net::session::create(); // POP3 @@ -54,8 +54,8 @@ VMIME_TEST_SUITE_BEGIN(POP3StoreTest) VASSERT_TRUE("pop3s", typeid(*store2) == typeid(vmime::net::pop3::POP3SStore)); } - void testConnectToInvalidServer() - { + void testConnectToInvalidServer() { + vmime::shared_ptr sess = vmime::net::session::create(); vmime::utility::url url("pop3://invalid-pop3-server"); diff --git a/tests/net/pop3/POP3TestUtils.hpp b/tests/net/pop3/POP3TestUtils.hpp index b0ec09b8..24efb8b3 100644 --- a/tests/net/pop3/POP3TestUtils.hpp +++ b/tests/net/pop3/POP3TestUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -25,37 +25,40 @@ #include "vmime/net/pop3/POP3Store.hpp" -class POP3TestStore : public vmime::net::pop3::POP3Store -{ +class POP3TestStore : public vmime::net::pop3::POP3Store { + public: POP3TestStore() : POP3Store(vmime::net::session::create(), - vmime::shared_ptr ()) - { + vmime::shared_ptr ()) { + } }; -class POP3ConnectionTest : public vmime::net::pop3::POP3Connection -{ +class POP3ConnectionTest : public vmime::net::pop3::POP3Connection { + public: - POP3ConnectionTest(vmime::shared_ptr socket, - vmime::shared_ptr timeoutHandler) + POP3ConnectionTest( + vmime::shared_ptr socket, + vmime::shared_ptr timeoutHandler + ) : POP3Connection(vmime::make_shared (), vmime::shared_ptr ()), - m_socket(socket), m_timeoutHandler(timeoutHandler) - { + m_socket(socket), + m_timeoutHandler(timeoutHandler) { + } - vmime::shared_ptr getSocket() - { + vmime::shared_ptr getSocket() { + return m_socket; } - vmime::shared_ptr getTimeoutHandler() - { + vmime::shared_ptr getTimeoutHandler() { + return m_timeoutHandler; } diff --git a/tests/net/pop3/POP3UtilsTest.cpp b/tests/net/pop3/POP3UtilsTest.cpp index 36029eaa..1cded39b 100644 --- a/tests/net/pop3/POP3UtilsTest.cpp +++ b/tests/net/pop3/POP3UtilsTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,13 +40,15 @@ VMIME_TEST_SUITE_BEGIN(POP3UtilsTest) VMIME_TEST_LIST_END - void testParseMultiListOrUidlResponse() - { + void testParseMultiListOrUidlResponse() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::shared_ptr toh = vmime::make_shared (); - vmime::shared_ptr conn = vmime::make_shared - (vmime::dynamicCast (socket), toh); + vmime::shared_ptr conn = + vmime::make_shared ( + vmime::dynamicCast (socket), toh + ); socket->localSend("+OK Response Text\r\n"); socket->localSend("1 abcdef\r\n"); @@ -70,11 +72,11 @@ VMIME_TEST_SUITE_BEGIN(POP3UtilsTest) VASSERT_EQ("5 (with extra space)", "yz", result[8]); } - void testMessageSetToNumberList() - { - const std::vector msgNums = - POP3Utils::messageSetToNumberList - (vmime::net::messageSet::byNumber(5, -1), /* msgCount */ 8); + void testMessageSetToNumberList() { + + const std::vector msgNums = POP3Utils::messageSetToNumberList( + vmime::net::messageSet::byNumber(5, -1), /* msgCount */ 8 + ); VASSERT_EQ("Count", 4, msgNums.size()); VASSERT_EQ("1", 5, msgNums[0]); @@ -84,4 +86,3 @@ VMIME_TEST_SUITE_BEGIN(POP3UtilsTest) } VMIME_TEST_SUITE_END - diff --git a/tests/net/smtp/SMTPCommandSetTest.cpp b/tests/net/smtp/SMTPCommandSetTest.cpp index f419eb40..7ea3578b 100644 --- a/tests/net/smtp/SMTPCommandSetTest.cpp +++ b/tests/net/smtp/SMTPCommandSetTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,24 +44,24 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) VMIME_TEST_LIST_END - void testCreate() - { + void testCreate() { + vmime::shared_ptr cset = SMTPCommandSet::create(/* pipelining */ false); VASSERT_NOT_NULL("Not null", cset); VASSERT_FALSE("Finished", cset->isFinished()); } - void testCreatePipeline() - { + void testCreatePipeline() { + vmime::shared_ptr cset = SMTPCommandSet::create(/* pipelining */ true); VASSERT_NOT_NULL("Not null", cset); VASSERT_FALSE("Finished", cset->isFinished()); } - void testAddCommand() - { + void testAddCommand() { + vmime::shared_ptr cset = SMTPCommandSet::create(/* pipelining */ false); VASSERT_NO_THROW("No throw 1", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1"))); @@ -82,8 +82,8 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) VASSERT_TRUE("Finished", cset->isFinished()); } - void testAddCommandPipeline() - { + void testAddCommandPipeline() { + vmime::shared_ptr cset = SMTPCommandSet::create(/* pipelining */ true); VASSERT_NO_THROW("No throw 1", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1"))); @@ -105,8 +105,8 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) VASSERT_THROW("Throw", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND3")), std::runtime_error); } - void testWriteToSocket() - { + void testWriteToSocket() { + vmime::shared_ptr cset = SMTPCommandSet::create(/* pipelining */ false); cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1")); @@ -127,8 +127,8 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) VASSERT_EQ("Receive cmd 2", "MY_COMMAND2\r\n", response); } - void testWriteToSocketPipeline() - { + void testWriteToSocketPipeline() { + vmime::shared_ptr cset = SMTPCommandSet::create(/* pipelining */ true); cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1")); @@ -144,8 +144,8 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) VASSERT_EQ("Receive cmds", "MY_COMMAND1\r\nMY_COMMAND2\r\n", response); } - void testGetLastCommandSent() - { + void testGetLastCommandSent() { + vmime::shared_ptr cset = SMTPCommandSet::create(/* pipelining */ false); cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1")); @@ -161,8 +161,8 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) VASSERT_EQ("Cmd 2", "MY_COMMAND2", cset->getLastCommandSent()->getText()); } - void testGetLastCommandSentPipeline() - { + void testGetLastCommandSentPipeline() { + vmime::shared_ptr cset = SMTPCommandSet::create(/* pipelining */ true); cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1")); diff --git a/tests/net/smtp/SMTPCommandTest.cpp b/tests/net/smtp/SMTPCommandTest.cpp index 9b3daa73..a0f03bb6 100644 --- a/tests/net/smtp/SMTPCommandTest.cpp +++ b/tests/net/smtp/SMTPCommandTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -56,150 +56,157 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandTest) VMIME_TEST_LIST_END - void testCreateCommand() - { + void testCreateCommand() { + vmime::shared_ptr cmd = SMTPCommand::createCommand("MY_COMMAND"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MY_COMMAND", cmd->getText()); } - void testCreateCommandParams() - { + void testCreateCommandParams() { + vmime::shared_ptr cmd = SMTPCommand::createCommand("MY_COMMAND param1 param2"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MY_COMMAND param1 param2", cmd->getText()); } - void testHELO() - { + void testHELO() { + vmime::shared_ptr cmd = SMTPCommand::HELO("hostname"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "HELO hostname", cmd->getText()); } - void testEHLO() - { + void testEHLO() { + vmime::shared_ptr cmd = SMTPCommand::EHLO("hostname"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "EHLO hostname", cmd->getText()); } - void testAUTH() - { + void testAUTH() { + vmime::shared_ptr cmd = SMTPCommand::AUTH("saslmechanism"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "AUTH saslmechanism", cmd->getText()); } - void testAUTH_InitialResponse() - { + void testAUTH_InitialResponse() { + vmime::shared_ptr cmd = SMTPCommand::AUTH("saslmechanism", "initial-response"); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "AUTH saslmechanism initial-response", cmd->getText()); } - void testSTARTTLS() - { + void testSTARTTLS() { + vmime::shared_ptr cmd = SMTPCommand::STARTTLS(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "STARTTLS", cmd->getText()); } - void testMAIL() - { + void testMAIL() { + vmime::shared_ptr cmd = SMTPCommand::MAIL(vmime::mailbox("me@vmime.org"), false); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MAIL FROM:", cmd->getText()); } - void testMAIL_Encoded() - { - vmime::shared_ptr cmd = SMTPCommand::MAIL - (vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), false); + void testMAIL_Encoded() { + + vmime::shared_ptr cmd = SMTPCommand::MAIL( + vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), false + ); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MAIL FROM:", cmd->getText()); } - void testMAIL_UTF8() - { - vmime::shared_ptr cmd = SMTPCommand::MAIL - (vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true); + void testMAIL_UTF8() { + + vmime::shared_ptr cmd = SMTPCommand::MAIL( + vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true + ); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MAIL FROM: SMTPUTF8", cmd->getText()); } - void testMAIL_SIZE() - { - vmime::shared_ptr cmd = SMTPCommand::MAIL - (vmime::mailbox("me@vmime.org"), false, 123456789); + void testMAIL_SIZE() { + + vmime::shared_ptr cmd = SMTPCommand::MAIL( + vmime::mailbox("me@vmime.org"), false, 123456789 + ); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MAIL FROM: SIZE=123456789", cmd->getText()); } - void testMAIL_SIZE_UTF8() - { - vmime::shared_ptr cmd = SMTPCommand::MAIL - (vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true, 123456789); + void testMAIL_SIZE_UTF8() { + + vmime::shared_ptr cmd = SMTPCommand::MAIL( + vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true, 123456789 + ); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "MAIL FROM: SMTPUTF8 SIZE=123456789", cmd->getText()); } - void testRCPT() - { - vmime::shared_ptr cmd = SMTPCommand::RCPT(vmime::mailbox("someone@vmime.org"), false); + void testRCPT() { + + vmime::shared_ptr cmd = + SMTPCommand::RCPT(vmime::mailbox("someone@vmime.org"), false); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "RCPT TO:", cmd->getText()); } - void testRCPT_Encoded() - { - vmime::shared_ptr cmd = SMTPCommand::RCPT - (vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), false); + void testRCPT_Encoded() { + + vmime::shared_ptr cmd = SMTPCommand::RCPT( + vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), false + ); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "RCPT TO:", cmd->getText()); } - void testRCPT_UTF8() - { - vmime::shared_ptr cmd = SMTPCommand::RCPT - (vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true); + void testRCPT_UTF8() { + + vmime::shared_ptr cmd = SMTPCommand::RCPT( + vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true + ); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "RCPT TO:", cmd->getText()); } - void testRSET() - { + void testRSET() { + vmime::shared_ptr cmd = SMTPCommand::RSET(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "RSET", cmd->getText()); } - void testDATA() - { + void testDATA() { + vmime::shared_ptr cmd = SMTPCommand::DATA(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "DATA", cmd->getText()); } - void testBDAT() - { + void testBDAT() { + vmime::shared_ptr cmd1 = SMTPCommand::BDAT(12345, false); VASSERT_NOT_NULL("Not null", cmd1); @@ -211,24 +218,24 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandTest) VASSERT_EQ("Text", "BDAT 67890 LAST", cmd2->getText()); } - void testNOOP() - { + void testNOOP() { + vmime::shared_ptr cmd = SMTPCommand::NOOP(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "NOOP", cmd->getText()); } - void testQUIT() - { + void testQUIT() { + vmime::shared_ptr cmd = SMTPCommand::QUIT(); VASSERT_NOT_NULL("Not null", cmd); VASSERT_EQ("Text", "QUIT", cmd->getText()); } - void testWriteToSocket() - { + void testWriteToSocket() { + vmime::shared_ptr cmd = SMTPCommand::createCommand("MY_COMMAND param1 param2"); vmime::shared_ptr tracer; diff --git a/tests/net/smtp/SMTPResponseTest.cpp b/tests/net/smtp/SMTPResponseTest.cpp index d47e31e9..f899a828 100644 --- a/tests/net/smtp/SMTPResponseTest.cpp +++ b/tests/net/smtp/SMTPResponseTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,12 +41,11 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VMIME_TEST_LIST_END - void testSingleLineResponse() - { + void testSingleLineResponse() { + vmime::shared_ptr tracer; vmime::shared_ptr socket = vmime::make_shared (); - vmime::shared_ptr toh = - vmime::make_shared (); + vmime::shared_ptr toh = vmime::make_shared (); socket->localSend("123 Response Text\r\n"); @@ -60,12 +59,11 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Text", "Response Text", resp->getText()); } - void testSingleLineResponseLF() - { + void testSingleLineResponseLF() { + vmime::shared_ptr tracer; vmime::shared_ptr socket = vmime::make_shared (); - vmime::shared_ptr toh = - vmime::make_shared (); + vmime::shared_ptr toh = vmime::make_shared (); socket->localSend("123 Response Text\n"); @@ -79,15 +77,13 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Text", "Response Text", resp->getText()); } - void testMultiLineResponse() - { + void testMultiLineResponse() { + vmime::shared_ptr tracer; vmime::shared_ptr socket = vmime::make_shared (); - vmime::shared_ptr toh = - vmime::make_shared (); + vmime::shared_ptr toh = vmime::make_shared (); - socket->localSend - ( + socket->localSend( "123-Response\r\n" "123 Text\r\n" ); @@ -108,15 +104,13 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Text", "Text", resp->getLineAt(1).getText()); } - void testMultiLineResponseDifferentCode() - { + void testMultiLineResponseDifferentCode() { + vmime::shared_ptr tracer; vmime::shared_ptr socket = vmime::make_shared (); - vmime::shared_ptr toh = - vmime::make_shared (); + vmime::shared_ptr toh = vmime::make_shared (); - socket->localSend - ( + socket->localSend( "123-Response\r\n" "456 Text\r\n" ); @@ -137,15 +131,13 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Text", "Text", resp->getLineAt(1).getText()); } - void testIncompleteMultiLineResponse() - { + void testIncompleteMultiLineResponse() { + vmime::shared_ptr tracer; vmime::shared_ptr socket = vmime::make_shared (); - vmime::shared_ptr toh = - vmime::make_shared (1); + vmime::shared_ptr toh = vmime::make_shared (1); - socket->localSend - ( + socket->localSend( "123-Response\r\n" "123-Text\r\n" // Missing data @@ -153,20 +145,20 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) vmime::net::smtp::SMTPResponse::state responseState; - VASSERT_THROW("Incomplete response", + VASSERT_THROW( + "Incomplete response", vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState), - vmime::exceptions::operation_timed_out); + vmime::exceptions::operation_timed_out + ); } - void testNoResponseText() - { + void testNoResponseText() { + vmime::shared_ptr tracer; vmime::shared_ptr socket = vmime::make_shared (); - vmime::shared_ptr toh = - vmime::make_shared (1); + vmime::shared_ptr toh = vmime::make_shared (1); - socket->localSend - ( + socket->localSend( "250\r\n" ); @@ -180,12 +172,11 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Text", "", resp->getText()); } - void testEnhancedStatusCode() - { + void testEnhancedStatusCode() { + vmime::shared_ptr tracer; vmime::shared_ptr socket = vmime::make_shared (); - vmime::shared_ptr toh = - vmime::make_shared (); + vmime::shared_ptr toh = vmime::make_shared (); socket->localSend("250 2.1.5 OK fu13sm4720601wic.7 - gsmtp\r\n"); @@ -202,12 +193,11 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Enh.detail", 5, resp->getEnhancedCode().detail); } - void testNoEnhancedStatusCode() - { + void testNoEnhancedStatusCode() { + vmime::shared_ptr tracer; vmime::shared_ptr socket = vmime::make_shared (); - vmime::shared_ptr toh = - vmime::make_shared (); + vmime::shared_ptr toh = vmime::make_shared (); socket->localSend("354 Go ahead fu13sm4720601wic.7 - gsmtp\r\n"); @@ -224,12 +214,11 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) VASSERT_EQ("Enh.detail", 0, resp->getEnhancedCode().detail); } - void testInvalidEnhancedStatusCode() - { + void testInvalidEnhancedStatusCode() { + vmime::shared_ptr tracer; vmime::shared_ptr socket = vmime::make_shared (); - vmime::shared_ptr toh = - vmime::make_shared (); + vmime::shared_ptr toh = vmime::make_shared (); socket->localSend("250 4.2 xxx\r\n"); @@ -247,4 +236,3 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) } VMIME_TEST_SUITE_END - diff --git a/tests/net/smtp/SMTPTransportTest.cpp b/tests/net/smtp/SMTPTransportTest.cpp index cbfab4f5..8ea4ba75 100644 --- a/tests/net/smtp/SMTPTransportTest.cpp +++ b/tests/net/smtp/SMTPTransportTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,21 +33,19 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) VMIME_TEST_LIST_BEGIN -/* VMIME_TEST(testConnectToInvalidServer) VMIME_TEST(testGreetingError) VMIME_TEST(testMAILandRCPT) VMIME_TEST(testChunking) VMIME_TEST(testSize_Chunking) VMIME_TEST(testSize_NoChunking) -*/ VMIME_TEST(testSMTPUTF8_available) VMIME_TEST(testSMTPUTF8_notAvailable) VMIME_TEST_LIST_END - void testConnectToInvalidServer() - { + void testConnectToInvalidServer() { + vmime::shared_ptr sess = vmime::net::session::create(); vmime::utility::url url("smtp://invalid-smtp-server"); @@ -56,26 +54,29 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) VASSERT_THROW("connect", store->connect(), vmime::exceptions::connection_error); } - void testGreetingError() - { + void testGreetingError() { + vmime::shared_ptr session = vmime::net::session::create(); - vmime::shared_ptr tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared >()); tr->setTimeoutHandlerFactory(vmime::make_shared ()); - VASSERT_THROW("Connection", tr->connect(), - vmime::exceptions::connection_greeting_error); + VASSERT_THROW( + "Connection", + tr->connect(), + vmime::exceptions::connection_greeting_error + ); } - void testMAILandRCPT() - { + void testMAILandRCPT() { + vmime::shared_ptr session = vmime::net::session::create(); - vmime::shared_ptr tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared >()); tr->setTimeoutHandlerFactory(vmime::make_shared ()); @@ -95,20 +96,22 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) tr->send(exp, recips, is, 0); } - void testChunking() - { + void testChunking() { + vmime::shared_ptr session = vmime::net::session::create(); - vmime::shared_ptr tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared >()); tr->setTimeoutHandlerFactory(vmime::make_shared ()); tr->connect(); - VASSERT("Test server should report it supports the CHUNKING extension!", - vmime::dynamicCast (tr)->getConnection()->hasExtension("CHUNKING")); + VASSERT( + "Test server should report it supports the CHUNKING extension!", + vmime::dynamicCast (tr)->getConnection()->hasExtension("CHUNKING") + ); vmime::mailbox exp("expeditor@test.vmime.org"); @@ -120,20 +123,22 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) tr->send(msg, exp, recips); } - void testSize_Chunking() - { + void testSize_Chunking() { + vmime::shared_ptr session = vmime::net::session::create(); - vmime::shared_ptr tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared > >()); tr->setTimeoutHandlerFactory(vmime::make_shared ()); tr->connect(); - VASSERT("Test server should report it supports the SIZE extension!", - vmime::dynamicCast (tr)->getConnection()->hasExtension("SIZE")); + VASSERT( + "Test server should report it supports the SIZE extension!", + vmime::dynamicCast (tr)->getConnection()->hasExtension("SIZE") + ); vmime::mailbox exp("expeditor@test.vmime.org"); @@ -142,24 +147,29 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) vmime::shared_ptr msg = vmime::make_shared (); - VASSERT_THROW("Connection", tr->send(msg, exp, recips), - vmime::net::smtp::SMTPMessageSizeExceedsMaxLimitsException); + VASSERT_THROW( + "Max size limit exception", + tr->send(msg, exp, recips), + vmime::net::smtp::SMTPMessageSizeExceedsMaxLimitsException + ); } - void testSize_NoChunking() - { + void testSize_NoChunking() { + vmime::shared_ptr session = vmime::net::session::create(); - vmime::shared_ptr tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared > >()); tr->setTimeoutHandlerFactory(vmime::make_shared ()); tr->connect(); - VASSERT("Test server should report it supports the SIZE extension!", - vmime::dynamicCast (tr)->getConnection()->hasExtension("SIZE")); + VASSERT( + "Test server should report it supports the SIZE extension!", + vmime::dynamicCast (tr)->getConnection()->hasExtension("SIZE") + ); vmime::mailbox exp("expeditor@test.vmime.org"); @@ -168,18 +178,21 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) vmime::shared_ptr msg = vmime::make_shared (); - VASSERT_THROW("Connection", tr->send(msg, exp, recips), - vmime::net::smtp::SMTPMessageSizeExceedsMaxLimitsException); + VASSERT_THROW( + "Max size limit exception", + tr->send(msg, exp, recips), + vmime::net::smtp::SMTPMessageSizeExceedsMaxLimitsException + ); } - void testSMTPUTF8_available() - { + void testSMTPUTF8_available() { + // Test with UTF8 sender { vmime::shared_ptr session = vmime::net::session::create(); - vmime::shared_ptr tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared > >()); tr->setTimeoutHandlerFactory(vmime::make_shared ()); @@ -213,8 +226,8 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) { vmime::shared_ptr session = vmime::net::session::create(); - vmime::shared_ptr tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared > >()); tr->setTimeoutHandlerFactory(vmime::make_shared ()); @@ -240,14 +253,14 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) } } - void testSMTPUTF8_notAvailable() - { + void testSMTPUTF8_notAvailable() { + // Test with UTF8 sender { vmime::shared_ptr session = vmime::net::session::create(); - vmime::shared_ptr tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared > >()); tr->setTimeoutHandlerFactory(vmime::make_shared ()); @@ -281,8 +294,8 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) { vmime::shared_ptr session = vmime::net::session::create(); - vmime::shared_ptr tr = session->getTransport - (vmime::utility::url("smtp://localhost")); + vmime::shared_ptr tr = + session->getTransport(vmime::utility::url("smtp://localhost")); tr->setSocketFactory(vmime::make_shared > >()); tr->setTimeoutHandlerFactory(vmime::make_shared ()); @@ -309,4 +322,3 @@ VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) } VMIME_TEST_SUITE_END - diff --git a/tests/net/smtp/SMTPTransportTestUtils.hpp b/tests/net/smtp/SMTPTransportTestUtils.hpp index b5af2f10..8710639f 100644 --- a/tests/net/smtp/SMTPTransportTestUtils.hpp +++ b/tests/net/smtp/SMTPTransportTestUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -24,20 +24,21 @@ /** Accepts connection and fails on greeting. */ -class greetingErrorSMTPTestSocket : public lineBasedTestSocket -{ +class greetingErrorSMTPTestSocket : public lineBasedTestSocket { + public: - void onConnected() - { + void onConnected() { + localSend("421 test.vmime.org Service not available, closing transmission channel\r\n"); disconnect(); } - void processCommand() - { - if (!haveMoreLines()) + void processCommand() { + + if (!haveMoreLines()) { return; + } getNextLine(); @@ -52,12 +53,12 @@ public: * Test send(). * Ensure MAIL and RCPT commands are sent correctly. */ -class MAILandRCPTSMTPTestSocket : public lineBasedTestSocket -{ +class MAILandRCPTSMTPTestSocket : public lineBasedTestSocket { + public: - MAILandRCPTSMTPTestSocket() - { + MAILandRCPTSMTPTestSocket() { + m_recipients.insert("recipient1@test.vmime.org"); m_recipients.insert("recipient2@test.vmime.org"); m_recipients.insert("recipient3@test.vmime.org"); @@ -66,60 +67,61 @@ public: m_ehloSent = m_heloSent = m_mailSent = m_rcptSent = m_dataSent = m_quitSent = false; } - ~MAILandRCPTSMTPTestSocket() - { + ~MAILandRCPTSMTPTestSocket() { + VASSERT("Client must send the DATA command", m_dataSent); VASSERT("Client must send the QUIT command", m_quitSent); } - void onConnected() - { + void onConnected() { + localSend("220 test.vmime.org Service ready\r\n"); processCommand(); m_state = STATE_COMMAND; } - void processCommand() - { - if (!haveMoreLines()) + void processCommand() { + + if (!haveMoreLines()) { return; + } vmime::string line = getNextLine(); std::istringstream iss(line); - switch (m_state) - { + switch (m_state) { + case STATE_NOT_CONNECTED: localSend("451 Requested action aborted: invalid state\r\n"); break; - case STATE_COMMAND: - { + case STATE_COMMAND: { + std::string cmd; iss >> cmd; - if (cmd.empty()) - { + if (cmd.empty()) { + localSend("500 Syntax error, command unrecognized\r\n"); - } - else if (cmd == "EHLO") - { + + } else if (cmd == "EHLO") { + localSend("502 Command not implemented\r\n"); m_ehloSent = true; - } - else if (cmd == "HELO") - { + + } else if (cmd == "HELO") { + VASSERT("Client must send the EHLO command before HELO", m_ehloSent); localSend("250 OK\r\n"); m_heloSent = true; - } - else if (cmd == "MAIL") - { + + } else if (cmd == "MAIL") { + VASSERT("Client must send the HELO command", m_heloSent); VASSERT("The MAIL command must be sent only one time", !m_mailSent); @@ -128,9 +130,9 @@ public: localSend("250 OK\r\n"); m_mailSent = true; - } - else if (cmd == "RCPT") - { + + } else if (cmd == "RCPT") { + const vmime::size_t lt = line.find('<'); const vmime::size_t gt = line.find('>'); @@ -138,23 +140,25 @@ public: VASSERT("RCPT >", gt != vmime::string::npos); VASSERT("RCPT ><", gt >= lt); - const vmime::string recip = vmime::string - (line.begin() + lt + 1, line.begin() + gt); + const vmime::string recip = + vmime::string(line.begin() + lt + 1, line.begin() + gt); std::set ::iterator it = m_recipients.find(recip); - VASSERT(std::string("Recipient not found: '") + recip + "'", - it != m_recipients.end()); + VASSERT( + std::string("Recipient not found: '") + recip + "'", + it != m_recipients.end() + ); m_recipients.erase(it); localSend("250 OK, recipient accepted\r\n"); m_rcptSent = true; - } - else if (cmd == "DATA") - { + + } else if (cmd == "DATA") { + VASSERT("Client must send the MAIL command", m_mailSent); VASSERT("Client must send the RCPT command", m_rcptSent); VASSERT("All recipients", m_recipients.empty()); @@ -165,35 +169,35 @@ public: m_msgData.clear(); m_dataSent = true; - } - else if (cmd == "NOOP") - { + + } else if (cmd == "NOOP") { + localSend("250 Completed\r\n"); - } - else if (cmd == "QUIT") - { + + } else if (cmd == "QUIT") { + m_quitSent = true; localSend("221 test.vmime.org Service closing transmission channel\r\n"); - } - else - { + + } else { + localSend("502 Command not implemented\r\n"); } break; } - case STATE_DATA: - { - if (line == ".") - { + case STATE_DATA: { + + if (line == ".") { + VASSERT_EQ("Data", "Message data\r\n", m_msgData); localSend("250 Message accepted for delivery\r\n"); m_state = STATE_COMMAND; - } - else - { + + } else { + m_msgData += line + "\r\n"; } @@ -207,8 +211,7 @@ public: private: - enum State - { + enum State { STATE_NOT_CONNECTED, STATE_COMMAND, STATE_DATA @@ -230,45 +233,45 @@ private: * * Test CHUNKING extension/BDAT command. */ -class chunkingSMTPTestSocket : public testSocket -{ +class chunkingSMTPTestSocket : public testSocket { + public: - chunkingSMTPTestSocket() - { + chunkingSMTPTestSocket() { + m_state = STATE_NOT_CONNECTED; m_bdatChunkCount = 0; m_ehloSent = m_mailSent = m_rcptSent = m_quitSent = false; } - ~chunkingSMTPTestSocket() - { + ~chunkingSMTPTestSocket() { + VASSERT_EQ("BDAT chunk count", 3, m_bdatChunkCount); VASSERT("Client must send the QUIT command", m_quitSent); } - void onConnected() - { + void onConnected() { + localSend("220 test.vmime.org Service ready\r\n"); processCommand(); m_state = STATE_COMMAND; } - void onDataReceived() - { - if (m_state == STATE_DATA) - { - if (m_bdatChunkReceived != m_bdatChunkSize) - { + void onDataReceived() { + + if (m_state == STATE_DATA) { + + if (m_bdatChunkReceived != m_bdatChunkSize) { + const size_t remaining = m_bdatChunkSize - m_bdatChunkReceived; const size_t received = localReceiveRaw(NULL, remaining); m_bdatChunkReceived += received; } - if (m_bdatChunkReceived == m_bdatChunkSize) - { + if (m_bdatChunkReceived == m_bdatChunkSize) { + m_state = STATE_COMMAND; } } @@ -276,58 +279,59 @@ public: processCommand(); } - void processCommand() - { + void processCommand() { + vmime::string line; - if (!localReceiveLine(line)) + if (!localReceiveLine(line)) { return; + } std::istringstream iss(line); - switch (m_state) - { + switch (m_state) { + case STATE_NOT_CONNECTED: localSend("451 Requested action aborted: invalid state\r\n"); break; - case STATE_COMMAND: - { + case STATE_COMMAND: { + std::string cmd; iss >> cmd; - if (cmd == "EHLO") - { + if (cmd == "EHLO") { + localSend("250-test.vmime.org says hello\r\n"); localSend("250 CHUNKING\r\n"); m_ehloSent = true; - } - else if (cmd == "HELO") - { + + } else if (cmd == "HELO") { + VASSERT("Client must not send the HELO command, as EHLO succeeded", false); - } - else if (cmd == "MAIL") - { + + } else if (cmd == "MAIL") { + VASSERT("The MAIL command must be sent only one time", !m_mailSent); localSend("250 OK\r\n"); m_mailSent = true; - } - else if (cmd == "RCPT") - { + + } else if (cmd == "RCPT") { + localSend("250 OK, recipient accepted\r\n"); m_rcptSent = true; - } - else if (cmd == "DATA") - { + + } else if (cmd == "DATA") { + VASSERT("BDAT must be used here!", false); - } - else if (cmd == "BDAT") - { + + } else if (cmd == "BDAT") { + VASSERT("Client must send the MAIL command", m_mailSent); VASSERT("Client must send the RCPT command", m_rcptSent); @@ -337,23 +341,23 @@ public: std::string last; iss >> last; - if (m_bdatChunkCount == 0) - { + if (m_bdatChunkCount == 0) { + VASSERT_EQ("BDAT chunk1 size", 262144, chunkSize); VASSERT_EQ("BDAT chunk1 last", "", last); - } - else if (m_bdatChunkCount == 1) - { + + } else if (m_bdatChunkCount == 1) { + VASSERT_EQ("BDAT chunk2 size", 262144, chunkSize); VASSERT_EQ("BDAT chunk2 last", "", last); - } - else if (m_bdatChunkCount == 2) - { + + } else if (m_bdatChunkCount == 2) { + VASSERT_EQ("BDAT chunk3 size", 4712, chunkSize); VASSERT_EQ("BDAT chunk3 last", "LAST", last); - } - else - { + + } else { + VASSERT("No more BDAT command should be issued!", false); } @@ -363,19 +367,19 @@ public: m_state = STATE_DATA; localSend("250 chunk received\r\n"); - } - else if (cmd == "NOOP") - { + + } else if (cmd == "NOOP") { + localSend("250 Completed\r\n"); - } - else if (cmd == "QUIT") - { + + } else if (cmd == "QUIT") { + localSend("221 test.vmime.org Service closing transmission channel\r\n"); m_quitSent = true; - } - else - { + + } else { + localSend("502 Command not implemented\r\n"); } @@ -389,8 +393,7 @@ public: private: - enum State - { + enum State { STATE_NOT_CONNECTED, STATE_COMMAND, STATE_DATA @@ -404,22 +407,21 @@ private: }; -class SMTPTestMessage : public vmime::message -{ +class SMTPTestMessage : public vmime::message { + public: - vmime::size_t getChunkBufferSize() const - { + vmime::size_t getChunkBufferSize() const { + static vmime::net::smtp::SMTPChunkingOutputStreamAdapter chunkStream(vmime::null, 0, NULL); return chunkStream.getBlockSize(); } - const std::vector & getChunks() const - { + const std::vector & getChunks() const { + static std::vector chunks; - if (chunks.size() == 0) - { + if (chunks.size() == 0) { chunks.push_back(vmime::string(1000, 'A')); chunks.push_back(vmime::string(3000, 'B')); chunks.push_back(vmime::string(500000, 'C')); @@ -429,12 +431,15 @@ public: return chunks; } - void generateImpl - (const vmime::generationContext& /* ctx */, vmime::utility::outputStream& outputStream, - const size_t /* curLinePos */ = 0, size_t* /* newLinePos */ = NULL) const - { - for (size_t i = 0, n = getChunks().size() ; i < n ; ++i) - { + void generateImpl( + const vmime::generationContext& /* ctx */, + vmime::utility::outputStream& outputStream, + const size_t /* curLinePos */ = 0, + size_t* /* newLinePos */ = NULL + ) const { + + for (size_t i = 0, n = getChunks().size() ; i < n ; ++i) { + const vmime::string& chunk = getChunks()[i]; outputStream.write(chunk.data(), chunk.size()); } @@ -448,72 +453,74 @@ public: * Test SIZE extension. */ template -class bigMessageSMTPTestSocket : public testSocket -{ +class bigMessageSMTPTestSocket : public testSocket { + public: - bigMessageSMTPTestSocket() - { + bigMessageSMTPTestSocket() { + m_state = STATE_NOT_CONNECTED; m_ehloSent = m_mailSent = m_rcptSent = m_quitSent = false; } - ~bigMessageSMTPTestSocket() - { + ~bigMessageSMTPTestSocket() { + VASSERT("Client must send the QUIT command", m_quitSent); } - void onConnected() - { + void onConnected() { + localSend("220 test.vmime.org Service ready\r\n"); processCommand(); m_state = STATE_COMMAND; } - void onDataReceived() - { + void onDataReceived() { + processCommand(); } - void processCommand() - { + void processCommand() { + vmime::string line; - if (!localReceiveLine(line)) + if (!localReceiveLine(line)) { return; + } std::istringstream iss(line); - switch (m_state) - { + switch (m_state) { + case STATE_NOT_CONNECTED: localSend("451 Requested action aborted: invalid state\r\n"); break; - case STATE_COMMAND: - { + case STATE_COMMAND: { + std::string cmd; iss >> cmd; - if (cmd == "EHLO") - { + if (cmd == "EHLO") { + localSend("250-test.vmime.org says hello\r\n"); - if (WITH_CHUNKING) + if (WITH_CHUNKING) { localSend("250-CHUNKING\r\n"); + } localSend("250 SIZE 1000000\r\n"); m_ehloSent = true; - } - else if (cmd == "HELO") - { + + } else if (cmd == "HELO") { + VASSERT("Client must not send the HELO command, as EHLO succeeded", false); - } - else if (cmd == "MAIL") - { + + } else if (cmd == "MAIL") { + VASSERT("The MAIL command must be sent only one time", !m_mailSent); std::string address; @@ -529,19 +536,19 @@ public: localSend("552 Channel size limit exceeded\r\n"); m_mailSent = true; - } - else if (cmd == "NOOP") - { + + } else if (cmd == "NOOP") { + localSend("250 Completed\r\n"); - } - else if (cmd == "QUIT") - { + + } else if (cmd == "QUIT") { + localSend("221 test.vmime.org Service closing transmission channel\r\n"); m_quitSent = true; - } - else - { + + } else { + VASSERT("No other command should be sent", false); localSend("502 Command not implemented\r\n"); @@ -557,8 +564,7 @@ public: private: - enum State - { + enum State { STATE_NOT_CONNECTED, STATE_COMMAND, STATE_DATA @@ -571,22 +577,25 @@ private: template -class SMTPBigTestMessage : public vmime::message -{ +class SMTPBigTestMessage : public vmime::message { + public: - size_t getGeneratedSize(const vmime::generationContext& /* ctx */) - { + size_t getGeneratedSize(const vmime::generationContext& /* ctx */) { + return SIZE; } - void generateImpl(const vmime::generationContext& /* ctx */, - vmime::utility::outputStream& outputStream, - const vmime::size_t /* curLinePos */ = 0, - vmime::size_t* /* newLinePos */ = NULL) const - { - for (unsigned int i = 0, n = SIZE ; i < n ; ++i) + void generateImpl( + const vmime::generationContext& /* ctx */, + vmime::utility::outputStream& outputStream, + const vmime::size_t /* curLinePos */ = 0, + vmime::size_t* /* newLinePos */ = NULL + ) const { + + for (unsigned int i = 0, n = SIZE ; i < n ; ++i) { outputStream.write("X", 1); + } } }; @@ -597,20 +606,20 @@ typedef SMTPBigTestMessage <4194304> SMTPBigTestMessage4MB; /** SMTP test server for SMTPUTF8 extension. */ template -class UTF8SMTPTestSocket : public lineBasedTestSocket -{ +class UTF8SMTPTestSocket : public lineBasedTestSocket { + public: - UTF8SMTPTestSocket() - { - if (SUPPORTS_UTF8) - { + UTF8SMTPTestSocket() { + + if (SUPPORTS_UTF8) { + m_rcptLines.insert("RCPT TO:"); m_rcptLines.insert("RCPT TO:"); m_rcptLines.insert("RCPT TO:"); - } - else - { + + } else { + m_rcptLines.insert("RCPT TO:"); m_rcptLines.insert("RCPT TO:"); m_rcptLines.insert("RCPT TO:<=?utf-8?Q?r=C3=A9cepteur?=@test.vmime.org>"); @@ -620,75 +629,76 @@ public: m_ehloSent = m_mailSent = m_rcptSent = m_dataSent = m_quitSent = false; } - ~UTF8SMTPTestSocket() - { + ~UTF8SMTPTestSocket() { + } - void onConnected() - { + void onConnected() { + localSend("220 test.vmime.org Service ready\r\n"); processCommand(); m_state = STATE_COMMAND; } - void processCommand() - { - if (!haveMoreLines()) + void processCommand() { + + if (!haveMoreLines()) { return; + } vmime::string line = getNextLine(); std::istringstream iss(line); - switch (m_state) - { + switch (m_state) { + case STATE_NOT_CONNECTED: localSend("451 Requested action aborted: invalid state\r\n"); break; - case STATE_COMMAND: - { + case STATE_COMMAND: { + std::string cmd; iss >> cmd; - if (cmd.empty()) - { + if (cmd.empty()) { + localSend("500 Syntax error, command unrecognized\r\n"); - } - else if (cmd == "EHLO") - { - if (SUPPORTS_UTF8) - { + + } else if (cmd == "EHLO") { + + if (SUPPORTS_UTF8) { + localSend("250-test.vmime.org\r\n"); localSend("250 SMTPUTF8\r\n"); - } - else - { + + } else { + localSend("250 test.vmime.org\r\n"); } m_ehloSent = true; - } - else if (cmd == "HELO") - { + + } else if (cmd == "HELO") { + VASSERT("Client must not send the HELO command, as EHLO succeeded", false); - } - else if (cmd == "MAIL") - { + + } else if (cmd == "MAIL") { + VASSERT("Client must send the EHLO command", m_ehloSent); VASSERT("The MAIL command must be sent only one time", !m_mailSent); - if (SUPPORTS_UTF8) - { + if (SUPPORTS_UTF8) { + VASSERT( "MAIL", std::string("MAIL FROM: SMTPUTF8") == line || std::string("MAIL FROM: SMTPUTF8") == line ); - } - else - { + + } else { + VASSERT( "MAIL", std::string("MAIL FROM:") == line @@ -699,9 +709,9 @@ public: localSend("250 OK\r\n"); m_mailSent = true; - } - else if (cmd == "RCPT") - { + + } else if (cmd == "RCPT") { + std::set ::iterator it = m_rcptLines.find(line); VASSERT(std::string("RCPT not found: '") + line + "'", it != m_rcptLines.end()); @@ -711,9 +721,9 @@ public: localSend("250 OK, recipient accepted\r\n"); m_rcptSent = true; - } - else if (cmd == "DATA") - { + + } else if (cmd == "DATA") { + VASSERT("Client must send the MAIL command", m_mailSent); VASSERT("Client must send the RCPT command", m_rcptSent); VASSERT("All recipients", m_rcptLines.empty()); @@ -724,35 +734,35 @@ public: m_msgData.clear(); m_dataSent = true; - } - else if (cmd == "NOOP") - { + + } else if (cmd == "NOOP") { + localSend("250 Completed\r\n"); - } - else if (cmd == "QUIT") - { + + } else if (cmd == "QUIT") { + m_quitSent = true; localSend("221 test.vmime.org Service closing transmission channel\r\n"); - } - else - { + + } else { + localSend("502 Command not implemented\r\n"); } break; } - case STATE_DATA: - { - if (line == ".") - { + case STATE_DATA: { + + if (line == ".") { + VASSERT_EQ("Data", "Message data\r\n", m_msgData); localSend("250 Message accepted for delivery\r\n"); m_state = STATE_COMMAND; - } - else - { + + } else { + m_msgData += line + "\r\n"; } @@ -766,8 +776,7 @@ public: private: - enum State - { + enum State { STATE_NOT_CONNECTED, STATE_COMMAND, STATE_DATA diff --git a/tests/parser/attachmentHelperTest.cpp b/tests/parser/attachmentHelperTest.cpp index 6bd3b7db..866f8de4 100644 --- a/tests/parser/attachmentHelperTest.cpp +++ b/tests/parser/attachmentHelperTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -39,23 +39,25 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) VMIME_TEST_LIST_END - static const vmime::string getStructure(const vmime::shared_ptr & part) - { + static const vmime::string getStructure(const vmime::shared_ptr & part) { + vmime::shared_ptr bdy = part->getBody(); vmime::string res = part->getBody()->getContentType().generate(); - if (bdy->getPartCount() == 0) + if (bdy->getPartCount() == 0) { return res; + } res += "["; - for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) - { + for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) { + vmime::shared_ptr subPart = bdy->getPartAt(i); - if (i != 0) + if (i != 0) { res += ","; + } res += getStructure(subPart); } @@ -63,8 +65,10 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) return res + "]"; } - static const vmime::string extractBodyContents(const vmime::shared_ptr & part) - { + static const vmime::string extractBodyContents( + const vmime::shared_ptr & part + ) { + vmime::shared_ptr cth = part->getBody()->getContents(); vmime::string data; @@ -75,8 +79,8 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) return data; } - void testAddAttachment1() - { + void testAddAttachment1() { + vmime::string data = "Content-Type: text/plain\r\n" "\r\n" @@ -86,9 +90,11 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) vmime::shared_ptr msg = vmime::make_shared (); msg->parse(data); - vmime::shared_ptr att = vmime::make_shared - (vmime::make_shared ("test"), - vmime::mediaType("image/jpeg")); + vmime::shared_ptr att = + vmime::make_shared ( + vmime::make_shared ("test"), + vmime::mediaType("image/jpeg") + ); vmime::attachmentHelper::addAttachment(msg, att); @@ -96,8 +102,8 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) VASSERT_EQ("2", "The text\r\n", extractBodyContents(msg->getBody()->getPartAt(0))); } - void testAddAttachment2() - { + void testAddAttachment2() { + vmime::string data = "Content-Type: multipart/mixed; boundary=\"foo\"\r\n" "\r\n" @@ -115,9 +121,11 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) vmime::shared_ptr msg = vmime::make_shared (); msg->parse(data); - vmime::shared_ptr att = vmime::make_shared - (vmime::make_shared ("test"), - vmime::mediaType("image/jpeg")); + vmime::shared_ptr att = + vmime::make_shared ( + vmime::make_shared ("test"), + vmime::mediaType("image/jpeg") + ); vmime::attachmentHelper::addAttachment(msg, att); @@ -128,8 +136,8 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) } // Initial part is encoded - void testAddAttachment3() - { + void testAddAttachment3() { + vmime::string data = "Content-Type: text/plain\r\n" "Content-Transfer-Encoding: base64\r\n" @@ -139,9 +147,11 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) vmime::shared_ptr msg = vmime::make_shared (); msg->parse(data); - vmime::shared_ptr att = vmime::make_shared - (vmime::make_shared ("test"), - vmime::mediaType("image/jpeg")); + vmime::shared_ptr att = + vmime::make_shared ( + vmime::make_shared ("test"), + vmime::mediaType("image/jpeg") + ); vmime::attachmentHelper::addAttachment(msg, att); @@ -151,8 +161,8 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) // Content-Disposition: attachment // No other field - void testIsBodyPartAnAttachment1() - { + void testIsBodyPartAnAttachment1() { + vmime::string data = "Content-Disposition: attachment\r\n\r\nFoo\r\n"; vmime::shared_ptr p = vmime::make_shared (); @@ -163,8 +173,8 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) // No Content-Disposition field // Content-Type: multipart/* or text/* - void testIsBodyPartAnAttachment2() - { + void testIsBodyPartAnAttachment2() { + vmime::string data = "Content-Type: multipart/*\r\n\r\nFoo\r\n"; vmime::shared_ptr p = vmime::make_shared (); @@ -180,8 +190,8 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) } // No Content-Disposition field - void testIsBodyPartAnAttachment3() - { + void testIsBodyPartAnAttachment3() { + vmime::string data = "Content-Type: application/octet-stream\r\n\r\nFoo\r\n"; vmime::shared_ptr p = vmime::make_shared (); @@ -192,8 +202,8 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) // Content-Disposition: attachment // Content-Id field present - void testIsBodyPartAnAttachment4() - { + void testIsBodyPartAnAttachment4() { + vmime::string data = "Content-Disposition: attachment\r\n" "Content-Type: application/octet-stream\r\n" "Content-Id: bar\r\n" @@ -205,8 +215,8 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) VASSERT_EQ("1", false, vmime::attachmentHelper::isBodyPartAnAttachment(p)); } - void testGetBodyPartAttachment() - { + void testGetBodyPartAttachment() { + vmime::string data = "Content-Type: image/jpeg\r\n" "Content-Description: foobar\r\n" @@ -238,8 +248,8 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) VASSERT_EQ("7", part->getHeader()->generate(), att->getHeader()->generate()); } - void testAddAttachmentMessage1() - { + void testAddAttachmentMessage1() { + const vmime::string data = "Subject: Test message\r\n" "Content-Type: text/plain\r\n" @@ -282,8 +292,8 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) VASSERT_EQ("4", "Attached message body", extractBodyContents(amsgOut)); } - void testGetBodyPartAttachmentMessage() - { + void testGetBodyPartAttachmentMessage() { + const vmime::string data = "Subject: Test message\r\n" "Content-Type: multipart/mixed; boundary=\"foo\"\r\n" @@ -305,8 +315,8 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) VASSERT_EQ("0", 2, msg->getBody()->getPartCount()); - vmime::shared_ptr att = vmime::attachmentHelper:: - getBodyPartAttachment(msg->getBody()->getPartAt(0)); + vmime::shared_ptr att = + vmime::attachmentHelper::getBodyPartAttachment(msg->getBody()->getPartAt(0)); VASSERT("1", att != NULL); @@ -323,4 +333,3 @@ VMIME_TEST_SUITE_BEGIN(attachmentHelperTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/bodyPartTest.cpp b/tests/parser/bodyPartTest.cpp index e6ff737a..91742553 100644 --- a/tests/parser/bodyPartTest.cpp +++ b/tests/parser/bodyPartTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,15 +42,21 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) VMIME_TEST_LIST_END - static const vmime::string extractComponentString - (const vmime::string& buffer, const vmime::component& c) - { - return vmime::string(buffer.begin() + c.getParsedOffset(), - buffer.begin() + c.getParsedOffset() + c.getParsedLength()); + static const vmime::string extractComponentString( + const vmime::string& buffer, + const vmime::component& c + ) { + + return vmime::string( + buffer.begin() + c.getParsedOffset(), + buffer.begin() + c.getParsedOffset() + c.getParsedLength() + ); } - static const vmime::string extractContents(const vmime::shared_ptr & cts) - { + static const vmime::string extractContents( + const vmime::shared_ptr & cts + ) { + std::ostringstream oss; vmime::utility::outputStreamAdapter os(oss); @@ -60,8 +66,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) } - void testParse() - { + void testParse() { + vmime::string str1 = "HEADER\r\n\r\nBODY"; vmime::bodyPart p1; p1.parse(str1); @@ -84,8 +90,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) VASSERT_EQ("6", "BODY", extractComponentString(str3, *p3.getBody())); } - void testParseMissingLastBoundary() - { + void testParseMissingLastBoundary() { + vmime::string str = "Content-Type: multipart/mixed; boundary=\"MY-BOUNDARY\"" "\r\n\r\n" @@ -101,8 +107,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) VASSERT_EQ("part2-body", "BODY2", extractContents(p.getBody()->getPartAt(1)->getBody()->getContents())); } - void testGenerate() - { + void testGenerate() { + vmime::bodyPart p1; p1.getHeader()->getField("Foo")->setValue(vmime::string("bar")); p1.getBody()->setContents(vmime::make_shared ("Baz")); @@ -110,8 +116,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) VASSERT_EQ("1", "Foo: bar\r\n\r\nBaz", p1.generate()); } - void testPrologEpilog() - { + void testPrologEpilog() { + const char testMail[] = "To: test@vmime.org\r\n" "From: test@vmime.org\r\n" @@ -136,8 +142,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) // Test for bug fix: prolog should not be encoded // http://sourceforge.net/tracker/?func=detail&atid=525568&aid=3174903&group_id=69724 - void testPrologEncoding() - { + void testPrologEncoding() { + const char testmail[] = "To: test@vmime.org\r\n" "From: test@vmime.org\r\n" @@ -169,8 +175,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) std::string ostr; vmime::utility::outputStreamStringAdapter out(ostr); - for (int i = 0 ; i < 10 ; ++i) - { + for (int i = 0 ; i < 10 ; ++i) { + ostr.clear(); msg->parse(istr); @@ -184,8 +190,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) VASSERT_EQ("epilog", "Epilog text", msg->getBody()->getEpilogText()); } - void testSuccessiveBoundaries() - { + void testSuccessiveBoundaries() { + vmime::string str = "Content-Type: multipart/mixed; boundary=\"MY-BOUNDARY\"" "\r\n\r\n" @@ -202,8 +208,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) VASSERT_EQ("part2-body", "", extractContents(p.getBody()->getPartAt(1)->getBody()->getContents())); } - void testTransportPaddingInBoundary() - { + void testTransportPaddingInBoundary() { + vmime::string str = "Content-Type: multipart/mixed; boundary=\"MY-BOUNDARY\"" "\r\n\r\n" @@ -221,8 +227,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) } /** Ensure '7bit' encoding is used when body is 7-bit only. */ - void testGenerate7bit() - { + void testGenerate7bit() { + vmime::shared_ptr p1 = vmime::make_shared (); p1->setText(vmime::make_shared ("Part1 is US-ASCII only.")); @@ -233,8 +239,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) VASSERT_EQ("1", "7bit", header1->ContentTransferEncoding()->getValue()->generate()); } - void testTextUsageForQPEncoding() - { + void testTextUsageForQPEncoding() { + vmime::shared_ptr part = vmime::make_shared (); part->setText(vmime::make_shared ("Part1-line1\r\nPart1-line2\r\n\x89")); @@ -255,8 +261,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) VASSERT_EQ("2", "Part1-line1\r\nPart1-line2\r\n=89", oss.str()); } - void testParseGuessBoundary() - { + void testParseGuessBoundary() { + // Boundary is not specified in "Content-Type" field // Parser will try to guess it from message contents. @@ -276,8 +282,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) VASSERT_EQ("part2-body", "BODY2", extractContents(p.getBody()->getPartAt(1)->getBody()->getContents())); } - void testParseGuessBoundaryWithTransportPadding() - { + void testParseGuessBoundaryWithTransportPadding() { + // Boundary is not specified in "Content-Type" field // Parser will try to guess it from message contents. // Transport padding white spaces should be ignored. @@ -298,8 +304,8 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) VASSERT_EQ("part2-body", "BODY2", extractContents(p.getBody()->getPartAt(1)->getBody()->getContents())); } - void testParseVeryBigMessage() - { + void testParseVeryBigMessage() { + // When parsing from a seekable input stream, body contents should not // be kept in memory in a "stringContentHandler" object. Instead, content // should be accessible via a "streamContentHandler" object. @@ -323,8 +329,9 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) oss << BODY1_BEGIN; - for (unsigned int i = 0 ; i < BODY1_REPEAT ; ++i) + for (unsigned int i = 0 ; i < BODY1_REPEAT ; ++i) { oss << BODY1_LINE; + } oss << BODY1_END; @@ -333,8 +340,9 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) << "HEADER2\r\n" << "\r\n"; - for (unsigned int i = 0 ; i < BODY2_REPEAT ; ++i) + for (unsigned int i = 0 ; i < BODY2_REPEAT ; ++i) { oss << BODY2_LINE; + } oss << "\r\n" << "--MY-BOUNDARY--\r\n"; @@ -366,4 +374,3 @@ VMIME_TEST_SUITE_BEGIN(bodyPartTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/bodyTest.cpp b/tests/parser/bodyTest.cpp index 92a4575e..fa396af5 100644 --- a/tests/parser/bodyTest.cpp +++ b/tests/parser/bodyTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,35 +32,49 @@ VMIME_TEST_SUITE_BEGIN(bodyTest) VMIME_TEST_LIST_END - void testGenerate_Text() - { + void testGenerate_Text() { + // RFC-2015: [Quoted-Printable encoding] A line break in a text body, // represented as a CRLF sequence in the text canonical form, must be // represented by a line break which is also a CRLF sequence, in the // Quoted-Printable encoding vmime::bodyPart p; - p.getBody()->setContents(vmime::make_shared - ("Foo éé\r\né bar\r\nbaz"), vmime::mediaType("text", "plain"), - vmime::charset("utf-8"), vmime::encoding("quoted-printable")); + p.getBody()->setContents( + vmime::make_shared ( + "Foo éé\r\né bar\r\nbaz" + ), + vmime::mediaType("text", "plain"), + vmime::charset("utf-8"), + vmime::encoding("quoted-printable") + ); - VASSERT_EQ("generate", + VASSERT_EQ( + "generate", "Foo =C3=A9=C3=A9\r\n" "=C3=A9 bar\r\n" "baz", - p.getBody()->generate()); + p.getBody()->generate() + ); } - void testGenerate_NonText() - { - vmime::bodyPart p; - p.getBody()->setContents(vmime::make_shared - ("Binary\xfa\xfb\r\ndata\r\n\r\n\xfc"), vmime::mediaType("application", "octet-stream"), - vmime::charset("utf-8"), vmime::encoding("quoted-printable")); + void testGenerate_NonText() { - VASSERT_EQ("generate", + vmime::bodyPart p; + p.getBody()->setContents( + vmime::make_shared ( + "Binary\xfa\xfb\r\ndata\r\n\r\n\xfc" + ), + vmime::mediaType("application", "octet-stream"), + vmime::charset("utf-8"), + vmime::encoding("quoted-printable") + ); + + VASSERT_EQ( + "generate", "Binary=FA=FB=0D=0Adata=0D=0A=0D=0A=FC", - p.getBody()->generate()); + p.getBody()->generate() + ); } VMIME_TEST_SUITE_END diff --git a/tests/parser/charsetFilteredOutputStreamTest.cpp b/tests/parser/charsetFilteredOutputStreamTest.cpp index 9b8397a8..0ebd83a7 100644 --- a/tests/parser/charsetFilteredOutputStreamTest.cpp +++ b/tests/parser/charsetFilteredOutputStreamTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,8 +40,8 @@ VMIME_TEST_SUITE_BEGIN(charsetFilteredOutputStreamTest) VMIME_TEST_LIST_END - void testInputBufferUnderflow() - { + void testInputBufferUnderflow() { + vmime::shared_ptr cc = vmime::charsetConverter::create("utf-8", "iso-8859-1"); @@ -65,8 +65,8 @@ VMIME_TEST_SUITE_BEGIN(charsetFilteredOutputStreamTest) VASSERT_EQ("chunk 2", toHex("f\xf8o"), toHex(output)); } - void testInvalidInput1() - { + void testInvalidInput1() { + vmime::string in("foo\xab\xcd\xef bar"); vmime::string expectedOut("foo??? bar"); @@ -74,9 +74,7 @@ VMIME_TEST_SUITE_BEGIN(charsetFilteredOutputStreamTest) vmime::utility::outputStreamStringAdapter osa(actualOut); vmime::shared_ptr conv = - vmime::charsetConverter::create - (vmime::charset("utf-8"), - vmime::charset("iso-8859-1")); + vmime::charsetConverter::create(vmime::charset("utf-8"), vmime::charset("iso-8859-1")); vmime::shared_ptr os = conv->getFilteredOutputStream(osa); @@ -96,10 +94,10 @@ VMIME_TEST_SUITE_BEGIN(charsetFilteredOutputStreamTest) } // Using 'bufferedStreamCopy' - void testStreamCopy() - { - for (unsigned int i = 0 ; i < charsetTestSuitesCount ; ++i) - { + void testStreamCopy() { + + for (unsigned int i = 0 ; i < charsetTestSuitesCount ; ++i) { + const charsetTestSuiteStruct& entry = charsetTestSuites[i]; std::ostringstream testName; @@ -133,10 +131,10 @@ VMIME_TEST_SUITE_BEGIN(charsetFilteredOutputStreamTest) } // One byte at a time - void testOneByteAtTime() - { - for (unsigned int i = 0 ; i < charsetTestSuitesCount ; ++i) - { + void testOneByteAtTime() { + + for (unsigned int i = 0 ; i < charsetTestSuitesCount ; ++i) { + const charsetTestSuiteStruct& entry = charsetTestSuites[i]; std::ostringstream testName; @@ -173,10 +171,10 @@ VMIME_TEST_SUITE_BEGIN(charsetFilteredOutputStreamTest) } // Variable chunks - void testVariableInputChunk() - { - for (unsigned int i = 0 ; i < charsetTestSuitesCount ; ++i) - { + void testVariableInputChunk() { + + for (unsigned int i = 0 ; i < charsetTestSuitesCount ; ++i) { + const charsetTestSuiteStruct& entry = charsetTestSuites[i]; std::ostringstream testName; diff --git a/tests/parser/charsetTest.cpp b/tests/parser/charsetTest.cpp index e599c5b5..e44bef5b 100644 --- a/tests/parser/charsetTest.cpp +++ b/tests/parser/charsetTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -52,10 +52,10 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) VMIME_TEST_LIST_END - void testConvertStringValid() - { - for (unsigned int i = 0 ; i < charsetTestSuitesCount ; ++i) - { + void testConvertStringValid() { + + for (unsigned int i = 0 ; i < charsetTestSuitesCount ; ++i) { + const charsetTestSuiteStruct& entry = charsetTestSuites[i]; std::ostringstream testName; @@ -76,10 +76,10 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) } } - void testConvertStreamValid() - { - for (unsigned int i = 0 ; i < charsetTestSuitesCount ; ++i) - { + void testConvertStreamValid() { + + for (unsigned int i = 0 ; i < charsetTestSuitesCount ; ++i) { + const charsetTestSuiteStruct& entry = charsetTestSuites[i]; std::ostringstream testName; @@ -96,8 +96,7 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) vmime::utility::inputStreamStringAdapter is(in); - vmime::charset::convert - (is, os, entry.fromCharset, entry.toCharset); + vmime::charset::convert(is, os, entry.fromCharset, entry.toCharset); os.flush(); @@ -105,8 +104,8 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) } } - void testEncodingHebrew1255() - { + void testEncodingHebrew1255() { + // hewbrew string in windows-1255 charset const char data[] = "\xe9\xf9\xf7\xf8\xe9\xf9\xf8\xf7\xe9\xe9\xf9"; vmime::word w = vmime::word(data, "windows-1255"); @@ -115,11 +114,14 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) VASSERT_EQ("1", "=?windows-1255?B?6fn3+On5+Pfp6fk=?=", encoded); } - static const vmime::string convertHelper - (const vmime::string& in, const vmime::charset& csrc, const vmime::charset& cdest, - const vmime::charsetConverterOptions& opts = vmime::charsetConverterOptions(), - vmime::charsetConverter::status* st = NULL) - { + static const vmime::string convertHelper( + const vmime::string& in, + const vmime::charset& csrc, + const vmime::charset& cdest, + const vmime::charsetConverterOptions& opts = vmime::charsetConverterOptions(), + vmime::charsetConverter::status* st = NULL + ) { + vmime::shared_ptr conv = vmime::charsetConverter::create(csrc, cdest, opts); @@ -129,8 +131,8 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) return out; } - void testEncodeIDNA() - { + void testEncodeIDNA() { + VASSERT_EQ("1", "xn--espaol-zwa", convertHelper("español", "utf-8", "idna")); // Tests from ICANN @@ -141,8 +143,8 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) VASSERT_EQ("3.2", "xn--kgbechtv", convertHelper("إختبار", "utf-8", "idna")); } - void testDecodeIDNA() - { + void testDecodeIDNA() { + VASSERT_EQ("1", "español", convertHelper("xn--espaol-zwa", "idna", "utf-8")); // Tests from ICANN @@ -153,21 +155,23 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) VASSERT_EQ("3.2", "إختبار", convertHelper("xn--kgbechtv", "idna", "utf-8")); } - void testUTF7Support() - { + void testUTF7Support() { + // Ensure UTF-7 is supported, because it is used for IMAP VASSERT_EQ("1", "VMime +- UTF-7 encoding", convertHelper("VMime + UTF-7 encoding", "utf-8", "utf-7")); VASSERT_EQ("2", "f+APg-o", convertHelper("\x66\xc3\xb8\x6f", "utf-8", "utf-7")); } - void testReplaceInvalidSequence() - { + void testReplaceInvalidSequence() { + vmime::charsetConverterOptions opts; opts.silentlyReplaceInvalidSequences = true; opts.invalidSequence = "?"; - vmime::string res = convertHelper - ("\x61\xf1\x80\x80\xe1\x80\xc2\x62\x80\x63\x80\xbf\x64", "utf-8", "iso-8859-1", opts); + vmime::string res = convertHelper( + "\x61\xf1\x80\x80\xe1\x80\xc2\x62\x80\x63\x80\xbf\x64", + "utf-8", "iso-8859-1", opts + ); // Result should be in the form "a???b?c??d" or "a??????b?c??d"... // Remove consecutive question marks for easier matching. @@ -180,8 +184,8 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) ); } - void testStopOnInvalidSequence() - { + void testStopOnInvalidSequence() { + vmime::charsetConverterOptions opts; opts.silentlyReplaceInvalidSequences = false; @@ -192,8 +196,8 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) ); } - void testStatus() - { + void testStatus() { + vmime::charsetConverterOptions opts; opts.silentlyReplaceInvalidSequences = false; @@ -206,23 +210,22 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) VASSERT_EQ("outputBytesWritten", 7, st.outputBytesWritten); } - void testStatusWithInvalidSequence() - { + void testStatusWithInvalidSequence() { + vmime::charsetConverterOptions opts; opts.silentlyReplaceInvalidSequences = false; vmime::charsetConverter::status st; - try - { + try { + // 01234 5 6789 0 1 convertHelper("Fran\xc3\xa7ois\xf1\x80\x65", "utf-8", "iso-8859-1", opts, &st); - } - catch (vmime::exceptions::illegal_byte_sequence_for_charset& e) - { - } - catch (...) - { + + } catch (vmime::exceptions::illegal_byte_sequence_for_charset& e) { + + } catch (...) { + throw; } @@ -230,8 +233,8 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) VASSERT_EQ("outputBytesWritten", 8, st.outputBytesWritten); } - void testIsValidText() - { + void testIsValidText() { + // Invalid text const vmime::string invalidText("Fran\xc3\xa7ois\xf1\x80\x65"); vmime::string::size_type firstInvalidByte; @@ -247,4 +250,3 @@ VMIME_TEST_SUITE_BEGIN(charsetTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/charsetTestSuites.hpp b/tests/parser/charsetTestSuites.hpp index cb10e29e..9653016b 100644 --- a/tests/parser/charsetTestSuites.hpp +++ b/tests/parser/charsetTestSuites.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -22,8 +22,8 @@ // -struct charsetTestSuiteStruct -{ +struct charsetTestSuiteStruct { + const char* fromCharset; const char* toCharset; const char* fromBytes; @@ -33,8 +33,8 @@ struct charsetTestSuiteStruct }; -static const charsetTestSuiteStruct charsetTestSuites[] = -{ +static const charsetTestSuiteStruct charsetTestSuites[] = { + // Test data 1 (excerpt from http://www.gnu.org) { "gb2312", "utf-8", @@ -97,7 +97,6 @@ static const charsetTestSuiteStruct charsetTestSuites[] = "\xe7\xbb\x9f\x20\xe3\x80\x82\x0a", 0 } - }; static const vmime::size_t charsetTestSuitesCount = sizeof(charsetTestSuites) / sizeof(charsetTestSuites[0]); diff --git a/tests/parser/datetimeTest.cpp b/tests/parser/datetimeTest.cpp index 90bbebbb..61c85221 100644 --- a/tests/parser/datetimeTest.cpp +++ b/tests/parser/datetimeTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,10 +33,9 @@ VMIME_TEST_SUITE_BEGIN(datetimeTest) VMIME_TEST_LIST_END - void testParse() - { - struct datetimePair - { + void testParse() { + + struct datetimePair { vmime::string parseBuffer; vmime::datetime result; }; @@ -45,8 +44,8 @@ VMIME_TEST_SUITE_BEGIN(datetimeTest) // so we test some cases. Don't forget to add a new test case // each time you encounter a bug in date/time parsing (after // you have fixed it). - datetimePair pairs[] = - { + datetimePair pairs[] = { + { /* 1 */ "Mon, 8 Nov 2004 13:42:56 +0000 (GMT)", vmime::datetime(2004, 11, 8, 13, 42, 56, vmime::datetime::GMT) }, @@ -66,8 +65,8 @@ VMIME_TEST_SUITE_BEGIN(datetimeTest) vmime::datetime(2004, 11, 18, 21, 44, 54, vmime::datetime::GMT3) } }; - for (unsigned int i = 0 ; i < sizeof(pairs) / sizeof(pairs[0]) ; ++i) - { + for (unsigned int i = 0 ; i < sizeof(pairs) / sizeof(pairs[0]) ; ++i) { + vmime::datetime d; d.parse(pairs[i].parseBuffer); @@ -78,15 +77,15 @@ VMIME_TEST_SUITE_BEGIN(datetimeTest) } } - void testGenerate() - { + void testGenerate() { + vmime::datetime d1(2005, 7, 8, 4, 5, 6, 1 * 60 + 23); VASSERT_EQ("1", "Fri, 8 Jul 2005 04:05:06 +0123", d1.generate()); } - void testCompare() - { + void testCompare() { + // Date1 = Date2 vmime::datetime d1(2005, 4, 22, 14, 6, 0, vmime::datetime::GMT2); vmime::datetime d2(2005, 4, 22, 10, 6, 0, vmime::datetime::GMT_2); @@ -122,4 +121,3 @@ VMIME_TEST_SUITE_BEGIN(datetimeTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/dispositionTest.cpp b/tests/parser/dispositionTest.cpp index 7b767caa..f51c51e8 100644 --- a/tests/parser/dispositionTest.cpp +++ b/tests/parser/dispositionTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,8 +33,8 @@ VMIME_TEST_SUITE_BEGIN(dispositionTest) VMIME_TEST_LIST_END - void testParse() - { + void testParse() { + // disposition-mode ";" disposition-type // [ "/" disposition-modifier *( "," disposition-modifier ) ] // @@ -84,8 +84,8 @@ VMIME_TEST_SUITE_BEGIN(dispositionTest) VASSERT_EQ("5.6", "modif2", disp5.getModifierList()[1]); } - void testGenerate() - { + void testGenerate() { + vmime::disposition disp; VASSERT_EQ("1", "automatic-action/MDN-sent-automatically;displayed", disp.generate()); @@ -112,8 +112,8 @@ VMIME_TEST_SUITE_BEGIN(dispositionTest) VASSERT_EQ("6", "amode/smode;type/modif1,modif2", disp.generate()); } - void testModifiers() - { + void testModifiers() { + vmime::disposition disp1; VASSERT_EQ("1", false, disp1.hasModifier("foo")); @@ -148,4 +148,3 @@ VMIME_TEST_SUITE_BEGIN(dispositionTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/emailAddressTest.cpp b/tests/parser/emailAddressTest.cpp index 2de401a9..f2a70705 100644 --- a/tests/parser/emailAddressTest.cpp +++ b/tests/parser/emailAddressTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -45,29 +45,26 @@ VMIME_TEST_SUITE_BEGIN(emailAddressTest) VMIME_TEST_LIST_END - void setUp() - { + void setUp() { + // 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 - { + try { std::locale::global(std::locale("")); - } - catch (std::exception &) - { + } catch (std::exception &) { std::setlocale(LC_ALL, ""); } } - void tearDown() - { + void tearDown() { + // Restore default locale std::locale::global(std::locale("C")); } - void testParseASCII() - { + void testParseASCII() { + vmime::emailAddress eml1("local@domain"); VASSERT_EQ("1/local", "local", eml1.getLocalName()); VASSERT_EQ("1/domain", "domain", eml1.getDomainName()); @@ -78,8 +75,8 @@ VMIME_TEST_SUITE_BEGIN(emailAddressTest) VASSERT_EQ("2/domain", vmime::platform::getHandler()->getHostName(), eml2.getDomainName()); } - void testParseEAI() - { + void testParseEAI() { + // Examples taken from Wikipedia (http://en.wikipedia.org/wiki/Email_address) // Latin Alphabet (with diacritics): @@ -103,8 +100,8 @@ VMIME_TEST_SUITE_BEGIN(emailAddressTest) VASSERT_EQ("4/domain", "ящик-с-апельсинами.рф", eml4.getDomainName()); } - void testParseInvalid() - { + void testParseInvalid() { + // Only one @ is allowed outside quotation marks vmime::emailAddress eml1("local@part@domain"); VASSERT_EQ("1/local", "local", eml1.getLocalName()); @@ -132,8 +129,8 @@ VMIME_TEST_SUITE_BEGIN(emailAddressTest) VASSERT_EQ("5/domain", vmime::platform::getHandler()->getHostName(), eml5.getDomainName()); } - void testParseSpecialChars() - { + void testParseSpecialChars() { + // Examples taken from Wikipedia (http://en.wikipedia.org/wiki/Email_address) vmime::emailAddress eml1("\" \"@example.org"); @@ -161,8 +158,8 @@ VMIME_TEST_SUITE_BEGIN(emailAddressTest) VASSERT_EQ("6/domain", "strange.example.com", eml6.getDomainName()); } - void testParseCommentInLocalPart() - { + void testParseCommentInLocalPart() { + vmime::emailAddress eml1("john.smith(comment)@example.com"); VASSERT_EQ("1/local", "john.smith", eml1.getLocalName()); VASSERT_EQ("1/domain", "example.com", eml1.getDomainName()); @@ -180,8 +177,8 @@ VMIME_TEST_SUITE_BEGIN(emailAddressTest) VASSERT_EQ("4/domain", "example.com", eml4.getDomainName()); } - void testParseCommentInDomainPart() - { + void testParseCommentInDomainPart() { + vmime::emailAddress eml1("john.smith@(comment)example.com"); VASSERT_EQ("1/local", "john.smith", eml1.getLocalName()); VASSERT_EQ("1/domain", "example.com", eml1.getDomainName()); @@ -199,8 +196,8 @@ VMIME_TEST_SUITE_BEGIN(emailAddressTest) VASSERT_EQ("4/domain", "example.com", eml4.getDomainName()); } - void testParseRFC2047EncodedLocalPart() - { + void testParseRFC2047EncodedLocalPart() { + vmime::emailAddress eml1("=?utf-8?Q?Pel=C3=A9?=@example.com"); VASSERT_EQ("1/local", "Pelé", eml1.getLocalName()); VASSERT_EQ("1/domain", "example.com", eml1.getDomainName()); @@ -214,47 +211,71 @@ VMIME_TEST_SUITE_BEGIN(emailAddressTest) VASSERT_EQ("3/domain", "黒川.com", eml3.getDomainName()); } - void testGenerateASCII() - { - VASSERT_EQ("email 1", "local@domain", vmime::emailAddress("local", "domain").generate()); + void testGenerateASCII() { - VASSERT_EQ("email 2", "=?utf-8?Q?Pel=C3=A9?=@example.com", - vmime::emailAddress("Pelé", "example.com").generate()); - VASSERT_EQ("email 3", "=?utf-8?B?55Sy5paQ?=@xn--5rtw95l.xn--wgv71a", - vmime::emailAddress("甲斐", "黒川.日本").generate()); - VASSERT_EQ("email 4", "mailtest@xn--r8jz45g.xn--zckzah", - vmime::emailAddress("mailtest", "例え.テスト").generate()); - VASSERT_EQ("email 5", "mailtest@xn--mgbh0fb.xn--kgbechtv", - vmime::emailAddress("mailtest", "مثال.إختبار").generate()); + VASSERT_EQ( + "email 1", "local@domain", + vmime::emailAddress("local", "domain").generate() + ); + VASSERT_EQ( + "email 2", "=?utf-8?Q?Pel=C3=A9?=@example.com", + vmime::emailAddress("Pelé", "example.com").generate() + ); + VASSERT_EQ( + "email 3", "=?utf-8?B?55Sy5paQ?=@xn--5rtw95l.xn--wgv71a", + vmime::emailAddress("甲斐", "黒川.日本").generate() + ); + VASSERT_EQ( + "email 4", "mailtest@xn--r8jz45g.xn--zckzah", + vmime::emailAddress("mailtest", "例え.テスト").generate() + ); + VASSERT_EQ( + "email 5", "mailtest@xn--mgbh0fb.xn--kgbechtv", + vmime::emailAddress("mailtest", "مثال.إختبار").generate() + ); } - void testGenerateEAI() - { + void testGenerateEAI() { + vmime::generationContext ctx(vmime::generationContext::getDefaultContext()); ctx.setInternationalizedEmailSupport(true); vmime::generationContext::switcher contextSwitcher(ctx); - VASSERT_EQ("email 1", "Pelé@example.com", - vmime::emailAddress("Pelé", "example.com").generate()); - VASSERT_EQ("email 2", "δοκιμή@παράδειγμα.δοκιμή", - vmime::emailAddress("δοκιμή", "παράδειγμα.δοκιμή").generate()); - VASSERT_EQ("email 3", "甲斐@黒川.日本", - vmime::emailAddress("甲斐", "黒川.日本").generate()); - VASSERT_EQ("email 4", "чебурашка@ящик-с-апельсинами.рф", - vmime::emailAddress("чебурашка", "ящик-с-апельсинами.рф").generate()); + VASSERT_EQ( + "email 1", "Pelé@example.com", + vmime::emailAddress("Pelé", "example.com").generate() + ); + VASSERT_EQ( + "email 2", "δοκιμή@παράδειγμα.δοκιμή", + vmime::emailAddress("δοκιμή", "παράδειγμα.δοκιμή").generate() + ); + VASSERT_EQ( + "email 3", "甲斐@黒川.日本", + vmime::emailAddress("甲斐", "黒川.日本").generate() + ); + VASSERT_EQ( + "email 4", "чебурашка@ящик-с-апельсинами.рф", + vmime::emailAddress("чебурашка", "ящик-с-апельсинами.рф").generate() + ); } - void testGenerateSpecialChars() - { - VASSERT_EQ("email 1", "\"very.unusual.@.unusual.com\"@example.com", - vmime::emailAddress("very.unusual.@.unusual.com", "example.com").generate()); + void testGenerateSpecialChars() { - VASSERT_EQ("email 2", "\"very.(),:;<>[]\\\".VERY.\\\"very@\\\\ \\\"very\\\".unusual\"@strange.example.com", - vmime::emailAddress("very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual", "strange.example.com").generate()); + VASSERT_EQ( + "email 1", "\"very.unusual.@.unusual.com\"@example.com", + vmime::emailAddress("very.unusual.@.unusual.com", "example.com").generate() + ); - VASSERT_EQ("email 3", "\" \"@example.com", - vmime::emailAddress(" ", "example.com").generate()); + VASSERT_EQ( + "email 2", "\"very.(),:;<>[]\\\".VERY.\\\"very@\\\\ \\\"very\\\".unusual\"@strange.example.com", + vmime::emailAddress("very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual", "strange.example.com").generate() + ); + + VASSERT_EQ( + "email 3", "\" \"@example.com", + vmime::emailAddress(" ", "example.com").generate() + ); } VMIME_TEST_SUITE_END diff --git a/tests/parser/emptyContentHandlerTest.cpp b/tests/parser/emptyContentHandlerTest.cpp index 81e2ed6b..43cd8c2b 100644 --- a/tests/parser/emptyContentHandlerTest.cpp +++ b/tests/parser/emptyContentHandlerTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,30 +38,30 @@ VMIME_TEST_SUITE_BEGIN(emptyContentHandlerTest) VMIME_TEST_LIST_END - void testIsEmpty() - { + void testIsEmpty() { + vmime::emptyContentHandler cth; VASSERT_TRUE("empty", cth.isEmpty()); } - void testGetLength() - { + void testGetLength() { + vmime::emptyContentHandler cth; VASSERT_EQ("length", 0, cth.getLength()); } - void testIsEncoded() - { + void testIsEncoded() { + vmime::emptyContentHandler cth; VASSERT_FALSE("encoded", cth.isEncoded()); VASSERT_EQ("encoding", vmime::contentHandler::NO_ENCODING, cth.getEncoding()); } - void testExtract() - { + void testExtract() { + vmime::emptyContentHandler cth; std::ostringstream oss; @@ -72,8 +72,8 @@ VMIME_TEST_SUITE_BEGIN(emptyContentHandlerTest) VASSERT_EQ("extract", "", oss.str()); } - void testExtractRaw() - { + void testExtractRaw() { + vmime::emptyContentHandler cth; std::ostringstream oss; @@ -84,8 +84,8 @@ VMIME_TEST_SUITE_BEGIN(emptyContentHandlerTest) VASSERT_EQ("extractRaw", "", oss.str()); } - void testGenerate() - { + void testGenerate() { + vmime::emptyContentHandler cth; std::ostringstream oss; diff --git a/tests/parser/fileContentHandlerTest.cpp b/tests/parser/fileContentHandlerTest.cpp index 9d1459db..e979b52f 100644 --- a/tests/parser/fileContentHandlerTest.cpp +++ b/tests/parser/fileContentHandlerTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,8 +42,8 @@ VMIME_TEST_SUITE_BEGIN(fileContentHandlerTest) vmime::string testDataEncoded, testDataDecoded; - void setUp() - { + void setUp() { + testDataDecoded = "ABCDEFGHIJKLMNOPQRSTUVWXYZ \x12\x34\x56\x78\x90 abcdefghijklmnopqrstuvwxyz0123456789"; testDataEncoded = "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVogEjRWeJAgYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5"; @@ -58,38 +58,38 @@ VMIME_TEST_SUITE_BEGIN(fileContentHandlerTest) testFile->getFileWriter()->getOutputStream()->write(testDataEncoded.data(), testDataEncoded.length()); } - void tearDown() - { + void tearDown() { + testFile->remove(); testFile = vmime::null; } - void testIsEmpty() - { + void testIsEmpty() { + vmime::fileContentHandler cth; VASSERT_TRUE("empty", cth.isEmpty()); } - void testGetLength() - { + void testGetLength() { + vmime::fileContentHandler cth(testFile); VASSERT_FALSE("empty", cth.isEmpty()); VASSERT_EQ("length", testDataEncoded.length(), cth.getLength()); } - void testIsEncoded() - { + void testIsEncoded() { + vmime::fileContentHandler cth(testFile, vmime::encoding("base64")); VASSERT_TRUE("encoded", cth.isEncoded()); VASSERT_EQ("encoding", "base64", cth.getEncoding().generate()); } - void testExtract() - { + void testExtract() { + vmime::fileContentHandler cth(testFile, vmime::encoding("base64")); std::ostringstream oss; @@ -101,8 +101,8 @@ VMIME_TEST_SUITE_BEGIN(fileContentHandlerTest) VASSERT_EQ("extract", testDataDecoded, oss.str()); } - void testExtractRaw() - { + void testExtractRaw() { + vmime::fileContentHandler cth(testFile, vmime::encoding("base64")); std::ostringstream oss; @@ -114,8 +114,8 @@ VMIME_TEST_SUITE_BEGIN(fileContentHandlerTest) VASSERT_EQ("extractRaw", testDataEncoded, oss.str()); } - void testGenerate() - { + void testGenerate() { + vmime::fileContentHandler cth(testFile, vmime::encoding("base64")); std::ostringstream oss; @@ -124,8 +124,11 @@ VMIME_TEST_SUITE_BEGIN(fileContentHandlerTest) cth.generate(osa, vmime::encoding("quoted-printable")); // Data should be reencoded from B64 to QP - VASSERT_EQ("generate", - "ABCDEFGHIJKLMNOPQRSTUVWXYZ =124Vx=90 abcdefghijklmnopqrstuvwxyz0123456789", oss.str()); + VASSERT_EQ( + "generate", + "ABCDEFGHIJKLMNOPQRSTUVWXYZ =124Vx=90 abcdefghijklmnopqrstuvwxyz0123456789", + oss.str() + ); } VMIME_TEST_SUITE_END diff --git a/tests/parser/headerFieldTest.cpp b/tests/parser/headerFieldTest.cpp index 0642dae7..78d04800 100644 --- a/tests/parser/headerFieldTest.cpp +++ b/tests/parser/headerFieldTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,27 +34,35 @@ VMIME_TEST_SUITE_BEGIN(headerFieldTest) VMIME_TEST_LIST_END - void testBadValueType() - { + void testBadValueType() { + vmime::shared_ptr hfactory = vmime::headerFieldFactory::getInstance(); // "To" header field accepts values of type "addressList" vmime::shared_ptr to = hfactory->create(vmime::fields::TO); - VASSERT_THROW("to", + + VASSERT_THROW( + "to", to->setValue(vmime::mailbox("email@vmime.org")), - vmime::exceptions::bad_field_value_type); + vmime::exceptions::bad_field_value_type + ); // Unregistered header field accepts any value type vmime::shared_ptr custom = hfactory->create("X-MyCustomHeader"); - VASSERT_NO_THROW("custom/1", - custom->setValue(vmime::mailbox("email@vmime.org"))); - VASSERT_NO_THROW("custom/2", - custom->setValue(vmime::text("field value text"))); + + VASSERT_NO_THROW( + "custom/1", + custom->setValue(vmime::mailbox("email@vmime.org")) + ); + VASSERT_NO_THROW( + "custom/2", + custom->setValue(vmime::text("field value text")) + ); } - void testValueOnNextLine() - { + void testValueOnNextLine() { + vmime::parsingContext ctx; const vmime::string buffer = "Field: \r\n\tfield data"; @@ -69,8 +77,8 @@ VMIME_TEST_SUITE_BEGIN(headerFieldTest) VASSERT_EQ("Field value", "field data", hvalue->getWholeBuffer()); } - void testStripSpacesAtEnd() - { + void testStripSpacesAtEnd() { + vmime::parsingContext ctx; const vmime::string buffer = "Field: \r\n\tfield data "; @@ -85,8 +93,8 @@ VMIME_TEST_SUITE_BEGIN(headerFieldTest) VASSERT_EQ("Field value", toHex("field data"), toHex(hvalue->getWholeBuffer())); } - void testValueWithEmptyLine() - { + void testValueWithEmptyLine() { + vmime::parsingContext ctx; const vmime::string buffer = "Field: \r\n\tdata1\r\n\tdata2\r\n\t\r\n\tdata3"; diff --git a/tests/parser/headerTest.cpp b/tests/parser/headerTest.cpp index 959fc631..839acee5 100644 --- a/tests/parser/headerTest.cpp +++ b/tests/parser/headerTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -64,18 +64,18 @@ VMIME_TEST_SUITE_BEGIN(headerTest) VMIME_TEST_LIST_END - static const std::string getFieldValue(const vmime::headerField& field) - { + static const std::string getFieldValue(const vmime::headerField& field) { + std::ostringstream oss; vmime::utility::outputStreamAdapter voss(oss); field.generate(voss); - return (oss.str()); + return oss.str(); } // has function tests - void testHas1() - { + void testHas1() { + vmime::header hdr; hdr.parse("From: x\r\nTo: y\r\nTo: z\r\n"); @@ -84,8 +84,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) VASSERT_EQ("Value", false, res); } - void testHas2() - { + void testHas2() { + vmime::header hdr; hdr.parse("X: x\r\nTo: y\r\nTo: z\r\n"); @@ -95,8 +95,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } // appendField function tests - void testAppend1() - { + void testAppend1() { + vmime::header hdr; hdr.parse(""); @@ -109,8 +109,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) VASSERT_EQ("First value", "A: a", headerTest::getFieldValue(*res[0])); } - void testAppend2() - { + void testAppend2() { + vmime::header hdr; hdr.parse("A: a\r\n"); @@ -125,8 +125,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } // insertFieldBefore - void testInsertFieldBefore1() - { + void testInsertFieldBefore1() { + vmime::header hdr; hdr.parse("A: a\r\nC: c\r\n"); @@ -141,8 +141,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) VASSERT_EQ("Third value", "C: c", headerTest::getFieldValue(*res[2])); } - void testInsertFieldBefore2() - { + void testInsertFieldBefore2() { + vmime::header hdr; hdr.parse("A: a\r\nC: c\r\n"); @@ -158,8 +158,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } // insertFieldAfter - void testInsertFieldAfter1() - { + void testInsertFieldAfter1() { + vmime::header hdr; hdr.parse("A: a\r\nC: c\r\n"); @@ -174,8 +174,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) VASSERT_EQ("Third value", "C: c", headerTest::getFieldValue(*res[2])); } - void testInsertFieldAfter2() - { + void testInsertFieldAfter2() { + vmime::header hdr; hdr.parse("A: a\r\nC: c\r\n"); @@ -191,8 +191,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } // replaceField - void testReplaceField() - { + void testReplaceField() { + vmime::header hdr; hdr.parse("A: a\r\nB: b\r\nC: c\r\n"); @@ -208,8 +208,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } // removeField - void testRemoveField1() - { + void testRemoveField1() { + vmime::header hdr1, hdr2; hdr1.parse("A: a\r\nB: b\r\nC: c\r\n"); hdr2.parse("A: a\r\nB: b\r\nC: c\r\n"); @@ -230,8 +230,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) VASSERT_EQ("Second value", "C: c", headerTest::getFieldValue(*res2[1])); } - void testRemoveField2() - { + void testRemoveField2() { + vmime::header hdr1, hdr2; hdr1.parse("A: a\r\n"); hdr2.parse("A: a\r\n"); @@ -247,8 +247,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } // removeAllFields - void testRemoveAllFields() - { + void testRemoveAllFields() { + vmime::header hdr1, hdr2; hdr1.parse("A: a\r\n"); hdr2.parse("A: a\r\nB: b\r\n"); @@ -264,8 +264,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } // getFieldCount - void testgetFieldCount() - { + void testgetFieldCount() { + vmime::header hdr; hdr.parse("A: a\r\nB: b\r\nC: c\r\nD: d\r\n"); @@ -273,16 +273,16 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } // isEmpty - void testIsEmpty1() - { + void testIsEmpty1() { + vmime::header hdr; hdr.parse("A: a\r\nB: b\r\nC: c\r\n"); VASSERT_EQ("Value", false, hdr.isEmpty()); } - void testIsEmpty2() - { + void testIsEmpty2() { + vmime::header hdr; hdr.parse("\r\n"); @@ -290,8 +290,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } // getFieldAt - void testGetFieldAt() - { + void testGetFieldAt() { + vmime::header hdr; hdr.parse("B: b\r\nA: a\r\nC: c\r\n"); @@ -301,8 +301,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } // getFieldList - void testGetFieldList1() - { + void testGetFieldList1() { + vmime::header hdr; hdr.parse("A: a\r\nB: b1\r\nC: c\r\nB: b2\r\n"); @@ -315,8 +315,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) VASSERT_EQ("Thourth value", "B: b2", headerTest::getFieldValue(*res[3])); } - void testGetFieldList2() - { + void testGetFieldList2() { + vmime::header hdr; hdr.parse("\r\n"); @@ -326,8 +326,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } // find function tests - void testFind1() - { + void testFind1() { + vmime::header hdr; hdr.parse("A: a\r\nB: b\r\nC: c\r\nB: d\r\n"); @@ -337,8 +337,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } // getAllByName function tests - void testFindAllFields1() - { + void testFindAllFields1() { + vmime::header hdr; hdr.parse("A: a1\nC: c1\n"); @@ -347,8 +347,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) VASSERT_EQ("Count", static_cast (0), res.size()); } - void testFindAllFields2() - { + void testFindAllFields2() { + vmime::header hdr; hdr.parse("A: a1\nB: b1\nB: b2\nC: c1\n"); @@ -359,8 +359,8 @@ VMIME_TEST_SUITE_BEGIN(headerTest) VASSERT_EQ("Second value", "B: b2", headerTest::getFieldValue(*res[1])); } - void testFindAllFields3() - { + void testFindAllFields3() { + vmime::header hdr; hdr.parse("A: a1\nB: b1\nB: b2\nC: c1\nC: c3\nC: c2\n"); @@ -373,4 +373,3 @@ VMIME_TEST_SUITE_BEGIN(headerTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/htmlTextPartTest.cpp b/tests/parser/htmlTextPartTest.cpp index 9eef5e84..6dfaaa0b 100644 --- a/tests/parser/htmlTextPartTest.cpp +++ b/tests/parser/htmlTextPartTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,9 +34,10 @@ VMIME_TEST_SUITE_BEGIN(htmlTextPartTest) VMIME_TEST_LIST_END - static const vmime::string extractContent - (const vmime::shared_ptr & cth) - { + static const vmime::string extractContent( + const vmime::shared_ptr & cth + ) { + std::ostringstream oss; vmime::utility::outputStreamAdapter osa(oss); @@ -46,8 +47,8 @@ VMIME_TEST_SUITE_BEGIN(htmlTextPartTest) } - void testParseText() - { + void testParseText() { + const vmime::string msgString = "" "MIME-Version: 1.0\r\n" "Content-Type: multipart/alternative; boundary=\"LEVEL1\"\r\n" @@ -94,8 +95,8 @@ VMIME_TEST_SUITE_BEGIN(htmlTextPartTest) /** Test parsing of embedded objects by CID (Content-Id). */ - void testParseEmbeddedObjectsCID() - { + void testParseEmbeddedObjectsCID() { + const vmime::string msgString = "" "MIME-Version: 1.0\r\n" "Content-Type: multipart/alternative; boundary=\"LEVEL1\"\r\n" @@ -137,8 +138,10 @@ VMIME_TEST_SUITE_BEGIN(htmlTextPartTest) VASSERT_EQ("part-count2", 3, msg->getBody()->getPartAt(1)->getBody()->getPartCount()); vmime::htmlTextPart htmlPart; - htmlPart.parse(msg, msg->getBody()->getPartAt(1), - msg->getBody()->getPartAt(1)->getBody()->getPartAt(1)); + htmlPart.parse( + msg, msg->getBody()->getPartAt(1), + msg->getBody()->getPartAt(1)->getBody()->getPartAt(1) + ); // Two embedded objects should be found. // BUGFIX: "CID:" prefix is not case-sensitive. @@ -172,8 +175,8 @@ VMIME_TEST_SUITE_BEGIN(htmlTextPartTest) /** Test parsing of embedded objects by location. */ - void testParseEmbeddedObjectsLocation() - { + void testParseEmbeddedObjectsLocation() { + const vmime::string msgString = "" "MIME-Version: 1.0\r\n" "Content-Type: multipart/alternative; boundary=\"LEVEL1\"\r\n" @@ -209,8 +212,10 @@ VMIME_TEST_SUITE_BEGIN(htmlTextPartTest) VASSERT_EQ("part-count2", 2, msg->getBody()->getPartAt(1)->getBody()->getPartCount()); vmime::htmlTextPart htmlPart; - htmlPart.parse(msg, msg->getBody()->getPartAt(1), - msg->getBody()->getPartAt(1)->getBody()->getPartAt(1)); + htmlPart.parse( + msg, msg->getBody()->getPartAt(1), + msg->getBody()->getPartAt(1)->getBody()->getPartAt(1) + ); // Only one embedded object VASSERT_EQ("count", 1, htmlPart.getObjectCount()); @@ -234,4 +239,3 @@ VMIME_TEST_SUITE_BEGIN(htmlTextPartTest) // TODO: test generation of text parts VMIME_TEST_SUITE_END - diff --git a/tests/parser/mailboxGroupTest.cpp b/tests/parser/mailboxGroupTest.cpp index 6c1319da..11a7f08f 100644 --- a/tests/parser/mailboxGroupTest.cpp +++ b/tests/parser/mailboxGroupTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,8 +34,8 @@ VMIME_TEST_SUITE_BEGIN(mailboxGroupTest) VMIME_TEST_LIST_END - void testParseExtraWhitespaces() - { + void testParseExtraWhitespaces() { + vmime::mailboxGroup mgrp; mgrp.parse(" \t group : aaa , bbb "); @@ -49,8 +49,8 @@ VMIME_TEST_SUITE_BEGIN(mailboxGroupTest) VASSERT_EQ("mbox2.name", "bbb", mgrp.getMailboxAt(1)->getName()); } - void testParseNoEndDelimiter() - { + void testParseNoEndDelimiter() { + vmime::addressList addrs; addrs.parse("group: aaa , bbb "); @@ -70,8 +70,8 @@ VMIME_TEST_SUITE_BEGIN(mailboxGroupTest) VASSERT_EQ("mbox2.name", "bbb", mgrp->getMailboxAt(1)->getName()); } - void testParseExtraChars() - { + void testParseExtraChars() { + vmime::mailboxGroup mgrp; mgrp.parse("group: aaa , bbb ; extra chars here..."); @@ -85,8 +85,8 @@ VMIME_TEST_SUITE_BEGIN(mailboxGroupTest) VASSERT_EQ("mbox2.name", "bbb", mgrp.getMailboxAt(1)->getName()); } - void testEmptyGroup() - { + void testEmptyGroup() { + vmime::mailboxGroup mgrp; mgrp.parse("Undisclosed recipients:;"); diff --git a/tests/parser/mailboxListTest.cpp b/tests/parser/mailboxListTest.cpp index c921069e..7505acd9 100644 --- a/tests/parser/mailboxListTest.cpp +++ b/tests/parser/mailboxListTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,8 +32,8 @@ VMIME_TEST_SUITE_BEGIN(mailboxListTest) // Disposition-Notification-To:: - void testParseGroup() - { + void testParseGroup() { + // Groups should be extracted to multiple mailboxes in mailbox lists vmime::mailboxList mboxList; mboxList.parse("email1@domain1.com, : , email3@domain3.com"); @@ -45,4 +45,3 @@ VMIME_TEST_SUITE_BEGIN(mailboxListTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/mailboxTest.cpp b/tests/parser/mailboxTest.cpp index 92fcd98f..127bb422 100644 --- a/tests/parser/mailboxTest.cpp +++ b/tests/parser/mailboxTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -34,10 +34,10 @@ VMIME_TEST_SUITE_BEGIN(mailboxTest) VMIME_TEST_LIST_END - void testParse() - { - static const vmime::string testSuitesParse[] = - { + void testParse() { + + static const vmime::string testSuitesParse[] = { + // Test 1 "My (this is a comment)name ", @@ -94,8 +94,8 @@ VMIME_TEST_SUITE_BEGIN(mailboxTest) "[address-list: [[mailbox: name=[text: [[word: charset=us-ascii, buffer=John]]], email=john.doe@acme.com]]]" }; - for (unsigned int i = 0 ; i < sizeof(testSuitesParse) / sizeof(testSuitesParse[0]) / 2 ; ++i) - { + for (unsigned int i = 0 ; i < sizeof(testSuitesParse) / sizeof(testSuitesParse[0]) / 2 ; ++i) { + vmime::string in = testSuitesParse[i * 2]; vmime::string out = testSuitesParse[i * 2 + 1]; @@ -112,8 +112,8 @@ VMIME_TEST_SUITE_BEGIN(mailboxTest) } } - void testEmptyEmailAddress() - { + void testEmptyEmailAddress() { + vmime::addressList addrList; addrList.parse("\"Full Name\" <>"); @@ -127,8 +127,8 @@ VMIME_TEST_SUITE_BEGIN(mailboxTest) VASSERT_EQ("email", "", mbox->getEmail()); } - void testSeparatorInComment() - { + void testSeparatorInComment() { + vmime::addressList addrList; addrList.parse("aaa(comment,comment)@vmime.org, bbb@vmime.org"); @@ -146,8 +146,8 @@ VMIME_TEST_SUITE_BEGIN(mailboxTest) VASSERT_EQ("email2", "bbb@vmime.org", mbox2->getEmail()); } - void testAddressInName() - { + void testAddressInName() { + vmime::mailbox mbox; mbox.parse("a@b.c "); @@ -156,4 +156,3 @@ VMIME_TEST_SUITE_BEGIN(mailboxTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/mediaTypeTest.cpp b/tests/parser/mediaTypeTest.cpp index 4002b714..e98cfcda 100644 --- a/tests/parser/mediaTypeTest.cpp +++ b/tests/parser/mediaTypeTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,8 +35,8 @@ VMIME_TEST_SUITE_BEGIN(mediaTypeTest) VMIME_TEST_LIST_END - void testConstructors() - { + void testConstructors() { + vmime::mediaType t1; VASSERT_EQ("1.1", vmime::mediaTypes::APPLICATION, t1.getType()); @@ -53,8 +53,8 @@ VMIME_TEST_SUITE_BEGIN(mediaTypeTest) VASSERT_EQ("3.2", "sub", t3.getSubType()); } - void testCopy() - { + void testCopy() { + vmime::mediaType t1("type/sub"); VASSERT_EQ("eq1", "type", t1.getType()); @@ -72,8 +72,8 @@ VMIME_TEST_SUITE_BEGIN(mediaTypeTest) VASSERT("copyFrom", t1 == t2); } - void testSetFromString() - { + void testSetFromString() { + vmime::mediaType t1; t1.setFromString("type/sub"); @@ -81,8 +81,8 @@ VMIME_TEST_SUITE_BEGIN(mediaTypeTest) VASSERT_EQ("1.2", "sub", t1.getSubType()); } - void testParse() - { + void testParse() { + vmime::mediaType t1; t1.parse("type/sub"); @@ -90,12 +90,11 @@ VMIME_TEST_SUITE_BEGIN(mediaTypeTest) VASSERT_EQ("1.2", "sub", t1.getSubType()); } - void testGenerate() - { + void testGenerate() { + vmime::mediaType t1("type", "sub"); VASSERT_EQ("1", "type/sub", t1.generate()); } VMIME_TEST_SUITE_END - diff --git a/tests/parser/messageIdSequenceTest.cpp b/tests/parser/messageIdSequenceTest.cpp index bc5c7617..0237108d 100644 --- a/tests/parser/messageIdSequenceTest.cpp +++ b/tests/parser/messageIdSequenceTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -32,8 +32,8 @@ VMIME_TEST_SUITE_BEGIN(messageIdSequenceTest) VMIME_TEST_LIST_END - void testParse() - { + void testParse() { + vmime::messageIdSequence s1; s1.parse(""); @@ -61,8 +61,8 @@ VMIME_TEST_SUITE_BEGIN(messageIdSequenceTest) VASSERT_EQ("4.5", "d", s4.getMessageIdAt(1)->getRight()); } - void testGenerate() - { + void testGenerate() { + vmime::messageIdSequence s1; s1.appendMessageId(vmime::make_shared ("a", "b")); @@ -76,4 +76,3 @@ VMIME_TEST_SUITE_BEGIN(messageIdSequenceTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/messageIdTest.cpp b/tests/parser/messageIdTest.cpp index 9863ae51..84330939 100644 --- a/tests/parser/messageIdTest.cpp +++ b/tests/parser/messageIdTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,8 +33,8 @@ VMIME_TEST_SUITE_BEGIN(messageIdTest) VMIME_TEST_LIST_END - void testParse() - { + void testParse() { + vmime::messageId m1; m1.parse(""); @@ -42,8 +42,8 @@ VMIME_TEST_SUITE_BEGIN(messageIdTest) VASSERT_EQ("1.2", "b", m1.getRight()); } - void testParseInvalid() - { + void testParseInvalid() { + vmime::messageId m1; m1.parse("foo@bar"); @@ -51,8 +51,8 @@ VMIME_TEST_SUITE_BEGIN(messageIdTest) VASSERT_EQ("1.2", "bar", m1.getRight()); } - void testGenerate() - { + void testGenerate() { + vmime::messageId m1; VASSERT_EQ("1", "<>", m1.generate()); @@ -75,4 +75,3 @@ VMIME_TEST_SUITE_BEGIN(messageIdTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/messageTest.cpp b/tests/parser/messageTest.cpp index 3891b47e..b89d63e5 100644 --- a/tests/parser/messageTest.cpp +++ b/tests/parser/messageTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -31,16 +31,24 @@ VMIME_TEST_SUITE_BEGIN(messageTest) VMIME_TEST_LIST_END - void testGetGeneratedSize() - { + void testGetGeneratedSize() { + vmime::generationContext ctx; vmime::shared_ptr msg = vmime::make_shared (); msg->getHeader()->getField("Foo")->setValue(vmime::string("bar")); vmime::htmlTextPart textPart; - textPart.setPlainText(vmime::make_shared ("Foo bar bazé foo foo foo")); - textPart.setText(vmime::make_shared ("Foo bar bazé foo foo foo")); + textPart.setPlainText( + vmime::make_shared ( + "Foo bar bazé foo foo foo" + ) + ); + textPart.setText( + vmime::make_shared ( + "Foo bar bazé foo foo foo" + ) + ); textPart.generateIn(msg, msg); // Estimated/computed generated size must be greater than the actual generated size @@ -54,4 +62,3 @@ VMIME_TEST_SUITE_BEGIN(messageTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/parameterTest.cpp b/tests/parser/parameterTest.cpp index 0cf2099f..464c3059 100644 --- a/tests/parser/parameterTest.cpp +++ b/tests/parser/parameterTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -45,12 +45,12 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) // HACK: parameterizedHeaderField constructor is private - class parameterizedHeaderField : public vmime::parameterizedHeaderField - { + class parameterizedHeaderField : public vmime::parameterizedHeaderField { + public: - parameterizedHeaderField() - { + parameterizedHeaderField() { + setName("F"); setValue(vmime::headerFieldFactory::getInstance()->createValue(getName())); setValue(vmime::word("X")); @@ -58,15 +58,17 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) using vmime::parameterizedHeaderField::generate; - const vmime::string generate - (const vmime::generationContext::EncodedParameterValueModes genMode, - const vmime::size_t maxLineLength = 0) const - { + const vmime::string generate( + const vmime::generationContext::EncodedParameterValueModes genMode, + const vmime::size_t maxLineLength = 0 + ) const { + vmime::generationContext ctx(vmime::generationContext::getDefaultContext()); ctx.setEncodedParameterValueMode(genMode); - if (maxLineLength != 0) + if (maxLineLength != 0) { ctx.setMaxLineLength(maxLineLength); + } std::ostringstream oss; vmime::utility::outputStreamAdapter adapter(oss); @@ -78,15 +80,17 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) }; - const vmime::string generateParameter - (const vmime::parameter& param, - const vmime::generationContext& ctx, - const vmime::size_t maxLineLength = 0) const - { + const vmime::string generateParameter( + const vmime::parameter& param, + const vmime::generationContext& ctx, + const vmime::size_t maxLineLength = 0 + ) const { + vmime::generationContext ctx2(ctx); - if (maxLineLength != 0) + if (maxLineLength != 0) { ctx2.setMaxLineLength(maxLineLength); + } std::ostringstream oss; vmime::utility::outputStreamAdapter adapter(oss); @@ -108,29 +112,26 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) (p.getParameterAt(n)->getValue().getBuffer()) - void setUp() - { + void setUp() { + // 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 - { + try { std::locale::global(std::locale("")); - } - catch (std::exception &) - { + } catch (std::exception &) { std::setlocale(LC_ALL, ""); } } - void tearDown() - { + void tearDown() { + // Restore default locale std::locale::global(std::locale("C")); } - void testParse() - { + void testParse() { + // Simple parameter parameterizedHeaderField p1; p1.parse("X; param1=value1;\r\n"); @@ -141,9 +142,11 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) // Multi-section parameters (1/2) parameterizedHeaderField p2a; - p2a.parse("X; param1=value1;\r\n" - " param2*0=\"val\";\r\n" - " param2*1=\"ue2\";"); + p2a.parse( + "X; param1=value1;\r\n" + " param2*0=\"val\";\r\n" + " param2*1=\"ue2\";" + ); VASSERT_EQ("2a.1", 2, p2a.getParameterCount()); VASSERT_EQ("2a.2", "param1", PARAM_NAME(p2a, 0)); @@ -153,10 +156,12 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) // Multi-section parameters (2/2) parameterizedHeaderField p2b; - p2b.parse("X; param1=value1;\r\n" - " param2=\"should be ignored\";\r\n" - " param2*0=\"val\";\r\n" - " param2*1=\"ue2\";"); + p2b.parse( + "X; param1=value1;\r\n" + " param2=\"should be ignored\";\r\n" + " param2*0=\"val\";\r\n" + " param2*1=\"ue2\";" + ); VASSERT_EQ("2b.1", 2, p2b.getParameterCount()); VASSERT_EQ("2b.2", "param1", PARAM_NAME(p2b, 0)); @@ -206,13 +211,15 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) VASSERT_EQ("7.3", "this is a slash: \"\\\"", PARAM_VALUE(p7, 0)); } - void testParseRFC2231() - { + void testParseRFC2231() { + // Extended parameter with charset specified in more than one // section (this is forbidden by RFC, but is should not fail) parameterizedHeaderField p1; - p1.parse("X; param1*0*=charset1'language1'value1;\r\n" - " param1*1*=charset2'language2'value2;"); + p1.parse( + "X; param1*0*=charset1'language1'value1;\r\n" + " param1*1*=charset2'language2'value2;" + ); VASSERT_EQ("1.1", 1, p1.getParameterCount()); VASSERT_EQ("1.2", "param1", PARAM_NAME(p1, 0)); @@ -222,8 +229,10 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) // Charset not specified in the first section (that is not encoded), // but specified in the second one (legal) parameterizedHeaderField p2; - p2.parse("X; param1*0=value1;\r\n" - " param1*1*=charset'language'value2;"); + p2.parse( + "X; param1*0=value1;\r\n" + " param1*1*=charset'language'value2;" + ); VASSERT_EQ("2.1", 1, p2.getParameterCount()); VASSERT_EQ("2.2", "param1", PARAM_NAME(p2, 0)); @@ -241,9 +250,11 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) // Multiple sections + charset specified and encoding parameterizedHeaderField p4; - p4.parse("X; param1*0*=charset'language'value1a%20;" - " param1*1*=value1b%20;" - " param1*2=value1c"); + p4.parse( + "X; param1*0*=charset'language'value1a%20;" + " param1*1*=value1b%20;" + " param1*2=value1c" + ); VASSERT_EQ("4.1", 1, p4.getParameterCount()); VASSERT_EQ("4.2", "param1", PARAM_NAME(p4, 0)); @@ -270,8 +281,8 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) VASSERT_EQ("6.5", "This is ***fun***", PARAM_BUFFER(p6, 0)); } - void testGenerate() - { + void testGenerate() { + // Simple parameter/value parameterizedHeaderField p1; p1.appendParameter(vmime::make_shared ("param1", "value1")); @@ -291,8 +302,8 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) VASSERT_EQ("2b", "F: X; param1=\"va\\\\lue\\\"1\"", p2b.generate()); } - void testGetGeneratedSize() - { + void testGetGeneratedSize() { + vmime::generationContext ctx(vmime::generationContext::getDefaultContext()); vmime::parameter p1("param1", "value1"); @@ -305,40 +316,70 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) VASSERT("1", p2b.getGeneratedSize(ctx) >= generateParameter(p2b, ctx).length()); } - void testGenerateRFC2231() - { + void testGenerateRFC2231() { + // Extended parameter with charset specifier parameterizedHeaderField p1; - p1.appendParameter(vmime::make_shared ("param1", - vmime::word("value 1\xe9", vmime::charset("charset")))); + p1.appendParameter( + vmime::make_shared ( + "param1", + vmime::word("value 1\xe9", vmime::charset("charset")) + ) + ); - VASSERT_EQ("1.no-encoding", "F: X; param1=\"value 1\"", - p1.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING)); + VASSERT_EQ( + "1.no-encoding", + "F: X; param1=\"value 1\"", + p1.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING) + ); - VASSERT_EQ("1.rfc2047", "F: X; param1=\"=?charset?Q?value_1=E9?=\"", - p1.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY)); + VASSERT_EQ( + "1.rfc2047", + "F: X; param1=\"=?charset?Q?value_1=E9?=\"", + p1.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY) + ); - VASSERT_EQ("1.rfc2231", "F: X; param1*=charset''value%201%E9", - p1.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY)); + VASSERT_EQ( + "1.rfc2231", + "F: X; param1*=charset''value%201%E9", + p1.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY) + ); - VASSERT_EQ("1.both", "F: X; param1=\"=?charset?Q?value_1=E9?=\";param1*=charset''value%201%E9", - p1.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047)); + VASSERT_EQ( + "1.both", + "F: X; param1=\"=?charset?Q?value_1=E9?=\";param1*=charset''value%201%E9", + p1.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047) + ); // Value that spans on multiple lines parameterizedHeaderField p2; - p2.appendParameter(vmime::make_shared ("param1", - vmime::word("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", - vmime::charset("charset")))); + p2.appendParameter( + vmime::make_shared ( + "param1", + vmime::word( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + vmime::charset("charset") + ) + ) + ); - VASSERT_EQ("2.no-encoding", "F: X; \r\n " + VASSERT_EQ( + "2.no-encoding", + "F: X; \r\n " "param1=abcdefghijkl", - p2.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING, 25)); // max line length = 25 + p2.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING, 25) // max line length = 25 + ); - VASSERT_EQ("2.rfc2047", "F: X; \r\n " + VASSERT_EQ( + "2.rfc2047", + "F: X; \r\n " "param1=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", - p2.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY, 25)); // max line length = 25 + p2.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY, 25) // max line length = 25 + ); - VASSERT_EQ("2.rfc2231", "F: X; \r\n " + VASSERT_EQ( + "2.rfc2231", + "F: X; \r\n " "param1*0*=charset''abc;\r\n " "param1*1*=defghijkl;\r\n " "param1*2*=mnopqrstu;\r\n " @@ -346,9 +387,12 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) "param1*4*=EFGHIJKLM;\r\n " "param1*5*=NOPQRSTUV;\r\n " "param1*6*=WXYZ", - p2.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY, 25)); // max line length = 25 + p2.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY, 25) // max line length = 25 + ); - VASSERT_EQ("2.both", "F: X; \r\n " + VASSERT_EQ( + "2.both", + "F: X; \r\n " "param1=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;\r\n " "param1*0*=charset''abc;\r\n " "param1*1*=defghijkl;\r\n " @@ -357,26 +401,41 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) "param1*4*=EFGHIJKLM;\r\n " "param1*5*=NOPQRSTUV;\r\n " "param1*6*=WXYZ", - p2.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047, 25)); // max line length = 25 + p2.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047, 25) // max line length = 25 + ); // Non-ASCII parameter value parameterizedHeaderField p3; - p3.appendParameter(vmime::make_shared ("param1", - vmime::word("δσσσσσσσσσσσσσσσσσσσσδσδα δσαδσδσαδσαδασδασ δσαδασδσα δσαδασδσα δασδασδασ δασαχφδδσα 2008.doc", - vmime::charset("utf-8")))); + p3.appendParameter( + vmime::make_shared ( + "param1", + vmime::word( + "δσσσσσσσσσσσσσσσσσσσσδσδα δσαδσδσαδσαδασδασ δσαδασδσα δσαδασδσα δασδασδασ δασαχφδδσα 2008.doc", + vmime::charset("utf-8") + ) + ) + ); - VASSERT_EQ("3.no-encoding", "F: X; \r\n " + VASSERT_EQ( + "3.no-encoding", + "F: X; \r\n " "param1=\" 2008.doc\"", - p3.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING, 80)); // max line length = 80 + p3.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING, 80) // max line length = 80 + ); - VASSERT_EQ("3.7bit-only", "F: X; \r\n " + VASSERT_EQ( + "3.7bit-only", + "F: X; \r\n " "param1=\"=?utf-8?B?zrTPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+DzrTPg860?=\r\n " "=?utf-8?B?zrEgzrTPg86xzrTPg860z4POsc60z4POsc60zrHPg860zrHPgyDOtM+DzrHOtM6x?=\r\n " "=?utf-8?B?z4POtM+DzrEgzrTPg86xzrTOsc+DzrTPg86xIM60zrHPg860zrHPg860zrHPgyDOtA==?=\r\n " "=?utf-8?B?zrHPg86xz4fPhs60zrTPg86xIDIwMDguZG9j?=\"", - p3.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY, 80)); // max line length = 80 + p3.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY, 80) // max line length = 80 + ); - VASSERT_EQ("3.both", "F: X; \r\n " + VASSERT_EQ( + "3.both", + "F: X; \r\n " "param1=\"=?utf-8?B?zrTPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+Dz4PPg8+DzrTPg860?=\r\n " "=?utf-8?B?zrEgzrTPg86xzrTPg860z4POsc60z4POsc60zrHPg860zrHPgyDOtM+DzrHOtM6x?=\r\n " "=?utf-8?B?z4POtM+DzrEgzrTPg86xzrTOsc+DzrTPg86xIM60zrHPg860zrHPg860zrHPgyDOtA==?=\r\n " @@ -389,9 +448,12 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) "param1*5*=%83%CE%B1%CE%B4%CE%B1%CF%83%CE%B4%CF%83%CE%B1%20%CE%B4%CE%B1%CF%83;\r\n " "param1*6*=%CE%B4%CE%B1%CF%83%CE%B4%CE%B1%CF%83%20%CE%B4%CE%B1%CF%83%CE%B1%CF;\r\n " "param1*7*=%87%CF%86%CE%B4%CE%B4%CF%83%CE%B1%202008.doc", - p3.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047, 80)); // max line length = 80 + p3.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047, 80) // max line length = 80 + ); - VASSERT_EQ("3.either", "F: X; param1*0*=utf-8''%CE%B4%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83;\r\n " + VASSERT_EQ( + "3.either", + "F: X; param1*0*=utf-8''%CE%B4%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83;\r\n " "param1*1*=%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83%CF%83;\r\n " "param1*2*=%CE%B4%CF%83%CE%B4%CE%B1%20%CE%B4%CF%83%CE%B1%CE%B4%CF%83%CE%B4%CF;\r\n " "param1*3*=%83%CE%B1%CE%B4%CF%83%CE%B1%CE%B4%CE%B1%CF%83%CE%B4%CE%B1%CF%83%20;\r\n " @@ -399,47 +461,77 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) "param1*5*=%83%CE%B1%CE%B4%CE%B1%CF%83%CE%B4%CF%83%CE%B1%20%CE%B4%CE%B1%CF%83;\r\n " "param1*6*=%CE%B4%CE%B1%CF%83%CE%B4%CE%B1%CF%83%20%CE%B4%CE%B1%CF%83%CE%B1%CF;\r\n " "param1*7*=%87%CF%86%CE%B4%CE%B4%CF%83%CE%B1%202008.doc", - p3.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY, 80)); // max line length = 80 + p3.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY, 80) // max line length = 80 + ); // No encoding needed parameterizedHeaderField p4; - p4.appendParameter(vmime::make_shared ("param1", - vmime::word("va lue", vmime::charset("charset")))); + p4.appendParameter( + vmime::make_shared ( + "param1", + vmime::word("va lue", vmime::charset("charset")) + ) + ); - VASSERT_EQ("4.no-encoding", "F: X; param1=\"va lue\"", - p4.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING)); + VASSERT_EQ( + "4.no-encoding", + "F: X; param1=\"va lue\"", + p4.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING) + ); - VASSERT_EQ("4.rfc2047", "F: X; param1=\"va lue\"", - p4.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY)); + VASSERT_EQ( + "4.rfc2047", + "F: X; param1=\"va lue\"", + p4.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY) + ); - VASSERT_EQ("4.rfc2231", "F: X; param1=\"va lue\"", - p4.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY)); + VASSERT_EQ( + "4.rfc2231", + "F: X; param1=\"va lue\"", + p4.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY) + ); - VASSERT_EQ("4.both", "F: X; param1=\"va lue\"", - p4.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047)); + VASSERT_EQ( + "4.both", + "F: X; param1=\"va lue\"", + p4.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047) + ); // Language specification parameterizedHeaderField p5; - p5.appendParameter(vmime::make_shared ("param1", - vmime::word("This is ***fun***", vmime::charset("us-ascii"), "en-us"))); + p5.appendParameter( + vmime::make_shared ("param1", + vmime::word("This is ***fun***", vmime::charset("us-ascii"), "en-us")) + ); - VASSERT_EQ("5.no-encoding", "F: X; param1=\"This is ***fun***\"", - p5.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING)); + VASSERT_EQ( + "5.no-encoding", + "F: X; param1=\"This is ***fun***\"", + p5.generate(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING) + ); - VASSERT_EQ("5.rfc2047", "F: X; param1=\"=?us-ascii*en-us?Q?This_is_***fun***?=\"", - p5.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY)); + VASSERT_EQ( + "5.rfc2047", + "F: X; param1=\"=?us-ascii*en-us?Q?This_is_***fun***?=\"", + p5.generate(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY) + ); - VASSERT_EQ("5.rfc2231", "F: X; param1*=us-ascii''This%20is%20***fun***", - p5.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY)); + VASSERT_EQ( + "5.rfc2231", + "F: X; param1*=us-ascii''This%20is%20***fun***", + p5.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY) + ); - VASSERT_EQ("5.both", "F: X; " - "param1=\"=?us-ascii*en-us?Q?This_is_***fun***?=\";\r\n " - "param1*=us-ascii''This%20is%20***fun***", + VASSERT_EQ( + "5.both", + "F: X; " + "param1=\"=?us-ascii*en-us?Q?This_is_***fun***?=\";\r\n " + "param1*=us-ascii''This%20is%20***fun***", p5.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047)); } - void testGetGeneratedSizeRFC2231() - { + void testGetGeneratedSizeRFC2231() { + vmime::generationContext ctx(vmime::generationContext::getDefaultContext()); // Extended parameter with charset specifier @@ -543,12 +635,12 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) VASSERT("5.both", p5.getGeneratedSize(ctx) >= generateParameter(p5, ctx).length()); } - void testNonStandardEncodedParam() - { + void testNonStandardEncodedParam() { + // This syntax is non-standard (expressly prohibited // by RFC-2047), but is used by Mozilla: // - // Content-Type: image/png; + // Content-Type: image/png; // name="=?us-ascii?Q?Logo_VMime=2Epng?=" parameterizedHeaderField p1; @@ -567,8 +659,8 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) } // Parse parameters with non-significant whitespaces - void testParseNonSignificantWS() - { + void testParseNonSignificantWS() { + parameterizedHeaderField p1; p1.parse(" \t X \r\n"); @@ -584,8 +676,8 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) } // Encode "tspecials" - void testEncodeTSpecials() - { + void testEncodeTSpecials() { + VASSERT_EQ(" 1", "p=\"val(ue\"", vmime::make_shared ("p", "val(ue")->generate()); VASSERT_EQ(" 2", "p=\"val)ue\"", vmime::make_shared ("p", "val)ue")->generate()); VASSERT_EQ(" 3", "p=\"val("p", "valgenerate()); @@ -604,16 +696,20 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) } // http://sourceforge.net/projects/vmime/forums/forum/237356/topic/3812278 - void testEncodeTSpecialsInRFC2231() - { - VASSERT_EQ("1", "filename*=UTF-8''my_file_name_%C3%B6%C3%A4%C3%BC_%281%29.txt", - vmime::make_shared - ("filename", - vmime::word("my_file_name_\xc3\xb6\xc3\xa4\xc3\xbc_(1).txt", "UTF-8"))->generate()); + void testEncodeTSpecialsInRFC2231() { + + VASSERT_EQ( + "1", + "filename*=UTF-8''my_file_name_%C3%B6%C3%A4%C3%BC_%281%29.txt", + vmime::make_shared ( + "filename", + vmime::word("my_file_name_\xc3\xb6\xc3\xa4\xc3\xbc_(1).txt", "UTF-8") + )->generate() + ); } - void testWhitespaceBreaksTheValue() - { + void testWhitespaceBreaksTheValue() { + parameterizedHeaderField p; p.parse("xxx yyy; param1=value1 \r\n"); @@ -624,4 +720,3 @@ VMIME_TEST_SUITE_BEGIN(parameterTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/pathTest.cpp b/tests/parser/pathTest.cpp index f73dd0d4..13969112 100644 --- a/tests/parser/pathTest.cpp +++ b/tests/parser/pathTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,8 +33,8 @@ VMIME_TEST_SUITE_BEGIN(pathTest) VMIME_TEST_LIST_END - void testParse() - { + void testParse() { + vmime::path p1; p1.parse("<>"); @@ -54,8 +54,8 @@ VMIME_TEST_SUITE_BEGIN(pathTest) VASSERT_EQ("3.2", "domain", p3.getDomain()); } - void testParse2() - { + void testParse2() { + // Test some invalid paths (no '<>') vmime::path p1; p1.parse(""); @@ -76,8 +76,8 @@ VMIME_TEST_SUITE_BEGIN(pathTest) VASSERT_EQ("3.2", "domain", p3.getDomain()); } - void testGenerate() - { + void testGenerate() { + vmime::path p1; VASSERT_EQ("1", "<>", p1.generate()); @@ -100,4 +100,3 @@ VMIME_TEST_SUITE_BEGIN(pathTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/streamContentHandlerTest.cpp b/tests/parser/streamContentHandlerTest.cpp index 55680c93..399118e7 100644 --- a/tests/parser/streamContentHandlerTest.cpp +++ b/tests/parser/streamContentHandlerTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,15 +41,15 @@ VMIME_TEST_SUITE_BEGIN(streamContentHandlerTest) VMIME_TEST_LIST_END - void testIsEmpty() - { + void testIsEmpty() { + vmime::streamContentHandler cth; VASSERT_TRUE("empty", cth.isEmpty()); } - void testGetLength() - { + void testGetLength() { + vmime::string data("Test Data"); vmime::shared_ptr stream = vmime::make_shared (data); @@ -60,8 +60,8 @@ VMIME_TEST_SUITE_BEGIN(streamContentHandlerTest) VASSERT_EQ("length", 9, cth.getLength()); } - void testIsEncoded() - { + void testIsEncoded() { + vmime::string data("Test Data"); vmime::shared_ptr stream = vmime::make_shared (data); @@ -82,8 +82,8 @@ VMIME_TEST_SUITE_BEGIN(streamContentHandlerTest) VASSERT_EQ("encoding", "base64", cth2.getEncoding().generate()); } - void testGetLength_Encoded() - { + void testGetLength_Encoded() { + vmime::string data("foo=12=34=56bar"); vmime::shared_ptr stream = vmime::make_shared (data); @@ -94,8 +94,8 @@ VMIME_TEST_SUITE_BEGIN(streamContentHandlerTest) VASSERT_EQ("length", 15, cth.getLength()); } - void testExtract() - { + void testExtract() { + vmime::string data("Test Data"); vmime::shared_ptr stream = vmime::make_shared (data); @@ -110,10 +110,12 @@ VMIME_TEST_SUITE_BEGIN(streamContentHandlerTest) VASSERT_EQ("extract", "Test Data", oss.str()); } - void testExtract_Encoded() - { - vmime::string data - ("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODk="); + void testExtract_Encoded() { + + vmime::string data( + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODk=" + ); + vmime::shared_ptr stream = vmime::make_shared (data); @@ -125,14 +127,18 @@ VMIME_TEST_SUITE_BEGIN(streamContentHandlerTest) cth.extract(osa); // Data should be decoded from B64 - VASSERT_EQ("extract", - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", oss.str()); + VASSERT_EQ( + "extract", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + oss.str() + ); } void testExtractRaw_Encoded() { - vmime::string data - ("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODk="); + vmime::string data( + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODk=" + ); vmime::shared_ptr stream = vmime::make_shared (data); @@ -144,12 +150,15 @@ VMIME_TEST_SUITE_BEGIN(streamContentHandlerTest) cth.extractRaw(osa); // Data should not be decoded - VASSERT_EQ("extractRaw", - "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODk=", oss.str()); + VASSERT_EQ( + "extractRaw", + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODk=", + oss.str() + ); } - void testGenerate() - { + void testGenerate() { + vmime::string data("foo\x12\x34\x56 bar"); vmime::shared_ptr stream = vmime::make_shared (data); @@ -165,8 +174,8 @@ VMIME_TEST_SUITE_BEGIN(streamContentHandlerTest) VASSERT_EQ("generate", "Zm9vEjRWIGJhcg==", oss.str()); } - void testGenerate_Encoded() - { + void testGenerate_Encoded() { + vmime::string data("foo=12=34=56bar"); vmime::shared_ptr stream = vmime::make_shared (data); diff --git a/tests/parser/stringContentHandlerTest.cpp b/tests/parser/stringContentHandlerTest.cpp index e238e172..0f886f76 100644 --- a/tests/parser/stringContentHandlerTest.cpp +++ b/tests/parser/stringContentHandlerTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -42,23 +42,23 @@ VMIME_TEST_SUITE_BEGIN(stringContentHandlerTest) VMIME_TEST_LIST_END - void testIsEmpty() - { + void testIsEmpty() { + vmime::stringContentHandler cth; VASSERT_TRUE("empty", cth.isEmpty()); } - void testGetLength() - { + void testGetLength() { + vmime::stringContentHandler cth("Test Data"); VASSERT_FALSE("empty", cth.isEmpty()); VASSERT_EQ("length", 9, cth.getLength()); } - void testIsEncoded() - { + void testIsEncoded() { + vmime::stringContentHandler cth("Test Data"); VASSERT_FALSE("encoded", cth.isEncoded()); @@ -71,17 +71,19 @@ VMIME_TEST_SUITE_BEGIN(stringContentHandlerTest) VASSERT_EQ("encoding", "base64", cth2.getEncoding().generate()); } - void testGetLength_Encoded() - { - vmime::stringContentHandler cth - ("foo=12=34=56bar", vmime::encoding("quoted-printable")); + void testGetLength_Encoded() { + + vmime::stringContentHandler cth( + "foo=12=34=56bar", + vmime::encoding("quoted-printable") + ); // Reported length should be the length of encoded data VASSERT_EQ("length", 15, cth.getLength()); } - void testExtract() - { + void testExtract() { + vmime::stringContentHandler cth("Test Data"); std::ostringstream oss; @@ -92,11 +94,12 @@ VMIME_TEST_SUITE_BEGIN(stringContentHandlerTest) VASSERT_EQ("extract", "Test Data", oss.str()); } - void testExtract_Encoded() - { - vmime::stringContentHandler cth - ("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODk=", - vmime::encoding("base64")); + void testExtract_Encoded() { + + vmime::stringContentHandler cth( + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODk=", + vmime::encoding("base64") + ); std::ostringstream oss; vmime::utility::outputStreamAdapter osa(oss); @@ -104,15 +107,19 @@ VMIME_TEST_SUITE_BEGIN(stringContentHandlerTest) cth.extract(osa); // Data should be decoded from B64 - VASSERT_EQ("extract", - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", oss.str()); + VASSERT_EQ( + "extract", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + oss.str() + ); } - void testExtractRaw_Encoded() - { - vmime::stringContentHandler cth - ("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODk=", - vmime::encoding("base64")); + void testExtractRaw_Encoded() { + + vmime::stringContentHandler cth( + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODk=", + vmime::encoding("base64") + ); std::ostringstream oss; vmime::utility::outputStreamAdapter osa(oss); @@ -120,12 +127,15 @@ VMIME_TEST_SUITE_BEGIN(stringContentHandlerTest) cth.extractRaw(osa); // Data should not be decoded - VASSERT_EQ("extractRaw", - "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODk=", oss.str()); + VASSERT_EQ( + "extractRaw", + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODk=", + oss.str() + ); } - void testGenerate() - { + void testGenerate() { + vmime::stringContentHandler cth("foo\x12\x34\x56 bar"); std::ostringstream oss; @@ -137,10 +147,12 @@ VMIME_TEST_SUITE_BEGIN(stringContentHandlerTest) VASSERT_EQ("generate", "Zm9vEjRWIGJhcg==", oss.str()); } - void testGenerate_Encoded() - { - vmime::stringContentHandler cth - ("foo=12=34=56bar", vmime::encoding("quoted-printable")); + void testGenerate_Encoded() { + + vmime::stringContentHandler cth( + "foo=12=34=56bar", + vmime::encoding("quoted-printable") + ); std::ostringstream oss; vmime::utility::outputStreamAdapter osa(oss); @@ -151,8 +163,8 @@ VMIME_TEST_SUITE_BEGIN(stringContentHandlerTest) VASSERT_EQ("generate", "Zm9vEjRWYmFy", oss.str()); } - void testStringProxy() - { + void testStringProxy() { + // With 'stringProxy' object vmime::utility::stringProxy str("This is the data buffer", 12, 12 + 4); vmime::stringContentHandler cth(str); diff --git a/tests/parser/textTest.cpp b/tests/parser/textTest.cpp index 60a9508e..16abf11b 100644 --- a/tests/parser/textTest.cpp +++ b/tests/parser/textTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -66,48 +66,46 @@ VMIME_TEST_SUITE_BEGIN(textTest) VMIME_TEST_LIST_END - static const vmime::string getDisplayText(const vmime::text& t) - { + static const vmime::string getDisplayText(const vmime::text& t) { + return t.getWholeBuffer(); } - static const vmime::string cleanGeneratedWords(const std::string& str) - { + static const vmime::string cleanGeneratedWords(const std::string& str) { + std::istringstream iss(str); std::string res; std::string x; - while (std::getline(iss, x)) + while (std::getline(iss, x)) { res += vmime::utility::stringUtils::trim(x); + } return res; } - void setUp() - { + void setUp() { + // 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 - { + try { std::locale::global(std::locale("")); - } - catch (std::exception &) - { + } catch (std::exception &) { std::setlocale(LC_ALL, ""); } } - void tearDown() - { + void tearDown() { + // Restore default locale std::locale::global(std::locale("C")); } - void testConstructors() - { + void testConstructors() { + vmime::text t1; VASSERT_EQ("1.1", 0, t1.getWordCount()); @@ -143,8 +141,8 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT_EQ("5.5", w2.getCharset(), t5.getWordAt(1)->getCharset()); } - void testCopy() - { + void testCopy() { + vmime::text t1("Test: \xa9\xc3"); VASSERT("operator==", t1 == t1); @@ -156,8 +154,8 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT("copyFrom", t1 == t2); } - void testNewFromString() - { + void testNewFromString() { + vmime::string s1 = "only ASCII characters"; vmime::charset c1("test"); vmime::text t1; @@ -186,52 +184,75 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT_EQ("2.7", vmime::charset(vmime::charsets::US_ASCII), t2.getWordAt(2)->getCharset()); } - static const vmime::string parseText(const vmime::string& buffer) - { + static const vmime::string parseText(const vmime::string& buffer) { + vmime::text t; t.parse(buffer); std::ostringstream oss; oss << t; - return (oss.str()); + return oss.str(); } - void testParse() - { + void testParse() { + // From RFC-2047 - VASSERT_EQ("1", "[text: [[word: charset=US-ASCII, buffer=Keith Moore]]]", - parseText("=?US-ASCII?Q?Keith_Moore?=")); + VASSERT_EQ( + "1", + "[text: [[word: charset=US-ASCII, buffer=Keith Moore]]]", + parseText("=?US-ASCII?Q?Keith_Moore?=") + ); - VASSERT_EQ("2", "[text: [[word: charset=ISO-8859-1, buffer=Keld J\xf8rn Simonsen]]]", - parseText("=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=")); + VASSERT_EQ( + "2", + "[text: [[word: charset=ISO-8859-1, buffer=Keld J\xf8rn Simonsen]]]", + parseText("=?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?=") + ); - VASSERT_EQ("3", "[text: [[word: charset=ISO-8859-1, buffer=Andr\xe9]," \ - "[word: charset=us-ascii, buffer= Pirard]]]", - parseText("=?ISO-8859-1?Q?Andr=E9?= Pirard")); + VASSERT_EQ( + "3", + "[text: [[word: charset=ISO-8859-1, buffer=Andr\xe9]," \ + "[word: charset=us-ascii, buffer= Pirard]]]", + parseText("=?ISO-8859-1?Q?Andr=E9?= Pirard") + ); - VASSERT_EQ("4", "[text: [[word: charset=ISO-8859-1, buffer=If you can read this yo]," \ - "[word: charset=ISO-8859-2, buffer=u understand the example.]]]", - parseText("=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=\r\n " \ - "=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=")); + VASSERT_EQ( + "4", + "[text: [[word: charset=ISO-8859-1, buffer=If you can read this yo]," \ + "[word: charset=ISO-8859-2, buffer=u understand the example.]]]", + parseText( + "=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=\r\n " \ + "=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=" + ) + ); // Bugfix: in "=?charset?q?=XX=YY?=", the "?=" finish // sequence was not correctly found (should be the one // after '=YY' and not the one after '?q'). - VASSERT_EQ("5", "[text: [[word: charset=abc, buffer=\xe9\xe9]]]", - parseText("=?abc?q?=E9=E9?=")); + VASSERT_EQ( + "5", + "[text: [[word: charset=abc, buffer=\xe9\xe9]]]", + parseText("=?abc?q?=E9=E9?=") + ); // Question marks (?) in the middle of the string - VASSERT_EQ("6", "[text: [[word: charset=iso-8859-1, buffer=Know wh\xe4t? It works!]]]", - parseText("=?iso-8859-1?Q?Know_wh=E4t?_It_works!?=")); + VASSERT_EQ( + "6", + "[text: [[word: charset=iso-8859-1, buffer=Know wh\xe4t? It works!]]]", + parseText("=?iso-8859-1?Q?Know_wh=E4t?_It_works!?=") + ); // With language specifier - VASSERT_EQ("7", "[text: [[word: charset=US-ASCII, buffer=Keith Moore, lang=EN]]]", - parseText("=?US-ASCII*EN?Q?Keith_Moore?=")); + VASSERT_EQ( + "7", + "[text: [[word: charset=US-ASCII, buffer=Keith Moore, lang=EN]]]", + parseText("=?US-ASCII*EN?Q?Keith_Moore?=") + ); } - void testGenerate() - { + void testGenerate() { + // TODO // With language specifier @@ -242,8 +263,8 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT_EQ("lang2", "=?US-ASCII*EN?Q?Keith_Moore?=", wlang2.generate()); } - void testDisplayForm() - { + void testDisplayForm() { + #define DISPLAY_FORM(x) getDisplayText(*vmime::text::decodeAndUnfold(x)) // From RFC-2047 @@ -276,8 +297,8 @@ VMIME_TEST_SUITE_BEGIN(textTest) #undef DISPLAY_FORM } - void testWordConstructors() - { + void testWordConstructors() { + VASSERT_EQ("1.1", vmime::charset::getLocalCharset(), vmime::word().getCharset()); VASSERT_EQ("1.2", "", vmime::word().getBuffer()); @@ -288,8 +309,8 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT_EQ("3.2", "foo", vmime::word("foo", vmime::charset("bar")).getBuffer()); } - void testWordParse() - { + void testWordParse() { + // Simple encoded word vmime::word w1; w1.parse("=?foo?q?bar=E9 baz?="); @@ -319,21 +340,32 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT_EQ("4.2", "=?whatever?not_q_or_b?whatever?=", w4.getBuffer()); } - void testWordGenerate() - { - VASSERT_EQ("1", "=?foo?Q?bar=E9_baz?=", - vmime::word("bar\xe9 baz", vmime::charset("foo")).generate()); + void testWordGenerate() { - VASSERT_EQ("2", "=?foo?B?8fLz9PU=?=", - vmime::word("\xf1\xf2\xf3\xf4\xf5", vmime::charset("foo")).generate()); + VASSERT_EQ( + "1", + "=?foo?Q?bar=E9_baz?=", + vmime::word("bar\xe9 baz", vmime::charset("foo")).generate() + ); + + VASSERT_EQ( + "2", + "=?foo?B?8fLz9PU=?=", + vmime::word("\xf1\xf2\xf3\xf4\xf5", vmime::charset("foo")).generate() + ); } - void testWordGenerateSpace() - { + void testWordGenerateSpace() { + // No white-space between an unencoded word and a encoded one - VASSERT_EQ("1", "Bonjour =?utf-8?Q?Fran=C3=A7ois?=", - vmime::text::newFromString("Bonjour Fran\xc3\xa7ois", - vmime::charset("utf-8"))->generate()); + VASSERT_EQ( + "1", + "Bonjour =?utf-8?Q?Fran=C3=A7ois?=", + vmime::text::newFromString( + "Bonjour Fran\xc3\xa7ois", + vmime::charset("utf-8") + )->generate() + ); // White-space between two encoded words vmime::text txt; @@ -356,8 +388,8 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT_EQ("4", encoded, txt2.generate()); } - void testWordGenerateSpace2() - { + void testWordGenerateSpace2() { + // White-space between two encoded words (#2) vmime::text txt; txt.appendWord(vmime::make_shared ("Facture ", "utf-8")); @@ -382,18 +414,28 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT_EQ("3", encoded, txt2.generate()); } - void testWordGenerateMultiBytes() - { - // Ensure we don't encode a non-integral number of characters - VASSERT_EQ("1", "=?utf-8?Q?aaa?==?utf-8?Q?=C3=A9?==?utf-8?Q?zzz?=", - cleanGeneratedWords(vmime::word("aaa\xc3\xa9zzz", vmime::charset("utf-8")).generate(16))); + void testWordGenerateMultiBytes() { - VASSERT_EQ("2", "=?utf-8?Q?aaa=C3=A9?==?utf-8?Q?zzz?=", - cleanGeneratedWords(vmime::word("aaa\xc3\xa9zzz", vmime::charset("utf-8")).generate(17))); + // Ensure we don't encode a non-integral number of characters + VASSERT_EQ( + "1", + "=?utf-8?Q?aaa?==?utf-8?Q?=C3=A9?==?utf-8?Q?zzz?=", + cleanGeneratedWords( + vmime::word("aaa\xc3\xa9zzz", vmime::charset("utf-8")).generate(16) + ) + ); + + VASSERT_EQ( + "2", + "=?utf-8?Q?aaa=C3=A9?==?utf-8?Q?zzz?=", + cleanGeneratedWords( + vmime::word("aaa\xc3\xa9zzz", vmime::charset("utf-8")).generate(17) + ) + ); } - void testWordGenerateQuote() - { + void testWordGenerateQuote() { + std::string str; vmime::utility::outputStreamStringAdapter os(str); @@ -402,37 +444,56 @@ VMIME_TEST_SUITE_BEGIN(textTest) // ASCII-only text is quotable str.clear(); - vmime::word("Quoted text").generate(ctx, os, 0, NULL, vmime::text::QUOTE_IF_POSSIBLE, NULL); + vmime::word("Quoted text") + .generate(ctx, os, 0, NULL, vmime::text::QUOTE_IF_POSSIBLE, NULL); + VASSERT_EQ("1", "\"Quoted text\"", cleanGeneratedWords(str)); // Text with CR/LF is not quotable str.clear(); - vmime::word("Non-quotable\ntext", "us-ascii").generate(ctx, os, 0, NULL, vmime::text::QUOTE_IF_POSSIBLE, NULL); + vmime::word("Non-quotable\ntext", "us-ascii") + .generate(ctx, os, 0, NULL, vmime::text::QUOTE_IF_POSSIBLE, NULL); + VASSERT_EQ("2", "=?us-ascii?Q?Non-quotable=0Atext?=", cleanGeneratedWords(str)); // Text with non-ASCII chars is not quotable str.clear(); - vmime::word("Non-quotable text \xc3\xa9").generate(ctx, os, 0, NULL, vmime::text::QUOTE_IF_POSSIBLE, NULL); + vmime::word("Non-quotable text \xc3\xa9") + .generate(ctx, os, 0, NULL, vmime::text::QUOTE_IF_POSSIBLE, NULL); + VASSERT_EQ("3", "=?UTF-8?Q?Non-quotable_text_=C3=A9?=", cleanGeneratedWords(str)); } - void testWordGenerateSpecialCharsets() - { + void testWordGenerateSpecialCharsets() { + // ISO-2022-JP only uses 7-bit chars but should be encoded in Base64 - VASSERT_EQ("1", "=?iso-2022-jp?B?XlskQiVRITwlPSVKJWshJiU9JVUlSCUmJSclIl5bKEI=?=", - cleanGeneratedWords(vmime::word("^[$B%Q!<%=%J%k!&%=%U%H%&%'%\"^[(B", - vmime::charset("iso-2022-jp")).generate(100))); + VASSERT_EQ( + "1", + "=?iso-2022-jp?B?XlskQiVRITwlPSVKJWshJiU9JVUlSCUmJSclIl5bKEI=?=", + cleanGeneratedWords( + vmime::word( + "^[$B%Q!<%=%J%k!&%=%U%H%&%'%\"^[(B", + vmime::charset("iso-2022-jp") + ).generate(100) + ) + ); } - void testWordGenerateSpecials() - { + void testWordGenerateSpecials() { + // In RFC-2047, quotation marks (ASCII 22h) should be encoded - VASSERT_EQ("1", "=?UTF-8?Q?=22=C3=9Cml=C3=A4ute=22?=", - vmime::word("\x22\xC3\x9Cml\xC3\xA4ute\x22", vmime::charset("UTF-8")).generate()); + VASSERT_EQ( + "1", + "=?UTF-8?Q?=22=C3=9Cml=C3=A4ute=22?=", + vmime::word( + "\x22\xC3\x9Cml\xC3\xA4ute\x22", + vmime::charset("UTF-8") + ).generate() + ); } - void testWhitespace() - { + void testWhitespace() { + // Create vmime::text text; text.createFromString("Achim Br\xc3\xa4ndt", vmime::charsets::UTF_8); @@ -456,8 +517,8 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT_EQ("11", "utf-8", text.getWordAt(1)->getCharset()); } - void testWhitespaceMBox() - { + void testWhitespaceMBox() { + // Space MUST be encoded inside a word vmime::mailbox mbox(vmime::text("Achim Br\xc3\xa4ndt", vmime::charsets::UTF_8), "me@vmime.org"); VASSERT_EQ("generate1", "=?us-ascii?Q?Achim_?= =?utf-8?Q?Br=C3=A4ndt?= ", mbox.generate()); @@ -478,30 +539,38 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT_EQ("parse.email", "me@vmime.org", mbox.getEmail()); } - void testFoldingAscii() - { + void testFoldingAscii() { + // In this test, no encoding is needed, but line should be folded anyway vmime::word w("01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789", vmime::charset("us-ascii")); - VASSERT_EQ("fold.ascii", + VASSERT_EQ( + "fold.ascii", "=?us-ascii?Q?01234567890123456789012345678901234?=\r\n" " =?us-ascii?Q?5678901234567890123456789012345678?=\r\n" - " =?us-ascii?Q?9012345678901234567890123456789?=", w.generate(50)); + " =?us-ascii?Q?9012345678901234567890123456789?=", w.generate(50) + ); } - void testForcedNonEncoding() - { + void testForcedNonEncoding() { + // Testing long unbreakable and unencodable header vmime::relay r; - r.parse(" from User (Ee9GMqZQ8t7IQwftfAFHd2KyScCYRrFSJ50tKEoXv2bVCG4HcPU80GGWiFabAvG77FekpGgF1h@[127.0.0.1]) by servername.hostname.com\n\t" - "with esmtp id 1NGTS9-2C0sqG0; Fri, 4 Dec 2009 09:23:49 +0100"); + r.parse( + " from User (Ee9GMqZQ8t7IQwftfAFHd2KyScCYRrFSJ50tKEoXv2bVCG4HcPU80GGWiFabAvG77FekpGgF1h@[127.0.0.1]) by servername.hostname.com\n\t" + "with esmtp id 1NGTS9-2C0sqG0; Fri, 4 Dec 2009 09:23:49 +0100" + ); - VASSERT_EQ("received.long", "from User\r\n (Ee9GMqZQ8t7IQwftfAFHd2KyScCYRrFSJ50tKEoXv2bVCG4HcPU80GGWiFabAvG77FekpGgF1h@[127.0.0.1])\r\n by servername.hostname.com with esmtp id 1NGTS9-2C0sqG0; Fri, 4 Dec 2009\r\n 09:23:49 +0100", r.generate(78)); + VASSERT_EQ( + "received.long", + "from User\r\n (Ee9GMqZQ8t7IQwftfAFHd2KyScCYRrFSJ50tKEoXv2bVCG4HcPU80GGWiFabAvG77FekpGgF1h@[127.0.0.1])\r\n by servername.hostname.com with esmtp id 1NGTS9-2C0sqG0; Fri, 4 Dec 2009\r\n 09:23:49 +0100", + r.generate(78) + ); } - void testBugFix20110511() - { + void testBugFix20110511() { + /* Using the latest version of vmime (0.9.1), encoding the following string: Jean @@ -520,8 +589,11 @@ VMIME_TEST_SUITE_BEGIN(textTest) const std::string ENCODED_TEXT = "Jean =?utf-8?Q?Gwena=C3=ABl?= Dutourd"; // Encode - VASSERT_EQ("encode", ENCODED_TEXT, - vmime::text::newFromString(DECODED_TEXT, vmime::charset("utf-8"))->generate()); + VASSERT_EQ( + "encode", + ENCODED_TEXT, + vmime::text::newFromString(DECODED_TEXT, vmime::charset("utf-8"))->generate() + ); // Decode vmime::text t; @@ -529,56 +601,69 @@ VMIME_TEST_SUITE_BEGIN(textTest) // -- words std::ostringstream oss; oss << t; - VASSERT_EQ("decode1", + VASSERT_EQ( + "decode1", "[text: [[word: charset=us-ascii, buffer=Jean ]," "[word: charset=utf-8, buffer=Gwenaël]," - "[word: charset=us-ascii, buffer= Dutourd]]]", oss.str()); + "[word: charset=us-ascii, buffer= Dutourd]]]", + oss.str() + ); // -- getWholeBuffer VASSERT_EQ("decode2", DECODED_TEXT, t.getWholeBuffer()); } - void testInternationalizedEmail_specialChars() - { + void testInternationalizedEmail_specialChars() { + vmime::generationContext ctx(vmime::generationContext::getDefaultContext()); ctx.setInternationalizedEmailSupport(true); vmime::generationContext::switcher contextSwitcher(ctx); // Special sequence/chars should still be encoded - VASSERT_EQ("1", "=?us-ascii?Q?Test=3D=3Frfc2047_sequence?=", - vmime::word("Test=?rfc2047 sequence", vmime::charset("us-ascii")).generate()); + VASSERT_EQ( + "1", + "=?us-ascii?Q?Test=3D=3Frfc2047_sequence?=", + vmime::word("Test=?rfc2047 sequence", vmime::charset("us-ascii")).generate() + ); - VASSERT_EQ("2", "=?us-ascii?Q?Line_One=0ALine_Two?=", - vmime::word("Line One\nLine Two", vmime::charset("us-ascii")).generate()); + VASSERT_EQ( + "2", + "=?us-ascii?Q?Line_One=0ALine_Two?=", + vmime::word("Line One\nLine Two", vmime::charset("us-ascii")).generate() + ); } - void testInternationalizedEmail_UTF8() - { + void testInternationalizedEmail_UTF8() { + vmime::generationContext ctx(vmime::generationContext::getDefaultContext()); ctx.setInternationalizedEmailSupport(true); vmime::generationContext::switcher contextSwitcher(ctx); // Already UTF-8 encoded text should be left as is - VASSERT_EQ("1", "Achim Br\xc3\xa4ndt", - vmime::word("Achim Br\xc3\xa4ndt", vmime::charset("utf-8")).generate()); + VASSERT_EQ( + "1", "Achim Br\xc3\xa4ndt", + vmime::word("Achim Br\xc3\xa4ndt", vmime::charset("utf-8")).generate() + ); } - void testInternationalizedEmail_nonUTF8() - { + void testInternationalizedEmail_nonUTF8() { + vmime::generationContext ctx(vmime::generationContext::getDefaultContext()); ctx.setInternationalizedEmailSupport(true); vmime::generationContext::switcher contextSwitcher(ctx); // Non UTF-8 encoded text should first be converted to UTF-8 - VASSERT_EQ("1", "Achim Br\xc3\xa4ndt", - vmime::word("Achim Br\xe4ndt", vmime::charset("iso-8859-1")).generate()); + VASSERT_EQ( + "1", "Achim Br\xc3\xa4ndt", + vmime::word("Achim Br\xe4ndt", vmime::charset("iso-8859-1")).generate() + ); } - void testInternationalizedEmail_folding() - { + void testInternationalizedEmail_folding() { + vmime::generationContext ctx(vmime::generationContext::getDefaultContext()); ctx.setInternationalizedEmailSupport(true); @@ -588,63 +673,82 @@ VMIME_TEST_SUITE_BEGIN(textTest) vmime::word w1("01234567890123456789\xc3\xa0x012345678901234567890123456789" "01234567890123456789\xc3\xa0x012345678901234567890123456789", vmime::charset("utf-8")); - VASSERT_EQ("1", + VASSERT_EQ( + "1", "=?utf-8?Q?01234567890123456789=C3=A0x01234567890?=\r\n" " =?utf-8?Q?1234567890123456789012345678901234567?=\r\n" " =?utf-8?Q?89=C3=A0x0123456789012345678901234567?=\r\n" - " =?utf-8?Q?89?=", w1.generate(50)); + " =?utf-8?Q?89?=", + w1.generate(50) + ); // RFC-2047 encoding will not be forced, as words can be wrapped in a new line vmime::word w2("bla bla bla This is some '\xc3\xa0\xc3\xa7' UTF-8 encoded text", vmime::charset("utf-8")); - VASSERT_EQ("2", + VASSERT_EQ( + "2", "bla bla bla This is\r\n" " some '\xc3\xa0\xc3\xa7' UTF-8\r\n" - " encoded text", w2.generate(20)); + " encoded text", + w2.generate(20) + ); } - void testWronglyPaddedB64Words() - { + void testWronglyPaddedB64Words() { + vmime::text outText; vmime::text::decodeAndUnfold("=?utf-8?B?5Lit5?=\n =?utf-8?B?paH?=", &outText); - VASSERT_EQ("1", "\xe4\xb8\xad\xe6\x96\x87", - outText.getConvertedText(vmime::charset("utf-8"))); + VASSERT_EQ( + "1", + "\xe4\xb8\xad\xe6\x96\x87", + outText.getConvertedText(vmime::charset("utf-8")) + ); vmime::text::decodeAndUnfold("=?utf-8?B?5Lit5p?=\n =?utf-8?B?aH?=", &outText); - VASSERT_EQ("2", "\xe4\xb8\xad\xe6\x96\x87", - outText.getConvertedText(vmime::charset("utf-8"))); + VASSERT_EQ( + "2", + "\xe4\xb8\xad\xe6\x96\x87", + outText.getConvertedText(vmime::charset("utf-8")) + ); vmime::text::decodeAndUnfold("=?utf-8?B?5Lit5pa?=\n =?utf-8?B?H?=", &outText); - VASSERT_EQ("3", "\xe4\xb8\xad\xe6\x96\x87", - outText.getConvertedText(vmime::charset("utf-8"))); + VASSERT_EQ( + "3", + "\xe4\xb8\xad\xe6\x96\x87", + outText.getConvertedText(vmime::charset("utf-8")) + ); } // Ensure that words which encode a non-integral number of characters // are correctly decoded. - void testFixBrokenWords() - { + void testFixBrokenWords() { + vmime::text outText; vmime::charsetConverterOptions opts; opts.silentlyReplaceInvalidSequences = false; // just to be sure that broken words are actually fixed // Test case 1 - vmime::text::decodeAndUnfold - ("=?utf-8?Q?Gwena=C3?=" - "=?utf-8?Q?=ABl?=", &outText); + vmime::text::decodeAndUnfold( + "=?utf-8?Q?Gwena=C3?=" + "=?utf-8?Q?=ABl?=", + &outText + ); VASSERT_EQ("1.1", 1, outText.getWordCount()); VASSERT_EQ("1.2", "Gwena\xc3\xabl", outText.getWordAt(0)->getBuffer()); VASSERT_EQ("1.3", vmime::charset("utf-8"), outText.getWordAt(0)->getCharset()); // Test case 2 - vmime::text::decodeAndUnfold - ("=?utf-8?B?5Lit6Yu85qmf5qKw6JGj5LqL5pyDMTAz5bm056ysMDXlsYbn?=" - "=?utf-8?B?rKwwN+asoeitsOeoiw==?=", &outText); + vmime::text::decodeAndUnfold( + "=?utf-8?B?5Lit6Yu85qmf5qKw6JGj5LqL5pyDMTAz5bm056ysMDXlsYbn?=" + "=?utf-8?B?rKwwN+asoeitsOeoiw==?=", + &outText + ); VASSERT_EQ("2.1", 1, outText.getWordCount()); VASSERT_EQ("2.2", "\xe4\xb8\xad\xe9\x8b\xbc\xe6\xa9\x9f\xe6\xa2\xb0" @@ -654,21 +758,25 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT_EQ("2.3", vmime::charset("utf-8"), outText.getWordAt(0)->getCharset()); // Test case 3 (a character spanning over 3 words: 'を' = E3 82 92) - vmime::text::decodeAndUnfold - ("=?utf-8?Q?abc=E3?=" - "=?utf-8?Q?=82?=" - "=?utf-8?Q?=92xyz?=", &outText); + vmime::text::decodeAndUnfold( + "=?utf-8?Q?abc=E3?=" + "=?utf-8?Q?=82?=" + "=?utf-8?Q?=92xyz?=", + &outText + ); VASSERT_EQ("3.1", 1, outText.getWordCount()); VASSERT_EQ("3.2", "abc\xe3\x82\x92xyz", outText.getWordAt(0)->getBuffer()); VASSERT_EQ("3.3", vmime::charset("utf-8"), outText.getWordAt(0)->getCharset()); // Test case 4 (remains invalid) - vmime::text::decodeAndUnfold - ("=?utf-8?Q?abc=E3?=" - "=?utf-8?Q?=82?=" - "=?utf-8?Q?xy?=" - "=?utf-8?Q?z?=", &outText); + vmime::text::decodeAndUnfold( + "=?utf-8?Q?abc=E3?=" + "=?utf-8?Q?=82?=" + "=?utf-8?Q?xy?=" + "=?utf-8?Q?z?=", + &outText + ); VASSERT_EQ("4.1", 2, outText.getWordCount()); VASSERT_EQ("4.2", "abc", outText.getWordAt(0)->getBuffer()); @@ -677,11 +785,13 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT_EQ("4.5", vmime::charset("utf-8"), outText.getWordAt(1)->getCharset()); // Test case 5 (remains partially invalid) - vmime::text::decodeAndUnfold - ("=?utf-8?Q?abc=E3?=" - "=?utf-8?Q?=82?=" - "=?utf-8?Q?\x92xy?=" - "=?utf-8?Q?z\xc3?=", &outText); + vmime::text::decodeAndUnfold( + "=?utf-8?Q?abc=E3?=" + "=?utf-8?Q?=82?=" + "=?utf-8?Q?\x92xy?=" + "=?utf-8?Q?z\xc3?=", + &outText + ); VASSERT_EQ("5.1", 2, outText.getWordCount()); VASSERT_EQ("5.2", "abc\xe3\x82\x92xyz", outText.getWordAt(0)->getBuffer()); @@ -690,8 +800,8 @@ VMIME_TEST_SUITE_BEGIN(textTest) VASSERT_EQ("5.5", vmime::charset("utf-8"), outText.getWordAt(1)->getCharset()); } - void testUnknownCharset() - { + void testUnknownCharset() { + vmime::text t; vmime::text::decodeAndUnfold("=?gb2312?B?wdaRY8PA?=", &t); @@ -721,4 +831,3 @@ VMIME_TEST_SUITE_BEGIN(textTest) } VMIME_TEST_SUITE_END - diff --git a/tests/parser/wordEncoderTest.cpp b/tests/parser/wordEncoderTest.cpp index c3c44a87..08d34aa4 100644 --- a/tests/parser/wordEncoderTest.cpp +++ b/tests/parser/wordEncoderTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -40,88 +40,133 @@ VMIME_TEST_SUITE_BEGIN(wordEncoderTest) VMIME_TEST_LIST_END - void testGetNextChunk() - { + void testGetNextChunk() { + // An integral number of characters should be encoded vmime::wordEncoder we( "bufferfoobarbaz", vmime::charset("utf-8"), - vmime::wordEncoder::ENCODING_AUTO); + vmime::wordEncoder::ENCODING_AUTO + ); VASSERT_EQ("1", "buffer", we.getNextChunk(6)); VASSERT_EQ("2", "foo", we.getNextChunk(3)); VASSERT_EQ("3", "barbaz", we.getNextChunk(10)); } - void testGetNextChunk_integral() - { + void testGetNextChunk_integral() { + // An integral number of characters should be encoded vmime::wordEncoder we( "buffer\xc3\xa0plop", vmime::charset("utf-8"), - vmime::wordEncoder::ENCODING_AUTO); + vmime::wordEncoder::ENCODING_AUTO + ); VASSERT_EQ("1", "buffer=C3=A0", we.getNextChunk(7)); VASSERT_EQ("2", "plop", we.getNextChunk(10)); } - void testIsEncodingNeeded_ascii() - { + void testIsEncodingNeeded_ascii() { + vmime::generationContext ctx(vmime::generationContext::getDefaultContext()); ctx.setInternationalizedEmailSupport(false); - VASSERT_FALSE("ascii", vmime::wordEncoder::isEncodingNeeded - (ctx, "ASCII-only buffer", vmime::charset("utf-8"), "")); + VASSERT_FALSE( + "ascii", + vmime::wordEncoder::isEncodingNeeded( + ctx, "ASCII-only buffer", vmime::charset("utf-8"), "" + ) + ); - VASSERT_TRUE("non-ascii", vmime::wordEncoder::isEncodingNeeded - (ctx, "Buffer with some UTF-8 '\xc3\xa0'", vmime::charset("utf-8"), "")); + VASSERT_TRUE( + "non-ascii", + vmime::wordEncoder::isEncodingNeeded( + ctx, "Buffer with some UTF-8 '\xc3\xa0'", vmime::charset("utf-8"), "" + ) + ); } - void testIsEncodingNeeded_withLanguage() - { - VASSERT_TRUE("ascii", vmime::wordEncoder::isEncodingNeeded - (vmime::generationContext::getDefaultContext(), "ASCII-only buffer", vmime::charset("utf-8"), "en")); + void testIsEncodingNeeded_withLanguage() { + + VASSERT_TRUE( + "ascii", + vmime::wordEncoder::isEncodingNeeded( + vmime::generationContext::getDefaultContext(), + "ASCII-only buffer", + vmime::charset("utf-8"), + "en" + ) + ); } - void testIsEncodingNeeded_specialChars() - { - VASSERT_TRUE("rfc2047", vmime::wordEncoder::isEncodingNeeded - (vmime::generationContext::getDefaultContext(), - "foo bar =? foo bar", vmime::charset("us-ascii"), "")); + void testIsEncodingNeeded_specialChars() { - VASSERT_TRUE("new line 1", vmime::wordEncoder::isEncodingNeeded - (vmime::generationContext::getDefaultContext(), - "foo bar \n foo bar", vmime::charset("us-ascii"), "")); + VASSERT_TRUE( + "rfc2047", + vmime::wordEncoder::isEncodingNeeded( + vmime::generationContext::getDefaultContext(), + "foo bar =? foo bar", + vmime::charset("us-ascii"), + "" + ) + ); - VASSERT_TRUE("new line 2", vmime::wordEncoder::isEncodingNeeded - (vmime::generationContext::getDefaultContext(), - "foo bar \r foo bar", vmime::charset("us-ascii"), "")); + VASSERT_TRUE( + "new line 1", + vmime::wordEncoder::isEncodingNeeded( + vmime::generationContext::getDefaultContext(), + "foo bar \n foo bar", + vmime::charset("us-ascii"), + "" + ) + ); + + VASSERT_TRUE( + "new line 2", + vmime::wordEncoder::isEncodingNeeded( + vmime::generationContext::getDefaultContext(), + "foo bar \r foo bar", + vmime::charset("us-ascii"), + "" + ) + ); } - void testGuessBestEncoding_QP() - { - VASSERT_EQ("1", vmime::wordEncoder::ENCODING_QP, - vmime::wordEncoder::guessBestEncoding("ASCII only buffer", vmime::charset("us-ascii"))); + void testGuessBestEncoding_QP() { + + VASSERT_EQ( + "1", + vmime::wordEncoder::ENCODING_QP, + vmime::wordEncoder::guessBestEncoding("ASCII only buffer", vmime::charset("us-ascii")) + ); } - void testGuessBestEncoding_B64() - { + void testGuessBestEncoding_B64() { + // >= 40% non-ASCII => Base64... - VASSERT_EQ("1", vmime::wordEncoder::ENCODING_B64, - vmime::wordEncoder::guessBestEncoding("xxxxx\xc3\xa0\xc3\xa0", vmime::charset("utf-8"))); + VASSERT_EQ( + "1", + vmime::wordEncoder::ENCODING_B64, + vmime::wordEncoder::guessBestEncoding("xxxxx\xc3\xa0\xc3\xa0", vmime::charset("utf-8")) + ); // ...else Quoted-Printable - VASSERT_EQ("2", vmime::wordEncoder::ENCODING_QP, - vmime::wordEncoder::guessBestEncoding("xxxxxx\xc3\xa0\xc3\xa0", vmime::charset("utf-8"))); + VASSERT_EQ( + "2", + vmime::wordEncoder::ENCODING_QP, + vmime::wordEncoder::guessBestEncoding("xxxxxx\xc3\xa0\xc3\xa0", vmime::charset("utf-8")) + ); } - void testEncodeQP_RFC2047() - { + void testEncodeQP_RFC2047() { + // When Quoted-Printable is used, it should be RFC-2047 QP encoding vmime::wordEncoder we( "buffer\xc3\xa0 foo_bar", vmime::charset("utf-8"), - vmime::wordEncoder::ENCODING_AUTO); + vmime::wordEncoder::ENCODING_AUTO + ); VASSERT_EQ("1", "buffer=C3=A0_foo=5Fbar", we.getNextChunk(100)); } diff --git a/tests/security/digest/md5Test.cpp b/tests/security/digest/md5Test.cpp index c7f0b521..ca6d3d45 100644 --- a/tests/security/digest/md5Test.cpp +++ b/tests/security/digest/md5Test.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -54,8 +54,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) // Test suites from RFC #1321 - void testRFC1321_1() - { + void testRFC1321_1() { + INIT_DIGEST(algo, "md5"); algo->update(""); @@ -64,8 +64,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("*", "d41d8cd98f00b204e9800998ecf8427e", algo->getHexDigest()); } - void testRFC1321_2() - { + void testRFC1321_2() { + INIT_DIGEST(algo, "md5"); algo->update("a"); @@ -74,8 +74,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("*", "0cc175b9c0f1b6a831c399e269772661", algo->getHexDigest()); } - void testRFC1321_3() - { + void testRFC1321_3() { + INIT_DIGEST(algo, "md5"); algo->update("abc"); @@ -84,8 +84,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("*", "900150983cd24fb0d6963f7d28e17f72", algo->getHexDigest()); } - void testRFC1321_4() - { + void testRFC1321_4() { + INIT_DIGEST(algo, "md5"); algo->update("message digest"); @@ -94,8 +94,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("*", "f96b697d7cb7938d525a2f31aaf161d0", algo->getHexDigest()); } - void testRFC1321_5() - { + void testRFC1321_5() { + INIT_DIGEST(algo, "md5"); algo->update("abcdefghijklmnopqrstuvwxyz"); @@ -104,8 +104,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("*", "c3fcd3d76192e4007dfb496cca67e13b", algo->getHexDigest()); } - void testRFC1321_6() - { + void testRFC1321_6() { + INIT_DIGEST(algo, "md5"); algo->update("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); @@ -114,8 +114,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("*", "d174ab98d277d9f5a5611c2c9f419d9f", algo->getHexDigest()); } - void testRFC1321_7() - { + void testRFC1321_7() { + INIT_DIGEST(algo, "md5"); algo->update("12345678901234567890123456789012345678901234567890123456789012345678901234567890"); @@ -124,8 +124,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("*", "57edf4a22be3c955ac49da2e2107b67a", algo->getHexDigest()); } - void testReset() - { + void testReset() { + INIT_DIGEST(algo, "md5"); algo->update("foo"); @@ -138,8 +138,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("*", "d41d8cd98f00b204e9800998ecf8427e", algo->getHexDigest()); // empty string } - void testUpdate1() - { + void testUpdate1() { + INIT_DIGEST(algo, "md5"); algo->update(""); @@ -148,8 +148,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("*", "d41d8cd98f00b204e9800998ecf8427e", algo->getHexDigest()); } - void testUpdate2() - { + void testUpdate2() { + INIT_DIGEST(algo, "md5"); algo->update("a"); @@ -159,8 +159,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("2", "0cc175b9c0f1b6a831c399e269772661", algo->getHexDigest()); } - void testUpdate3() - { + void testUpdate3() { + INIT_DIGEST(algo, "md5"); algo->update("ab"); @@ -170,8 +170,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("3", "900150983cd24fb0d6963f7d28e17f72", algo->getHexDigest()); } - void testUpdate4() - { + void testUpdate4() { + INIT_DIGEST(algo, "md5"); algo->update(""); @@ -183,8 +183,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("4", "f96b697d7cb7938d525a2f31aaf161d0", algo->getHexDigest()); } - void testUpdate5() - { + void testUpdate5() { + INIT_DIGEST(algo, "md5"); algo->update("abcd"); @@ -197,8 +197,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("5", "c3fcd3d76192e4007dfb496cca67e13b", algo->getHexDigest()); } - void testUpdate6() - { + void testUpdate6() { + INIT_DIGEST(algo, "md5"); algo->update("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012"); @@ -211,8 +211,8 @@ VMIME_TEST_SUITE_BEGIN(md5Test) VASSERT_EQ("6", "d174ab98d277d9f5a5611c2c9f419d9f", algo->getHexDigest()); } - void testUpdate7() - { + void testUpdate7() { + INIT_DIGEST(algo, "md5"); algo->update("12345678901234567890123456789"); @@ -226,4 +226,3 @@ VMIME_TEST_SUITE_BEGIN(md5Test) } VMIME_TEST_SUITE_END - diff --git a/tests/security/digest/sha1Test.cpp b/tests/security/digest/sha1Test.cpp index c6ce1e65..cbcd1cf0 100644 --- a/tests/security/digest/sha1Test.cpp +++ b/tests/security/digest/sha1Test.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -46,8 +46,8 @@ VMIME_TEST_SUITE_BEGIN(sha1Test) // Test suites from FIPS PUB 180-1 // http://www.itl.nist.gov/fipspubs/fip180-1.htm - void testFIPS180_1() - { + void testFIPS180_1() { + INIT_DIGEST(algo, "sha1"); algo->update("abc"); @@ -56,8 +56,8 @@ VMIME_TEST_SUITE_BEGIN(sha1Test) VASSERT_EQ("*", "a9993e364706816aba3e25717850c26c9cd0d89d", algo->getHexDigest()); } - void testFIPS180_2() - { + void testFIPS180_2() { + INIT_DIGEST(algo, "sha1"); algo->update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); @@ -66,14 +66,15 @@ VMIME_TEST_SUITE_BEGIN(sha1Test) VASSERT_EQ("*", "84983e441c3bd26ebaae4aa1f95129e5e54670f1", algo->getHexDigest()); } - void testFIPS180_3() - { + void testFIPS180_3() { + INIT_DIGEST(algo, "sha1"); vmime::byte_t* buffer = new vmime::byte_t[1000000]; - for (int i = 0 ; i < 1000000 ; ++i) + for (int i = 0 ; i < 1000000 ; ++i) { buffer[i] = 'a'; + } algo->update(buffer, 1000000); algo->finalize(); @@ -83,8 +84,8 @@ VMIME_TEST_SUITE_BEGIN(sha1Test) VASSERT_EQ("*", "34aa973cd4c4daa4f61eeb2bdbad27316534016f", algo->getHexDigest()); } - void testReset() - { + void testReset() { + INIT_DIGEST(algo, "sha1"); algo->update("ab"); @@ -97,8 +98,8 @@ VMIME_TEST_SUITE_BEGIN(sha1Test) VASSERT_EQ("*", "da39a3ee5e6b4b0d3255bfef95601890afd80709", algo->getHexDigest()); // empty string } - void testUpdate() - { + void testUpdate() { + INIT_DIGEST(algo, "sha1"); algo->update("a"); @@ -116,4 +117,3 @@ VMIME_TEST_SUITE_BEGIN(sha1Test) } VMIME_TEST_SUITE_END - diff --git a/tests/testRunner.cpp b/tests/testRunner.cpp index 08a06930..f1f13b25 100644 --- a/tests/testRunner.cpp +++ b/tests/testRunner.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -45,19 +45,19 @@ #include "vmime/platforms/posix/posixHandler.hpp" -class Clock -{ +class Clock { + public: - void reset() - { + void reset() { + struct timezone tz; gettimeofday(&m_start, &tz); } - double getDuration() const - { + double getDuration() const { + struct timeval tv; struct timezone tz; @@ -73,18 +73,19 @@ private: }; -class XmlTestListener : public CppUnit::TestListener -{ +class XmlTestListener : public CppUnit::TestListener { + public: XmlTestListener() - : m_doc("utf-8"), m_testElt(NULL) - { + : m_doc("utf-8"), + m_testElt(NULL) { + m_doc.setRootElement(new CppUnit::XmlElement("TestRun")); } - void startTest(CppUnit::Test* test) - { + void startTest(CppUnit::Test* test) { + m_testElt = new CppUnit::XmlElement("Test"); m_suiteElt.back()->addElement(m_testElt); @@ -93,16 +94,17 @@ public: m_chrono.reset(); } - void addFailure(const CppUnit::TestFailure& failure) - { + void addFailure(const CppUnit::TestFailure& failure) { + CppUnit::XmlElement* failElt = new CppUnit::XmlElement("Failure"); m_testElt->addElement(failElt); - failElt->addElement(new CppUnit::XmlElement("FailureType", - failure.isError() ? "Error" : "Assertion")); + failElt->addElement( + new CppUnit::XmlElement("FailureType", failure.isError() ? "Error" : "Assertion") + ); + + if (failure.sourceLine().isValid()) { - if (failure.sourceLine().isValid()) - { CppUnit::XmlElement* locElt = new CppUnit::XmlElement("Location"); failElt->addElement(locElt); @@ -116,8 +118,8 @@ public: exElt->addElement(new CppUnit::XmlElement("Message", failure.thrownException()->what())); } - void endTest(CppUnit::Test* /* test */) - { + void endTest(CppUnit::Test* /* test */) { + std::ostringstream ossTime; ossTime << (m_chrono.getDuration() * 1000.0); @@ -126,39 +128,42 @@ public: m_testElt = NULL; } - void startSuite(CppUnit::Test* suite) - { - if (suite->getName() == "All Tests") + void startSuite(CppUnit::Test* suite) { + + if (suite->getName() == "All Tests") { return; + } CppUnit::XmlElement* suiteElt = new CppUnit::XmlElement("Suite"); - if (m_suiteElt.size() == 0) + if (m_suiteElt.size() == 0) { m_doc.rootElement().addElement(suiteElt); - else + } else { m_suiteElt.back()->addElement(suiteElt); + } m_suiteElt.push_back(suiteElt); suiteElt->addElement(new CppUnit::XmlElement("Name", suite->getName())); } - void endSuite(CppUnit::Test* /* suite */) - { - if (m_suiteElt.size()) + void endSuite(CppUnit::Test* /* suite */) { + + if (m_suiteElt.size()) { m_suiteElt.pop_back(); + } } - void startTestRun(CppUnit::Test* /* test */, CppUnit::TestResult* /* eventManager */) - { + void startTestRun(CppUnit::Test* /* test */, CppUnit::TestResult* /* eventManager */) { + } - void endTestRun(CppUnit::Test* /* test */, CppUnit::TestResult* /* eventManager */) - { + void endTestRun(CppUnit::Test* /* test */, CppUnit::TestResult* /* eventManager */) { + } - void output(std::ostream& os) - { + void output(std::ostream& os) { + os << m_doc.toString(); } @@ -175,43 +180,46 @@ private: // see testUtils.hpp -std::vector & getTestModules() -{ +std::vector & getTestModules() { + static std::vector allModules; return allModules; } -void registerTestModule(const char* name_) -{ +void registerTestModule(const char* name_) { + std::vector & testModules = getTestModules(); std::string name(name_); - if (std::find(testModules.begin(), testModules.end(), name) == testModules.end()) + if (std::find(testModules.begin(), testModules.end(), name) == testModules.end()) { testModules.push_back(name); + } } -const std::string getNormalizedPath(const std::string& path) -{ +const std::string getNormalizedPath(const std::string& path) { + std::string res = path; - for (std::size_t i = 0, n = res.length() ; i < n ; ++i) - { - if (res[i] == '\\') + for (std::size_t i = 0, n = res.length() ; i < n ; ++i) { + + if (res[i] == '\\') { res[i] = '/'; + } } return res; } -const std::string getFileNameFromPath(const std::string& path) -{ +const std::string getFileNameFromPath(const std::string& path) { + const std::size_t pos = path.find_last_of('/'); - if (pos == std::string::npos) + if (pos == std::string::npos) { return ""; + } return path.substr(pos + 1); } @@ -220,8 +228,8 @@ const std::string getFileNameFromPath(const std::string& path) static char g_moduleNameBuffer[2048]; -const char* getTestModuleNameFromSourceFile(const char *path_) -{ +const char* getTestModuleNameFromSourceFile(const char *path_) { + static const std::string testRunnerPath(getNormalizedPath(__FILE__)); static const std::string testRunnerFileName(getFileNameFromPath(testRunnerPath)); @@ -244,29 +252,31 @@ const char* getTestModuleNameFromSourceFile(const char *path_) } -int main(int argc, char* argv[]) -{ +int main(int argc, char* argv[]) { + // Parse arguments bool xmlOutput = false; - for (int c = 1 ; c < argc ; ++c) - { + for (int c = 1 ; c < argc ; ++c) { + const std::string arg = argv[c]; - if (arg == "--xml") + if (arg == "--xml") { xmlOutput = true; + } } // Run the tests - if (xmlOutput) - { + if (xmlOutput) { + // Get the test suites from the registry and add them to the list of tests to run CppUnit::TestRunner runner; - for (unsigned int i = 0 ; i < getTestModules().size() ; ++i) - { - runner.addTest(CppUnit::TestFactoryRegistry:: - getRegistry(getTestModules()[i]).makeTest()); + for (unsigned int i = 0 ; i < getTestModules().size() ; ++i) { + + runner.addTest( + CppUnit::TestFactoryRegistry::getRegistry(getTestModules()[i]).makeTest() + ); } XmlTestListener xmlListener; @@ -283,9 +293,9 @@ int main(int argc, char* argv[]) // Return error code 1 if a test failed return result.wasSuccessful() ? 0 : 1; - } - else - { + + } else { + // Get the top level suite from the registry CppUnit::TextUi::TestRunner runner; runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); @@ -293,4 +303,3 @@ int main(int argc, char* argv[]) return runner.run() ? 0 : 1; } } - diff --git a/tests/testUtils.cpp b/tests/testUtils.cpp index 6e31d93f..ae755474 100644 --- a/tests/testUtils.cpp +++ b/tests/testUtils.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -36,8 +36,8 @@ // testSocket -void testSocket::connect(const vmime::string& address, const vmime::port_t port) -{ +void testSocket::connect(const vmime::string& address, const vmime::port_t port) { + m_address = address; m_port = port; m_connected = true; @@ -46,96 +46,96 @@ void testSocket::connect(const vmime::string& address, const vmime::port_t port) } -void testSocket::disconnect() -{ +void testSocket::disconnect() { + m_address.clear(); m_port = 0; m_connected = false; } -bool testSocket::isConnected() const -{ +bool testSocket::isConnected() const { + return m_connected; } -vmime::size_t testSocket::getBlockSize() const -{ +vmime::size_t testSocket::getBlockSize() const { + return 16384; } -unsigned int testSocket::getStatus() const -{ +unsigned int testSocket::getStatus() const { + return 0; } -const vmime::string testSocket::getPeerName() const -{ +const vmime::string testSocket::getPeerName() const { + return "test.vmime.org"; } -const vmime::string testSocket::getPeerAddress() const -{ +const vmime::string testSocket::getPeerAddress() const { + return "127.0.0.1"; } -vmime::shared_ptr testSocket::getTimeoutHandler() -{ +vmime::shared_ptr testSocket::getTimeoutHandler() { + return vmime::null; } -void testSocket::setTracer(const vmime::shared_ptr & /* tracer */) -{ +void testSocket::setTracer(const vmime::shared_ptr & /* tracer */) { + } -vmime::shared_ptr testSocket::getTracer() -{ +vmime::shared_ptr testSocket::getTracer() { + return vmime::null; } -bool testSocket::waitForRead(const int /* msecs */) -{ +bool testSocket::waitForRead(const int /* msecs */) { + return true; } -bool testSocket::waitForWrite(const int /* msecs */) -{ +bool testSocket::waitForWrite(const int /* msecs */) { + return true; } -void testSocket::receive(vmime::string& buffer) -{ +void testSocket::receive(vmime::string& buffer) { + buffer = m_inBuffer; m_inBuffer.clear(); } -void testSocket::send(const vmime::string& buffer) -{ +void testSocket::send(const vmime::string& buffer) { + m_outBuffer += buffer; onDataReceived(); } -void testSocket::send(const char* str) -{ +void testSocket::send(const char* str) { + sendRaw(reinterpret_cast (str), strlen(str)); } -vmime::size_t testSocket::receiveRaw(vmime::byte_t* buffer, const size_t count) -{ +vmime::size_t testSocket::receiveRaw(vmime::byte_t* buffer, const size_t count) { + const size_t n = std::min(count, static_cast (m_inBuffer.size())); std::copy(m_inBuffer.begin(), m_inBuffer.begin() + n, buffer); @@ -145,21 +145,21 @@ vmime::size_t testSocket::receiveRaw(vmime::byte_t* buffer, const size_t count) } -void testSocket::sendRaw(const vmime::byte_t* buffer, const size_t count) -{ +void testSocket::sendRaw(const vmime::byte_t* buffer, const size_t count) { + send(vmime::utility::stringUtils::makeStringFromBytes(buffer, count)); } -vmime::size_t testSocket::sendRawNonBlocking(const vmime::byte_t* buffer, const size_t count) -{ +vmime::size_t testSocket::sendRawNonBlocking(const vmime::byte_t* buffer, const size_t count) { + sendRaw(buffer, count); return count; } -void testSocket::localSend(const vmime::string& buffer) -{ +void testSocket::localSend(const vmime::string& buffer) { + m_inBuffer += buffer; #if DEBUG_SOCKET_IN_OUT @@ -169,23 +169,24 @@ void testSocket::localSend(const vmime::string& buffer) } -void testSocket::localReceive(vmime::string& buffer) -{ +void testSocket::localReceive(vmime::string& buffer) { + buffer = m_outBuffer; m_outBuffer.clear(); } -bool testSocket::localReceiveLine(vmime::string& line) -{ +bool testSocket::localReceiveLine(vmime::string& line) { + vmime::size_t eol; - if ((eol = m_outBuffer.find('\n')) != vmime::string::npos) - { + if ((eol = m_outBuffer.find('\n')) != vmime::string::npos) { + line = vmime::string(m_outBuffer.begin(), m_outBuffer.begin() + eol); - if (!line.empty() && line[line.length() - 1] == '\r') + if (!line.empty() && line[line.length() - 1] == '\r') { line.erase(line.end() - 1, line.end()); + } m_outBuffer.erase(m_outBuffer.begin(), m_outBuffer.begin() + eol + 1); @@ -196,14 +197,15 @@ bool testSocket::localReceiveLine(vmime::string& line) } -vmime::size_t testSocket::localReceiveRaw(vmime::byte_t* buffer, const size_t count) -{ +vmime::size_t testSocket::localReceiveRaw(vmime::byte_t* buffer, const size_t count) { + const size_t received = std::min(count, static_cast (m_outBuffer.size())); - if (received != 0) - { - if (buffer != NULL) + if (received != 0) { + + if (buffer) { std::copy(m_outBuffer.begin(), m_outBuffer.begin() + received, buffer); + } m_outBuffer.erase(m_outBuffer.begin(), m_outBuffer.begin() + received); } @@ -212,22 +214,22 @@ vmime::size_t testSocket::localReceiveRaw(vmime::byte_t* buffer, const size_t co } -void testSocket::onDataReceived() -{ +void testSocket::onDataReceived() { + // Override } -void testSocket::onConnected() -{ +void testSocket::onConnected() { + // Override } // lineBasedTestSocket -void lineBasedTestSocket::onDataReceived() -{ +void lineBasedTestSocket::onDataReceived() { + vmime::string chunk; localReceive(chunk); @@ -235,12 +237,13 @@ void lineBasedTestSocket::onDataReceived() vmime::size_t eol; - while ((eol = m_buffer.find('\n')) != vmime::string::npos) - { + while ((eol = m_buffer.find('\n')) != vmime::string::npos) { + vmime::string line(std::string(m_buffer.begin(), m_buffer.begin() + eol)); - if (!line.empty() && line[line.length() - 1] == '\r') + if (!line.empty() && line[line.length() - 1] == '\r') { line.erase(line.end() - 1, line.end()); + } #if DEBUG_SOCKET_IN_OUT std::cout << "< " << vmime::utility::stringUtils::trim(line) << std::endl; @@ -250,20 +253,22 @@ void lineBasedTestSocket::onDataReceived() m_buffer.erase(m_buffer.begin(), m_buffer.begin() + eol + 1); } - while (!m_lines.empty()) + while (!m_lines.empty()) { processCommand(); + } } -const vmime::string lineBasedTestSocket::getNextLine() -{ +const vmime::string lineBasedTestSocket::getNextLine() { + const vmime::string line = m_lines.front(); m_lines.erase(m_lines.begin(), m_lines.begin() + 1); return line; } -bool lineBasedTestSocket::haveMoreLines() const -{ + +bool lineBasedTestSocket::haveMoreLines() const { + return !m_lines.empty(); } @@ -271,47 +276,48 @@ bool lineBasedTestSocket::haveMoreLines() const // testTimeoutHandler testTimeoutHandler::testTimeoutHandler(const unsigned long delay) - : m_delay(delay), m_start(0) -{ + : m_delay(delay), + m_start(0) { + } -bool testTimeoutHandler::isTimeOut() -{ +bool testTimeoutHandler::isTimeOut() { + return (vmime::platform::getHandler()->getUnixTime() - m_start) >= m_delay; } -void testTimeoutHandler::resetTimeOut() -{ +void testTimeoutHandler::resetTimeOut() { + m_start = vmime::platform::getHandler()->getUnixTime(); } -bool testTimeoutHandler::handleTimeOut() -{ +bool testTimeoutHandler::handleTimeOut() { + return false; } // testTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory -vmime::shared_ptr testTimeoutHandlerFactory::create() -{ +vmime::shared_ptr testTimeoutHandlerFactory::create() { + return vmime::make_shared (); } // Exception helper -std::ostream& operator<<(std::ostream& os, const vmime::exception& e) -{ +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 (&e)) - { + if (dynamic_cast (&e)) { + const vmime::exceptions::command_error& cee = dynamic_cast (e); @@ -319,32 +325,32 @@ std::ostream& operator<<(std::ostream& os, const vmime::exception& e) os << " response = " << cee.response() << std::endl; } - if (dynamic_cast (&e)) - { + if (dynamic_cast (&e)) { + const vmime::exceptions::invalid_response& ir = dynamic_cast (e); os << " response = " << ir.response() << std::endl; } - if (dynamic_cast (&e)) - { + if (dynamic_cast (&e)) { + const vmime::exceptions::connection_greeting_error& cgee = dynamic_cast (e); os << " response = " << cgee.response() << std::endl; } - if (dynamic_cast (&e)) - { + if (dynamic_cast (&e)) { + const vmime::exceptions::authentication_error& aee = dynamic_cast (e); os << " response = " << aee.response() << std::endl; } - if (dynamic_cast (&e)) - { + if (dynamic_cast (&e)) { + const vmime::exceptions::filesystem_exception& fse = dynamic_cast (e); @@ -352,29 +358,29 @@ std::ostream& operator<<(std::ostream& os, const vmime::exception& e) getFileSystemFactory()->pathToString(fse.path()) << std::endl; } - if (e.other() != NULL) + if (e.other()) { os << *e.other(); + } return os; } -const vmime::string toHex(const vmime::string str) -{ +const vmime::string toHex(const vmime::string str) { + static const char hexChars[] = "0123456789abcdef"; vmime::string res = "\n"; - for (size_t i = 0 ; i < str.length() ; i += 16) - { - size_t r = std::min - (static_cast (16), str.length() - i); + for (size_t i = 0 ; i < str.length() ; i += 16) { + + size_t r = std::min(static_cast (16), str.length() - i); vmime::string hex; vmime::string chr; - for (size_t j = 0 ; j < r ; ++j) - { + for (size_t j = 0 ; j < r ; ++j) { + const unsigned char c = str[i + j]; hex += hexChars[c / 16]; @@ -387,8 +393,9 @@ const vmime::string toHex(const vmime::string str) chr += '.'; } - for (size_t j = r ; j < 16 ; ++j) + for (size_t j = r ; j < 16 ; ++j) { hex += " "; + } res += hex + " " + chr + "\n"; } diff --git a/tests/testUtils.hpp b/tests/testUtils.hpp index d17c38b2..e6bf1eee 100644 --- a/tests/testUtils.hpp +++ b/tests/testUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -88,123 +88,134 @@ #define VMIME_TEST(name) CPPUNIT_TEST(name); -namespace CppUnit -{ +namespace CppUnit { + // Work-around for comparing 'std::string' against 'char*' - inline void assertEquals(const char* expected, const std::string actual, - SourceLine sourceLine, const std::string &message) - { + inline void assertEquals( + const char* expected, + const std::string actual, + SourceLine sourceLine, + const std::string &message + ) { + assertEquals(std::string(expected), actual, sourceLine, message); } template - void assertEquals(const X expected, const Y actual, - SourceLine sourceLine, const std::string &message) - { + void assertEquals( + const X expected, + const Y actual, + SourceLine sourceLine, + const std::string &message + ) { + assertEquals(static_cast (expected), actual, sourceLine, message); } } -namespace std -{ +namespace std { -inline std::ostream& operator<<(std::ostream& os, const vmime::charset& ch) -{ +inline std::ostream& operator<<(std::ostream& os, const vmime::charset& ch) { + os << "[charset: " << ch.getName() << "]"; - return (os); + return os; } -inline std::ostream& operator<<(std::ostream& os, const vmime::word& w) -{ +inline std::ostream& operator<<(std::ostream& os, const vmime::word& w) { + os << "[word: charset=" << w.getCharset().getName() << ", buffer=" << w.getBuffer(); - if (!w.getLanguage().empty()) + if (!w.getLanguage().empty()) { os << ", lang=" << w.getLanguage(); + } os << "]"; - return (os); + return os; } -inline std::ostream& operator<<(std::ostream& os, const vmime::text& txt) -{ +inline std::ostream& operator<<(std::ostream& os, const vmime::text& txt) { + os << "[text: ["; - for (size_t i = 0 ; i < txt.getWordCount() ; ++i) - { + for (size_t i = 0 ; i < txt.getWordCount() ; ++i) { + const vmime::word& w = *txt.getWordAt(i); - if (i != 0) + if (i != 0) { os << ","; + } os << w; } os << "]]"; - return (os); + return os; } -inline std::ostream& operator<<(std::ostream& os, const vmime::emailAddress& email) -{ +inline std::ostream& operator<<(std::ostream& os, const vmime::emailAddress& email) { + os << email.generate(); - return (os); + return os; } -inline std::ostream& operator<<(std::ostream& os, const vmime::mailbox& mbox) -{ +inline std::ostream& operator<<(std::ostream& os, const vmime::mailbox& mbox) { + os << "[mailbox: name=" << mbox.getName() << ", email=" << mbox.getEmail() << "]"; - return (os); + return os; } -inline std::ostream& operator<<(std::ostream& os, const vmime::mailboxGroup& group) -{ +inline std::ostream& operator<<(std::ostream& os, const vmime::mailboxGroup& group) { + os << "[mailbox-group: name=" << group.getName() << ", list=["; - for (size_t i = 0 ; i < group.getMailboxCount() ; ++i) - { - if (i != 0) + for (size_t i = 0 ; i < group.getMailboxCount() ; ++i) { + + if (i != 0) { os << ","; + } os << *group.getMailboxAt(i); } os << "]]"; - return (os); + return os; } -inline std::ostream& operator<<(std::ostream& os, const vmime::addressList& list) -{ +inline std::ostream& operator<<(std::ostream& os, const vmime::addressList& list) { + os << "[address-list: ["; - for (size_t i = 0 ; i < list.getAddressCount() ; ++i) - { + for (size_t i = 0 ; i < list.getAddressCount() ; ++i) { + const vmime::address& addr = *list.getAddressAt(i); - if (i != 0) + if (i != 0) { os << ","; + } + + if (addr.isGroup()) { - if (addr.isGroup()) - { const vmime::mailboxGroup& group = dynamic_cast (addr); os << group; - } - else - { + + } else { + const vmime::mailbox& mbox = dynamic_cast (addr); @@ -214,25 +225,25 @@ inline std::ostream& operator<<(std::ostream& os, const vmime::addressList& list os << "]]"; - return (os); + return os; } -inline std::ostream& operator<<(std::ostream& os, const vmime::datetime& d) -{ +inline std::ostream& operator<<(std::ostream& os, const vmime::datetime& d) { + os << "[datetime: " << d.getYear() << "/" << d.getMonth() << "/" << d.getDay(); os << " " << d.getHour() << ":" << d.getMinute() << ":" << d.getSecond(); os << " #" << d.getZone() << "]"; - return (os); + return os; } -inline std::ostream& operator<<(std::ostream& os, const vmime::encoding& enc) -{ +inline std::ostream& operator<<(std::ostream& os, const vmime::encoding& enc) { + os << enc.generate(); - return (os); + return os; } @@ -246,8 +257,8 @@ inline std::ostream& operator<<(std::ostream& os, const vmime::encoding& enc) // and send(). Server reads incoming data with localReceive() and sends data // to client with localSend(). -class testSocket : public vmime::net::socket -{ +class testSocket : public vmime::net::socket { + public: void connect(const vmime::string& address, const vmime::port_t port); @@ -327,24 +338,26 @@ private: template -class testSocketFactory : public vmime::net::socketFactory -{ +class testSocketFactory : public vmime::net::socketFactory { + public: - vmime::shared_ptr create() - { + vmime::shared_ptr create() { + return vmime::make_shared (); } - vmime::shared_ptr create(const vmime::shared_ptr & /* th */) - { + vmime::shared_ptr create( + const vmime::shared_ptr & /* th */ + ) { + return vmime::make_shared (); } }; -class lineBasedTestSocket : public testSocket -{ +class lineBasedTestSocket : public testSocket { + public: void onDataReceived(); @@ -361,8 +374,8 @@ private: }; -class testTimeoutHandler : public vmime::net::timeoutHandler -{ +class testTimeoutHandler : public vmime::net::timeoutHandler { + public: testTimeoutHandler(const unsigned long delay = 3); @@ -378,8 +391,8 @@ private: }; -class testTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory -{ +class testTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory { + public: vmime::shared_ptr create(); diff --git a/tests/utility/datetimeUtilsTest.cpp b/tests/utility/datetimeUtilsTest.cpp index 1e21c5f9..77ce2425 100644 --- a/tests/utility/datetimeUtilsTest.cpp +++ b/tests/utility/datetimeUtilsTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,8 +43,8 @@ VMIME_TEST_SUITE_BEGIN(datetimeUtilsTest) typedef vmime::utility::datetimeUtils datetimeUtils; - void testIsLeapYear() - { + void testIsLeapYear() { + VASSERT_EQ("1", false, datetimeUtils::isLeapYear(1999)); VASSERT_EQ("2", false, datetimeUtils::isLeapYear(1800)); VASSERT_EQ("3", false, datetimeUtils::isLeapYear(1900)); @@ -55,8 +55,8 @@ VMIME_TEST_SUITE_BEGIN(datetimeUtilsTest) VASSERT_EQ("7", true, datetimeUtils::isLeapYear(2000)); } - void testGetDaysInMonth() - { + void testGetDaysInMonth() { + VASSERT_EQ("1", 31, datetimeUtils::getDaysInMonth(2006, 1)); VASSERT_EQ("2", 28, datetimeUtils::getDaysInMonth(2006, 2)); VASSERT_EQ("3", 31, datetimeUtils::getDaysInMonth(2006, 3)); @@ -71,8 +71,8 @@ VMIME_TEST_SUITE_BEGIN(datetimeUtilsTest) VASSERT_EQ("12", 31, datetimeUtils::getDaysInMonth(2006, 12)); } - void testGetDaysInMonthLeapYear() - { + void testGetDaysInMonthLeapYear() { + VASSERT_EQ("1", 31, datetimeUtils::getDaysInMonth(2004, 1)); VASSERT_EQ("2", 29, datetimeUtils::getDaysInMonth(2004, 2)); VASSERT_EQ("3", 31, datetimeUtils::getDaysInMonth(2004, 3)); @@ -87,13 +87,11 @@ VMIME_TEST_SUITE_BEGIN(datetimeUtilsTest) VASSERT_EQ("12", 31, datetimeUtils::getDaysInMonth(2004, 12)); } - void testToUniversalTime() - { - const vmime::datetime local - (2005, 12, 2, 12, 34, 56, -789); + void testToUniversalTime() { - const vmime::datetime gmt = - datetimeUtils::toUniversalTime(local); + const vmime::datetime local(2005, 12, 2, 12, 34, 56, -789); + + const vmime::datetime gmt = datetimeUtils::toUniversalTime(local); // 789 is 13 hours, 9 minutes later VASSERT_EQ("1", 2005, gmt.getYear()); @@ -105,13 +103,11 @@ VMIME_TEST_SUITE_BEGIN(datetimeUtilsTest) VASSERT_EQ("7", 0, gmt.getZone()); } - void testToLocalTime() - { - const vmime::datetime date - (2005, 12, 2, 12, 34, 56, -120); // GMT-2 + void testToLocalTime() { - const vmime::datetime local = - datetimeUtils::toLocalTime(date, 120); // GMT+2 + const vmime::datetime date(2005, 12, 2, 12, 34, 56, -120); // GMT-2 + + const vmime::datetime local = datetimeUtils::toLocalTime(date, 120); // GMT+2 VASSERT_EQ("1", 2005, local.getYear()); VASSERT_EQ("2", 12, local.getMonth()); @@ -122,8 +118,8 @@ VMIME_TEST_SUITE_BEGIN(datetimeUtilsTest) VASSERT_EQ("7", 120, local.getZone()); } - void testGetDayOfWeek() - { + void testGetDayOfWeek() { + VASSERT_EQ("1", vmime::datetime::WEDNESDAY, datetimeUtils::getDayOfWeek(1969, 12, 31)); VASSERT_EQ("2", vmime::datetime::FRIDAY, datetimeUtils::getDayOfWeek(1976, 4, 9)); VASSERT_EQ("3", vmime::datetime::TUESDAY, datetimeUtils::getDayOfWeek(1987, 6, 23)); @@ -135,8 +131,8 @@ VMIME_TEST_SUITE_BEGIN(datetimeUtilsTest) VASSERT_EQ("9", vmime::datetime::FRIDAY, datetimeUtils::getDayOfWeek(2027, 3, 12)); } - void testGetWeekOfYear() - { + void testGetWeekOfYear() { + VASSERT_EQ("1.1", 52, datetimeUtils::getWeekOfYear(2003, 12, 27)); VASSERT_EQ("1.2", 52, datetimeUtils::getWeekOfYear(2003, 12, 28)); VASSERT_EQ("1.3", 1, datetimeUtils::getWeekOfYear(2003, 12, 29, true)); @@ -159,4 +155,3 @@ VMIME_TEST_SUITE_BEGIN(datetimeUtilsTest) } VMIME_TEST_SUITE_END - diff --git a/tests/utility/encoder/b64EncoderTest.cpp b/tests/utility/encoder/b64EncoderTest.cpp index fa6fd766..36fa61ac 100644 --- a/tests/utility/encoder/b64EncoderTest.cpp +++ b/tests/utility/encoder/b64EncoderTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,10 +33,10 @@ VMIME_TEST_SUITE_BEGIN(b64EncoderTest) VMIME_TEST_LIST_END - void testBase64() - { - static const vmime::string testSuites[] = - { + void testBase64() { + + static const vmime::string testSuites[] = { + // Test 1 "", @@ -96,8 +96,8 @@ VMIME_TEST_SUITE_BEGIN(b64EncoderTest) }; - for (unsigned int i = 0 ; i < sizeof(testSuites) / sizeof(testSuites[0]) / 2 ; ++i) - { + for (unsigned int i = 0 ; i < sizeof(testSuites) / sizeof(testSuites[0]) / 2 ; ++i) { + const vmime::string decoded = testSuites[i * 2]; const vmime::string encoded = testSuites[i * 2 + 1]; @@ -111,25 +111,36 @@ VMIME_TEST_SUITE_BEGIN(b64EncoderTest) VASSERT_EQ(oss.str() + "decoding", decoded, decode("base64", encoded)); // Multiple and successive encoding/decoding - VASSERT_EQ(oss.str() + "multiple1", decoded, + VASSERT_EQ( + oss.str() + "multiple1", + decoded, decode("base64", - encode("base64", decoded))); + encode("base64", decoded)) + ); - VASSERT_EQ(oss.str() + "multiple2", decoded, + VASSERT_EQ( + oss.str() + "multiple2", + decoded, decode("base64", decode("base64", encode("base64", - encode("base64", decoded))))); + encode("base64", decoded)))) + ); - VASSERT_EQ(oss.str() + "multiple3", decoded, + VASSERT_EQ( + oss.str() + "multiple3", + decoded, decode("base64", decode("base64", decode("base64", encode("base64", encode("base64", - encode("base64", decoded))))))); + encode("base64", decoded)))))) + ); - VASSERT_EQ(oss.str() + "multiple4", decoded, + VASSERT_EQ( + oss.str() + "multiple4", + decoded, decode("base64", decode("base64", decode("base64", @@ -137,17 +148,21 @@ VMIME_TEST_SUITE_BEGIN(b64EncoderTest) encode("base64", encode("base64", encode("base64", - encode("base64", decoded))))))))); + encode("base64", decoded)))))))) + ); - VASSERT(oss.str() + "encoded size", + VASSERT( + oss.str() + "encoded size", getEncoder("base64")->getEncodedSize(decoded.length()) - >= encode("base64", decoded).length()); + >= encode("base64", decoded).length() + ); - VASSERT(oss.str() + "decoded size", + VASSERT( + oss.str() + "decoded size", getEncoder("base64")->getDecodedSize(encoded.length()) - >= decode("base64", encoded).length()); + >= decode("base64", encoded).length() + ); } } VMIME_TEST_SUITE_END - diff --git a/tests/utility/encoder/encoderFactoryTest.cpp b/tests/utility/encoder/encoderFactoryTest.cpp index ce50dc6a..916706c9 100644 --- a/tests/utility/encoder/encoderFactoryTest.cpp +++ b/tests/utility/encoder/encoderFactoryTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,8 +35,8 @@ VMIME_TEST_SUITE_BEGIN(encoderFactoryTest) VMIME_TEST_LIST_END - void testNoDefaultEncoder() - { + void testNoDefaultEncoder() { + vmime::shared_ptr ef = vmime::utility::encoder::encoderFactory::getInstance(); @@ -47,8 +47,8 @@ VMIME_TEST_SUITE_BEGIN(encoderFactoryTest) ); } - void testDefaultEncoder() - { + void testDefaultEncoder() { + vmime::shared_ptr ef = vmime::utility::encoder::encoderFactory::getInstance(); diff --git a/tests/utility/encoder/encoderTestUtils.hpp b/tests/utility/encoder/encoderTestUtils.hpp index d74c4709..cc1141c7 100644 --- a/tests/utility/encoder/encoderTestUtils.hpp +++ b/tests/utility/encoder/encoderTestUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -23,25 +23,32 @@ // Helper function to obtain an encoder given its name -static vmime::shared_ptr getEncoder(const vmime::string& name, - int maxLineLength = 0, const vmime::propertySet props = vmime::propertySet()) -{ +static vmime::shared_ptr getEncoder( + const vmime::string& name, + int maxLineLength = 0, + const vmime::propertySet props = vmime::propertySet() +) { + vmime::shared_ptr enc = vmime::utility::encoder::encoderFactory::getInstance()->create(name); enc->getProperties() = props; - if (maxLineLength != 0) + if (maxLineLength != 0) { enc->getProperties()["maxlinelength"] = maxLineLength; + } return enc; } // Encoding helper function -static const vmime::string encode(const vmime::string& name, const vmime::string& in, - int maxLineLength = 0, const vmime::propertySet props = vmime::propertySet()) -{ +static const vmime::string encode( + const vmime::string& name, const vmime::string& in, + int maxLineLength = 0, + const vmime::propertySet props = vmime::propertySet() +) { + vmime::shared_ptr enc = getEncoder(name, maxLineLength, props); vmime::utility::inputStreamStringAdapter vin(in); @@ -56,8 +63,12 @@ static const vmime::string encode(const vmime::string& name, const vmime::string // Decoding helper function -static const vmime::string decode(const vmime::string& name, const vmime::string& in, int maxLineLength = 0) -{ +static const vmime::string decode( + const vmime::string& name, + const vmime::string& in, + int maxLineLength = 0 +) { + vmime::shared_ptr enc = getEncoder(name, maxLineLength); vmime::utility::inputStreamStringAdapter vin(in); diff --git a/tests/utility/encoder/qpEncoderTest.cpp b/tests/utility/encoder/qpEncoderTest.cpp index e7d1bcd2..e4769475 100644 --- a/tests/utility/encoder/qpEncoderTest.cpp +++ b/tests/utility/encoder/qpEncoderTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -38,10 +38,10 @@ VMIME_TEST_SUITE_BEGIN(qpEncoderTest) VMIME_TEST_LIST_END - void testQuotedPrintable() - { - static const vmime::string testSuites[] = - { + void testQuotedPrintable() { + + static const vmime::string testSuites[] = { + // Test 1 "", @@ -94,8 +94,8 @@ VMIME_TEST_SUITE_BEGIN(qpEncoderTest) }; - for (unsigned int i = 0 ; i < sizeof(testSuites) / sizeof(testSuites[0]) / 2 ; ++i) - { + for (unsigned int i = 0 ; i < sizeof(testSuites) / sizeof(testSuites[0]) / 2 ; ++i) { + const vmime::string decoded = testSuites[i * 2]; const vmime::string encoded = testSuites[i * 2 + 1]; @@ -109,25 +109,36 @@ VMIME_TEST_SUITE_BEGIN(qpEncoderTest) VASSERT_EQ(oss.str() + "decoding", decoded, decode("quoted-printable", encoded, 74)); // Multiple and successive encoding/decoding - VASSERT_EQ(oss.str() + "multiple1", decoded, + VASSERT_EQ( + oss.str() + "multiple1", + decoded, decode("quoted-printable", - encode("quoted-printable", decoded))); + encode("quoted-printable", decoded)) + ); - VASSERT_EQ(oss.str() + "multiple2", decoded, + VASSERT_EQ( + oss.str() + "multiple2", + decoded, decode("quoted-printable", decode("quoted-printable", encode("quoted-printable", - encode("quoted-printable", decoded))))); + encode("quoted-printable", decoded)))) + ); - VASSERT_EQ(oss.str() + "multiple3", decoded, + VASSERT_EQ( + oss.str() + "multiple3", + decoded, decode("quoted-printable", decode("quoted-printable", decode("quoted-printable", encode("quoted-printable", encode("quoted-printable", - encode("quoted-printable", decoded))))))); + encode("quoted-printable", decoded)))))) + ); - VASSERT_EQ(oss.str() + "multiple4", decoded, + VASSERT_EQ( + oss.str() + "multiple4", + decoded, decode("quoted-printable", decode("quoted-printable", decode("quoted-printable", @@ -135,38 +146,50 @@ VMIME_TEST_SUITE_BEGIN(qpEncoderTest) encode("quoted-printable", encode("quoted-printable", encode("quoted-printable", - encode("quoted-printable", decoded))))))))); + encode("quoted-printable", decoded)))))))) + ); - VASSERT(oss.str() + "encoded size", + VASSERT( + oss.str() + "encoded size", getEncoder("quoted-printable")->getEncodedSize(decoded.length()) - >= encode("quoted-printable", decoded).length()); + >= encode("quoted-printable", decoded).length() + ); - VASSERT(oss.str() + "decoded size", + VASSERT( + oss.str() + "decoded size", getEncoder("quoted-printable")->getDecodedSize(encoded.length()) - >= decode("quoted-printable", encoded).length()); + >= decode("quoted-printable", encoded).length() + ); } } /** Tests Soft Line Breaks (RFC-2047/6.7(5). */ - void testQuotedPrintable_SoftLineBreaks() - { - VASSERT_EQ("1", "Now's the time=\r\n" - " for all folk =\r\n" - "to come to the=\r\n" - " aid of their =\r\n" - "country.", - encode("quoted-printable", "Now's the time for all folk " - "to come to the aid of their country.", 15)); + void testQuotedPrintable_SoftLineBreaks() { + + VASSERT_EQ( + "1", + "Now's the time=\r\n" + " for all folk =\r\n" + "to come to the=\r\n" + " aid of their =\r\n" + "country.", + encode( + "quoted-printable", + "Now's the time for all folk " + "to come to the aid of their country.", + 15 + ) + ); } - void testQuotedPrintable_HardLineBreakEncode() - { + void testQuotedPrintable_HardLineBreakEncode() { + const std::string data = "If you believe that truth=beauty," " then surely mathematics\r\nis the most" " beautiful branch of philosophy."; - const std::string expected = + const std::string expected = "If you believe that truth=3Dbeauty=\r\n" ", then surely mathematics\r\n" "is the most beautiful branch of ph=\r\n" @@ -178,14 +201,14 @@ VMIME_TEST_SUITE_BEGIN(qpEncoderTest) VASSERT_EQ("1", expected, encode("quoted-printable", data, 35, encProps)); } - void testQuotedPrintable_HardLineBreakDecode() - { + void testQuotedPrintable_HardLineBreakDecode() { + const std::string expected = "If you believe that truth=beauty," " then surely mathematics\r\nis the most" " beautiful branch of philosophy."; - const std::string data = + const std::string data = "If you believe that truth=3Dbeauty=\r\n" ", then surely mathematics\r\n" "is the most beautiful branch of ph=\r\n" @@ -197,23 +220,29 @@ VMIME_TEST_SUITE_BEGIN(qpEncoderTest) /** In text mode, ensure line breaks in QP-encoded text are represented * by a CRLF sequence, as per RFC-2047/6.7(4). */ - void testQuotedPrintable_CRLF() - { + void testQuotedPrintable_CRLF() { + vmime::propertySet encProps; // in "text" mode encProps["text"] = true; - VASSERT_EQ("text", "line1\r\nline2", - encode("quoted-printable", "line1\r\nline2", 80, encProps)); + VASSERT_EQ( + "text", + "line1\r\nline2", + encode("quoted-printable", "line1\r\nline2", 80, encProps) + ); // in "binary" mode encProps["text"] = false; - VASSERT_EQ("binary", "line1=0D=0Aline2", - encode("quoted-printable", "line1\r\nline2", 80, encProps)); + VASSERT_EQ( + "binary", + "line1=0D=0Aline2", + encode("quoted-printable", "line1\r\nline2", 80, encProps) + ); } - void testQuotedPrintable_RFC2047() - { + void testQuotedPrintable_RFC2047() { + /* * The RFC (http://tools.ietf.org/html/rfc2047#section-5) says: * @@ -243,6 +272,4 @@ VMIME_TEST_SUITE_BEGIN(qpEncoderTest) VASSERT_EQ("especials.12", "=22", encode("quoted-printable", "\"", 10, encProps)); } - // TODO: UUEncode - VMIME_TEST_SUITE_END diff --git a/tests/utility/filteredStreamTest.cpp b/tests/utility/filteredStreamTest.cpp index cedfab2a..ff3fb6a3 100644 --- a/tests/utility/filteredStreamTest.cpp +++ b/tests/utility/filteredStreamTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,8 +41,8 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) VMIME_TEST_LIST_END - class chunkInputStream : public vmime::utility::inputStream - { + class chunkInputStream : public vmime::utility::inputStream { + private: std::vector m_chunks; @@ -57,10 +57,11 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) bool eof() const { return (m_index >= m_chunks.size()); } void reset() { m_index = 0; } - vmime::size_t read(vmime::byte_t* const data, const vmime::size_t /* count */) - { - if (eof()) + vmime::size_t read(vmime::byte_t* const data, const vmime::size_t /* count */) { + + if (eof()) { return 0; + } const std::string chunk = m_chunks[m_index]; @@ -73,37 +74,41 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) return chunk.length(); } - vmime::size_t skip(const vmime::size_t /* count */) - { + vmime::size_t skip(const vmime::size_t /* count */) { + // Not supported return 0; } }; - const std::string readWhole(vmime::utility::inputStream& is) - { + const std::string readWhole(vmime::utility::inputStream& is) { + vmime::byte_t buffer[256]; std::string whole; - while (!is.eof()) - { + while (!is.eof()) { + const vmime::size_t read = is.read(buffer, sizeof(buffer)); whole += vmime::utility::stringUtils::makeStringFromBytes(buffer, read); } - return (whole); + return whole; } // dotFilteredInputStream - void testDotFilteredInputStreamHelper - (const std::string& number, const std::string& expected, - const std::string& c1, const std::string& c2 = "", - const std::string& c3 = "", const std::string& c4 = "") - { + void testDotFilteredInputStreamHelper( + const std::string& number, + const std::string& expected, + const std::string& c1, + const std::string& c2 = "", + const std::string& c3 = "", + const std::string& c4 = "" + ) { + chunkInputStream cis; cis.addChunk(c1); if (!c2.empty()) cis.addChunk(c2); @@ -120,8 +125,8 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) VASSERT_EQ(number, expected, oss.str()); } - void testDotFilteredInputStream() - { + void testDotFilteredInputStream() { + testDotFilteredInputStreamHelper("1", "foo\n.bar", "foo\n..bar"); testDotFilteredInputStreamHelper("2", "foo\n.bar", "foo\n", "..bar"); testDotFilteredInputStreamHelper("3", "foo\n.bar", "foo\n.", ".bar"); @@ -140,11 +145,15 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) // CRLFToLFFilteredOutputStream template - void testFilteredOutputStreamHelper - (const std::string& number, const std::string& expected, - const std::string& c1, const std::string& c2 = "", - const std::string& c3 = "", const std::string& c4 = "") - { + void testFilteredOutputStreamHelper( + const std::string& number, + const std::string& expected, + const std::string& c1, + const std::string& c2 = "", + const std::string& c3 = "", + const std::string& c4 = "" + ) { + std::ostringstream oss; vmime::utility::outputStreamAdapter os(oss); @@ -158,8 +167,8 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) VASSERT_EQ(number, expected, oss.str()); } - void testDotFilteredOutputStream() - { + void testDotFilteredOutputStream() { + typedef vmime::utility::dotFilteredOutputStream FILTER; testFilteredOutputStreamHelper("1", "foo\n..bar", "foo\n.bar"); @@ -177,8 +186,8 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) testFilteredOutputStreamHelper("11", "this is the first line\x0d\x0a...\x0d\x0aone dot\x0d\x0a....\x0d\x0atwo dots\x0d\x0a.....\x0d\x0athree... \x0d\x0a...\x0d\x0a..\x0d\x0a", "this is the first line\x0d\x0a..\x0d\x0aone dot\x0d\x0a...\x0d\x0atwo dots\x0d\x0a....\x0d\x0athree... \x0d\x0a..\x0d\x0a.\x0d\x0a"); } - void testCRLFToLFFilteredOutputStream() - { + void testCRLFToLFFilteredOutputStream() { + typedef vmime::utility::CRLFToLFFilteredOutputStream FILTER; testFilteredOutputStreamHelper("1", "foo\nbar", "foo\r\nbar"); @@ -193,12 +202,17 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) // stopSequenceFilteredInputStream template - void testStopSequenceFISHelper - (const std::string& number, const std::string& sequence, - const std::string& expected, const std::string& c1, - const std::string& c2 = "", const std::string& c3 = "", - const std::string& c4 = "", const std::string& c5 = "") - { + void testStopSequenceFISHelper( + const std::string& number, + const std::string& sequence, + const std::string& expected, + const std::string& c1, + const std::string& c2 = "", + const std::string& c3 = "", + const std::string& c4 = "", + const std::string& c5 = "" + ) { + chunkInputStream cis; cis.addChunk(c1); if (!c2.empty()) cis.addChunk(c2); @@ -211,8 +225,8 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) VASSERT_EQ(number, expected, readWhole(is)); } - void testStopSequenceFilteredInputStream1() - { + void testStopSequenceFilteredInputStream1() { + testStopSequenceFISHelper <1>("1", "x", "foo", "fooxbar"); testStopSequenceFISHelper <1>("2", "x", "foo", "foox", "bar"); testStopSequenceFISHelper <1>("3", "x", "foo", "foo", "x", "bar"); @@ -231,8 +245,8 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) testStopSequenceFISHelper <1>("13", "x", "", "", "x"); } - void testStopSequenceFilteredInputStreamN_2() - { + void testStopSequenceFilteredInputStreamN_2() { + testStopSequenceFISHelper <2>("1", "xy", "foo", "fooxybar"); testStopSequenceFISHelper <2>("2", "xy", "foo", "foox", "ybar"); testStopSequenceFISHelper <2>("3", "xy", "foo", "foox", "y", "bar"); @@ -255,8 +269,8 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) testStopSequenceFISHelper <2>("17", "xy", "", "x", "y"); } - void testStopSequenceFilteredInputStreamN_3() - { + void testStopSequenceFilteredInputStreamN_3() { + testStopSequenceFISHelper <3>("1", "xyz", "foo", "fooxyzbar"); testStopSequenceFISHelper <3>("2", "xyz", "foo", "foox", "yzbar"); testStopSequenceFISHelper <3>("3", "xyz", "foo", "foox", "y", "zbar"); @@ -289,8 +303,8 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) // LFToCRLFFilteredOutputStream - void testLFToCRLFFilteredOutputStream_Global() - { + void testLFToCRLFFilteredOutputStream_Global() { + typedef vmime::utility::LFToCRLFFilteredOutputStream FILTER; testFilteredOutputStreamHelper("1", "ABC\r\nDEF", "ABC\nDEF"); @@ -306,8 +320,8 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) testFilteredOutputStreamHelper("11", "\r\n\r\n\r\n\r\n", "\n\n\n\r\n"); } - void testLFToCRLFFilteredOutputStream_Edge() - { + void testLFToCRLFFilteredOutputStream_Edge() { + typedef vmime::utility::LFToCRLFFilteredOutputStream FILTER; testFilteredOutputStreamHelper("1", "\r\n\r\n", "\r", "\r"); @@ -325,4 +339,3 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest) } VMIME_TEST_SUITE_END - diff --git a/tests/utility/outputStreamByteArrayAdapterTest.cpp b/tests/utility/outputStreamByteArrayAdapterTest.cpp index b14d0a39..07a0f4b9 100644 --- a/tests/utility/outputStreamByteArrayAdapterTest.cpp +++ b/tests/utility/outputStreamByteArrayAdapterTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,8 +35,8 @@ VMIME_TEST_SUITE_BEGIN(outputStreamByteArrayAdapterTest) VMIME_TEST_LIST_END - void testWrite() - { + void testWrite() { + vmime::byteArray bytes; vmime::utility::outputStreamByteArrayAdapter stream(bytes); @@ -50,8 +50,8 @@ VMIME_TEST_SUITE_BEGIN(outputStreamByteArrayAdapterTest) VASSERT_EQ("Write 2", 0, memcmp("some datamore data", &bytes[0], 18)); } - void testWriteBinary() - { + void testWriteBinary() { + const char binaryData[] = "\xc5\x9a\xc3\xb8\xc9\xb1\xc9\x9b\x20\xc9\x93\xc9\xa8\xc9\xb2\xc9" "\x91\xc5\x95\xc9\xa3\x20\xc9\x96\xc9\x90\xca\x88\xc9\x92"; @@ -65,8 +65,8 @@ VMIME_TEST_SUITE_BEGIN(outputStreamByteArrayAdapterTest) VASSERT_EQ("Write", 0, memcmp(binaryData, &bytes[0], sizeof(binaryData))); } - void testWriteCRLF() - { + void testWriteCRLF() { + vmime::byteArray bytes; vmime::utility::outputStreamByteArrayAdapter stream(bytes); @@ -80,4 +80,3 @@ VMIME_TEST_SUITE_BEGIN(outputStreamByteArrayAdapterTest) } VMIME_TEST_SUITE_END - diff --git a/tests/utility/outputStreamSocketAdapterTest.cpp b/tests/utility/outputStreamSocketAdapterTest.cpp index 4920a75c..a869ed74 100644 --- a/tests/utility/outputStreamSocketAdapterTest.cpp +++ b/tests/utility/outputStreamSocketAdapterTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,8 +35,8 @@ VMIME_TEST_SUITE_BEGIN(outputStreamSocketAdapterTest) VMIME_TEST_LIST_END - void testWrite() - { + void testWrite() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::utility::outputStreamSocketAdapter stream(*socket); @@ -49,8 +49,8 @@ VMIME_TEST_SUITE_BEGIN(outputStreamSocketAdapterTest) VASSERT_EQ("Write", "some data", buffer); } - void testWriteBinary() - { + void testWriteBinary() { + const char binaryData[] = "\xc5\x9a\xc3\xb8\xc9\xb1\xc9\x9b\x20\xc9\x93\xc9\xa8\xc9\xb2\xc9" "\x91\xc5\x95\xc9\xa3\x20\xc9\x96\xc9\x90\xca\x88\xc9\x92"; @@ -67,8 +67,8 @@ VMIME_TEST_SUITE_BEGIN(outputStreamSocketAdapterTest) VASSERT_EQ("Write", 0, memcmp(binaryData, buffer.data(), sizeof(binaryData))); } - void testWriteCRLF() - { + void testWriteCRLF() { + vmime::shared_ptr socket = vmime::make_shared (); vmime::utility::outputStreamSocketAdapter stream(*socket); @@ -85,4 +85,3 @@ VMIME_TEST_SUITE_BEGIN(outputStreamSocketAdapterTest) } VMIME_TEST_SUITE_END - diff --git a/tests/utility/outputStreamStringAdapterTest.cpp b/tests/utility/outputStreamStringAdapterTest.cpp index 1cd3b3a0..3de8f8b8 100644 --- a/tests/utility/outputStreamStringAdapterTest.cpp +++ b/tests/utility/outputStreamStringAdapterTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -35,8 +35,8 @@ VMIME_TEST_SUITE_BEGIN(outputStreamStringAdapterTest) VMIME_TEST_LIST_END - void testWrite() - { + void testWrite() { + vmime::string str("initial data"); vmime::utility::outputStreamStringAdapter stream(str); @@ -52,8 +52,8 @@ VMIME_TEST_SUITE_BEGIN(outputStreamStringAdapterTest) VASSERT_EQ("Write 2 data", "initial dataadditional datamore data", str); } - void testWriteBinary() - { + void testWriteBinary() { + const vmime::byte_t binaryData[] = "\xc5\x9a\xc3\xb8\xc9\xb1\xc9\x9b\x20\xc9\x93\xc9\xa8\xc9\xb2\xc9" "\x91\xc5\x95\xc9\xa3\x20\xc9\x96\xc9\x90\xca\x88\xc9\x92"; @@ -67,8 +67,8 @@ VMIME_TEST_SUITE_BEGIN(outputStreamStringAdapterTest) VASSERT_EQ("Write", 0, memcmp(binaryData, str.data(), sizeof(binaryData))); } - void testWriteCRLF() - { + void testWriteCRLF() { + vmime::string str; vmime::utility::outputStreamStringAdapter stream(str); @@ -82,4 +82,3 @@ VMIME_TEST_SUITE_BEGIN(outputStreamStringAdapterTest) } VMIME_TEST_SUITE_END - diff --git a/tests/utility/parserInputStreamAdapterTest.cpp b/tests/utility/parserInputStreamAdapterTest.cpp index 0fd4f4e8..4bc310c9 100644 --- a/tests/utility/parserInputStreamAdapterTest.cpp +++ b/tests/utility/parserInputStreamAdapterTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -33,8 +33,8 @@ VMIME_TEST_SUITE_BEGIN(parserInputStreamAdapterTest) VMIME_TEST_LIST_END - void testEndlessLoopBufferSize() - { + void testEndlessLoopBufferSize() { + static const unsigned int BUFFER_SIZE = 4096; // same as in parserInputStreamAdapter::findNext() vmime::string str(BUFFER_SIZE, 'X'); diff --git a/tests/utility/pathTest.cpp b/tests/utility/pathTest.cpp index ef1b773d..e6227f3a 100644 --- a/tests/utility/pathTest.cpp +++ b/tests/utility/pathTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -64,14 +64,14 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) typedef vmime::utility::path::component comp; - void testConstruct1() - { + void testConstruct1() { + VASSERT_EQ("1", true, path().isEmpty()); VASSERT_EQ("2", 0, path().getSize()); } - void testConstruct2() - { + void testConstruct2() { + path p(comp("foo")); VASSERT_EQ("1", false, p.isEmpty()); @@ -79,8 +79,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("3", "foo", p.getComponentAt(0).getBuffer()); } - void testAppendComponent() - { + void testAppendComponent() { + path p; VASSERT_EQ("1", 0, p.getSize()); @@ -92,8 +92,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("3", c.getBuffer(), p.getComponentAt(0).getBuffer()); } - void testConstruct3() - { + void testConstruct3() { + path p1; p1.appendComponent(comp("foo")); p1.appendComponent(comp("bar")); @@ -105,8 +105,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("3", "bar", p2.getComponentAt(1).getBuffer()); } - void testConstruct4() - { + void testConstruct4() { + // Same as path::path(const component&) path p("foo"); @@ -115,8 +115,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("3", "foo", p.getComponentAt(0).getBuffer()); } - void testOperatorDiv1() - { + void testOperatorDiv1() { + path p1; p1.appendComponent(comp("foo")); p1.appendComponent(comp("bar")); @@ -132,8 +132,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("4", p2.getComponentAt(0).getBuffer(), p3.getComponentAt(2).getBuffer()); } - void testOperatorDiv2() - { + void testOperatorDiv2() { + path p1; p1.appendComponent(comp("foo")); p1.appendComponent(comp("bar")); @@ -148,8 +148,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("4", c.getBuffer(), p2.getComponentAt(2).getBuffer()); } - void testOperatorDivEqual1() - { + void testOperatorDivEqual1() { + path p1; p1.appendComponent(comp("foo")); p1.appendComponent(comp("bar")); @@ -166,8 +166,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("4", p2.getComponentAt(0).getBuffer(), p3.getComponentAt(2).getBuffer()); } - void testOperatorDivEqual2() - { + void testOperatorDivEqual2() { + path p1; p1.appendComponent(comp("foo")); p1.appendComponent(comp("bar")); @@ -183,8 +183,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("4", c.getBuffer(), p2.getComponentAt(2).getBuffer()); } - void testGetParent() - { + void testGetParent() { + path p1; path p1p = p1.getParent(); @@ -200,8 +200,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("3", p2.getComponentAt(0).getBuffer(), p2p.getComponentAt(0).getBuffer()); } - void testComparison() - { + void testComparison() { + path p1; p1.appendComponent(comp("foo")); p1.appendComponent(comp("bar")); @@ -224,8 +224,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("5", true, p3.getParent() == p1); } - void testGetLastComponent() - { + void testGetLastComponent() { + path p1; p1.appendComponent(comp("foo")); p1.appendComponent(comp("bar")); @@ -236,8 +236,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("3", "foo", p1.getParent().getParent().getLastComponent().getBuffer()); } - void testIsDirectParentOf() - { + void testIsDirectParentOf() { + path p1; p1.appendComponent(comp("foo")); @@ -256,8 +256,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("4", false, p2.isDirectParentOf(p1)); } - void testIsParentOf() - { + void testIsParentOf() { + path p1; p1.appendComponent(comp("foo")); @@ -276,8 +276,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("4", false, p2.isParentOf(p1)); } - void testIsParentOf_EquivalentCharset() - { + void testIsParentOf_EquivalentCharset() { + path p1; p1.appendComponent(comp("foo", "us-ascii")); @@ -289,8 +289,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("1", true, p1.isParentOf(p2)); } - void testRenameParent() - { + void testRenameParent() { + path p1; p1.appendComponent(comp("a")); p1.appendComponent(comp("b")); @@ -317,8 +317,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("6", "d", p.getComponentAt(4).getBuffer()); } - void testFromString() - { + void testFromString() { + path p = path::fromString("ab/cde/f", "/", vmime::charset("my-charset")); VASSERT_EQ("count", 3, p.getSize()); @@ -330,8 +330,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("charset3", "my-charset", p.getComponentAt(2).getCharset().getName()); } - void testFromString_IgnoreLeadingOrTrailingSep() - { + void testFromString_IgnoreLeadingOrTrailingSep() { + path p = path::fromString("//ab/cde/f////", "/", vmime::charset("my-charset")); VASSERT_EQ("count", 3, p.getSize()); @@ -343,8 +343,8 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) VASSERT_EQ("charset3", "my-charset", p.getComponentAt(2).getCharset().getName()); } - void testToString() - { + void testToString() { + path p; p.appendComponent(comp("ab")); p.appendComponent(comp("cde")); @@ -354,4 +354,3 @@ VMIME_TEST_SUITE_BEGIN(utilityPathTest) } VMIME_TEST_SUITE_END - diff --git a/tests/utility/seekableInputStreamRegionAdapterTest.cpp b/tests/utility/seekableInputStreamRegionAdapterTest.cpp index e703051b..b099cd77 100644 --- a/tests/utility/seekableInputStreamRegionAdapterTest.cpp +++ b/tests/utility/seekableInputStreamRegionAdapterTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -43,9 +43,10 @@ VMIME_TEST_SUITE_BEGIN(seekableInputStreamRegionAdapterTest) VMIME_TEST_LIST_END - vmime::shared_ptr createStream - (vmime::shared_ptr * underlyingStream = NULL) - { + vmime::shared_ptr createStream( + vmime::shared_ptr * underlyingStream = NULL + ) { + vmime::string buffer("THIS IS A TEST BUFFER"); vmime::shared_ptr strStream = @@ -54,22 +55,23 @@ VMIME_TEST_SUITE_BEGIN(seekableInputStreamRegionAdapterTest) vmime::shared_ptr rgnStream = vmime::make_shared (strStream, 10, 11); - if (underlyingStream) + if (underlyingStream) { *underlyingStream = strStream; + } return rgnStream; } - void testInitialPosition() - { + void testInitialPosition() { + vmime::shared_ptr stream = createStream(); VASSERT_EQ("Pos", 0, stream->getPosition()); VASSERT_FALSE("EOF", stream->eof()); } - void testSeekAndGetPosition() - { + void testSeekAndGetPosition() { + vmime::shared_ptr stream = createStream(); stream->seek(5); @@ -83,8 +85,8 @@ VMIME_TEST_SUITE_BEGIN(seekableInputStreamRegionAdapterTest) VASSERT_TRUE("EOF 2", stream->eof()); } - void testRead() - { + void testRead() { + vmime::shared_ptr stream = createStream(); stream->seek(5); @@ -96,12 +98,11 @@ VMIME_TEST_SUITE_BEGIN(seekableInputStreamRegionAdapterTest) VASSERT_EQ("Pos", 11, stream->getPosition()); VASSERT_EQ("Read", 6, read); VASSERT_TRUE("EOF", stream->eof()); - VASSERT_EQ("Buffer", "BUFFER", - vmime::utility::stringUtils::makeStringFromBytes(buffer, 6)); + VASSERT_EQ("Buffer", "BUFFER", vmime::utility::stringUtils::makeStringFromBytes(buffer, 6)); } - void testSkip() - { + void testSkip() { + vmime::shared_ptr stream = createStream(); stream->skip(5); @@ -116,8 +117,7 @@ VMIME_TEST_SUITE_BEGIN(seekableInputStreamRegionAdapterTest) VASSERT_EQ("Pos 2", 8, stream->getPosition()); VASSERT_EQ("Read", 3, read); VASSERT_FALSE("EOF 2", stream->eof()); - VASSERT_EQ("Buffer", "BUF", - vmime::utility::stringUtils::makeStringFromBytes(buffer, 3)); + VASSERT_EQ("Buffer", "BUF", vmime::utility::stringUtils::makeStringFromBytes(buffer, 3)); stream->skip(50); @@ -125,8 +125,8 @@ VMIME_TEST_SUITE_BEGIN(seekableInputStreamRegionAdapterTest) VASSERT_TRUE("EOF 3", stream->eof()); } - void testReset() - { + void testReset() { + vmime::shared_ptr stream = createStream(); stream->skip(100); @@ -136,8 +136,8 @@ VMIME_TEST_SUITE_BEGIN(seekableInputStreamRegionAdapterTest) VASSERT_FALSE("EOF", stream->eof()); } - void testOwnPosition() - { + void testOwnPosition() { + // seekableInputStreamRegionAdapter should keep track of its own position // in the underlying stream, and not be affected by possible seek/read // operations on it... @@ -156,10 +156,17 @@ VMIME_TEST_SUITE_BEGIN(seekableInputStreamRegionAdapterTest) VASSERT_EQ("Read 2", 6, stream->read(buffer2, 6)); - VASSERT_EQ("Buffer 1", "THIS IS", - vmime::utility::stringUtils::makeStringFromBytes(buffer1, 7)); - VASSERT_EQ("Buffer 2", "BUFFER", - vmime::utility::stringUtils::makeStringFromBytes(buffer2, 6)); + VASSERT_EQ( + "Buffer 1", + "THIS IS", + vmime::utility::stringUtils::makeStringFromBytes(buffer1, 7) + ); + + VASSERT_EQ( + "Buffer 2", + "BUFFER", + vmime::utility::stringUtils::makeStringFromBytes(buffer2, 6) + ); // ...but the underlying stream position is affected by read operations // from the region adapter (FIXME?) diff --git a/tests/utility/stringProxyTest.cpp b/tests/utility/stringProxyTest.cpp index d6513681..89b96568 100644 --- a/tests/utility/stringProxyTest.cpp +++ b/tests/utility/stringProxyTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -41,8 +41,8 @@ VMIME_TEST_SUITE_BEGIN(stringProxyTest) VMIME_TEST_LIST_END - void testConstruct() - { + void testConstruct() { + vmime::utility::stringProxy s; VASSERT_EQ("1", static_cast (0), s.length()); @@ -50,8 +50,8 @@ VMIME_TEST_SUITE_BEGIN(stringProxyTest) VASSERT_EQ("3", static_cast (0), s.end()); } - void testConstruct2() - { + void testConstruct2() { + vmime::string str("This is a test string."); vmime::utility::stringProxy s1(str); @@ -78,8 +78,8 @@ VMIME_TEST_SUITE_BEGIN(stringProxyTest) VASSERT_EQ("13", 't', *(s3.it_begin() + 3)); } - void testDetach() - { + void testDetach() { + vmime::utility::stringProxy s; s = "foo"; @@ -90,8 +90,8 @@ VMIME_TEST_SUITE_BEGIN(stringProxyTest) VASSERT_EQ("3", static_cast (0), s.end()); } - void testSet() - { + void testSet() { + vmime::string str("This is a test string."); vmime::utility::stringProxy s1; @@ -121,8 +121,8 @@ VMIME_TEST_SUITE_BEGIN(stringProxyTest) VASSERT_EQ("13", 't', *(s3.it_begin() + 3)); } - void testExtract() - { + void testExtract() { + vmime::string str("This is a test string."); vmime::utility::stringProxy s1(str, 10, 14); @@ -144,8 +144,8 @@ VMIME_TEST_SUITE_BEGIN(stringProxyTest) VASSERT_EQ("2", str, oss2.str()); } - void testOperatorLTLT1() - { + void testOperatorLTLT1() { + vmime::string str("This is a test string."); vmime::utility::stringProxy s1(str, 10, 14); @@ -163,8 +163,8 @@ VMIME_TEST_SUITE_BEGIN(stringProxyTest) VASSERT_EQ("2", str, oss2.str()); } - void testOperatorLTLT2() - { + void testOperatorLTLT2() { + vmime::string str("This is a test string."); vmime::utility::stringProxy s1(str, 10, 14); @@ -187,4 +187,3 @@ VMIME_TEST_SUITE_BEGIN(stringProxyTest) } VMIME_TEST_SUITE_END - diff --git a/tests/utility/stringUtilsTest.cpp b/tests/utility/stringUtilsTest.cpp index d86bbda0..393482f3 100644 --- a/tests/utility/stringUtilsTest.cpp +++ b/tests/utility/stringUtilsTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -52,8 +52,8 @@ VMIME_TEST_SUITE_BEGIN(stringUtilsTest) typedef vmime::utility::stringUtils stringUtils; - void testMakeStringFromBytes() - { + void testMakeStringFromBytes() { + vmime::byte_t bytes[] = { 0x12, 0x34, 0x56, 0x78 }; vmime::string str = vmime::utility::stringUtils::makeStringFromBytes(bytes, 3); @@ -63,8 +63,8 @@ VMIME_TEST_SUITE_BEGIN(stringUtilsTest) VASSERT_EQ("byte3", '\x56', str[2]); } - void testAppendBytesToString() - { + void testAppendBytesToString() { + vmime::byte_t bytes[] = { 0x42, 0x56, 0x12, 0x00, 'f', 'o', 'o' }; vmime::string str = "test"; @@ -84,8 +84,8 @@ VMIME_TEST_SUITE_BEGIN(stringUtilsTest) VASSERT_EQ("byte11", 'o', str[10]); } - void testIsStringEqualNoCase1() - { + void testIsStringEqualNoCase1() { + VASSERT_EQ("1", true, stringUtils::isStringEqualNoCase(vmime::string("foo"), "foo", 3)); VASSERT_EQ("2", true, stringUtils::isStringEqualNoCase(vmime::string("FOo"), "foo", 3)); @@ -93,15 +93,15 @@ VMIME_TEST_SUITE_BEGIN(stringUtilsTest) VASSERT_EQ("4", false, stringUtils::isStringEqualNoCase(vmime::string("foo"), "bar", 3)); } - void testIsStringEqualNoCase2() - { + void testIsStringEqualNoCase2() { + VASSERT_EQ("1", true, stringUtils::isStringEqualNoCase(vmime::string("foo"), vmime::string("foo"))); VASSERT_EQ("2", true, stringUtils::isStringEqualNoCase(vmime::string("FOo"), vmime::string("foo"))); VASSERT_EQ("3", true, stringUtils::isStringEqualNoCase(vmime::string("foO"), vmime::string("FOo"))); } - void testIsStringEqualNoCase3() - { + void testIsStringEqualNoCase3() { + vmime::string str1("FooBar"); VASSERT_EQ("1", true, stringUtils::isStringEqualNoCase(str1.begin(), str1.end(), "foobar", 6)); @@ -110,15 +110,15 @@ VMIME_TEST_SUITE_BEGIN(stringUtilsTest) VASSERT_EQ("4", false, stringUtils::isStringEqualNoCase(str1.begin(), str1.begin() + 3, "fooBar", 6)); } - void testToLower() - { + void testToLower() { + VASSERT_EQ("1", "foo", stringUtils::toLower("FOO")); VASSERT_EQ("2", "foo", stringUtils::toLower("foO")); VASSERT_EQ("3", "foo", stringUtils::toLower("foo")); } - void testTrim() - { + void testTrim() { + VASSERT_EQ("1", "foo", stringUtils::trim(" foo")); VASSERT_EQ("2", "foo", stringUtils::trim("\t\tfoo")); VASSERT_EQ("3", "foo", stringUtils::trim(" \t \tfoo")); @@ -136,35 +136,47 @@ VMIME_TEST_SUITE_BEGIN(stringUtilsTest) VASSERT_EQ("13", "foo", stringUtils::trim("\r \tfoo \n\t")); } - void testCountASCIIChars() - { + void testCountASCIIChars() { + vmime::string str1("foo"); - VASSERT_EQ("1", static_cast (3), - stringUtils::countASCIIchars(str1.begin(), str1.end())); + VASSERT_EQ( + "1", + static_cast (3), + stringUtils::countASCIIchars(str1.begin(), str1.end()) + ); vmime::string str2("f=?oo"); - VASSERT_EQ("2", static_cast (3 + 1), - stringUtils::countASCIIchars(str2.begin(), str2.end())); + VASSERT_EQ( + "2", + static_cast (3 + 1), + stringUtils::countASCIIchars(str2.begin(), str2.end()) + ); vmime::string str3("foo\x7f"); - VASSERT_EQ("3", static_cast (4), - stringUtils::countASCIIchars(str3.begin(), str3.end())); + VASSERT_EQ( + "3", + static_cast (4), + stringUtils::countASCIIchars(str3.begin(), str3.end()) + ); vmime::string str4("foo\x80"); - VASSERT_EQ("4", static_cast (3), - stringUtils::countASCIIchars(str4.begin(), str4.end())); + VASSERT_EQ( + "4", + static_cast (3), + stringUtils::countASCIIchars(str4.begin(), str4.end()) + ); } - void testUnquote() - { + void testUnquote() { + VASSERT_EQ("1", "quoted", stringUtils::unquote("\"quoted\"")); // "quoted" VASSERT_EQ("2", "\"not quoted", stringUtils::unquote("\"not quoted")); // "not quoted VASSERT_EQ("3", "not quoted\"", stringUtils::unquote("not quoted\"")); // not quoted" VASSERT_EQ("4", "quoted with \"escape\"", stringUtils::unquote("\"quoted with \\\"escape\\\"\"")); // "quoted with \"escape\"" } - void testIsValidHostname() - { + void testIsValidHostname() { + VASSERT_TRUE ("1", stringUtils::isValidHostname("localhost")); VASSERT_TRUE ("2", stringUtils::isValidHostname("localhost.localdomain")); VASSERT_TRUE ("3", stringUtils::isValidHostname("example.com")); @@ -176,8 +188,8 @@ VMIME_TEST_SUITE_BEGIN(stringUtilsTest) VASSERT_FALSE("9", stringUtils::isValidHostname("-example.com")); } - void testIsValidFQDN() - { + void testIsValidFQDN() { + VASSERT_FALSE("1", stringUtils::isValidFQDN("localhost")); VASSERT_FALSE("2", stringUtils::isValidFQDN("localhost.localdomain")); VASSERT_FALSE("3", stringUtils::isValidFQDN("example.com")); @@ -189,4 +201,3 @@ VMIME_TEST_SUITE_BEGIN(stringUtilsTest) } VMIME_TEST_SUITE_END - diff --git a/tests/utility/urlTest.cpp b/tests/utility/urlTest.cpp index 85991511..36820a68 100644 --- a/tests/utility/urlTest.cpp +++ b/tests/utility/urlTest.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard +// Copyright (C) 2002 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 @@ -44,14 +44,14 @@ VMIME_TEST_SUITE_BEGIN(urlTest) VMIME_TEST_LIST_END - static bool parseHelper(vmime::utility::url& u, const vmime::string& str) - { - try - { + static bool parseHelper(vmime::utility::url& u, const vmime::string& str) { + + try { + u = vmime::utility::url(str); - } - catch (vmime::exceptions::malformed_url) - { + + } catch (vmime::exceptions::malformed_url) { + return false; } @@ -59,8 +59,8 @@ VMIME_TEST_SUITE_BEGIN(urlTest) } - void testParse1() - { + void testParse1() { + // Test some valid constructions vmime::utility::url u1("", ""); @@ -123,8 +123,8 @@ VMIME_TEST_SUITE_BEGIN(urlTest) VASSERT_EQ("6.7", "/path/file", u4.getPath()); } - void testParse2() - { + void testParse2() { + // Now, test some ill-formed URLs // -- missing protocol @@ -144,8 +144,8 @@ VMIME_TEST_SUITE_BEGIN(urlTest) VASSERT_EQ("4", false, parseHelper(u4, "protohost/path")); } - void testParse3() - { + void testParse3() { + // Test decoding vmime::utility::url u1("", ""); @@ -158,8 +158,8 @@ VMIME_TEST_SUITE_BEGIN(urlTest) VASSERT_EQ("1.7", "/pa\xabth/", u1.getPath()); } - void testParse4() - { + void testParse4() { + // Test parameters vmime::utility::url u1("", ""); @@ -191,8 +191,8 @@ VMIME_TEST_SUITE_BEGIN(urlTest) } // '@' symbol in the username part - void testParse5() - { + void testParse5() { + vmime::utility::url u1("", ""); VASSERT_EQ("1", true, parseHelper(u1, "imap://account@myserver.com:password@myserver.com")); @@ -201,42 +201,54 @@ VMIME_TEST_SUITE_BEGIN(urlTest) VASSERT_EQ("4", "myserver.com", u1.getHost()); } - void testGenerate() - { + void testGenerate() { + vmime::utility::url u1("proto", "host", 12345, "path", "user", "password"); - VASSERT_EQ("1", "proto://user:password@host:12345/path", - static_cast (u1)); + VASSERT_EQ( + "1", + "proto://user:password@host:12345/path", + static_cast (u1) + ); vmime::utility::url u2("proto", "host"); VASSERT_EQ("2", "proto://host", static_cast (u2)); vmime::utility::url u3("proto", "host"); u3.getParams()["p1"] = "v1"; - VASSERT_EQ("3.1", "proto://host/?p1=v1", - static_cast (u3)); + VASSERT_EQ( + "3.1", + "proto://host/?p1=v1", + static_cast (u3) + ); u3.getParams()["p2"] = "v2"; - VASSERT_EQ("3.2", "proto://host/?p1=v1&p2=v2", - static_cast (u3)); + VASSERT_EQ( + "3.2", + "proto://host/?p1=v1&p2=v2", + static_cast (u3) + ); // Test special characters u3.getParams().clear(); u3.getParams()["&"] = "="; - VASSERT_EQ("3.3", "proto://host/?%26=%3D", - static_cast (u3)); + VASSERT_EQ( + "3.3", + "proto://host/?%26=%3D", + static_cast (u3) + ); } - void testUtilsEncode() - { + void testUtilsEncode() { + VASSERT_EQ("1", "%01", vmime::utility::urlUtils::encode("\x01")); VASSERT_EQ("2", "%20", vmime::utility::urlUtils::encode(" ")); VASSERT_EQ("3", "%FF", vmime::utility::urlUtils::encode("\xff")); VASSERT_EQ("4", "a", vmime::utility::urlUtils::encode("a")); } - void testUtilsDecode() - { - for (int i = 0 ; i < 255 ; ++i) - { + void testUtilsDecode() { + + for (int i = 0 ; i < 255 ; ++i) { + std::ostringstream ossTest; ossTest << "%" << "0123456789ABCDEF"[i / 16] << "0123456789ABCDEF"[i % 16]; @@ -247,22 +259,25 @@ VMIME_TEST_SUITE_BEGIN(urlTest) vmime::string res; res += static_cast (i); - VASSERT_EQ(ossNum.str(), res, - vmime::utility::urlUtils::decode(ossTest.str())); + VASSERT_EQ( + ossNum.str(), + res, + vmime::utility::urlUtils::decode(ossTest.str()) + ); } } - void testUtilsDecodeSpecialCases() - { + void testUtilsDecodeSpecialCases() { + // Bug #1656547: segfault with '%' at the end of the string VASSERT_EQ("1.1", "sadfsda%", vmime::utility::urlUtils::decode("sadfsda%")); VASSERT_EQ("1.2", "sadfsda\x05", vmime::utility::urlUtils::decode("sadfsda%5")); VASSERT_EQ("1.3", "sadfsda\x42", vmime::utility::urlUtils::decode("sadfsda%42")); } - void testUtilsEncodeReservedChars() - { + void testUtilsEncodeReservedChars() { + VASSERT_EQ("1", "%24", vmime::utility::urlUtils::encode("$")); VASSERT_EQ("2", "%26", vmime::utility::urlUtils::encode("&")); VASSERT_EQ("3", "%2B", vmime::utility::urlUtils::encode("+")); @@ -275,8 +290,8 @@ VMIME_TEST_SUITE_BEGIN(urlTest) VASSERT_EQ("10", "%40", vmime::utility::urlUtils::encode("@")); } - void testUtilsEncodeUnsafeChars() - { + void testUtilsEncodeUnsafeChars() { + VASSERT_EQ("1", "%20", vmime::utility::urlUtils::encode(" ")); VASSERT_EQ("2", "%22", vmime::utility::urlUtils::encode("\"")); VASSERT_EQ("3", "%3C", vmime::utility::urlUtils::encode("<")); @@ -295,4 +310,3 @@ VMIME_TEST_SUITE_BEGIN(urlTest) } VMIME_TEST_SUITE_END -