
ferencd@0: \chapter{Basics}
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Reference counting}
ferencd@0: 
ferencd@0: \subsection{Introduction} % --------------------------------------------------
ferencd@0: 
ferencd@0: Since version 0.7.2cvs, VMime use smart pointers to simplify memory
ferencd@0: management. Smart pointers rely on
ferencd@0: RAII\footnote{Ressource Allocation is Initialisation} so that we do not need
ferencd@0: to bother with deleting an object (freeing memory) when it is not used
ferencd@0: anymore.
ferencd@0: 
ferencd@0: There are two possibilities for owning a reference to an object. We can own a
ferencd@0: strong reference to an object: as long as we keep this reference, the object
ferencd@0: is not destroyed. Or we can own a weak reference to the object: the object can
ferencd@0: be destroyed if nobody owns a strong reference to it, in which case the weak
ferencd@0: reference becomes invalid.
ferencd@0: 
ferencd@0: An object is destroyed as soon as the last strong reference to it is released.
ferencd@0: At the same tine, all weak references (if any) are automatically set to point
ferencd@0: to \vnull.
ferencd@0: 
ferencd@0: In VMime, these two types of references are known as {\vcode vmime::shared\_ptr}
ferencd@0: and {\vcode vmime::weak\_ptr}, respectively.
ferencd@0: 
ferencd@0: \vnote{since November 2013, we switched from an old, intrusive implementation
ferencd@0: of smart pointers to a more standard one: either Boost {\vcode shared\_ptr<>}
ferencd@0: implementation or standard C++ one if we are compiling in C++11. Here are the
ferencd@0: changes:
ferencd@0: 
ferencd@0: {\vcode vmime::ref <>} is replaced with {\vcode vmime::shared\_ptr <>}
ferencd@0: 
ferencd@0: {\vcode vmime::weak\_ref <>} is replaced with {\vcode vmime::weak\_ptr <>}
ferencd@0: 
ferencd@0: {\vcode vmime::create <>} is replaced with {\vcode vmime::make\_shared <>}
ferencd@0: }
ferencd@0: 
ferencd@0: \subsection{Instanciating reference-counted objects} % -----------------------
ferencd@0: 
ferencd@0: In VMime, all objects that support reference counting inherit from the
ferencd@0: {\vcode vmime::object} class, which is responsible for
ferencd@0: incrementing/decrementing the counter and managing the object's life cycle.
ferencd@0: If you want to create a smart pointer to a new object instance, you should
ferencd@0: use the function {\vcode vmime::make\_shared} instead of the {\vcode new}
ferencd@0: operator.
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Smarts pointers and creating objects}]
ferencd@0: class myObject : public vmime::object
ferencd@0: {
ferencd@0: public:
ferencd@0: 
ferencd@0:    myObject(const vmime::string& name)
ferencd@0:       : m_name(name)
ferencd@0:    {
ferencd@0:    }
ferencd@0: 
ferencd@0:    void sayHello()
ferencd@0:    {
ferencd@0:       std::cout << "Hello " << m_name << std::endl;
ferencd@0:    }
ferencd@0: 
ferencd@0: private:
ferencd@0: 
ferencd@0:    vmime::string m_name;
ferencd@0: };
ferencd@0: 
ferencd@0: int main()
ferencd@0: {
ferencd@0:    vmime::shared_ptr <myObject> obj =
ferencd@0:       vmime::make_shared <myObject>("world");
ferencd@0: 
ferencd@0:    obj->sayHello();
ferencd@0: 
ferencd@0:    return 0;
ferencd@0: 
ferencd@0: } // Here, 'obj' gets automatically destroyed
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \subsection{Using smart pointers} % ------------------------------------------
ferencd@0: 
ferencd@0: Smart pointers are copiable, assignable and comparable. You can use them like
ferencd@0: you would use normal ("raw") C++ pointers (eg. you can write
ferencd@0: \lstinline{!ptr, ptr != NULL, ptr->method(), *ptr}...).
ferencd@0: 
ferencd@0: Type safety is also guaranteed, and you can type cast smart pointers using
ferencd@0: the {\vcode static\_cast()}, {\vcode dynamic\_cast()} and {\vcode const\_cast()}
ferencd@0: equivalents on {\vcode vmime::shared\_ptr} and {\vcode vmime::weak\_ptr} objects:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Casting smart pointers}]
ferencd@0: class myBase : public vmime::object { }
ferencd@0: class myObject : public myBase { }
ferencd@0: 
ferencd@0: vmime::shared_ptr <myObject> obj = vmime::make_shared <myObject>();
ferencd@0: 
ferencd@0: // Implicit downcast
ferencd@0: vmime::shared_ptr <myBase> base = obj;
ferencd@0: 
ferencd@0: // Explicit upcast
ferencd@0: vmime::shared_ptr <myObject> obj2 = vmime::dynamicCast <myObject>(base);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: Weak references are used to resolve reference cycles (an object which refers
ferencd@0: directly or indirectly to itself). The following example illustrates a
ferencd@0: typical problem of reference counting:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: class parent : public vmime::object
ferencd@0: {
ferencd@0: public:
ferencd@0: 
ferencd@0:    void createChild(vmime::shared_ptr <child> c)
ferencd@0:    {
ferencd@0:       m_child = c;
ferencd@0:    }
ferencd@0: 
ferencd@0: private:
ferencd@0: 
ferencd@0:    vmime::shared_ptr <child> m_child;
ferencd@0: };
ferencd@0: 
ferencd@0: class child : public vmime::object
ferencd@0: {
ferencd@0: public:
ferencd@0: 
ferencd@0:    child(vmime::shared_ptr <parent> p)
ferencd@0:       : m_parent(p)
ferencd@0:    {
ferencd@0:    }
ferencd@0: 
ferencd@0: private:
ferencd@0: 
ferencd@0:    vmime::shared_ptr <parent> m_parent;
ferencd@0: };
ferencd@0: 
ferencd@0: int main()
ferencd@0: {
ferencd@0:    vmime::shared_ptr <parent> p = vmime::make_shared <parent>();
ferencd@0:    vmime::shared_ptr <child> c = vmime::make_shared <child>();
ferencd@0: 
ferencd@0:    p->setChild(c);
ferencd@0: }
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: In this example, neither {\vcode p} nor {\vcode c} will be deleted when
ferencd@0: exiting {\vcode main()}. That's because {\vcode p} indirectly points to itself
ferencd@0: {\em via} {\vcode c}, and {\em vice versa}. The solution is to use a weak
ferencd@0: reference to the parent:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: vmime::weak_ptr <parent> m_parent;
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: The decision to make the parent or the child a weak reference is purely
ferencd@0: semantic, and it depends on the context and the relationships between the
ferencd@0: objects. Note that when the parent is deleted, the {\vcode m\_parent} member
ferencd@0: of the child points to \vnull.
ferencd@0: 
ferencd@0: More information about reference counting can be found on
ferencd@0: Wikipedia\footnote{http://en.wikipedia.org/wiki/Reference\_counting}.
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Error handling}
ferencd@0: 
ferencd@0: In VMime, error handling is exclusively based on exceptions, there is no error
ferencd@0: codes, or things like that.
ferencd@0: 
ferencd@0: VMime code may throw exceptions in many different situations: an unexpected
ferencd@0: error occured, an operation is not supported, etc. You should catch them if
ferencd@0: you want to report failures to the user. This is also useful when debugging
ferencd@0: your program.
ferencd@0: 
ferencd@0: VMime exceptions support chaining: an exception can be encapsulated into
ferencd@0: another exception to hide implementation details. The function
ferencd@0: {\vcode exception::other()} returns the next exception in the chain,
ferencd@0: or \vnull.
ferencd@0: 
ferencd@0: Following is an example code for catching VMime exceptions and writing error
ferencd@0: messages to the console:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Catching VMime exceptions}]
ferencd@0: std::ostream& operator<<(std::ostream& os, const vmime::exception& e)
ferencd@0: {
ferencd@0:    os << "* vmime::exceptions::" << e.name() << std::endl;
ferencd@0:    os << "    what = " << e.what() << std::endl;
ferencd@0: 
ferencd@0:    // Recursively print all encapsuled exceptions
ferencd@0:    if (e.other() != NULL)
ferencd@0:       os << *e.other();
ferencd@0: 
ferencd@0:    return os;
ferencd@0: }
ferencd@0: 
ferencd@0: ...
ferencd@0: 
ferencd@0: try
ferencd@0: {
ferencd@0:    // ...some call to VMime...
ferencd@0: }
ferencd@0: catch (vmime::exception& e)
ferencd@0: {
ferencd@0:    std::cerr << e;         // VMime exception
ferencd@0: }
ferencd@0: catch (std::exception& e)
ferencd@0: {
ferencd@0:    std::cerr << e.what();  // standard exception
ferencd@0: }
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: Read the source of {\vexample example6} if yo want to see a more complete
ferencd@0: example of using VMime exceptions (such as getting more detailed information
ferencd@0: by using specialized classes of {\vcode vmime::exception}).
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Basic objects}
ferencd@0: 
ferencd@0: \subsection{The {\vcode component} class} % ----------------------------------
ferencd@0: 
ferencd@0: In VMime, all the components of a message inherit from the same class
ferencd@0: {\vcode component}. This includes the message itself (classes {\vcode message}
ferencd@0: and {\vcode bodyPart}), the header, the header fields and the value of each
ferencd@0: header field, the body and all the parts in the message.
ferencd@0: 
ferencd@0: The class component provide a common interface for parsing or generating all
ferencd@0: these components (methods {\vcode parse()} and {\vcode generate()}). It also
ferencd@0: provides additional functions to get some information about the parsing
ferencd@0: process or the structure (methods {\vcode getParsedOffset()},
ferencd@0: {\vcode getParsedLength()} and {\vcode getChildComponents()}).
ferencd@0: 
ferencd@0: VMime also provides a set of classes corresponding to the basic types found
ferencd@0: in a message; for example a mailbox, a mailbox list, date/time information,
ferencd@0: media type, etc. They all inherit from {\vcode component} too.
ferencd@0: 
ferencd@0: \subsection{Date and time} % -------------------------------------------------
ferencd@0: 
ferencd@0: Date and time are used in several places in VMime, particularly in header
ferencd@0: fields (Date, Received, ...). VMime fully supports RFC-2822's date and time
ferencd@0: specification. The object {\vcode vmime::datetime} is used to manipulate date
ferencd@0: and time information, and to parse/generate it from/to RFC-2822 format.
ferencd@0: 
ferencd@0: The following code snippet show various manners of using the
ferencd@0: {\vcode vmime::datetime} object:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Using {\vcode vmime::datetime} object}]
ferencd@0: // Creating from string in RFC-2822 format
ferencd@0: vmime::datetime d1("Sat, 08 Oct 2005 14:07:52 +0200");
ferencd@0: 
ferencd@0: // Creating from components
ferencd@0: vmime::datetime d2(
ferencd@0:    /* date */ 2005, vmime::datetime::OCTOBER, 8,
ferencd@0:    /* time */ 14, 7, 52,
ferencd@0:    /* zone */ vmime::datetime::GMT2);
ferencd@0: 
ferencd@0: // Getting day of week
ferencd@0: const int dow = d2.getWeekDay();  // 'dow' should be datetime::SATURDAY
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \subsection{Media type} % ----------------------------------------------------
ferencd@0: 
ferencd@0: In MIME, the nature of the data contained in parts is identified using a
ferencd@0: media type. A general type (eg. \emph{image}) and a sub-type (eg. \emph{jpeg})
ferencd@0: are put together to form a media type (eg. \emph{image/jpeg}). This is also
ferencd@0: called the MIME type.
ferencd@0: 
ferencd@0: There are a lot of media types officially registered, and vendor-specific
ferencd@0: types are possible (they start with ``x-'', eg.
ferencd@0: \emph{application/x-zip-compressed}).
ferencd@0: 
ferencd@0: In VMime, the object {\vcode vmime::mediaType} represents a media type. There
ferencd@0: are also some constants for top-level types and sub-types in the
ferencd@0: {\vcode vmime::mediaTypes} namespace. For example, you can instanciate a new
ferencd@0: media type with:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: vmime::mediaType theType(
ferencd@0:    /* top-level type */ vmime::mediaTypes::IMAGE,
ferencd@0:    /* sub-type */       vmime::mediaTypes::IMAGE_JPEG);
ferencd@0: 
ferencd@0: // theType.getType() is "image"
ferencd@0: // theType.getSubType() is "jpeg"
ferencd@0: // theType.generate() returns "image/jpeg"
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: For more information about media types, see
ferencd@0: RFC-2046\footnote{http://www.faqs.org/rfcs/rfc2046.html}.
ferencd@0: 
ferencd@0: \subsection{Mailbox and mailbox groups} % ------------------------------------
ferencd@0: 
ferencd@0: VMime provides several objects for working with mailboxes and addresses.
ferencd@0: 
ferencd@0: The {\vcode vmime::address} class is an abstract type for representing an
ferencd@0: address: it can be either a mailbox (type {\vcode vmime::mailbox}) or a
ferencd@0: mailbox group (type {\vcode vmime::mailboxGroup}). A mailbox is composed of
ferencd@0: an email address (mandatory) and possibly a name. A mailbox group is simply
ferencd@0: a named list of mailboxes (see Figure \ref{uml_addr_mbox_mboxgroup}).
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Using mailboxes and mailbox groups}]
ferencd@0: vmime::shared_ptr <vmime::mailbox> mbox1 = vmime::make_shared <vmime::mailbox>
ferencd@0:     (/* name */ vmime::text("John Doe"), /* email */ "john.doe@acme.com");
ferencd@0: vmime::shared_ptr <vmime::mailbox> mbox2 = vmime::make_shared <vmime::mailbox>
ferencd@0:     (/* no name, email only */ "bill@acme.com");
ferencd@0: 
ferencd@0: vmime::shared_ptr <vmime::mailboxGroup> grp = vmime::make_shared <vmime::mailboxGroup>();
ferencd@0: grp->appendMailbox(mbox1);
ferencd@0: grp->appendMailbox(mbox2);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \begin{figure}[ht!]
ferencd@0: 	\center\includegraphics[width=0.7\textwidth]
ferencd@0: 		{images/address-mailbox-mailboxgroup.png}\endcenter
ferencd@0: 	\caption{Diagram for address-related classes}
ferencd@0: 	\label{uml_addr_mbox_mboxgroup}
ferencd@0: \end{figure}
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Message, body parts and header}
ferencd@0: 
ferencd@0: \subsection{Introduction to MIME messages} % ---------------------------------
ferencd@0: 
ferencd@0: A MIME message is a recursive structure in which each part can contains one
ferencd@0: or more parts (or \emph{entities}). Each part is composed of a header and
ferencd@0: a body (actual contents). Figure \ref{uml_msg_body_header} shows how this
ferencd@0: model is implemented in VMime, and all classes that take part in it.
ferencd@0: 
ferencd@0: \begin{figure}
ferencd@0: 	\center\includegraphics[width=1.0\textwidth]
ferencd@0: 		{images/message-body-header.png}\endcenter
ferencd@0: 	\caption{Overall structure of MIME messages}
ferencd@0: 	\label{uml_msg_body_header}
ferencd@0: \end{figure}
ferencd@0: 
ferencd@0: 
ferencd@0: \subsection{Header and header fields} % --------------------------------------
ferencd@0: 
ferencd@0: \subsubsection{Standard header fields} % .....................................
ferencd@0: 
ferencd@0: Header fields carry information about a message (or a part) and its contents.
ferencd@0: Each header field has a name and a value. All types that can be used as a
ferencd@0: field value inherit from the {\vcode headerFieldValue} class.
ferencd@0: 
ferencd@0: You cannot instanciate header fields directly using their constructor.
ferencd@0: Instead, you should use the {\vcode headerFieldFactory} object. This ensures
ferencd@0: the right field type and value type is used for the specified field name.
ferencd@0: For more information about how to use header fields and the factory, see
ferencd@0: section \ref{msg-building-simple-message}.
ferencd@0: 
ferencd@0: Some standard fields are officially registered and have their value type
ferencd@0: specified in a RFC. Table \ref{standard-fields} lists all the fields
ferencd@0: registered by default in VMime and the value type they contains.
ferencd@0: 
ferencd@0: By default, all unregistered fields have a value of type {\vcode text}.
ferencd@0: 
ferencd@0: \begin{table}[!ht]
ferencd@0: \begin{center}
ferencd@0: \noindent\begin{tabularx}{0.85\textwidth}{|X|X|}
ferencd@0: \hline
ferencd@0: 	{\bf Field Name} &
ferencd@0: 	{\bf Value Type} \\
ferencd@0: \hline
ferencd@0: \hline
ferencd@0: From & mailbox \\
ferencd@0: To & addressList \\
ferencd@0: Cc & addressList \\
ferencd@0: Bcc & addressList \\
ferencd@0: Sender & mailbox \\
ferencd@0: Date & datetime \\
ferencd@0: Received & relay \\
ferencd@0: Subject & text \\
ferencd@0: Reply-To & mailbox \\
ferencd@0: Delivered-To & mailbox \\
ferencd@0: Organization & text \\
ferencd@0: Return-Path & path \\
ferencd@0: Mime-Version & text \\
ferencd@0: Content-Type & mediaType \\
ferencd@0: Content-Transfer-Encoding & encoding \\
ferencd@0: Content-Description & text \\
ferencd@0: Content-Disposition & contentDisposition \\
ferencd@0: Content-Id & messageId \\
ferencd@0: Content-Location & text \\
ferencd@0: Message-Id & messageId \\
ferencd@0: In-Reply-To & messageIdSequence \\
ferencd@0: References & messageIdSequence \\
ferencd@0: Original-Message-Id & messageId \\
ferencd@0: Disposition & disposition \\
ferencd@0: Disposition-Notification-To & mailboxList \\
ferencd@0: \hline
ferencd@0: \end{tabularx}
ferencd@0: \end{center}
ferencd@0: \label{standard-fields}
ferencd@0: \caption{Standard fields and their types}
ferencd@0: \end{table}
ferencd@0: 
ferencd@0: 
ferencd@0: \subsubsection{Parameterized fields} % .......................................
ferencd@0: 
ferencd@0: In addition to a value, some header fields can contain one or more
ferencd@0: \emph{name=value} couples which are called \emph{parameters}. For example,
ferencd@0: this is used in the \emph{Content-Type} field to give more information about
ferencd@0: the content:
ferencd@0: 
ferencd@0: \begin{verbatim}
ferencd@0:    Content-Type: text/plain; charset="utf-8"
ferencd@0: \end{verbatim}
ferencd@0: 
ferencd@0: Fields that support parameters inherit from the
ferencd@0: {\vcode parameterizedHeaderField} class which provides methods to deal with
ferencd@0: these parameters: {\vcode appendParameter()}, {\vcode getParameterAt()}...
ferencd@0: 
ferencd@0: A parameter is identified by a name (eg. \emph{charset}) and associated to
ferencd@0: a value of type {\vcode vmime::text}. Parameters provide helper functions to
ferencd@0: convert automatically from basic types to text, and \emph{vice versa}. The
ferencd@0: following example illustrates it:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Getting and setting parameter value in fields}]
ferencd@0: vmime::shared_ptr <vmime::parameterizedField> field =
ferencd@0:    header->findField <vmime::parameterizedField>("X-Field-That-Contains-Parameters");
ferencd@0: 
ferencd@0: // Use setValue() to convert from a basic type to 'text'
ferencd@0: vmime::shared_ptr <vmime::parameter> prm = field->getParameter("my-date-param");
ferencd@0: prm->setValue(vmime::datetime::now());
ferencd@0: 
ferencd@0: // Use getValueAs() to convert from 'text' to a basic type
ferencd@0: prm = field->getParameter("my-charset-param");
ferencd@0: const vmime::charset ch = prm->getValueAs <vmime::charset>();
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: Some fields provide easy access to their standard parameters (see
ferencd@0: Table \ref{standard-prm-fields}). This avoids finding the parameter and
ferencd@0: \emph{dynamic-casting} its value to the right type. The following code
ferencd@0: illustrates how to use it:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: vmime::shared_ptr <vmime::contentTypeField> field =
ferencd@0:    header->getField <vmime::contentTypeField>(vmime::fields::CONTENT_TYPE);
ferencd@0: 
ferencd@0: // 1. First solution: the "hard" way
ferencd@0: vmime::shared_ptr <vmime::parameter> prm = field->findParameter("charset");
ferencd@0: const charset ch1 = prm->getValueAs <vmime::charset>();
ferencd@0: 
ferencd@0: // 2. Second solution: the simple way
ferencd@0: const charset ch2 = field->getCharset();
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \vnote{In both cases, an exception {\vcode no\_such\_parameter} can be
ferencd@0: thrown if the parameter does not exist, so be sure to catch it.}
ferencd@0: 
ferencd@0: \begin{table}[ht!]
ferencd@0: \begin{center}
ferencd@0: \noindent\begin{tabularx}{0.85\textwidth}{|l|l|X|}
ferencd@0: \hline
ferencd@0: 	{\bf Field Name} &
ferencd@0: 	{\bf Field Type} &
ferencd@0: 	{\bf Parameters} \\
ferencd@0: \hline
ferencd@0: \hline
ferencd@0: Content-Type & contentTypeField & boundary, charset, report-type  \\
ferencd@0: \hline
ferencd@0: Content-Disposition & contentDispositionField & creation-date,
ferencd@0: modification-date, read-date, filename, size \\
ferencd@0: \hline
ferencd@0: \end{tabularx}
ferencd@0: \end{center}
ferencd@0: \label{standard-prm-fields}
ferencd@0: \caption{Standard parameterized fields}
ferencd@0: \end{table}
ferencd@0: 
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Streams}
ferencd@0: 
ferencd@0: \subsection{Streams and stream adapters} % -----------------------------------
ferencd@0: 
ferencd@0: Streams permit reading or writing data whatever the underlying system is:
ferencd@0: a file on a hard disk, a socket connected to a remote service...
ferencd@0: 
ferencd@0: There are two types of streams: input streams (from which you can read data)
ferencd@0: and output streams (in which you can write data). Some adapters are provided
ferencd@0: for compatibility and convenience, for example:
ferencd@0: 
ferencd@0: \begin{itemize}
ferencd@0: \item {\vcode inputStreamAdapter} and {\vcode outputStreamAdapter}: allow
ferencd@0: to use standard C++ iostreams with VMime;
ferencd@0: \item {\vcode inputStreamStringAdapter} and
ferencd@0: {\vcode outputStreamStringAdapter}: use a {\vcode vmime::string} object to
ferencd@0: read/write data.
ferencd@0: \end{itemize}
ferencd@0: 
ferencd@0: The following example shows two ways of writing the current date to the
ferencd@0: standard output, using stream adapters:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Using stream adapters}]
ferencd@0: // Get current date and time
ferencd@0: const vmime::datetime date = vmime::datetime::now();
ferencd@0: 
ferencd@0: // 1. Using outputStreamAdapter
ferencd@0: vmime::utility::outputStreamAdapter out(std::cout);
ferencd@0: 
ferencd@0: std::cout << "Current date is: ";
ferencd@0: date.generate(out);
ferencd@0: std::cout << std::endl;
ferencd@0: 
ferencd@0: // 2. Using outputStreamStringAdapter
ferencd@0: vmime::string dateStr;
ferencd@0: vmime::utility::outputStreamStringAdapter outStr(dateStr);
ferencd@0: 
ferencd@0: date.generate(outStr);
ferencd@0: 
ferencd@0: std::cout << "Current date is: " << dateStr << std::endl;
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: 
ferencd@0: \subsection{Stream filters} % ------------------------------------------------
ferencd@0: 
ferencd@0: Input and output streams can be filtered to perform inline conversions (for
ferencd@0: example, there is a filter to convert ``{\textbackslash}r{\textbackslash}n''
ferencd@0: sequences to ``{\textbackslash}n''). They inherit from
ferencd@0: {\vcode vmime::utility::filteredInputStream} or
ferencd@0: {\vcode vmime::utility::filteredOutputStream} and are used like adapters (some
ferencd@0: filters also accept parameters; read the documentation).
ferencd@0: 
ferencd@0: The most useful filter in VMime (and probably the only one you will need) is
ferencd@0: the {\vcode charsetFilteredOutputStream}, which performs inline conversion
ferencd@0: of charsets. See \ref{section_charsets} to know how to use it.
ferencd@0: 
ferencd@0: \vnote{After you have finished to use a filtered output stream, it is
ferencd@0: important to call {\vcode flush()} on it to flush the internal buffer.
ferencd@0: If {\vcode flush()} is not called, not all data may be written to the
ferencd@0: underlying stream.}
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Content handlers}
ferencd@0: 
ferencd@0: \subsection{Introduction} % --------------------------------------------------
ferencd@0: 
ferencd@0: Content handlers are an abstraction for data sources. They are currently used
ferencd@0: when some data need to be stored for later use (eg. body part contents,
ferencd@0: attachment data, ...). Data can be stored encoded or unencoded (for more
ferencd@0: information about encodings, see \ref{section_encodings}).
ferencd@0: 
ferencd@0: \subsection{Extracting data from content handlers} % -------------------------
ferencd@0: 
ferencd@0: You can extract data in a content handler using the {\vcode extract()} method
ferencd@0: (which automatically decodes data if encoded) or {\vcode extractRaw()} (which
ferencd@0: extracts data without perfoming any decoding).
ferencd@0: 
ferencd@0: The following example shows how to extract the body text from a message, and
ferencd@0: writing it to the standard output with charset conversion:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Using content handlers to extract body text from
ferencd@0: a message}]
ferencd@0: // Suppose we already have a message
ferencd@0: vmime::shared_ptr <vmime::message> msg;
ferencd@0: 
ferencd@0: // Obtains a reference to the body contents
ferencd@0: vmime::shared_ptr <vmime::body> body = msg->getBody();
ferencd@0: vmime::shared_ptr <vmime::contentHandler> cts = body->getContents();
ferencd@0: 
ferencd@0: vmime::utility::outputStreamAdapter out(std::cout);
ferencd@0: cts->extract(out);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \vnote{The body contents is extracted ``as is''. No charset conversion is
ferencd@0: performed. See \ref{section_charsets} to know more about conversion between
ferencd@0: charsets.}
ferencd@0: 
ferencd@0: 
ferencd@0: \subsection{Creating content handlers} % -------------------------------------
ferencd@0: 
ferencd@0: When you are building a message, you may need to instanciate content handlers
ferencd@0: if you want to set the contents of a body part. The following code snippet
ferencd@0: shows how to set the body text of a part from a string:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Setting the contents of a body part}]
ferencd@0: vmime::shared_ptr <vmime::bodyPart> part;  // suppose we have a body part
ferencd@0: 
ferencd@0: // Create a new content handler from a string
ferencd@0: vmime::shared_ptr <vmime::contentHandler> cth =
ferencd@0:    vmime::make_shared <vmime::stringContentHandler>("Put body contents here");
ferencd@0: 
ferencd@0: // Set the contents
ferencd@0: part->getBody()->setContents(cth);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: Content handlers are also used when creating attachments. The following
ferencd@0: example illustrates how to create an attachment from a file:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Creating an attachment from a file}]
ferencd@0: // Create a stream from a file
ferencd@0: std::ifstream* fileStream = new std::ifstream();
ferencd@0: 
ferencd@0: fileStream->open("/home/vincent/paris.jpg", std::ios::binary);
ferencd@0: 
ferencd@0: if (!*fileStream)
ferencd@0:    // handle error
ferencd@0: 
ferencd@0: vmime::shared_ptr <utility::stream> dataStream =
ferencd@0:    vmime::make_shared <vmime::utility::inputStreamPointerAdapter>(fileStream);
ferencd@0: 
ferencd@0:    // NOTE: 'fileStream' will be automatically deleted
ferencd@0:    // when 'dataStream' is deleted
ferencd@0: 
ferencd@0: // Create a new content handler
ferencd@0: vmime::shared_ptr <contentHandler> data =
ferencd@0:    vmime::make_shared <vmime::streamContentHandler>(dataStream, 0);
ferencd@0: 
ferencd@0: // Now create the attachment
ferencd@0: ref <vmime::attachment> att = vmime::make_shared <vmime::defaultAttachment>
ferencd@0:    (
ferencd@0:    	/* attachment data */ data,
ferencd@0: 	/* content type */    vmime::mediaType("image/jpeg"),
ferencd@0: 	/* description */     vmime::text("Holiday photo"),
ferencd@0: 	/* filename */        vmime::word("paris.jpg")
ferencd@0:    );
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: You will see later that the {\vcode vmime::fileAttachment} class already
ferencd@0: encapsulates all the mechanics to create an attachment from a file.
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Character sets, charsets and conversions\label{section_charsets}}
ferencd@0: 
ferencd@0: Quoting from RFC-2278: \emph{`` The term 'charset' is used to refer to a
ferencd@0: method of converting a sequence of octets into a sequence of characters.''}
ferencd@0: 
ferencd@0: With the {\vcode vmime::charset} object, VMime supports conversion between
ferencd@0: charsets using the {\em iconv} library, which is available on almost all
ferencd@0: existing platforms. See {\vcode vmime::charset} and
ferencd@0: {\vcode vmime::charsetConverter} in the class documentation to know more
ferencd@0: about charset conversion.
ferencd@0: 
ferencd@0: The following example shows how to convert data in one charset to another
ferencd@0: charset. The data is extracted from the body of a message and converted
ferencd@0: to UTF-8 charset:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Extracting and converting body contents to a
ferencd@0: specified charset}]
ferencd@0: vmime::shared_ptr <vmime::message> msg;  // we have a message
ferencd@0: 
ferencd@0: // Obtain the content handler first
ferencd@0: vmime::shared_ptr <vmime::body> body = msg->getBody();
ferencd@0: vmime::shared_ptr <const vmime::contentHandler> cth = body->getContents();
ferencd@0: 
ferencd@0: // Then, extract and convert the contents
ferencd@0: vmime::utility::outputStreamAdapter out(std::cout);
ferencd@0: vmime::utility::charsetFilteredOutputStream fout
ferencd@0:    (/* source charset */ body->getCharset(),
ferencd@0:     /* dest charset */   vmime::charset("utf-8"),
ferencd@0:     /* dest stream */    out);
ferencd@0: 
ferencd@0: cth->extract(fout);
ferencd@0: 
ferencd@0: fout.flush();  // Very important!
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Non-ASCII text in header fields}
ferencd@0: 
ferencd@0: MIME standard defines methods\footnote{See RFC-2047: Message Header Extensions
ferencd@0: for Non-ASCII Text} for dealing with data which is not 7-bit only (ie. the
ferencd@0: ASCII character set), in particular in header fields. For example, the field
ferencd@0: ``Subject:'' use this data type.
ferencd@0: 
ferencd@0: VMime is fully compatible with RFC-2047 and provides two objects for
ferencd@0: manipulating 8-bit data: {\vcode vmime::text} and {\vcode vmime::word}. A word
ferencd@0: represents textual information encoded in a specified charset. A text is
ferencd@0: composed of one or more words.
ferencd@0: 
ferencd@0: RFC-2047 describes the process of encoding 8-bit data into a 7-bit form;
ferencd@0: basically, it relies on Base64 and Quoted-Printable encoding. Hopefully, all
ferencd@0: the encoding/decoding process is done internally by VMime, so creating text
ferencd@0: objects is fairly simple:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Creating \vcode{vmime::text} objects}]
ferencd@0: vmime::string inText = "Linux dans un téléphone mobile";
ferencd@0: vmime::charset inCharset = "utf-8";
ferencd@0: 
ferencd@0: vmime::text outText;
ferencd@0: outText.createFromString(inText, inCharset);
ferencd@0: 
ferencd@0: // 'outText' now contains 3 words:
ferencd@0: //    . <us-ascii>   "Linux dans un "
ferencd@0: //    . <utf-8>      "téléphone "
ferencd@0: //    . <us-ascii>   "mobile"
ferencd@0: 
ferencd@0: vmime::shared_ptr <vmime::header> header = myMessage->getHeader();
ferencd@0: header->Subject()->setValue(outText);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: In general, you will not need to decode RFC-2047-encoded data as the process
ferencd@0: is totally transparent in VMime. If you really have to, you can use the
ferencd@0: {\vcode vmime::text::decodeAndUnfold()} static method to create a text object
ferencd@0: from encoded data.
ferencd@0: 
ferencd@0: For example, say you have the following encoded data:
ferencd@0: 
ferencd@0: \begin{verbatim}
ferencd@0:    Linux dans un =?UTF-8?B?dMOpbMOpcGhvbmUgbW9iaWxl?=
ferencd@0: \end{verbatim}
ferencd@0: 
ferencd@0: You can simply decode it using the following code:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Decoding RFC-2047-encoded data}]
ferencd@0: vmime::string inData =
ferencd@0:     "Linux dans un =?UTF-8?B?dMOpbMOpcGhvbmUgbW9iaWxl?=";
ferencd@0: 
ferencd@0: vmime::text outText;
ferencd@0: vmime::text::decodeAndUnfold(inData, &outText);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: {\vcode vmime::text} also provides a function to convert all the words to
ferencd@0: another charset in a single call. The following example shows how to convert
ferencd@0: text stored in the Subject field of a message:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Converting data in a {\vcode vmime::text} to a
ferencd@0: specified charset}]
ferencd@0: vmime::shared_ptr <vmime::message> msg;  // we have a message
ferencd@0: 
ferencd@0: vmime::text subject = msg->getHeader()->Subject()->getValue();
ferencd@0: 
ferencd@0: const vmime::string subjectText =
ferencd@0:    subject.getConvertedText(vmime::charset("utf-8"));
ferencd@0: 
ferencd@0: // 'subjectText' now contains the subject in UTF-8 encoding
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Encodings\label{section_encodings}}
ferencd@0: 
ferencd@0: \subsection{Introduction} % --------------------------------------------------
ferencd@0: 
ferencd@0: The MIME standard defines a certain number of encodings to allow data
ferencd@0: to be safely transmitted from one peer to another. VMime provides
ferencd@0: data encoding and decoding using the {\vcode vmime::utility::encoder::encoder} object.
ferencd@0: 
ferencd@0: You should not need to use encoders directly, as all encoding/decoding
ferencd@0: process is handled internally by the library, but it is good to know
ferencd@0: they exist and how they work.
ferencd@0: 
ferencd@0: \subsection{Using encoders} % ------------------------------------------------
ferencd@0: 
ferencd@0: You can create an instance of an encoder using the 'vmime::utility::encoder::encoderFactory'
ferencd@0: object, giving the encoding name ({\it base64}, {\it quoted-printable}, ...).
ferencd@0: The following example creates an instance of the Base64 encoder to encode
ferencd@0: some data:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={A simple example of using an encoder}]
ferencd@0: vmime::shared_ptr <vmime::utility::encoder::encoder> enc =
ferencd@0:     vmime::utility::encoder::encoderFactory::getInstance()->create("base64");
ferencd@0: 
ferencd@0: vmime::string inString("Some data to encode");
ferencd@0: vmime::utility::inputStreamStringAdapter in(inString);
ferencd@0: 
ferencd@0: vmime::string outString;
ferencd@0: vmime::utility::outputStreamStringAdapter out(outString);
ferencd@0: 
ferencd@0: enc->encode(in, out);
ferencd@0: 
ferencd@0: std::cout << "Encoded data is:"  << outString << std::endl;
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: \subsection{Enumerating available encoders} % --------------------------------
ferencd@0: 
ferencd@0: The behaviour of the encoders can be configured using properties. However,
ferencd@0: not all encoders support properties. The following example\footnote{This is
ferencd@0: an excerpt from {\vexample example6}} enumerates available encoders and the
ferencd@0: supported properties for each of them:
ferencd@0: 
ferencd@0: \begin{lstlisting}[caption={Enumerating encoders and their properties}]
ferencd@0: vmime::shared_ptr <vmime::utility::encoder::encoderFactory> ef =
ferencd@0:    vmime::utility::encoder::encoderFactory::getInstance();
ferencd@0: 
ferencd@0: std::cout << "Available encoders:" << std::endl;
ferencd@0: 
ferencd@0: for (int i = 0 ; i < ef->getEncoderCount() ; ++i)
ferencd@0: {
ferencd@0:    // Output encoder name
ferencd@0:    vmime::shared_ptr <const vmime::utility::encoder::encoderFactory::registeredEncoder>
ferencd@0:       enc = ef->getEncoderAt(i);
ferencd@0: 
ferencd@0:    std::cout << "  * " << enc->getName() << std::endl;
ferencd@0: 
ferencd@0:    // Create an instance of the encoder to get its properties
ferencd@0:    vmime::shared_ptr <vmime::utility::encoder::encoder> e = enc->create();
ferencd@0: 
ferencd@0:    std::vector <vmime::string> props = e->getAvailableProperties();
ferencd@0:    std::vector <vmime::string>::const_iterator it;
ferencd@0: 
ferencd@0:    for (it = props.begin() ; it != props.end() ; ++it)
ferencd@0:       std::cout << "      - " << *it << std::endl;
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: 
ferencd@0: % ============================================================================
ferencd@0: \section{Progress listeners}
ferencd@0: 
ferencd@0: Progress listeners are used with objects that can notify you about the state
ferencd@0: of progress when they are performing an operation.
ferencd@0: 
ferencd@0: The {\vcode vmime::utility::progressListener} interface is rather simple:
ferencd@0: 
ferencd@0: \begin{lstlisting}
ferencd@0: void start(const int predictedTotal);
ferencd@0: void progress(const int current, const int currentTotal);
ferencd@0: void stop(const int total);
ferencd@0: \end{lstlisting}
ferencd@0: 
ferencd@0: {\vcode start()} and {\vcode stop()} are called at the beginning and the end
ferencd@0: of the operation, respectively. {\vcode progress()} is called each time the
ferencd@0: status of progress changes (eg. a chunk of data has been processed). There is
ferencd@0: no unit specified for the values passed in argument. It depends on the
ferencd@0: notifier: it can be bytes, percent, number of messages...




