First version of the VMime Book.
This commit is contained in:
parent
c179a10068
commit
7a3b1fe471
@ -2,6 +2,10 @@
|
||||
VERSION 0.7.2cvs
|
||||
================
|
||||
|
||||
2005-11-06 Vincent Richard <vincent@vincent-richard.net>
|
||||
|
||||
* First version of the VMime Book.
|
||||
|
||||
2005-11-05 Vincent Richard <vincent@vincent-richard.net>
|
||||
|
||||
* Refactored header field values and parameters.
|
||||
|
19
doc/book/Makefile
Normal file
19
doc/book/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
all: convert-images book
|
||||
|
||||
convert-images:
|
||||
cd images ; make
|
||||
|
||||
# Full build: multiple runs for correct references...
|
||||
book:
|
||||
pdflatex book.tex
|
||||
pdflatex book.tex
|
||||
pdflatex book.tex
|
||||
|
||||
# Only one run for development (faster)
|
||||
book-dev:
|
||||
pdflatex book.tex
|
||||
|
||||
clean:
|
||||
rm -f *.toc *.aux *.lof *.log *.lol *.pdf
|
||||
|
812
doc/book/basics.tex
Normal file
812
doc/book/basics.tex
Normal file
@ -0,0 +1,812 @@
|
||||
\chapter{Basics}
|
||||
|
||||
% ============================================================================
|
||||
\section{Reference counting}
|
||||
|
||||
\subsection{Introduction} % --------------------------------------------------
|
||||
|
||||
Since version 0.7.2cvs, VMime use smart pointers to simplify memory
|
||||
management. VMime's smart pointer implementation relies 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::ref}
|
||||
and {\vcode vmime::weak\_ref}, respectively.
|
||||
|
||||
\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::create} 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::ref <myObject> obj =
|
||||
vmime::create <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 staticCast()}, {\vcode dynamicCast()} and {\vcode constCast()}
|
||||
equivalents on {\vcode mime::ref} and {\vcode vmime::weak\_ref} objects:
|
||||
|
||||
\begin{lstlisting}[caption={Casting smart pointers}]
|
||||
class myBase : public vmime::object { }
|
||||
class myObject : public myBase { }
|
||||
|
||||
vmime::ref <myObject> obj = vmime::create <myObject>();
|
||||
|
||||
// Implicit downcast
|
||||
vmime::ref <myBase> base = obj;
|
||||
|
||||
// Explicit upcast
|
||||
vmime::ref <myObject> obj2 = base.dynamicCast <myObject>();
|
||||
\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::ref <child> c)
|
||||
{
|
||||
m_child = c;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
vmime::ref <child> m_child;
|
||||
};
|
||||
|
||||
class child : public vmime::object
|
||||
{
|
||||
public:
|
||||
|
||||
child(vmime::ref <parent> p)
|
||||
: m_parent(p)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
vmime::ref <parent> m_parent;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
vmime::ref <parent> p = vmime::create <parent>();
|
||||
vmime::ref <child> c = vmime::create <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_ref <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 occured, 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::ref <vmime::mailbox> mbox1 = vmime::create <vmime::mailbox>
|
||||
(/* name */ vmime::text("John Doe"), /* email */ "john.doe@acme.com");
|
||||
vmime::ref <vmime::mailbox> mbox2 = vmime::create <vmime::mailbox>
|
||||
(/* no name, email only */ "bill@acme.com");
|
||||
|
||||
vmime::ref <vmime::mailboxGroup> grp = vmime::create <vmime::mailboxGroup>();
|
||||
grp->appendMailbox(mbox1);
|
||||
grp->appendMailbox(mbox2);
|
||||
\end{lstlisting}
|
||||
|
||||
\begin{figure}[ht!]
|
||||
\center\includegraphics[width=0.7\textwidth]
|
||||
{images/address-mailbox-mailboxgroup.png}
|
||||
\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}
|
||||
\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::ref <vmime::parameterizedField> field =
|
||||
header->findField("X-Field-That-Contains-Parameters")
|
||||
.dynamicCast <vmime::parameterizedField>();
|
||||
|
||||
// Use setValue() to convert from a basic type to 'text'
|
||||
vmime::ref <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::ref <vmime::contentTypeField> field =
|
||||
header->getField(vmime::fields::CONTENT_TYPE)
|
||||
.dynamicCast <vmime::contentTypeField>();
|
||||
|
||||
// 1. First solution: the "hard" way
|
||||
vmime::ref <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);
|
||||
|
||||
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::ref <vmime::message> msg;
|
||||
|
||||
// Obtains a reference to the body contents
|
||||
vmime::ref <vmime::body> body = msg->getBody();
|
||||
vmime::ref <vmime::contentHandler> cts = msg->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::ref <vmime::bodyPart> part; // suppose we have a body part
|
||||
|
||||
// Create a new content handler from a string
|
||||
vmime::ref <vmime::contentHandler> cth =
|
||||
vmime::create <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::ref <utility::stream> dataStream =
|
||||
vmime::create <vmime::utility::inputStreamPointerAdapter>(fileStream);
|
||||
|
||||
// NOTE: 'fileStream' will be automatically deleted
|
||||
// when 'dataStream' is deleted
|
||||
|
||||
// Create a new content handler
|
||||
vmime::ref <contentHandler> data =
|
||||
vmime::create <vmime::streamContentHandler>(dataStream, 0);
|
||||
|
||||
// Now create the attachment
|
||||
ref <vmime::attachment> att = vmime::create <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::ref <vmime::message> msg; // we have a message
|
||||
|
||||
// Obtain the content handler first
|
||||
vmime::ref <vmime::body> body = msg->getBody();
|
||||
vmime::ref <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;
|
||||
vmime::newFromString(inText, inCharset, &outText);
|
||||
|
||||
// 'outText' now contains 3 words:
|
||||
// . <us-ascii> "Linux dans un "
|
||||
// . <utf-8> "téléphone "
|
||||
// . <us-ascii> "mobile"
|
||||
|
||||
vmime::ref <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::ref <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::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::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::ref <vmime::encoder> enc =
|
||||
vmime::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::encoderFactory* ef = vmime::encoderFactory::getInstance();
|
||||
|
||||
std::cout << "Available encoders:" << std::endl;
|
||||
|
||||
for (int i = 0 ; i < ef->getEncoderCount() ; ++i)
|
||||
{
|
||||
// Output encoder name
|
||||
vmime::ref <const vmime::encoderFactory::registeredEncoder>
|
||||
enc = ef->getEncoderAt(i);
|
||||
|
||||
std::cout << " * " << enc->getName() << std::endl;
|
||||
|
||||
// Create an instance of the encoder to get its properties
|
||||
vmime::ref <vmime::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}
|
||||
const bool cancel() const;
|
||||
|
||||
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...
|
||||
|
||||
Your listener can return {\vcode} in the {\vcode cancel()} method to cancel
|
||||
the operation. However, be warned that cancelling is not always supported by
|
||||
the source object.
|
||||
|
100
doc/book/book.tex
Normal file
100
doc/book/book.tex
Normal file
@ -0,0 +1,100 @@
|
||||
\documentclass[11pt]{report}
|
||||
|
||||
\title{{\Huge VMime Book} \\ \ \\ A Developer's Guide To VMime}
|
||||
\author{Vincent Richard \\ vincent@vincent-richard.net}
|
||||
|
||||
\usepackage{graphicx}
|
||||
\usepackage{tabularx}
|
||||
\usepackage{listings}
|
||||
\usepackage[usenames]{color}
|
||||
\usepackage{ucs}
|
||||
\usepackage[latin1]{inputenc}
|
||||
\usepackage[vcentering,dvips]{geometry}
|
||||
%\usepackage{type1cm} % scalable Computer Modern fonts
|
||||
\usepackage{courier} % use Adobe Courier instead of Computer Modern Typewriter
|
||||
\usepackage{fancyheadings}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{sverb}
|
||||
\usepackage{footmisc}
|
||||
|
||||
|
||||
\addtolength{\parskip}{+0.3cm}
|
||||
\linespread{1.05}
|
||||
|
||||
\setlength{\skip\footins}{1cm} % margin between text and footnotes
|
||||
|
||||
\clubpenalty=1000
|
||||
\widowpenalty=1000
|
||||
|
||||
\setcounter{secnumdepth}{10}
|
||||
\setcounter{tocdepth}{10}
|
||||
|
||||
\def\vcode{\tt}
|
||||
\def\vnull{{\tt NULL}}
|
||||
\newcommand{\vnote}[1]{{\sc note:} #1}
|
||||
\def\vexample{\tt\sc}
|
||||
\newcommand{\verti}[1]{\rotatebox{90}{#1\ }} % vertical text
|
||||
\def\vdot{$\bullet$}
|
||||
|
||||
\sloppy % Disable "overfull \hbox..." warnings
|
||||
|
||||
\newcommand{\Chapter}[1]{\chapter{#1} \setcounter{figure}{1}}
|
||||
|
||||
% 'geometry' configuration
|
||||
\geometry{papersize={210mm,297mm},total={160mm,230mm}}
|
||||
|
||||
% 'listings' configuration
|
||||
\definecolor{listingFrame}{rgb}{0.9,0.9,0.9}
|
||||
\lstset{language=C++,showstringspaces=false}
|
||||
\lstset{captionpos=b,extendedchars=true,inputencoding=latin1}
|
||||
\lstset{fontadjust=true,basewidth={0.5em,0.4em},columns=fixed,flexiblecolumns=false}
|
||||
\lstset{frame=leftline,framerule=0.1cm,framesep=0.3cm,rulecolor=\color{listingFrame}}
|
||||
\lstset{abovecaptionskip=0.5cm,xleftmargin=1.1cm,aboveskip=0.5cm,belowskip=0.2cm}
|
||||
|
||||
% 'hyperref' configuration
|
||||
\hypersetup{
|
||||
backref=true,pagebackref=true,hyperindex=rue,colorlinks=true,
|
||||
breaklinks=true,urlcolor=blue,linkcolor=black,bookmarks=true,bookmarksopen=true
|
||||
}
|
||||
|
||||
\begin{document}
|
||||
|
||||
% Title page
|
||||
\maketitle
|
||||
\newpage
|
||||
|
||||
% Table of contents
|
||||
\tableofcontents
|
||||
\newpage
|
||||
|
||||
% Chapters
|
||||
\include{intro}
|
||||
\include{building}
|
||||
\include{start}
|
||||
\include{basics}
|
||||
\include{msg}
|
||||
\include{net}
|
||||
|
||||
\thispagestyle{empty}
|
||||
\ \newpage
|
||||
|
||||
% List of listings
|
||||
\lstlistoflistings
|
||||
\addcontentsline{toc}{chapter}{Listings}
|
||||
|
||||
% List of figures
|
||||
\listoffigures
|
||||
\addcontentsline{toc}{chapter}{List of figures}
|
||||
|
||||
% List of table
|
||||
\listoftables
|
||||
\addcontentsline{toc}{chapter}{List of tables}
|
||||
|
||||
% Appendixes
|
||||
\appendix
|
||||
|
||||
\chapter{The GNU General Public License\label{appendix_license}}
|
||||
\verbinput{../../COPYING}
|
||||
|
||||
\end{document}
|
||||
|
102
doc/book/building.tex
Normal file
102
doc/book/building.tex
Normal file
@ -0,0 +1,102 @@
|
||||
\chapter{Building and Installing VMime\label{chapter_building}}
|
||||
|
||||
% ============================================================================
|
||||
\section{Introduction}
|
||||
|
||||
If no pre-build packages of VMime is available for your system, or if for some
|
||||
reason you want to compile it yourself from scratch, this section will guide
|
||||
you through the process.
|
||||
|
||||
% ============================================================================
|
||||
\section{What you need}
|
||||
|
||||
To build VMime from the sources, you will need the following:
|
||||
|
||||
\begin{itemize}
|
||||
\item a working C++ compiler with good STL implementation and also a good
|
||||
support for templates (for example, \href{http://gcc.gnu.org/}{GNU GCC}) ;
|
||||
\item \href{http://www.scons.org/}{SCons} build system, or the
|
||||
autoconf/automake tool chain ;
|
||||
\item an usable iconv() implementation (see
|
||||
\href{http://www.gnu.org/software/libiconv/}{libiconv of GNU Project}) ;
|
||||
\item the \href{http://www.gnu.org/software/gsasl/}{GNU SASL Library} if you
|
||||
want SASL\footnote{Simple Authentication and Security Layer} support ;
|
||||
\item the \href{http://www.gnu.org/software/gnutls/}{GNU TLS Library} if you
|
||||
want SSL and TLS\footnote{Transport Layer Security} support ;
|
||||
\end{itemize}
|
||||
|
||||
% ============================================================================
|
||||
\section{Obtaining source files}
|
||||
|
||||
You can download a package containing the source files of the latest release
|
||||
of the VMime library from the \href{http://www.vmime.org/}{VMime web site}.
|
||||
|
||||
You can also obtain the current development version from the CVS. VMime's CVS
|
||||
repository can be checked out from anonymous CVS with the following
|
||||
instructions. When prompted for a password for {\em anonymous}, simply press
|
||||
Enter key.
|
||||
|
||||
\begin{verbatim}
|
||||
cvs -d:pserver:anonymous@cvs.vmime.org:/cvsroot/vmime login
|
||||
cvs -z3 -d:pserver:anonymous@cvs.vmime.org:/cvsroot/vmime co -P vmime
|
||||
\end{verbatim}
|
||||
|
||||
% ============================================================================
|
||||
\section{Compiling and installing}
|
||||
|
||||
There are two possibilities for compiling VMime: using SCons building system,
|
||||
or using the Autotools.
|
||||
|
||||
\vnote{MS Visual C++ users, you can skip this section as a project file
|
||||
is provided in the distribution tarball.}
|
||||
|
||||
SCons is only used for development purposes, and so it is recommended that you
|
||||
use Autotools to build the project as it is a more portable solution, and is
|
||||
likely to work out-of-the-box on your computer. Thus, we will not describe
|
||||
the process of compiling VMime using SCons here.
|
||||
|
||||
\vnote{Windows users, you can use MinGW and MSYS\footnote{See on the MinGW
|
||||
website: http://www.mingw.org/} to install a POSIX compatible environment
|
||||
on top of Windows. This allow executing configure scripts and Makefiles on
|
||||
Windows}.
|
||||
|
||||
Before compiling VMime, you should run the {\vcode configure} script to
|
||||
detect some parameters specific to your platform. Go into the directory where
|
||||
you extracted the tarball and type:
|
||||
|
||||
\begin{verbatim}
|
||||
$ ./configure
|
||||
\end{verbatim}
|
||||
|
||||
This will create a file named {\vcode config.hpp} in the {\vcode vmime/}
|
||||
directory, with the parameters detected for your platform. You should modify
|
||||
this file only if you know what you are doing!
|
||||
|
||||
If you want to enable or disable some features in VMime, you can obtain some
|
||||
help by typing {\vcode ./configure --help}. The defaults should be OK though.
|
||||
|
||||
Next, you can start the compilation process:
|
||||
|
||||
\begin{verbatim}
|
||||
$ make
|
||||
\end{verbatim}
|
||||
|
||||
Please wait a few minutes will the compilation runs (you should have some time
|
||||
to have a coffee right now!). If you get errors during the compilation, be
|
||||
sure your system meet the requirements given at the beginning of the chapter.
|
||||
You can also try to get a newer version (from the CVS, for example) or to
|
||||
get some help on VMime user forums.
|
||||
|
||||
If everything has been compiled successfully, you can install the library and
|
||||
the development files on your system:
|
||||
|
||||
\begin{verbatim}
|
||||
# make install
|
||||
\end{verbatim}
|
||||
|
||||
\vnote{you must do that with superuser rights (root) if you chose to install
|
||||
the library into the default location (ie: /usr/lib and /usr/include).}
|
||||
|
||||
Now, you are done! You can jump to the next chapter to know how to use VMime
|
||||
in your program...
|
||||
|
14
doc/book/images/Makefile
Normal file
14
doc/book/images/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
# 'inkscape' is needed for converting from SVG to PNG
|
||||
|
||||
build-makefile:
|
||||
@echo "# Auto-generated file" > Makefile2
|
||||
@echo ".SUFFIXES: .png .svg" >> Makefile2
|
||||
@echo -n "foo: " >> Makefile2
|
||||
@for f in *.svg ; do (echo -n " $$f" | sed 's/svg/png/g') >> Makefile2 ; done
|
||||
@echo >> Makefile2
|
||||
@echo " @echo -n" >> Makefile2
|
||||
@echo ".svg.png:" >> Makefile2
|
||||
@echo ' echo Converting $$<' >> Makefile2
|
||||
@echo ' inkscape -b "#ffffff" -w 1000 -e $$@ $$<' >> Makefile2
|
||||
@make -f Makefile2
|
||||
|
355
doc/book/images/address-mailbox-mailboxgroup.svg
Normal file
355
doc/book/images/address-mailbox-mailboxgroup.svg
Normal file
@ -0,0 +1,355 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="453.27998pt"
|
||||
height="307.89001pt"
|
||||
id="svg2"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.42.2"
|
||||
sodipodi:docbase="/home/vincent/projects/vmime/doc/book/images"
|
||||
sodipodi:docname="address-mailbox-mailboxgroup.svg"
|
||||
inkscape:export-xdpi="73.779999"
|
||||
inkscape:export-ydpi="73.779999">
|
||||
<defs
|
||||
id="defs3">
|
||||
<marker
|
||||
inkscape:stockid="Torso"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Torso"
|
||||
style="overflow:visible">
|
||||
<g
|
||||
id="g2045"
|
||||
transform="scale(0.7)">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="path1128"
|
||||
d="M -4.7792281,-3.2395420 C -2.4288541,-2.8736027 0.52103922,-1.3019943 0.25792722,0.38794346 C -0.0051877922,2.0778819 -2.2126741,2.6176539 -4.5630471,2.2517169 C -6.9134221,1.8857769 -8.5210350,0.75201414 -8.2579220,-0.93792336 C -7.9948090,-2.6278615 -7.1296041,-3.6054813 -4.7792281,-3.2395420 z "
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;marker-start:none;marker-mid:none;marker-end:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
id="path1909"
|
||||
d="M 4.4598789,0.088665736 C -2.5564571,-4.3783320 5.2248769,-3.9061806 -0.84829578,-8.7197331"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-end:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
id="path1910"
|
||||
d="M 4.9298719,0.057520736 C -1.3872731,1.7494689 1.8027579,5.4782079 -4.9448731,7.5462725"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" />
|
||||
<rect
|
||||
transform="matrix(0.527536,-0.849533,0.887668,0.460484,0.000000,0.000000)"
|
||||
y="-1.7408575"
|
||||
x="-10.391706"
|
||||
height="2.7608147"
|
||||
width="2.6366582"
|
||||
id="rect2035"
|
||||
style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" />
|
||||
<rect
|
||||
transform="matrix(0.671205,-0.741272,0.790802,0.612072,0.000000,0.000000)"
|
||||
y="-7.9629307"
|
||||
x="4.9587269"
|
||||
height="2.8614161"
|
||||
width="2.7327356"
|
||||
id="rect2036"
|
||||
style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" />
|
||||
<path
|
||||
transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,25.96648,19.71619)"
|
||||
d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z"
|
||||
sodipodi:ry="0.60731727"
|
||||
sodipodi:rx="0.60731727"
|
||||
sodipodi:cy="-28.685045"
|
||||
sodipodi:cx="16.172634"
|
||||
id="path2037"
|
||||
style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,26.82450,16.99126)"
|
||||
d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z"
|
||||
sodipodi:ry="0.60731727"
|
||||
sodipodi:rx="0.60731727"
|
||||
sodipodi:cy="-28.685045"
|
||||
sodipodi:cx="16.172634"
|
||||
id="path2038"
|
||||
style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutL"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="TriangleOutL"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path5324"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
|
||||
transform="scale(0.8)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1.0000000"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.0000000"
|
||||
inkscape:cx="248.49444"
|
||||
inkscape:cy="298.91345"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:window-width="1150"
|
||||
inkscape:window-height="986"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
fill="#ff0000"
|
||||
inkscape:showpageshadow="true"
|
||||
showguides="true"
|
||||
showgrid="false"
|
||||
inkscape:grid-bbox="false"
|
||||
inkscape:grid-points="false" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<path
|
||||
id="path5442"
|
||||
d="M 303.65293,104.37647 L 303.65293,173.68448"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<path
|
||||
id="path5440"
|
||||
d="M 462.39333,172.39335 L 462.39333,240.10630"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<path
|
||||
id="path5438"
|
||||
d="M 139.24323,172.39335 L 139.24323,240.10630"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
|
||||
d="M 257.32713,293.92642 L 392.05898,293.92642"
|
||||
id="path2543" />
|
||||
<rect
|
||||
style="fill:#e0f5cc;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect1291"
|
||||
width="132.69368"
|
||||
height="105.95705"
|
||||
x="237.85556"
|
||||
y="13.003311" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="245.51651"
|
||||
y="55.887268"
|
||||
id="text1293"
|
||||
sodipodi:linespacing="125.00000%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2242"
|
||||
x="245.51651"
|
||||
y="55.887268">isEmpty() : bool</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2244"
|
||||
x="245.51651"
|
||||
y="70.887268">isGroup() : bool</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="279.65814"
|
||||
y="29.038483"
|
||||
id="text2347"
|
||||
sodipodi:linespacing="125.00000%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2222"
|
||||
x="279.65814"
|
||||
y="29.038483">address</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
|
||||
d="M 238.27499,37.373470 L 370.37704,37.373470"
|
||||
id="path2351" />
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2433"
|
||||
width="242.87289"
|
||||
height="157.12062"
|
||||
x="17.947495"
|
||||
y="215.62213" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="24.265694"
|
||||
y="258.30316"
|
||||
id="text2435"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2315"
|
||||
x="24.265694"
|
||||
y="258.30316">getName() : string</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2317"
|
||||
x="24.265694"
|
||||
y="273.30316">setName(n : string) : void</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2319"
|
||||
x="24.265694"
|
||||
y="288.30316">appendMailbox(m : ref <mailbox>)</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2321"
|
||||
x="24.265694"
|
||||
y="303.30316">getMailboxCount() : int</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2323"
|
||||
x="24.265694"
|
||||
y="318.30316">getMailboxAt(i : int) : ref <mailbox></tspan><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2325"
|
||||
x="24.265694"
|
||||
y="333.30316">...</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="91.950951"
|
||||
y="231.45441"
|
||||
id="text2439"
|
||||
sodipodi:linespacing="125.00000%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2246"
|
||||
x="91.950951"
|
||||
y="231.45441">mailboxGroup</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
|
||||
d="M 19.330207,239.78939 L 260.20091,239.78939"
|
||||
id="path2443" />
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2447"
|
||||
width="174.79645"
|
||||
height="124.30678"
|
||||
x="373.27942"
|
||||
y="215.33472" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="380.74768"
|
||||
y="258.15143"
|
||||
id="text2449"
|
||||
sodipodi:linespacing="125.00000%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2286"
|
||||
x="380.74768"
|
||||
y="258.15143">getName() : text</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2288"
|
||||
x="380.74768"
|
||||
y="273.15143">setName(n : text) : void</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2290"
|
||||
x="380.74768"
|
||||
y="288.15143">getEmail() : string</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2292"
|
||||
x="380.74768"
|
||||
y="303.15143">setEmail(e : string) : void</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="434.7478"
|
||||
y="231.30267"
|
||||
id="text2453"
|
||||
sodipodi:linespacing="125.00000%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2276"
|
||||
x="434.74780"
|
||||
y="231.30267">mailbox</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 373.64397,239.63760 L 547.69600,239.63760"
|
||||
id="path2457" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500457;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2541"
|
||||
width="15.541327"
|
||||
height="15.541327"
|
||||
x="-23.443876"
|
||||
y="392.33624"
|
||||
transform="matrix(0.707107,-0.707107,0.707107,0.707107,0.000000,0.000000)" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="344.41357"
|
||||
y="289.23822"
|
||||
id="text2545"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan5160"
|
||||
sodipodi:role="line"
|
||||
y="289.23822"
|
||||
x="344.41357">0..n</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="293.07501"
|
||||
y="312.23822"
|
||||
id="text2549"
|
||||
sodipodi:linespacing="125.00000%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2294"
|
||||
x="293.07501"
|
||||
y="312.23822">mailboxes</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="289.07501"
|
||||
y="289.23822"
|
||||
id="text2553"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan5158"
|
||||
sodipodi:role="line"
|
||||
y="289.23822"
|
||||
x="289.07501">0</tspan></text>
|
||||
<path
|
||||
id="path2575"
|
||||
d="M 290.22642,134.62157 L 318.11534,134.62157 L 303.70606,120.21230 L 290.22642,134.62157 z "
|
||||
style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
</g>
|
||||
<path
|
||||
id="path5436"
|
||||
d="M 139.78693,173.17443 L 461.72537,173.17443"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;stroke-dasharray:none" />
|
||||
</svg>
|
After Width: | Height: | Size: 17 KiB |
716
doc/book/images/message-body-header.svg
Normal file
716
doc/book/images/message-body-header.svg
Normal file
@ -0,0 +1,716 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="707.28000pt"
|
||||
height="612.89000pt"
|
||||
id="svg2"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.42.2"
|
||||
sodipodi:docbase="/home/vincent/projects/vmime/doc/book/images"
|
||||
sodipodi:docname="message-body-header.svg"
|
||||
inkscape:export-xdpi="73.779999"
|
||||
inkscape:export-ydpi="73.779999">
|
||||
<defs
|
||||
id="defs3">
|
||||
<marker
|
||||
inkscape:stockid="Torso"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Torso"
|
||||
style="overflow:visible">
|
||||
<g
|
||||
id="g2045"
|
||||
transform="scale(0.7)">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="path1128"
|
||||
d="M -4.7792281,-3.2395420 C -2.4288541,-2.8736027 0.52103922,-1.3019943 0.25792722,0.38794346 C -0.0051877922,2.0778819 -2.2126741,2.6176539 -4.5630471,2.2517169 C -6.9134221,1.8857769 -8.5210350,0.75201414 -8.2579220,-0.93792336 C -7.9948090,-2.6278615 -7.1296041,-3.6054813 -4.7792281,-3.2395420 z "
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;marker-start:none;marker-mid:none;marker-end:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
id="path1909"
|
||||
d="M 4.4598789,0.088665736 C -2.5564571,-4.3783320 5.2248769,-3.9061806 -0.84829578,-8.7197331"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-end:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
id="path1910"
|
||||
d="M 4.9298719,0.057520736 C -1.3872731,1.7494689 1.8027579,5.4782079 -4.9448731,7.5462725"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" />
|
||||
<rect
|
||||
transform="matrix(0.527536,-0.849533,0.887668,0.460484,0.000000,0.000000)"
|
||||
y="-1.7408575"
|
||||
x="-10.391706"
|
||||
height="2.7608147"
|
||||
width="2.6366582"
|
||||
id="rect2035"
|
||||
style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" />
|
||||
<rect
|
||||
transform="matrix(0.671205,-0.741272,0.790802,0.612072,0.000000,0.000000)"
|
||||
y="-7.9629307"
|
||||
x="4.9587269"
|
||||
height="2.8614161"
|
||||
width="2.7327356"
|
||||
id="rect2036"
|
||||
style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" />
|
||||
<path
|
||||
transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,25.96648,19.71619)"
|
||||
d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z"
|
||||
sodipodi:ry="0.60731727"
|
||||
sodipodi:rx="0.60731727"
|
||||
sodipodi:cy="-28.685045"
|
||||
sodipodi:cx="16.172634"
|
||||
id="path2037"
|
||||
style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,26.82450,16.99126)"
|
||||
d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z"
|
||||
sodipodi:ry="0.60731727"
|
||||
sodipodi:rx="0.60731727"
|
||||
sodipodi:cy="-28.685045"
|
||||
sodipodi:cx="16.172634"
|
||||
id="path2038"
|
||||
style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutL"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="TriangleOutL"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path5324"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
|
||||
transform="scale(0.8)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.00000000"
|
||||
inkscape:cx="394.46478"
|
||||
inkscape:cy="380.70648"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="svg2"
|
||||
inkscape:window-width="1150"
|
||||
inkscape:window-height="986"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<path
|
||||
id="path2407"
|
||||
d="M 253.02743,136.68448 L 253.02743,67.376470"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<path
|
||||
id="path5442"
|
||||
d="M 635.99153,281.37647 L 635.99153,350.68448"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<path
|
||||
id="path5440"
|
||||
d="M 783.39333,349.39335 L 783.39333,417.10630"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<path
|
||||
id="path5438"
|
||||
d="M 446.06998,349.39335 L 446.06998,417.10630"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 16.987518,219.56412 L 153.50367,219.56412"
|
||||
id="path2375" />
|
||||
<path
|
||||
id="path2345"
|
||||
d="M 508.29892,263.82217 L 105.85472,471.31117"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<path
|
||||
id="path2347"
|
||||
d="M 502.39025,252.30315 L 515.17042,277.09145 L 521.37461,257.68108 L 502.39025,252.30315 z "
|
||||
style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<g
|
||||
transform="matrix(1.828236e-17,1.000000,-1.000000,1.828236e-17,533.0981,623.6004)"
|
||||
id="g2321">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M -100.36367,371.67294 L 26.017722,371.67294"
|
||||
id="path2323" />
|
||||
<g
|
||||
id="g2325"
|
||||
transform="translate(-113.9177,-82.19766)">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 140.20049,454.12696 L 129.75724,443.68372"
|
||||
id="path2327" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 139.84823,453.80527 L 129.66343,463.99007"
|
||||
id="path2329" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
id="path2241"
|
||||
d="M 507.60723,180.01568 L 350.16119,180.01568"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<rect
|
||||
style="fill:#dcf5e6;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect1291"
|
||||
width="236.14607"
|
||||
height="157.54773"
|
||||
x="522.13733"
|
||||
y="126.86942" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="529.52441"
|
||||
y="169.54865"
|
||||
id="text1293"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan5228"
|
||||
sodipodi:role="line"
|
||||
y="169.54865"
|
||||
x="529.52441">parse(buf : string) : void</tspan><tspan
|
||||
id="tspan5230"
|
||||
sodipodi:role="line"
|
||||
y="183.94865"
|
||||
x="529.52441">generate(out : outputStream) : void</tspan><tspan
|
||||
id="tspan5232"
|
||||
sodipodi:role="line"
|
||||
y="198.34865"
|
||||
x="529.52441" /><tspan
|
||||
id="tspan5234"
|
||||
sodipodi:role="line"
|
||||
y="212.74865"
|
||||
x="529.52441">clone() : ref <component></tspan><tspan
|
||||
id="tspan5236"
|
||||
sodipodi:role="line"
|
||||
y="227.14865"
|
||||
x="529.52441">copyFrom(src : component) : void</tspan><tspan
|
||||
id="tspan5238"
|
||||
sodipodi:role="line"
|
||||
y="241.54865"
|
||||
x="529.52441">getChildComponents() : vector</tspan><tspan
|
||||
id="tspan5240"
|
||||
sodipodi:role="line"
|
||||
y="255.94865"
|
||||
x="529.52441">getParsedOffset() : int</tspan><tspan
|
||||
id="tspan5242"
|
||||
sodipodi:role="line"
|
||||
y="270.34865"
|
||||
x="529.52441">getParsedLength() : int</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="609.02057"
|
||||
y="142.69992"
|
||||
id="text2347"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan5172"
|
||||
sodipodi:role="line"
|
||||
y="142.69992"
|
||||
x="609.02057">component</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 522.50261,151.03487 L 758.16522,151.03487"
|
||||
id="path2351" />
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2353"
|
||||
width="218.71376"
|
||||
height="151.16983"
|
||||
x="145.51056"
|
||||
y="133.04831" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="154.6483"
|
||||
y="175.75391"
|
||||
id="text2355"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan2349"
|
||||
sodipodi:role="line"
|
||||
y="175.75391"
|
||||
x="154.64830">getBody() : ref <body></tspan><tspan
|
||||
id="tspan2351"
|
||||
sodipodi:role="line"
|
||||
y="190.15391"
|
||||
x="154.64830">getHeader() : ref <header></tspan><tspan
|
||||
id="tspan2353"
|
||||
sodipodi:role="line"
|
||||
y="204.55391"
|
||||
x="154.64830">getParentPart() : ref <bodyPart></tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="222.66418"
|
||||
y="148.90518"
|
||||
id="text2375"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan5272"
|
||||
sodipodi:role="line"
|
||||
y="148.90518"
|
||||
x="222.66418">bodyPart</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 145.87565,157.24013 L 363.84409,157.24013"
|
||||
id="path2379" />
|
||||
<g
|
||||
transform="matrix(1.828236e-17,1.000000,-1.000000,1.828236e-17,548.9327,384.9312)"
|
||||
id="g2247">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M -100.36367,371.67294 L 26.017722,371.67294"
|
||||
id="path2387" />
|
||||
<g
|
||||
id="g2395"
|
||||
transform="translate(-113.9177,-82.19766)">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 140.20049,454.12696 L 129.75724,443.68372"
|
||||
id="path2389" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 139.84823,453.80527 L 129.66343,463.99007"
|
||||
id="path2393" />
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
sodipodi:linespacing="100.00000%"
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="138.11696"
|
||||
y="382.06345"
|
||||
id="text2403"><tspan
|
||||
id="tspan2273"
|
||||
sodipodi:role="line"
|
||||
y="382.06345"
|
||||
x="138.11696">body</tspan></text>
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2433"
|
||||
width="276.37778"
|
||||
height="157.12062"
|
||||
x="304.96820"
|
||||
y="412.46472" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="313.24988"
|
||||
y="455.14575"
|
||||
id="text2435"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan5256"
|
||||
sodipodi:role="line"
|
||||
y="455.14575"
|
||||
x="313.24988">hasField(name : string) : bool</tspan><tspan
|
||||
id="tspan5258"
|
||||
sodipodi:role="line"
|
||||
y="469.54575"
|
||||
x="313.24988">findField(name : string) : ref <headerField></tspan><tspan
|
||||
id="tspan5260"
|
||||
sodipodi:role="line"
|
||||
y="483.94575"
|
||||
x="313.24988">findAllFields(name : string) : vector</tspan><tspan
|
||||
id="tspan5262"
|
||||
sodipodi:role="line"
|
||||
y="498.34575"
|
||||
x="313.24988">getField(name : string) : ref <headerField></tspan><tspan
|
||||
id="tspan5264"
|
||||
sodipodi:role="line"
|
||||
y="512.74575"
|
||||
x="313.24988">appendField(f : ref <headerField>) : void</tspan><tspan
|
||||
id="tspan5266"
|
||||
sodipodi:role="line"
|
||||
y="527.14575"
|
||||
x="313.24988">...</tspan><tspan
|
||||
id="tspan5268"
|
||||
sodipodi:role="line"
|
||||
y="541.54576"
|
||||
x="313.24988">getFieldAt(pos : int) : ref <headerField></tspan><tspan
|
||||
id="tspan5270"
|
||||
sodipodi:role="line"
|
||||
y="555.94576"
|
||||
x="313.24988">getFieldCount() : int</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="412.95099"
|
||||
y="428.297"
|
||||
id="text2439"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan5154"
|
||||
sodipodi:role="line"
|
||||
y="428.29700"
|
||||
x="412.95099">header</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 306.34976,436.63194 L 580.95005,436.63194"
|
||||
id="path2443" />
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2447"
|
||||
width="174.79645"
|
||||
height="124.30678"
|
||||
x="694.27942"
|
||||
y="412.17731" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="701.74768"
|
||||
y="454.99402"
|
||||
id="text2449"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan5176"
|
||||
sodipodi:role="line"
|
||||
y="454.99402"
|
||||
x="701.74768">getName() : string</tspan><tspan
|
||||
id="tspan5178"
|
||||
sodipodi:role="line"
|
||||
y="469.39402"
|
||||
x="701.74768">getValue() : component</tspan><tspan
|
||||
id="tspan5180"
|
||||
sodipodi:role="line"
|
||||
y="483.79402"
|
||||
x="701.74768">setValue(val : component)</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="738.73987"
|
||||
y="428.14526"
|
||||
id="text2453"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan5152"
|
||||
sodipodi:role="line"
|
||||
y="428.14526"
|
||||
x="738.73987">headerField</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 694.64397,436.48015 L 868.69600,436.48015"
|
||||
id="path2457" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500381;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2541"
|
||||
width="15.541226"
|
||||
height="15.541226"
|
||||
x="65.401291"
|
||||
y="759.55469"
|
||||
transform="matrix(0.707107,-0.707107,0.707107,0.707107,0.000000,0.000000)" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 605.07226,490.76897 L 694.31385,490.76897"
|
||||
id="path2543" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="661.23236"
|
||||
y="486.08081"
|
||||
id="text2545"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan5160"
|
||||
sodipodi:role="line"
|
||||
y="486.08081"
|
||||
x="661.23236">0..n</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="626.90173"
|
||||
y="509.08081"
|
||||
id="text2549"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan5156"
|
||||
sodipodi:role="line"
|
||||
y="509.08081"
|
||||
x="626.90173">fields</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="611.56311"
|
||||
y="486.08081"
|
||||
id="text2553"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan5158"
|
||||
sodipodi:role="line"
|
||||
y="486.08081"
|
||||
x="611.56311">0</tspan></text>
|
||||
<path
|
||||
id="path2575"
|
||||
d="M 622.56502,300.28297 L 650.45394,300.28297 L 636.04466,285.87370 L 622.56502,300.28297 z "
|
||||
style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2225"
|
||||
width="171.85686"
|
||||
height="151.16983"
|
||||
x="74.698677"
|
||||
y="412.04831" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="82.183701"
|
||||
y="454.75391"
|
||||
id="text2227"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan2377"
|
||||
sodipodi:role="line"
|
||||
y="454.75391"
|
||||
x="82.183701">getContents() : ref <ch></tspan><tspan
|
||||
id="tspan2379"
|
||||
sodipodi:role="line"
|
||||
y="469.15391"
|
||||
x="82.183701">getCharset() : charset</tspan><tspan
|
||||
id="tspan2381"
|
||||
sodipodi:role="line"
|
||||
y="483.55391"
|
||||
x="82.183701">getEncoding() : encoding</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="141.69556"
|
||||
y="427.90518"
|
||||
id="text2231"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan2237"
|
||||
sodipodi:role="line"
|
||||
y="427.90518"
|
||||
x="141.69556">body</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 75.063282,436.24013 L 246.17599,436.24013"
|
||||
id="path2235" />
|
||||
<path
|
||||
id="path2239"
|
||||
d="M 506.13949,167.78737 L 506.13949,195.67630 L 520.54876,181.26702 L 506.13949,167.78737 z "
|
||||
style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<g
|
||||
transform="matrix(1.828236e-17,1.000000,-1.000000,1.828236e-17,548.9327,384.9312)"
|
||||
id="g2253">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M -100.36367,371.67294 L 26.017722,371.67294"
|
||||
id="path2255" />
|
||||
<g
|
||||
id="g2257"
|
||||
transform="translate(-113.9177,-82.19766)">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 140.20049,454.12696 L 129.75724,443.68372"
|
||||
id="path2259" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 139.84823,453.80527 L 129.66343,463.99007"
|
||||
id="path2261" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1.828236e-17,1.000000,-1.000000,1.828236e-17,704.8357,384.9312)"
|
||||
id="g2263">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M -100.36367,371.67294 L 26.017722,371.67294"
|
||||
id="path2265" />
|
||||
<g
|
||||
id="g2267"
|
||||
transform="translate(-113.9177,-82.19766)">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 140.20049,454.12696 L 129.75724,443.68372"
|
||||
id="path2269" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 139.84823,453.80527 L 129.66343,463.99007"
|
||||
id="path2271" />
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
sodipodi:linespacing="100.00000%"
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="342.21133"
|
||||
y="384.8981"
|
||||
id="text2275"><tspan
|
||||
id="tspan2279"
|
||||
sodipodi:role="line"
|
||||
y="384.89810"
|
||||
x="342.21133">header</tspan></text>
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2283"
|
||||
width="223.48137"
|
||||
height="99.596283"
|
||||
x="46.366730"
|
||||
y="650.83508" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="53.664009"
|
||||
y="693.75391"
|
||||
id="text2285"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan2337"
|
||||
sodipodi:role="line"
|
||||
y="693.75391"
|
||||
x="53.664009">extract(out : outputStream) : void</tspan><tspan
|
||||
id="tspan2339"
|
||||
sodipodi:role="line"
|
||||
y="708.15391"
|
||||
x="53.664009">getLength() : int</tspan><tspan
|
||||
id="tspan2341"
|
||||
sodipodi:role="line"
|
||||
y="722.55391"
|
||||
x="53.664009">getEncoding() : encoding</tspan><tspan
|
||||
id="tspan2343"
|
||||
sodipodi:role="line"
|
||||
y="736.95391"
|
||||
x="53.664009">isEmpty() : bool</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="107.50659"
|
||||
y="666.90515"
|
||||
id="text2289"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan2295"
|
||||
sodipodi:role="line"
|
||||
y="666.90515"
|
||||
x="107.50659">contentHandler</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 46.694654,675.24013 L 269.50523,675.24013"
|
||||
id="path2293" />
|
||||
<text
|
||||
sodipodi:linespacing="100.00000%"
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="96.439804"
|
||||
y="606.38623"
|
||||
id="text2313"><tspan
|
||||
id="tspan2331"
|
||||
sodipodi:role="line"
|
||||
y="606.38623"
|
||||
x="96.439804">contents</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2343873;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 16.600928,494.52517 L 54.665082,494.52517"
|
||||
id="path2357" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="114.21628"
|
||||
y="211.67206"
|
||||
id="text2359"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan2361"
|
||||
sodipodi:role="line"
|
||||
y="211.67206"
|
||||
x="114.21628">0..n</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="15.201084"
|
||||
y="211.39832"
|
||||
id="text2363"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan2371"
|
||||
sodipodi:role="line"
|
||||
y="211.39832"
|
||||
x="15.201084">sub-parts</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="37.547035"
|
||||
y="486.67206"
|
||||
id="text2367"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan2369"
|
||||
sodipodi:role="line"
|
||||
y="486.67206"
|
||||
x="37.547035">0</tspan></text>
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500843;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2355"
|
||||
width="15.541844"
|
||||
height="15.541844"
|
||||
x="-313.66727"
|
||||
y="385.82047"
|
||||
transform="matrix(0.707107,-0.707107,0.707107,0.707107,0.000000,0.000000)" />
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2383"
|
||||
width="171.85686"
|
||||
height="67.987976"
|
||||
x="169.86403"
|
||||
y="15.308525" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="228.35699"
|
||||
y="31.574478"
|
||||
id="text2393"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan2399"
|
||||
sodipodi:role="line"
|
||||
y="31.574478"
|
||||
x="228.35699">message</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 170.22863,39.909422 L 341.34134,39.909422"
|
||||
id="path2397" />
|
||||
<path
|
||||
id="path2405"
|
||||
d="M 266.45394,117.77798 L 238.56502,117.77798 L 252.97430,132.18725 L 266.45394,117.77798 z "
|
||||
style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
</g>
|
||||
<path
|
||||
id="path5436"
|
||||
d="M 446.81292,350.17443 L 782.69938,350.17443"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2515085;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<path
|
||||
id="path2373"
|
||||
d="M 16.806908,219.05029 L 16.806908,493.94805"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2522694;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
</svg>
|
After Width: | Height: | Size: 36 KiB |
621
doc/book/images/messaging-services.svg
Normal file
621
doc/book/images/messaging-services.svg
Normal file
@ -0,0 +1,621 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="629.28000pt"
|
||||
height="615.89000pt"
|
||||
id="svg2"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.42.2"
|
||||
sodipodi:docbase="/home/vincent/projects/vmime/doc/book/images"
|
||||
sodipodi:docname="messaging-services.svg"
|
||||
inkscape:export-filename="/home/vincent/www/vmime/documentation/images/design-messaging.png"
|
||||
inkscape:export-xdpi="74.639999"
|
||||
inkscape:export-ydpi="74.639999">
|
||||
<defs
|
||||
id="defs3">
|
||||
<marker
|
||||
inkscape:stockid="Torso"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Torso"
|
||||
style="overflow:visible">
|
||||
<g
|
||||
id="g2045"
|
||||
transform="scale(0.7)">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="path1128"
|
||||
d="M -4.7792281,-3.2395420 C -2.4288541,-2.8736027 0.52103922,-1.3019943 0.25792722,0.38794346 C -0.0051877922,2.0778819 -2.2126741,2.6176539 -4.5630471,2.2517169 C -6.9134221,1.8857769 -8.5210350,0.75201414 -8.2579220,-0.93792336 C -7.9948090,-2.6278615 -7.1296041,-3.6054813 -4.7792281,-3.2395420 z "
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;marker-start:none;marker-mid:none;marker-end:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
id="path1909"
|
||||
d="M 4.4598789,0.088665736 C -2.5564571,-4.3783320 5.2248769,-3.9061806 -0.84829578,-8.7197331"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-end:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
id="path1910"
|
||||
d="M 4.9298719,0.057520736 C -1.3872731,1.7494689 1.8027579,5.4782079 -4.9448731,7.5462725"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" />
|
||||
<rect
|
||||
transform="matrix(0.527536,-0.849533,0.887668,0.460484,0.000000,0.000000)"
|
||||
y="-1.7408575"
|
||||
x="-10.391706"
|
||||
height="2.7608147"
|
||||
width="2.6366582"
|
||||
id="rect2035"
|
||||
style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" />
|
||||
<rect
|
||||
transform="matrix(0.671205,-0.741272,0.790802,0.612072,0.000000,0.000000)"
|
||||
y="-7.9629307"
|
||||
x="4.9587269"
|
||||
height="2.8614161"
|
||||
width="2.7327356"
|
||||
id="rect2036"
|
||||
style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" />
|
||||
<path
|
||||
transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,25.96648,19.71619)"
|
||||
d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z"
|
||||
sodipodi:ry="0.60731727"
|
||||
sodipodi:rx="0.60731727"
|
||||
sodipodi:cy="-28.685045"
|
||||
sodipodi:cx="16.172634"
|
||||
id="path2037"
|
||||
style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,26.82450,16.99126)"
|
||||
d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z"
|
||||
sodipodi:ry="0.60731727"
|
||||
sodipodi:rx="0.60731727"
|
||||
sodipodi:cy="-28.685045"
|
||||
sodipodi:cx="16.172634"
|
||||
id="path2038"
|
||||
style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutL"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="TriangleOutL"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path5324"
|
||||
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
|
||||
transform="scale(0.8)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.75785828"
|
||||
inkscape:cx="365.32198"
|
||||
inkscape:cy="407.27112"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:window-width="1150"
|
||||
inkscape:window-height="986"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<path
|
||||
id="path5442"
|
||||
d="M 495.30781,321.26414 L 495.30781,390.57215"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<path
|
||||
id="path5440"
|
||||
d="M 662.55216,389.28102 L 662.55216,456.99397"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<path
|
||||
id="path5438"
|
||||
d="M 325.22881,389.28102 L 325.22881,456.99397"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
transform="matrix(0.866025,0.499999,-0.499999,0.866025,111.0615,336.6054)"
|
||||
id="g3452">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:5.0000000 5.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
d="M 278.87323,198.08204 L 405.25462,198.08204"
|
||||
id="path3454" />
|
||||
<g
|
||||
transform="matrix(-1.000000,-1.845854e-17,1.845854e-17,-1.000000,684.3929,415.9391)"
|
||||
style="stroke-width:1.2500000;stroke-miterlimit:4.0000000"
|
||||
id="g3456">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 278.87321,217.60074 L 289.31646,228.04398"
|
||||
id="path3458" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 279.22547,217.92243 L 289.41027,207.73763"
|
||||
id="path3460" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(-0.499998,0.866024,-0.866024,-0.499998,528.2205,319.3107)"
|
||||
id="g3396">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:5.0000000 5.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
d="M 278.87323,198.08204 L 405.25462,198.08204"
|
||||
id="path3398" />
|
||||
<g
|
||||
transform="matrix(-1.000000,-1.845854e-17,1.845854e-17,-1.000000,684.3929,415.9391)"
|
||||
style="stroke-width:1.2500000;stroke-miterlimit:4.0000000"
|
||||
id="g3400">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 278.87321,217.60074 L 289.31646,228.04398"
|
||||
id="path3402" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 279.22547,217.92243 L 289.41027,207.73763"
|
||||
id="path3404" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.500000,0.866024,-0.866024,0.500000,431.6077,-252.3913)"
|
||||
id="g3200">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:5.0000000 5.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
d="M 278.87323,198.08204 L 405.25462,198.08204"
|
||||
id="path3202" />
|
||||
<g
|
||||
transform="matrix(-1.000000,-1.845854e-17,1.845854e-17,-1.000000,684.3929,415.9391)"
|
||||
style="stroke-width:1.2500000;stroke-miterlimit:4.0000000"
|
||||
id="g3204">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 278.87321,217.60074 L 289.31646,228.04398"
|
||||
id="path3206" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 279.22547,217.92243 L 289.41027,207.73763"
|
||||
id="path3208" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.499999,-0.866025,0.866025,0.499999,-54.36140,359.0658)"
|
||||
id="g3168">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:5.0000000 5.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
d="M 278.87323,198.08204 L 405.25462,198.08204"
|
||||
id="path3156" />
|
||||
<g
|
||||
transform="matrix(-1.000000,-1.845854e-17,1.845854e-17,-1.000000,684.3929,415.9391)"
|
||||
style="stroke-width:1.2500000;stroke-miterlimit:4.0000000"
|
||||
id="g3158">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 278.87321,217.60074 L 289.31646,228.04398"
|
||||
id="path3160" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 279.22547,217.92243 L 289.41027,207.73763"
|
||||
id="path3162" />
|
||||
</g>
|
||||
</g>
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect1291"
|
||||
width="144.63049"
|
||||
height="123.75754"
|
||||
x="423.21133"
|
||||
y="200.65219" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="430.8407"
|
||||
y="243.43631"
|
||||
id="text1293"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan3116"
|
||||
sodipodi:role="line"
|
||||
y="243.43631"
|
||||
x="430.84070">connect() : void</tspan><tspan
|
||||
id="tspan3118"
|
||||
sodipodi:role="line"
|
||||
y="257.83631"
|
||||
x="430.84070">disconnect() : void</tspan><tspan
|
||||
id="tspan3120"
|
||||
sodipodi:role="line"
|
||||
y="272.23631"
|
||||
x="430.84070">isConnected() : bool</tspan><tspan
|
||||
id="tspan3122"
|
||||
sodipodi:role="line"
|
||||
y="286.63631"
|
||||
x="430.84070">noop() : void</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="473.4863"
|
||||
y="216.58759"
|
||||
id="text2347"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan2932"
|
||||
sodipodi:role="line"
|
||||
y="216.58759"
|
||||
x="473.48630">service</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 423.62452,224.92254 L 567.67587,224.92254"
|
||||
id="path2351" />
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2353"
|
||||
width="254.50919"
|
||||
height="106.53888"
|
||||
x="40.771675"
|
||||
y="200.75146" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="49.807129"
|
||||
y="243.64157"
|
||||
id="text2355"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan3148"
|
||||
sodipodi:role="line"
|
||||
y="243.64157"
|
||||
x="49.807129">getTransport(url : url) : ref <transport></tspan><tspan
|
||||
id="tspan3150"
|
||||
sodipodi:role="line"
|
||||
y="258.04157"
|
||||
x="49.807129">getStore(url : url) : ref <store></tspan><tspan
|
||||
id="tspan3152"
|
||||
sodipodi:role="line"
|
||||
y="272.44157"
|
||||
x="49.807129">getProperties() : propertySet</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="143.33478"
|
||||
y="216.79285"
|
||||
id="text2375"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan3124"
|
||||
sodipodi:role="line"
|
||||
y="216.79285"
|
||||
x="143.33478">session</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 41.137120,225.12780 L 294.90028,225.12780"
|
||||
id="path2379" />
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2433"
|
||||
width="219.00885"
|
||||
height="100.80741"
|
||||
x="215.20381"
|
||||
y="429.00940" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="223.58997"
|
||||
y="472.3562"
|
||||
id="text2435"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan3110"
|
||||
sodipodi:role="line"
|
||||
y="472.35620"
|
||||
x="223.58997">getDefaultFolder() : ref <folder></tspan><tspan
|
||||
id="tspan3112"
|
||||
sodipodi:role="line"
|
||||
y="486.75620"
|
||||
x="223.58997">getRootFolder() : ref <folder></tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="309.11777"
|
||||
y="445.50742"
|
||||
id="text2439"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan2936"
|
||||
sodipodi:role="line"
|
||||
y="445.50742"
|
||||
x="309.11777">store</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 216.61640,453.84241 L 433.36337,453.84241"
|
||||
id="path2443" />
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect2447"
|
||||
width="219.00674"
|
||||
height="101.04262"
|
||||
x="553.75336"
|
||||
y="428.77499" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="561.0639"
|
||||
y="472.20447"
|
||||
id="text2449"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan3114"
|
||||
sodipodi:role="line"
|
||||
y="472.20447"
|
||||
x="561.06390">send(msg : ref <message>) : void</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="632.07196"
|
||||
y="445.35568"
|
||||
id="text2453"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan2934"
|
||||
sodipodi:role="line"
|
||||
y="445.35568"
|
||||
x="632.07196">transport</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 554.08593,453.69062 L 771.88660,453.69062"
|
||||
id="path2457" />
|
||||
<path
|
||||
id="path2575"
|
||||
d="M 481.88130,340.17064 L 509.77022,340.17064 L 495.36094,325.76137 L 481.88130,340.17064 z "
|
||||
style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<g
|
||||
transform="translate(17.15883,45.55696)"
|
||||
id="g3136">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 405.51967,217.85706 L 279.13828,217.85706"
|
||||
id="path2265" />
|
||||
<g
|
||||
style="stroke-width:1.2500000;stroke-miterlimit:4.0000000"
|
||||
id="g3132">
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 278.87321,217.60074 L 289.31646,228.04398"
|
||||
id="path2269" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
d="M 279.22547,217.92243 L 289.41027,207.73763"
|
||||
id="path2271" />
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
sodipodi:linespacing="100.00000%"
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="335.37018"
|
||||
y="257.45505"
|
||||
id="text2275"><tspan
|
||||
id="tspan3146"
|
||||
sodipodi:role="line"
|
||||
y="257.45505"
|
||||
x="335.37018">session</tspan></text>
|
||||
<text
|
||||
transform="matrix(0.500000,0.866025,-0.866025,0.500000,0.000000,0.000000)"
|
||||
sodipodi:linespacing="100.00000%"
|
||||
xml:space="preserve"
|
||||
style="font-size:11.999973px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="313.42676"
|
||||
y="-318.0412"
|
||||
id="text3174"><tspan
|
||||
id="tspan3178"
|
||||
sodipodi:role="line"
|
||||
y="-318.04120"
|
||||
x="313.42676"><instanciates></tspan></text>
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect3180"
|
||||
width="253.81813"
|
||||
height="96.037521"
|
||||
x="234.02649"
|
||||
y="9.0948601" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="241.24963"
|
||||
y="52.019093"
|
||||
id="text3182"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan3218"
|
||||
sodipodi:role="line"
|
||||
y="52.019093"
|
||||
x="241.24963">create(protocol : string) : ref <service></tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="312.24161"
|
||||
y="25.170307"
|
||||
id="text3192"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan3198"
|
||||
sodipodi:role="line"
|
||||
y="25.170307"
|
||||
x="312.24161">serviceFactory</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 234.44127,33.505080 L 487.67742,33.505080"
|
||||
id="path3196" />
|
||||
<text
|
||||
transform="matrix(0.500000,-0.866025,0.866025,0.500000,0.000000,0.000000)"
|
||||
sodipodi:linespacing="100.00000%"
|
||||
xml:space="preserve"
|
||||
style="font-size:11.999965px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="-19.006903"
|
||||
y="316.46106"
|
||||
id="text3210"><tspan
|
||||
id="tspan3214"
|
||||
sodipodi:role="line"
|
||||
y="316.46106"
|
||||
x="-19.006903"><uses></tspan></text>
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect3362"
|
||||
width="244.86130"
|
||||
height="116.61144"
|
||||
x="14.277589"
|
||||
y="572.10736" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="22.589966"
|
||||
y="615.3562"
|
||||
id="text3364"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan3386"
|
||||
sodipodi:role="line"
|
||||
y="615.35620"
|
||||
x="22.589966">getName() : string</tspan><tspan
|
||||
id="tspan3388"
|
||||
sodipodi:role="line"
|
||||
y="629.75620"
|
||||
x="22.589966">open() : void</tspan><tspan
|
||||
id="tspan3390"
|
||||
sodipodi:role="line"
|
||||
y="644.15620"
|
||||
x="22.589966">close() : void</tspan><tspan
|
||||
id="tspan3392"
|
||||
sodipodi:role="line"
|
||||
y="658.55620"
|
||||
x="22.589966">getMessages(int from, int to) : vector</tspan><tspan
|
||||
id="tspan3394"
|
||||
sodipodi:role="line"
|
||||
y="672.95620"
|
||||
x="22.589966">...</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="119.45631"
|
||||
y="588.50739"
|
||||
id="text3370"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan3376"
|
||||
sodipodi:role="line"
|
||||
y="588.50739"
|
||||
x="119.45631">folder</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2449049;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 15.691587,596.84241 L 258.28817,596.84241"
|
||||
id="path3374" />
|
||||
<text
|
||||
transform="matrix(0.500000,-0.866025,0.866025,0.500000,0.000000,0.000000)"
|
||||
sodipodi:linespacing="100.00000%"
|
||||
xml:space="preserve"
|
||||
style="font-size:11.999992px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="-398.12543"
|
||||
y="406.40524"
|
||||
id="text3406"><tspan
|
||||
id="tspan3408"
|
||||
sodipodi:role="line"
|
||||
y="406.40524"
|
||||
x="-398.12543"><instanciates></tspan></text>
|
||||
<rect
|
||||
style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
|
||||
id="rect3410"
|
||||
width="244.86130"
|
||||
height="140.35690"
|
||||
x="365.27762"
|
||||
y="617.23462" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="373.59"
|
||||
y="660.3562"
|
||||
id="text3412"
|
||||
sodipodi:linespacing="120.00000%"><tspan
|
||||
id="tspan3440"
|
||||
sodipodi:role="line"
|
||||
y="660.35620"
|
||||
x="373.59000">getNumber() : int</tspan><tspan
|
||||
id="tspan3442"
|
||||
sodipodi:role="line"
|
||||
y="674.75620"
|
||||
x="373.59000">getFlags() : int</tspan><tspan
|
||||
id="tspan3444"
|
||||
sodipodi:role="line"
|
||||
y="689.15620"
|
||||
x="373.59000">getHeader() : int</tspan><tspan
|
||||
id="tspan3446"
|
||||
sodipodi:role="line"
|
||||
y="703.55620"
|
||||
x="373.59000">getStructure() : structure</tspan><tspan
|
||||
id="tspan3448"
|
||||
sodipodi:role="line"
|
||||
y="717.95620"
|
||||
x="373.59000">extract(out : outputStream) : void</tspan><tspan
|
||||
id="tspan3450"
|
||||
sodipodi:role="line"
|
||||
y="732.35620"
|
||||
x="373.59000">...</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="459.11771"
|
||||
y="633.50739"
|
||||
id="text3424"
|
||||
sodipodi:linespacing="100.00000%"><tspan
|
||||
id="tspan3430"
|
||||
sodipodi:role="line"
|
||||
y="633.50739"
|
||||
x="459.11771">message</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2449049;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
|
||||
d="M 366.69159,641.84241 L 609.28817,641.84241"
|
||||
id="path3428" />
|
||||
<text
|
||||
transform="matrix(0.866025,0.500000,-0.500000,0.866025,0.000000,0.000000)"
|
||||
sodipodi:linespacing="100.00000%"
|
||||
xml:space="preserve"
|
||||
style="font-size:11.999992px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
|
||||
x="558.315"
|
||||
y="419.37476"
|
||||
id="text3462"><tspan
|
||||
id="tspan3464"
|
||||
sodipodi:role="line"
|
||||
y="419.37476"
|
||||
x="558.31500"><instanciates></tspan></text>
|
||||
</g>
|
||||
<path
|
||||
id="path5436"
|
||||
d="M 325.97175,390.06210 L 661.85821,390.06210"
|
||||
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2515085;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
|
||||
<rect
|
||||
y="102.22088"
|
||||
x="-7.6927943"
|
||||
height="76.000000"
|
||||
width="106.00000"
|
||||
id="rect3358"
|
||||
style="fill:none;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.2500000;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
|
||||
<rect
|
||||
y="170.36218"
|
||||
x="668.00000"
|
||||
height="76.000000"
|
||||
width="134.00000"
|
||||
id="rect3360"
|
||||
style="stroke-opacity:1.0000000;stroke-dashoffset:0.0000000;stroke-miterlimit:4.0000000;stroke-linejoin:miter;stroke-linecap:round;stroke-width:1.2500000;stroke:none;fill-rule:nonzero;fill-opacity:1.0000000;fill:none" />
|
||||
</svg>
|
After Width: | Height: | Size: 31 KiB |
90
doc/book/intro.tex
Normal file
90
doc/book/intro.tex
Normal file
@ -0,0 +1,90 @@
|
||||
\chapter{Introduction}
|
||||
|
||||
% ============================================================================
|
||||
\section{Overview}
|
||||
|
||||
VMime is a powerful C++ class library for working with MIME messages and
|
||||
Internet messaging services like IMAP, POP or SMTP.
|
||||
|
||||
With VMime you can parse, generate and modify messages, and also connect to
|
||||
store and transport services to receive or send messages over the Internet.
|
||||
The library offers all the features to build a complete mail client.
|
||||
|
||||
The main objectives of this library are:
|
||||
|
||||
\begin{itemize}
|
||||
\item fully RFC-compliant implementation;
|
||||
\item object-oriented and modular design;
|
||||
\item very easy-to-use (intuitive design);
|
||||
\item well documented code;
|
||||
\item very high reliability;
|
||||
\item maximum portability.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
% ============================================================================
|
||||
\section{Features}
|
||||
|
||||
\noindent MIME features:
|
||||
|
||||
\begin{itemize}
|
||||
\item Full support for RFC-2822 and multipart messages (RFC-1521)
|
||||
\item Aggregate documents (MHTML) and embedded objects (RFC-2557)
|
||||
\item Message Disposition Notification (RFC-3798)
|
||||
\item 8-bit MIME (RFC-2047)
|
||||
\item Encoded word extensions (RFC-2231)
|
||||
\item Attachments
|
||||
\end{itemize}
|
||||
|
||||
\noindent Network features:
|
||||
|
||||
\begin{itemize}
|
||||
\item Support for IMAP, POP3 and maildir stores
|
||||
\item Support for SMTP and sendmail transport methods
|
||||
\item Extraction of whole message or specific parts
|
||||
\item TLS/SSL security layer
|
||||
\item SASL authentication
|
||||
\end{itemize}
|
||||
|
||||
|
||||
% ============================================================================
|
||||
\section{Copyright and license}
|
||||
|
||||
VMime library is Free Software and is licensed under the terms of the GNU
|
||||
General Public License\footnote{See Appendix \ref{appendix_license} and
|
||||
\url{http://www.gnu.org/copyleft/gpl.html}} (GPL):
|
||||
|
||||
\begin{verbatim}
|
||||
Copyright (C) 2002-2005 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
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
VMime is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Linking this library statically or dynamically with other
|
||||
modules is making a combined work based on this library.
|
||||
Thus, the terms and conditions of the GNU General Public
|
||||
License cover the whole combination.
|
||||
\end{verbatim}
|
||||
|
||||
\newpage
|
||||
\noindent This document is released under the terms of the
|
||||
GNU Free Documentation
|
||||
License\footnote{See \url{http://www.gnu.org/copyleft/fdl.html}} (FDL):
|
||||
|
||||
\begin{verbatim}
|
||||
Copyright (C) 2004-2005 Vincent Richard
|
||||
|
||||
Permission is granted to copy, distribute and/or modify
|
||||
this document under the terms of the GNU Free Documentation
|
||||
License, Version 1.2 or any later version published by the
|
||||
Free Software Foundation; with no Invariant Sections, no
|
||||
Front-Cover Texts, and no Back-Cover Texts.
|
||||
\end{verbatim}
|
||||
|
385
doc/book/msg.tex
Normal file
385
doc/book/msg.tex
Normal file
@ -0,0 +1,385 @@
|
||||
\chapter{Parsing and Building Messages}
|
||||
|
||||
% ============================================================================
|
||||
\section{Parsing messages}
|
||||
|
||||
\subsection{Introduction} % --------------------------------------------------
|
||||
|
||||
Parsing is the process of creating a structured representation (for example,
|
||||
a hierarchy of C++ objects) of a message from its ``textual'' representation
|
||||
(the raw data that is actually sent on the Internet).
|
||||
|
||||
For example, say you have the following email in a file called "hello.eml":
|
||||
|
||||
\begin{verbatim}
|
||||
Date: Thu, Oct 13 2005 15:22:46 +0200
|
||||
From: Vincent <vincent@vmime.org>
|
||||
To: you@vmime.org
|
||||
Subject: Hello from VMime!
|
||||
|
||||
A simple message to test VMime
|
||||
\end{verbatim}
|
||||
|
||||
The following code snippet shows how you can easily obtain a
|
||||
{\vcode vmime::message} object from data in this file:
|
||||
|
||||
\begin{lstlisting}[caption={Parsing a message from a file}]
|
||||
// Read data from file
|
||||
std::ifstream file;
|
||||
file.open("hello.eml", std::ios::in | std::ios::binary);
|
||||
|
||||
vmime::utility::inputStreamAdapter is(file);
|
||||
|
||||
vmime::string data;
|
||||
vmime::utility::outputStreamStringAdapter os(data);
|
||||
|
||||
vmime::utility::bufferedStreamCopy(is, os);
|
||||
|
||||
// Actually parse the message
|
||||
vmime::ref <vmime::message> msg = vmime::create <vmime::message>();
|
||||
msg->parse(data);
|
||||
|
||||
vmime::ref <vmime::header> hdr = msg->getHeader();
|
||||
vmime::ref <vmime::body> bdy = msg->getBody();
|
||||
|
||||
// Now, you can extract some of its components
|
||||
vmime::charset ch(vmime::charsets::UTF_8);
|
||||
|
||||
std::cout
|
||||
<< "The subject of the message is: "
|
||||
<< hdr->Subject()->getValue().getDecodedText(ch)
|
||||
<< std::endl
|
||||
<< "It was sent by: "
|
||||
<< hdr->From()->getValue().getName().getDecodedText(ch)
|
||||
<< " (email: " << hdr->From()->getValue().getEmail() << ")"
|
||||
<< std::endl;
|
||||
\end{lstlisting}
|
||||
|
||||
The output of this program is:
|
||||
|
||||
\begin{verbatim}
|
||||
The subject of the message is: Hello from VMime!
|
||||
It was sent by: Vincent (email: vincent@vmime.org)
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
\subsection{Using the {\vcode vmime::messageParser} object} % ----------------
|
||||
|
||||
The {\vcode vmime::messageParser} object allows to parse messages in a more
|
||||
simple manner. You can obtain all the text parts and attachments as well as
|
||||
basic fields (expeditor, recipients, subject...), without dealing with
|
||||
MIME message structure.
|
||||
|
||||
\begin{lstlisting}[caption={Using {\vcode vmime::messageParser} to parse
|
||||
more complex messages}]
|
||||
// Read data from file
|
||||
std::ifstream file;
|
||||
file.open("hello.eml", std::ios::in | std::ios::binary);
|
||||
|
||||
vmime::utility::inputStreamAdapter is(file);
|
||||
|
||||
vmime::string data;
|
||||
vmime::utility::outputStreamStringAdapter os(data);
|
||||
|
||||
vmime::utility::bufferedStreamCopy(is, os);
|
||||
|
||||
// Actually parse the message
|
||||
vmime::ref <vmime::message> msg = vmime::create <vmime::message>();
|
||||
msg->parse(data);
|
||||
|
||||
// Here start the differences with the previous example
|
||||
vmime::messageParser mp(msg);
|
||||
|
||||
// Output information about attachments
|
||||
std::cout << "Message has " << mp.getAttachmentCount()
|
||||
<< " attachment(s)" << std::endl;
|
||||
|
||||
for (int i = 0 ; i < mp.getAttachmentCount() ; ++i)
|
||||
{
|
||||
vmime::ref <const vmime::attachment> att = mp.getAttachmentAt(i);
|
||||
std::cout << " - " << att->getType().generate() << std::endl;
|
||||
}
|
||||
|
||||
// Output information about text parts
|
||||
std::cout << "Message has " << mp.getTextPartCount()
|
||||
<< " text part(s)" << std::endl;
|
||||
|
||||
for (int i = 0 ; i < mp.getTextPartCount() ; ++i)
|
||||
{
|
||||
vmime::ref <const vmime::textPart> tp = mp.getTextPartAt(i);
|
||||
|
||||
// text/html
|
||||
if (tp->getType().getSubType() == vmime::mediaTypes::TEXT_HTML)
|
||||
{
|
||||
vmime::ref <const vmime::htmlTextPart> htp =
|
||||
tp.dynamicCast <const vmime::htmlTextPart>();
|
||||
|
||||
// HTML text is in tp->getText()
|
||||
// Plain text is in tp->getPlainText()
|
||||
|
||||
// Enumerate embedded objects
|
||||
for (int j = 0 ; j < htp->getObjectCount() ; ++j)
|
||||
{
|
||||
vmime::ref <const vmime::htmlTextPart::embeddedObject> 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
|
||||
{
|
||||
// Text is in tp->getText()
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
% ============================================================================
|
||||
\section{Building messages}
|
||||
|
||||
\subsection{A simple message\label{msg-building-simple-message}} % -----------
|
||||
|
||||
Of course, you can build a MIME message from scratch by creating the various
|
||||
objects that compose it (parts, fields, etc.). The following is an example of
|
||||
how to achieve it:
|
||||
|
||||
\begin{lstlisting}[caption={Building a simple message from scratch}]
|
||||
vmime::ref <vmime::message> msg = vmime::create <vmime::message>();
|
||||
|
||||
vmime::ref <vmime::header> hdr = msg->getHeader();
|
||||
vmime::ref <vmime::body> bdy = msg->getBody();
|
||||
|
||||
vmime::headerFieldFactory* hfFactory =
|
||||
vmime::headerFieldFactory::getInstance();
|
||||
|
||||
// Append a 'Date:' field
|
||||
vmime::ref <vmime::headerField> dateField =
|
||||
hfFactory->create(vmime::fields::DATE);
|
||||
|
||||
dateField->setValue(vmime::datetime::now());
|
||||
hdr->appendField(dateField);
|
||||
|
||||
// Append a 'Subject:' field
|
||||
vmime::ref <vmime::headerField> subjectField =
|
||||
hfFactory->create(vmime::fields::SUBJECT);
|
||||
|
||||
subjectField->setValue(vmime::text("Message subject"));
|
||||
hdr->appendField(subjectField);
|
||||
|
||||
// Append a 'From:' field
|
||||
vmime::ref <vmime::headerField> fromField =
|
||||
hfFactory->create(vmime::fields::FROM);
|
||||
|
||||
fromField->setValue
|
||||
(vmime::create <vmime::mailbox>("me@vmime.org"));
|
||||
hdr->appendField(fromField);
|
||||
|
||||
// Append a 'To:' field
|
||||
vmime::ref <vmime::headerField> toField =
|
||||
hfFactory->create(vmime::fields::TO);
|
||||
|
||||
vmime::ref <vmime::mailboxList> recipients =
|
||||
vmime::create <vmime::mailboxList>();
|
||||
|
||||
recipients->appendMailbox
|
||||
(vmime::create <vmime::mailbox>("you@vmime.org"));
|
||||
|
||||
toField->setValue(recipients);
|
||||
hdr->appendField(toField);
|
||||
|
||||
// Set the body contents
|
||||
bdy->setContents(vmime::create <vmime::stringContentHandler>
|
||||
("This is the text of your message..."));
|
||||
|
||||
// Output raw message data to standard output
|
||||
vmime::utility::outputStreamAdapter out(std::cout);
|
||||
msg->generate(out);
|
||||
\end{lstlisting}
|
||||
|
||||
As you can see, this is a little fastidious. Hopefully, VMime also offers a
|
||||
more simple way for creating messages. The {\vcode vmime::messageBuilder}
|
||||
object can create basic messages that you can then customize.
|
||||
|
||||
The following code can be used to build exactly the same message as in the
|
||||
previous example, using the {\vcode vmime::messageBuilder} object:
|
||||
|
||||
\begin{lstlisting}[caption={Building a simple message
|
||||
using {\vcode vmime::messageBuilder}}]
|
||||
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::create <vmime::mailbox>("you@vmime.org"));
|
||||
|
||||
mb.getTextPart()->setCharset(vmime::charsets::ISO8859_15);
|
||||
mb.getTextPart()->setText(vmime::create <vmime::stringContentHandler>
|
||||
("This is the text of your message..."));
|
||||
|
||||
// Message construction
|
||||
vmime::ref <vmime::message> msg = mb.construct();
|
||||
|
||||
// Output raw message data to standard output
|
||||
vmime::utility::outputStreamAdapter out(std::cout);
|
||||
msg->generate(out);
|
||||
}
|
||||
// VMime exception
|
||||
catch (vmime::exception& e)
|
||||
{
|
||||
std::cerr << "vmime::exception: " << e.what() << std::endl;
|
||||
}
|
||||
// Standard exception
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "std::exception: " << e.what() << std::endl;
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\subsection{Adding an attachment} % ------------------------------------------
|
||||
|
||||
Dealing with attachments is quite simple. Add the following code to the
|
||||
previous example to attach a file to the message:
|
||||
|
||||
\begin{lstlisting}[caption={Building a message with an attachment using
|
||||
{\vcode vmime::messageBuilder}}]
|
||||
// Create an attachment
|
||||
vmime::ref <vmime::fileAttachment> att =
|
||||
vmime::create <vmime::fileAttachment>
|
||||
(
|
||||
/* 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"));
|
||||
|
||||
// Add this attachment to the message
|
||||
mb.appendAttachment(att);
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\subsection{HTML messages and embedded objects} % ----------------------------
|
||||
|
||||
VMime also supports aggregated messages, which permits to build MIME messages
|
||||
containing HTML text and embedded objects (such as images).
|
||||
|
||||
Creating such messages is quite easy, using the {\vcode vmime::messageBuilder}
|
||||
object. The following code constructs a message containing text in both plain
|
||||
and HTML format, and a JPEG image:
|
||||
|
||||
\begin{lstlisting}[caption={Building an HTML message with an embedded image
|
||||
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::create <vmime::mailbox>("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));
|
||||
|
||||
// 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.
|
||||
vmime::ref <vmime::htmlTextPart> textPart =
|
||||
mb.getTextPart().dynamicCast <vmime::htmlTextPart>();
|
||||
|
||||
// -- add the JPEG image (the returned identifier is used to identify the
|
||||
// -- embedded object in the HTML text, the famous "CID", or "Content-Id")
|
||||
vmime::string id = textPart->addObject("<...image data...>",
|
||||
vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG));
|
||||
|
||||
// -- set the text
|
||||
textPart->setCharset(vmime::charsets::ISO8859_15);
|
||||
|
||||
textPart->setText(vmime::create <vmime::stringContentHandler>
|
||||
("This is the <b>HTML text</b>, and the image:<br/>"
|
||||
"<img src=\"") + id + vmime::string("\"/>"));
|
||||
|
||||
textPart->setPlainText(vmime::create <vmime::stringContentHandler>
|
||||
("This is the plain text."));
|
||||
\end{lstlisting}
|
||||
|
||||
This will create a message having the following structure:
|
||||
|
||||
\begin{verbatim}
|
||||
multipart/alternative
|
||||
text/plain
|
||||
multipart/related
|
||||
text/html
|
||||
image/jpeg
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
% ============================================================================
|
||||
\section{Working with attachments: the attachment helper}
|
||||
|
||||
The {\vcode attachmentHelper} object allows listing all attachments in a
|
||||
message, as well as adding new attachments, without using the
|
||||
{\vcode messageParser} and {\vcode messageBuilders} objects. It can work
|
||||
directly on messages and body parts.
|
||||
|
||||
To use it, you do not need any knowledge about how attachment parts should
|
||||
be organized in a MIME message.
|
||||
|
||||
The following code snippet tests if a body part is an attachment, and if so,
|
||||
extract its contents to the standard output:
|
||||
|
||||
\begin{lstlisting}[caption={Testing if a body part is an attachment}]
|
||||
vmime::ref <vmime::bodyPart> part; // suppose we have a body part
|
||||
|
||||
if (vmime::attachmentHelper::isBodyPartAnAttachment(part))
|
||||
{
|
||||
// The body part contains an attachment, get it
|
||||
vmime::ref <const vmime::attachment> attach =
|
||||
attachmentHelper::getBodyPartAttachment(part);
|
||||
|
||||
// Extract attachment data to standard output
|
||||
vmime::utility::outputStreamAdapter out(std::cout);
|
||||
attach->getData()->extract(out);
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
You can also easily extract all attachments from a message:
|
||||
|
||||
\begin{lstlisting}[caption={Extracting all attachments from a message}]
|
||||
vmime::ref <vmime::message> msg; // suppose we have a message
|
||||
|
||||
const std::vector <ref <const attachment> > atts =
|
||||
attachmentHelper::findAttachmentsInMessage(msg);
|
||||
\end{lstlisting}
|
||||
|
||||
Finally, the {\vcode attachmentHelper} object can be used to add an
|
||||
attachment to an existing message, whatever it contains (text parts,
|
||||
attachments, ...). The algorithm can modify the structure of the
|
||||
message if needed (eg. add a \emph{multipart/mixed} part if no one
|
||||
exists in the message). Simply call the {\vcode addAttachment}
|
||||
function:
|
||||
|
||||
\begin{lstlisting}[caption={Adding an attachment to an existing message}]
|
||||
vmime::ref <vmime::message> msg; // suppose we have a message
|
||||
|
||||
// Create an attachment
|
||||
vmime::ref <vmime::fileAttachment> att =
|
||||
vmime::create <vmime::fileAttachment>
|
||||
(
|
||||
/* 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
|
||||
vmime::attachmentHelper::addAttachment(msg, att);
|
||||
\end{lstlisting}
|
||||
|
946
doc/book/net.tex
Normal file
946
doc/book/net.tex
Normal file
@ -0,0 +1,946 @@
|
||||
\chapter{Working with Messaging Services}
|
||||
|
||||
% ============================================================================
|
||||
\section{Introduction}
|
||||
|
||||
In addition to parsing and building MIME messages, VMime also offers a lot of
|
||||
features to work with messaging services. This includes connecting to remote
|
||||
messaging stores (like IMAP or POP3), local stores (maildir) and transport
|
||||
services (send messages over SMTP or local sendmail), through an unified
|
||||
interface (see Figure \ref{uml_messaging_module}). That means that you can
|
||||
use independently IMAP of POP3 without having to change any line of code.
|
||||
|
||||
Source code of {\vexample Example6} covers all features presented in this
|
||||
chapter, so it is important you take some time to read it.
|
||||
|
||||
\begin{figure}
|
||||
\center\includegraphics[width=0.9\textwidth]
|
||||
{images/messaging-services.png}
|
||||
\caption{Overall structure of the messaging module}
|
||||
\label{uml_messaging_module}
|
||||
\end{figure}
|
||||
|
||||
The interface is composed of five classes:
|
||||
|
||||
\begin{itemize}
|
||||
\item {\vcode vmime::net::service}: this is the base interface for a
|
||||
messaging service. It can be either a store service or a transport
|
||||
service.
|
||||
|
||||
\item {\vcode vmime::net::serviceFactory}: create instances of a service.
|
||||
This is used internally by the session object (see below).
|
||||
|
||||
\item {\vcode vmime::net::store}: interface for a store service. A store
|
||||
service offers access to a set of folders containing messages. This is
|
||||
used for IMAP, POP3 and maildir.
|
||||
|
||||
\item {\vcode vmime::net::transport}: interface for a transport service.
|
||||
A transport service is capable of sending messages. This is used for
|
||||
SMTP and sendmail.
|
||||
|
||||
\item {\vcode vmime::net::session}: a session oject is used to store the
|
||||
parameters used by a service (eg. connection parameters). Each service
|
||||
instance is associated with only one session. The session object is capable
|
||||
of creating instances of services.
|
||||
\end{itemize}
|
||||
|
||||
The following classes are specific to store services:
|
||||
|
||||
\begin{itemize}
|
||||
\item {\vcode vmime::net::folder}: a folder can either contain other folders
|
||||
or messages, or both.
|
||||
|
||||
\item {\vcode vmime::net::message}: this is the interface for dealing with
|
||||
messages. For a given message, you can have access to its flags, its MIME
|
||||
structure and you can also extract the whole message data or given parts (if
|
||||
supported by the underlying protocol).
|
||||
\end{itemize}
|
||||
|
||||
|
||||
% ============================================================================
|
||||
\section{Working with sessions}
|
||||
|
||||
\subsection{Setting properties} % --------------------------------------------
|
||||
|
||||
Sessions are used to store configuration parameters for services. They
|
||||
contains a set of typed properties that can modify the behaviour of the
|
||||
services. Before using a messaging service, you must create and
|
||||
initialize a session object:
|
||||
|
||||
\begin{lstlisting}
|
||||
vmime::ref <net::session> theSession = vmime::create <net::session>();
|
||||
\end{lstlisting}
|
||||
|
||||
Session properties include:
|
||||
|
||||
\begin{itemize}
|
||||
\item connection parameters: host and port to connect to;
|
||||
\item authentication parameters: user credentials required to use the
|
||||
service (if any);
|
||||
\item protocol-specific parameters: enable or disable extensions (eg. APOP
|
||||
support in POP3).
|
||||
\end{itemize}
|
||||
|
||||
Properties are stored using a dotted notation, to specify the service type,
|
||||
the protocol name, the category and the name of the property:
|
||||
|
||||
\begin{verbatim}
|
||||
{service_type}.{protocol}.category.name
|
||||
\end{verbatim}
|
||||
|
||||
An example of property is \emph{store.pop3.options.apop} (used to enable or
|
||||
disable the use of APOP authentication). The \emph{store.pop3} part is called
|
||||
the \emph{prefix}. This allow specifying different values for the same
|
||||
property depending on the protocol used.
|
||||
|
||||
The session properties are stored in a {\vcode vmime::propertySet} object.
|
||||
To set the value of a property, you can use either:
|
||||
|
||||
\begin{lstlisting}
|
||||
theSession->getProperties().setProperty("property-name", value);
|
||||
\end{lstlisting}
|
||||
|
||||
or:
|
||||
|
||||
\begin{lstlisting}
|
||||
theSession->getProperties()["property-name"] = value;
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\subsection{Available properties} % ------------------------------------------
|
||||
|
||||
Following is a list of available properties and the protocols they apply to,
|
||||
as the time of writing this documentation\footnote{You can get an up-to-date
|
||||
list of the properties by running \vexample{Example7}}. For better clarity,
|
||||
the prefixes do not appear in this table.
|
||||
|
||||
\begin{table}[!ht]
|
||||
\noindent\begin{tabularx}{1.0\textwidth}{|l|c|X|c|c|c|c|c|c|c|c|}
|
||||
\hline
|
||||
{\bf Property name} &
|
||||
{\bf Type} &
|
||||
{\bf Description} &
|
||||
\verti{\bf POP3} &
|
||||
\verti{\bf POP3S} &
|
||||
\verti{\bf IMAP} &
|
||||
\verti{\bf IMAPS} &
|
||||
\verti{\bf SMTP} &
|
||||
\verti{\bf SMTPS} &
|
||||
\verti{\bf maildir} &
|
||||
\verti{\bf sendmail} \\
|
||||
\hline
|
||||
\hline
|
||||
options.sasl & bool & Set to {\vcode true} to use SASL authentication, if
|
||||
available. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\
|
||||
\hline
|
||||
options.sasl.fallback & bool & Fail if SASL authentication failed (do not
|
||||
try other authentication mechanisms). & \vdot & \vdot & \vdot & \vdot &
|
||||
\vdot & \vdot & & \\
|
||||
\hline
|
||||
auth.username\footnote{You should use authenticators
|
||||
instead.\label{fn_auth_username}} & string & Set the username of the account
|
||||
to connect to. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\
|
||||
\hline
|
||||
auth.password\footref{fn_auth_username} & string & Set the password of the
|
||||
account. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\
|
||||
\hline
|
||||
connection.tls & bool & Set to {\vcode true} to start a secured connection
|
||||
using STARTTLS extension, if available. & \vdot & & \vdot & & \vdot & & & \\
|
||||
\hline
|
||||
connection.tls.required & bool & Fail if a secured connection cannot be
|
||||
started. & \vdot & & \vdot & & \vdot & & & \\
|
||||
\hline
|
||||
server.address & string & Server host name or IP address. &\vdot & \vdot &
|
||||
\vdot & \vdot & \vdot & \vdot & & \\
|
||||
\hline
|
||||
server.port & int & Server port. & \vdot & \vdot & \vdot & \vdot &
|
||||
\vdot & \vdot & & \\
|
||||
\hline
|
||||
server.rootpath & string & Root directory for mail repository (eg.
|
||||
\emph{/home/vincent/Mail}). & & & & & & & \vdot & \\
|
||||
\hline
|
||||
\end{tabularx}
|
||||
\caption{Properties common to all protocols}
|
||||
\end{table}
|
||||
|
||||
\newpage
|
||||
These are the protocol-specific options:
|
||||
|
||||
\begin{table}[!ht]
|
||||
\noindent\begin{tabularx}{1.0\textwidth}{|l|c|X|}
|
||||
\hline
|
||||
{\bf Property name} &
|
||||
{\bf Type} &
|
||||
{\bf Description} \\
|
||||
% POP3/POP3S
|
||||
\hline
|
||||
\multicolumn{3}{|c|}{POP3, POP3S} \\
|
||||
\hline
|
||||
store.pop3.options.apop & bool & Enable or disable authentication with
|
||||
APOP (if SASL is enabled, this occurs after all SASL mechanisms have been
|
||||
tried). \\
|
||||
\hline
|
||||
store.pop3.options.apop.fallback & bool & If set to {\vcode true} and
|
||||
APOP fails, the authentication process fails (ie. unsecure plain text
|
||||
authentication is not used). \\
|
||||
\hline
|
||||
% SMTP
|
||||
\multicolumn{3}{|c|}{SMTP, SMTPS} \\
|
||||
\hline
|
||||
transport.smtp.options.need-authentication & bool & Set to \emph{true} if
|
||||
the server requires to authenticate before sending messages. \\
|
||||
\hline
|
||||
% sendmail
|
||||
\multicolumn{3}{|c|}{sendmail} \\
|
||||
\hline
|
||||
transport.sendmail.binpath & string & The path to the \emph{sendmail}
|
||||
executable on your system. The default is the one found by the configuration
|
||||
script when VMime was built. \\
|
||||
\hline
|
||||
\end{tabularx}
|
||||
\caption{Protocol-specific options}
|
||||
\end{table}
|
||||
|
||||
|
||||
\subsection{Instanciating services} % ----------------------------------------
|
||||
|
||||
You can create a service either by specifying its protocol name, or by
|
||||
specifying the URL of the service. Creation by name is deprecated so
|
||||
this chapter only presents the latter option.
|
||||
|
||||
The URL scheme for connecting to services is:
|
||||
|
||||
\begin{verbatim}
|
||||
protocol://[username[:password]@]host[:port]/[root-path]
|
||||
\end{verbatim}
|
||||
|
||||
\vnote{For local services (ie. \emph{sendmail} and \emph{maildir}), the host
|
||||
part is not used, but it must not be empty (you can use "localhost").}
|
||||
|
||||
The following table shows an example URL for each service:
|
||||
|
||||
\noindent\begin{tabularx}{1.0\textwidth}{|c|X|}
|
||||
\hline
|
||||
{\bf Service} &
|
||||
{\bf Connection URL} \\
|
||||
\hline
|
||||
imap, imaps & {\tt imap://imap.example.com},
|
||||
{\tt imaps://vincent:pass@example.com} \\
|
||||
\hline
|
||||
pop3, pop3s & {\tt pop3://pop3.example.com} \\
|
||||
\hline
|
||||
smtp, smtps & {\tt smtp://smtp.example.com} \\
|
||||
\hline
|
||||
maildir & {\tt maildir://localhost/home/vincent/Mail} (host not used) \\
|
||||
\hline
|
||||
sendmail & {\tt sendmail://localhost} (host not used, always localhost) \\
|
||||
\hline
|
||||
\end{tabularx}
|
||||
|
||||
\newpage
|
||||
|
||||
When you have the connection URL, instanciating the service is quite simple.
|
||||
Depending on the type of service, you will use either {\vcode getStore()} or
|
||||
{\vcode getTransport()}. For example, for store services, use:
|
||||
|
||||
\begin{lstlisting}
|
||||
vmime::utility:url url("imap://user:pass@imap.example.com");
|
||||
vmime::ref <vmime::net::store> st = sess->getStore(url);
|
||||
\end{lstlisting}
|
||||
|
||||
and for transport services:
|
||||
|
||||
\begin{lstlisting}
|
||||
vmime::utility:url url("smtp://smtp.example.com");
|
||||
vmime::ref <vmime::net::transport> tr = sess->getTransport(url);
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
% ============================================================================
|
||||
\section{User credentials and authenticators}
|
||||
|
||||
Some services need some user credentials (eg. username and password) to open
|
||||
a session. In VMime, user credentials can be specified in the session
|
||||
properties or by using a custom authenticator (callback).
|
||||
|
||||
\begin{lstlisting}[caption={Setting user credentials using session
|
||||
properties}]
|
||||
vmime::ref <vmime::net::session> sess; // Suppose we have a session
|
||||
|
||||
sess->getProperties()["store.imap.auth.username"] = "vincent";
|
||||
sess->getProperties()["store.imap.auth.password"] = "my-password";
|
||||
\end{lstlisting}
|
||||
|
||||
Although not recommended, you can also specify username and password
|
||||
directly in the connection URL,
|
||||
ie: \emph{imap://username:password@imap.example.com/}. This works only for
|
||||
services requiring an username and a password as user credentials, and no
|
||||
other information.
|
||||
|
||||
Sometimes, it may not be very convenient to set username/password in the
|
||||
session properties, or not possible (eg. extended SASL mechanisms) . That's
|
||||
why VMime offers an alternate way of getting user credentials: the
|
||||
{\vcode authenticator} object. Basically, an authenticator is an object that
|
||||
can return user credentials on-demand (like a callback).
|
||||
|
||||
Currently, there are two types of authenticator in VMime: a basic
|
||||
authenticator (class {\vcode vmime::security::authenticator}) and, if SASL
|
||||
support is enabled, a SASL authenticator
|
||||
(class {\vcode vmime::security::sasl::SASLAuthenticator}). Usually, you
|
||||
should use the default implementations, or at least make your own
|
||||
implementation inherit from them.
|
||||
|
||||
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
|
||||
{
|
||||
std::cout << "Enter your username: " << std::endl;
|
||||
|
||||
vmime::string res;
|
||||
std::getline(std::cin, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const string getPassword() const
|
||||
{
|
||||
std::cout << "Enter your password: " << std::endl;
|
||||
|
||||
vmime::string res;
|
||||
std::getline(std::cin, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
\end{lstlisting}
|
||||
|
||||
This is how to use it:
|
||||
|
||||
\begin{lstlisting}
|
||||
// First, create a session
|
||||
vmime::ref <vmime::net::session> sess =
|
||||
vmime::create <vmime::net::session>();
|
||||
|
||||
// Next, initialize a service which will use our authenticator
|
||||
vmime::ref <vmime::net::store> st =
|
||||
sess->getStore(vmime::utility::url("imap://imap.example.com"),
|
||||
/* use our authenticator */ vmime::create <myAuthenticator>());
|
||||
\end{lstlisting}
|
||||
|
||||
\vnote{An authenticator object should be used with one and only one service
|
||||
at a time. This is required because the authentication process may need to
|
||||
retrieve the service name (SASL).}
|
||||
|
||||
Of course, this example is quite simplified. For example, if several
|
||||
authentication mechanisms are tried, the user may be requested to enter the
|
||||
same information multiple times. See {\vexample Example6} for a more complex
|
||||
implementation of an authenticator, with caching support.
|
||||
|
||||
If you want to use SASL (ie. if \emph{options.sasl} is set to \emph{true}),
|
||||
your authenticator must inherit from
|
||||
{\vcode vmime::security::sasl::SASLAuthenticator} or
|
||||
{\vcode vmime::security::sasl::defaultSASLAuthenticator}, even if you do not
|
||||
use the SASL-specific methods {\vcode getAcceptableMechanisms()} and
|
||||
{\vcode setSASLMechanism()}. Have a look at {\vexample Example6} to see an
|
||||
implementation of an SASL authenticator.
|
||||
|
||||
\begin{lstlisting}[caption={A simple SASL authenticator}]
|
||||
class mySASLAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator
|
||||
{
|
||||
typedef vmime::security::sasl::SASLMechanism mechanism; // save us typing
|
||||
|
||||
const std::vector <vmime::ref <mechanism > getAcceptableMechanisms
|
||||
(const std::vector <vmime::ref <mechanism> >& available,
|
||||
vmime::ref <mechanism> 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.
|
||||
//
|
||||
// If you do not want to bother with this, you can simply return
|
||||
// the default list, which is ordered by security strength.
|
||||
return defaultSASLAuthenticator::
|
||||
getAcceptableMechanisms(available, suggested);
|
||||
}
|
||||
|
||||
void setSASLMechanism(vmime::ref <mechanism> mech)
|
||||
{
|
||||
// This is called when the authentication process is going to
|
||||
// try the specified mechanism.
|
||||
//
|
||||
// The mechanism name is in mech->getName()
|
||||
|
||||
defaultSASLAuthenticator::setSASLMechanism(mech);
|
||||
}
|
||||
|
||||
// ...implement getUsername() and getPassword()...
|
||||
};
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
% ============================================================================
|
||||
\section{Using transport service}
|
||||
|
||||
You have two possibilities for giving message data to the service when you
|
||||
want to send a message:
|
||||
|
||||
\begin{itemize}
|
||||
\item either you have a reference to a message (type {\vcode vmime::message})
|
||||
and you can simply call {\vcode send(msg)};
|
||||
\item or you only have raw message data (as a string, for example), and you
|
||||
have to call the second overload of {\vcode send()}, which takes additional
|
||||
parameters (corresponding to message envelope);
|
||||
\end{itemize}
|
||||
|
||||
The following example illustrates the use of a transport service to send a
|
||||
message using the second method:
|
||||
|
||||
\begin{lstlisting}[caption={Using a transport service}]
|
||||
const vmime::string msgData =
|
||||
"From: me@example.org \r\n"
|
||||
"To: you@example.org \r\n"
|
||||
"Date: Sun, Oct 30 2005 17:06:42 +0200 \r\n"
|
||||
"Subject: Test \r\n"
|
||||
"\r\n"
|
||||
"Message body";
|
||||
|
||||
// Create a new session
|
||||
vmime::utility::url url("smtp://example.com");
|
||||
|
||||
vmime::ref <vmime::net::session> sess =
|
||||
vmime::create <vmime::net::session>();
|
||||
|
||||
// Create an instance of the transport service
|
||||
vmime::ref <vmime::net::transport> tr = sess->getTransport(url);
|
||||
|
||||
// Connect it
|
||||
tr->connect();
|
||||
|
||||
// Send the message
|
||||
vmime::utility::inputStreamStringAdapter is(msgData);
|
||||
|
||||
vmime::mailbox from("me@example.org");
|
||||
vmime::mailboxList to;
|
||||
to.appendMailbox(vmime::create <vmime::mailbox>("you@example.org"));
|
||||
|
||||
tr->send(
|
||||
/* expeditor */ from,
|
||||
/* recipient(s) */ to,
|
||||
/* data */ is,
|
||||
/* total length */ msgData.length());
|
||||
|
||||
// We have finished using the service
|
||||
tr->disconnect();
|
||||
\end{lstlisting}
|
||||
|
||||
\vnote{Exceptions can be thrown at any time when using a service. For better
|
||||
clarity, exceptions are not caught here, but be sure to catch them in your own
|
||||
application to provide error feedback to the user.}
|
||||
|
||||
If you use SMTP, you can enable authentication by setting some properties
|
||||
on the session object ({\vcode service::setProperty()} is a shortcut for
|
||||
setting properties on the session with the correct prefix):
|
||||
|
||||
\begin{lstlisting}
|
||||
tr->setProperty("options.need-authentication", true);
|
||||
tr->setProperty("auth.username", "user");
|
||||
tr->setProperty("auth.password", "password");
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
% ============================================================================
|
||||
\section{Using store service}
|
||||
|
||||
\subsection{Connecting to a store} % -----------------------------------------
|
||||
|
||||
The first basic step for using a store service is to connect to it. The
|
||||
following example shows how to initialize a session and instanciate the
|
||||
store service:
|
||||
|
||||
\begin{lstlisting}[caption={Connecting to a store service}]
|
||||
// Create a new session
|
||||
vmime::utility::url url("imap://vincent:password@imap:example.org");
|
||||
|
||||
vmime::ref <vmime::net::session> sess =
|
||||
vmime::create <vmime::net::session>();
|
||||
|
||||
// Create an instance of the transport service
|
||||
vmime::ref <vmime::net::store> store = sess->getStore(url);
|
||||
|
||||
// Connect it
|
||||
store->connect();
|
||||
\end{lstlisting}
|
||||
|
||||
\vnote{{\vexample Example6} contains a more complete example for connecting
|
||||
to a store service, with support for a custom authenticator.}
|
||||
|
||||
\subsection{Opening a folder} % ----------------------------------------------
|
||||
|
||||
You can open a folder using two different access modes: either in
|
||||
\emph{read-only} mode (where you can only read message flags and contents), or
|
||||
in \emph{read-write} mode (where you can read messages, but also delete them
|
||||
or add new ones). When you have a reference to a folder, simply call the
|
||||
{\vcode open()} method with the desired access mode:
|
||||
|
||||
\begin{lstlisting}
|
||||
folder->open(vmime::net::folder::MODE_READ_WRITE);
|
||||
\end{lstlisting}
|
||||
|
||||
\vnote{Not all stores support the \emph{read-write} mode. By default, if the
|
||||
\emph{read-write} mode is not available, the folder silently fall backs on
|
||||
the \emph{read-only} mode, unless the \emph{failIfModeIsNotAvailable} argument
|
||||
to {\vcode open()} is set to true.}
|
||||
|
||||
Call {\vcode getDefaultFolder()} on the store to obtain a reference to the
|
||||
default folder, which is usually the INBOX folder (where messages arrive when
|
||||
they are received).
|
||||
|
||||
You can also open a specific folder by specifying its path. The following
|
||||
example will open a folder named \emph{bar}, which is a child of \emph{foo}
|
||||
in the root folder:
|
||||
|
||||
\begin{lstlisting}[caption={Opening a folder from its path}]
|
||||
vmime::net::folder::path path;
|
||||
path /= vmime::net::folder::path::component("foo");
|
||||
path /= vmime::net::folder::path::component("bar");
|
||||
|
||||
vmime::ref <vmime::net::folder> fld = store->getFolder(path);
|
||||
fld->open(vmime::net::folder::MODE_READ_WRITE);
|
||||
\end{lstlisting}
|
||||
|
||||
\vnote{You can specify a path as a string as there is no way to get the
|
||||
separator used to delimitate path components. Always use {\vcode operator/=}
|
||||
or {\vcode appendComponent}.}
|
||||
|
||||
\vnote{Path components are of type {\vcode vmime::word}, which means that
|
||||
VMime supports folder names with extended characters, not only 7-bit
|
||||
US-ASCII. However, be careful that this may not be supported by the
|
||||
underlying store protocol (IMAP supports it, because it uses internally a
|
||||
modified UTF-7 encoding).}
|
||||
|
||||
\subsection{Fetching messages} % ---------------------------------------------
|
||||
|
||||
You can fetch some information about a message without having to download the
|
||||
whole message. Moreover, folders support fetching for multiple messages in
|
||||
a single request, for better performance. The following items are currently
|
||||
available for fetching:
|
||||
|
||||
\begin{itemize}
|
||||
\item {\bf envelope}: sender, recipients, date and subject;
|
||||
\item {\bf structure}: MIME structure of the message;
|
||||
\item {\bf content-info}: content-type of the root part;
|
||||
\item {\bf flags}: message flags;
|
||||
\item {\bf size}: message size;
|
||||
\item {\bf header}: retrieve all the header fields of a message;
|
||||
\item {\bf uid}: unique identifier of a message;
|
||||
\item {\bf importance}: fetch header fields suitable for use with
|
||||
{\vcode misc::importanceHelper}.
|
||||
\end{itemize}
|
||||
|
||||
\vnote{Not all services support all fetchable items. Call
|
||||
{\vcode getFetchCapabilities()} on a folder to know which information can be
|
||||
fetched by a service.}
|
||||
|
||||
The following code shows how to list all the messages in a folder, and
|
||||
retrieve basic information to show them to the user:
|
||||
|
||||
\begin{lstlisting}[caption={Fetching information about multiple messages}]
|
||||
std::vector <ref <vmime::net::message> > allMessages = folder->getMessages();
|
||||
|
||||
folder->fetchMessages(allMessages,
|
||||
vmime::net::folder::FETCH_FLAGS |
|
||||
vmime::net::folder::FETCH_ENVELOPE);
|
||||
|
||||
for (unsigned int i = 0 ; i < allMessages.size() ; ++i)
|
||||
{
|
||||
vmime::ref <vmime::net::message> msg = allMessages[i];
|
||||
|
||||
const int flags = msg->getFlags();
|
||||
|
||||
std::cout << "Message " << i << ":" << std::endl;
|
||||
|
||||
if (flags & vmime::net::message::FLAG_SEEN)
|
||||
std::cout << " - is read" << std::endl;
|
||||
if (flags & vmime::net::message::FLAG_DELETED)
|
||||
std::cout << " - is deleted" << std::endl;
|
||||
|
||||
vmime::ref <const vmime::header> hdr = msg->getHeader();
|
||||
|
||||
std::cout << " - sent on " << hdr->Date()->generate() << std::endl;
|
||||
std::cout << " - sent by " << hdr->From()->generate() << std::endl;
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Extracting messages and parts}
|
||||
|
||||
To extract the whole contents of a message (including headers), use the
|
||||
{\vcode extract()} method on a {\vcode vmime::net::message} object. The
|
||||
following example extracts the first message in the default folder:
|
||||
|
||||
\begin{lstlisting}[caption={Extracting messages}]
|
||||
// Get a reference to the folder and to its first message
|
||||
vmime::ref <vmime::net::folder> folder = store->getDefaultFolder();
|
||||
vmime::ref <vmime::net::message> msg = folder->getMessage(1);
|
||||
|
||||
// Write the message contents to the standard output
|
||||
vmime::utility::outputStreamAdapter out(std::cout);
|
||||
msg->extract(out);
|
||||
\end{lstlisting}
|
||||
|
||||
Some protocols (like IMAP) also support the extraction of specific MIME parts
|
||||
of a message without downloading the whole message. This can save bandwidth
|
||||
and time. The method {\vcode extractPart()} is used in this case:
|
||||
|
||||
\begin{lstlisting}[caption={Extracting a specific MIME part of a message}]
|
||||
// Fetching structure is required before extracting a part
|
||||
folder->fetchMessage(msg, vmime::net::folder::FETCH_STRUCTURE);
|
||||
|
||||
// Now, we can extract the part
|
||||
msg->extractPart(msg->getStructure()->getPartAt(0)->getPartAt(1));
|
||||
\end{lstlisting}
|
||||
|
||||
Suppose we have a message with the following structure:
|
||||
|
||||
\begin{verbatim}
|
||||
multipart/mixed
|
||||
text/html
|
||||
image/jpeg [*]
|
||||
\end{verbatim}
|
||||
|
||||
The previous example will extract the header and body of the \emph{image/jpeg}
|
||||
part.
|
||||
|
||||
\subsection{Events} % --------------------------------------------------------
|
||||
|
||||
As a result of executing some operation (or from time to time, even if no
|
||||
operation has been performed), a store service can send events to notify you
|
||||
that something has changed (eg. the number of messages in a folder). These
|
||||
events may allow you to update the user interface associated to a message
|
||||
store.
|
||||
|
||||
Currently, there are three types of event:
|
||||
|
||||
\begin{itemize}
|
||||
\item {\bf message change}: sent when the number of messages in a folder
|
||||
has changed (ie. some messages have been added or removed);
|
||||
\item {\bf message count change}: sent when one or more message(s) have
|
||||
changed (eg. flags or deleted status);
|
||||
\item {\bf folder change}: sent when a folder has been created, renamed or
|
||||
deleted.
|
||||
\end{itemize}
|
||||
|
||||
You can register a listener for each event type by using the corresponding
|
||||
methods on a {\vcode folder} object: {\vcode addMessageChangedListener()},
|
||||
{\vcode addMessageCountListener()} or {\vcode addFolderListener()}. For more
|
||||
information, please read the class documentation for
|
||||
{\vcode vmime::net::events} namespace.
|
||||
|
||||
|
||||
% ============================================================================
|
||||
\section{Handling time-outs}
|
||||
|
||||
Unexpected errors can occur while messaging services are performing
|
||||
operations and waiting a response from the server (eg. server stops
|
||||
responding, network link falls down). As all operations as synchronous,
|
||||
they can be ``blocked'' a long time before returning (in fact, they loop
|
||||
until they either receive a response from the server, or the underlying
|
||||
socket system returns an error).
|
||||
|
||||
VMime provides a mechanism to control the duration of operations. This
|
||||
mechanism allows the program to cancel an operation that is currently
|
||||
running.
|
||||
|
||||
An interface called {\vcode timeoutHandler} is provided:
|
||||
|
||||
\begin{lstlisting}
|
||||
class timeoutHandler : public object
|
||||
{
|
||||
/** Called to test if the time limit has been reached.
|
||||
*
|
||||
* @return true if the time-out delay is elapsed
|
||||
*/
|
||||
virtual const bool isTimeOut() = 0;
|
||||
|
||||
/** Called to reset the time-out counter.
|
||||
*/
|
||||
virtual void resetTimeOut() = 0;
|
||||
|
||||
/** Called when the time limit has been reached (when
|
||||
* isTimeOut() returned true).
|
||||
*
|
||||
* @return true to continue (and reset the time-out)
|
||||
* or false to cancel the current operation
|
||||
*/
|
||||
virtual const bool handleTimeOut() = 0;
|
||||
};
|
||||
\end{lstlisting}
|
||||
|
||||
While the operation runs, the service calls {\vcode isTimeout()} at variable
|
||||
intervals. If the function returns {\vcode true}, then
|
||||
{\vcode handleTimeout()} is called. If it also returns {\vcode true}, the
|
||||
operation is cancelled and an {\vcode operation\_timed\_out} exception is
|
||||
thrown. The function {\vcode resetTimeout()} is called each time data has
|
||||
been received from the server to reset time-out delay.
|
||||
|
||||
The following example shows how to implement a simple time-out handler:
|
||||
|
||||
\begin{lstlisting}[caption={Implementing a simple time-out handler}]
|
||||
class myTimeoutHandler : public vmime::net::timeoutHandler
|
||||
{
|
||||
public:
|
||||
|
||||
const bool isTimeOut()
|
||||
{
|
||||
return (getTime() >= m_last + 30); // 30 seconds time-out
|
||||
}
|
||||
|
||||
void resetTimeOut()
|
||||
{
|
||||
m_last = getTime();
|
||||
}
|
||||
|
||||
const bool handleTimeOut()
|
||||
{
|
||||
std::cout << "Operation timed out." << std::endl;
|
||||
<< "Press [Y] to continue, or [N] to "
|
||||
<< "cancel the operation." << std::endl;
|
||||
|
||||
std::string response;
|
||||
std::cin >> response;
|
||||
|
||||
return (response == "y" || response == "Y");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const unsigned int getTime() const
|
||||
{
|
||||
return vmime::platformDependant::getHandler()->getUnixTime();
|
||||
}
|
||||
|
||||
unsigned int m_last;
|
||||
};
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
% ============================================================================
|
||||
\newpage
|
||||
\section{Secured connection using TLS/SSL}
|
||||
|
||||
\subsection{Introduction} % --------------------------------------------------
|
||||
|
||||
If you have enabled TLS support in VMime, you can configure messaging services
|
||||
so that they use a secured connection.
|
||||
|
||||
Quoting from RFC-2246 - the TLS 1.0 protocol specification: \emph{`` The TLS
|
||||
protocol provides communications privacy over the Internet. The protocol
|
||||
allows client/server applications to communicate in a way that is designed
|
||||
to prevent eavesdropping, tampering, or message forgery.''}
|
||||
|
||||
TLS has the following advantages:
|
||||
|
||||
\begin{itemize}
|
||||
\item authentication: server identity can be verified;
|
||||
\item privacy: transmission of data between client and server cannot be read
|
||||
by someone in the middle of the connection;
|
||||
\item integrity: original data which is transferred between a client and a
|
||||
server can not be modified by an attacker without being detected.
|
||||
\end{itemize}
|
||||
|
||||
\vnote{What is the difference between SSL and TLS? SSL is a protocol designed
|
||||
by Netscape. TLS is a standard protocol, and is partly based on version 3 of
|
||||
the SSL protocol. The two protocols are not interoperable, but TLS does
|
||||
support a mechanism to back down to SSL 3.}
|
||||
|
||||
VMime offers two possibilities for using a secured connection:
|
||||
|
||||
\begin{itemize}
|
||||
\item you can connect to a server listening on a special port (eg. IMAPS
|
||||
instead of IMAP): this is the classical use of SSL, but is now deprecated;
|
||||
\item connect to a server listening on the default port, and then begin a
|
||||
secured connection: this is STARTTLS.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
\subsection{Setting up a secured connection} % -------------------------------
|
||||
|
||||
\subsubsection{Connecting to a ``secured'' port} % ...........................
|
||||
|
||||
To use the classical SSL/TLS way, simply use the ``S'' version of the protocol
|
||||
to connect to the server (eg. \emph{imaps} instead of \emph{imap}). This is
|
||||
currently available for SMTP, POP3 and IMAP.
|
||||
|
||||
\begin{lstlisting}
|
||||
vmime::ref <vmime::net::store> store =
|
||||
theSession->getStore(vmime::utility::url("imaps://example.org"));
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Using STARTTLS} % .............................................
|
||||
|
||||
To make the service start a secured session using the STARTTLS method, simply
|
||||
set the \emph{connection.tls} property:
|
||||
|
||||
\begin{lstlisting}
|
||||
theService->setProperty("connection.tls", true);
|
||||
\end{lstlisting}
|
||||
|
||||
\vnote{If, for some reason, a secured connection cannot be started, the
|
||||
default behaviour is to fallback on a normal connection. To make
|
||||
{\vcode connect()} fail if STARTTLS fails, set the
|
||||
\emph{connection.tls.required} to \emph{true}.}
|
||||
|
||||
\subsection{Certificate verification} % --------------------------------------
|
||||
|
||||
\subsubsection{How it works} % ...............................................
|
||||
|
||||
If you tried the previous examples, a
|
||||
{\vcode certificate\_verification\_exception} might have been thrown.
|
||||
This is because the default certificate verifier in VMime did not manage to
|
||||
verify the certificate, and so could not trust it.
|
||||
|
||||
Basically, when you connect to a server using TLS, the server responds with
|
||||
a list of certificates, called a certificate chain (usually, certificates are
|
||||
of type X.509\footnote{And VMime currently supports only X.509 certificates}).
|
||||
The certificate chain is ordered so that the first certificate is the subject
|
||||
certificate, the second is the subject's issuer one, the third is the issuer's
|
||||
issuer, and so on.
|
||||
|
||||
To decide whether the server can be trusted or not, you have to verify that
|
||||
\emph{each} certificate is valid (ie. is trusted). For more information
|
||||
about X.509 and certificate verification, see related articles on Wikipedia
|
||||
\footnote{\url{See http://wikipedia.org/wiki/Public\_key\_certificate}}.
|
||||
|
||||
\subsubsection{Using the default certificate verifier} % .....................
|
||||
|
||||
The default certificate verifier maintains a list of root (CAs) and user
|
||||
certificates that are trusted. By default, the list is empty. So, you have
|
||||
to initialize it before using the verifier.
|
||||
|
||||
The algorithm\footnote{See
|
||||
\url{http://wikipedia.org/wiki/Certification\_path\_validation\_algorithm}}
|
||||
used is quite simple:
|
||||
|
||||
\begin{enumerate}
|
||||
\item for every certificate in the chain, verify that the certificate has been
|
||||
issued by the next certificate in the chain;
|
||||
\item for every certificate in the chain, verify that the certificate is valid
|
||||
at the current time;
|
||||
\item decide whether the subject's certificate can be trusted:
|
||||
\begin{itemize}
|
||||
\item first, verify that the the last certificate in the chain was
|
||||
issued by a third-party that we trust (root CAs);
|
||||
\item if the issuer certificate cannot be verified against root CAs,
|
||||
compare the subject's certificate against the trusted certificates
|
||||
(the certificates the user has decided to trust).
|
||||
\end{itemize}
|
||||
\end{enumerate}
|
||||
|
||||
First, we need some code to load existing X.509 certificates:
|
||||
|
||||
\begin{lstlisting}[caption={Reading a X.509 certificate from a file}]
|
||||
vmime::ref <vmime::security::cert::X509Certificate>
|
||||
loadX509CertificateFromFile(const std::string& path)
|
||||
{
|
||||
std::ifstream certFile;
|
||||
certFile.open(path.c_str(), std::ios::in | std::ios::binary);
|
||||
|
||||
if (!certFile)
|
||||
{
|
||||
// ...handle error...
|
||||
}
|
||||
|
||||
vmime::utility::inputStreamAdapter is(certFile);
|
||||
vmime::ref <vmime::security::cert::X509Certificate> cert;
|
||||
|
||||
// Try DER format
|
||||
cert = vmime::security::cert::X509Certificate::import
|
||||
(is, vmime::security::cert::X509Certificate::FORMAT_DER);
|
||||
|
||||
if (cert != NULL)
|
||||
return cert;
|
||||
|
||||
// Try PEM format
|
||||
is.reset();
|
||||
cert = vmime::security::cert::X509Certificate::import
|
||||
(is, vmime::security::cert::X509Certificate::FORMAT_PEM);
|
||||
|
||||
return cert;
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
Then, we can use the {\vcode loadX509CertificateFromFile} function to load
|
||||
certificates and initialize the certificate verifier:
|
||||
|
||||
\begin{lstlisting}[caption={Using the default certificate verifier}]
|
||||
vmime::ref <vmime::security::cert::defaultCertificateVerifier> vrf =
|
||||
vmime::create <vmime::security::cert::defaultCertificateVerifier>();
|
||||
|
||||
// Load root CAs (such as Verisign or Thawte)
|
||||
std::vector <vmime::ref <vmime::security::cert::X509Certificate> > rootCAs;
|
||||
|
||||
rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca1.cer");
|
||||
rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca2.cer");
|
||||
rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca3.cer");
|
||||
|
||||
vrf->setX509RootCAs(rootCAs);
|
||||
|
||||
// Then, load certificates that the user explicitely chose to trust
|
||||
std::vector <vmime::ref <vmime::security::cert::X509Certificate> > trusted;
|
||||
|
||||
trusted.push_back(loadX509CertificateFromFile("/path/to/trusted-site1.cer");
|
||||
trusted.push_back(loadX509CertificateFromFile("/path/to/trusted-site2.cer");
|
||||
|
||||
vrf->setX509TrustedCerts(trusted);
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\subsubsection{Writing your own certificate verifier} % ......................
|
||||
|
||||
If you need to do more complex verifications on certificates, you will have to
|
||||
write your own verifier. Your verifier should inherit from the
|
||||
{\vcode vmime::security::cert::certificateVerifier} class and implement the
|
||||
method {\vcode verify()}. Then, if the specified certificate chain is trusted,
|
||||
simply return from the function, or else throw a
|
||||
{\vcode certificate\_verification\_exception}.
|
||||
|
||||
The following example shows how to implement an interactive certificate
|
||||
verifier which relies on the user's decision, and nothing else (you SHOULD NOT
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
||||
void verify(vmime::ref <certificateChain> certs)
|
||||
{
|
||||
// Obtain the subject's certificate
|
||||
vmime::ref <vmime::security::cert::certificate> cert = chain->getAt(0);
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << "Server sent a '" << cert->getType() << "'"
|
||||
<< " certificate." << std::endl;
|
||||
std::cout << "Do you want to accept this certificate? (Y/n) ";
|
||||
std::cout.flush();
|
||||
|
||||
std::string answer;
|
||||
std::getline(std::cin, answer);
|
||||
|
||||
if (answer.length() != 0 && (answer[0] == 'Y' || answer[0] == 'y'))
|
||||
return; // OK, we trust the certificate
|
||||
|
||||
// Don't trust this certificate
|
||||
throw exceptions::certificate_verification_exception();
|
||||
}
|
||||
};
|
||||
\end{lstlisting}
|
||||
|
||||
\vnote{In production code, it may be a good idea to remember user's decisions
|
||||
about which certificates to trust and which not. See {\vexample Example6} for
|
||||
a basic cache implementation.}
|
||||
|
104
doc/book/start.tex
Normal file
104
doc/book/start.tex
Normal file
@ -0,0 +1,104 @@
|
||||
\chapter{Getting Started}
|
||||
|
||||
% ============================================================================
|
||||
\section{Using VMime in your programs}
|
||||
|
||||
First, make sure you have successfully compiled and installed VMime using the
|
||||
instructions described in Chapter \ref{chapter_building}. To use VMime in your
|
||||
program, you simply have to include VMime headers:
|
||||
|
||||
\begin{lstlisting}
|
||||
#include <vmime/vmime.hpp>
|
||||
\end{lstlisting}
|
||||
|
||||
\vnote{for versions older than 0.6.1, include $<$vmime/vmime$>$.}
|
||||
|
||||
As of version 0.6.1, VMime uses {\vcode pkg-config} to simplify compiling and
|
||||
linking with VMime. The {\vcode pkg-config} utility is used to detect the
|
||||
appropriate compiler and linker flags needed for a library.
|
||||
|
||||
You can simply build your program with:
|
||||
|
||||
\begin{verbatim}
|
||||
$ g++ `pkg-config --cflags --libs vmime` -static -o myprog myprog.cpp
|
||||
\end{verbatim}
|
||||
|
||||
to use the static version, or with:
|
||||
|
||||
\begin{verbatim}
|
||||
$ g++ `pkg-config --cflags --libs vmime` -o myprog myprog.cpp
|
||||
\end{verbatim}
|
||||
|
||||
to use the shared version.
|
||||
|
||||
\vnote{it is highly recommended that you link your program against the shared
|
||||
version of the library.}
|
||||
|
||||
All VMime classes and global functions are defined in the namespace
|
||||
{\vcode vmime}, so prefix explicitely all your declarations which use VMime
|
||||
with {\vcode vmime::}, or import the {\vcode vmime} namespace into the global
|
||||
namespace with the C++ keywork {\vcode using} (not recommended, though).
|
||||
|
||||
|
||||
% ============================================================================
|
||||
\section{If you can not (or do not want to) use {\vcode pkg-config}}
|
||||
|
||||
{\bf Linking with the shared library (.so):} compile your program with the
|
||||
{\vcode -lvmime} flag. You can use the -L path flag if the library file is
|
||||
not in a standard path (ie. not in /usr/lib or /usr/local/lib).
|
||||
|
||||
\vnote{if you want to link your program with the shared version of VMime
|
||||
library, make sure the library has been compiled using the autotools version
|
||||
of the build system ({\vcode ./configure}, {\vcode make} and {\vcode make
|
||||
install}). When you compile with SCons, only the static library is built and
|
||||
installed.}
|
||||
|
||||
{\bf Linking with the static library (.a):} follow the same procedure as for
|
||||
shared linking and append the flag -static to force static linking. Although
|
||||
static linking is possible, you are encouraged to use the shared (dynamic)
|
||||
version of the library.
|
||||
|
||||
|
||||
% ============================================================================
|
||||
\section{Platform-dependant code}
|
||||
|
||||
While the most part of VMime code is pure ANSI C++, there are some features
|
||||
that are platform-specific: file management (opening/reading/writing files),
|
||||
network code (socket, DNS resolution) and time management. All the
|
||||
non-portable stuff is done by a bridge object called a platform handler (see
|
||||
{\vcode vmime::platformDependant}).
|
||||
|
||||
If your platform is POSIX-compatible (eg. GNU/Linux, *BSD) or is Windows,
|
||||
then you are lucky: VMime has built-in support for these platforms. If not,
|
||||
don't worry, the sources of the built-in platform handlers are very well
|
||||
documented, so writing you own should not be very difficult.
|
||||
|
||||
At the beginning of your program (before using \emph{any} VMime object, or
|
||||
calling \emph{any} VMime global function), you should tell VMime which
|
||||
platform handler you want to use.
|
||||
|
||||
So, if your platform is POSIX, your program should look like this:
|
||||
|
||||
\begin{lstlisting}[caption={Initializing VMime and the platform handler}]
|
||||
#include <vmime/vmime.hpp>
|
||||
#include <vmime/platforms/posix/posixHandler.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
vmime::platformDependant::
|
||||
setHandler <vmime::platforms::posix::posixHandler>();
|
||||
|
||||
// Now, you can use VMime
|
||||
// ...do what you want, it's your program...
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
For using VMime on Windows, include
|
||||
$<$vmime/platforms/windows/windowsHandler.hpp$>$ and use the following line
|
||||
to initialize the platform handler:
|
||||
|
||||
\begin{lstlisting}
|
||||
vmime::platformDependant::
|
||||
setHandler <vmime::platforms::windows::windowsHandler>();
|
||||
\end{lstlisting}
|
||||
|
Loading…
Reference in New Issue
Block a user