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