Initial import.
This commit is contained in:
commit
a3229a0513
434
ChangeLog
Normal file
434
ChangeLog
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
|
||||||
|
VERSION 0.5.2-CVS
|
||||||
|
=================
|
||||||
|
|
||||||
|
2004-09-09 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* IMAPFolder.cpp: fixed rename(): folder name is now updated.
|
||||||
|
|
||||||
|
2004-08-21 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* charset.cpp: workaround (hack?) for different 'iconv' prototypes (they
|
||||||
|
may differ in the second parameter being 'const' or not).
|
||||||
|
|
||||||
|
2004-08-20 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* renamed "messaging/folderPath" to "utility/path" for common use in
|
||||||
|
"messaging/folder" and "utility/file".
|
||||||
|
|
||||||
|
* moved "stream" and "stringProxy" into "utility" namespace.
|
||||||
|
|
||||||
|
* started to write some "JavaDoc-like" comments, for use with Doxygen.
|
||||||
|
|
||||||
|
2004-08-18 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* stringProxy.hpp: fixed stringProxy::it_end() which returned wrong
|
||||||
|
value (typo...).
|
||||||
|
|
||||||
|
2004-07-26 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* fileAttachment: fixed the encoding param (not set to default anymore)
|
||||||
|
and provided a new constructor to specify your own encoding.
|
||||||
|
|
||||||
|
2004-07-22 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* wide-char support is disabled by default. To enable, set the flag
|
||||||
|
"with_wide_char_support=yes" on the SCons command line.
|
||||||
|
|
||||||
|
2004-07-08 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* renamed messaging/POP3*, messaging/IMAP* and messaging/SMTP* classes
|
||||||
|
to follow the same convention as other class names.
|
||||||
|
|
||||||
|
2004-07-03 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* moved some files to "utility" subdirectory ("vmime::utility" namespace).
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.5.1
|
||||||
|
=============
|
||||||
|
|
||||||
|
2004-06-15 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* contentHandler, htmlTextPart: Fixed some compilation issues with
|
||||||
|
g++ version < 3.4:
|
||||||
|
[error: declaration of `const vmime::encoding& encoding() const'
|
||||||
|
changes meaning of `encoding' from `class vmime::encoding'].
|
||||||
|
|
||||||
|
* Fixed errors in SConstruct with Windows NT (2k, XP...).
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.5.0
|
||||||
|
=============
|
||||||
|
|
||||||
|
2004-05-26 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* added methods receiveRaw() and sendRaw() on vmime::socket object. Do not
|
||||||
|
forget to implement it, or you will get a compile error.
|
||||||
|
|
||||||
|
2004-05-21 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* added some unit tests in the "tests" directory. To run all the tests, 'cd'
|
||||||
|
to the "tests" directory, compile test programs by running "make" and then
|
||||||
|
execute the "run-tests.sh" script.
|
||||||
|
|
||||||
|
* charset: added a convert() function to perform stream conversion.
|
||||||
|
|
||||||
|
2004-05-18 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* encoder*: updated all encoders so they use input streams and output
|
||||||
|
streams instead of a in-memory string. You can use the stream adapters
|
||||||
|
(inputStreamStringAdapter and outputStreamStringAdapter) for your code
|
||||||
|
to continue working the old-fashioned way...
|
||||||
|
|
||||||
|
2004-05-17 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* messaging/transport.hpp: added a "size" parameter to send() function.
|
||||||
|
|
||||||
|
2004-05-16 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* body: body contents and data in text parts are now handled via a
|
||||||
|
proxy object: contentHandler. This allow more flexibility, including
|
||||||
|
providing data from an input stream instead of storing whole data in
|
||||||
|
memory into a string object. This also provide a big performance and
|
||||||
|
memory usage improvement. For more information, please see the comments
|
||||||
|
in the file "contentHandler.hpp".
|
||||||
|
|
||||||
|
2004-05-15 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* all files: modified the parsing in depth (not using iterators anymore),
|
||||||
|
the code is clearer and faster.
|
||||||
|
|
||||||
|
* IMAPutils.cpp: corrected a bug (typo) in IMAPutils::dateTime().
|
||||||
|
|
||||||
|
2004-05-13 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* all files: added a generate() method on vmime::component to generate
|
||||||
|
objects into an output stream (outputStream). This offers a large
|
||||||
|
performance and memory usage improvement when generating big messages.
|
||||||
|
|
||||||
|
* stream.cpp/.hpp: new objects "inputStream" and "outputStream" to
|
||||||
|
provide more flexibility than with standard C++ streams. There are
|
||||||
|
also adapters for standard i/o streams, provided for compatibility.
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.4.2
|
||||||
|
=============
|
||||||
|
|
||||||
|
2004-05-08 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* messaging: added a system of event notification (message change,
|
||||||
|
folder renamed, etc...). For more information about this, please
|
||||||
|
consult "src/messaging/events.hpp".
|
||||||
|
|
||||||
|
2004-05-03 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* messaging: added a lot of useful features to message stores
|
||||||
|
(set/get message flags, message deletion, copy, rename folder,
|
||||||
|
adding messages, unique identifiers, MIME part/header fetch,
|
||||||
|
partial fetch...).
|
||||||
|
|
||||||
|
2004-04-30 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* messaging/message.hpp: added a fetchPartHeader() method to
|
||||||
|
extract the header of a specific MIME part.
|
||||||
|
|
||||||
|
2004-04-25 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* all files: removed (illegal) extra ';' after namespace
|
||||||
|
declarations.
|
||||||
|
|
||||||
|
* all files: fixed some compilation errors with g++-3.4 (the
|
||||||
|
parser is more strict and more standard-compliant).
|
||||||
|
|
||||||
|
2004-04-24 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* messaging/*: splitted "progressListener" into two objects:
|
||||||
|
"progressionListener" and "timeoutHandler". The last one is
|
||||||
|
used internally in VMime. The "progressionListener" parameter
|
||||||
|
is no more passed as argument to the constructor of a "service"
|
||||||
|
object. Instead, it can be given in argument to the functions
|
||||||
|
that use it:
|
||||||
|
- message::extract[Part]()
|
||||||
|
- folder::fetchMessages()
|
||||||
|
- transport::send()
|
||||||
|
|
||||||
|
2004-04-04 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* messaging/folder.hpp: added a (optional) parameter "recursive"
|
||||||
|
to getFolders() to allow enumeration of all sub-folders
|
||||||
|
(that is, direct and indirect).
|
||||||
|
|
||||||
|
2004-04-03 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* messaging/authenti[fi]cationInfos: renamed class
|
||||||
|
'authentificationInfos' to 'authenticationInfos'.
|
||||||
|
|
||||||
|
* exception.hpp: renamed class 'authentification_error' to
|
||||||
|
'authentication_error'.
|
||||||
|
|
||||||
|
* messaging/SMTPtransport: renamed 'options.need-authentification'
|
||||||
|
to 'options.need-authentication'.
|
||||||
|
|
||||||
|
2004-04-02 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* added basic IMAP support. This is EXPERIMENTAL.
|
||||||
|
|
||||||
|
2004-03-25 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* messaging::folder::path: changed type of 'component' from 'string'
|
||||||
|
to 'word' to allow multiple charsets to be used in a path.
|
||||||
|
|
||||||
|
* implemented a noop() command on vmime::messaging::service class.
|
||||||
|
|
||||||
|
* messageParser.cpp: it is now possible to get more information on an
|
||||||
|
attachment using the "Content-Disposition" (use the attachmentInfo()
|
||||||
|
fonction to retrieve the "Content-Disposition" field related to
|
||||||
|
the attachment).
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.4.1
|
||||||
|
=============
|
||||||
|
|
||||||
|
2004-03-24 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* SMTPtransport.cpp: fixed a bug in send().
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.4.0
|
||||||
|
=============
|
||||||
|
|
||||||
|
2004-02-19 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* mailboxGroup.cpp: fixed a segfault when generating() an empty group
|
||||||
|
(eg. "undisclosed-recipient").
|
||||||
|
|
||||||
|
2004-02-17 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* === MAJOR CHANGE === Removed old "network features". Now, this is called
|
||||||
|
"messaging system" and a new (incompatible) interface is provided.
|
||||||
|
|
||||||
|
2003-12-30 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* encoderFactory.cpp/.hpp: added stuff to allow iterating through
|
||||||
|
registered encoders.
|
||||||
|
|
||||||
|
* encoder*.cpp/.hpp: changed the way options/results are set in encoders:
|
||||||
|
now, a vmime::propertySet is used. This provides more flexibility.
|
||||||
|
|
||||||
|
2003-12-25 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* constants.cpp/.hpp: media types constants: removed "sub" namespace and
|
||||||
|
translated "sub::[TYPE]::[SUBTYPE]" to "[TYPE]_[SUBTYPE]".
|
||||||
|
|
||||||
|
2003-12-08 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* constants.cpp/.hpp, dateTime.cpp/.hpp: translated all constants/enums
|
||||||
|
from lower-case to upper-case letters.
|
||||||
|
|
||||||
|
2003-12-04 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* Created a new class for singleton. Derived all concerned class from
|
||||||
|
this new class. This concerns: "encoderFactory", "headerFieldFactory",
|
||||||
|
"parameterFactory", "options" and "textPartFactory".
|
||||||
|
|
||||||
|
2003-12-02 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* Moved to SCons building system (http://www.scons.org/) and dropped old
|
||||||
|
autoconf/automake system. Type 'scons' to build the library and use
|
||||||
|
'scons install' to install it on your system.
|
||||||
|
|
||||||
|
2003-12-01 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* mailboxGroup.cpp: fixed a bug in typeid() comparison: changed
|
||||||
|
"typeid(parsedAddress)" to "typeid(*parsedAddress)" to test the
|
||||||
|
object dynamic type (the previous test was always false).
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.3.5
|
||||||
|
=============
|
||||||
|
|
||||||
|
2003-10-24 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* included some sample programs in the "examples/" directory. For a more
|
||||||
|
complete documentation, please visit: http://www.kisli.com/vmime/doc/ .
|
||||||
|
|
||||||
|
* all files: it is not possible to create header fields directly anymore
|
||||||
|
(ie. you cannot call the constructor directly); instead, you should use
|
||||||
|
the "headerFieldFactory" object.
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.3.4
|
||||||
|
=============
|
||||||
|
|
||||||
|
2003-10-05 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* all files: changed all calls 'std::isspace(???)' to '[vmime::]isspace(???)'
|
||||||
|
since no locale was passed (anyway, no locale is needed: text is ASCII).
|
||||||
|
|
||||||
|
2003-10-04 Kai Stammerjohann <orp@uni.de>
|
||||||
|
|
||||||
|
* included a Visual C++ 7 solution/project for vmime: see "vmime.sln" and
|
||||||
|
"vmime.vcproj" in the root directory.
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.3.3
|
||||||
|
=============
|
||||||
|
|
||||||
|
2003-09-22 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* moved all constants (media types, charsets...) from base.cpp/.hpp to new
|
||||||
|
files constants.cpp/.hpp.
|
||||||
|
|
||||||
|
2003-09-21 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* messageBuilder.cpp (construct): fixed algorithm for generating text parts.
|
||||||
|
Single and multiple text parts, with or without attachments are now handled
|
||||||
|
correctly (as recommended by the RFCs).
|
||||||
|
|
||||||
|
* bodyPart.cpp/.hpp, body.cpp/.hpp, header.cpp/.hpp: added clone() and
|
||||||
|
operator=() functions to be able to duplicate body parts.
|
||||||
|
|
||||||
|
* messageParser.cpp (findTextParts): handled the case in which the message
|
||||||
|
is not "multipart/*": we use the main part if its type is "text/*".
|
||||||
|
|
||||||
|
* messageParser.cpp (destructor): added code for deleting the text parts
|
||||||
|
created by the findTextParts() function.
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.3.2
|
||||||
|
=============
|
||||||
|
|
||||||
|
2003-09-19 Bevan Collins <bcollins@ihug.co.nz>
|
||||||
|
|
||||||
|
* encoderQP.cpp: fixed a bug in quoted-printable encoding: "=20\r\n" is
|
||||||
|
appended to the line ending with a space.
|
||||||
|
|
||||||
|
2003-09-13 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* charset.cpp/.hpp: dropped internal conversion from charset name (string) to
|
||||||
|
charset type (enum). We keep only the name of the charset.
|
||||||
|
|
||||||
|
* base.cpp/.hpp: added string constants for some charsets.
|
||||||
|
|
||||||
|
2003-09-12 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* messageParser.cpp (findAttachments): fixed the search for attachment
|
||||||
|
parts. The right test is "cdf.value().name() != dispositionTypes::_inline"
|
||||||
|
and not "cdf.value().name() != dispositionTypes::attachment"...
|
||||||
|
|
||||||
|
2003-09-11 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* plainTextPart.cpp/htmlTextPart.cpp: fixed a bug in parse(): when getting
|
||||||
|
the "charset" parameter, "no_such_parameter" exception was not caught if
|
||||||
|
the parameter was not present.
|
||||||
|
|
||||||
|
2003-09-06 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* base.cpp: added a special case when encoding to Quoted-Printable: lines
|
||||||
|
are no more limited to 76 characters (the maximum length recommended by
|
||||||
|
the RFC) if maxLineLength == lineLengthLimits::infinite. However, this
|
||||||
|
SHOULD NOT be used when generating mails (not RFC compliant).
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.3.1
|
||||||
|
=============
|
||||||
|
|
||||||
|
2003-08-24 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* mailbox.hpp: added "const" functions for name() and email().
|
||||||
|
|
||||||
|
2003-07-26 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* charset.cpp: fixed a bug in "charset::iconvert()". Also, the
|
||||||
|
conversion is now done using a buffer, and not in one block.
|
||||||
|
|
||||||
|
2003-07-24 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* receiveProtocol[POP3].hpp/.cpp: a socket factory can now be passed in
|
||||||
|
argument to the constructor so that it is possible to override the
|
||||||
|
use of the default factory (set in vmime::platformDependantHandler).
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.3.0
|
||||||
|
=============
|
||||||
|
|
||||||
|
2003-07-21 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* configure.in: changed 'libdir' to install lib files in {PREFIX}/lib
|
||||||
|
instead of {PREFIX}/lib/vmime. However, include files remain in the
|
||||||
|
{PREFIX}/include/vmime directory.
|
||||||
|
|
||||||
|
2003-06-28 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* base.hpp/.cpp: changed the return type of "libname()" and "libversion()"
|
||||||
|
from "string::value_type*" to "string".
|
||||||
|
|
||||||
|
2003-06-16 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* platformDependant.hpp: added "getSocketFactory()" function to be used
|
||||||
|
with the new network features.
|
||||||
|
|
||||||
|
* configure.in: modified the file to permit passing arguments to
|
||||||
|
the "configure" script:
|
||||||
|
. --disable-net: disable network support (new in 0.3.0)
|
||||||
|
. --enable-debug: enable debug mode (not used for now)
|
||||||
|
|
||||||
|
* started version 0.3.0: added network features: connection to mail
|
||||||
|
servers via POP3, IMAP... Related classes: "receiveProtocol*",
|
||||||
|
"serverInfos" and "socket", an abstract socket class.
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.2.1
|
||||||
|
=============
|
||||||
|
|
||||||
|
2003-05-28 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* messageId.cpp: added "vmime." at the beginning of random-generated
|
||||||
|
message-ids (to make them more unique).
|
||||||
|
|
||||||
|
2003-05-26 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* all source files: replaced "_VMIME_xxxxx_HPP_INCLUDED_" macros with
|
||||||
|
"VMIME_xxxxx_HPP_INCLUDED". Names beginning with "_" (underscore) and
|
||||||
|
followed by an uppercase letter are reserved to the implementation
|
||||||
|
(see the C++ standard: 17.4.3.1.2 Global names).
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.2.0
|
||||||
|
=============
|
||||||
|
|
||||||
|
2003-05-18 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* messageParser.cpp: added a message parser (to be used parallely with
|
||||||
|
messageBuilder). Extraction of attachment, plain text parts and HTML
|
||||||
|
text parts (with embedded objects) is supported.
|
||||||
|
|
||||||
|
2003-05-09 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* body.cpp (generate): the default prolog & epilog text (as defined
|
||||||
|
in vmime::options) are not written anymore in sub-parts (only for
|
||||||
|
the "root" part). Added a "isRoot" member to vmime::header.
|
||||||
|
|
||||||
|
2003-05-08 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* encoding.cpp (decide): added some code to choose "quoted-printable"
|
||||||
|
when there are lines with more than "lineLengthLimits::convenient"
|
||||||
|
characters (or with a '.' just after a '\n').
|
||||||
|
|
||||||
|
* base.cpp (makeWordsFromText): enhanced algorithm.
|
||||||
|
|
||||||
|
2003-05-04 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* address.cpp, mailbox.cpp, mailboxGroup.cpp: added empty() function.
|
||||||
|
|
||||||
|
* messageBuilder.cpp (construct): some validity checks: we now check
|
||||||
|
there is one expeditor and at least one recipient.
|
||||||
|
|
||||||
|
|
||||||
|
VERSION 0.1.0
|
||||||
|
=============
|
||||||
|
|
||||||
|
2003-05-03 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
|
||||||
|
* First (beta) version released.
|
688
SConstruct
Normal file
688
SConstruct
Normal file
@ -0,0 +1,688 @@
|
|||||||
|
#
|
||||||
|
# SConstruct
|
||||||
|
# libvmime build script
|
||||||
|
#
|
||||||
|
# Process this file with 'scons' to build the project.
|
||||||
|
# For more information, please visit: http://www.scons.org/ .
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# . scons build the library
|
||||||
|
# . scons -h see available configuration options
|
||||||
|
# . scons opt=value set a configuration option
|
||||||
|
# . scons install install library and include files (as root)
|
||||||
|
# . scons dist build a source package (.tar.bz2)
|
||||||
|
#
|
||||||
|
|
||||||
|
import commands
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
import string
|
||||||
|
|
||||||
|
|
||||||
|
##################
|
||||||
|
# Source files #
|
||||||
|
##################
|
||||||
|
|
||||||
|
libvmime_sources = [
|
||||||
|
'address.cpp', 'address.hpp',
|
||||||
|
'addressList.cpp', 'addressList.hpp',
|
||||||
|
'addressListField.cpp', 'addressListField.hpp',
|
||||||
|
'attachment.hpp',
|
||||||
|
'base.cpp', 'base.hpp',
|
||||||
|
'body.cpp', 'body.hpp',
|
||||||
|
'bodyPart.cpp', 'bodyPart.hpp',
|
||||||
|
'charset.cpp', 'charset.hpp',
|
||||||
|
'charsetParameter.cpp', 'charsetParameter.hpp',
|
||||||
|
'component.cpp', 'component.hpp',
|
||||||
|
'constants.cpp', 'constants.hpp',
|
||||||
|
'contentDispositionField.cpp', 'contentDispositionField.hpp',
|
||||||
|
'contentEncodingField.cpp', 'contentEncodingField.hpp',
|
||||||
|
'contentHandler.cpp', 'contentHandler.hpp',
|
||||||
|
'contentTypeField.cpp', 'contentTypeField.hpp',
|
||||||
|
'dateField.cpp', 'dateField.hpp',
|
||||||
|
'dateParameter.cpp', 'dateParameter.hpp',
|
||||||
|
'dateTime.cpp', 'dateTime.hpp',
|
||||||
|
'defaultAttachment.cpp', 'defaultAttachment.hpp',
|
||||||
|
'defaultField.cpp', 'defaultField.hpp',
|
||||||
|
'defaultParameter.cpp', 'defaultParameter.hpp',
|
||||||
|
'defaultParameterizedHeaderField.cpp', 'defaultParameterizedHeaderField.hpp',
|
||||||
|
'disposition.cpp', 'disposition.hpp',
|
||||||
|
'encoder.cpp', 'encoder.hpp',
|
||||||
|
'encoder7bit.cpp', 'encoder7bit.hpp',
|
||||||
|
'encoder8bit.cpp', 'encoder8bit.hpp',
|
||||||
|
'encoderB64.cpp', 'encoderB64.hpp',
|
||||||
|
'encoderBinary.cpp', 'encoderBinary.hpp',
|
||||||
|
'encoderDefault.cpp', 'encoderDefault.hpp',
|
||||||
|
'encoderFactory.cpp', 'encoderFactory.hpp',
|
||||||
|
'encoderQP.cpp', 'encoderQP.hpp',
|
||||||
|
'encoderUUE.cpp', 'encoderUUE.hpp',
|
||||||
|
'encoding.cpp', 'encoding.hpp',
|
||||||
|
'exception.hpp',
|
||||||
|
'fileAttachment.cpp', 'fileAttachment.hpp',
|
||||||
|
'header.cpp', 'header.hpp',
|
||||||
|
'headerFieldFactory.cpp', 'headerFieldFactory.hpp',
|
||||||
|
'headerField.cpp', 'headerField.hpp',
|
||||||
|
'htmlTextPart.cpp', 'htmlTextPart.hpp',
|
||||||
|
'mailbox.cpp', 'mailbox.hpp',
|
||||||
|
'mailboxField.cpp', 'mailboxField.hpp',
|
||||||
|
'mailboxGroup.cpp', 'mailboxGroup.hpp',
|
||||||
|
'mailboxList.cpp', 'mailboxList.hpp',
|
||||||
|
'mailboxListField.cpp', 'mailboxListField.hpp',
|
||||||
|
'mediaType.cpp', 'mediaType.hpp',
|
||||||
|
'messageBuilder.cpp', 'messageBuilder.hpp',
|
||||||
|
'message.cpp', 'message.hpp',
|
||||||
|
'messageId.cpp', 'messageId.hpp',
|
||||||
|
'messageIdField.cpp', 'messageIdField.hpp',
|
||||||
|
'messageParser.cpp', 'messageParser.hpp',
|
||||||
|
'options.cpp', 'options.hpp',
|
||||||
|
'parameter.cpp', 'parameter.hpp',
|
||||||
|
'parameterFactory.cpp', 'parameterFactory.hpp',
|
||||||
|
'parameterizedHeaderField.cpp', 'parameterizedHeaderField.hpp',
|
||||||
|
'parserHelpers.hpp',
|
||||||
|
'plainTextPart.cpp', 'plainTextPart.hpp',
|
||||||
|
'platformDependant.cpp', 'platformDependant.hpp',
|
||||||
|
'propertySet.cpp', 'propertySet.hpp',
|
||||||
|
'relayField.cpp', 'relayField.hpp',
|
||||||
|
'text.cpp', 'text.hpp',
|
||||||
|
'textField.cpp', 'textField.hpp',
|
||||||
|
'textParameter.cpp', 'textParameter.hpp',
|
||||||
|
'textPartFactory.cpp', 'textPartFactory.hpp',
|
||||||
|
'textPart.hpp',
|
||||||
|
'types.hpp',
|
||||||
|
'word.cpp', 'word.hpp',
|
||||||
|
'vmime',
|
||||||
|
'utility/file.hpp',
|
||||||
|
'utility/md5.cpp', 'utility/md5.hpp',
|
||||||
|
'utility/path.cpp', 'utility/path.hpp',
|
||||||
|
'utility/random.cpp', 'utility/random.hpp',
|
||||||
|
'utility/singleton.cpp', 'utility/singleton.hpp',
|
||||||
|
'utility/smartPtr.hpp',
|
||||||
|
'utility/stream.cpp', 'utility/stream.hpp',
|
||||||
|
'utility/stringProxy.cpp', 'utility/stringProxy.hpp'
|
||||||
|
]
|
||||||
|
|
||||||
|
libvmime_examples_sources = [
|
||||||
|
'examples/common.inc',
|
||||||
|
'examples/README',
|
||||||
|
'examples/example1.cpp',
|
||||||
|
'examples/example2.cpp',
|
||||||
|
'examples/example3.cpp',
|
||||||
|
'examples/example4.cpp',
|
||||||
|
'examples/example5.cpp',
|
||||||
|
'examples/example6.cpp'
|
||||||
|
]
|
||||||
|
|
||||||
|
libvmime_messaging_sources = [
|
||||||
|
'messaging/authenticator.cpp', 'messaging/authenticator.hpp',
|
||||||
|
'messaging/authenticationInfos.cpp', 'messaging/authenticationInfos.hpp',
|
||||||
|
'messaging/authHelper.cpp', 'messaging/authHelper.hpp',
|
||||||
|
'messaging/builtinServices.inl',
|
||||||
|
'messaging/defaultAuthenticator.cpp', 'messaging/defaultAuthenticator.hpp',
|
||||||
|
'messaging/events.cpp', 'messaging/events.hpp',
|
||||||
|
'messaging/folder.cpp', 'messaging/folder.hpp',
|
||||||
|
'messaging/message.cpp', 'messaging/message.hpp',
|
||||||
|
'messaging/progressionListener.hpp',
|
||||||
|
'messaging/service.cpp', 'messaging/service.hpp',
|
||||||
|
'messaging/serviceFactory.cpp', 'messaging/serviceFactory.hpp',
|
||||||
|
'messaging/serviceInfos.hpp',
|
||||||
|
'messaging/session.cpp', 'messaging/session.hpp',
|
||||||
|
'messaging/simpleAuthenticator.cpp', 'messaging/simpleAuthenticator.hpp',
|
||||||
|
'messaging/socket.hpp',
|
||||||
|
'messaging/store.hpp',
|
||||||
|
'messaging/timeoutHandler.hpp',
|
||||||
|
'messaging/transport.hpp',
|
||||||
|
'messaging/url.cpp', 'messaging/url.hpp',
|
||||||
|
'messaging/urlUtils.cpp', 'messaging/urlUtils.hpp'
|
||||||
|
]
|
||||||
|
|
||||||
|
libvmime_messaging_proto_sources = [
|
||||||
|
[
|
||||||
|
'pop3',
|
||||||
|
[
|
||||||
|
'messaging/POP3Store.cpp', 'messaging/POP3Store.hpp',
|
||||||
|
'messaging/POP3Folder.cpp', 'messaging/POP3Folder.hpp',
|
||||||
|
'messaging/POP3Message.cpp', 'messaging/POP3Message.hpp'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'smtp',
|
||||||
|
[
|
||||||
|
'messaging/SMTPTransport.cpp', 'messaging/SMTPTransport.hpp'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'imap',
|
||||||
|
[
|
||||||
|
'messaging/IMAPConnection.cpp', 'messaging/IMAPConnection.hpp',
|
||||||
|
'messaging/IMAPStore.cpp', 'messaging/IMAPStore.hpp',
|
||||||
|
'messaging/IMAPFolder.cpp', 'messaging/IMAPFolder.hpp',
|
||||||
|
'messaging/IMAPMessage.cpp', 'messaging/IMAPMessage.hpp',
|
||||||
|
'messaging/IMAPTag.cpp', 'messaging/IMAPTag.hpp',
|
||||||
|
'messaging/IMAPUtils.cpp', 'messaging/IMAPUtils.hpp',
|
||||||
|
'messaging/IMAPParser.hpp'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'maildir',
|
||||||
|
[
|
||||||
|
'messaging/maildirStore.cpp', 'messaging/maildirStore.hpp',
|
||||||
|
'messaging/maildirFolder.cpp', 'messaging/maildirFolder.hpp',
|
||||||
|
'messaging/maildirMessage.cpp', 'messaging/maildirMessage.hpp',
|
||||||
|
'messaging/maildirUtils.cpp', 'messaging/maildirUtils.hpp'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
libvmime_extra = [
|
||||||
|
'AUTHORS',
|
||||||
|
'ChangeLog',
|
||||||
|
'COPYING',
|
||||||
|
'INSTALL',
|
||||||
|
'NEWS',
|
||||||
|
'README',
|
||||||
|
'SConstruct',
|
||||||
|
'VERSION'
|
||||||
|
]
|
||||||
|
|
||||||
|
libvmime_tests = [
|
||||||
|
# charset
|
||||||
|
'tests/charset/Makefile',
|
||||||
|
'tests/charset/main.cpp',
|
||||||
|
'tests/charset/run-test.sh',
|
||||||
|
'tests/charset/test-suites/gnu.in.utf-8',
|
||||||
|
'tests/charset/test-suites/gnu.out.iso-8859-1',
|
||||||
|
|
||||||
|
# encoding
|
||||||
|
'tests/encoding/Makefile',
|
||||||
|
'tests/encoding/main.cpp',
|
||||||
|
'tests/encoding/run-test.sh',
|
||||||
|
'tests/encoding/test-suites/encode/1byte',
|
||||||
|
'tests/encoding/test-suites/encode/1byte.base64',
|
||||||
|
'tests/encoding/test-suites/encode/2bytes',
|
||||||
|
'tests/encoding/test-suites/encode/2bytes.base64',
|
||||||
|
'tests/encoding/test-suites/encode/3bytes',
|
||||||
|
'tests/encoding/test-suites/encode/3bytes.base64',
|
||||||
|
'tests/encoding/test-suites/encode/empty',
|
||||||
|
'tests/encoding/test-suites/encode/empty.base64',
|
||||||
|
'tests/encoding/test-suites/encode/empty.quoted-printable',
|
||||||
|
'tests/encoding/test-suites/encode/gpl',
|
||||||
|
'tests/encoding/test-suites/encode/gpl.base64',
|
||||||
|
'tests/encoding/test-suites/encode/gpl.quoted-printable',
|
||||||
|
'tests/encoding/test-suites/encode/gpl.uuencode',
|
||||||
|
'tests/encoding/test-suites/encode/ls',
|
||||||
|
'tests/encoding/test-suites/encode/ls.base64',
|
||||||
|
'tests/encoding/test-suites/encode/ls.quoted-printable',
|
||||||
|
'tests/encoding/test-suites/encode/ls.uuencode',
|
||||||
|
'tests/encoding/test-suites/encode/simple',
|
||||||
|
'tests/encoding/test-suites/encode/simple.base64',
|
||||||
|
'tests/encoding/test-suites/encode/simple.quoted-printable',
|
||||||
|
'tests/encoding/test-suites/encode/simple.uuencode',
|
||||||
|
'tests/encoding/test-suites/decode/ls',
|
||||||
|
'tests/encoding/test-suites/decode/ls.base64',
|
||||||
|
|
||||||
|
# mailbox
|
||||||
|
'tests/mailbox/Makefile',
|
||||||
|
'tests/mailbox/main.cpp',
|
||||||
|
'tests/mailbox/run-test.sh',
|
||||||
|
'tests/mailbox/test-suites/test1.in',
|
||||||
|
'tests/mailbox/test-suites/test1.out',
|
||||||
|
'tests/mailbox/test-suites/test2.in',
|
||||||
|
'tests/mailbox/test-suites/test2.out',
|
||||||
|
|
||||||
|
# main
|
||||||
|
'tests/Makefile',
|
||||||
|
'tests/run-tests.sh'
|
||||||
|
]
|
||||||
|
|
||||||
|
libvmime_dist_files = libvmime_sources + libvmime_messaging_sources
|
||||||
|
|
||||||
|
for i in range(len(libvmime_dist_files)):
|
||||||
|
libvmime_dist_files[i] = 'src/' + libvmime_dist_files[i]
|
||||||
|
|
||||||
|
for p in libvmime_messaging_proto_sources:
|
||||||
|
for f in p[1]:
|
||||||
|
libvmime_dist_files.append('src/' + f)
|
||||||
|
|
||||||
|
libvmime_dist_files = libvmime_dist_files + libvmime_extra + libvmime_examples_sources
|
||||||
|
libvmime_dist_files_with_tests = libvmime_dist_files + libvmime_tests
|
||||||
|
|
||||||
|
|
||||||
|
#################
|
||||||
|
# Set options #
|
||||||
|
#################
|
||||||
|
|
||||||
|
EnsureSConsVersion(0, 94)
|
||||||
|
|
||||||
|
SetOption('implicit_cache', 1)
|
||||||
|
|
||||||
|
#SourceSignatures('timestamp')
|
||||||
|
SourceSignatures('MD5')
|
||||||
|
TargetSignatures('build')
|
||||||
|
|
||||||
|
|
||||||
|
#############
|
||||||
|
# Version #
|
||||||
|
#############
|
||||||
|
|
||||||
|
def GetPackageVersion():
|
||||||
|
import re
|
||||||
|
contents = open('VERSION', 'r').read()
|
||||||
|
major = re.compile('(\d+)\.(\d+)\.(\d+)', re.DOTALL).sub(r'\1', contents)
|
||||||
|
minor = re.compile('(\d+)\.(\d+)\.(\d+)', re.DOTALL).sub(r'\2', contents)
|
||||||
|
patch = re.compile('(\d+)\.(\d+)\.(\d+)', re.DOTALL).sub(r'\3', contents)
|
||||||
|
return '%d.%d.%d' % (int(major), int(minor), int(patch))
|
||||||
|
|
||||||
|
packageName = 'libvmime'
|
||||||
|
packageVersion = GetPackageVersion()
|
||||||
|
|
||||||
|
|
||||||
|
#############
|
||||||
|
# Options #
|
||||||
|
#############
|
||||||
|
|
||||||
|
# Try to guess some default values
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
# Command line options
|
||||||
|
opts = Options('options.cache')
|
||||||
|
|
||||||
|
opts.AddOptions(
|
||||||
|
(
|
||||||
|
'prefix',
|
||||||
|
'Installation prefix directory',
|
||||||
|
'/usr'
|
||||||
|
),
|
||||||
|
EnumOption(
|
||||||
|
'debug',
|
||||||
|
'Debug version (useful for developers only)',
|
||||||
|
'no',
|
||||||
|
allowed_values = ('yes', 'no'),
|
||||||
|
map = { },
|
||||||
|
ignorecase = 1
|
||||||
|
),
|
||||||
|
EnumOption(
|
||||||
|
'static',
|
||||||
|
'Build a static library (.a)',
|
||||||
|
'yes',
|
||||||
|
allowed_values = ('yes', 'no'),
|
||||||
|
map = { },
|
||||||
|
ignorecase = 1
|
||||||
|
),
|
||||||
|
EnumOption(
|
||||||
|
'shared',
|
||||||
|
'Build a shared library (.so)',
|
||||||
|
'no',
|
||||||
|
allowed_values = ('yes', 'no'),
|
||||||
|
map = { },
|
||||||
|
ignorecase = 1
|
||||||
|
),
|
||||||
|
EnumOption(
|
||||||
|
'with_messaging',
|
||||||
|
'Messaging support (connection to mail store/transport servers)',
|
||||||
|
'yes',
|
||||||
|
allowed_values = ('yes', 'no'),
|
||||||
|
map = { },
|
||||||
|
ignorecase = 1
|
||||||
|
),
|
||||||
|
EnumOption(
|
||||||
|
'with_filesystem',
|
||||||
|
'Enable file-system support (eg. "maildir" messaging support)',
|
||||||
|
'yes',
|
||||||
|
allowed_values = ('yes', 'no'),
|
||||||
|
map = { },
|
||||||
|
ignorecase = 1
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'with_messaging_protocols',
|
||||||
|
'Specifies which protocols to build into the library.\n'
|
||||||
|
+ 'This option has no effect if "with_messaging" is not activated.\n'
|
||||||
|
+ 'Separate protocols with spaces; string must be quoted with ".',
|
||||||
|
'"pop3 smtp imap"'
|
||||||
|
),
|
||||||
|
EnumOption(
|
||||||
|
'with_wide_char_support',
|
||||||
|
'Support for wide characters (rarely used, should be set to "no")',
|
||||||
|
'no',
|
||||||
|
allowed_values = ('yes', 'no'),
|
||||||
|
map = { },
|
||||||
|
ignorecase = 1
|
||||||
|
),
|
||||||
|
EnumOption(
|
||||||
|
'byte_order',
|
||||||
|
'Byte order',
|
||||||
|
sys.byteorder,
|
||||||
|
allowed_values = ('big', 'little'),
|
||||||
|
map = { },
|
||||||
|
ignorecase = 1
|
||||||
|
),
|
||||||
|
EnumOption(
|
||||||
|
'pf_8bit_type',
|
||||||
|
'The C-language 8-bit type for your platform',
|
||||||
|
'char',
|
||||||
|
allowed_values = ('char', 'short', 'int', 'long'),
|
||||||
|
map = { },
|
||||||
|
ignorecase = 1
|
||||||
|
),
|
||||||
|
EnumOption(
|
||||||
|
'pf_16bit_type',
|
||||||
|
'The C-language 16-bit type for your platform',
|
||||||
|
'short',
|
||||||
|
allowed_values = ('char', 'short', 'int', 'long'),
|
||||||
|
map = { },
|
||||||
|
ignorecase = 1
|
||||||
|
),
|
||||||
|
EnumOption(
|
||||||
|
'pf_32bit_type',
|
||||||
|
'The C-language 32-bit type for your platform',
|
||||||
|
'int',
|
||||||
|
allowed_values = ('char', 'short', 'int', 'long'),
|
||||||
|
map = { },
|
||||||
|
ignorecase = 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
###############################
|
||||||
|
# Configuration Environment #
|
||||||
|
###############################
|
||||||
|
|
||||||
|
env = Environment(options = opts)
|
||||||
|
|
||||||
|
env.Append(ENV = {'PATH' : os.environ['PATH']})
|
||||||
|
|
||||||
|
env.Append(CPPPATH = [ '.', 'src' ])
|
||||||
|
|
||||||
|
env.Append(CPPDEFINES = { '_REENTRANT' : 1 })
|
||||||
|
|
||||||
|
env.Append(CXXFLAGS = ['-pipe'])
|
||||||
|
env.Append(CXXFLAGS = ['-W'])
|
||||||
|
env.Append(CXXFLAGS = ['-Wall'])
|
||||||
|
env.Append(CXXFLAGS = ['-ansi'])
|
||||||
|
env.Append(CXXFLAGS = ['-pedantic'])
|
||||||
|
|
||||||
|
env.Append(TARFLAGS = ['-c'])
|
||||||
|
env.Append(TARFLAGS = ['--bzip2'])
|
||||||
|
|
||||||
|
if env['debug'] == 'yes':
|
||||||
|
env.Append(CXXFLAGS = ['-g'])
|
||||||
|
env.Append(CXXFLAGS = ['-O0'])
|
||||||
|
else:
|
||||||
|
env.Append(CXXFLAGS = ['-O2'])
|
||||||
|
#-fomit-frame-pointer -fmove-all-movables -fstrict-aliasing ')
|
||||||
|
|
||||||
|
#env.Append(LIBS = ['additional-lib-here'])
|
||||||
|
|
||||||
|
# Generate help text for command line options
|
||||||
|
Help(opts.GenerateHelpText(env))
|
||||||
|
|
||||||
|
# Cache current options
|
||||||
|
opts.Save('options.cache', env)
|
||||||
|
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# Some initializations #
|
||||||
|
##########################
|
||||||
|
|
||||||
|
# Messaging protocols
|
||||||
|
messaging_protocols = [ ]
|
||||||
|
|
||||||
|
for proto in re.split('\W+', env['with_messaging_protocols']):
|
||||||
|
proto = string.strip(proto)
|
||||||
|
if len(proto) >= 1:
|
||||||
|
messaging_protocols.append(proto)
|
||||||
|
|
||||||
|
# Show configuration summary
|
||||||
|
print ""
|
||||||
|
print "+=================+"
|
||||||
|
print "| CONFIGURATION |"
|
||||||
|
print "+=================+"
|
||||||
|
print ""
|
||||||
|
print "Installation prefix : " + env['prefix']
|
||||||
|
print "Static library (.a) : " + env['static']
|
||||||
|
print "Shared library (.so) : " + env['shared']
|
||||||
|
print "Debugging mode : " + env['debug']
|
||||||
|
print "Messaging support : " + env['with_messaging']
|
||||||
|
if env['with_messaging'] == 'yes':
|
||||||
|
print " * protocols : " + env['with_messaging_protocols']
|
||||||
|
print "File-system support : " + env['with_filesystem']
|
||||||
|
print ""
|
||||||
|
|
||||||
|
|
||||||
|
########################
|
||||||
|
# Some sanity checks #
|
||||||
|
########################
|
||||||
|
|
||||||
|
def IsProtocolSupported(protoList, proto):
|
||||||
|
for supportedProto in protoList:
|
||||||
|
if string.upper(supportedProto) == string.upper(proto):
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# File-system support must be activated when 'maildir' protocol is selected
|
||||||
|
if env['with_messaging'] == 'yes':
|
||||||
|
if IsProtocolSupported(messaging_protocols, 'maildir'):
|
||||||
|
if env['with_filesystem'] != 'yes':
|
||||||
|
print "ERROR: 'maildir' protocol requires file-system support!\n"
|
||||||
|
Exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
#########################
|
||||||
|
# Generate config.hpp #
|
||||||
|
#########################
|
||||||
|
|
||||||
|
config_hpp = open('src/config.hpp', 'w')
|
||||||
|
|
||||||
|
config_hpp.write("""
|
||||||
|
//
|
||||||
|
// This file was automatically generated by configuration script.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_CONFIG_HPP_INCLUDED
|
||||||
|
#define VMIME_CONFIG_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
""")
|
||||||
|
|
||||||
|
config_hpp.write('// Name of package\n')
|
||||||
|
config_hpp.write('#define VMIME_PACKAGE "' + packageName + '"\n')
|
||||||
|
config_hpp.write('\n')
|
||||||
|
config_hpp.write('// Version number of package\n')
|
||||||
|
config_hpp.write('#define VMIME_VERSION "' + packageVersion + '"\n')
|
||||||
|
config_hpp.write('\n')
|
||||||
|
config_hpp.write('// Target OS and architecture\n')
|
||||||
|
|
||||||
|
if os.name == 'posix':
|
||||||
|
config_hpp.write('#define VMIME_TARGET_ARCH "' + commands.getoutput('uname -m') + '"\n')
|
||||||
|
config_hpp.write('#define VMIME_TARGET_OS "' + commands.getoutput('uname -o') + '"\n')
|
||||||
|
else:
|
||||||
|
config_hpp.write('#define VMIME_TARGET_ARCH "" // Unknown\n')
|
||||||
|
config_hpp.write('#define VMIME_TARGET_OS "' + sys.platform + '/' + os.name + '"\n')
|
||||||
|
|
||||||
|
config_hpp.write('\n')
|
||||||
|
|
||||||
|
if os.name == 'posix':
|
||||||
|
config_hpp.write('#define VMIME_TARGET_OS_IS_POSIX 1 // POSIX compatible\n')
|
||||||
|
config_hpp.write('#define VMIME_TARGET_OS_IS_WIN32 0 // Win32\n')
|
||||||
|
elif os.name == 'win32' or os.name == 'nt':
|
||||||
|
config_hpp.write('#define VMIME_TARGET_OS_IS_POSIX 0 // POSIX compatible\n')
|
||||||
|
config_hpp.write('#define VMIME_TARGET_OS_IS_WIN32 1 // Win32\n')
|
||||||
|
else:
|
||||||
|
print "ERROR: unsupported system: '" + os.name + "'\n"
|
||||||
|
Exit(1)
|
||||||
|
|
||||||
|
config_hpp.write('\n')
|
||||||
|
config_hpp.write('// Set to 1 if debugging should be activated\n')
|
||||||
|
|
||||||
|
if env['debug'] == 'yes':
|
||||||
|
config_hpp.write('#define VMIME_DEBUG 1\n')
|
||||||
|
else:
|
||||||
|
config_hpp.write('#define VMIME_DEBUG 0\n')
|
||||||
|
|
||||||
|
config_hpp.write('\n')
|
||||||
|
config_hpp.write('// Byte order (set one or the other, but not both!)\n')
|
||||||
|
|
||||||
|
if env['byte_order'] == 'big':
|
||||||
|
config_hpp.write('#define IMEL_BYTE_ORDER_BIG_ENDIAN 1\n')
|
||||||
|
config_hpp.write('#define IMEL_BYTE_ORDER_LITTLE_ENDIAN 0\n')
|
||||||
|
else:
|
||||||
|
config_hpp.write('#define IMEL_BYTE_ORDER_BIG_ENDIAN 0\n')
|
||||||
|
config_hpp.write('#define IMEL_BYTE_ORDER_LITTLE_ENDIAN 1\n')
|
||||||
|
|
||||||
|
config_hpp.write('\n')
|
||||||
|
config_hpp.write('// Generic types\n')
|
||||||
|
config_hpp.write('// -- 8-bit\n')
|
||||||
|
config_hpp.write('typedef signed ' + env['pf_8bit_type'] + ' vmime_int8;\n')
|
||||||
|
config_hpp.write('typedef unsigned ' + env['pf_8bit_type'] + ' vmime_uint8;\n')
|
||||||
|
config_hpp.write('// -- 16-bit\n')
|
||||||
|
config_hpp.write('typedef signed ' + env['pf_16bit_type'] + ' vmime_int16;\n')
|
||||||
|
config_hpp.write('typedef unsigned ' + env['pf_16bit_type'] + ' vmime_uint16;\n')
|
||||||
|
config_hpp.write('// -- 32-bit\n')
|
||||||
|
config_hpp.write('typedef signed ' + env['pf_32bit_type'] + ' vmime_int32;\n')
|
||||||
|
config_hpp.write('typedef unsigned ' + env['pf_32bit_type'] + ' vmime_uint32;\n')
|
||||||
|
config_hpp.write('\n')
|
||||||
|
|
||||||
|
config_hpp.write('// Options\n')
|
||||||
|
|
||||||
|
config_hpp.write('// -- Wide characters support\n')
|
||||||
|
if env['with_wide_char_support'] == 'yes':
|
||||||
|
config_hpp.write('#define VMIME_WIDE_CHAR_SUPPORT 1\n')
|
||||||
|
else:
|
||||||
|
config_hpp.write('#define VMIME_WIDE_CHAR_SUPPORT 0\n')
|
||||||
|
|
||||||
|
config_hpp.write('// -- File-system support\n');
|
||||||
|
if env['with_filesystem'] == 'yes':
|
||||||
|
config_hpp.write('#define VMIME_HAVE_FILESYSTEM_FEATURES 1\n')
|
||||||
|
else:
|
||||||
|
config_hpp.write('#define VMIME_HAVE_FILESYSTEM_FEATURES 0\n')
|
||||||
|
|
||||||
|
config_hpp.write('// -- Messaging support\n');
|
||||||
|
if env['with_messaging'] == 'yes':
|
||||||
|
config_hpp.write('#define VMIME_HAVE_MESSAGING_FEATURES 1\n')
|
||||||
|
|
||||||
|
config_hpp.write('// -- Built-in messaging protocols\n')
|
||||||
|
config_hpp.write('#define VMIME_BUILTIN_MESSAGING_PROTOS ' + env['with_messaging_protocols'] + '\n')
|
||||||
|
|
||||||
|
for proto in messaging_protocols:
|
||||||
|
config_hpp.write('#define VMIME_BUILTIN_MESSAGING_PROTO_' + string.upper(proto) + ' 1\n');
|
||||||
|
else:
|
||||||
|
config_hpp.write('#define VMIME_HAVE_MESSAGING_FEATURES 0\n')
|
||||||
|
|
||||||
|
config_hpp.write("""
|
||||||
|
|
||||||
|
#endif // VMIME_CONFIG_HPP_INCLUDED
|
||||||
|
""")
|
||||||
|
|
||||||
|
config_hpp.close()
|
||||||
|
|
||||||
|
|
||||||
|
#################
|
||||||
|
# Build rules #
|
||||||
|
#################
|
||||||
|
|
||||||
|
# Build directory
|
||||||
|
if env['debug'] == 'yes':
|
||||||
|
BuildDir("#build/debug", 'src', duplicate = 0)
|
||||||
|
buildDirectory = 'build/debug/'
|
||||||
|
else:
|
||||||
|
BuildDir("#build/release", 'src', duplicate = 0)
|
||||||
|
buildDirectory = 'build/release/'
|
||||||
|
|
||||||
|
# Create source files list
|
||||||
|
libvmime_full_sources = libvmime_sources
|
||||||
|
|
||||||
|
if env['with_messaging'] == 'yes':
|
||||||
|
# -- Add common files for messaging support
|
||||||
|
for file in libvmime_messaging_sources:
|
||||||
|
libvmime_full_sources.append(file)
|
||||||
|
|
||||||
|
# -- Add protocol specific source files
|
||||||
|
for proto in messaging_protocols:
|
||||||
|
for protosrc in libvmime_messaging_proto_sources:
|
||||||
|
if protosrc[0] == proto:
|
||||||
|
for file in protosrc[1]:
|
||||||
|
libvmime_full_sources.append(file)
|
||||||
|
|
||||||
|
# Split source files list into two lists: .CPP and .HPP
|
||||||
|
libvmime_sources_CPP = [ ]
|
||||||
|
libvmime_sources_HPP = [ ]
|
||||||
|
|
||||||
|
libvmime_install_includes = [ ]
|
||||||
|
|
||||||
|
for file in libvmime_full_sources:
|
||||||
|
slash = string.find(file, '/')
|
||||||
|
dir = ''
|
||||||
|
|
||||||
|
if slash != -1:
|
||||||
|
dir = file[0:slash] + '/'
|
||||||
|
|
||||||
|
if file[-4:] == '.cpp':
|
||||||
|
libvmime_sources_CPP.append(buildDirectory + file)
|
||||||
|
else:
|
||||||
|
libvmime_sources_HPP.append(buildDirectory + file)
|
||||||
|
libvmime_install_includes.append([dir, buildDirectory + file])
|
||||||
|
|
||||||
|
# Main program build
|
||||||
|
if env['debug'] == 'yes':
|
||||||
|
libVmime = env.StaticLibrary(
|
||||||
|
target = 'vmime-debug',
|
||||||
|
source = libvmime_sources_CPP
|
||||||
|
)
|
||||||
|
libVmimeSh = env.SharedLibrary(
|
||||||
|
target = 'vmime-debug',
|
||||||
|
source = libvmime_sources_CPP
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
libVmime = env.StaticLibrary(
|
||||||
|
target = 'vmime',
|
||||||
|
source = libvmime_sources_CPP
|
||||||
|
)
|
||||||
|
libVmimeSh = env.SharedLibrary(
|
||||||
|
target = 'vmime',
|
||||||
|
source = libvmime_sources_CPP
|
||||||
|
)
|
||||||
|
|
||||||
|
if env['static'] == 'yes': Default(libVmime)
|
||||||
|
if env['shared'] == 'yes': Default(libVmimeSh)
|
||||||
|
|
||||||
|
|
||||||
|
########################
|
||||||
|
# Installation rules #
|
||||||
|
########################
|
||||||
|
|
||||||
|
libDir = "%s/lib" % env['prefix']
|
||||||
|
includeDir = "%s/include/vmime" % env['prefix']
|
||||||
|
|
||||||
|
installPaths = [libDir, includeDir]
|
||||||
|
|
||||||
|
# Library
|
||||||
|
if env['static'] == 'yes': env.Install(libDir, libVmime)
|
||||||
|
if env['shared'] == 'yes': env.Install(libDir, libVmimeSh)
|
||||||
|
|
||||||
|
# Header files
|
||||||
|
for i in range(len(libvmime_install_includes)):
|
||||||
|
env.Install(includeDir + '/' + libvmime_install_includes[i][0], libvmime_install_includes[i][1])
|
||||||
|
|
||||||
|
# Configuration header file
|
||||||
|
env.Install(includeDir, 'src/config.hpp')
|
||||||
|
|
||||||
|
# Provide "install" target (ie. 'scons install')
|
||||||
|
env.Alias('install', installPaths)
|
||||||
|
|
||||||
|
|
||||||
|
#####################
|
||||||
|
# Packaging rules #
|
||||||
|
#####################
|
||||||
|
|
||||||
|
# 'tar' is not available under Windows...
|
||||||
|
if not (os.name == 'win32' or os.name == 'nt'):
|
||||||
|
packageFile = 'libvmime-' + packageVersion + '.tar.bz2'
|
||||||
|
packageFileWithTests = 'libvmime-' + packageVersion + '-with-tests.tar.bz2'
|
||||||
|
|
||||||
|
#env.Tar(packageFile, libvmime_dist_files)
|
||||||
|
#env.Tar(packageFileWithTests, libvmime_dist_files_with_tests)
|
||||||
|
env.Tar(packageFile, libvmime_dist_files_with_tests)
|
||||||
|
|
||||||
|
#env.Alias('dist', [ packageFile, packageFileWithTests ])
|
||||||
|
env.Alias('dist', packageFile)
|
9
examples/README
Normal file
9
examples/README
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
1) Configure, compile and install vmime library
|
||||||
|
|
||||||
|
2) Compile the sample programs with:
|
||||||
|
$ g++ -o exampleX exampleX.cpp ../libvmime.a
|
||||||
|
|
||||||
|
3) For a more complete documentation, please visit:
|
||||||
|
http://www.kisli.com/vmime/doc/
|
||||||
|
|
85
examples/example1.cpp
Normal file
85
examples/example1.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// EXAMPLE DESCRIPTION:
|
||||||
|
// ====================
|
||||||
|
// This sample program demonstrate the use of the messageBuilder component
|
||||||
|
// to build a simple message.
|
||||||
|
//
|
||||||
|
// For more information, please visit:
|
||||||
|
// http://vmime.sourceforge.net/
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "../src/vmime"
|
||||||
|
#include "common.inc"
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// VMime initialization
|
||||||
|
vmime::platformDependant::setHandler<my_handler>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
vmime::messageBuilder mb;
|
||||||
|
|
||||||
|
// Fill in the basic fields
|
||||||
|
mb.expeditor() = vmime::mailbox("me@somewhere.com");
|
||||||
|
mb.recipients().append(vmime::mailbox("you@elsewhere.com"));
|
||||||
|
mb.blindCopyRecipients().append(vmime::mailbox("you-bcc@nowhere.com"));
|
||||||
|
mb.subject() = vmime::text("My first message generated with vmime::messageBuilder");
|
||||||
|
|
||||||
|
// Message body
|
||||||
|
mb.textPart().text() = "I'm writing this short text to test message construction " \
|
||||||
|
"using the vmime::messageBuilder component.";
|
||||||
|
|
||||||
|
// Construction
|
||||||
|
vmime::message* msg = mb.construct();
|
||||||
|
|
||||||
|
// Raw text generation
|
||||||
|
std::cout << "Generated message:" << std::endl;
|
||||||
|
std::cout << "==================" << std::endl;
|
||||||
|
|
||||||
|
vmime::outputStreamAdapter out(std::cout);
|
||||||
|
msg->generate(out);
|
||||||
|
|
||||||
|
// Destruction
|
||||||
|
delete (msg);
|
||||||
|
}
|
||||||
|
// VMime exception
|
||||||
|
catch (vmime::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "vmime::exception: " << e.what() << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
// Standard exception
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "std::exception: " << e.what() << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
99
examples/example2.cpp
Normal file
99
examples/example2.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// EXAMPLE DESCRIPTION:
|
||||||
|
// ====================
|
||||||
|
// This sample program demonstrate the use of the messageBuilder component
|
||||||
|
// to build a simple message with an attachment.
|
||||||
|
//
|
||||||
|
// For more information, please visit:
|
||||||
|
// http://vmime.sourceforge.net/
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "../src/vmime"
|
||||||
|
#include "common.inc"
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// VMime initialization
|
||||||
|
vmime::platformDependant::setHandler<my_handler>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
vmime::messageBuilder mb;
|
||||||
|
|
||||||
|
// Fill in the basic fields
|
||||||
|
mb.expeditor() = vmime::mailbox("me@somewhere.com");
|
||||||
|
mb.recipients().append(vmime::mailbox("you@elsewhere.com"));
|
||||||
|
mb.blindCopyRecipients().append(vmime::mailbox("you-bcc@nowhere.com"));
|
||||||
|
mb.subject() = vmime::text("My first message generated with vmime::messageBuilder");
|
||||||
|
|
||||||
|
// Message body
|
||||||
|
mb.textPart().text() = "I'm writing this short text to test message construction " \
|
||||||
|
"with attachment, using the vmime::messageBuilder component.";
|
||||||
|
|
||||||
|
// Adding an attachment
|
||||||
|
vmime::fileAttachment* a = new vmime::fileAttachment
|
||||||
|
(
|
||||||
|
"./example2.cpp", // full path to file
|
||||||
|
vmime::mediaType("application/octet-stream"), // content type
|
||||||
|
vmime::text("My first attachment") // description
|
||||||
|
);
|
||||||
|
|
||||||
|
a->fileInfo().setFilename("example2.cpp");
|
||||||
|
a->fileInfo().setCreationDate(vmime::datetime("30 Apr 2003 14:30:00 +0200"));
|
||||||
|
|
||||||
|
mb.attach(a);
|
||||||
|
|
||||||
|
// Construction
|
||||||
|
vmime::message* msg = mb.construct();
|
||||||
|
|
||||||
|
// Raw text generation
|
||||||
|
vmime::string dataToSend = msg->generate();
|
||||||
|
|
||||||
|
std::cout << "Generated message:" << std::endl;
|
||||||
|
std::cout << "==================" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << dataToSend << std::endl;
|
||||||
|
|
||||||
|
// Destruction
|
||||||
|
delete (msg);
|
||||||
|
}
|
||||||
|
// VMime exception
|
||||||
|
catch (vmime::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "vmime::exception: " << e.what() << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
// Standard exception
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "std::exception: " << e.what() << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
99
examples/example3.cpp
Normal file
99
examples/example3.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// EXAMPLE DESCRIPTION:
|
||||||
|
// ====================
|
||||||
|
// This sample program demonstrate the use of the messageBuilder component
|
||||||
|
// to build a complex message (HTML content, plain text and embedded image).
|
||||||
|
//
|
||||||
|
// For more information, please visit:
|
||||||
|
// http://vmime.sourceforge.net/
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "../src/vmime"
|
||||||
|
#include "common.inc"
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// VMime initialization
|
||||||
|
vmime::platformDependant::setHandler<my_handler>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
vmime::messageBuilder mb;
|
||||||
|
|
||||||
|
// Fill in the basic fields
|
||||||
|
mb.expeditor() = vmime::mailbox("me@somewhere.com");
|
||||||
|
mb.recipients().append(vmime::mailbox("you@elsewhere.com"));
|
||||||
|
mb.blindCopyRecipients().append(vmime::mailbox("you-bcc@nowhere.com"));
|
||||||
|
mb.subject() = vmime::text("My first message generated with vmime::messageBuilder");
|
||||||
|
|
||||||
|
// Set the content-type to "text/html"
|
||||||
|
mb.constructTextPart(vmime::mediaType
|
||||||
|
(vmime::mediaTypes::TEXT, vmime::mediaTypes::TEXT_HTML));
|
||||||
|
|
||||||
|
// Fill in the text part: the message is available in two formats: HTML and plain text.
|
||||||
|
// HTML text part also includes an inline image (embedded into the message).
|
||||||
|
vmime::htmlTextPart& textPart = dynamic_cast<vmime::htmlTextPart&>(mb.textPart());
|
||||||
|
|
||||||
|
// -- embed an image (the returned "CID" (content identifier) is used to reference
|
||||||
|
// -- the image into HTML content).
|
||||||
|
vmime::string cid = textPart.embeddedObjects.add("<...IMAGE DATA...>",
|
||||||
|
vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG));
|
||||||
|
|
||||||
|
// -- message text
|
||||||
|
textPart.text() = vmime::string("This is the <b>HTML text</b>.<br/><img src=\"") + cid + vmime::string("\"/>");
|
||||||
|
textPart.plainText() = vmime::string("This is the plain text (without HTML formatting).");
|
||||||
|
|
||||||
|
// Construction
|
||||||
|
vmime::message* msg = mb.construct();
|
||||||
|
|
||||||
|
// Raw text generation
|
||||||
|
vmime::string dataToSend = msg->generate();
|
||||||
|
|
||||||
|
std::cout << "Generated message:" << std::endl;
|
||||||
|
std::cout << "==================" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << dataToSend << std::endl;
|
||||||
|
|
||||||
|
// Destruction
|
||||||
|
delete (msg);
|
||||||
|
}
|
||||||
|
// VMime exception
|
||||||
|
catch (vmime::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "vmime::exception: " << e.what() << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
// Standard exception
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "std::exception: " << e.what() << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
94
examples/example4.cpp
Normal file
94
examples/example4.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// EXAMPLE DESCRIPTION:
|
||||||
|
// ====================
|
||||||
|
// This sample program demonstrate the use of the messageParser component
|
||||||
|
// to enumerate the text parts in a message.
|
||||||
|
//
|
||||||
|
// For more information, please visit:
|
||||||
|
// http://vmime.sourceforge.net/
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "../src/vmime"
|
||||||
|
#include "common.inc"
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// VMime initialization
|
||||||
|
vmime::platformDependant::setHandler<my_handler>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
vmime::messageParser mp("<...MIME message content...>");
|
||||||
|
|
||||||
|
// Enumerate text parts
|
||||||
|
for (std::vector <vmime::textPart*>::const_iterator i = mp.textParts().begin() ;
|
||||||
|
i != mp.textParts().end() ; ++i)
|
||||||
|
{
|
||||||
|
const vmime::textPart& part = **i;
|
||||||
|
|
||||||
|
// Output content-type of the part
|
||||||
|
std::cout << part.type().generate() << std::endl;
|
||||||
|
|
||||||
|
// text/html
|
||||||
|
if (part.type().subType() == vmime::mediaTypes::TEXT_HTML)
|
||||||
|
{
|
||||||
|
const vmime::htmlTextPart& hp = dynamic_cast<const vmime::htmlTextPart&>(part);
|
||||||
|
|
||||||
|
// HTML text is in "hp.text()"
|
||||||
|
// Corresponding plain text is in "hp.plainText()"
|
||||||
|
|
||||||
|
// Enumerate embedded objects (eg. images)
|
||||||
|
for (vmime::htmlTextPart::const_iterator i = hp.embeddedObjects.begin() ;
|
||||||
|
i != hp.embeddedObjects.end() ; ++i)
|
||||||
|
{
|
||||||
|
// Identifier (content-id or content-location) is in "(*i).id()"
|
||||||
|
// Object data is in "(*i).data()"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// text/plain
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const vmime::textPart& tp = dynamic_cast<const vmime::textPart&>(part);
|
||||||
|
|
||||||
|
// Text is in "tp.text()"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// VMime exception
|
||||||
|
catch (vmime::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "vmime::exception: " << e.what() << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
// Standard exception
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "std::exception: " << e.what() << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
70
examples/example5.cpp
Normal file
70
examples/example5.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// EXAMPLE DESCRIPTION:
|
||||||
|
// ====================
|
||||||
|
// This sample program demonstrate the use of the messageParser component
|
||||||
|
// to enumerate the attachments in a message.
|
||||||
|
//
|
||||||
|
// For more information, please visit:
|
||||||
|
// http://vmime.sourceforge.net/
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "../src/vmime"
|
||||||
|
#include "common.inc"
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// VMime initialization
|
||||||
|
vmime::platformDependant::setHandler<my_handler>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
vmime::messageParser mp("<...MIME message content...>");
|
||||||
|
|
||||||
|
// Enumerate attachments
|
||||||
|
for (std::vector <vmime::attachment*>::const_iterator i = mp.attachments().begin() ;
|
||||||
|
i != mp.attachments().end() ; ++i)
|
||||||
|
{
|
||||||
|
// Media type (content type) is in "(*i).type()"
|
||||||
|
// Description is in "(*i).description()"
|
||||||
|
// Data is in "(*i).data()"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// VMime exception
|
||||||
|
catch (vmime::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "vmime::exception: " << e.what() << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
// Standard exception
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "std::exception: " << e.what() << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
352
examples/example6.cpp
Normal file
352
examples/example6.cpp
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "../src/vmime"
|
||||||
|
#include "common.inc"
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Authentification handler
|
||||||
|
//
|
||||||
|
|
||||||
|
class my_auth : public vmime::messaging::authenticator
|
||||||
|
{
|
||||||
|
const vmime::messaging::authenticationInfos requestAuthInfos() const
|
||||||
|
{
|
||||||
|
vmime::string username, password;
|
||||||
|
|
||||||
|
std::cout << "Username: "; std::cout.flush();
|
||||||
|
std::cin >> username;
|
||||||
|
|
||||||
|
std::cout << "Password: "; std::cout.flush();
|
||||||
|
std::cin >> password;
|
||||||
|
|
||||||
|
return (vmime::messaging::authenticationInfos(username, password));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void printStructure(const vmime::messaging::structure& s, int level = 0)
|
||||||
|
{
|
||||||
|
for (int i = 1 ; i <= s.count() ; ++i)
|
||||||
|
{
|
||||||
|
const vmime::messaging::part& part = s[i];
|
||||||
|
|
||||||
|
for (int j = 0 ; j < level * 2 ; ++j)
|
||||||
|
std::cout << " ";
|
||||||
|
|
||||||
|
std::cout << part.number() << ". "
|
||||||
|
<< part.type().generate()
|
||||||
|
<< " [" << part.size() << " byte(s)]"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
printStructure(part.structure(), level + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// VMime initialization
|
||||||
|
vmime::platformDependant::setHandler <my_handler>();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test the new enumeration system for encoders
|
||||||
|
//
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
vmime::encoderFactory* ef = vmime::encoderFactory::getInstance();
|
||||||
|
|
||||||
|
std::cout << "Available encoders:" << std::endl;
|
||||||
|
|
||||||
|
for (vmime::encoderFactory::iterator it = ef->begin() ;
|
||||||
|
it != ef->end() ; ++it)
|
||||||
|
{
|
||||||
|
std::cout << " * " << (*it).name() << std::endl;
|
||||||
|
|
||||||
|
vmime::encoder* e = (*it).create();
|
||||||
|
|
||||||
|
std::vector <vmime::string> props = e->availableProperties();
|
||||||
|
|
||||||
|
for (std::vector <vmime::string>::const_iterator it2 = props.begin() ; it2 != props.end() ; ++it2)
|
||||||
|
std::cout << " - " << *it2 << std::endl;
|
||||||
|
|
||||||
|
delete (e);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ======================================================================================
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test the new enumeration system for messaging services
|
||||||
|
//
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
vmime::messaging::serviceFactory* sf = vmime::messaging::serviceFactory::getInstance();
|
||||||
|
|
||||||
|
std::cout << "Available messaging services:" << std::endl;
|
||||||
|
|
||||||
|
for (vmime::messaging::serviceFactory::const_iterator it = sf->begin() ;
|
||||||
|
it != sf->end() ; ++it)
|
||||||
|
{
|
||||||
|
std::cout << " * " << (*it).name() << " (" << (*it).infos().defaultPort() << ")" << std::endl;
|
||||||
|
|
||||||
|
std::vector <vmime::string> props = (*it).infos().availableProperties();
|
||||||
|
|
||||||
|
for (std::vector <vmime::string>::const_iterator it2 = props.begin() ; it2 != props.end() ; ++it2)
|
||||||
|
std::cout << " - " << (*it).infos().propertyPrefix() + *it2 << std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vmime::messaging::session sess;
|
||||||
|
sess.properties()["store.protocol"] = "imap";
|
||||||
|
sess.properties()["transport.protocol"] = "smtp";
|
||||||
|
|
||||||
|
my_auth auth;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Test the sending of a message
|
||||||
|
//
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Transport protocol configuration
|
||||||
|
vmime::messaging::transport* tr = sess.getTransport();
|
||||||
|
|
||||||
|
//sess.properties()[tr->infos().propertyPrefix() + "auth.username"] = "username";
|
||||||
|
//sess.properties()[tr->infos().propertyPrefix() + "auth.password"] = "password";
|
||||||
|
|
||||||
|
sess.properties()[tr->infos().propertyPrefix() + "server.address"] = "smtp.mydomain.com";
|
||||||
|
|
||||||
|
//sess.properties()[tr->infos().propertyPrefix() + "options.need-authentification"] = true;
|
||||||
|
|
||||||
|
// Connection
|
||||||
|
tr->connect();
|
||||||
|
|
||||||
|
// Expeditor
|
||||||
|
vmime::mailbox from("me@somewhere.com");
|
||||||
|
|
||||||
|
// Recipients list
|
||||||
|
vmime::mailboxList to;
|
||||||
|
to.append(vmime::mailbox("you@somewhere.com"));
|
||||||
|
to.append(vmime::mailbox("somebody.else@anywhere.com"));
|
||||||
|
|
||||||
|
std::istringstream iss("[MESSAGE DATA: HEADER + BODY]");
|
||||||
|
tr->send(from, to, iss);
|
||||||
|
|
||||||
|
// Note: you could also write this:
|
||||||
|
// vmime::message msg;
|
||||||
|
// ...
|
||||||
|
// tr->send(&msg);
|
||||||
|
|
||||||
|
tr->disconnect();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test the access to a mail store
|
||||||
|
//
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// If no authenticator is given in argument to getStore(), a default one
|
||||||
|
// is used. Its behaviour is to get the user credentials from the
|
||||||
|
// session properties "auth.username" and "auth.password".
|
||||||
|
vmime::messaging::store* st = sess.getStore(&auth);
|
||||||
|
|
||||||
|
// Store protocol configuration
|
||||||
|
//sess.properties()[st->infos().propertyPrefix() + "auth.username"] = "username";
|
||||||
|
//sess.properties()[st->infos().propertyPrefix() + "auth.password"] = "password";
|
||||||
|
|
||||||
|
sess.properties()[st->infos().propertyPrefix() + "server.address"] = "imap.mydomain.com";
|
||||||
|
//sess.properties()[st->infos().propertyPrefix() + "server.port"] = 110;
|
||||||
|
//sess.properties()[st->infos().propertyPrefix() + "server.socket-factory"] = "default";
|
||||||
|
|
||||||
|
//sess.properties()[st->infos().propertyPrefix() + "options.apop"] = false;
|
||||||
|
//sess.properties()[st->infos().propertyPrefix() + "options.apop.fallback"] = true;
|
||||||
|
|
||||||
|
// Connection
|
||||||
|
st->connect();
|
||||||
|
|
||||||
|
// Open the default folder in this store
|
||||||
|
vmime::messaging::folder* f = st->getDefaultFolder();
|
||||||
|
|
||||||
|
f->open(vmime::messaging::folder::MODE_READ_WRITE);
|
||||||
|
|
||||||
|
std::cout << f->getMessageCount() << " message(s) in your inbox" << std::endl;
|
||||||
|
|
||||||
|
// Get a pointer to the first message
|
||||||
|
vmime::messaging::message* m = f->getMessage(1);
|
||||||
|
|
||||||
|
// To fetch the header
|
||||||
|
f->fetchMessage(m, vmime::messaging::folder::FETCH_ENVELOPE |
|
||||||
|
vmime::messaging::folder::FETCH_CONTENT_INFO);
|
||||||
|
|
||||||
|
// To retrieve the whole message
|
||||||
|
std::ostringstream oss;
|
||||||
|
vmime::outputStreamAdapter out(oss);
|
||||||
|
|
||||||
|
m->extract(out);
|
||||||
|
|
||||||
|
// To fetch the header
|
||||||
|
f->fetchMessage(m, vmime::messaging::folder::FETCH_ENVELOPE |
|
||||||
|
vmime::messaging::folder::FETCH_CONTENT_INFO |
|
||||||
|
vmime::messaging::folder::FETCH_STRUCTURE |
|
||||||
|
vmime::messaging::folder::FETCH_SIZE |
|
||||||
|
//vmime::messaging::folder::FETCH_FULL_HEADER |
|
||||||
|
vmime::messaging::folder::FETCH_SIZE |
|
||||||
|
vmime::messaging::folder::FETCH_FLAGS |
|
||||||
|
vmime::messaging::folder::FETCH_UID);
|
||||||
|
|
||||||
|
// Print structure
|
||||||
|
std::cout << "STRUCTURE:" << std::endl;
|
||||||
|
std::cout << "==========" << std::endl;
|
||||||
|
|
||||||
|
printStructure(m->structure());
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
std::cout << "Size = " << m->size() << " byte(s)" << std::endl;
|
||||||
|
std::cout << "UID = " << m->uniqueId() << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
std::cout << "ENVELOPE:" << std::endl;
|
||||||
|
std::cout << "=========" << std::endl;
|
||||||
|
try { std::cout << m->header().fields.From().generate() << std::endl; } catch (...) { }
|
||||||
|
try { std::cout << m->header().fields.To().generate() << std::endl; } catch (...) { }
|
||||||
|
try { std::cout << m->header().fields.Date().generate() << std::endl; } catch (...) { }
|
||||||
|
try { std::cout << m->header().fields.Subject().generate() << std::endl; } catch (...) { }
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
std::cout << "FULL HEADER:" << std::endl;
|
||||||
|
std::cout << "============" << std::endl;
|
||||||
|
std::cout << m->header().generate() << std::endl;
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "=========================================================" << std::endl;
|
||||||
|
|
||||||
|
vmime::outputStreamAdapter out2(std::cout);
|
||||||
|
m->extractPart(m->structure()[1][2][1], out2, NULL); //, 0, 10);
|
||||||
|
|
||||||
|
std::cout << "=========================================================" << std::endl;
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "=========================================================" << std::endl;
|
||||||
|
|
||||||
|
m->fetchPartHeader(m->structure()[1][2][1]);
|
||||||
|
|
||||||
|
std::cout << m->structure()[1][2][1].header().generate() << std::endl;
|
||||||
|
|
||||||
|
std::cout << "=========================================================" << std::endl;
|
||||||
|
|
||||||
|
// Flags manipulation
|
||||||
|
std::cout << "Flags = " << m->flags() << std::endl;
|
||||||
|
m->setFlags(vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_ADD);
|
||||||
|
std::cout << "Flags = " << m->flags() << std::endl;
|
||||||
|
m->setFlags(vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_REMOVE);
|
||||||
|
std::cout << "Flags = " << m->flags() << std::endl;
|
||||||
|
|
||||||
|
f->setMessageFlags(m->number(), m->number(), vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_ADD);
|
||||||
|
std::cout << "Flags = " << m->flags() << std::endl;
|
||||||
|
f->setMessageFlags(m->number(), m->number(), vmime::messaging::message::FLAG_REPLIED, vmime::messaging::message::FLAG_MODE_REMOVE);
|
||||||
|
std::cout << "Flags = " << m->flags() << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "=========================================================" << std::endl;
|
||||||
|
|
||||||
|
// Append message
|
||||||
|
/*
|
||||||
|
std::istringstream iss(
|
||||||
|
"From: me@localhost\r\n"
|
||||||
|
"To: you@localhost\r\n"
|
||||||
|
"Subject: Message Text\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"This is a test message...\r\n"
|
||||||
|
"Bye bye!\r\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
f->addMessage(iss, iss.str().size());
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Folder renaming
|
||||||
|
{
|
||||||
|
vmime::messaging::folder* f = st->getFolder(vmime::messaging::folder::path("c"));
|
||||||
|
f->rename(vmime::messaging::folder::path("c2"));
|
||||||
|
delete (f);
|
||||||
|
|
||||||
|
vmime::messaging::folder* g = st->getFolder(vmime::messaging::folder::path("c2"));
|
||||||
|
g->rename(vmime::messaging::folder::path("c"));
|
||||||
|
delete (g);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Message copy
|
||||||
|
{
|
||||||
|
vmime::messaging::folder* g = st->getFolder(vmime::messaging::folder::path("TEMP"));
|
||||||
|
|
||||||
|
if (!g->exists())
|
||||||
|
g->create(vmime::messaging::folder::TYPE_CONTAINS_MESSAGES);
|
||||||
|
|
||||||
|
f->copyMessages(g->fullPath());
|
||||||
|
|
||||||
|
delete (g);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
delete (m);
|
||||||
|
|
||||||
|
f->close(true);
|
||||||
|
delete (f);
|
||||||
|
|
||||||
|
st->disconnect();
|
||||||
|
delete (st);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (vmime::exceptions::authentication_error& e)
|
||||||
|
{
|
||||||
|
std::cout << "vmime::authentication_error: " << e.what() << std::endl
|
||||||
|
<< "Response is: '" << e.response() << "'." << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (vmime::exceptions::command_error& e)
|
||||||
|
{
|
||||||
|
std::cout << "vmime::command_error: " << e.what() << std::endl
|
||||||
|
<< "Response is: '" << e.response() << "'." << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (vmime::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "vmime::exception: " << e.what() << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "std::exception: " << e.what() << std::endl;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
201
src/address.cpp
Normal file
201
src/address.cpp
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "address.hpp"
|
||||||
|
|
||||||
|
#include "mailbox.hpp"
|
||||||
|
#include "mailboxGroup.hpp"
|
||||||
|
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
address::address()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
RFC #2822:
|
||||||
|
3.4. ADDRESS SPECIFICATION
|
||||||
|
|
||||||
|
Addresses occur in several message header fields to indicate senders
|
||||||
|
and recipients of messages. An address may either be an individual
|
||||||
|
mailbox, or a group of mailboxes.
|
||||||
|
|
||||||
|
address = mailbox / group
|
||||||
|
|
||||||
|
mailbox = name-addr / addr-spec
|
||||||
|
|
||||||
|
name-addr = [display-name] angle-addr
|
||||||
|
|
||||||
|
angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
|
||||||
|
|
||||||
|
group = display-name ":" [mailbox-list / CFWS] ";"
|
||||||
|
[CFWS]
|
||||||
|
|
||||||
|
display-name = phrase
|
||||||
|
|
||||||
|
mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list
|
||||||
|
|
||||||
|
address-list = (address *("," address)) / obs-addr-list
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
address* address::parseNext(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
bool escaped = false;
|
||||||
|
bool quoted = false;
|
||||||
|
bool quotedRFC2047 = false;
|
||||||
|
bool inRouteAddr = false;
|
||||||
|
bool isGroup = false;
|
||||||
|
bool stop = false;
|
||||||
|
|
||||||
|
string::size_type pos = position;
|
||||||
|
|
||||||
|
while (pos < end && isspace(buffer[pos]))
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
const string::size_type start = pos;
|
||||||
|
|
||||||
|
while (!stop && pos < end)
|
||||||
|
{
|
||||||
|
if (escaped)
|
||||||
|
{
|
||||||
|
escaped = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (buffer[pos])
|
||||||
|
{
|
||||||
|
case '\\':
|
||||||
|
escaped = true;
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
quoted = !quoted;
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
inRouteAddr = true;
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
inRouteAddr = false;
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
|
||||||
|
if (pos + 1 < end && buffer[pos + 1] == '?')
|
||||||
|
{
|
||||||
|
++pos;
|
||||||
|
quotedRFC2047 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
|
||||||
|
if (quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '=')
|
||||||
|
{
|
||||||
|
++pos;
|
||||||
|
quotedRFC2047 = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if (!quoted && !quotedRFC2047 && !inRouteAddr)
|
||||||
|
{
|
||||||
|
switch (buffer[pos])
|
||||||
|
{
|
||||||
|
case ';':
|
||||||
|
|
||||||
|
if (isGroup)
|
||||||
|
{
|
||||||
|
if (pos + 1 < end && buffer[pos + 1] == ',')
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
stop = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ':':
|
||||||
|
|
||||||
|
isGroup = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ',':
|
||||||
|
|
||||||
|
if (!isGroup) stop = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stop)
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
{
|
||||||
|
if (pos == end)
|
||||||
|
*newPosition = end;
|
||||||
|
else
|
||||||
|
*newPosition = pos + 1; // ',' or ';'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse extracted address (mailbox or group)
|
||||||
|
if (pos != start)
|
||||||
|
{
|
||||||
|
address* parsedAddress = isGroup
|
||||||
|
? static_cast<address*>(new mailboxGroup)
|
||||||
|
: static_cast<address*>(new mailbox);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parsedAddress->parse(buffer, start, pos, NULL);
|
||||||
|
return (parsedAddress);
|
||||||
|
}
|
||||||
|
catch (std::exception&)
|
||||||
|
{
|
||||||
|
delete (parsedAddress);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
address& address::operator=(const address& addr)
|
||||||
|
{
|
||||||
|
copyFrom(addr);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
99
src/address.hpp
Normal file
99
src/address.hpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ADDRESS_HPP_INCLUDED
|
||||||
|
#define VMIME_ADDRESS_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** Abstract class representing a mailbox or a group of mailboxes.
|
||||||
|
*
|
||||||
|
* This class define a common behaviour for the mailbox
|
||||||
|
* and mailboxGroup classes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class address : public component
|
||||||
|
{
|
||||||
|
friend class addressList;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
address();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Copy data from another object to this object.
|
||||||
|
* Both objects must be the same type.
|
||||||
|
*
|
||||||
|
* @param addr other object
|
||||||
|
*/
|
||||||
|
address& operator=(const address& addr);
|
||||||
|
|
||||||
|
/** Duplicate this object.
|
||||||
|
*
|
||||||
|
* @return a copy of this object
|
||||||
|
*/
|
||||||
|
virtual address* clone() const = 0;
|
||||||
|
|
||||||
|
/** Copy data from another object to this object.
|
||||||
|
* Both objects must be the same type.
|
||||||
|
*
|
||||||
|
* @param addr other object
|
||||||
|
*/
|
||||||
|
virtual void copyFrom(const address& addr) = 0;
|
||||||
|
|
||||||
|
/** Check whether this address is empty (no mailboxes specified
|
||||||
|
* if this is a mailboxGroup -or- no email specified if this is
|
||||||
|
* a mailbox).
|
||||||
|
*
|
||||||
|
* @return true if this address is empty
|
||||||
|
*/
|
||||||
|
virtual const bool empty() const = 0;
|
||||||
|
|
||||||
|
/** Test whether this is object is a mailboxGroup.
|
||||||
|
*
|
||||||
|
* @return true if this is a mailboxGroup, false otherwise
|
||||||
|
*/
|
||||||
|
virtual const bool isGroup() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** Parse an address from an input buffer.
|
||||||
|
*
|
||||||
|
* @param buffer input buffer
|
||||||
|
* @param position position in the input buffer
|
||||||
|
* @param end end position in the input buffer
|
||||||
|
* @param newPosition will receive the new position in the input buffer
|
||||||
|
* @return a new address object, or null if no more address is available in the input buffer
|
||||||
|
*/
|
||||||
|
static address* parseNext(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ADDRESS_HPP_INCLUDED
|
188
src/addressList.cpp
Normal file
188
src/addressList.cpp
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "addressList.hpp"
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
addressList::addressList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addressList::addressList(const class addressList& addressList)
|
||||||
|
: component()
|
||||||
|
{
|
||||||
|
copyFrom(addressList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addressList::~addressList()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void addressList::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
string::size_type pos = position;
|
||||||
|
|
||||||
|
while (pos < end)
|
||||||
|
{
|
||||||
|
address* parsedAddress = address::parseNext(buffer, pos, end, &pos);
|
||||||
|
|
||||||
|
if (parsedAddress != NULL)
|
||||||
|
m_list.push_back(parsedAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void addressList::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
if (!m_list.empty())
|
||||||
|
{
|
||||||
|
string::size_type pos = curLinePos;
|
||||||
|
const_iterator i = m_list.begin();
|
||||||
|
|
||||||
|
for ( ; ; )
|
||||||
|
{
|
||||||
|
(*i).generate(os, maxLineLength - 2, pos, &pos);
|
||||||
|
|
||||||
|
if (++i != m_list.end())
|
||||||
|
{
|
||||||
|
os << ", ";
|
||||||
|
pos += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
*newLinePos = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Return the number of addresses in the list.
|
||||||
|
*
|
||||||
|
* @return number of addresses in the list
|
||||||
|
*/
|
||||||
|
|
||||||
|
const std::vector <address*>::size_type addressList::size() const
|
||||||
|
{
|
||||||
|
return (m_list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Return the number of addresses in the list.
|
||||||
|
*
|
||||||
|
* @return number of addresses in the list
|
||||||
|
*/
|
||||||
|
|
||||||
|
const std::vector <address*>::size_type addressList::count() const
|
||||||
|
{
|
||||||
|
return (m_list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Test whether the list is empty.
|
||||||
|
*
|
||||||
|
* @return true if the list is empty, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
const bool addressList::empty() const
|
||||||
|
{
|
||||||
|
return (m_list.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Append an address to the list.
|
||||||
|
*
|
||||||
|
* @param addr the address to add
|
||||||
|
*/
|
||||||
|
|
||||||
|
void addressList::append(const address& addr)
|
||||||
|
{
|
||||||
|
m_list.push_back(addr.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Insert an address at the specified position in the list.
|
||||||
|
*
|
||||||
|
* @param it position of the new address
|
||||||
|
* @param addr the address to insert
|
||||||
|
*/
|
||||||
|
|
||||||
|
void addressList::insert(const iterator it, const address& addr)
|
||||||
|
{
|
||||||
|
m_list.insert(it.m_iterator, addr.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Remove the address at the specified position.
|
||||||
|
*
|
||||||
|
* @param it position of the address to remove
|
||||||
|
*/
|
||||||
|
|
||||||
|
void addressList::erase(const iterator it)
|
||||||
|
{
|
||||||
|
delete (*it.m_iterator);
|
||||||
|
m_list.erase(it.m_iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Remove all the addresses from the list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void addressList::clear()
|
||||||
|
{
|
||||||
|
free_container(m_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void addressList::copyFrom(const addressList& source)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
for (std::vector <address*>::const_iterator i = source.m_list.begin() ; i != source.m_list.end() ; ++i)
|
||||||
|
m_list.push_back((*i)->clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addressList& addressList::operator=(const addressList& source)
|
||||||
|
{
|
||||||
|
copyFrom(source);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
148
src/addressList.hpp
Normal file
148
src/addressList.hpp
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ADDRESSLIST_HPP_INCLUDED
|
||||||
|
#define VMIME_ADDRESSLIST_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
#include "address.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** A list of addresses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class addressList : public component
|
||||||
|
{
|
||||||
|
friend class addressListField;
|
||||||
|
friend class mailboxListField;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
addressList();
|
||||||
|
addressList(const class addressList& addressList);
|
||||||
|
|
||||||
|
~addressList();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
addressList& operator=(const addressList& source);
|
||||||
|
|
||||||
|
// Address iterator
|
||||||
|
class const_iterator;
|
||||||
|
|
||||||
|
class iterator
|
||||||
|
{
|
||||||
|
friend class addressList;
|
||||||
|
friend class const_iterator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
iterator(std::vector <address*>::iterator it) : m_iterator(it) { }
|
||||||
|
iterator(const iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
|
||||||
|
iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
|
||||||
|
address& operator*() const { return (**m_iterator); }
|
||||||
|
address* operator->() const { return (*m_iterator); }
|
||||||
|
|
||||||
|
iterator& operator++() { ++m_iterator; return (*this); }
|
||||||
|
iterator& operator++(int) { ++m_iterator; return (*this); }
|
||||||
|
|
||||||
|
const bool operator==(const iterator& it) const { return (it.m_iterator == m_iterator); }
|
||||||
|
const bool operator!=(const iterator& it) const { return (!(*this == it)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector <address*>::iterator m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
class const_iterator
|
||||||
|
{
|
||||||
|
friend class addressList;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const_iterator(std::vector <address*>::const_iterator it) : m_iterator(it) { }
|
||||||
|
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
|
||||||
|
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
|
||||||
|
const address& operator*() const { return (**m_iterator); }
|
||||||
|
const address* operator->() const { return (*m_iterator); }
|
||||||
|
|
||||||
|
const_iterator& operator++() { ++m_iterator; return (*this); }
|
||||||
|
const_iterator& operator++(int) { ++m_iterator; return (*this); }
|
||||||
|
|
||||||
|
const bool operator==(const const_iterator& it) const { return (it.m_iterator == m_iterator); }
|
||||||
|
const bool operator!=(const const_iterator& it) const { return (!(*this == it)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector <address*>::const_iterator m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator begin() { return (m_list.begin()); }
|
||||||
|
iterator end() { return (m_list.end()); }
|
||||||
|
|
||||||
|
const_iterator begin() const { return (const_iterator(m_list.begin())); }
|
||||||
|
const_iterator end() const { return (const_iterator(m_list.end())); }
|
||||||
|
|
||||||
|
const std::vector <address*>::size_type size() const;
|
||||||
|
const std::vector <address*>::size_type count() const;
|
||||||
|
const bool empty() const;
|
||||||
|
|
||||||
|
const address& operator[](const std::vector <address*>::size_type x) const { return (*m_list[x]); }
|
||||||
|
address& operator[](const std::vector <address*>::size_type x) { return (*m_list[x]); }
|
||||||
|
|
||||||
|
virtual void append(const address& addr);
|
||||||
|
virtual void insert(const iterator it, const address& addr);
|
||||||
|
|
||||||
|
void erase(const iterator it);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::vector <address*> m_list;
|
||||||
|
|
||||||
|
void copyFrom(const addressList& source);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using component::parse;
|
||||||
|
using component::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ADDRESSLIST_HPP_INCLUDED
|
67
src/addressListField.cpp
Normal file
67
src/addressListField.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "addressListField.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
addressListField::addressListField()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void addressListField::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
m_list.parse(buffer, position, end, newPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void addressListField::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
string::size_type pos = curLinePos;
|
||||||
|
|
||||||
|
headerField::generate(os, maxLineLength, pos, &pos);
|
||||||
|
|
||||||
|
m_list.generate(os, maxLineLength, pos, newLinePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
addressListField& addressListField::operator=(const addressList& list)
|
||||||
|
{
|
||||||
|
m_list.copyFrom(list);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void addressListField::copyFrom(const headerField& field)
|
||||||
|
{
|
||||||
|
const addressListField& source = dynamic_cast<const addressListField&>(field);
|
||||||
|
m_list = source.m_list;
|
||||||
|
|
||||||
|
headerField::copyFrom(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
70
src/addressListField.hpp
Normal file
70
src/addressListField.hpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ADDRESSLISTFIELD_HPP_INCLUDED
|
||||||
|
#define VMIME_ADDRESSLISTFIELD_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
#include "headerFieldFactory.hpp"
|
||||||
|
#include "addressList.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class addressListField : public headerField
|
||||||
|
{
|
||||||
|
friend class headerFieldFactory::registerer <addressListField>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
addressListField();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void copyFrom(const headerField& field);
|
||||||
|
|
||||||
|
addressListField& operator=(const addressList& list);
|
||||||
|
|
||||||
|
const addressList& value() const { return (m_list); }
|
||||||
|
addressList& value() { return (m_list); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
addressList m_list;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using headerField::parse;
|
||||||
|
using headerField::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ADDRESSLISTFIELD_HPP_INCLUDED
|
82
src/attachment.hpp
Normal file
82
src/attachment.hpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ATTACHMENT_HPP_INCLUDED
|
||||||
|
#define VMIME_ATTACHMENT_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
|
||||||
|
#include "bodyPart.hpp"
|
||||||
|
#include "mediaType.hpp"
|
||||||
|
#include "text.hpp"
|
||||||
|
#include "contentHandler.hpp"
|
||||||
|
#include "encoding.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class attachment
|
||||||
|
{
|
||||||
|
friend class messageBuilder;
|
||||||
|
friend class messageParser;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
attachment() { }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~attachment() { }
|
||||||
|
|
||||||
|
virtual attachment& operator=(const attachment& attach) = 0;
|
||||||
|
|
||||||
|
/** Return the media type of this attachment.
|
||||||
|
* @return content type of the attachment
|
||||||
|
*/
|
||||||
|
virtual const mediaType& type() const = 0;
|
||||||
|
|
||||||
|
/** Return the description of this attachment.
|
||||||
|
* @return attachment description
|
||||||
|
*/
|
||||||
|
virtual const text& description() const = 0;
|
||||||
|
|
||||||
|
/** Return the data contained in this attachment.
|
||||||
|
* @return attachment data
|
||||||
|
*/
|
||||||
|
virtual const contentHandler& data() const = 0;
|
||||||
|
|
||||||
|
/** Return the encoding used for this attachment.
|
||||||
|
* @return attachment data encoding
|
||||||
|
*/
|
||||||
|
virtual const class encoding& encoding() const = 0;
|
||||||
|
|
||||||
|
/** Generate the attachment in the specified body part.
|
||||||
|
* @param parent body part in which to generate the attachment
|
||||||
|
*/
|
||||||
|
virtual void generateIn(bodyPart& parent) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ATTACHMENT_HPP_INCLUDED
|
877
src/base.cpp
Normal file
877
src/base.cpp
Normal file
@ -0,0 +1,877 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "config.hpp"
|
||||||
|
|
||||||
|
#include "charset.hpp"
|
||||||
|
#include "base.hpp"
|
||||||
|
|
||||||
|
#include "encoder.hpp"
|
||||||
|
#include "encoderB64.hpp"
|
||||||
|
#include "encoderQP.hpp"
|
||||||
|
|
||||||
|
#include "text.hpp"
|
||||||
|
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
// For initializing
|
||||||
|
#include "encoderFactory.hpp"
|
||||||
|
#include "headerFieldFactory.hpp"
|
||||||
|
#include "parameterFactory.hpp"
|
||||||
|
#include "textPartFactory.hpp"
|
||||||
|
#include "options.hpp"
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||||
|
#include "messaging/serviceFactory.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** "Null" (empty) string.
|
||||||
|
*/
|
||||||
|
const string NULL_STRING;
|
||||||
|
|
||||||
|
#if VMIME_WIDE_CHAR_SUPPORT
|
||||||
|
/** "Null" (empty) wide-char string.
|
||||||
|
*/
|
||||||
|
const wstring NULL_WSTRING;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** "Null" (empty) text.
|
||||||
|
*/
|
||||||
|
const text NULL_TEXT;
|
||||||
|
|
||||||
|
|
||||||
|
/** Return the library name (eg. "libvmime").
|
||||||
|
*
|
||||||
|
* @return library name
|
||||||
|
*/
|
||||||
|
const string libname() { return (VMIME_PACKAGE); }
|
||||||
|
|
||||||
|
/** Return the library version (eg. "0.5.2").
|
||||||
|
*
|
||||||
|
* @return library version
|
||||||
|
*/
|
||||||
|
const string libversion() { return (VMIME_VERSION " (" __DATE__ " " __TIME__ ")"); }
|
||||||
|
|
||||||
|
|
||||||
|
// New line sequence to be used when folding header fields.
|
||||||
|
const string NEW_LINE_SEQUENCE("\r\n ");
|
||||||
|
const string::size_type NEW_LINE_SEQUENCE_LENGTH(1); // space
|
||||||
|
|
||||||
|
/** The CR-LF sequence.
|
||||||
|
*/
|
||||||
|
const string CRLF("\r\n");
|
||||||
|
|
||||||
|
|
||||||
|
/** The current MIME version supported by VMime.
|
||||||
|
*/
|
||||||
|
const string MIME_VERSION("1.0");
|
||||||
|
|
||||||
|
|
||||||
|
// Line length limits
|
||||||
|
namespace lineLengthLimits
|
||||||
|
{
|
||||||
|
const string::size_type infinite = std::numeric_limits <string::size_type>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Test two strings for equality (case insensitive).
|
||||||
|
* WARNING: use this with ASCII-only strings.
|
||||||
|
*
|
||||||
|
* @param s1 first string
|
||||||
|
* @param s2 second string (must be in lower-case!)
|
||||||
|
* @param n length of the second string
|
||||||
|
* @return true if the two strings compare equally, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool isStringEqualNoCase(const string& s1, const char* s2, const string::size_type n)
|
||||||
|
{
|
||||||
|
// 'n' is the number of characters to compare
|
||||||
|
// 's2' must be in lowercase letters only
|
||||||
|
if (s1.length() < n)
|
||||||
|
return (false);
|
||||||
|
|
||||||
|
bool equal = true;
|
||||||
|
|
||||||
|
for (string::size_type i = 0 ; equal && i < n ; ++i)
|
||||||
|
equal = (std::tolower(s1[i], std::locale()) == s2[i]);
|
||||||
|
|
||||||
|
return (equal);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Test two strings for equality (case insensitive).
|
||||||
|
* WARNING: use this with ASCII-only strings.
|
||||||
|
*
|
||||||
|
* @param s1 first string
|
||||||
|
* @param s2 second string
|
||||||
|
* @return true if the two strings compare equally, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool isStringEqualNoCase(const string& s1, const string& s2)
|
||||||
|
{
|
||||||
|
if (s1.length() != s2.length())
|
||||||
|
return (false);
|
||||||
|
|
||||||
|
bool equal = true;
|
||||||
|
const string::const_iterator end = s1.end();
|
||||||
|
|
||||||
|
for (string::const_iterator i = s1.begin(), j = s2.begin(); i != end ; ++i, ++j)
|
||||||
|
equal = (std::tolower(*i, std::locale()) == std::tolower(*j, std::locale()));
|
||||||
|
|
||||||
|
return (equal);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Test two strings for equality (case insensitive).
|
||||||
|
* WARNING: use this with ASCII-only strings.
|
||||||
|
*
|
||||||
|
* @param begin start position of the first string
|
||||||
|
* @param end end position of the first string
|
||||||
|
* @param s second string (must be in lower-case!)
|
||||||
|
* @param n length of the second string
|
||||||
|
* @return true if the two strings compare equally, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool isStringEqualNoCase(const string::const_iterator begin, const string::const_iterator end,
|
||||||
|
const char* s, const string::size_type n)
|
||||||
|
{
|
||||||
|
if ((string::size_type)(end - begin) < n)
|
||||||
|
return (false);
|
||||||
|
|
||||||
|
bool equal = true;
|
||||||
|
char* c = const_cast<char*>(s);
|
||||||
|
string::size_type r = n;
|
||||||
|
|
||||||
|
for (string::const_iterator i = begin ; equal && r && *c ; ++i, ++c, --r)
|
||||||
|
equal = (std::tolower(*i, std::locale()) == *c);
|
||||||
|
|
||||||
|
return (r == 0 && equal);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Transform all the characters in a string to lower-case.
|
||||||
|
* WARNING: use this with ASCII-only strings.
|
||||||
|
*
|
||||||
|
* @param str the string to transform
|
||||||
|
* @return a new string in lower-case
|
||||||
|
*/
|
||||||
|
|
||||||
|
const string toLower(const string& str)
|
||||||
|
{
|
||||||
|
string out(str);
|
||||||
|
const string::iterator end = out.end();
|
||||||
|
|
||||||
|
for (string::iterator i = out.begin() ; i != end ; ++i)
|
||||||
|
*i = std::tolower(*i, std::locale());
|
||||||
|
|
||||||
|
return (out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Strip the space characters (SPC, TAB, CR, LF) at the beginning
|
||||||
|
* and at the end of the specified string.
|
||||||
|
*
|
||||||
|
* @param str string in which to strip spaces
|
||||||
|
* @return a new string with space characters removed
|
||||||
|
*/
|
||||||
|
|
||||||
|
const string trim(const string& str)
|
||||||
|
{
|
||||||
|
string::const_iterator b = str.begin();
|
||||||
|
string::const_iterator e = str.end();
|
||||||
|
|
||||||
|
if (b != e)
|
||||||
|
{
|
||||||
|
for ( ; b != e && isspace(*b) ; ++b);
|
||||||
|
for ( ; e != b && isspace(*(e - 1)) ; --e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (string(b, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Return the number of 7-bit US-ASCII characters in a string.
|
||||||
|
*
|
||||||
|
* @param begin start position
|
||||||
|
* @param end end position
|
||||||
|
* @return number of ASCII characters
|
||||||
|
*/
|
||||||
|
|
||||||
|
string::size_type countASCIIchars
|
||||||
|
(const string::const_iterator begin, const string::const_iterator end)
|
||||||
|
{
|
||||||
|
string::size_type count = 0;
|
||||||
|
|
||||||
|
for (string::const_iterator i = begin ; i != end ; ++i)
|
||||||
|
{
|
||||||
|
if (isascii(*i))
|
||||||
|
{
|
||||||
|
if (*i != '=' || *(i + 1) != '?') // To avoid bad behaviour...
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Encode and fold text in respect to RFC-2047.
|
||||||
|
*
|
||||||
|
* @param os output stream
|
||||||
|
* @param in input text
|
||||||
|
* @param maxLineLength maximum line length for output
|
||||||
|
* @param firstLineOffset the first line length (may be useful if the current output line is not empty)
|
||||||
|
* @param lastLineLength will receive the length of the last line written
|
||||||
|
* @param flags encoding flags (see encodeAndFoldFlags)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void encodeAndFoldText(utility::outputStream& os, const text& in, const string::size_type maxLineLength,
|
||||||
|
const string::size_type firstLineOffset, string::size_type* lastLineLength, const int flags)
|
||||||
|
{
|
||||||
|
string::size_type curLineLength = firstLineOffset;
|
||||||
|
|
||||||
|
for (text::const_iterator wi = in.begin() ; wi != in.end() ; ++wi)
|
||||||
|
{
|
||||||
|
const word& w = *wi;
|
||||||
|
const string& buffer = w.buffer();
|
||||||
|
|
||||||
|
// Calculate the number of ASCII chars to check whether encoding is needed
|
||||||
|
// and _which_ encoding to use.
|
||||||
|
const string::size_type asciiCount = countASCIIchars(buffer.begin(), buffer.end());
|
||||||
|
|
||||||
|
bool noEncoding = (flags & encodeAndFoldFlags::forceNoEncoding) ||
|
||||||
|
(!(flags & encodeAndFoldFlags::forceEncoding) && asciiCount == buffer.length());
|
||||||
|
|
||||||
|
if (noEncoding)
|
||||||
|
{
|
||||||
|
// We will fold lines without encoding them.
|
||||||
|
|
||||||
|
string::const_iterator lastWSpos = buffer.end(); // last white-space position
|
||||||
|
string::const_iterator curLineStart = buffer.begin(); // current line start
|
||||||
|
|
||||||
|
string::const_iterator p = buffer.begin();
|
||||||
|
const string::const_iterator end = buffer.end();
|
||||||
|
|
||||||
|
bool finished = false;
|
||||||
|
bool newLine = false;
|
||||||
|
|
||||||
|
while (!finished)
|
||||||
|
{
|
||||||
|
for ( ; p != end ; ++p, ++curLineLength)
|
||||||
|
{
|
||||||
|
// Exceeded maximum line length, but we have found a white-space
|
||||||
|
// where we can cut the line...
|
||||||
|
if (curLineLength >= maxLineLength && lastWSpos != end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (*p == ' ' || *p == '\t')
|
||||||
|
{
|
||||||
|
// Remember the position of this white-space character
|
||||||
|
lastWSpos = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p != end)
|
||||||
|
++curLineLength;
|
||||||
|
|
||||||
|
//if (p == end || curLineLength >= maxLineLength)
|
||||||
|
{
|
||||||
|
if (p == end || lastWSpos == end)
|
||||||
|
{
|
||||||
|
// If we are here, it means that we have found no whitespace
|
||||||
|
// before the first "maxLineLength" characters. In this case,
|
||||||
|
// we write the full line no matter of the max line length...
|
||||||
|
|
||||||
|
if (!newLine && p != end && lastWSpos == end &&
|
||||||
|
wi != in.begin() && curLineStart == buffer.begin())
|
||||||
|
{
|
||||||
|
// Here, we are continuing on the line of previous encoded
|
||||||
|
// word, but there is not even enough space to put the
|
||||||
|
// first word of this line, so we start a new line.
|
||||||
|
if (flags & encodeAndFoldFlags::noNewLineSequence)
|
||||||
|
{
|
||||||
|
os << CRLF;
|
||||||
|
curLineLength = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << NEW_LINE_SEQUENCE;
|
||||||
|
curLineLength = NEW_LINE_SEQUENCE_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = curLineStart;
|
||||||
|
lastWSpos = end;
|
||||||
|
newLine = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << string(curLineStart, p);
|
||||||
|
|
||||||
|
if (p == end)
|
||||||
|
{
|
||||||
|
finished = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (flags & encodeAndFoldFlags::noNewLineSequence)
|
||||||
|
{
|
||||||
|
os << CRLF;
|
||||||
|
curLineLength = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << NEW_LINE_SEQUENCE;
|
||||||
|
curLineLength = NEW_LINE_SEQUENCE_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
curLineStart = p;
|
||||||
|
lastWSpos = end;
|
||||||
|
newLine = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// In this case, there will not be enough space on the line for all the
|
||||||
|
// characters _after_ the last white-space; so we cut the line at this
|
||||||
|
// last white-space.
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
if (curLineLength != 1 && wi != in.begin())
|
||||||
|
os << " "; // Separate from previous word
|
||||||
|
#endif
|
||||||
|
|
||||||
|
os << string(curLineStart, lastWSpos);
|
||||||
|
|
||||||
|
if (flags & encodeAndFoldFlags::noNewLineSequence)
|
||||||
|
{
|
||||||
|
os << CRLF;
|
||||||
|
curLineLength = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << NEW_LINE_SEQUENCE;
|
||||||
|
curLineLength = NEW_LINE_SEQUENCE_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
curLineStart = lastWSpos + 1;
|
||||||
|
|
||||||
|
p = lastWSpos + 1;
|
||||||
|
lastWSpos = end;
|
||||||
|
newLine = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
RFC #2047:
|
||||||
|
4. Encodings
|
||||||
|
|
||||||
|
Initially, the legal values for "encoding" are "Q" and "B". These
|
||||||
|
encodings are described below. The "Q" encoding is recommended for
|
||||||
|
use when most of the characters to be encoded are in the ASCII
|
||||||
|
character set; otherwise, the "B" encoding should be used.
|
||||||
|
Nevertheless, a mail reader which claims to recognize 'encoded-word's
|
||||||
|
MUST be able to accept either encoding for any character set which it
|
||||||
|
supports.
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We will encode _AND_ fold lines
|
||||||
|
|
||||||
|
/*
|
||||||
|
RFC #2047:
|
||||||
|
2. Syntax of encoded-words
|
||||||
|
|
||||||
|
" While there is no limit to the length of a multiple-line header
|
||||||
|
field, each line of a header field that contains one or more
|
||||||
|
'encoded-word's is limited to 76 characters. "
|
||||||
|
*/
|
||||||
|
|
||||||
|
const string::size_type maxLineLength3 =
|
||||||
|
(maxLineLength == lineLengthLimits::infinite)
|
||||||
|
? maxLineLength
|
||||||
|
: std::min(maxLineLength, (const string::size_type) 76);
|
||||||
|
|
||||||
|
// Base64 if more than 60% non-ascii, quoted-printable else (default)
|
||||||
|
const string::size_type asciiPercent = (100 * asciiCount) / buffer.length();
|
||||||
|
const string::value_type encoding = (asciiPercent <= 40) ? 'B' : 'Q';
|
||||||
|
|
||||||
|
string wordStart("=?" + w.charset().name() + "?" + encoding + "?");
|
||||||
|
string wordEnd("?=");
|
||||||
|
|
||||||
|
const string::size_type minWordLength = wordStart.length() + wordEnd.length();
|
||||||
|
const string::size_type maxLineLength2 = (maxLineLength3 < minWordLength + 1)
|
||||||
|
? maxLineLength3 + minWordLength + 1 : maxLineLength3;
|
||||||
|
|
||||||
|
// Checks whether remaining space on this line is usable. If too few
|
||||||
|
// characters can be encoded, start a new line.
|
||||||
|
bool startNewLine = true;
|
||||||
|
|
||||||
|
if (curLineLength + 2 < maxLineLength2)
|
||||||
|
{
|
||||||
|
const string::size_type remainingSpaceOnLine = maxLineLength2 - curLineLength - 2;
|
||||||
|
|
||||||
|
if (remainingSpaceOnLine < minWordLength + 10)
|
||||||
|
{
|
||||||
|
// Space for no more than 10 encoded chars!
|
||||||
|
// It is not worth while to continue on this line...
|
||||||
|
startNewLine = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// OK, there is enough usable space on the current line.
|
||||||
|
startNewLine = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startNewLine)
|
||||||
|
{
|
||||||
|
os << NEW_LINE_SEQUENCE;
|
||||||
|
curLineLength = NEW_LINE_SEQUENCE_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode and fold input buffer
|
||||||
|
string::const_iterator pos = buffer.begin();
|
||||||
|
string::size_type remaining = buffer.length();
|
||||||
|
|
||||||
|
encoder* theEncoder = ((encoding == 'B')
|
||||||
|
? ((encoder*) new encoderB64)
|
||||||
|
: ((encoder*) new encoderQP));
|
||||||
|
|
||||||
|
string qpEncodedBuffer;
|
||||||
|
|
||||||
|
if (encoding == 'Q')
|
||||||
|
{
|
||||||
|
theEncoder->properties()["rfc2047"] = true;
|
||||||
|
|
||||||
|
// In the case of Quoted-Printable encoding, we cannot simply encode input
|
||||||
|
// buffer line by line. So, we encode the whole buffer and we will fold it
|
||||||
|
// in the next loop...
|
||||||
|
utility::inputStreamStringAdapter in(buffer);
|
||||||
|
utility::outputStreamStringAdapter out(qpEncodedBuffer);
|
||||||
|
|
||||||
|
theEncoder->encode(in, out);
|
||||||
|
|
||||||
|
pos = qpEncodedBuffer.begin();
|
||||||
|
remaining = qpEncodedBuffer.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
if (curLineLength != 1 && wi != in.begin())
|
||||||
|
{
|
||||||
|
os << " "; // Separate from previous word
|
||||||
|
++curLineLength;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for ( ; remaining ; )
|
||||||
|
{
|
||||||
|
// Start a new encoded word
|
||||||
|
os << wordStart;
|
||||||
|
curLineLength += minWordLength;
|
||||||
|
|
||||||
|
// Compute the number of encoded chars that will fit on this line
|
||||||
|
const string::size_type fit = maxLineLength2 - curLineLength;
|
||||||
|
|
||||||
|
// Base-64 encoding
|
||||||
|
if (encoding == 'B')
|
||||||
|
{
|
||||||
|
// TODO: WARNING! "Any encoded word which encodes a non-integral
|
||||||
|
// number of characters or octets is incorrectly formed."
|
||||||
|
|
||||||
|
// Here, we have a formula to compute the maximum number of source
|
||||||
|
// characters to encode knowing the maximum number of encoded chars
|
||||||
|
// (with Base64, 3 bytes of input provide 4 bytes of output).
|
||||||
|
string::size_type count = (fit > 1) ? ((fit - 1) * 3) / 4 : 1;
|
||||||
|
if (count > remaining) count = remaining;
|
||||||
|
|
||||||
|
utility::inputStreamStringAdapter in
|
||||||
|
(buffer, pos - buffer.begin(), pos - buffer.begin() + count);
|
||||||
|
|
||||||
|
curLineLength += theEncoder->encode(in, os);
|
||||||
|
|
||||||
|
pos += count;
|
||||||
|
remaining -= count;
|
||||||
|
}
|
||||||
|
// Quoted-Printable encoding
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: WARNING! "Any encoded word which encodes a non-integral
|
||||||
|
// number of characters or octets is incorrectly formed."
|
||||||
|
|
||||||
|
// All we have to do here is to take a certain number of character
|
||||||
|
// (that is less than or equal to "fit") from the QP encoded buffer,
|
||||||
|
// but we also make sure not to fold a "=XY" encoded char.
|
||||||
|
const string::const_iterator qpEnd = qpEncodedBuffer.end();
|
||||||
|
string::const_iterator lastFoldPos = pos;
|
||||||
|
string::const_iterator p = pos;
|
||||||
|
string::size_type n = 0;
|
||||||
|
|
||||||
|
while (n < fit && p != qpEnd)
|
||||||
|
{
|
||||||
|
if (*p == '=')
|
||||||
|
{
|
||||||
|
if (n + 3 >= fit)
|
||||||
|
{
|
||||||
|
lastFoldPos = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 3;
|
||||||
|
n += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastFoldPos == pos)
|
||||||
|
lastFoldPos = p;
|
||||||
|
|
||||||
|
os << string(pos, lastFoldPos);
|
||||||
|
|
||||||
|
curLineLength += (lastFoldPos - pos) + 1;
|
||||||
|
|
||||||
|
pos += n;
|
||||||
|
remaining -= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of the encoded word
|
||||||
|
os << wordEnd;
|
||||||
|
|
||||||
|
if (remaining)
|
||||||
|
{
|
||||||
|
os << NEW_LINE_SEQUENCE;
|
||||||
|
curLineLength = NEW_LINE_SEQUENCE_LENGTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete (theEncoder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastLineLength)
|
||||||
|
*lastLineLength = curLineLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void decodeAndUnfoldText(const string::const_iterator& inStart, const string::const_iterator& inEnd, text& out)
|
||||||
|
{
|
||||||
|
// NOTE: See RFC-2047, Pages 11-12 for knowing about handling
|
||||||
|
// of white-spaces between encoded words.
|
||||||
|
|
||||||
|
out.clear();
|
||||||
|
|
||||||
|
string::const_iterator p = inStart;
|
||||||
|
const string::const_iterator end = inEnd;
|
||||||
|
|
||||||
|
const charset defaultCharset(charsets::US_ASCII);
|
||||||
|
charset prevWordCharset(defaultCharset);
|
||||||
|
|
||||||
|
bool prevIsEncoded = false;
|
||||||
|
|
||||||
|
string::const_iterator prevPos = p;
|
||||||
|
|
||||||
|
for ( ; ; )
|
||||||
|
{
|
||||||
|
if (p == end || *p == '\n')
|
||||||
|
{
|
||||||
|
string::const_iterator textEnd = p;
|
||||||
|
|
||||||
|
if (textEnd != inStart && *(textEnd - 1) == '\r')
|
||||||
|
--textEnd;
|
||||||
|
|
||||||
|
if (textEnd != prevPos)
|
||||||
|
{
|
||||||
|
if (out.size() && prevWordCharset == defaultCharset)
|
||||||
|
{
|
||||||
|
out.back().buffer() += string(prevPos, textEnd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prevWordCharset = defaultCharset;
|
||||||
|
out.append(word(string(prevPos, textEnd), defaultCharset));
|
||||||
|
prevIsEncoded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == end)
|
||||||
|
{
|
||||||
|
// Finished
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip the new-line character
|
||||||
|
prevPos = ++p;
|
||||||
|
}
|
||||||
|
else if (*p == '=' && (p + 1) != end && *(p + 1) == '?')
|
||||||
|
{
|
||||||
|
string::const_iterator wordPos = p;
|
||||||
|
p += 2; // skip '=?'
|
||||||
|
|
||||||
|
if (p != end)
|
||||||
|
{
|
||||||
|
const string::const_iterator charsetPos = p;
|
||||||
|
|
||||||
|
for ( ; p != end && *p != '?' ; ++p);
|
||||||
|
|
||||||
|
if (p != end) // a charset is specified
|
||||||
|
{
|
||||||
|
const string::const_iterator charsetEnd = p;
|
||||||
|
const string::const_iterator encPos = ++p; // skip '?'
|
||||||
|
|
||||||
|
for ( ; p != end && *p != '?' ; ++p);
|
||||||
|
|
||||||
|
if (p != end) // an encoding is specified
|
||||||
|
{
|
||||||
|
//const string::const_iterator encEnd = p;
|
||||||
|
const string::const_iterator dataPos = ++p; // skip '?'
|
||||||
|
|
||||||
|
for ( ; p != end && !(*p == '?' && *(p + 1) == '=') ; ++p);
|
||||||
|
|
||||||
|
if (p != end) // some data is specified
|
||||||
|
{
|
||||||
|
const string::const_iterator dataEnd = p;
|
||||||
|
p += 2; // skip '?='
|
||||||
|
|
||||||
|
encoder* theEncoder = NULL;
|
||||||
|
|
||||||
|
// Base-64 encoding
|
||||||
|
if (*encPos == 'B' || *encPos == 'b')
|
||||||
|
{
|
||||||
|
theEncoder = new encoderB64;
|
||||||
|
}
|
||||||
|
// Quoted-Printable encoding
|
||||||
|
else if (*encPos == 'Q' || *encPos == 'q')
|
||||||
|
{
|
||||||
|
theEncoder = new encoderQP;
|
||||||
|
theEncoder->properties()["rfc2047"] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (theEncoder)
|
||||||
|
{
|
||||||
|
// Decode text
|
||||||
|
string decodedBuffer;
|
||||||
|
|
||||||
|
utility::inputStreamStringAdapter ein(string(dataPos, dataEnd));
|
||||||
|
utility::outputStreamStringAdapter eout(decodedBuffer);
|
||||||
|
|
||||||
|
theEncoder->decode(ein, eout);
|
||||||
|
delete (theEncoder);
|
||||||
|
|
||||||
|
// Append all the unencoded text before this word
|
||||||
|
if (prevPos != wordPos)
|
||||||
|
{
|
||||||
|
string::const_iterator p = prevPos;
|
||||||
|
|
||||||
|
if (prevIsEncoded)
|
||||||
|
{
|
||||||
|
// Check whether there are only white-spaces between
|
||||||
|
// the two encoded words
|
||||||
|
for ( ; (p != wordPos) && isspace(*p) ; ++p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p != wordPos) // if not empty
|
||||||
|
{
|
||||||
|
if (out.size() && prevWordCharset == defaultCharset)
|
||||||
|
{
|
||||||
|
out.back().buffer() += string(prevPos, wordPos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.append(word(string(prevPos, wordPos), defaultCharset));
|
||||||
|
prevWordCharset = defaultCharset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append this fresh decoded word to output text
|
||||||
|
charset thisCharset(string(charsetPos, charsetEnd));
|
||||||
|
|
||||||
|
if (out.size() && prevWordCharset == thisCharset)
|
||||||
|
{
|
||||||
|
out.back().buffer() += decodedBuffer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prevWordCharset = thisCharset;
|
||||||
|
out.append(word(decodedBuffer, thisCharset));
|
||||||
|
}
|
||||||
|
|
||||||
|
// This word has been decoded: we can advance in the input buffer
|
||||||
|
prevPos = p;
|
||||||
|
prevIsEncoded = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Unknown encoding: can't decode this word, we will
|
||||||
|
// treat this word as ordinary text (RFC-2047, Page 9).
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ; p != end && *p != '=' && *p != '\n' ; ++p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void decodeAndUnfoldText(const string& in, text& out)
|
||||||
|
{
|
||||||
|
decodeAndUnfoldText(in.begin(), in.end(), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** This function can be used to make several encoded words from a text.
|
||||||
|
* All the characters in the text must be in the same specified charset.
|
||||||
|
*
|
||||||
|
* <p>Eg: giving:</p>
|
||||||
|
* <pre> <iso-8859-1> "Linux dans un t'el'ephone mobile"
|
||||||
|
* ("=?iso-8859-1?Q?Linux_dans_un_t=E9l=E9phone_mobile?=")
|
||||||
|
* </pre><p>it will return:</p>
|
||||||
|
* <pre> <:us-ascii> "Linux dans un "
|
||||||
|
* <iso-8859-1> "t'el'ephone "
|
||||||
|
* <us-ascii> "mobile"
|
||||||
|
* ("Linux dans un =?iso-8859-1?Q?t=E9l=E9phone_?= mobile")
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param in input string
|
||||||
|
* @param ch input charset
|
||||||
|
* @param out output text
|
||||||
|
*/
|
||||||
|
|
||||||
|
void makeWordsFromText(const string& in, const charset& ch, text& out)
|
||||||
|
{
|
||||||
|
const string::const_iterator end = in.end();
|
||||||
|
string::const_iterator p = in.begin();
|
||||||
|
string::const_iterator start = in.begin();
|
||||||
|
|
||||||
|
bool is8bit = false; // is the current word 8-bit?
|
||||||
|
bool prevIs8bit = false; // is previous word 8-bit?
|
||||||
|
unsigned int count = 0; // total number of words
|
||||||
|
|
||||||
|
out.clear();
|
||||||
|
|
||||||
|
for ( ; ; )
|
||||||
|
{
|
||||||
|
if (p == end || isspace(*p))
|
||||||
|
{
|
||||||
|
if (p != end)
|
||||||
|
++p;
|
||||||
|
|
||||||
|
if (is8bit)
|
||||||
|
{
|
||||||
|
if (prevIs8bit)
|
||||||
|
{
|
||||||
|
// No need to create a new encoded word, just append
|
||||||
|
// the current word to the previous one.
|
||||||
|
out.back().buffer() += string(start, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.append(word(string(start, p), ch));
|
||||||
|
prevIs8bit = true;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (count && !prevIs8bit)
|
||||||
|
{
|
||||||
|
out.back().buffer() += string(start, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.append(word(string(start, p), charset(charsets::US_ASCII)));
|
||||||
|
prevIs8bit = false;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
is8bit = false;
|
||||||
|
start = p;
|
||||||
|
}
|
||||||
|
else if (!isascii(*p))
|
||||||
|
{
|
||||||
|
is8bit = true;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// V-Mime Initializer
|
||||||
|
// ====================
|
||||||
|
//
|
||||||
|
// Force instanciation of singletons. This is to prevent problems that might
|
||||||
|
// happen in multithreaded applications...
|
||||||
|
//
|
||||||
|
// WARNING: we put the initializer at the end of this compilation unit. This
|
||||||
|
// ensures this object is initialized _after_ all other global variables in
|
||||||
|
// the same compilation unit (in particular "lineLengthLimits::infinite",
|
||||||
|
// which is used by the generate() function (called from "textPartFactory"
|
||||||
|
// constructor, for example).
|
||||||
|
//
|
||||||
|
|
||||||
|
class initializer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
initializer()
|
||||||
|
{
|
||||||
|
options::getInstance();
|
||||||
|
|
||||||
|
encoderFactory::getInstance();
|
||||||
|
headerFieldFactory::getInstance();
|
||||||
|
parameterFactory::getInstance();
|
||||||
|
textPartFactory::getInstance();
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||||
|
messaging::serviceFactory::getInstance();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
initializer theInitializer;
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
216
src/base.hpp
Normal file
216
src/base.hpp
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_BASE_HPP_INCLUDED
|
||||||
|
#define VMIME_BASE_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <sstream>
|
||||||
|
#include <locale>
|
||||||
|
|
||||||
|
#include "config.hpp"
|
||||||
|
#include "types.hpp"
|
||||||
|
#include "constants.hpp"
|
||||||
|
#include "utility/stream.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
class text;
|
||||||
|
class charset;
|
||||||
|
|
||||||
|
|
||||||
|
// "Null" strings
|
||||||
|
extern const string NULL_STRING;
|
||||||
|
#if VMIME_WIDE_CHAR_SUPPORT
|
||||||
|
extern const wstring NULL_WSTRING;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern const text NULL_TEXT;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Library name and version
|
||||||
|
//
|
||||||
|
|
||||||
|
const string libname();
|
||||||
|
const string libversion();
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helpful functions used for array -> iterator conversion
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
inline T const* begin(T const (&array)[N])
|
||||||
|
{
|
||||||
|
return (array);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
inline T const* end(T const (&array)[N])
|
||||||
|
{
|
||||||
|
return (array + N);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
inline size_t count(T const (&array)[N])
|
||||||
|
{
|
||||||
|
return (N);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Some helpful functions
|
||||||
|
//
|
||||||
|
|
||||||
|
bool isStringEqualNoCase(const string& s1, const char* s2, const string::size_type n);
|
||||||
|
bool isStringEqualNoCase(const string& s1, const string& s2);
|
||||||
|
bool isStringEqualNoCase(const string::const_iterator begin, const string::const_iterator end, const char* s, const string::size_type n);
|
||||||
|
|
||||||
|
|
||||||
|
const string toLower(const string& str);
|
||||||
|
const string trim(const string& str);
|
||||||
|
|
||||||
|
template <class TYPE>
|
||||||
|
const string toString(const TYPE& value)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << value;
|
||||||
|
|
||||||
|
return (oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TYPE>
|
||||||
|
const TYPE fromString(const string& value)
|
||||||
|
{
|
||||||
|
TYPE ret;
|
||||||
|
|
||||||
|
std::istringstream iss(value);
|
||||||
|
iss >> ret;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Free the pointer elements in a STL container and empty the container
|
||||||
|
|
||||||
|
template <class CONTAINER>
|
||||||
|
void free_container(CONTAINER& c)
|
||||||
|
{
|
||||||
|
for (typename CONTAINER::iterator it = c.begin() ; it != c.end() ; ++it)
|
||||||
|
delete (*it);
|
||||||
|
|
||||||
|
c.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Field contents encoding (RFC-2047 and folding)
|
||||||
|
string::size_type countASCIIchars(const string::const_iterator begin, const string::const_iterator end);
|
||||||
|
|
||||||
|
void encodeAndFoldText(utility::outputStream& os, const text& in, const string::size_type maxLineLength, const string::size_type firstLineOffset, string::size_type* lastLineLength, const int flags);
|
||||||
|
void decodeAndUnfoldText(const string& in, text& out);
|
||||||
|
void decodeAndUnfoldText(const string::const_iterator& inStart, const string::const_iterator& inEnd, text& out);
|
||||||
|
|
||||||
|
void makeWordsFromText(const string& in, const charset& ch, text& out);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Some constants
|
||||||
|
//
|
||||||
|
|
||||||
|
// Flags used by "encodeAndFoldText" function
|
||||||
|
namespace encodeAndFoldFlags
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
// If both "forceNoEncoding" and "forceEncoding" are specified,
|
||||||
|
// "forceNoEncoding" is used by default.
|
||||||
|
forceNoEncoding = (1 << 0),
|
||||||
|
forceEncoding = (1 << 1),
|
||||||
|
|
||||||
|
noNewLineSequence = (1 << 2),
|
||||||
|
|
||||||
|
none = 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
RFC#2822
|
||||||
|
2.1.1. Line Length Limits
|
||||||
|
|
||||||
|
There are two limits that this standard places on the number of
|
||||||
|
characters in a line. Each line of characters MUST be no more than
|
||||||
|
998 characters, and SHOULD be no more than 78 characters, excluding
|
||||||
|
the CRLF.
|
||||||
|
|
||||||
|
The 998 character limit is due to limitations in many implementations
|
||||||
|
which send, receive, or store Internet Message Format messages that
|
||||||
|
simply cannot handle more than 998 characters on a line. Receiving
|
||||||
|
implementations would do well to handle an arbitrarily large number
|
||||||
|
of characters in a line for robustness sake. However, there are so
|
||||||
|
many implementations which (in compliance with the transport
|
||||||
|
requirements of [RFC2821]) do not accept messages containing more
|
||||||
|
than 1000 character including the CR and LF per line, it is important
|
||||||
|
for implementations not to create such messages.
|
||||||
|
|
||||||
|
The more conservative 78 character recommendation is to accommodate
|
||||||
|
the many implementations of user interfaces that display these
|
||||||
|
messages which may truncate, or disastrously wrap, the display of
|
||||||
|
more than 78 characters per line, in spite of the fact that such
|
||||||
|
implementations are non-conformant to the intent of this specification
|
||||||
|
(and that of [RFC2821] if they actually cause information to be lost).
|
||||||
|
Again, even though this limitation is put on messages, it is encumbant
|
||||||
|
upon implementations which display messages to handle an arbitrarily
|
||||||
|
large number of characters in a line (certainly at least up to the 998
|
||||||
|
character limit) for the sake of robustness.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace lineLengthLimits
|
||||||
|
{
|
||||||
|
extern const string::size_type infinite;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
max = 998,
|
||||||
|
convenient = 78
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// New line sequence to be used when folding header fields.
|
||||||
|
extern const string NEW_LINE_SEQUENCE;
|
||||||
|
extern const string::size_type NEW_LINE_SEQUENCE_LENGTH;
|
||||||
|
|
||||||
|
|
||||||
|
// CR-LF sequence
|
||||||
|
extern const string CRLF;
|
||||||
|
|
||||||
|
|
||||||
|
// Mime version
|
||||||
|
extern const string MIME_VERSION;
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_BASE_HPP_INCLUDED
|
543
src/body.cpp
Normal file
543
src/body.cpp
Normal file
@ -0,0 +1,543 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "bodyPart.hpp"
|
||||||
|
#include "body.hpp"
|
||||||
|
|
||||||
|
#include "options.hpp"
|
||||||
|
|
||||||
|
#include "contentTypeField.hpp"
|
||||||
|
#include "contentEncodingField.hpp"
|
||||||
|
|
||||||
|
#include "utility/random.hpp"
|
||||||
|
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
body::body(bodyPart& part)
|
||||||
|
: parts(*this), m_part(part), m_header(part.header())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void body::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
parts.clear();
|
||||||
|
|
||||||
|
// Check whether the body is a MIME-multipart
|
||||||
|
bool isMultipart = false;
|
||||||
|
string boundary;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const contentTypeField& ctf = dynamic_cast <contentTypeField&>
|
||||||
|
(m_header.fields.find(headerField::ContentType));
|
||||||
|
|
||||||
|
if (ctf.value().type() == mediaTypes::MULTIPART)
|
||||||
|
{
|
||||||
|
isMultipart = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boundary = ctf.boundary();
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_parameter&)
|
||||||
|
{
|
||||||
|
// No "boundary" parameter specified: we can try to
|
||||||
|
// guess it by scanning the body contents...
|
||||||
|
string::size_type pos = buffer.find("\n--", position);
|
||||||
|
|
||||||
|
if ((pos != string::npos) && (pos < end))
|
||||||
|
{
|
||||||
|
pos += 3;
|
||||||
|
|
||||||
|
const string::size_type start = pos;
|
||||||
|
|
||||||
|
char_t c = buffer[pos];
|
||||||
|
string::size_type length = 0;
|
||||||
|
|
||||||
|
// We have to stop after a reasonnably long boundary length (100)
|
||||||
|
// not to take the whole body contents for a boundary...
|
||||||
|
while (pos < end && length < 100 && !(c == '\r' || c == '\n'))
|
||||||
|
{
|
||||||
|
++length;
|
||||||
|
c = buffer[pos++];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos < end && length < 100)
|
||||||
|
{
|
||||||
|
// RFC #1521, Page 31:
|
||||||
|
// "...the boundary parameter, which consists of 1 to 70
|
||||||
|
// characters from a set of characters known to be very
|
||||||
|
// robust through email gateways, and NOT ending with
|
||||||
|
// white space..."
|
||||||
|
while (pos != start && isspace(buffer[pos - 1]))
|
||||||
|
--pos;
|
||||||
|
|
||||||
|
boundary = string(buffer.begin() + start,
|
||||||
|
buffer.begin() + pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_field&)
|
||||||
|
{
|
||||||
|
// No "Content-Type" field...
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a multi-part body
|
||||||
|
if (isMultipart && !boundary.empty())
|
||||||
|
{
|
||||||
|
const string boundarySep("--" + boundary);
|
||||||
|
|
||||||
|
string::size_type partStart = position;
|
||||||
|
string::size_type pos = buffer.find(boundarySep, position);
|
||||||
|
|
||||||
|
bool lastPart = false;
|
||||||
|
|
||||||
|
if (pos != string::npos && pos < end)
|
||||||
|
{
|
||||||
|
m_prologText = string(buffer.begin() + position, buffer.begin() + pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0 ; !lastPart && (pos != string::npos) && (pos < end) ; ++index)
|
||||||
|
{
|
||||||
|
string::size_type partEnd = pos;
|
||||||
|
|
||||||
|
// Get rid of the [CR]LF just before the boundary string
|
||||||
|
if (pos - 1 >= position && buffer[pos - 1] == '\n') --partEnd;
|
||||||
|
if (pos - 2 >= position && buffer[pos - 2] == '\r') --partEnd;
|
||||||
|
|
||||||
|
// Check whether it is the last part (boundary terminated by "--")
|
||||||
|
pos += boundarySep.length();
|
||||||
|
|
||||||
|
if (pos + 1 < end && buffer[pos] == '-' && buffer[pos + 1] == '-')
|
||||||
|
{
|
||||||
|
lastPart = true;
|
||||||
|
pos += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RFC #1521, Page 31:
|
||||||
|
// "...(If a boundary appears to end with white space, the
|
||||||
|
// white space must be presumed to have been added by a
|
||||||
|
// gateway, and must be deleted.)..."
|
||||||
|
while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t'))
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
// End of boundary line
|
||||||
|
if (pos + 1 < end && buffer[pos] == '\r' && buffer[pos + 1] =='\n')
|
||||||
|
{
|
||||||
|
pos += 2;
|
||||||
|
}
|
||||||
|
else if (pos < end && buffer[pos] == '\n')
|
||||||
|
{
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
bodyPart* part = new bodyPart;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
part->parse(buffer, partStart, partEnd, NULL);
|
||||||
|
}
|
||||||
|
catch (std::exception&)
|
||||||
|
{
|
||||||
|
delete (part);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
parts.m_parts.push_back(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
partStart = pos;
|
||||||
|
pos = buffer.find(boundarySep, partStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (partStart < end)
|
||||||
|
m_epilogText = string(buffer.begin() + partStart, buffer.begin() + end);
|
||||||
|
}
|
||||||
|
// Treat the contents as 'simple' data
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Extract the (encoded) contents
|
||||||
|
m_contents.set(buffer, position, end, encoding());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void body::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
||||||
|
const string::size_type /* curLinePos */, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
// MIME-Multipart
|
||||||
|
if (parts.size() != 0)
|
||||||
|
{
|
||||||
|
string boundary;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
contentTypeField& ctf = dynamic_cast<contentTypeField&>
|
||||||
|
(m_header.fields.find(headerField::ContentType));
|
||||||
|
|
||||||
|
boundary = ctf.boundary();
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_field&)
|
||||||
|
{
|
||||||
|
// Warning: no content-type and no boundary string specified!
|
||||||
|
boundary = generateRandomBoundaryString();
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_parameter&)
|
||||||
|
{
|
||||||
|
// Warning: no boundary string specified!
|
||||||
|
boundary = generateRandomBoundaryString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const string& prologText =
|
||||||
|
m_prologText.empty()
|
||||||
|
? (isRootPart()
|
||||||
|
? options::getInstance()->multipart.prologText()
|
||||||
|
: NULL_STRING
|
||||||
|
)
|
||||||
|
: m_prologText;
|
||||||
|
|
||||||
|
const string& epilogText =
|
||||||
|
m_epilogText.empty()
|
||||||
|
? (isRootPart()
|
||||||
|
? options::getInstance()->multipart.epilogText()
|
||||||
|
: NULL_STRING
|
||||||
|
)
|
||||||
|
: m_epilogText;
|
||||||
|
|
||||||
|
if (!prologText.empty())
|
||||||
|
{
|
||||||
|
encodeAndFoldText(os, text(word(prologText, charset())), maxLineLength, 0,
|
||||||
|
NULL, encodeAndFoldFlags::forceNoEncoding | encodeAndFoldFlags::noNewLineSequence);
|
||||||
|
|
||||||
|
os << CRLF;
|
||||||
|
}
|
||||||
|
|
||||||
|
os << "--" << boundary;
|
||||||
|
|
||||||
|
for (std::vector <bodyPart*>::const_iterator
|
||||||
|
p = parts.m_parts.begin() ; p != parts.m_parts.end() ; ++p)
|
||||||
|
{
|
||||||
|
os << CRLF;
|
||||||
|
|
||||||
|
(*p)->generate(os, maxLineLength, 0);
|
||||||
|
|
||||||
|
os << CRLF << "--" << boundary;
|
||||||
|
}
|
||||||
|
|
||||||
|
os << "--" << CRLF;
|
||||||
|
|
||||||
|
if (!epilogText.empty())
|
||||||
|
{
|
||||||
|
encodeAndFoldText(os, text(word(epilogText, charset())), maxLineLength, 0,
|
||||||
|
NULL, encodeAndFoldFlags::forceNoEncoding | encodeAndFoldFlags::noNewLineSequence);
|
||||||
|
|
||||||
|
os << CRLF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
*newLinePos = 0;
|
||||||
|
}
|
||||||
|
// Simple body
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Generate the contents
|
||||||
|
m_contents.generate(os, encoding(), maxLineLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
RFC #1521, Page 32:
|
||||||
|
7.2.1. Multipart: The common syntax
|
||||||
|
|
||||||
|
"...Encapsulation boundaries must not appear within the
|
||||||
|
encapsulations, and must be no longer than 70 characters..."
|
||||||
|
|
||||||
|
|
||||||
|
boundary := 0*69<bchars> bcharsnospace
|
||||||
|
|
||||||
|
bchars := bcharsnospace / " "
|
||||||
|
|
||||||
|
bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / "+" /"_"
|
||||||
|
/ "," / "-" / "." / "/" / ":" / "=" / "?"
|
||||||
|
*/
|
||||||
|
|
||||||
|
const string body::generateRandomBoundaryString()
|
||||||
|
{
|
||||||
|
// 64 characters that can be _safely_ used in a boundary string
|
||||||
|
static const char bchars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-+";
|
||||||
|
|
||||||
|
/*
|
||||||
|
RFC #1521, Page 19:
|
||||||
|
|
||||||
|
Since the hyphen character ("-") is represented as itself in the
|
||||||
|
Quoted-Printable encoding, care must be taken, when encapsulating a
|
||||||
|
quoted-printable encoded body in a multipart entity, to ensure that
|
||||||
|
the encapsulation boundary does not appear anywhere in the encoded
|
||||||
|
body. (A good strategy is to choose a boundary that includes a
|
||||||
|
character sequence such as "=_" which can never appear in a quoted-
|
||||||
|
printable body. See the definition of multipart messages later in
|
||||||
|
this document.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
string::value_type boundary[2 + 48 + 1] = { 0 };
|
||||||
|
|
||||||
|
boundary[0] = '=';
|
||||||
|
boundary[1] = '_';
|
||||||
|
|
||||||
|
// Generate a string of random characters
|
||||||
|
unsigned int r = utility::random::time();
|
||||||
|
unsigned int m = sizeof(unsigned int);
|
||||||
|
|
||||||
|
for (size_t i = 2 ; i < (sizeof(boundary) / sizeof(boundary[0]) - 1) ; ++i)
|
||||||
|
{
|
||||||
|
boundary[i] = bchars[r & 63];
|
||||||
|
r >>= 6;
|
||||||
|
|
||||||
|
if (--m == 0)
|
||||||
|
{
|
||||||
|
r = utility::random::next();
|
||||||
|
m = sizeof(unsigned int);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (string(boundary));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool body::isValidBoundary(const string& boundary)
|
||||||
|
{
|
||||||
|
static const string validChars("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'()+_,-./:=?");
|
||||||
|
|
||||||
|
const string::const_iterator end = boundary.end();
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
if (boundary.length() > 0 && boundary.length() < 70)
|
||||||
|
{
|
||||||
|
const string::value_type last = *(end - 1);
|
||||||
|
|
||||||
|
if (!(last == ' ' || last == '\t' || last == '\n'))
|
||||||
|
{
|
||||||
|
valid = true;
|
||||||
|
|
||||||
|
for (string::const_iterator i = boundary.begin() ; valid && i != end ; ++i)
|
||||||
|
valid = (validChars.find_first_of(*i) != string::npos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (valid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Quick-access functions
|
||||||
|
//
|
||||||
|
|
||||||
|
const mediaType body::contentType() const
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const contentTypeField& ctf = dynamic_cast<contentTypeField&>(m_header.fields.find(headerField::ContentType));
|
||||||
|
return (ctf.value());
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_field&)
|
||||||
|
{
|
||||||
|
// Defaults to "text/plain" (RFC-1521)
|
||||||
|
return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const class charset body::charset() const
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const contentTypeField& ctf = dynamic_cast<contentTypeField&>(m_header.fields.find(headerField::ContentType));
|
||||||
|
const class charset& cs = ctf.charset();
|
||||||
|
|
||||||
|
return (cs);
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_parameter&)
|
||||||
|
{
|
||||||
|
// Defaults to "us-ascii" (RFC-1521)
|
||||||
|
return (vmime::charset(charsets::US_ASCII));
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_field&)
|
||||||
|
{
|
||||||
|
// Defaults to "us-ascii" (RFC-1521)
|
||||||
|
return (vmime::charset(charsets::US_ASCII));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const class encoding body::encoding() const
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const contentEncodingField& cef = m_header.fields.ContentTransferEncoding();
|
||||||
|
return (cef.value());
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_field&)
|
||||||
|
{
|
||||||
|
// Defaults to "7bit" (RFC-1521)
|
||||||
|
return (vmime::encoding(encodingTypes::SEVEN_BIT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool body::isRootPart() const
|
||||||
|
{
|
||||||
|
return (m_part.parent() == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
body& body::operator=(const body& b)
|
||||||
|
{
|
||||||
|
m_prologText = b.m_prologText;
|
||||||
|
m_epilogText = b.m_epilogText;
|
||||||
|
|
||||||
|
m_contents = b.m_contents;
|
||||||
|
|
||||||
|
parts = b.parts;
|
||||||
|
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////
|
||||||
|
// Parts container //
|
||||||
|
/////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
body::partsContainer::partsContainer(class body& body)
|
||||||
|
: m_body(body)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Part insertion
|
||||||
|
void body::partsContainer::append(bodyPart* part)
|
||||||
|
{
|
||||||
|
part->m_parent = &(m_body.m_part);
|
||||||
|
|
||||||
|
m_parts.push_back(part);
|
||||||
|
|
||||||
|
// Check whether we have a boundary string
|
||||||
|
try
|
||||||
|
{
|
||||||
|
contentTypeField& ctf = dynamic_cast<contentTypeField&>
|
||||||
|
(m_body.m_header.fields.find(headerField::ContentType));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const string boundary = ctf.boundary();
|
||||||
|
|
||||||
|
if (boundary.empty() || !isValidBoundary(boundary))
|
||||||
|
throw exceptions::no_such_parameter("boundary"); // to generate a new one
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_parameter&)
|
||||||
|
{
|
||||||
|
// No "boundary" parameter: generate a random one.
|
||||||
|
ctf.boundary() = generateRandomBoundaryString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctf.value().type() != mediaTypes::MULTIPART)
|
||||||
|
{
|
||||||
|
// Warning: multi-part body but the Content-Type is
|
||||||
|
// not specified as "multipart/..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_field&)
|
||||||
|
{
|
||||||
|
// No "Content-Type" field: create a new one and generate
|
||||||
|
// a random boundary string.
|
||||||
|
contentTypeField& ctf = dynamic_cast<contentTypeField&>
|
||||||
|
(m_body.m_header.fields.get(headerField::ContentType));
|
||||||
|
|
||||||
|
ctf.value() = mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED);
|
||||||
|
ctf.boundary() = generateRandomBoundaryString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void body::partsContainer::insert(const iterator it, bodyPart* part)
|
||||||
|
{
|
||||||
|
part->m_parent = &(m_body.m_part);
|
||||||
|
|
||||||
|
m_parts.insert(it.m_iterator, part);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Part removing
|
||||||
|
void body::partsContainer::remove(const iterator it)
|
||||||
|
{
|
||||||
|
delete (*it.m_iterator);
|
||||||
|
m_parts.erase(it.m_iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void body::partsContainer::clear()
|
||||||
|
{
|
||||||
|
free_container(m_parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
body::partsContainer::~partsContainer()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
body::partsContainer& body::partsContainer::operator=(const partsContainer& c)
|
||||||
|
{
|
||||||
|
std::vector <bodyPart*> parts;
|
||||||
|
|
||||||
|
for (std::vector <bodyPart*>::const_iterator it = c.m_parts.begin() ; it != c.m_parts.end() ; ++it)
|
||||||
|
{
|
||||||
|
bodyPart* p = (*it)->clone();
|
||||||
|
p->m_parent = &(m_body.m_part);
|
||||||
|
|
||||||
|
parts.push_back(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector <bodyPart*>::iterator it = m_parts.begin() ; it != m_parts.end() ; ++it)
|
||||||
|
delete (*it);
|
||||||
|
|
||||||
|
m_parts.resize(parts.size());
|
||||||
|
std::copy(parts.begin(), parts.end(), m_parts.begin());
|
||||||
|
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
234
src/body.hpp
Normal file
234
src/body.hpp
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_BODY_HPP_INCLUDED
|
||||||
|
#define VMIME_BODY_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
#include "header.hpp"
|
||||||
|
|
||||||
|
#include "mediaType.hpp"
|
||||||
|
#include "charset.hpp"
|
||||||
|
#include "encoding.hpp"
|
||||||
|
|
||||||
|
#include "contentHandler.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class bodyPart;
|
||||||
|
|
||||||
|
|
||||||
|
/** Body section of a MIME part.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class body : public component
|
||||||
|
{
|
||||||
|
friend class bodyPart;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
body(bodyPart& part);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// A sub-class for part manipulation
|
||||||
|
class partsContainer
|
||||||
|
{
|
||||||
|
friend class body;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
partsContainer(class body& body);
|
||||||
|
~partsContainer();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Part iterator
|
||||||
|
class const_iterator;
|
||||||
|
|
||||||
|
class iterator
|
||||||
|
{
|
||||||
|
friend class body::partsContainer::const_iterator;
|
||||||
|
friend class body::partsContainer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::vector <bodyPart*>::iterator::difference_type difference_type;
|
||||||
|
|
||||||
|
iterator(std::vector <bodyPart*>::iterator it) : m_iterator(it) { }
|
||||||
|
iterator(const iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
|
||||||
|
iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
|
||||||
|
bodyPart& operator*() const { return (**m_iterator); }
|
||||||
|
bodyPart* operator->() const { return (*m_iterator); }
|
||||||
|
|
||||||
|
iterator& operator++() { ++m_iterator; return (*this); }
|
||||||
|
iterator operator++(int) { iterator i(*this); ++m_iterator; return (i); }
|
||||||
|
|
||||||
|
iterator& operator--() { --m_iterator; return (*this); }
|
||||||
|
iterator operator--(int) { iterator i(*this); --m_iterator; return (i); }
|
||||||
|
|
||||||
|
iterator& operator+=(difference_type n) { m_iterator += n; return (*this); }
|
||||||
|
iterator& operator-=(difference_type n) { m_iterator -= n; return (*this); }
|
||||||
|
|
||||||
|
iterator operator-(difference_type x) const { return iterator(m_iterator - x); }
|
||||||
|
|
||||||
|
bodyPart& operator[](difference_type n) const { return *(m_iterator[n]); }
|
||||||
|
|
||||||
|
const bool operator==(const iterator& it) const { return (it.m_iterator == m_iterator); }
|
||||||
|
const bool operator!=(const iterator& it) const { return (!(*this == it)); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::vector <bodyPart*>::iterator m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
class const_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::vector <bodyPart*>::const_iterator::difference_type difference_type;
|
||||||
|
|
||||||
|
const_iterator(std::vector <bodyPart*>::const_iterator it) : m_iterator(it) { }
|
||||||
|
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
|
||||||
|
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
|
||||||
|
const bodyPart& operator*() const { return (**m_iterator); }
|
||||||
|
const bodyPart* operator->() const { return (*m_iterator); }
|
||||||
|
|
||||||
|
const_iterator& operator++() { ++m_iterator; return (*this); }
|
||||||
|
const_iterator operator++(int) { const_iterator i(*this); ++m_iterator; return (i); }
|
||||||
|
|
||||||
|
const_iterator& operator--() { --m_iterator; return (*this); }
|
||||||
|
const_iterator operator--(int) { const_iterator i(*this); --m_iterator; return (i); }
|
||||||
|
|
||||||
|
const_iterator& operator+=(difference_type n) { m_iterator += n; return (*this); }
|
||||||
|
const_iterator& operator-=(difference_type n) { m_iterator -= n; return (*this); }
|
||||||
|
|
||||||
|
const_iterator operator-(difference_type x) const { return const_iterator(m_iterator - x); }
|
||||||
|
|
||||||
|
const bodyPart& operator[](difference_type n) const { return *(m_iterator[n]); }
|
||||||
|
|
||||||
|
const bool operator==(const const_iterator& it) const { return (it.m_iterator == m_iterator); }
|
||||||
|
const bool operator!=(const const_iterator& it) const { return (!(*this == it)); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::vector <bodyPart*>::const_iterator m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
iterator begin() { return (m_parts.begin()); }
|
||||||
|
iterator end() { return (m_parts.end()); }
|
||||||
|
|
||||||
|
const_iterator begin() const { return (const_iterator(m_parts.begin())); }
|
||||||
|
const_iterator end() const { return (const_iterator(m_parts.end())); }
|
||||||
|
|
||||||
|
const bodyPart& operator[](const std::vector <bodyPart*>::size_type x) const { return (*m_parts[x]); }
|
||||||
|
bodyPart& operator[](const std::vector <bodyPart*>::size_type x) { return (*m_parts[x]); }
|
||||||
|
|
||||||
|
// Part insertion
|
||||||
|
void append(bodyPart* part);
|
||||||
|
void insert(const iterator it, bodyPart* part);
|
||||||
|
|
||||||
|
// Part removing
|
||||||
|
void remove(const iterator it);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// Part count
|
||||||
|
const size_t count() const { return (m_parts.size()); }
|
||||||
|
const size_t size() const { return (m_parts.size()); }
|
||||||
|
|
||||||
|
bodyPart& front() { return (*m_parts.front()); }
|
||||||
|
const bodyPart& front() const { return (*m_parts.front()); }
|
||||||
|
bodyPart& back() { return (*m_parts.back()); }
|
||||||
|
const bodyPart& back() const { return (*m_parts.back()); }
|
||||||
|
|
||||||
|
partsContainer& operator=(const partsContainer& c);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
body& m_body;
|
||||||
|
|
||||||
|
std::vector <bodyPart*> m_parts;
|
||||||
|
|
||||||
|
} parts;
|
||||||
|
|
||||||
|
typedef partsContainer::iterator iterator;
|
||||||
|
typedef partsContainer::const_iterator const_iterator;
|
||||||
|
|
||||||
|
|
||||||
|
const string& prologText() const { return (m_prologText); }
|
||||||
|
string& prologText() { return (m_prologText); }
|
||||||
|
|
||||||
|
const string& epilogText() const { return (m_epilogText); }
|
||||||
|
string& epilogText() { return (m_epilogText); }
|
||||||
|
|
||||||
|
const contentHandler& contents() const { return (m_contents); }
|
||||||
|
contentHandler& contents() { return (m_contents); }
|
||||||
|
|
||||||
|
// Quick-access functions
|
||||||
|
const mediaType contentType() const;
|
||||||
|
const class charset charset() const;
|
||||||
|
const class encoding encoding() const;
|
||||||
|
|
||||||
|
// Boundary string functions
|
||||||
|
static const string generateRandomBoundaryString();
|
||||||
|
static const bool isValidBoundary(const string& boundary);
|
||||||
|
|
||||||
|
body& operator=(const body& b);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
string m_prologText;
|
||||||
|
string m_epilogText;
|
||||||
|
|
||||||
|
contentHandler m_contents;
|
||||||
|
|
||||||
|
bodyPart& m_part;
|
||||||
|
header& m_header;
|
||||||
|
|
||||||
|
const bool isRootPart() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using component::parse;
|
||||||
|
using component::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_BODY_HPP_INCLUDED
|
75
src/bodyPart.cpp
Normal file
75
src/bodyPart.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "bodyPart.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
bodyPart::bodyPart()
|
||||||
|
: m_body(*this), m_parent(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bodyPart::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
// Parse the headers
|
||||||
|
string::size_type pos = position;
|
||||||
|
m_header.parse(buffer, pos, end, &pos);
|
||||||
|
|
||||||
|
// Parse the body contents
|
||||||
|
m_body.parse(buffer, pos, end, NULL);
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bodyPart::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
||||||
|
const string::size_type /* curLinePos */, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
m_header.generate(os, maxLineLength);
|
||||||
|
|
||||||
|
os << CRLF;
|
||||||
|
|
||||||
|
m_body.generate(os, maxLineLength);
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
*newLinePos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bodyPart* bodyPart::clone() const
|
||||||
|
{
|
||||||
|
bodyPart* p = new bodyPart;
|
||||||
|
|
||||||
|
p->m_parent = NULL;
|
||||||
|
p->m_header = m_header;
|
||||||
|
p->m_body = m_body;
|
||||||
|
|
||||||
|
return (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
80
src/bodyPart.hpp
Normal file
80
src/bodyPart.hpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_BODYPART_HPP_INCLUDED
|
||||||
|
#define VMIME_BODYPART_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
#include "header.hpp"
|
||||||
|
#include "body.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** A MIME part.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class bodyPart : public component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
bodyPart();
|
||||||
|
|
||||||
|
const class header& header() const { return (m_header); }
|
||||||
|
class header& header() { return (m_header); }
|
||||||
|
|
||||||
|
const class body& body() const { return (m_body); }
|
||||||
|
class body& body() { return (m_body); }
|
||||||
|
|
||||||
|
bodyPart* parent() const { return (m_parent); }
|
||||||
|
|
||||||
|
bodyPart* clone() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
class header m_header;
|
||||||
|
class body m_body;
|
||||||
|
|
||||||
|
bodyPart* m_parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using component::parse;
|
||||||
|
using component::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
|
||||||
|
|
||||||
|
// This is here because of a bug in g++ < 3.4
|
||||||
|
friend class body;
|
||||||
|
friend class body::partsContainer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_BODYPART_HPP_INCLUDED
|
305
src/charset.cpp
Normal file
305
src/charset.cpp
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "charset.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
#include "platformDependant.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <iconv.h>
|
||||||
|
|
||||||
|
// HACK: prototypes may differ depending on the compiler and/or system (the
|
||||||
|
// second parameter may or may not be 'const'). This redeclaration is a hack
|
||||||
|
// to have a common prototype "iconv_cast".
|
||||||
|
typedef size_t (*iconv_const_hack)(iconv_t cd, const char* * inbuf,
|
||||||
|
size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);
|
||||||
|
|
||||||
|
#define iconv_const ((iconv_const_hack) iconv)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
charset::charset()
|
||||||
|
: m_name(charsets::US_ASCII)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
charset::charset(const string& name)
|
||||||
|
: m_name(name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void charset::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
m_name = string(buffer.begin() + position, buffer.begin() + end);
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void charset::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
os << m_name;
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
*newLinePos = curLinePos + m_name.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Convert the contents of an input stream in a specified charset
|
||||||
|
* to another charset and write the result to an output stream.
|
||||||
|
*
|
||||||
|
* @param in input stream to read data from
|
||||||
|
* @param out output stream to write the converted data
|
||||||
|
* @param source input charset
|
||||||
|
* @param dest output charset
|
||||||
|
*/
|
||||||
|
|
||||||
|
void charset::convert(utility::inputStream& in, utility::outputStream& out,
|
||||||
|
const charset& source, const charset& dest)
|
||||||
|
{
|
||||||
|
// Get an iconv descriptor
|
||||||
|
const iconv_t cd = iconv_open(dest.name().c_str(), source.name().c_str());
|
||||||
|
|
||||||
|
if (cd != (iconv_t) -1)
|
||||||
|
{
|
||||||
|
char inBuffer[5];
|
||||||
|
char outBuffer[32768];
|
||||||
|
size_t inPos = 0;
|
||||||
|
|
||||||
|
bool prevIsInvalid = false;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Fullfill the buffer
|
||||||
|
size_t inLength = (size_t) in.read(inBuffer + inPos, sizeof(inBuffer) - inPos) + inPos;
|
||||||
|
size_t outLength = sizeof(outBuffer);
|
||||||
|
|
||||||
|
const char* inPtr = inBuffer;
|
||||||
|
char* outPtr = outBuffer;
|
||||||
|
|
||||||
|
// Convert input bytes
|
||||||
|
if (iconv_const(cd, &inPtr, &inLength, &outPtr, &outLength) == (size_t) -1)
|
||||||
|
{
|
||||||
|
// Illegal input sequence or input sequence has no equivalent
|
||||||
|
// sequence in the destination charset.
|
||||||
|
if (prevIsInvalid)
|
||||||
|
{
|
||||||
|
// Write successfully converted bytes
|
||||||
|
out.write(outBuffer, sizeof(outBuffer) - outLength);
|
||||||
|
|
||||||
|
// Output a special character to indicate we don't known how to
|
||||||
|
// convert the sequence at this position
|
||||||
|
out.write("?", 1);
|
||||||
|
|
||||||
|
// Skip a byte and leave unconverted bytes in the input buffer
|
||||||
|
std::copy((char*) inPtr + 1, inBuffer + sizeof(inBuffer), inBuffer);
|
||||||
|
inPos = inLength - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Write successfully converted bytes
|
||||||
|
out.write(outBuffer, sizeof(outBuffer) - outLength);
|
||||||
|
|
||||||
|
// Leave unconverted bytes in the input buffer
|
||||||
|
std::copy((char*) inPtr, inBuffer + sizeof(inBuffer), inBuffer);
|
||||||
|
inPos = inLength;
|
||||||
|
|
||||||
|
prevIsInvalid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Write successfully converted bytes
|
||||||
|
out.write(outBuffer, sizeof(outBuffer) - outLength);
|
||||||
|
|
||||||
|
inPos = 0;
|
||||||
|
prevIsInvalid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for end of data
|
||||||
|
if (in.eof() && inPos == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close iconv handle
|
||||||
|
iconv_close(cd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw exceptions::charset_conv_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Convert a string buffer in a specified charset to a string
|
||||||
|
* buffer in another charset.
|
||||||
|
*
|
||||||
|
* @param in input buffer
|
||||||
|
* @param out output buffer
|
||||||
|
* @param from input charset
|
||||||
|
* @param to output charset
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class STRINGF, class STRINGT>
|
||||||
|
void charset::iconvert(const STRINGF& in, STRINGT& out, const charset& from, const charset& to)
|
||||||
|
{
|
||||||
|
// Get an iconv descriptor
|
||||||
|
const iconv_t cd = iconv_open(to.name().c_str(), from.name().c_str());
|
||||||
|
|
||||||
|
typedef typename STRINGF::value_type ivt;
|
||||||
|
typedef typename STRINGT::value_type ovt;
|
||||||
|
|
||||||
|
if (cd != (iconv_t) -1)
|
||||||
|
{
|
||||||
|
out.clear();
|
||||||
|
|
||||||
|
char buffer[65536];
|
||||||
|
|
||||||
|
const char* inBuffer = (const char*) in.data();
|
||||||
|
size_t inBytesLeft = in.length();
|
||||||
|
|
||||||
|
for ( ; inBytesLeft > 0 ; )
|
||||||
|
{
|
||||||
|
size_t outBytesLeft = sizeof(buffer);
|
||||||
|
char* outBuffer = buffer;
|
||||||
|
|
||||||
|
if (iconv_const(cd, &inBuffer, &inBytesLeft,
|
||||||
|
&outBuffer, &outBytesLeft) == (size_t) -1)
|
||||||
|
{
|
||||||
|
out += STRINGT((ovt*) buffer, sizeof(buffer) - outBytesLeft);
|
||||||
|
|
||||||
|
// Ignore this "blocking" character and continue
|
||||||
|
out += '?';
|
||||||
|
++inBuffer;
|
||||||
|
--inBytesLeft;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out += STRINGT((ovt*) buffer, sizeof(buffer) - outBytesLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close iconv handle
|
||||||
|
iconv_close(cd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw exceptions::charset_conv_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_WIDE_CHAR_SUPPORT
|
||||||
|
|
||||||
|
/** Convert a string buffer in the specified charset to a wide-char
|
||||||
|
* string buffer.
|
||||||
|
*
|
||||||
|
* @param in input buffer
|
||||||
|
* @param out output buffer
|
||||||
|
* @param ch input charset
|
||||||
|
*/
|
||||||
|
|
||||||
|
void charset::decode(const string& in, wstring& out, const charset& ch)
|
||||||
|
{
|
||||||
|
iconvert(in, out, ch, charset("WCHAR_T"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Convert a wide-char string buffer to a string buffer in the
|
||||||
|
* specified charset.
|
||||||
|
*
|
||||||
|
* @param in input buffer
|
||||||
|
* @param out output buffer
|
||||||
|
* @param ch output charset
|
||||||
|
*/
|
||||||
|
|
||||||
|
void charset::encode(const wstring& in, string& out, const charset& ch)
|
||||||
|
{
|
||||||
|
iconvert(in, out, charset("WCHAR_T"), ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/** Convert a string buffer from one charset to another charset.
|
||||||
|
*
|
||||||
|
* @param in input buffer
|
||||||
|
* @param out output buffer
|
||||||
|
* @param source input charset
|
||||||
|
* @param dest output charset
|
||||||
|
*/
|
||||||
|
|
||||||
|
void charset::convert(const string& in, string& out, const charset& source, const charset& dest)
|
||||||
|
{
|
||||||
|
iconvert(in, out, source, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns the default charset used on the system.
|
||||||
|
*
|
||||||
|
* This function simply calls <code>platformDependantHandler::getLocaleCharset()</code>
|
||||||
|
* and is provided for convenience.
|
||||||
|
*
|
||||||
|
* @return system default charset
|
||||||
|
*/
|
||||||
|
|
||||||
|
const charset charset::getLocaleCharset()
|
||||||
|
{
|
||||||
|
return (platformDependant::getHandler()->getLocaleCharset());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
charset& charset::operator=(const charset& source)
|
||||||
|
{
|
||||||
|
m_name = source.m_name;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
charset& charset::operator=(const string& name)
|
||||||
|
{
|
||||||
|
parse(name);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool charset::operator==(const charset& value) const
|
||||||
|
{
|
||||||
|
return (isStringEqualNoCase(m_name, value.m_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool charset::operator!=(const charset& value) const
|
||||||
|
{
|
||||||
|
return !(*this == value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
86
src/charset.hpp
Normal file
86
src/charset.hpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_CHARSET_HPP_INCLUDED
|
||||||
|
#define VMIME_CHARSET_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** Charset description (basic type).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class charset : public component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
charset();
|
||||||
|
charset(const string& name);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const string name() const { return (m_name); }
|
||||||
|
|
||||||
|
charset& operator=(const charset& source);
|
||||||
|
charset& operator=(const string& name);
|
||||||
|
|
||||||
|
const bool operator==(const charset& value) const;
|
||||||
|
const bool operator!=(const charset& value) const;
|
||||||
|
|
||||||
|
static const charset getLocaleCharset();
|
||||||
|
|
||||||
|
#if VMIME_WIDE_CHAR_SUPPORT
|
||||||
|
static void decode(const string& in, wstring& out, const charset& ch);
|
||||||
|
static void encode(const wstring& in, string& out, const charset& ch);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// In-memory conversion
|
||||||
|
static void convert(const string& in, string& out, const charset& source, const charset& dest);
|
||||||
|
|
||||||
|
// Stream conversion
|
||||||
|
static void convert(utility::inputStream& in, utility::outputStream& out, const charset& source, const charset& dest);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
string m_name;
|
||||||
|
|
||||||
|
template <class STRINGF, class STRINGT>
|
||||||
|
static void iconvert(const STRINGF& in, STRINGT& out, const charset& from, const charset& to);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using component::parse;
|
||||||
|
using component::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_CHARSET_HPP_INCLUDED
|
50
src/charsetParameter.cpp
Normal file
50
src/charsetParameter.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "charsetParameter.hpp"
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
void charsetParameter::parseValue(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end)
|
||||||
|
{
|
||||||
|
m_value.parse(buffer, position, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string charsetParameter::generateValue() const
|
||||||
|
{
|
||||||
|
return (m_value.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void charsetParameter::copyFrom(const parameter& param)
|
||||||
|
{
|
||||||
|
const charsetParameter& source = dynamic_cast<const charsetParameter&>(param);
|
||||||
|
m_value = source.m_value;
|
||||||
|
|
||||||
|
defaultParameter::copyFrom(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
55
src/charsetParameter.hpp
Normal file
55
src/charsetParameter.hpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_CHARSETPARAMETER_HPP_INCLUDED
|
||||||
|
#define VMIME_CHARSETPARAMETER_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "defaultParameter.hpp"
|
||||||
|
#include "charset.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class charsetParameter : public defaultParameter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
charset m_value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void copyFrom(const parameter& param);
|
||||||
|
|
||||||
|
const charset& value() const { return (m_value); }
|
||||||
|
charset& value() { return (m_value); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void parseValue(const string& buffer, const string::size_type position, const string::size_type end);
|
||||||
|
const string generateValue() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_CHARSETPARAMETER_HPP_INCLUDED
|
47
src/component.cpp
Normal file
47
src/component.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
void component::parse(const string& buffer)
|
||||||
|
{
|
||||||
|
parse(buffer, 0, buffer.length(), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string component::generate(const string::size_type maxLineLength,
|
||||||
|
const string::size_type curLinePos) const
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
utility::outputStreamAdapter adapter(oss);
|
||||||
|
|
||||||
|
generate(adapter, maxLineLength, curLinePos, NULL);
|
||||||
|
|
||||||
|
return (oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
84
src/component.hpp
Normal file
84
src/component.hpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_COMPONENT_HPP_INCLUDED
|
||||||
|
#define VMIME_COMPONENT_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** This abstract class is the base for all the classes in the library.
|
||||||
|
* It defines the methods for parsing and generating all the components.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class component
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual ~component() {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** Parse RFC-822/MIME data for this component.
|
||||||
|
*
|
||||||
|
* @param buffer input buffer
|
||||||
|
*/
|
||||||
|
void parse(const string& buffer);
|
||||||
|
|
||||||
|
/** Parse RFC-822/MIME data for this component.
|
||||||
|
*
|
||||||
|
* @param buffer input buffer
|
||||||
|
* @param position current position in the input buffer
|
||||||
|
* @param end end position in the input buffer
|
||||||
|
* @param newPosition will receive the new position in the input buffer
|
||||||
|
*/
|
||||||
|
virtual void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL) = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Generate RFC-2822/MIME data for this component.
|
||||||
|
*
|
||||||
|
* \deprecated Use the new generate() method, which takes an outputStream parameter.
|
||||||
|
*
|
||||||
|
* @param maxLineLength maximum line length for output
|
||||||
|
* @param curLinePos length of the current line in the output buffer
|
||||||
|
* @return generated data
|
||||||
|
*/
|
||||||
|
virtual const string generate(const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0) const;
|
||||||
|
|
||||||
|
/** Generate RFC-2822/MIME data for this component.
|
||||||
|
*
|
||||||
|
* @param os output stream
|
||||||
|
* @param maxLineLength maximum line length for output
|
||||||
|
* @param curLinePos length of the current line in the output buffer
|
||||||
|
* @param newLinePos will receive the new line position (length of the last line written)
|
||||||
|
*/
|
||||||
|
virtual void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_COMPONENT_HPP_INCLUDED
|
151
src/constants.cpp
Normal file
151
src/constants.cpp
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "constants.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// Media Types
|
||||||
|
namespace mediaTypes
|
||||||
|
{
|
||||||
|
// Types
|
||||||
|
const string::value_type* const TEXT = "text";
|
||||||
|
const string::value_type* const MULTIPART = "multipart";
|
||||||
|
const string::value_type* const MESSAGE = "message";
|
||||||
|
const string::value_type* const APPLICATION = "application";
|
||||||
|
const string::value_type* const IMAGE = "image";
|
||||||
|
const string::value_type* const AUDIO = "audio";
|
||||||
|
const string::value_type* const VIDEO = "video";
|
||||||
|
|
||||||
|
// Sub-types
|
||||||
|
const string::value_type* const TEXT_PLAIN = "plain";
|
||||||
|
const string::value_type* const TEXT_HTML = "html";
|
||||||
|
const string::value_type* const TEXT_RICHTEXT = "richtext";
|
||||||
|
const string::value_type* const TEXT_ENRICHED = "enriched";
|
||||||
|
|
||||||
|
const string::value_type* const MULTIPART_MIXED = "mixed";
|
||||||
|
const string::value_type* const MULTIPART_RELATED = "related";
|
||||||
|
const string::value_type* const MULTIPART_ALTERNATIVE = "alternative";
|
||||||
|
const string::value_type* const MULTIPART_PARALLEL = "parallel";
|
||||||
|
const string::value_type* const MULTIPART_DIGEST = "digest";
|
||||||
|
|
||||||
|
const string::value_type* const MESSAGE_RFC822 = "rfc822";
|
||||||
|
const string::value_type* const MESSAGE_PARTIAL = "partial";
|
||||||
|
const string::value_type* const MESSAGE_EXTERNAL_BODY = "external-body";
|
||||||
|
|
||||||
|
const string::value_type* const APPLICATION_OCTET_STREAM = "octet-stream";
|
||||||
|
|
||||||
|
const string::value_type* const IMAGE_JPEG = "jpeg";
|
||||||
|
const string::value_type* const IMAGE_GIF = "gif";
|
||||||
|
|
||||||
|
const string::value_type* const AUDIO_BASIC = "basic";
|
||||||
|
|
||||||
|
const string::value_type* const VIDEO_MPEG = "mpeg";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Encoding types
|
||||||
|
namespace encodingTypes
|
||||||
|
{
|
||||||
|
const string::value_type* const SEVEN_BIT = "7bit";
|
||||||
|
const string::value_type* const EIGHT_BIT = "8bit";
|
||||||
|
const string::value_type* const BASE64 = "base64";
|
||||||
|
const string::value_type* const QUOTED_PRINTABLE = "quoted-printable";
|
||||||
|
const string::value_type* const BINARY = "binary";
|
||||||
|
const string::value_type* const UUENCODE = "uuencode";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Disposition types = "RFC-2183)
|
||||||
|
namespace dispositionTypes
|
||||||
|
{
|
||||||
|
const string::value_type* const INLINE = "inline";
|
||||||
|
const string::value_type* const ATTACHMENT = "attachment";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Charsets
|
||||||
|
namespace charsets
|
||||||
|
{
|
||||||
|
const string::value_type* const ISO8859_1 = "iso-8859-1";
|
||||||
|
const string::value_type* const ISO8859_2 = "iso-8859-2";
|
||||||
|
const string::value_type* const ISO8859_3 = "iso-8859-3";
|
||||||
|
const string::value_type* const ISO8859_4 = "iso-8859-4";
|
||||||
|
const string::value_type* const ISO8859_5 = "iso-8859-5";
|
||||||
|
const string::value_type* const ISO8859_6 = "iso-8859-6";
|
||||||
|
const string::value_type* const ISO8859_7 = "iso-8859-7";
|
||||||
|
const string::value_type* const ISO8859_8 = "iso-8859-8";
|
||||||
|
const string::value_type* const ISO8859_9 = "iso-8859-9";
|
||||||
|
const string::value_type* const ISO8859_10 = "iso-8859-10";
|
||||||
|
const string::value_type* const ISO8859_13 = "iso-8859-13";
|
||||||
|
const string::value_type* const ISO8859_14 = "iso-8859-14";
|
||||||
|
const string::value_type* const ISO8859_15 = "iso-8859-15";
|
||||||
|
const string::value_type* const ISO8859_16 = "iso-8859-16";
|
||||||
|
|
||||||
|
const string::value_type* const CP_437 = "cp-437";
|
||||||
|
const string::value_type* const CP_737 = "cp-737";
|
||||||
|
const string::value_type* const CP_775 = "cp-775";
|
||||||
|
const string::value_type* const CP_850 = "cp-850";
|
||||||
|
const string::value_type* const CP_852 = "cp-852";
|
||||||
|
const string::value_type* const CP_853 = "cp-853";
|
||||||
|
const string::value_type* const CP_855 = "cp-855";
|
||||||
|
const string::value_type* const CP_857 = "cp-857";
|
||||||
|
const string::value_type* const CP_858 = "cp-858";
|
||||||
|
const string::value_type* const CP_860 = "cp-860";
|
||||||
|
const string::value_type* const CP_861 = "cp-861";
|
||||||
|
const string::value_type* const CP_862 = "cp-862";
|
||||||
|
const string::value_type* const CP_863 = "cp-863";
|
||||||
|
const string::value_type* const CP_864 = "cp-864";
|
||||||
|
const string::value_type* const CP_865 = "cp-865";
|
||||||
|
const string::value_type* const CP_866 = "cp-866";
|
||||||
|
const string::value_type* const CP_869 = "cp-869";
|
||||||
|
const string::value_type* const CP_874 = "cp-874";
|
||||||
|
const string::value_type* const CP_1125 = "cp-1125";
|
||||||
|
const string::value_type* const CP_1250 = "cp-1250";
|
||||||
|
const string::value_type* const CP_1251 = "cp-1251";
|
||||||
|
const string::value_type* const CP_1252 = "cp-1252";
|
||||||
|
const string::value_type* const CP_1253 = "cp-1253";
|
||||||
|
const string::value_type* const CP_1254 = "cp-1254";
|
||||||
|
const string::value_type* const CP_1255 = "cp-1255";
|
||||||
|
const string::value_type* const CP_1256 = "cp-1256";
|
||||||
|
const string::value_type* const CP_1257 = "cp-1257";
|
||||||
|
|
||||||
|
const string::value_type* const US_ASCII = "us-ascii";
|
||||||
|
|
||||||
|
const string::value_type* const UTF_7 = "utf-7";
|
||||||
|
const string::value_type* const UTF_8 = "utf-8";
|
||||||
|
const string::value_type* const UTF_16 = "utf-16";
|
||||||
|
const string::value_type* const UTF_32 = "utf-32";
|
||||||
|
|
||||||
|
const string::value_type* const WINDOWS_1250 = "windows-1250";
|
||||||
|
const string::value_type* const WINDOWS_1251 = "windows-1251";
|
||||||
|
const string::value_type* const WINDOWS_1252 = "windows-1252";
|
||||||
|
const string::value_type* const WINDOWS_1253 = "windows-1253";
|
||||||
|
const string::value_type* const WINDOWS_1254 = "windows-1254";
|
||||||
|
const string::value_type* const WINDOWS_1255 = "windows-1255";
|
||||||
|
const string::value_type* const WINDOWS_1256 = "windows-1256";
|
||||||
|
const string::value_type* const WINDOWS_1257 = "windows-1257";
|
||||||
|
const string::value_type* const WINDOWS_1258 = "windows-1258";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
156
src/constants.hpp
Normal file
156
src/constants.hpp
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free SOFTWARE; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software FOUNDATION; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this PROGRAM; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_CONSTANTS_HPP_INCLUDED
|
||||||
|
#define VMIME_CONSTANTS_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "types.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
// Media types (predefined types)
|
||||||
|
namespace mediaTypes
|
||||||
|
{
|
||||||
|
// Types
|
||||||
|
extern const string::value_type* const TEXT;
|
||||||
|
extern const string::value_type* const MULTIPART;
|
||||||
|
extern const string::value_type* const MESSAGE;
|
||||||
|
extern const string::value_type* const APPLICATION;
|
||||||
|
extern const string::value_type* const IMAGE;
|
||||||
|
extern const string::value_type* const AUDIO;
|
||||||
|
extern const string::value_type* const VIDEO;
|
||||||
|
|
||||||
|
// Sub-types
|
||||||
|
extern const string::value_type* const TEXT_PLAIN;
|
||||||
|
extern const string::value_type* const TEXT_HTML;
|
||||||
|
extern const string::value_type* const TEXT_RICHTEXT;
|
||||||
|
extern const string::value_type* const TEXT_ENRICHED;
|
||||||
|
|
||||||
|
extern const string::value_type* const MULTIPART_MIXED;
|
||||||
|
extern const string::value_type* const MULTIPART_RELATED;
|
||||||
|
extern const string::value_type* const MULTIPART_ALTERNATIVE;
|
||||||
|
extern const string::value_type* const MULTIPART_PARALLEL;
|
||||||
|
extern const string::value_type* const MULTIPART_DIGEST;
|
||||||
|
|
||||||
|
extern const string::value_type* const MESSAGE_RFC822;
|
||||||
|
extern const string::value_type* const MESSAGE_PARTIAL;
|
||||||
|
extern const string::value_type* const MESSAGE_EXTERNAL_BODY;
|
||||||
|
|
||||||
|
extern const string::value_type* const APPLICATION_OCTET_STREAM;
|
||||||
|
|
||||||
|
extern const string::value_type* const IMAGE_JPEG;
|
||||||
|
extern const string::value_type* const IMAGE_GIF;
|
||||||
|
|
||||||
|
extern const string::value_type* const AUDIO_BASIC;
|
||||||
|
|
||||||
|
extern const string::value_type* const VIDEO_MPEG;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Encoding types
|
||||||
|
namespace encodingTypes
|
||||||
|
{
|
||||||
|
extern const string::value_type* const SEVEN_BIT;
|
||||||
|
extern const string::value_type* const EIGHT_BIT;
|
||||||
|
extern const string::value_type* const BASE64;
|
||||||
|
extern const string::value_type* const QUOTED_PRINTABLE;
|
||||||
|
extern const string::value_type* const BINARY;
|
||||||
|
extern const string::value_type* const UUENCODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Disposition types (RFC-2183)
|
||||||
|
namespace dispositionTypes
|
||||||
|
{
|
||||||
|
extern const string::value_type* const INLINE;
|
||||||
|
extern const string::value_type* const ATTACHMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Charsets
|
||||||
|
namespace charsets
|
||||||
|
{
|
||||||
|
extern const string::value_type* const ISO8859_1;
|
||||||
|
extern const string::value_type* const ISO8859_2;
|
||||||
|
extern const string::value_type* const ISO8859_3;
|
||||||
|
extern const string::value_type* const ISO8859_4;
|
||||||
|
extern const string::value_type* const ISO8859_5;
|
||||||
|
extern const string::value_type* const ISO8859_6;
|
||||||
|
extern const string::value_type* const ISO8859_7;
|
||||||
|
extern const string::value_type* const ISO8859_8;
|
||||||
|
extern const string::value_type* const ISO8859_9;
|
||||||
|
extern const string::value_type* const ISO8859_10;
|
||||||
|
extern const string::value_type* const ISO8859_13;
|
||||||
|
extern const string::value_type* const ISO8859_14;
|
||||||
|
extern const string::value_type* const ISO8859_15;
|
||||||
|
extern const string::value_type* const ISO8859_16;
|
||||||
|
|
||||||
|
extern const string::value_type* const CP_437;
|
||||||
|
extern const string::value_type* const CP_737;
|
||||||
|
extern const string::value_type* const CP_775;
|
||||||
|
extern const string::value_type* const CP_850;
|
||||||
|
extern const string::value_type* const CP_852;
|
||||||
|
extern const string::value_type* const CP_853;
|
||||||
|
extern const string::value_type* const CP_855;
|
||||||
|
extern const string::value_type* const CP_857;
|
||||||
|
extern const string::value_type* const CP_858;
|
||||||
|
extern const string::value_type* const CP_860;
|
||||||
|
extern const string::value_type* const CP_861;
|
||||||
|
extern const string::value_type* const CP_862;
|
||||||
|
extern const string::value_type* const CP_863;
|
||||||
|
extern const string::value_type* const CP_864;
|
||||||
|
extern const string::value_type* const CP_865;
|
||||||
|
extern const string::value_type* const CP_866;
|
||||||
|
extern const string::value_type* const CP_869;
|
||||||
|
extern const string::value_type* const CP_874;
|
||||||
|
extern const string::value_type* const CP_1125;
|
||||||
|
extern const string::value_type* const CP_1250;
|
||||||
|
extern const string::value_type* const CP_1251;
|
||||||
|
extern const string::value_type* const CP_1252;
|
||||||
|
extern const string::value_type* const CP_1253;
|
||||||
|
extern const string::value_type* const CP_1254;
|
||||||
|
extern const string::value_type* const CP_1255;
|
||||||
|
extern const string::value_type* const CP_1256;
|
||||||
|
extern const string::value_type* const CP_1257;
|
||||||
|
|
||||||
|
extern const string::value_type* const US_ASCII;
|
||||||
|
|
||||||
|
extern const string::value_type* const UTF_7;
|
||||||
|
extern const string::value_type* const UTF_8;
|
||||||
|
extern const string::value_type* const UTF_16;
|
||||||
|
extern const string::value_type* const UTF_32;
|
||||||
|
|
||||||
|
extern const string::value_type* const WINDOWS_1250;
|
||||||
|
extern const string::value_type* const WINDOWS_1251;
|
||||||
|
extern const string::value_type* const WINDOWS_1252;
|
||||||
|
extern const string::value_type* const WINDOWS_1253;
|
||||||
|
extern const string::value_type* const WINDOWS_1254;
|
||||||
|
extern const string::value_type* const WINDOWS_1255;
|
||||||
|
extern const string::value_type* const WINDOWS_1256;
|
||||||
|
extern const string::value_type* const WINDOWS_1257;
|
||||||
|
extern const string::value_type* const WINDOWS_1258;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_CONSTANTS_HPP_INCLUDED
|
62
src/contentDispositionField.cpp
Normal file
62
src/contentDispositionField.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "contentDispositionField.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
contentDispositionField::contentDispositionField()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void contentDispositionField::parseValue(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end)
|
||||||
|
{
|
||||||
|
m_value.parse(buffer, position, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string contentDispositionField::generateValue() const
|
||||||
|
{
|
||||||
|
return (m_value.generate());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
contentDispositionField& contentDispositionField::operator=(const disposition& type)
|
||||||
|
{
|
||||||
|
m_value = type;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void contentDispositionField::copyFrom(const headerField& field)
|
||||||
|
{
|
||||||
|
const contentDispositionField& source = dynamic_cast<const contentDispositionField&>(field);
|
||||||
|
m_value = source.m_value;
|
||||||
|
|
||||||
|
parameterizedHeaderField::copyFrom(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
79
src/contentDispositionField.hpp
Normal file
79
src/contentDispositionField.hpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_CONTENTDISPOSITIONFIELD_HPP_INCLUDED
|
||||||
|
#define VMIME_CONTENTDISPOSITIONFIELD_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "parameterizedHeaderField.hpp"
|
||||||
|
#include "disposition.hpp"
|
||||||
|
|
||||||
|
#include "dateParameter.hpp"
|
||||||
|
#include "textParameter.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class contentDispositionField : public parameterizedHeaderField
|
||||||
|
{
|
||||||
|
friend class headerFieldFactory::registerer <contentDispositionField>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
contentDispositionField();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void copyFrom(const headerField& field);
|
||||||
|
|
||||||
|
contentDispositionField& operator=(const disposition& type);
|
||||||
|
|
||||||
|
const disposition& value() const { return (m_value); }
|
||||||
|
disposition& value() { return (m_value); }
|
||||||
|
|
||||||
|
const datetime& creationDate() const { return (dynamic_cast<const dateParameter&>(parameters.find("creation-date")).value()); }
|
||||||
|
datetime& creationDate() { return (dynamic_cast<dateParameter&>(parameters.get("creation-date")).value()); }
|
||||||
|
|
||||||
|
const datetime& modificationDate() const { return (dynamic_cast<const dateParameter&>(parameters.find("modification-date")).value()); }
|
||||||
|
datetime& modificationDate() { return (dynamic_cast<dateParameter&>(parameters.get("modification-date")).value()); }
|
||||||
|
|
||||||
|
const datetime& readDate() const { return (dynamic_cast<const dateParameter&>(parameters.find("read-date")).value()); }
|
||||||
|
datetime& readDate() { return (dynamic_cast<dateParameter&>(parameters.get("read-date")).value()); }
|
||||||
|
|
||||||
|
const string& filename() const { return (dynamic_cast<const textParameter&>(parameters.find("filename")).value()); }
|
||||||
|
string& filename() { return (dynamic_cast<textParameter&>(parameters.get("filename")).value()); }
|
||||||
|
|
||||||
|
const string& size() const { return (dynamic_cast<const textParameter&>(parameters.find("size")).value()); }
|
||||||
|
string& size() { return (dynamic_cast<textParameter&>(parameters.get("size")).value()); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
disposition m_value;
|
||||||
|
|
||||||
|
void parseValue(const string& buffer, const string::size_type position, const string::size_type end);
|
||||||
|
const string generateValue() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_CONTENTDISPOSITIONFIELD_HPP_INCLUDED
|
62
src/contentEncodingField.cpp
Normal file
62
src/contentEncodingField.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "contentEncodingField.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
contentEncodingField::contentEncodingField()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void contentEncodingField::parseValue(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end)
|
||||||
|
{
|
||||||
|
m_value.parse(buffer, position, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string contentEncodingField::generateValue() const
|
||||||
|
{
|
||||||
|
return (m_value.generate());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
contentEncodingField& contentEncodingField::operator=(const encoding& type)
|
||||||
|
{
|
||||||
|
m_value = type;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void contentEncodingField::copyFrom(const headerField& field)
|
||||||
|
{
|
||||||
|
const contentEncodingField& source = dynamic_cast<const contentEncodingField&>(field);
|
||||||
|
m_value = source.m_value;
|
||||||
|
|
||||||
|
parameterizedHeaderField::copyFrom(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
61
src/contentEncodingField.hpp
Normal file
61
src/contentEncodingField.hpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_CONTENTENCODINGFIELD_HPP_INCLUDED
|
||||||
|
#define VMIME_CONTENTENCODINGFIELD_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "defaultParameterizedHeaderField.hpp"
|
||||||
|
#include "encoding.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class contentEncodingField : public parameterizedHeaderField
|
||||||
|
{
|
||||||
|
friend class headerFieldFactory::registerer <contentEncodingField>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
contentEncodingField();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void copyFrom(const headerField& field);
|
||||||
|
|
||||||
|
contentEncodingField& operator=(const encoding& type);
|
||||||
|
|
||||||
|
const encoding& value() const { return (m_value); }
|
||||||
|
encoding& value() { return (m_value); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
encoding m_value;
|
||||||
|
|
||||||
|
void parseValue(const string& buffer, const string::size_type position, const string::size_type end);
|
||||||
|
const string generateValue() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_CONTENTENCODINGFIELD_HPP_INCLUDED
|
369
src/contentHandler.cpp
Normal file
369
src/contentHandler.cpp
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "contentHandler.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// No encoding = "binary" encoding
|
||||||
|
const encoding contentHandler::NO_ENCODING(encodingTypes::BINARY);
|
||||||
|
|
||||||
|
|
||||||
|
contentHandler::contentHandler()
|
||||||
|
: m_type(TYPE_NONE), m_encoding(NO_ENCODING), m_ownedStream(NULL), m_stream(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
contentHandler::contentHandler(const string& buffer, const vmime::encoding& enc)
|
||||||
|
: m_type(TYPE_STRING), m_encoding(enc), m_string(buffer),
|
||||||
|
m_ownedStream(NULL), m_stream(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
contentHandler::~contentHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
contentHandler::contentHandler(const contentHandler& cts)
|
||||||
|
: m_type(cts.m_type), m_encoding(cts.m_encoding), m_string(cts.m_string),
|
||||||
|
m_ownedStream(const_cast <utility::smart_ptr <utility::inputStream>&>(cts.m_ownedStream)),
|
||||||
|
m_stream(cts.m_stream), m_length(cts.m_length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
contentHandler& contentHandler::operator=(const contentHandler& cts)
|
||||||
|
{
|
||||||
|
m_type = cts.m_type;
|
||||||
|
m_encoding = cts.m_encoding;
|
||||||
|
|
||||||
|
m_string = cts.m_string;
|
||||||
|
|
||||||
|
m_ownedStream = const_cast <utility::smart_ptr <utility::inputStream>&>(cts.m_ownedStream);
|
||||||
|
m_stream = cts.m_stream;
|
||||||
|
m_length = cts.m_length;
|
||||||
|
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void contentHandler::set(const utility::stringProxy& str, const vmime::encoding& enc)
|
||||||
|
{
|
||||||
|
m_type = TYPE_STRING;
|
||||||
|
m_encoding = enc;
|
||||||
|
|
||||||
|
m_string = str;
|
||||||
|
|
||||||
|
m_ownedStream = NULL;
|
||||||
|
m_stream = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void contentHandler::set(const string& buffer, const vmime::encoding& enc)
|
||||||
|
{
|
||||||
|
m_type = TYPE_STRING;
|
||||||
|
m_encoding = enc;
|
||||||
|
|
||||||
|
m_string.set(buffer);
|
||||||
|
|
||||||
|
m_ownedStream = NULL;
|
||||||
|
m_stream = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void contentHandler::set(const string& buffer, const string::size_type start,
|
||||||
|
const string::size_type end, const vmime::encoding& enc)
|
||||||
|
{
|
||||||
|
m_type = TYPE_STRING;
|
||||||
|
m_encoding = enc;
|
||||||
|
|
||||||
|
m_string.set(buffer, start, end);
|
||||||
|
|
||||||
|
m_ownedStream = NULL;
|
||||||
|
m_stream = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void contentHandler::set(utility::inputStream* const is, const string::size_type length,
|
||||||
|
const bool own, const vmime::encoding& enc)
|
||||||
|
{
|
||||||
|
m_type = TYPE_STREAM;
|
||||||
|
m_encoding = enc;
|
||||||
|
|
||||||
|
m_length = length;
|
||||||
|
|
||||||
|
if (own)
|
||||||
|
{
|
||||||
|
m_ownedStream = is;
|
||||||
|
m_stream = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ownedStream = NULL;
|
||||||
|
m_stream = is;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_string.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
contentHandler& contentHandler::operator=(const string& buffer)
|
||||||
|
{
|
||||||
|
set(buffer, NO_ENCODING);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void contentHandler::generate(utility::outputStream& os, const vmime::encoding& enc,
|
||||||
|
const string::size_type maxLineLength) const
|
||||||
|
{
|
||||||
|
if (m_type == TYPE_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Managed data is already encoded
|
||||||
|
if (isEncoded())
|
||||||
|
{
|
||||||
|
// The data is already encoded but the encoding specified for
|
||||||
|
// the generation is different from the current one. We need
|
||||||
|
// to re-encode data: decode from input buffer to temporary
|
||||||
|
// buffer, and then re-encode to output stream...
|
||||||
|
if (m_encoding != enc)
|
||||||
|
{
|
||||||
|
utility::auto_ptr <encoder> theDecoder(m_encoding.getEncoder());
|
||||||
|
utility::auto_ptr <encoder> theEncoder(enc.getEncoder());
|
||||||
|
|
||||||
|
theEncoder->properties()["maxlinelength"] = maxLineLength;
|
||||||
|
|
||||||
|
switch (m_type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// No data
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TYPE_STRING:
|
||||||
|
{
|
||||||
|
utility::inputStreamStringProxyAdapter in(m_string);
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
utility::outputStreamAdapter tempOut(oss);
|
||||||
|
|
||||||
|
theDecoder->decode(in, tempOut);
|
||||||
|
|
||||||
|
string str = oss.str();
|
||||||
|
utility::inputStreamStringAdapter tempIn(str);
|
||||||
|
|
||||||
|
theEncoder->encode(tempIn, os);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TYPE_STREAM:
|
||||||
|
{
|
||||||
|
utility::inputStream& in = const_cast <utility::inputStream&>
|
||||||
|
(*(m_stream ? m_stream : m_ownedStream.ptr()));
|
||||||
|
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
utility::outputStreamAdapter tempOut(oss);
|
||||||
|
|
||||||
|
theDecoder->decode(in, tempOut);
|
||||||
|
|
||||||
|
string str = oss.str();
|
||||||
|
utility::inputStreamStringAdapter tempIn(str);
|
||||||
|
|
||||||
|
theEncoder->encode(tempIn, os);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No encoding to perform
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (m_type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// No data
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TYPE_STRING:
|
||||||
|
{
|
||||||
|
m_string.extract(os);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TYPE_STREAM:
|
||||||
|
{
|
||||||
|
utility::inputStream& in = const_cast <utility::inputStream&>
|
||||||
|
(*(m_stream ? m_stream : m_ownedStream.ptr()));
|
||||||
|
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
utility::bufferedStreamCopy(in, os);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Need to encode data before
|
||||||
|
else
|
||||||
|
{
|
||||||
|
utility::auto_ptr <encoder> theEncoder(enc.getEncoder());
|
||||||
|
theEncoder->properties()["maxlinelength"] = maxLineLength;
|
||||||
|
|
||||||
|
// Encode the contents
|
||||||
|
switch (m_type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// No data
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TYPE_STRING:
|
||||||
|
{
|
||||||
|
utility::inputStreamStringProxyAdapter in(m_string);
|
||||||
|
|
||||||
|
theEncoder->encode(in, os);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TYPE_STREAM:
|
||||||
|
{
|
||||||
|
utility::inputStream& in = const_cast <utility::inputStream&>
|
||||||
|
(*(m_stream ? m_stream : m_ownedStream.ptr()));
|
||||||
|
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
theEncoder->encode(in, os);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void contentHandler::extract(utility::outputStream& os) const
|
||||||
|
{
|
||||||
|
if (m_type == TYPE_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// No decoding to perform
|
||||||
|
if (!isEncoded())
|
||||||
|
{
|
||||||
|
switch (m_type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// No data
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TYPE_STRING:
|
||||||
|
{
|
||||||
|
m_string.extract(os);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TYPE_STREAM:
|
||||||
|
{
|
||||||
|
utility::inputStream& in = const_cast <utility::inputStream&>
|
||||||
|
(*(m_stream ? m_stream : m_ownedStream.ptr()));
|
||||||
|
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
utility::bufferedStreamCopy(in, os);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Need to decode data
|
||||||
|
else
|
||||||
|
{
|
||||||
|
utility::auto_ptr <encoder> theDecoder(m_encoding.getEncoder());
|
||||||
|
|
||||||
|
switch (m_type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// No data
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TYPE_STRING:
|
||||||
|
{
|
||||||
|
utility::inputStreamStringProxyAdapter in(m_string);
|
||||||
|
|
||||||
|
theDecoder->decode(in, os);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TYPE_STREAM:
|
||||||
|
{
|
||||||
|
utility::inputStream& in = const_cast <utility::inputStream&>
|
||||||
|
(*(m_stream ? m_stream : m_ownedStream.ptr()));
|
||||||
|
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
theDecoder->decode(in, os);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string::size_type contentHandler::length() const
|
||||||
|
{
|
||||||
|
switch (m_type)
|
||||||
|
{
|
||||||
|
case TYPE_NONE: return (0);
|
||||||
|
case TYPE_STRING: return (m_string.length());
|
||||||
|
case TYPE_STREAM: return (m_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool contentHandler::empty() const
|
||||||
|
{
|
||||||
|
return (m_type == TYPE_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool contentHandler::isEncoded() const
|
||||||
|
{
|
||||||
|
return (m_encoding != NO_ENCODING);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const vmime::encoding& contentHandler::encoding() const
|
||||||
|
{
|
||||||
|
return (m_encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
125
src/contentHandler.hpp
Normal file
125
src/contentHandler.hpp
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_CONTENTHANDLER_HPP_INCLUDED
|
||||||
|
#define VMIME_CONTENTHANDLER_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "utility/stringProxy.hpp"
|
||||||
|
#include "utility/smartPtr.hpp"
|
||||||
|
#include "encoding.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class contentHandler
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
static const vmime::encoding NO_ENCODING;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
contentHandler();
|
||||||
|
contentHandler(const string& buffer, const vmime::encoding& enc = NO_ENCODING); // for compatibility
|
||||||
|
~contentHandler();
|
||||||
|
|
||||||
|
// Copy
|
||||||
|
contentHandler(const contentHandler& cts);
|
||||||
|
contentHandler& operator=(const contentHandler& cts);
|
||||||
|
|
||||||
|
// Set the data contained in the body.
|
||||||
|
//
|
||||||
|
// The two first functions take advantage of the COW (copy-on-write) system that
|
||||||
|
// might be implemented into std::string. This is done using "stringProxy" object.
|
||||||
|
//
|
||||||
|
// Set "enc" parameter to anything other than NO_ENCODING if the data managed by
|
||||||
|
// this content handler is already encoded with the specified encoding (so, no
|
||||||
|
// encoding/decoding will be performed on generate()/extract()). Note that the
|
||||||
|
// data may be re-encoded (that is, decoded and encoded) if the encoding passed
|
||||||
|
// to generate() is different from this one...
|
||||||
|
//
|
||||||
|
// The 'length' parameter is optional (user-defined). You can pass 0 if you want,
|
||||||
|
// VMime does not make use of it.
|
||||||
|
void set(const utility::stringProxy& str, const vmime::encoding& enc = NO_ENCODING);
|
||||||
|
void set(const string& buffer, const vmime::encoding& enc = NO_ENCODING);
|
||||||
|
void set(const string& buffer, const string::size_type start, const string::size_type end, const vmime::encoding& enc = NO_ENCODING);
|
||||||
|
void set(utility::inputStream* const is, const utility::stream::size_type length, const bool own, const vmime::encoding& enc = NO_ENCODING);
|
||||||
|
|
||||||
|
// For compatibility
|
||||||
|
contentHandler& operator=(const string& buffer);
|
||||||
|
|
||||||
|
// WRITE: Output the contents into the specified stream. Data will be
|
||||||
|
// encoded before being written into the stream. This is used internally
|
||||||
|
// by the body object to generate the message, you may not need to use
|
||||||
|
// this (see function extract() if you want to get the contents).
|
||||||
|
void generate(utility::outputStream& os, const vmime::encoding& enc, const string::size_type maxLineLength = lineLengthLimits::infinite) const;
|
||||||
|
|
||||||
|
// READ: Extract the contents into the specified stream. If needed, data
|
||||||
|
// will be decoded before being written into the stream.
|
||||||
|
void extract(utility::outputStream& os) const;
|
||||||
|
|
||||||
|
// Returns the actual length of the data. WARNING: this can return 0 if no
|
||||||
|
// length was specified when setting data of this object.
|
||||||
|
const string::size_type length() const;
|
||||||
|
|
||||||
|
// Returns 'true' if the data managed by this object is encoded.
|
||||||
|
const bool isEncoded() const;
|
||||||
|
|
||||||
|
// Returns the encoding used for the data (or "binary" if not encoded).
|
||||||
|
const vmime::encoding& encoding() const;
|
||||||
|
|
||||||
|
// Returns 'true' if there is no data set.
|
||||||
|
const bool empty() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Source of data managed by this content handler
|
||||||
|
enum Types
|
||||||
|
{
|
||||||
|
TYPE_NONE,
|
||||||
|
TYPE_STRING,
|
||||||
|
TYPE_STREAM
|
||||||
|
};
|
||||||
|
|
||||||
|
Types m_type;
|
||||||
|
|
||||||
|
// Equals to NO_ENCODING if data is not encoded, otherwise this
|
||||||
|
// specifies the encoding that have been used to encode the data.
|
||||||
|
vmime::encoding m_encoding;
|
||||||
|
|
||||||
|
// Used if m_type == TYPE_STRING
|
||||||
|
utility::stringProxy m_string;
|
||||||
|
|
||||||
|
// Used if m_type == TYPE_STREAM
|
||||||
|
utility::smart_ptr <utility::inputStream> m_ownedStream; // 'contentHandler' objects are copiable...
|
||||||
|
utility::inputStream* m_stream;
|
||||||
|
string::size_type m_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_CONTENTHANDLER_HPP_INCLUDED
|
62
src/contentTypeField.cpp
Normal file
62
src/contentTypeField.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "contentTypeField.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
contentTypeField::contentTypeField()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void contentTypeField::parseValue(const string& buffer,
|
||||||
|
const string::size_type position, const string::size_type end)
|
||||||
|
{
|
||||||
|
m_value.parse(buffer, position, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string contentTypeField::generateValue() const
|
||||||
|
{
|
||||||
|
return (m_value.generate());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
contentTypeField& contentTypeField::operator=(const mediaType& type)
|
||||||
|
{
|
||||||
|
m_value = type;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void contentTypeField::copyFrom(const headerField& field)
|
||||||
|
{
|
||||||
|
const contentTypeField& source = dynamic_cast<const contentTypeField&>(field);
|
||||||
|
m_value = source.m_value;
|
||||||
|
|
||||||
|
parameterizedHeaderField::copyFrom(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
72
src/contentTypeField.hpp
Normal file
72
src/contentTypeField.hpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_CONTENTTYPEFIELD_HPP_INCLUDED
|
||||||
|
#define VMIME_CONTENTTYPEFIELD_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "parameterizedHeaderField.hpp"
|
||||||
|
|
||||||
|
#include "mediaType.hpp"
|
||||||
|
#include "charset.hpp"
|
||||||
|
|
||||||
|
#include "textParameter.hpp"
|
||||||
|
#include "charsetParameter.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class contentTypeField : public parameterizedHeaderField
|
||||||
|
{
|
||||||
|
friend class headerFieldFactory::registerer <contentTypeField>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
contentTypeField();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void copyFrom(const headerField& field);
|
||||||
|
|
||||||
|
contentTypeField& operator=(const mediaType& type);
|
||||||
|
|
||||||
|
const mediaType& value() const { return (m_value); }
|
||||||
|
mediaType& value() { return (m_value); }
|
||||||
|
|
||||||
|
const string& boundary() const { return (dynamic_cast<const textParameter&>(parameters.find("boundary")).value()); }
|
||||||
|
string& boundary() { return (dynamic_cast<textParameter&>(parameters.get("boundary")).value()); }
|
||||||
|
|
||||||
|
const class charset& charset() const { return (dynamic_cast<const charsetParameter&>(parameters.find("charset")).value()); }
|
||||||
|
class charset& charset() { return (dynamic_cast<charsetParameter&>(parameters.get("charset")).value()); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
mediaType m_value;
|
||||||
|
|
||||||
|
void parseValue(const string& buffer, const string::size_type position, const string::size_type end);
|
||||||
|
const string generateValue() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_CONTENTTYPEFIELD_HPP_INCLUDED
|
66
src/dateField.cpp
Normal file
66
src/dateField.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "dateField.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
dateField::dateField()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dateField::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
m_datetime.parse(buffer, position, end, newPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dateField::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
string::size_type pos = curLinePos;
|
||||||
|
|
||||||
|
headerField::generate(os, maxLineLength, pos, &pos);
|
||||||
|
|
||||||
|
m_datetime.generate(os, maxLineLength, pos, newLinePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dateField& dateField::operator=(const class datetime& datetime)
|
||||||
|
{
|
||||||
|
m_datetime = datetime;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dateField::copyFrom(const headerField& field)
|
||||||
|
{
|
||||||
|
const dateField& source = dynamic_cast<const dateField&>(field);
|
||||||
|
m_datetime = source.m_datetime;
|
||||||
|
|
||||||
|
headerField::copyFrom(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
70
src/dateField.hpp
Normal file
70
src/dateField.hpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_DATEFIELD_HPP_INCLUDED
|
||||||
|
#define VMIME_DATEFIELD_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
#include "headerFieldFactory.hpp"
|
||||||
|
#include "dateTime.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class dateField : public headerField
|
||||||
|
{
|
||||||
|
friend class headerFieldFactory::registerer <dateField>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
dateField();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void copyFrom(const headerField& field);
|
||||||
|
|
||||||
|
dateField& operator=(const class datetime& datetime);
|
||||||
|
|
||||||
|
const datetime& value() const { return (m_datetime); }
|
||||||
|
datetime& value() { return (m_datetime); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
datetime m_datetime;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using headerField::parse;
|
||||||
|
using headerField::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_DATEFIELD_HPP_INCLUDED
|
50
src/dateParameter.cpp
Normal file
50
src/dateParameter.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "dateParameter.hpp"
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
void dateParameter::parseValue(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end)
|
||||||
|
{
|
||||||
|
m_value.parse(buffer, position, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string dateParameter::generateValue() const
|
||||||
|
{
|
||||||
|
return (m_value.generate());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dateParameter::copyFrom(const parameter& param)
|
||||||
|
{
|
||||||
|
const dateParameter& source = dynamic_cast<const dateParameter&>(param);
|
||||||
|
m_value = source.m_value;
|
||||||
|
|
||||||
|
defaultParameter::copyFrom(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
55
src/dateParameter.hpp
Normal file
55
src/dateParameter.hpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_DATEPARAMETER_HPP_INCLUDED
|
||||||
|
#define VMIME_DATEPARAMETER_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "defaultParameter.hpp"
|
||||||
|
#include "dateTime.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class dateParameter : public defaultParameter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
datetime m_value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void copyFrom(const parameter& param);
|
||||||
|
|
||||||
|
const datetime& value() const { return (m_value); }
|
||||||
|
datetime& value() { return (m_value); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void parseValue(const string& buffer, const string::size_type position, const string::size_type end);
|
||||||
|
const string generateValue() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_DATEPARAMETER_HPP_INCLUDED
|
702
src/dateTime.cpp
Normal file
702
src/dateTime.cpp
Normal file
@ -0,0 +1,702 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
#include "dateTime.hpp"
|
||||||
|
#include "platformDependant.hpp"
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
RFC #822:
|
||||||
|
5. DATE AND TIME SPECIFICATION
|
||||||
|
|
||||||
|
date-time = [ day "," ] date time ; dd mm yy
|
||||||
|
; hh:mm:ss zzz
|
||||||
|
day = "Mon" / "Tue" / "Wed" / "Thu" /
|
||||||
|
"Fri" / "Sat" / "Sun"
|
||||||
|
|
||||||
|
date = 1*2DIGIT month 2DIGIT ; day month year
|
||||||
|
; e.g. 20 Jun 82
|
||||||
|
month = "Jan" / "Feb" / "Mar" / "Apr" /
|
||||||
|
"May" / "Jun" / "Jul" / "Aug" /
|
||||||
|
"Sep" / "Oct" / "Nov" / "Dec"
|
||||||
|
|
||||||
|
time = hour zone ; ANSI and Military
|
||||||
|
|
||||||
|
hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] ; 00:00:00 - 23:59:59
|
||||||
|
|
||||||
|
zone = "UT" / "GMT" ; Universal Time
|
||||||
|
; North American : UT
|
||||||
|
/ "EST" / "EDT" ; Eastern: - 5/ - 4
|
||||||
|
/ "CST" / "CDT" ; Central: - 6/ - 5
|
||||||
|
/ "MST" / "MDT" ; Mountain: - 7/ - 6
|
||||||
|
/ "PST" / "PDT" ; Pacific: - 8/ - 7
|
||||||
|
/ 1ALPHA ; Military: Z = UT;
|
||||||
|
; A:-1; (J not used)
|
||||||
|
; M:-12; N:+1; Y:+12
|
||||||
|
/ ( ("+" / "-") 4DIGIT ) ; Local differential
|
||||||
|
; hours+min. (HHMM)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void datetime::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
const string::value_type* const pend = buffer.data() + end;
|
||||||
|
const string::value_type* p = buffer.data() + position;
|
||||||
|
|
||||||
|
// Parse the date and time value
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
|
||||||
|
if (p < pend)
|
||||||
|
{
|
||||||
|
if (isalpha(*p))
|
||||||
|
{
|
||||||
|
// Ignore week day
|
||||||
|
while (p < pend && isalpha(*p)) ++p;
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
if (p < pend && *p == ',') ++p;
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (p < pend && !isdigit(*p)) ++p;
|
||||||
|
|
||||||
|
if (p < pend && isdigit(*p))
|
||||||
|
{
|
||||||
|
// Month day
|
||||||
|
comp_t day = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
day = day * 10 + (*p - '0');
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
while (p < pend && isdigit(*p));
|
||||||
|
|
||||||
|
m_day = (day >= 1 && day <= 31) ? day : 1;
|
||||||
|
|
||||||
|
while (p < pend && !isspace(*p)) ++p;
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_day = 1;
|
||||||
|
|
||||||
|
// Skip everything to the next field
|
||||||
|
while (p < pend && !isspace(*p)) ++p;
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p < pend && isalpha(*p))
|
||||||
|
{
|
||||||
|
// Month
|
||||||
|
char_t month[4] = { 0 };
|
||||||
|
int monthLength = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
month[monthLength++] = *p;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
while (monthLength < 3 && p < pend && isalpha(*p));
|
||||||
|
|
||||||
|
while (p < pend && isalpha(*p)) ++p;
|
||||||
|
|
||||||
|
switch (month[0])
|
||||||
|
{
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
{
|
||||||
|
if (month[1] == 'u' || month[1] == 'U')
|
||||||
|
m_month = AUGUST;
|
||||||
|
else
|
||||||
|
m_month = APRIL; // by default
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
{
|
||||||
|
m_month = DECEMBER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'f':
|
||||||
|
case 'F':
|
||||||
|
{
|
||||||
|
m_month = FEBRUARY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'j':
|
||||||
|
case 'J':
|
||||||
|
{
|
||||||
|
if (month[1] == 'u' || month[1] == 'U')
|
||||||
|
{
|
||||||
|
if (month[2] == 'l' || month[2] == 'L')
|
||||||
|
m_month = JULY;
|
||||||
|
else // if (month[2] == 'n' || month[2] == 'N')
|
||||||
|
m_month = JUNE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_month = JANUARY; // by default
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
{
|
||||||
|
if ((month[1] == 'a' || month[1] == 'A') &&
|
||||||
|
(month[2] == 'y' || month[2] == 'Y'))
|
||||||
|
{
|
||||||
|
m_month = MAY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_month = MARCH; // by default
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'n':
|
||||||
|
case 'N':
|
||||||
|
{
|
||||||
|
m_month = NOVEMBER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'o':
|
||||||
|
case 'O':
|
||||||
|
{
|
||||||
|
m_month = OCTOBER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
{
|
||||||
|
m_month = SEPTEMBER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
m_month = JANUARY; // by default
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
while (p < pend && !isspace(*p)) ++p;
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_month = JANUARY;
|
||||||
|
|
||||||
|
// Skip everything to the next field
|
||||||
|
while (p < pend && !isspace(*p)) ++p;
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p < pend && isdigit(*p))
|
||||||
|
{
|
||||||
|
// Year
|
||||||
|
comp_t year = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
year = year * 10 + (*p - '0');
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
while (p < pend && isdigit(*p));
|
||||||
|
|
||||||
|
if (year < 70) m_year = year + 2000;
|
||||||
|
else if (year < 1000) m_year = year + 1900;
|
||||||
|
else m_year = year;
|
||||||
|
|
||||||
|
while (p < pend && !isspace(*p)) ++p;
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_year = 1970;
|
||||||
|
|
||||||
|
// Skip everything to the next field
|
||||||
|
while (p < pend && !isspace(*p)) ++p;
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p < pend && isdigit(*p))
|
||||||
|
{
|
||||||
|
// Hour
|
||||||
|
comp_t hour = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
hour = hour * 10 + (*p - '0');
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
while (p < pend && isdigit(*p));
|
||||||
|
|
||||||
|
m_hour = (hour >= 0 && hour <= 23) ? hour : 0;
|
||||||
|
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
|
||||||
|
if (p < pend && *p == ':')
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
|
||||||
|
if (p < pend && isdigit(*p))
|
||||||
|
{
|
||||||
|
// Minute
|
||||||
|
comp_t minute = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
minute = minute * 10 + (*p - '0');
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
while (p < pend && isdigit(*p));
|
||||||
|
|
||||||
|
m_minute = (minute >= 0 && minute <= 59) ? minute : 0;
|
||||||
|
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
|
||||||
|
if (p < pend && *p == ':')
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
|
||||||
|
if (p < pend && isdigit(*p))
|
||||||
|
{
|
||||||
|
// Second
|
||||||
|
comp_t second = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
second = second * 10 + (*p - '0');
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
while (p < pend && isdigit(*p));
|
||||||
|
|
||||||
|
m_second = (second >= 0 && second <= 59) ? second : 0;
|
||||||
|
|
||||||
|
while (p < pend && !isspace(*p)) ++p;
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_second = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_second = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_minute = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_minute = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_hour = 0;
|
||||||
|
|
||||||
|
// Skip everything to the next field
|
||||||
|
while (p < pend && !isspace(*p)) ++p;
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p + 1 < pend && (*p == '+' || *p == '-') && isdigit(*(p + 1)))
|
||||||
|
{
|
||||||
|
const char_t sign = *p;
|
||||||
|
++p;
|
||||||
|
|
||||||
|
// Zone offset (in hour/minutes)
|
||||||
|
comp_t offset = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
offset = offset * 10 + (*p - '0');
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
while (p < pend && isdigit(*p));
|
||||||
|
|
||||||
|
const comp_t hourOff = offset / 100;
|
||||||
|
const comp_t minOff = offset % 100;
|
||||||
|
|
||||||
|
if (sign == '+')
|
||||||
|
m_zone = hourOff * 60 + minOff;
|
||||||
|
else
|
||||||
|
m_zone = -(hourOff * 60 + minOff);
|
||||||
|
}
|
||||||
|
else if (p < pend && isalpha(*p))
|
||||||
|
{
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
// Zone offset (Time zone name)
|
||||||
|
char_t zone[4] = { 0 };
|
||||||
|
int zoneLength = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
zone[zoneLength++] = *p;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
while (zoneLength < 3 && p < pend && isdigit(*p));
|
||||||
|
|
||||||
|
switch (zone[0])
|
||||||
|
{
|
||||||
|
case 'c':
|
||||||
|
case 'C':
|
||||||
|
{
|
||||||
|
if (zoneLength >= 2)
|
||||||
|
{
|
||||||
|
if (zone[1] == 's' || zone[1] == 'S')
|
||||||
|
m_zone = CST;
|
||||||
|
else
|
||||||
|
m_zone = CDT;
|
||||||
|
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'e':
|
||||||
|
case 'E':
|
||||||
|
{
|
||||||
|
if (zoneLength >= 2)
|
||||||
|
{
|
||||||
|
if (zone[1] == 's' || zone[1] == 'S')
|
||||||
|
m_zone = EST;
|
||||||
|
else
|
||||||
|
m_zone = EDT;
|
||||||
|
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
{
|
||||||
|
if (zoneLength >= 2)
|
||||||
|
{
|
||||||
|
if (zone[1] == 's' || zone[1] == 'S')
|
||||||
|
m_zone = MST;
|
||||||
|
else
|
||||||
|
m_zone = MDT;
|
||||||
|
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'p':
|
||||||
|
case 'P':
|
||||||
|
{
|
||||||
|
if (zoneLength >= 2)
|
||||||
|
{
|
||||||
|
if (zone[1] == 's' || zone[1] == 'S')
|
||||||
|
m_zone = PST;
|
||||||
|
else
|
||||||
|
m_zone = PDT;
|
||||||
|
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u':
|
||||||
|
case 'U':
|
||||||
|
{
|
||||||
|
if (zoneLength >= 2)
|
||||||
|
{
|
||||||
|
m_zone = GMT; // = UTC
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!done)
|
||||||
|
{
|
||||||
|
const char_t z = zone[0];
|
||||||
|
|
||||||
|
// Military time zone
|
||||||
|
if (z != 'j' && z != 'J')
|
||||||
|
{
|
||||||
|
typedef std::map <char_t, int> Map;
|
||||||
|
static const Map::value_type offsetMapInit[] =
|
||||||
|
{
|
||||||
|
Map::value_type('a', -60),
|
||||||
|
Map::value_type('b', -120),
|
||||||
|
Map::value_type('c', -180),
|
||||||
|
Map::value_type('d', -240),
|
||||||
|
Map::value_type('e', -300),
|
||||||
|
Map::value_type('f', -360),
|
||||||
|
Map::value_type('g', -420),
|
||||||
|
Map::value_type('h', -480),
|
||||||
|
Map::value_type('i', -540),
|
||||||
|
Map::value_type('k', -600),
|
||||||
|
Map::value_type('l', -660),
|
||||||
|
Map::value_type('m', -720),
|
||||||
|
|
||||||
|
Map::value_type('n', 60),
|
||||||
|
Map::value_type('o', 120),
|
||||||
|
Map::value_type('p', 180),
|
||||||
|
Map::value_type('q', 240),
|
||||||
|
Map::value_type('r', 300),
|
||||||
|
Map::value_type('s', 360),
|
||||||
|
Map::value_type('t', 420),
|
||||||
|
Map::value_type('u', 480),
|
||||||
|
Map::value_type('v', 540),
|
||||||
|
Map::value_type('w', 600),
|
||||||
|
Map::value_type('x', 660),
|
||||||
|
Map::value_type('y', 720),
|
||||||
|
|
||||||
|
Map::value_type('z', 0),
|
||||||
|
};
|
||||||
|
static const Map offsetMap
|
||||||
|
(::vmime::begin(offsetMapInit),
|
||||||
|
::vmime::end(offsetMapInit));
|
||||||
|
|
||||||
|
Map::const_iterator pos =
|
||||||
|
offsetMap.find(tolower(z));
|
||||||
|
|
||||||
|
if (pos != offsetMap.end())
|
||||||
|
m_zone = (*pos).second;
|
||||||
|
else
|
||||||
|
m_zone = GMT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_zone = GMT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_zone = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_year = 1970;
|
||||||
|
m_month = JANUARY;
|
||||||
|
m_day = 1;
|
||||||
|
|
||||||
|
m_hour = 0;
|
||||||
|
m_minute = 0;
|
||||||
|
m_second = 0;
|
||||||
|
|
||||||
|
m_zone = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void datetime::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
static const string::value_type* dayNames[] =
|
||||||
|
{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||||
|
static const string::value_type* monthNames[] =
|
||||||
|
{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||||
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||||
|
|
||||||
|
const comp_t z = ((m_zone < 0) ? -m_zone : m_zone);
|
||||||
|
const comp_t zh = z / 60;
|
||||||
|
const comp_t zm = z % 60;
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << dayNames[dayOfWeek(m_year, m_month, m_day)] << ", "
|
||||||
|
<< m_day << " " << monthNames[month() - 1] << " " << year()
|
||||||
|
<< " " << std::setfill('0') << std::setw(2) << m_hour << ":"
|
||||||
|
<< std::setfill('0') << std::setw(2) << m_minute << ":"
|
||||||
|
<< std::setfill('0') << std::setw(2) << m_second
|
||||||
|
<< " " << ((m_zone < 0) ? '-' : '+') << std::setfill('0') << std::setw(2) << zh
|
||||||
|
<< std::setfill('0') << std::setw(2) << zm;
|
||||||
|
|
||||||
|
const string& str = oss.str();
|
||||||
|
os << str;
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
*newLinePos = curLinePos + str.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
datetime::datetime()
|
||||||
|
: m_year(1970), m_month(1), m_day(1),
|
||||||
|
m_hour(0), m_minute(0), m_second(0), m_zone(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
datetime::datetime(const comp_t year, const comp_t month, const comp_t day)
|
||||||
|
: m_year(year), m_month(month), m_day(day),
|
||||||
|
m_hour(0), m_minute(0), m_second(0), m_zone(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
datetime::datetime(const comp_t year, const comp_t month, const comp_t day,
|
||||||
|
const comp_t hour, const comp_t minute, const comp_t second,
|
||||||
|
const comp_t zone)
|
||||||
|
: m_year(year), m_month(month), m_day(day),
|
||||||
|
m_hour(hour), m_minute(minute), m_second(second), m_zone(zone)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
datetime::datetime(const datetime& d)
|
||||||
|
: component(), m_year(d.m_year), m_month(d.m_month), m_day(d.m_day),
|
||||||
|
m_hour(d.m_hour), m_minute(d.m_minute), m_second(d.m_second), m_zone(d.m_zone)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
datetime::datetime(const string& date)
|
||||||
|
{
|
||||||
|
parse(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
datetime::~datetime()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void datetime::copyFrom(const datetime& d)
|
||||||
|
{
|
||||||
|
m_year = d.m_year;
|
||||||
|
m_month = d.m_month;
|
||||||
|
m_day = d.m_day;
|
||||||
|
m_hour = d.m_hour;
|
||||||
|
m_minute = d.m_minute;
|
||||||
|
m_second = d.m_second;
|
||||||
|
m_zone = d.m_zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
datetime& datetime::operator=(const datetime& d)
|
||||||
|
{
|
||||||
|
copyFrom(d);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
datetime& datetime::operator=(const string& s)
|
||||||
|
{
|
||||||
|
parse(s);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void datetime::getTime(comp_t& hour, comp_t& minute, comp_t& second, comp_t& zone) const
|
||||||
|
{
|
||||||
|
hour = m_hour;
|
||||||
|
minute = m_minute;
|
||||||
|
second = m_second;
|
||||||
|
zone = m_zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void datetime::getTime(comp_t& hour, comp_t& minute, comp_t& second) const
|
||||||
|
{
|
||||||
|
hour = m_hour;
|
||||||
|
minute = m_minute;
|
||||||
|
second = m_second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void datetime::getDate(comp_t& year, comp_t& month, comp_t& day) const
|
||||||
|
{
|
||||||
|
year = m_year;
|
||||||
|
month = m_month;
|
||||||
|
day = m_day;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void datetime::setTime(const comp_t hour, const comp_t minute,
|
||||||
|
const comp_t second, const comp_t zone)
|
||||||
|
{
|
||||||
|
m_hour = hour;
|
||||||
|
m_minute = minute;
|
||||||
|
m_second = second;
|
||||||
|
m_zone = zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void datetime::setDate(const comp_t year, const comp_t month, const comp_t day)
|
||||||
|
{
|
||||||
|
m_year = year;
|
||||||
|
m_month = month;
|
||||||
|
m_day = day;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const datetime::comp_t datetime::dayOfWeek(const comp_t year, const comp_t month, const comp_t day)
|
||||||
|
{
|
||||||
|
comp_t y = year;
|
||||||
|
comp_t m = month;
|
||||||
|
|
||||||
|
// From RFC-3339 - Appendix B. Day of the Week
|
||||||
|
|
||||||
|
// Adjust months so February is the last one
|
||||||
|
m -= 2;
|
||||||
|
|
||||||
|
if (m < 1)
|
||||||
|
{
|
||||||
|
m += 12;
|
||||||
|
--y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split by century
|
||||||
|
const comp_t cent = y / 100;
|
||||||
|
y %= 100;
|
||||||
|
|
||||||
|
return (((26 * m - 2) / 10 + day + y + (y >> 2) + (cent >> 2) + 5 * cent) % 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const datetime datetime::now()
|
||||||
|
{
|
||||||
|
return (platformDependant::getHandler()->getCurrentLocalTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
242
src/dateTime.hpp
Normal file
242
src/dateTime.hpp
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_DATETIME_HPP_INCLUDED
|
||||||
|
#define VMIME_DATETIME_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** Date and time (basic type).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class datetime : public component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Data type for a date/time component
|
||||||
|
typedef int comp_t;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
datetime();
|
||||||
|
datetime(const comp_t year, const comp_t month, const comp_t day);
|
||||||
|
datetime(const comp_t year, const comp_t month, const comp_t day, const comp_t hour, const comp_t minute, const comp_t second, const comp_t zone = GMT);
|
||||||
|
datetime(const datetime& d);
|
||||||
|
datetime(const string& date);
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~datetime();
|
||||||
|
|
||||||
|
// Some time zones (in minutes)
|
||||||
|
enum TimeZones
|
||||||
|
{
|
||||||
|
GMT_12 = -720, // GMT-12h
|
||||||
|
GMT_11 = -660, // GMT-11h
|
||||||
|
GMT_10 = -600, // GMT-10h
|
||||||
|
GMT_9 = -540, // GMT-9h
|
||||||
|
GMT_8 = -480, // GMT-8h
|
||||||
|
GMT_7 = -420, // GMT-7h
|
||||||
|
GMT_6 = -360, // GMT-6h
|
||||||
|
GMT_5 = -300, // GMT-5h
|
||||||
|
GMT_4 = -240, // GMT-4h
|
||||||
|
GMT_3 = -180, // GMT-3h
|
||||||
|
GMT_2 = -120, // GMT-2h
|
||||||
|
GMT_1 = -60, // GMT-1h
|
||||||
|
GMT = 0, // GMT
|
||||||
|
GMT1 = 60, // GMT+1h
|
||||||
|
GMT2 = 120, // GMT+2h
|
||||||
|
GMT3 = 180, // GMT+3h
|
||||||
|
GMT4 = 240, // GMT+4h
|
||||||
|
GMT5 = 300, // GMT+5h
|
||||||
|
GMT6 = 360, // GMT+6h
|
||||||
|
GMT7 = 420, // GMT+7h
|
||||||
|
GMT8 = 480, // GMT+8h
|
||||||
|
GMT9 = 540, // GMT+9h
|
||||||
|
GMT10 = 600, // GMT+10h
|
||||||
|
GMT11 = 660, // GMT+11h
|
||||||
|
GMT12 = 720, // GMT+12h
|
||||||
|
|
||||||
|
UT = GMT, // Universal Time
|
||||||
|
|
||||||
|
EST = GMT_5, // Eastern
|
||||||
|
EDT = GMT_4,
|
||||||
|
CST = GMT_6, // Central
|
||||||
|
CDT = GMT_5,
|
||||||
|
MST = GMT_7, // Mountain
|
||||||
|
MDT = GMT_6,
|
||||||
|
PST = GMT_8, // Pacific
|
||||||
|
PDT = GMT_7,
|
||||||
|
|
||||||
|
// Military time zones
|
||||||
|
A = GMT_1,
|
||||||
|
B = GMT_2,
|
||||||
|
C = GMT_3,
|
||||||
|
D = GMT_4,
|
||||||
|
E = GMT_5,
|
||||||
|
F = GMT_6,
|
||||||
|
G = GMT_7,
|
||||||
|
H = GMT_8,
|
||||||
|
I = GMT_9, // J not used
|
||||||
|
K = GMT_10,
|
||||||
|
L = GMT_11,
|
||||||
|
M = GMT_12,
|
||||||
|
|
||||||
|
N = GMT1,
|
||||||
|
O = GMT2,
|
||||||
|
P = GMT3,
|
||||||
|
Q = GMT4,
|
||||||
|
R = GMT5,
|
||||||
|
S = GMT6,
|
||||||
|
T = GMT7,
|
||||||
|
U = GMT8,
|
||||||
|
V = GMT9,
|
||||||
|
W = GMT10,
|
||||||
|
X = GMT11,
|
||||||
|
Y = GMT12,
|
||||||
|
|
||||||
|
Z = GMT
|
||||||
|
};
|
||||||
|
|
||||||
|
// Months list
|
||||||
|
enum Months
|
||||||
|
{
|
||||||
|
// Long
|
||||||
|
JANUARY = 1,
|
||||||
|
FEBRUARY = 2,
|
||||||
|
MARCH = 3,
|
||||||
|
APRIL = 4,
|
||||||
|
MAY = 5,
|
||||||
|
JUNE = 6,
|
||||||
|
JULY = 7,
|
||||||
|
AUGUST = 8,
|
||||||
|
SEPTEMBER = 9,
|
||||||
|
OCTOBER = 10,
|
||||||
|
NOVEMBER = 11,
|
||||||
|
DECEMBER = 12,
|
||||||
|
|
||||||
|
// Short
|
||||||
|
JAN = 1,
|
||||||
|
FEB = 2,
|
||||||
|
MAR = 3,
|
||||||
|
APR = 4,
|
||||||
|
JUN = 6,
|
||||||
|
JUL = 7,
|
||||||
|
AUG = 8,
|
||||||
|
SEP = 9,
|
||||||
|
OCT = 10,
|
||||||
|
NOV = 11,
|
||||||
|
DEC = 12
|
||||||
|
};
|
||||||
|
|
||||||
|
// Days of week list
|
||||||
|
enum DaysOfWeek
|
||||||
|
{
|
||||||
|
// Long
|
||||||
|
SUNDAY = 0,
|
||||||
|
MONDAY = 1,
|
||||||
|
TUESDAY = 2,
|
||||||
|
WEDNESDAY = 3,
|
||||||
|
THURSDAY = 4,
|
||||||
|
FRIDAY = 5,
|
||||||
|
SATURDAY = 6,
|
||||||
|
|
||||||
|
// Short
|
||||||
|
SUN = 0,
|
||||||
|
MON = 1,
|
||||||
|
TUE = 2,
|
||||||
|
WED = 3,
|
||||||
|
THU = 4,
|
||||||
|
FRI = 5,
|
||||||
|
SAT = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Date components
|
||||||
|
comp_t m_year;
|
||||||
|
comp_t m_month;
|
||||||
|
comp_t m_day;
|
||||||
|
|
||||||
|
// Time components
|
||||||
|
comp_t m_hour;
|
||||||
|
comp_t m_minute;
|
||||||
|
comp_t m_second;
|
||||||
|
comp_t m_zone;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Get
|
||||||
|
const comp_t year() const { return (m_year); }
|
||||||
|
const comp_t month() const { return (m_month); }
|
||||||
|
const comp_t day() const { return (m_day); }
|
||||||
|
const comp_t hour() const { return (m_hour); }
|
||||||
|
const comp_t minute() const { return (m_minute); }
|
||||||
|
const comp_t second() const { return (m_second); }
|
||||||
|
const comp_t zone() const { return (m_zone); }
|
||||||
|
|
||||||
|
void getTime(comp_t& hour, comp_t& minute, comp_t& second, comp_t& zone) const;
|
||||||
|
void getTime(comp_t& hour, comp_t& minute, comp_t& second) const;
|
||||||
|
void getDate(comp_t& year, comp_t& month, comp_t& day) const;
|
||||||
|
|
||||||
|
// Set
|
||||||
|
comp_t& year() { return (m_year); }
|
||||||
|
comp_t& month() { return (m_month); }
|
||||||
|
comp_t& day() { return (m_day); }
|
||||||
|
comp_t& hour() { return (m_hour); }
|
||||||
|
comp_t& minute() { return (m_minute); }
|
||||||
|
comp_t& second() { return (m_second); }
|
||||||
|
comp_t& zone() { return (m_zone); }
|
||||||
|
|
||||||
|
void setTime(const comp_t hour = 0, const comp_t minute = 0, const comp_t second = 0, const comp_t zone = GMT);
|
||||||
|
void setDate(const comp_t year, const comp_t month, const comp_t day);
|
||||||
|
|
||||||
|
// Assignment
|
||||||
|
datetime& operator=(const datetime& d);
|
||||||
|
datetime& operator=(const string& s);
|
||||||
|
|
||||||
|
void copyFrom(const datetime& d);
|
||||||
|
|
||||||
|
// Current date and time
|
||||||
|
static const datetime now();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
static const comp_t dayOfWeek(const comp_t year, const comp_t month, const comp_t day);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using component::parse;
|
||||||
|
using component::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_DATETIME_HPP_INCLUDED
|
91
src/defaultAttachment.cpp
Normal file
91
src/defaultAttachment.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "defaultAttachment.hpp"
|
||||||
|
#include "encoding.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
defaultAttachment::defaultAttachment()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
defaultAttachment::defaultAttachment(const contentHandler& data,
|
||||||
|
const class encoding& enc, const mediaType& type, const text& desc)
|
||||||
|
: m_type(type), m_desc(desc), m_data(data), m_encoding(enc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
defaultAttachment::defaultAttachment(const contentHandler& data,
|
||||||
|
const mediaType& type, const text& desc)
|
||||||
|
: m_type(type), m_desc(desc), m_data(data), m_encoding(encoding::decide(data))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
defaultAttachment::defaultAttachment(const defaultAttachment& attach)
|
||||||
|
: attachment(), m_type(attach.m_type), m_desc(attach.m_desc),
|
||||||
|
m_data(attach.m_data), m_encoding(attach.m_encoding)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
attachment& defaultAttachment::operator=(const attachment& attach)
|
||||||
|
{
|
||||||
|
const defaultAttachment& att =
|
||||||
|
dynamic_cast <const defaultAttachment&>(attach);
|
||||||
|
|
||||||
|
m_type = att.m_type;
|
||||||
|
m_desc = att.m_desc;
|
||||||
|
m_data = att.m_data;
|
||||||
|
m_encoding = att.m_encoding;
|
||||||
|
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void defaultAttachment::generateIn(bodyPart& parent) const
|
||||||
|
{
|
||||||
|
// Create and append a new part for this attachment
|
||||||
|
bodyPart* part = new bodyPart;
|
||||||
|
parent.body().parts.append(part);
|
||||||
|
|
||||||
|
generatePart(*part);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void defaultAttachment::generatePart(bodyPart& part) const
|
||||||
|
{
|
||||||
|
// Set header fields
|
||||||
|
part.header().fields.ContentType() = m_type;
|
||||||
|
if (!m_desc.empty()) part.header().fields.ContentDescription() = m_desc;
|
||||||
|
part.header().fields.ContentTransferEncoding() = m_encoding;
|
||||||
|
part.header().fields.ContentDisposition() = disposition(dispositionTypes::ATTACHMENT);
|
||||||
|
|
||||||
|
// Set contents
|
||||||
|
part.body().contents() = m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
69
src/defaultAttachment.hpp
Normal file
69
src/defaultAttachment.hpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_DEFAULTATTACHMENT_HPP_INCLUDED
|
||||||
|
#define VMIME_DEFAULTATTACHMENT_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "attachment.hpp"
|
||||||
|
#include "encoding.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class defaultAttachment : public attachment
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// For use in derived classes.
|
||||||
|
defaultAttachment();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
defaultAttachment(const contentHandler& data, const class encoding& enc, const mediaType& type, const text& desc = NULL_TEXT);
|
||||||
|
defaultAttachment(const contentHandler& data, const mediaType& type, const text& desc = NULL_TEXT);
|
||||||
|
defaultAttachment(const defaultAttachment& attach);
|
||||||
|
|
||||||
|
attachment& operator=(const attachment& attach);
|
||||||
|
|
||||||
|
const mediaType& type() const { return (m_type); }
|
||||||
|
const text& description() const { return (m_desc); }
|
||||||
|
const contentHandler& data() const { return (m_data); }
|
||||||
|
const class encoding& encoding() const { return (m_encoding); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
mediaType m_type; // Media type (eg. "application/octet-stream")
|
||||||
|
text m_desc; // Description (eg. "The image you requested")
|
||||||
|
contentHandler m_data; // Attachment data (eg. the file contents)
|
||||||
|
class encoding m_encoding; // Encoding
|
||||||
|
|
||||||
|
// No need to override "generateIn", use "generatePart" instead (see below).
|
||||||
|
void generateIn(bodyPart& parent) const;
|
||||||
|
|
||||||
|
virtual void generatePart(bodyPart& part) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_DEFAULTATTACHMENT_HPP_INCLUDED
|
71
src/defaultField.cpp
Normal file
71
src/defaultField.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "defaultField.hpp"
|
||||||
|
#include "text.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
defaultField::defaultField()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void defaultField::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
m_text = string(buffer.begin() + position, buffer.begin() + end);
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void defaultField::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
string::size_type pos = curLinePos;
|
||||||
|
|
||||||
|
headerField::generate(os, maxLineLength, pos, &pos);
|
||||||
|
|
||||||
|
encodeAndFoldText(os, vmime::text(word(m_text, charset())), maxLineLength,
|
||||||
|
pos, newLinePos, encodeAndFoldFlags::forceNoEncoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
defaultField& defaultField::operator=(const string& text)
|
||||||
|
{
|
||||||
|
m_text = text;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void defaultField::copyFrom(const headerField& field)
|
||||||
|
{
|
||||||
|
const defaultField& source = dynamic_cast<const defaultField&>(field);
|
||||||
|
m_text = source.m_text;
|
||||||
|
|
||||||
|
headerField::copyFrom(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
70
src/defaultField.hpp
Normal file
70
src/defaultField.hpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_DEFAULTFIELD_HPP_INCLUDED
|
||||||
|
#define VMIME_DEFAULTFIELD_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
#include "headerFieldFactory.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class defaultField : public headerField
|
||||||
|
{
|
||||||
|
friend class headerFieldFactory;
|
||||||
|
friend class headerFieldFactory::registerer <defaultField>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
defaultField();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void copyFrom(const headerField& field);
|
||||||
|
|
||||||
|
defaultField& operator=(const string& text);
|
||||||
|
|
||||||
|
const string& value() const { return (m_text); }
|
||||||
|
string& value() { return (m_text); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
string m_text;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using headerField::parse;
|
||||||
|
using headerField::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_DEFAULTFIELD_HPP_INCLUDED
|
117
src/defaultParameter.cpp
Normal file
117
src/defaultParameter.cpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "defaultParameter.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
void defaultParameter::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
parseValue(buffer, position, end);
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void defaultParameter::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
string::size_type pos = curLinePos;
|
||||||
|
|
||||||
|
const string value = quotedValue();
|
||||||
|
|
||||||
|
pos += m_name.length() + value.length() + 2;
|
||||||
|
|
||||||
|
if (pos > maxLineLength)
|
||||||
|
{
|
||||||
|
os << NEW_LINE_SEQUENCE;
|
||||||
|
pos = NEW_LINE_SEQUENCE_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
os << m_name << "=" << value;
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
*newLinePos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string defaultParameter::quotedValue() const
|
||||||
|
{
|
||||||
|
const string value(generateValue());
|
||||||
|
|
||||||
|
std::ostringstream ss;
|
||||||
|
string::const_iterator start = value.begin();
|
||||||
|
bool quoted = false;
|
||||||
|
|
||||||
|
for (string::const_iterator i = value.begin() ; i != value.end() ; ++i)
|
||||||
|
{
|
||||||
|
switch (*i)
|
||||||
|
{
|
||||||
|
// Characters that need to be quoted _and_ escaped
|
||||||
|
case '"':
|
||||||
|
case '\\':
|
||||||
|
|
||||||
|
ss << string(start, i) << "\\" << *i;
|
||||||
|
|
||||||
|
start = i + 1;
|
||||||
|
quoted = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Other characters that need quoting
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
case '(':
|
||||||
|
case ')':
|
||||||
|
case '<':
|
||||||
|
case '>':
|
||||||
|
case '@':
|
||||||
|
case ',':
|
||||||
|
case ';':
|
||||||
|
case ':':
|
||||||
|
case '/':
|
||||||
|
case '[':
|
||||||
|
case ']':
|
||||||
|
case '?':
|
||||||
|
case '=':
|
||||||
|
|
||||||
|
quoted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start != value.end())
|
||||||
|
ss << string(start, value.end());
|
||||||
|
|
||||||
|
return (quoted ? ("\"" + ss.str() + "\"") : (ss.str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void defaultParameter::copyFrom(const parameter& param)
|
||||||
|
{
|
||||||
|
parameter::copyFrom(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
55
src/defaultParameter.hpp
Normal file
55
src/defaultParameter.hpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_DEFAULTPARAMETER_HPP_INCLUDED
|
||||||
|
#define VMIME_DEFAULTPARAMETER_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "parameter.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class defaultParameter : public parameter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void copyFrom(const parameter& param);
|
||||||
|
|
||||||
|
virtual void parseValue(const string& buffer, const string::size_type position, const string::size_type end) = 0;
|
||||||
|
virtual const string generateValue() const = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const string quotedValue() const;
|
||||||
|
|
||||||
|
// No need to override these in class that derive from "defaultParameter".
|
||||||
|
// "defaultParameter" provides a default handling for value parsing/building.
|
||||||
|
// Instead, you must define two functions: "parseValue" and "generateValue" (see above).
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_DEFAULTPARAMETER_HPP_INCLUDED
|
62
src/defaultParameterizedHeaderField.cpp
Normal file
62
src/defaultParameterizedHeaderField.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "defaultParameterizedHeaderField.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
defaultParameterizedHeaderField::defaultParameterizedHeaderField()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void defaultParameterizedHeaderField::parseValue(const string& buffer,
|
||||||
|
const string::size_type position, const string::size_type end)
|
||||||
|
{
|
||||||
|
m_value = string(buffer.begin() + position, buffer.begin() + end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string defaultParameterizedHeaderField::generateValue() const
|
||||||
|
{
|
||||||
|
return (m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void defaultParameterizedHeaderField::copyFrom(const headerField& field)
|
||||||
|
{
|
||||||
|
const defaultParameterizedHeaderField& source = dynamic_cast
|
||||||
|
<const defaultParameterizedHeaderField&>(field);
|
||||||
|
m_value = source.m_value;
|
||||||
|
|
||||||
|
parameterizedHeaderField::copyFrom(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
defaultParameterizedHeaderField& defaultParameterizedHeaderField::operator=(const string& value)
|
||||||
|
{
|
||||||
|
m_value = value;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
63
src/defaultParameterizedHeaderField.hpp
Normal file
63
src/defaultParameterizedHeaderField.hpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_DEFAULTPARAMETERIZEDHEADERFIELD_HPP_INCLUDED
|
||||||
|
#define VMIME_DEFAULTPARAMETERIZEDHEADERFIELD_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "parameterizedHeaderField.hpp"
|
||||||
|
#include "base.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class defaultParameterizedHeaderField : public parameterizedHeaderField
|
||||||
|
{
|
||||||
|
friend class headerFieldFactory::registerer <defaultParameterizedHeaderField>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
defaultParameterizedHeaderField();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void copyFrom(const headerField& field);
|
||||||
|
|
||||||
|
defaultParameterizedHeaderField& operator=(const string& value);
|
||||||
|
|
||||||
|
const string& value() const { return (m_value); }
|
||||||
|
string& value() { return (m_value); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
string m_value;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void parseValue(const string& buffer, const string::size_type position, const string::size_type end);
|
||||||
|
const string generateValue() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_DEFAULTPARAMETERIZEDHEADERFIELD_HPP_INCLUDED
|
91
src/disposition.cpp
Normal file
91
src/disposition.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "disposition.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
disposition::disposition()
|
||||||
|
: m_name(dispositionTypes::INLINE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
disposition::disposition(const string& name)
|
||||||
|
: m_name(toLower(name))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
disposition::disposition(const disposition& type)
|
||||||
|
: component(), m_name(type.m_name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void disposition::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
m_name = toLower(string(buffer.begin() + position, buffer.begin() + end));
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void disposition::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
os << m_name;
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
*newLinePos = curLinePos + m_name.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
disposition& disposition::operator=(const disposition& source)
|
||||||
|
{
|
||||||
|
m_name = source.m_name;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
disposition& disposition::operator=(const string& name)
|
||||||
|
{
|
||||||
|
m_name = toLower(name);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool disposition::operator==(const disposition& value) const
|
||||||
|
{
|
||||||
|
return (toLower(m_name) == value.m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool disposition::operator!=(const disposition& value) const
|
||||||
|
{
|
||||||
|
return !(*this == value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
74
src/disposition.hpp
Normal file
74
src/disposition.hpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_DISPOSITION_HPP_INCLUDED
|
||||||
|
#define VMIME_DISPOSITION_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** Content disposition (basic type).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class disposition : public component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
disposition();
|
||||||
|
disposition(const string& name);
|
||||||
|
disposition(const disposition& disp);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const string& name() const { return (m_name); }
|
||||||
|
string& name() { return (m_name); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
disposition& operator=(const disposition& source);
|
||||||
|
disposition& operator=(const string& name);
|
||||||
|
|
||||||
|
const bool operator==(const disposition& value) const;
|
||||||
|
const bool operator!=(const disposition& value) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
string m_name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using component::parse;
|
||||||
|
using component::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_DISPOSITION_HPP_INCLUDED
|
69
src/encoder.cpp
Normal file
69
src/encoder.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "encoder.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
encoder::encoder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encoder::~encoder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const propertySet& encoder::properties() const
|
||||||
|
{
|
||||||
|
return (m_props);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
propertySet& encoder::properties()
|
||||||
|
{
|
||||||
|
return (m_props);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const propertySet& encoder::results() const
|
||||||
|
{
|
||||||
|
return (m_results);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
propertySet& encoder::results()
|
||||||
|
{
|
||||||
|
return (m_results);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector <string> encoder::availableProperties() const
|
||||||
|
{
|
||||||
|
std::vector <string> list;
|
||||||
|
return (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
95
src/encoder.hpp
Normal file
95
src/encoder.hpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ENCODER_HPP_INCLUDED
|
||||||
|
#define VMIME_ENCODER_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "propertySet.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class encoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
encoder();
|
||||||
|
virtual ~encoder();
|
||||||
|
|
||||||
|
/** Encode data.
|
||||||
|
*
|
||||||
|
* @param in input data (decoded)
|
||||||
|
* @param out output stream for encoded data
|
||||||
|
* @return number of bytes written into output stream
|
||||||
|
*/
|
||||||
|
virtual const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out) = 0;
|
||||||
|
|
||||||
|
/** Decode data.
|
||||||
|
*
|
||||||
|
* @param in input data (encoded)
|
||||||
|
* @param out output stream for decoded data
|
||||||
|
* @return number of bytes written into output stream
|
||||||
|
*/
|
||||||
|
virtual const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out) = 0;
|
||||||
|
|
||||||
|
/** Return the properties of the encoder.
|
||||||
|
*
|
||||||
|
* @return properties of the encoder
|
||||||
|
*/
|
||||||
|
const propertySet& properties() const;
|
||||||
|
|
||||||
|
/** Return the properties of the encoder.
|
||||||
|
*
|
||||||
|
* @return properties of the encoder
|
||||||
|
*/
|
||||||
|
propertySet& properties();
|
||||||
|
|
||||||
|
/** Return a list of property names that can be set for
|
||||||
|
* this encoder.
|
||||||
|
*
|
||||||
|
* @return list of property names
|
||||||
|
*/
|
||||||
|
virtual const std::vector <string> availableProperties() const;
|
||||||
|
|
||||||
|
/** Return the results returned by this encoder.
|
||||||
|
*
|
||||||
|
* @return results returned by the encoder
|
||||||
|
*/
|
||||||
|
const propertySet& results() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
propertySet& results();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
propertySet m_props;
|
||||||
|
propertySet m_results;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ENCODER_HPP_INCLUDED
|
32
src/encoder7bit.cpp
Normal file
32
src/encoder7bit.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "encoder7bit.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
encoder7bit::encoder7bit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
45
src/encoder7bit.hpp
Normal file
45
src/encoder7bit.hpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ENCODER7BIT_HPP_INCLUDED
|
||||||
|
#define VMIME_ENCODER7BIT_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "encoderDefault.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** 7-bit encoder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class encoder7bit : public encoderDefault
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
encoder7bit();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ENCODER7BIT_HPP_INCLUDED
|
32
src/encoder8bit.cpp
Normal file
32
src/encoder8bit.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "encoder8bit.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
encoder8bit::encoder8bit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
45
src/encoder8bit.hpp
Normal file
45
src/encoder8bit.hpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ENCODER8BIT_HPP_INCLUDED
|
||||||
|
#define VMIME_ENCODER8BIT_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "encoderDefault.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** 8-bit encoder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class encoder8bit : public encoderDefault
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
encoder8bit();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ENCODER8BIT_HPP_INCLUDED
|
265
src/encoderB64.cpp
Normal file
265
src/encoderB64.cpp
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "encoderB64.hpp"
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
encoderB64::encoderB64()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector <string> encoderB64::availableProperties() const
|
||||||
|
{
|
||||||
|
std::vector <string> list(encoder::availableProperties());
|
||||||
|
|
||||||
|
list.push_back("maxlinelength");
|
||||||
|
|
||||||
|
return (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 7-bits alphabet used to encode binary data
|
||||||
|
const unsigned char encoderB64::sm_alphabet[] =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||||
|
|
||||||
|
const unsigned char encoderB64::sm_decodeMap[256] =
|
||||||
|
{
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0x00 - 0x0f
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0x10 - 0x1f
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3e,0xff,0xff,0xff,0x3f, // 0x20 - 0x2f
|
||||||
|
0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0xff,0xff,0xff,0x3d,0xff,0xff, // 0x30 - 0x3f
|
||||||
|
0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, // 0x40 - 0x4f
|
||||||
|
0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0xff,0xff,0xff,0xff,0xff, // 0x50 - 0x5f
|
||||||
|
0xff,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28, // 0x60 - 0x6f
|
||||||
|
0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0xff,0xff,0xff,0xff, // 0x70 - 0x7f
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0x80 - 0x8f
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0x90 - 0x9f
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0xa0 - 0xaf
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0xb0 - 0xbf
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0xc0 - 0xcf
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0xd0 - 0xdf
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0xe0 - 0xef
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0xf0 - 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const utility::stream::size_type encoderB64::encode(utility::inputStream& in, utility::outputStream& out)
|
||||||
|
{
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
const int propMaxLineLength = properties().get <int>("maxlinelength", -1);
|
||||||
|
|
||||||
|
const bool cutLines = (propMaxLineLength != -1);
|
||||||
|
const int maxLineLength = std::min(propMaxLineLength, 76);
|
||||||
|
|
||||||
|
// Process data
|
||||||
|
utility::stream::value_type buffer[65536];
|
||||||
|
utility::stream::size_type bufferLength = 0;
|
||||||
|
utility::stream::size_type bufferPos = 0;
|
||||||
|
|
||||||
|
unsigned char bytes[3];
|
||||||
|
unsigned char output[4];
|
||||||
|
|
||||||
|
utility::stream::size_type total = 0;
|
||||||
|
|
||||||
|
int curCol = 0;
|
||||||
|
|
||||||
|
while (bufferPos < bufferLength || !in.eof())
|
||||||
|
{
|
||||||
|
if (bufferPos >= bufferLength)
|
||||||
|
{
|
||||||
|
bufferLength = in.read(buffer, sizeof(buffer));
|
||||||
|
bufferPos = 0;
|
||||||
|
|
||||||
|
if (bufferLength == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 3 bytes of data
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
while (count < 3 && bufferPos < bufferLength)
|
||||||
|
bytes[count++] = buffer[bufferPos++];
|
||||||
|
|
||||||
|
if (count != 3)
|
||||||
|
{
|
||||||
|
// There may be more data in the next chunk...
|
||||||
|
if (bufferPos >= bufferLength)
|
||||||
|
{
|
||||||
|
bufferLength = in.read(buffer, sizeof(buffer));
|
||||||
|
bufferPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (count < 3 && bufferPos < bufferLength)
|
||||||
|
bytes[count++] = buffer[bufferPos++];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode data
|
||||||
|
switch (count)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
|
||||||
|
output[0] = sm_alphabet[(bytes[0] & 0xFC) >> 2];
|
||||||
|
output[1] = sm_alphabet[(bytes[0] & 0x03) << 4];
|
||||||
|
output[2] = sm_alphabet[64]; // padding
|
||||||
|
output[3] = sm_alphabet[64]; // padding
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
|
||||||
|
output[0] = sm_alphabet[(bytes[0] & 0xFC) >> 2];
|
||||||
|
output[1] = sm_alphabet[((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xF0) >> 4)];
|
||||||
|
output[2] = sm_alphabet[(bytes[1] & 0x0F) << 2];
|
||||||
|
output[3] = sm_alphabet[64]; // padding
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
case 3:
|
||||||
|
|
||||||
|
output[0] = sm_alphabet[(bytes[0] & 0xFC) >> 2];
|
||||||
|
output[1] = sm_alphabet[((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xF0) >> 4)];
|
||||||
|
output[2] = sm_alphabet[((bytes[1] & 0x0F) << 2) | ((bytes[2] & 0xC0) >> 6)];
|
||||||
|
output[3] = sm_alphabet[(bytes[2] & 0x3F)];
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write encoded data to output stream
|
||||||
|
out.write((char*) output, 4);
|
||||||
|
|
||||||
|
total += 4;
|
||||||
|
curCol += 4;
|
||||||
|
|
||||||
|
if (cutLines && curCol >= maxLineLength - 1)
|
||||||
|
{
|
||||||
|
out.write("\r\n", 2);
|
||||||
|
curCol = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (total);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const utility::stream::size_type encoderB64::decode(utility::inputStream& in, utility::outputStream& out)
|
||||||
|
{
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
// Process the data
|
||||||
|
char buffer[16384];
|
||||||
|
int bufferLength = 0;
|
||||||
|
int bufferPos = 0;
|
||||||
|
|
||||||
|
utility::stream::size_type total = 0;
|
||||||
|
|
||||||
|
unsigned char bytes[4];
|
||||||
|
unsigned char output[3];
|
||||||
|
|
||||||
|
while (bufferPos < bufferLength || !in.eof())
|
||||||
|
{
|
||||||
|
// Need to get more data?
|
||||||
|
if (bufferPos >= bufferLength)
|
||||||
|
{
|
||||||
|
bufferLength = in.read(buffer, sizeof(buffer));
|
||||||
|
bufferPos = 0;
|
||||||
|
|
||||||
|
// No more data
|
||||||
|
if (bufferLength == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 bytes of input provide 3 bytes of output, so
|
||||||
|
// get the next 4 bytes from the input stream.
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
while (count < 4 && bufferPos < bufferLength)
|
||||||
|
{
|
||||||
|
const unsigned char c = buffer[bufferPos++];
|
||||||
|
|
||||||
|
if (!isspace(c))
|
||||||
|
bytes[count++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count != 4)
|
||||||
|
{
|
||||||
|
while (count < 4 && !in.eof())
|
||||||
|
{
|
||||||
|
// Data continues on the next chunk
|
||||||
|
bufferLength = in.read(buffer, sizeof(buffer));
|
||||||
|
bufferPos = 0;
|
||||||
|
|
||||||
|
while (count < 4 && bufferPos < bufferLength)
|
||||||
|
{
|
||||||
|
const unsigned char c = buffer[bufferPos++];
|
||||||
|
|
||||||
|
if (!isspace(c))
|
||||||
|
bytes[count++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the bytes
|
||||||
|
unsigned char c1 = bytes[0];
|
||||||
|
unsigned char c2 = bytes[1];
|
||||||
|
|
||||||
|
if (c1 == '=' || c2 == '=') // end
|
||||||
|
break;
|
||||||
|
|
||||||
|
output[0] = (unsigned char)((sm_decodeMap[c1] << 2) | ((sm_decodeMap[c2] & 0x30) >> 4));
|
||||||
|
|
||||||
|
c1 = bytes[2];
|
||||||
|
|
||||||
|
if (c1 == '=') // end
|
||||||
|
{
|
||||||
|
out.write((char*) output, 1);
|
||||||
|
total += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
output[1] = (unsigned char)(((sm_decodeMap[c2] & 0xf) << 4) | ((sm_decodeMap[c1] & 0x3c) >> 2));
|
||||||
|
|
||||||
|
c2 = bytes[3];
|
||||||
|
|
||||||
|
if (c2 == '=') // end
|
||||||
|
{
|
||||||
|
out.write((char*) output, 2);
|
||||||
|
total += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
output[2] = (unsigned char)(((sm_decodeMap[c1] & 0x03) << 6) | sm_decodeMap[c2]);
|
||||||
|
|
||||||
|
out.write((char*) output, 3);
|
||||||
|
total += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (total);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
55
src/encoderB64.hpp
Normal file
55
src/encoderB64.hpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ENCODERB64_HPP_INCLUDED
|
||||||
|
#define VMIME_ENCODERB64_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "encoder.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** Base64 encoder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class encoderB64 : public encoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
encoderB64();
|
||||||
|
|
||||||
|
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out);
|
||||||
|
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out);
|
||||||
|
|
||||||
|
const std::vector <string> availableProperties() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
static const unsigned char sm_alphabet[];
|
||||||
|
static const unsigned char sm_decodeMap[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ENCODERB64_HPP_INCLUDED
|
32
src/encoderBinary.cpp
Normal file
32
src/encoderBinary.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "encoderBinary.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
encoderBinary::encoderBinary()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
45
src/encoderBinary.hpp
Normal file
45
src/encoderBinary.hpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ENCODERBINARY_HPP_INCLUDED
|
||||||
|
#define VMIME_ENCODERBINARY_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "encoderDefault.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** Binary encoder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class encoderBinary : public encoderDefault
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
encoderBinary();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ENCODERBINARY_HPP_INCLUDED
|
50
src/encoderDefault.cpp
Normal file
50
src/encoderDefault.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "encoderDefault.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
encoderDefault::encoderDefault()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const utility::stream::size_type encoderDefault::encode(utility::inputStream& in, utility::outputStream& out)
|
||||||
|
{
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
// No encoding performed
|
||||||
|
return (utility::bufferedStreamCopy(in, out));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const utility::stream::size_type encoderDefault::decode(utility::inputStream& in, utility::outputStream& out)
|
||||||
|
{
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
// No decoding performed
|
||||||
|
return (utility::bufferedStreamCopy(in, out));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
48
src/encoderDefault.hpp
Normal file
48
src/encoderDefault.hpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ENCODERDEFAULT_HPP_INCLUDED
|
||||||
|
#define VMIME_ENCODERDEFAULT_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "encoder.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** Default encoder (simple copy, no encoding/decoding is performed).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class encoderDefault : public encoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
encoderDefault();
|
||||||
|
|
||||||
|
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out);
|
||||||
|
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ENCODERDEFAUL_HPP_INCLUDED
|
70
src/encoderFactory.cpp
Normal file
70
src/encoderFactory.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "encoderFactory.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
|
||||||
|
#include "encoderB64.hpp"
|
||||||
|
#include "encoderQP.hpp"
|
||||||
|
#include "encoderUUE.hpp"
|
||||||
|
#include "encoderBinary.hpp"
|
||||||
|
#include "encoder7bit.hpp"
|
||||||
|
#include "encoder8bit.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
encoderFactory::encoderFactory()
|
||||||
|
{
|
||||||
|
// Register some default encoders
|
||||||
|
registerName <encoderB64>("base64");
|
||||||
|
registerName <encoderQP>("quoted-printable");
|
||||||
|
registerName <encoderUUE>("uuencode");
|
||||||
|
registerName <encoder7bit>("7bit");
|
||||||
|
registerName <encoder8bit>("8bit");
|
||||||
|
registerName <encoderBinary>("binary");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encoderFactory::~encoderFactory()
|
||||||
|
{
|
||||||
|
for (NameMap::iterator it = m_nameMap.begin() ; it != m_nameMap.end() ; ++it)
|
||||||
|
delete ((*it).second);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encoder* encoderFactory::create(const string& name)
|
||||||
|
{
|
||||||
|
NameMap::const_iterator pos = m_nameMap.find(toLower(name));
|
||||||
|
|
||||||
|
if (pos != m_nameMap.end())
|
||||||
|
{
|
||||||
|
return ((*pos).second)->create();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw exceptions::no_encoder_available();
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
183
src/encoderFactory.hpp
Normal file
183
src/encoderFactory.hpp
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ENCODERFACTORY_HPP_INCLUDED
|
||||||
|
#define VMIME_ENCODERFACTORY_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "encoder.hpp"
|
||||||
|
#include "utility/singleton.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** A factory to create 'encoder' objects for the specified encoding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class encoderFactory : public utility::singleton <encoderFactory>
|
||||||
|
{
|
||||||
|
friend class utility::singleton <encoderFactory>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
encoderFactory();
|
||||||
|
~encoderFactory();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
class registeredEncoder
|
||||||
|
{
|
||||||
|
friend class encoderFactory;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual ~registeredEncoder() { }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual encoder* create() = 0;
|
||||||
|
|
||||||
|
virtual const string& name() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
template <class E>
|
||||||
|
class registeredEncoderImpl : public registeredEncoder
|
||||||
|
{
|
||||||
|
friend class encoderFactory;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
registeredEncoderImpl(const string& name) : m_name(name) { }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
encoder* create()
|
||||||
|
{
|
||||||
|
return new E;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string& name() const
|
||||||
|
{
|
||||||
|
return (m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const string m_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::map <string, registeredEncoder*> NameMap;
|
||||||
|
NameMap m_nameMap;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
template <class E>
|
||||||
|
void registerName(const string& name)
|
||||||
|
{
|
||||||
|
const string _name = toLower(name);
|
||||||
|
m_nameMap.insert(NameMap::value_type(_name,
|
||||||
|
new registeredEncoderImpl <E>(_name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder* create(const string& name);
|
||||||
|
|
||||||
|
const registeredEncoder& operator[](const string& name) const;
|
||||||
|
|
||||||
|
|
||||||
|
class iterator;
|
||||||
|
|
||||||
|
class const_iterator
|
||||||
|
{
|
||||||
|
friend class encoderFactory;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const_iterator() { }
|
||||||
|
const_iterator(const const_iterator& it) : m_it(it.m_it) { }
|
||||||
|
const_iterator(const iterator& it) : m_it(it.m_it) { }
|
||||||
|
|
||||||
|
const_iterator& operator=(const const_iterator& it) { m_it = it.m_it; return (*this); }
|
||||||
|
|
||||||
|
const registeredEncoder& operator*() const { return (*(*m_it).second); }
|
||||||
|
const registeredEncoder* operator->() const { return ((*m_it).second); }
|
||||||
|
|
||||||
|
const_iterator& operator++() { ++m_it; return (*this); }
|
||||||
|
const_iterator operator++(int) { return (m_it++); }
|
||||||
|
|
||||||
|
const_iterator& operator--() { --m_it; return (*this); }
|
||||||
|
const_iterator operator--(int) { return (m_it--); }
|
||||||
|
|
||||||
|
const bool operator==(const const_iterator& it) const { return (m_it == it.m_it); }
|
||||||
|
const bool operator!=(const const_iterator& it) const { return (m_it != it.m_it); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const_iterator(const NameMap::const_iterator it) : m_it(it) { }
|
||||||
|
|
||||||
|
NameMap::const_iterator m_it;
|
||||||
|
};
|
||||||
|
|
||||||
|
class iterator
|
||||||
|
{
|
||||||
|
friend class encoderFactory;
|
||||||
|
friend class encoderFactory::const_iterator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
iterator() { }
|
||||||
|
iterator(const iterator& it) : m_it(it.m_it) { }
|
||||||
|
|
||||||
|
iterator& operator=(const iterator& it) { m_it = it.m_it; return (*this); }
|
||||||
|
|
||||||
|
registeredEncoder& operator*() const { return (*(*m_it).second); }
|
||||||
|
registeredEncoder* operator->() const { return ((*m_it).second); }
|
||||||
|
|
||||||
|
iterator& operator++() { ++m_it; return (*this); }
|
||||||
|
iterator operator++(int) { return (m_it++); }
|
||||||
|
|
||||||
|
iterator& operator--() { --m_it; return (*this); }
|
||||||
|
iterator operator--(int) { return (m_it--); }
|
||||||
|
|
||||||
|
const bool operator==(const iterator& it) const { return (m_it == it.m_it); }
|
||||||
|
const bool operator!=(const iterator& it) const { return (m_it != it.m_it); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
iterator(const NameMap::iterator it) : m_it(it) { }
|
||||||
|
|
||||||
|
NameMap::iterator m_it;
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator begin() { return iterator(m_nameMap.begin()); }
|
||||||
|
iterator end() { return iterator(m_nameMap.end()); }
|
||||||
|
|
||||||
|
const_iterator begin() const { return const_iterator(m_nameMap.begin()); }
|
||||||
|
const_iterator end() const { return const_iterator(m_nameMap.end()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ENCODERFACTORY_HPP_INCLUDED
|
422
src/encoderQP.cpp
Normal file
422
src/encoderQP.cpp
Normal file
@ -0,0 +1,422 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "encoderQP.hpp"
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
encoderQP::encoderQP()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector <string> encoderQP::availableProperties() const
|
||||||
|
{
|
||||||
|
std::vector <string> list(encoder::availableProperties());
|
||||||
|
|
||||||
|
list.push_back("maxlinelength");
|
||||||
|
|
||||||
|
list.push_back("text"); // if set, '\r' and '\n' are not hex-encoded.
|
||||||
|
// WARNING! You should not use this for binary data!
|
||||||
|
|
||||||
|
list.push_back("rfc2047"); // for header fields encoding (RFC #2047)
|
||||||
|
|
||||||
|
return (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Encoding table
|
||||||
|
const unsigned char encoderQP::sm_hexDigits[] = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
// Decoding table
|
||||||
|
const unsigned char encoderQP::sm_hexDecodeTable[256] =
|
||||||
|
{
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define QP_ENCODE_HEX(x) \
|
||||||
|
outBuffer[outBufferPos] = '='; \
|
||||||
|
outBuffer[outBufferPos + 1] = sm_hexDigits[x >> 4]; \
|
||||||
|
outBuffer[outBufferPos + 2] = sm_hexDigits[x & 0xF]; \
|
||||||
|
outBufferPos += 3; \
|
||||||
|
curCol += 3;
|
||||||
|
|
||||||
|
|
||||||
|
const utility::stream::size_type encoderQP::encode(utility::inputStream& in, utility::outputStream& out)
|
||||||
|
{
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
const string::size_type propMaxLineLength =
|
||||||
|
properties().get <string::size_type>("maxlinelength", (string::size_type) -1);
|
||||||
|
|
||||||
|
const bool rfc2047 = properties().get <bool>("rfc2047", false);
|
||||||
|
const bool text = properties().get <bool>("text", false); // binary mode by default
|
||||||
|
|
||||||
|
const bool cutLines = (propMaxLineLength != (string::size_type) -1);
|
||||||
|
const string::size_type maxLineLength = std::min(propMaxLineLength, (string::size_type) 74);
|
||||||
|
|
||||||
|
// Process the data
|
||||||
|
char buffer[16384];
|
||||||
|
int bufferLength = 0;
|
||||||
|
int bufferPos = 0;
|
||||||
|
|
||||||
|
string::size_type curCol = 0;
|
||||||
|
|
||||||
|
unsigned char outBuffer[16384];
|
||||||
|
int outBufferPos = 0;
|
||||||
|
|
||||||
|
utility::stream::size_type total = 0;
|
||||||
|
|
||||||
|
while (bufferPos < bufferLength || !in.eof())
|
||||||
|
{
|
||||||
|
// Flush current output buffer
|
||||||
|
if (outBufferPos + 6 >= (int) sizeof(outBuffer))
|
||||||
|
{
|
||||||
|
out.write((char*) outBuffer, outBufferPos);
|
||||||
|
|
||||||
|
total += outBufferPos;
|
||||||
|
outBufferPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to get more data?
|
||||||
|
if (bufferPos >= bufferLength)
|
||||||
|
{
|
||||||
|
bufferLength = in.read(buffer, sizeof(buffer));
|
||||||
|
bufferPos = 0;
|
||||||
|
|
||||||
|
// No more data
|
||||||
|
if (bufferLength == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next char and encode it
|
||||||
|
const unsigned char c = (unsigned char) buffer[bufferPos++];
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '.':
|
||||||
|
{
|
||||||
|
if (!rfc2047 && curCol == 0)
|
||||||
|
{
|
||||||
|
// If a '.' appears at the beginning of a line, we encode it to
|
||||||
|
// to avoid problems with SMTP servers... ("\r\n.\r\n" means the
|
||||||
|
// end of data transmission).
|
||||||
|
QP_ENCODE_HEX('.')
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
outBuffer[outBufferPos++] = '.';
|
||||||
|
++curCol;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ' ':
|
||||||
|
{
|
||||||
|
// RFC-2047, Page 5, 4.2. The "Q" encoding:
|
||||||
|
// << The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be
|
||||||
|
// represented as "_" (underscore, ASCII 95.). >>
|
||||||
|
if (rfc2047)
|
||||||
|
{
|
||||||
|
outBuffer[outBufferPos++] = ' ';
|
||||||
|
++curCol;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Need to get more data?
|
||||||
|
if (bufferPos >= bufferLength)
|
||||||
|
{
|
||||||
|
bufferLength = in.read(buffer, sizeof(buffer));
|
||||||
|
bufferPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spaces cannot appear at the end of a line. So, encode the space.
|
||||||
|
if (bufferPos >= bufferLength ||
|
||||||
|
(buffer[bufferPos] == '\r' || buffer[bufferPos] == '\n'))
|
||||||
|
{
|
||||||
|
QP_ENCODE_HEX(' ');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outBuffer[outBufferPos++] = ' ';
|
||||||
|
++curCol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '\t':
|
||||||
|
{
|
||||||
|
QP_ENCODE_HEX(c)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
{
|
||||||
|
// Text mode (where using CRLF or LF or ... does not
|
||||||
|
// care for a new line...)
|
||||||
|
if (text)
|
||||||
|
{
|
||||||
|
outBuffer[outBufferPos++] = c;
|
||||||
|
++curCol;
|
||||||
|
}
|
||||||
|
// Binary mode (where CR and LF bytes are important!)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QP_ENCODE_HEX(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '=':
|
||||||
|
{
|
||||||
|
QP_ENCODE_HEX('=')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ',':
|
||||||
|
case ';':
|
||||||
|
case ':':
|
||||||
|
case '_':
|
||||||
|
{
|
||||||
|
if (rfc2047)
|
||||||
|
{
|
||||||
|
QP_ENCODE_HEX(c)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outBuffer[outBufferPos++] = c;
|
||||||
|
++curCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Rule #2: (Literal representation) Octets with decimal values of 33
|
||||||
|
through 60 inclusive, and 62 through 126, inclusive, MAY be
|
||||||
|
represented as the ASCII characters which correspond to those
|
||||||
|
octets (EXCLAMATION POINT through LESS THAN, and GREATER THAN
|
||||||
|
through TILDE, respectively).
|
||||||
|
*/
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
//if ((c >= 33 && c <= 60) || (c >= 62 && c <= 126))
|
||||||
|
if (c >= 33 && c <= 126 && c != 61)
|
||||||
|
{
|
||||||
|
outBuffer[outBufferPos++] = c;
|
||||||
|
++curCol;
|
||||||
|
}
|
||||||
|
// Other characters: '=' + hexadecimal encoding
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QP_ENCODE_HEX(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Soft line break : "=\r\n"
|
||||||
|
if (cutLines && curCol >= maxLineLength - 1)
|
||||||
|
{
|
||||||
|
outBuffer[outBufferPos] = '=';
|
||||||
|
outBuffer[outBufferPos + 1] = '\r';
|
||||||
|
outBuffer[outBufferPos + 2] = '\n';
|
||||||
|
|
||||||
|
outBufferPos += 3;
|
||||||
|
curCol = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush remaining output buffer
|
||||||
|
if (outBufferPos != 0)
|
||||||
|
{
|
||||||
|
out.write((char*) outBuffer, outBufferPos);
|
||||||
|
total += outBufferPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (total);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const utility::stream::size_type encoderQP::decode(utility::inputStream& in, utility::outputStream& out)
|
||||||
|
{
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
// Process the data
|
||||||
|
const bool rfc2047 = properties().get <bool>("rfc2047", false);
|
||||||
|
|
||||||
|
char buffer[16384];
|
||||||
|
int bufferLength = 0;
|
||||||
|
int bufferPos = 0;
|
||||||
|
|
||||||
|
unsigned char outBuffer[16384];
|
||||||
|
int outBufferPos = 0;
|
||||||
|
|
||||||
|
utility::stream::size_type total = 0;
|
||||||
|
|
||||||
|
while (bufferPos < bufferLength || !in.eof())
|
||||||
|
{
|
||||||
|
// Flush current output buffer
|
||||||
|
if (outBufferPos >= (int) sizeof(outBuffer))
|
||||||
|
{
|
||||||
|
out.write((char*) outBuffer, outBufferPos);
|
||||||
|
|
||||||
|
total += outBufferPos;
|
||||||
|
outBufferPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to get more data?
|
||||||
|
if (bufferPos >= bufferLength)
|
||||||
|
{
|
||||||
|
bufferLength = in.read(buffer, sizeof(buffer));
|
||||||
|
bufferPos = 0;
|
||||||
|
|
||||||
|
// No more data
|
||||||
|
if (bufferLength == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the next sequence (hex-encoded byte or printable character)
|
||||||
|
unsigned char c = (unsigned char) buffer[bufferPos++];
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
{
|
||||||
|
if (bufferPos >= bufferLength)
|
||||||
|
{
|
||||||
|
bufferLength = in.read(buffer, sizeof(buffer));
|
||||||
|
bufferPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufferPos < bufferLength)
|
||||||
|
{
|
||||||
|
c = (unsigned char) buffer[bufferPos++];
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
// Ignore soft line break ("=\r\n" or "=\n")
|
||||||
|
case '\r':
|
||||||
|
|
||||||
|
// Read one byte more
|
||||||
|
if (bufferPos >= bufferLength)
|
||||||
|
{
|
||||||
|
bufferLength = in.read(buffer, sizeof(buffer));
|
||||||
|
bufferPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufferPos < bufferLength)
|
||||||
|
++bufferPos;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Hex-encoded char
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// We need another byte...
|
||||||
|
if (bufferPos >= bufferLength)
|
||||||
|
{
|
||||||
|
bufferLength = in.read(buffer, sizeof(buffer));
|
||||||
|
bufferPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufferPos < bufferLength)
|
||||||
|
{
|
||||||
|
const unsigned char next = (unsigned char) buffer[bufferPos++];
|
||||||
|
|
||||||
|
const unsigned char value =
|
||||||
|
sm_hexDecodeTable[c] * 16
|
||||||
|
+ sm_hexDecodeTable[next];
|
||||||
|
|
||||||
|
outBuffer[outBufferPos++] = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Premature end-of-data
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Premature end-of-data
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '_':
|
||||||
|
{
|
||||||
|
if (rfc2047)
|
||||||
|
{
|
||||||
|
// RFC-2047, Page 5, 4.2. The "Q" encoding:
|
||||||
|
// << Note that the "_" always represents hexadecimal 20, even if the SPACE
|
||||||
|
// character occupies a different code position in the character set in use. >>
|
||||||
|
outBuffer[outBufferPos++] = 0x20;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no break here...
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
outBuffer[outBufferPos++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush remaining output buffer
|
||||||
|
if (outBufferPos != 0)
|
||||||
|
{
|
||||||
|
out.write((char*) outBuffer, outBufferPos);
|
||||||
|
total += outBufferPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (total);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
55
src/encoderQP.hpp
Normal file
55
src/encoderQP.hpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ENCODERQP_HPP_INCLUDED
|
||||||
|
#define VMIME_ENCODERQP_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "encoder.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** Quoted-printable encoder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class encoderQP : public encoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
encoderQP();
|
||||||
|
|
||||||
|
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out);
|
||||||
|
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out);
|
||||||
|
|
||||||
|
const std::vector <string> availableProperties() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
static const unsigned char sm_hexDigits[17];
|
||||||
|
static const unsigned char sm_hexDecodeTable[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ENCODERQP_HPP_INCLUDED
|
289
src/encoderUUE.cpp
Normal file
289
src/encoderUUE.cpp
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "encoderUUE.hpp"
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
encoderUUE::encoderUUE()
|
||||||
|
{
|
||||||
|
properties()["mode"] = 644;
|
||||||
|
properties()["filename"] = "no_name";
|
||||||
|
properties()["maxlinelength"] = 46;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector <string> encoderUUE::availableProperties() const
|
||||||
|
{
|
||||||
|
std::vector <string> list(encoder::availableProperties());
|
||||||
|
|
||||||
|
list.push_back("maxlinelength");
|
||||||
|
|
||||||
|
list.push_back("mode");
|
||||||
|
list.push_back("filename");
|
||||||
|
|
||||||
|
return (list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This is the character encoding function to make a character printable
|
||||||
|
static inline const unsigned char UUENCODE(const unsigned char c)
|
||||||
|
{
|
||||||
|
return ((c & 077) + ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single character decoding
|
||||||
|
static inline const unsigned char UUDECODE(const unsigned char c)
|
||||||
|
{
|
||||||
|
return ((c - ' ') & 077);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const utility::stream::size_type encoderUUE::encode(utility::inputStream& in, utility::outputStream& out)
|
||||||
|
{
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
const string propFilename = properties().get <string>("filename", "");
|
||||||
|
const string propMode = properties().get <string>("mode", "644");
|
||||||
|
|
||||||
|
const string::size_type maxLineLength =
|
||||||
|
std::min(properties().get <string::size_type>("maxlinelength", 46),
|
||||||
|
static_cast <string::size_type>(46));
|
||||||
|
|
||||||
|
utility::stream::size_type total = 0;
|
||||||
|
|
||||||
|
// Output the prelude text ("begin [mode] [filename]")
|
||||||
|
out << "begin";
|
||||||
|
|
||||||
|
if (!propFilename.empty())
|
||||||
|
{
|
||||||
|
out << " " << propMode << " " << propFilename;
|
||||||
|
total += 2 + propMode.length() + propFilename.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "\r\n";
|
||||||
|
total += 7;
|
||||||
|
|
||||||
|
// Process the data
|
||||||
|
utility::stream::value_type inBuffer[64];
|
||||||
|
utility::stream::value_type outBuffer[64];
|
||||||
|
|
||||||
|
while (!in.eof())
|
||||||
|
{
|
||||||
|
// Process up to 45 characters per line
|
||||||
|
std::fill(inBuffer, inBuffer + sizeof(inBuffer), 0);
|
||||||
|
|
||||||
|
const utility::stream::size_type inLength = in.read(inBuffer, maxLineLength - 1);
|
||||||
|
|
||||||
|
outBuffer[0] = UUENCODE(inLength); // Line length
|
||||||
|
|
||||||
|
utility::stream::size_type j = 1;
|
||||||
|
|
||||||
|
for (utility::stream::size_type i = 0 ; i < inLength ; i += 3, j += 4)
|
||||||
|
{
|
||||||
|
const unsigned char c1 = (unsigned char) inBuffer[i];
|
||||||
|
const unsigned char c2 = (unsigned char) inBuffer[i + 1];
|
||||||
|
const unsigned char c3 = (unsigned char) inBuffer[i + 2];
|
||||||
|
|
||||||
|
outBuffer[j] = UUENCODE(c1 >> 2);
|
||||||
|
outBuffer[j + 1] = UUENCODE((c1 << 4) & 060 | (c2 >> 4) & 017);
|
||||||
|
outBuffer[j + 2] = UUENCODE((c2 << 2) & 074 | (c3 >> 6) & 03);
|
||||||
|
outBuffer[j + 3] = UUENCODE(c3 & 077);
|
||||||
|
}
|
||||||
|
|
||||||
|
outBuffer[j] = '\r';
|
||||||
|
outBuffer[j + 1] = '\n';
|
||||||
|
|
||||||
|
out.write(outBuffer, j + 2);
|
||||||
|
|
||||||
|
total += j + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "end\r\n";
|
||||||
|
total += 5;
|
||||||
|
|
||||||
|
return (total);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const utility::stream::size_type encoderUUE::decode(utility::inputStream& in, utility::outputStream& out)
|
||||||
|
{
|
||||||
|
in.reset(); // may not work...
|
||||||
|
|
||||||
|
// Process the data
|
||||||
|
utility::stream::value_type inBuffer[64];
|
||||||
|
utility::stream::value_type outBuffer[64];
|
||||||
|
|
||||||
|
utility::stream::size_type total = 0;
|
||||||
|
|
||||||
|
bool stop = false;
|
||||||
|
|
||||||
|
std::fill(inBuffer, inBuffer + sizeof(inBuffer), 0);
|
||||||
|
|
||||||
|
while (!stop && !in.eof())
|
||||||
|
{
|
||||||
|
// Get the line length
|
||||||
|
utility::stream::value_type lengthChar;
|
||||||
|
|
||||||
|
if (in.read(&lengthChar, 1) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const utility::stream::size_type outLength = UUDECODE(lengthChar);
|
||||||
|
const utility::stream::size_type inLength = std::min((outLength * 4) / 3, (utility::stream::size_type) 64);
|
||||||
|
utility::stream::value_type inPos = 0;
|
||||||
|
|
||||||
|
switch (lengthChar)
|
||||||
|
{
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 'b':
|
||||||
|
{
|
||||||
|
// Read 5 characters more to check for begin ("begin ...\r\n" or "begin ...\n")
|
||||||
|
inPos = in.read(inBuffer, 5);
|
||||||
|
|
||||||
|
if (inPos == 5 &&
|
||||||
|
inBuffer[0] == 'e' &&
|
||||||
|
inBuffer[1] == 'g' &&
|
||||||
|
inBuffer[2] == 'i' &&
|
||||||
|
inBuffer[3] == 'n' &&
|
||||||
|
isspace(inBuffer[4]))
|
||||||
|
{
|
||||||
|
utility::stream::value_type c = 0;
|
||||||
|
|
||||||
|
utility::stream::size_type count = 0;
|
||||||
|
utility::stream::value_type buffer[512];
|
||||||
|
|
||||||
|
while (count < sizeof(buffer) - 1 && in.read(&c, 1) == 1)
|
||||||
|
{
|
||||||
|
if (c == '\n')
|
||||||
|
break;
|
||||||
|
|
||||||
|
buffer[count++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c != '\n')
|
||||||
|
{
|
||||||
|
// OOPS! Weird line. Don't try to decode more...
|
||||||
|
return (total);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse filename and mode
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
buffer[count] = '\0';
|
||||||
|
|
||||||
|
utility::stream::value_type* p = buffer;
|
||||||
|
|
||||||
|
while (*p && isspace(*p)) ++p;
|
||||||
|
|
||||||
|
utility::stream::value_type* modeStart = buffer;
|
||||||
|
|
||||||
|
while (*p && !isspace(*p)) ++p;
|
||||||
|
|
||||||
|
results()["mode"] = string(modeStart, p);
|
||||||
|
|
||||||
|
while (*p && isspace(*p)) ++p;
|
||||||
|
|
||||||
|
utility::stream::value_type* filenameStart = buffer;
|
||||||
|
|
||||||
|
while (*p && !(*p == '\r' || *p == '\n')) ++p;
|
||||||
|
|
||||||
|
results()["filename"] = string(filenameStart, p);
|
||||||
|
}
|
||||||
|
// No filename or mode specified
|
||||||
|
else
|
||||||
|
{
|
||||||
|
results()["filename"] = "untitled";
|
||||||
|
results()["mode"] = 644;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'e':
|
||||||
|
{
|
||||||
|
// Read 3 characters more to check for end ("end\r\n" or "end\n")
|
||||||
|
inPos = in.read(inBuffer, 3);
|
||||||
|
|
||||||
|
if (inPos == 3 &&
|
||||||
|
inBuffer[0] == 'n' &&
|
||||||
|
inBuffer[1] == 'd' &&
|
||||||
|
(inBuffer[2] == '\r' || inBuffer[2] == '\n'))
|
||||||
|
{
|
||||||
|
stop = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read encoded data
|
||||||
|
if (in.read(inBuffer + inPos, inLength - inPos) != inLength - inPos)
|
||||||
|
{
|
||||||
|
// Premature end of data
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode data
|
||||||
|
for (utility::stream::size_type i = 0, j = 0 ; i < inLength ; i += 4, j += 3)
|
||||||
|
{
|
||||||
|
const unsigned char c1 = (unsigned char) inBuffer[i];
|
||||||
|
const unsigned char c2 = (unsigned char) inBuffer[i + 1];
|
||||||
|
const unsigned char c3 = (unsigned char) inBuffer[i + 2];
|
||||||
|
const unsigned char c4 = (unsigned char) inBuffer[i + 3];
|
||||||
|
|
||||||
|
const utility::stream::size_type n =
|
||||||
|
std::min(inLength - i, static_cast <utility::stream::size_type>(3));
|
||||||
|
|
||||||
|
switch (n)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case 3: outBuffer[j + 2] = UUDECODE(c3) << 6 | UUDECODE(c4);
|
||||||
|
case 2: outBuffer[j + 1] = UUDECODE(c2) << 4 | UUDECODE(c3) >> 2;
|
||||||
|
case 1: outBuffer[j] = UUDECODE(c1) << 2 | UUDECODE(c2) >> 4;
|
||||||
|
case 0: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
total += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.write(outBuffer, outLength);
|
||||||
|
|
||||||
|
std::fill(inBuffer, inBuffer + sizeof(inBuffer), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (total);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
50
src/encoderUUE.hpp
Normal file
50
src/encoderUUE.hpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ENCODERUUE_HPP_INCLUDED
|
||||||
|
#define VMIME_ENCODERUUE_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "encoder.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** UUEncode encoder.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class encoderUUE : public encoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
encoderUUE();
|
||||||
|
|
||||||
|
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out);
|
||||||
|
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out);
|
||||||
|
|
||||||
|
const std::vector <string> availableProperties() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ENCODERUUE_HPP_INCLUDED
|
161
src/encoding.cpp
Normal file
161
src/encoding.cpp
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "encoding.hpp"
|
||||||
|
#include "encoderFactory.hpp"
|
||||||
|
#include "contentHandler.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
encoding::encoding()
|
||||||
|
: m_name(encodingTypes::SEVEN_BIT)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encoding::encoding(const string& name)
|
||||||
|
: m_name(toLower(name))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encoding::encoding(const encoding& enc)
|
||||||
|
: component(), m_name(enc.m_name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void encoding::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
m_name = toLower(string(buffer.begin() + position, buffer.begin() + end));
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void encoding::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
os << m_name;
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
*newLinePos = curLinePos + m_name.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encoder* encoding::getEncoder() const
|
||||||
|
{
|
||||||
|
return (encoderFactory::getInstance()->create(generate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encoding& encoding::operator=(const encoding& source)
|
||||||
|
{
|
||||||
|
m_name = source.m_name;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encoding& encoding::operator=(const string& name)
|
||||||
|
{
|
||||||
|
m_name = toLower(name);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool encoding::operator==(const encoding& value) const
|
||||||
|
{
|
||||||
|
return (toLower(m_name) == value.m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool encoding::operator!=(const encoding& value) const
|
||||||
|
{
|
||||||
|
return !(*this == value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const encoding encoding::decide
|
||||||
|
(const string::const_iterator begin, const string::const_iterator end)
|
||||||
|
{
|
||||||
|
const string::difference_type length = end - begin;
|
||||||
|
const string::difference_type count = std::count_if
|
||||||
|
(begin, end, std::bind2nd(std::less<unsigned char>(), 127));
|
||||||
|
|
||||||
|
// All is in 7-bit US-ASCII --> 7-bit (or Quoted-Printable...)
|
||||||
|
if (length == count)
|
||||||
|
{
|
||||||
|
// Now, we check if there is any line with more than
|
||||||
|
// "lineLengthLimits::convenient" characters (7-bit requires that)
|
||||||
|
string::const_iterator p = begin;
|
||||||
|
|
||||||
|
const string::size_type maxLen = lineLengthLimits::convenient;
|
||||||
|
string::size_type len = 0;
|
||||||
|
|
||||||
|
for ( ; p != end && len <= maxLen ; )
|
||||||
|
{
|
||||||
|
if (*p == '\n')
|
||||||
|
{
|
||||||
|
len = 0;
|
||||||
|
++p;
|
||||||
|
|
||||||
|
// May or may not need to be encoded, we don't take
|
||||||
|
// any risk (avoid problems with SMTP)
|
||||||
|
if (p != end && *p == '.')
|
||||||
|
len = maxLen + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++len;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > maxLen)
|
||||||
|
return (encoding(encodingTypes::QUOTED_PRINTABLE));
|
||||||
|
else
|
||||||
|
return (encoding(encodingTypes::SEVEN_BIT));
|
||||||
|
}
|
||||||
|
// Less than 20% non US-ASCII --> Quoted-Printable
|
||||||
|
else if ((length - count) <= length / 5)
|
||||||
|
{
|
||||||
|
return (encoding(encodingTypes::QUOTED_PRINTABLE));
|
||||||
|
}
|
||||||
|
// Otherwise --> Base64
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (encoding(encodingTypes::BASE64));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const encoding encoding::decide(const contentHandler& /* data */)
|
||||||
|
{
|
||||||
|
return (encoding(encodingTypes::BASE64));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
87
src/encoding.hpp
Normal file
87
src/encoding.hpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_ENCODING_HPP_INCLUDED
|
||||||
|
#define VMIME_ENCODING_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
#include "encoder.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class contentHandler;
|
||||||
|
|
||||||
|
|
||||||
|
/** Content encoding (basic type).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class encoding : public component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
encoding();
|
||||||
|
encoding(const string& name);
|
||||||
|
encoding(const encoding& enc);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const string& name() const { return (m_name); }
|
||||||
|
string& name() { return (m_name); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
encoding& operator=(const encoding& source);
|
||||||
|
encoding& operator=(const string& name);
|
||||||
|
|
||||||
|
const bool operator==(const encoding& value) const;
|
||||||
|
const bool operator!=(const encoding& value) const;
|
||||||
|
|
||||||
|
// Decide which encoding to use based on the data
|
||||||
|
static const encoding decide(const string::const_iterator begin, const string::const_iterator end);
|
||||||
|
static const encoding decide(const contentHandler& data);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Obtain an encoder/decoder for the current encoding type
|
||||||
|
encoder* getEncoder() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
string m_name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using component::parse;
|
||||||
|
using component::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_ENCODING_HPP_INCLUDED
|
558
src/exception.hpp
Normal file
558
src/exception.hpp
Normal file
@ -0,0 +1,558 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_EXCEPTION_HPP_INCLUDED
|
||||||
|
#define VMIME_EXCEPTION_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.hpp"
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "utility/path.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class exception
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
string m_what;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
exception(const string& what) : m_what(what) { }
|
||||||
|
virtual ~exception() { }
|
||||||
|
|
||||||
|
const string what() const throw() { return (m_what); };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace exceptions
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class bad_field_type : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
bad_field_type() : exception("Bad field type.") {}
|
||||||
|
~bad_field_type() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class charset_conv_error : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
charset_conv_error() : exception("Charset conversion error.") {}
|
||||||
|
~charset_conv_error() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class no_encoder_available : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
no_encoder_available() : exception("No encoder available.") {}
|
||||||
|
~no_encoder_available() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class no_such_parameter : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
no_such_parameter(const string& name) : exception
|
||||||
|
(string("Parameter not found: '") + name + string("'.")) {}
|
||||||
|
~no_such_parameter() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class no_such_field : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
no_such_field() : exception("Field not found.") {}
|
||||||
|
~no_such_field() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class open_file_error : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
open_file_error() : exception("Error opening file.") {}
|
||||||
|
~open_file_error() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class no_factory_available : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
no_factory_available() : exception("No factory available.") {}
|
||||||
|
~no_factory_available() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class no_platform_dependant_handler : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
no_platform_dependant_handler() : exception("No platform-dependant handler installed.") {}
|
||||||
|
~no_platform_dependant_handler() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class no_expeditor : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
no_expeditor() : exception("No expeditor specified.") {}
|
||||||
|
~no_expeditor() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class no_recipient : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
no_recipient() : exception("No recipient specified.") {}
|
||||||
|
~no_recipient() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class no_object_found : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
no_object_found() : exception("No object found.") {}
|
||||||
|
~no_object_found() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// There is no property with that name in the set.
|
||||||
|
|
||||||
|
class no_such_property : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
no_such_property(const string& name) : exception
|
||||||
|
(std::string("No such property: '") + name + string("'.")) { }
|
||||||
|
~no_such_property() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Bad type specified when reading property.
|
||||||
|
|
||||||
|
class invalid_property_type : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
invalid_property_type() : exception("Invalid property type.") {}
|
||||||
|
~invalid_property_type() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Bad argument was passed to the function.
|
||||||
|
|
||||||
|
class invalid_argument : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
invalid_argument() : exception("Invalid argument.") {}
|
||||||
|
~invalid_argument() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||||
|
|
||||||
|
|
||||||
|
/** Base class for exceptions thrown by the messaging module.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class messaging_exception : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
messaging_exception(const string& what) : exception(what) {}
|
||||||
|
~messaging_exception() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Error while connecting to the server: this may be a DNS resolution error
|
||||||
|
* or a connection error (for example, time-out while connecting).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class connection_error : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
connection_error() : messaging_exception("Connection error.") {}
|
||||||
|
~connection_error() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Server did not initiated the connection correctly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class connection_greeting_error : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
connection_greeting_error(const string& response)
|
||||||
|
: messaging_exception("Greeting error."), m_response(response) {}
|
||||||
|
~connection_greeting_error() throw() {}
|
||||||
|
|
||||||
|
const string& response() const { return (m_response); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
string m_response;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Error while giving credentials to the server (wrong username
|
||||||
|
* or password, or wrong authentication method).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class authentication_error : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
authentication_error(const string& response)
|
||||||
|
: messaging_exception("Authentication error."), m_response(response) {}
|
||||||
|
~authentication_error() throw() {}
|
||||||
|
|
||||||
|
const string& response() const { return (m_response); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
string m_response;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Option not supported.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class unsupported_option : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
unsupported_option() : messaging_exception("Unsupported option.") {}
|
||||||
|
~unsupported_option() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** No service available for this protocol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class no_service_available : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
no_service_available() : messaging_exception("No service available for this protocol.") {}
|
||||||
|
~no_service_available() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** The current state of the object does not permit to execute the
|
||||||
|
* operation (for example, you try to close a folder which is not open).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class illegal_state : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
illegal_state(const string& state)
|
||||||
|
: messaging_exception("Illegal state to accomplish the operation: '" + state + "'.") {}
|
||||||
|
~illegal_state() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Folder not found (does not exist).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class folder_not_found : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
folder_not_found() : messaging_exception("Folder not found.") {}
|
||||||
|
~folder_not_found() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Message not found (does not exist).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class message_not_found : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
message_not_found() : messaging_exception("Message not found.") {}
|
||||||
|
~message_not_found() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Operation not supported by the underlying protocol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class operation_not_supported : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
operation_not_supported() : messaging_exception("Operation not supported.") {}
|
||||||
|
~operation_not_supported() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** The operation timed out (time-out delay is elapsed).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class operation_timed_out : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
operation_timed_out() : messaging_exception("Operation timed out.") {}
|
||||||
|
~operation_timed_out() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** The operation has been cancelled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class operation_cancelled : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
operation_cancelled() : messaging_exception("Operation cancelled by the user.") {}
|
||||||
|
~operation_cancelled() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Must call fetchMessage() or fetchHeader() before accessing
|
||||||
|
* the requested object.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class unfetched_object : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
unfetched_object() : messaging_exception("Object not fetched.") {}
|
||||||
|
~unfetched_object() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** The service is not currently connected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class not_connected : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
not_connected() : messaging_exception("Not connected to a service.") {}
|
||||||
|
~not_connected() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** The service is already connected (must disconnect before).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class already_connected : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
already_connected() : messaging_exception("Already connected to a service. Disconnect and retry.") {}
|
||||||
|
~already_connected() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Command error: operation failed (this is specific to the underlying protocol).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class command_error : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
command_error(const string& command, const string& response, const string& desc = "")
|
||||||
|
: messaging_exception(desc.empty()
|
||||||
|
? "Error while executing command '" + command + "'."
|
||||||
|
: "Error while executing command '" + command + "': " + desc + "."
|
||||||
|
),
|
||||||
|
m_command(command), m_response(response) {}
|
||||||
|
~command_error() throw() {}
|
||||||
|
|
||||||
|
/** Return the name of the command which have thrown the exception.
|
||||||
|
* This is protocol-dependant.
|
||||||
|
*
|
||||||
|
* @return command name (protocol-dependant)
|
||||||
|
*/
|
||||||
|
const string& command() const { return (m_command); }
|
||||||
|
|
||||||
|
/** Return the invalid response line.
|
||||||
|
* The meaning is protocol-dependant.
|
||||||
|
*
|
||||||
|
* @return response line (protocol-dependant)
|
||||||
|
*/
|
||||||
|
const string& response() const { return (m_response); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
string m_command;
|
||||||
|
string m_response;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** The server returned an invalid response.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class invalid_response : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
invalid_response(const string& command, const string& response)
|
||||||
|
: messaging_exception(command.empty()
|
||||||
|
? "Received invalid response."
|
||||||
|
: "Received invalid response for command '" + command + "'."
|
||||||
|
),
|
||||||
|
m_command(command), m_response(response) {}
|
||||||
|
~invalid_response() throw() {}
|
||||||
|
|
||||||
|
/** Return the name of the command which have thrown the exception.
|
||||||
|
* This is protocol-dependant.
|
||||||
|
*
|
||||||
|
* @return command name (protocol-dependant)
|
||||||
|
*/
|
||||||
|
const string& command() const { return (m_command); }
|
||||||
|
|
||||||
|
/** Return the invalid response line.
|
||||||
|
* The meaning is protocol-dependant.
|
||||||
|
*
|
||||||
|
* @return response line (protocol-dependant)
|
||||||
|
*/
|
||||||
|
const string& response() const { return (m_response); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
string m_command;
|
||||||
|
string m_response;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Partial fetch is not supported by the underlying protocol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class partial_fetch_not_supported : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
partial_fetch_not_supported() : messaging_exception("Partial fetch not supported.") {}
|
||||||
|
~partial_fetch_not_supported() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** The URL is malformed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class malformed_url : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
malformed_url(const string& error) : messaging_exception("Malformed URL: " + error + ".") {}
|
||||||
|
~malformed_url() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Folder name is invalid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class invalid_folder_name : public messaging_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
invalid_folder_name(const string& error) : messaging_exception("Invalid folder name: " + error + ".") {}
|
||||||
|
~invalid_folder_name() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_MESSAGING_FEATURES
|
||||||
|
|
||||||
|
|
||||||
|
#if VMIME_HAVE_FILESYSTEM_FEATURES
|
||||||
|
|
||||||
|
|
||||||
|
/** Base class for exceptions thrown by the filesystem features.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class filesystem_exception : public vmime::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
filesystem_exception(const string& what, const utility::path& path) : exception(what), m_path(path) {}
|
||||||
|
~filesystem_exception() throw() {}
|
||||||
|
|
||||||
|
/** Return the full path of the file have thrown the exception.
|
||||||
|
*
|
||||||
|
* @return full path of the file/directory
|
||||||
|
*/
|
||||||
|
const utility::path& path() const { return (m_path); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const utility::path m_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** File is not a directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class not_a_directory : public filesystem_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
not_a_directory(const utility::path& path) : filesystem_exception("Operation failed: this is not a directory.", path) {}
|
||||||
|
~not_a_directory() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** File not found.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class file_not_found : public filesystem_exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
file_not_found(const utility::path& path) : filesystem_exception("File not found.", path) {}
|
||||||
|
~file_not_found() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HAVE_FILESYSTEM_FEATURES
|
||||||
|
|
||||||
|
|
||||||
|
} // exceptions
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_EXCEPTION_HPP_INCLUDED
|
123
src/fileAttachment.cpp
Normal file
123
src/fileAttachment.cpp
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "fileAttachment.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
fileAttachment::fileAttachment(const string& filename, const mediaType& type, const text& desc)
|
||||||
|
{
|
||||||
|
m_type = type;
|
||||||
|
m_desc = desc;
|
||||||
|
|
||||||
|
setData(filename);
|
||||||
|
|
||||||
|
m_encoding = encoding::decide(m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fileAttachment::fileAttachment(const string& filename, const mediaType& type,
|
||||||
|
const class encoding& enc, const text& desc)
|
||||||
|
{
|
||||||
|
m_type = type;
|
||||||
|
m_desc = desc;
|
||||||
|
|
||||||
|
setData(filename);
|
||||||
|
|
||||||
|
m_encoding = enc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void fileAttachment::setData(const string& filename)
|
||||||
|
{
|
||||||
|
std::ifstream* file = new std::ifstream();
|
||||||
|
file->open(filename.c_str(), std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
if (!*file)
|
||||||
|
{
|
||||||
|
delete (file);
|
||||||
|
throw exceptions::open_file_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_data.set(new utility::inputStreamPointerAdapter(file, true), 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void fileAttachment::generatePart(bodyPart& part) const
|
||||||
|
{
|
||||||
|
defaultAttachment::generatePart(part);
|
||||||
|
|
||||||
|
contentDispositionField& cdf = part.header().fields.ContentDisposition();
|
||||||
|
|
||||||
|
if (m_fileInfo.hasSize()) cdf.size() = toString(m_fileInfo.getSize());
|
||||||
|
if (m_fileInfo.hasFilename()) cdf.filename() = m_fileInfo.getFilename();
|
||||||
|
if (m_fileInfo.hasCreationDate()) cdf.creationDate() = m_fileInfo.getCreationDate();
|
||||||
|
if (m_fileInfo.hasModificationDate()) cdf.modificationDate() = m_fileInfo.getModificationDate();
|
||||||
|
if (m_fileInfo.hasReadDate()) cdf.readDate() = m_fileInfo.getReadDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// fileAttachment::fileInfo
|
||||||
|
//
|
||||||
|
|
||||||
|
fileAttachment::fileInfo::fileInfo()
|
||||||
|
: m_filename(NULL), m_size(NULL), m_creationDate(NULL), m_modifDate(NULL), m_readDate(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fileAttachment::fileInfo::~fileInfo()
|
||||||
|
{
|
||||||
|
delete (m_filename);
|
||||||
|
delete (m_size);
|
||||||
|
delete (m_creationDate);
|
||||||
|
delete (m_modifDate);
|
||||||
|
delete (m_readDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool fileAttachment::fileInfo::hasFilename() const { return (m_filename != NULL); }
|
||||||
|
const string& fileAttachment::fileInfo::getFilename() const { return (*m_filename); }
|
||||||
|
void fileAttachment::fileInfo::setFilename(const string& name) { if (m_filename) { *m_filename = name; } else { m_filename = new string(name); } }
|
||||||
|
|
||||||
|
const bool fileAttachment::fileInfo::hasCreationDate() const { return (m_creationDate != NULL); }
|
||||||
|
const datetime& fileAttachment::fileInfo::getCreationDate() const { return (*m_creationDate); }
|
||||||
|
void fileAttachment::fileInfo::setCreationDate(const datetime& date) { if (m_creationDate) { *m_creationDate = date; } else { m_creationDate = new datetime(date); } }
|
||||||
|
|
||||||
|
const bool fileAttachment::fileInfo::hasModificationDate() const { return (m_modifDate != NULL); }
|
||||||
|
const datetime& fileAttachment::fileInfo::getModificationDate() const { return (*m_modifDate); }
|
||||||
|
void fileAttachment::fileInfo::setModificationDate(const datetime& date) { if (m_modifDate) { *m_modifDate = date; } else { m_modifDate = new datetime(date); } }
|
||||||
|
|
||||||
|
const bool fileAttachment::fileInfo::hasReadDate() const { return (m_readDate != NULL); }
|
||||||
|
const datetime& fileAttachment::fileInfo::getReadDate() const { return (*m_readDate); }
|
||||||
|
void fileAttachment::fileInfo::setReadDate(const datetime& date) { if (m_readDate) { *m_readDate = date; } else { m_readDate = new datetime(date); } }
|
||||||
|
|
||||||
|
const bool fileAttachment::fileInfo::hasSize() const { return (m_size != NULL); }
|
||||||
|
const unsigned int fileAttachment::fileInfo::getSize() const { return (*m_size); }
|
||||||
|
void fileAttachment::fileInfo::setSize(const unsigned int& size) { if (m_size) { *m_size = size; } else { m_size = new unsigned int(size); } }
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
90
src/fileAttachment.hpp
Normal file
90
src/fileAttachment.hpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_FILEATTACHMENT_HPP_INCLUDED
|
||||||
|
#define VMIME_FILEATTACHMENT_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "defaultAttachment.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class fileAttachment : public defaultAttachment
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
fileAttachment(const string& filename, const mediaType& type, const text& desc = NULL_TEXT);
|
||||||
|
fileAttachment(const string& filename, const mediaType& type, const class encoding& enc, const text& desc = NULL_TEXT);
|
||||||
|
|
||||||
|
class fileInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
fileInfo();
|
||||||
|
~fileInfo();
|
||||||
|
|
||||||
|
const bool hasFilename() const;
|
||||||
|
const string& getFilename() const;
|
||||||
|
void setFilename(const string& name);
|
||||||
|
|
||||||
|
const bool hasCreationDate() const;
|
||||||
|
const datetime& getCreationDate() const;
|
||||||
|
void setCreationDate(const datetime& date);
|
||||||
|
|
||||||
|
const bool hasModificationDate() const;
|
||||||
|
const datetime& getModificationDate() const;
|
||||||
|
void setModificationDate(const datetime& date);
|
||||||
|
|
||||||
|
const bool hasReadDate() const;
|
||||||
|
const datetime& getReadDate() const;
|
||||||
|
void setReadDate(const datetime& date);
|
||||||
|
|
||||||
|
const bool hasSize() const;
|
||||||
|
const unsigned int getSize() const;
|
||||||
|
void setSize(const unsigned int& size);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
string* m_filename;
|
||||||
|
unsigned int* m_size;
|
||||||
|
datetime* m_creationDate;
|
||||||
|
datetime* m_modifDate;
|
||||||
|
datetime* m_readDate;
|
||||||
|
};
|
||||||
|
|
||||||
|
const class fileInfo& fileInfo() const { return (m_fileInfo); }
|
||||||
|
class fileInfo& fileInfo() { return (m_fileInfo); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void setData(const string& filename);
|
||||||
|
|
||||||
|
class fileInfo m_fileInfo;
|
||||||
|
|
||||||
|
void generatePart(bodyPart& part) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_FILEATTACHMENT_HPP_INCLUDED
|
452
src/header.cpp
Normal file
452
src/header.cpp
Normal file
@ -0,0 +1,452 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "header.hpp"
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
header::header()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
header::~header()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
RFC #822:
|
||||||
|
3.2. HEADER FIELD DEFINITIONS
|
||||||
|
|
||||||
|
field = field-name ":" [ field-body ] CRLF
|
||||||
|
|
||||||
|
field-name = 1*<any CHAR, excluding CTLs, SPACE, and ":">
|
||||||
|
|
||||||
|
field-body = field-body-contents
|
||||||
|
[CRLF LWSP-char field-body]
|
||||||
|
|
||||||
|
field-body-contents =
|
||||||
|
<the ASCII characters making up the field-body, as
|
||||||
|
defined in the following sections, and consisting
|
||||||
|
of combinations of atom, quoted-string, and
|
||||||
|
specials tokens, or else consisting of texts>
|
||||||
|
*/
|
||||||
|
|
||||||
|
void header::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
string::size_type pos = position;
|
||||||
|
|
||||||
|
fields.clear();
|
||||||
|
|
||||||
|
while (pos < end)
|
||||||
|
{
|
||||||
|
char_t c = buffer[pos];
|
||||||
|
|
||||||
|
// Check for end of headers (empty line): although RFC-822 recommends
|
||||||
|
// to use CRLF for header/body separator (see 4.1 SYNTAX), here, we
|
||||||
|
// also check for LF just in case...
|
||||||
|
if (c == '\n')
|
||||||
|
{
|
||||||
|
++pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n')
|
||||||
|
{
|
||||||
|
pos += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This line may be a field description
|
||||||
|
if (!isspace(c))
|
||||||
|
{
|
||||||
|
const string::size_type nameStart = pos; // remember the start position of the line
|
||||||
|
|
||||||
|
while (pos < end && (buffer[pos] != ':' && !isspace(buffer[pos])))
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
const string::size_type nameEnd = pos;
|
||||||
|
|
||||||
|
while (pos < end && isspace(buffer[pos]))
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
if (buffer[pos] != ':')
|
||||||
|
{
|
||||||
|
// Humm...does not seem to be a valid header line.
|
||||||
|
// Skip this error and advance to the next line
|
||||||
|
pos = nameStart;
|
||||||
|
|
||||||
|
while (pos < end && buffer[pos] != '\n')
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
if (buffer[pos] == '\n')
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Extract the field name
|
||||||
|
const string name(buffer.begin() + nameStart,
|
||||||
|
buffer.begin() + nameEnd);
|
||||||
|
|
||||||
|
// Skip ':' character
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
// Skip spaces between ':' and the field contents
|
||||||
|
while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t'))
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
// Extract the field value
|
||||||
|
string contents;
|
||||||
|
|
||||||
|
while (pos < end)
|
||||||
|
{
|
||||||
|
c = buffer[pos];
|
||||||
|
|
||||||
|
// Check for end of contents
|
||||||
|
if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n')
|
||||||
|
{
|
||||||
|
pos += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (c == '\n')
|
||||||
|
{
|
||||||
|
++pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string::size_type ctsStart = pos;
|
||||||
|
string::size_type ctsEnd = pos;
|
||||||
|
|
||||||
|
while (pos < end)
|
||||||
|
{
|
||||||
|
c = buffer[pos];
|
||||||
|
|
||||||
|
// Check for end of line
|
||||||
|
if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n')
|
||||||
|
{
|
||||||
|
ctsEnd = pos;
|
||||||
|
pos += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (c == '\n')
|
||||||
|
{
|
||||||
|
ctsEnd = pos;
|
||||||
|
++pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctsEnd != ctsStart)
|
||||||
|
{
|
||||||
|
// Append this line to contents
|
||||||
|
contents.append(buffer.begin() + ctsStart,
|
||||||
|
buffer.begin() + ctsEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle the case of folded lines
|
||||||
|
if (buffer[pos] == ' ' || buffer[pos] == '\t')
|
||||||
|
{
|
||||||
|
// This is a folding white-space: we keep it as is and
|
||||||
|
// we continue with contents parsing...
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// End of this field
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new field to list
|
||||||
|
fields.m_fields.push_back(headerFieldFactory::getInstance()->
|
||||||
|
create(headerField::nameToType(name), name, contents));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Skip this error and advance to the next line
|
||||||
|
while (pos < end && buffer[pos] != '\n')
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
if (buffer[pos] == '\n')
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have found the header/body separator, skip it
|
||||||
|
if (pos < end)
|
||||||
|
{
|
||||||
|
if (buffer[pos] == '\n')
|
||||||
|
{
|
||||||
|
// This is a LF (illegal but...)
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
else if (buffer[pos] == '\r' && pos + 1 < end)
|
||||||
|
{
|
||||||
|
// This is a CRLF
|
||||||
|
pos += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void header::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
||||||
|
const string::size_type /* curLinePos */, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
// Generate the fields
|
||||||
|
for (std::vector <headerField*>::const_iterator
|
||||||
|
it = fields.m_fields.begin() ; it != fields.m_fields.end() ; ++it)
|
||||||
|
{
|
||||||
|
(*it)->generate(os, maxLineLength);
|
||||||
|
os << CRLF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
*newLinePos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
header& header::operator=(const header& h)
|
||||||
|
{
|
||||||
|
fields = h.fields;
|
||||||
|
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// Fields container //
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
header::fieldsContainer::fieldsContainer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
header::fieldsContainer::~fieldsContainer()
|
||||||
|
{
|
||||||
|
for (std::vector <headerField*>::iterator i = m_fields.begin() ; i != m_fields.end() ; ++i)
|
||||||
|
delete (*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Checks whether (at least) one field with this type/name exists
|
||||||
|
const bool header::fieldsContainer::has(const headerField::Types fieldType) const
|
||||||
|
{
|
||||||
|
std::vector <headerField*>::const_iterator pos = m_fields.begin();
|
||||||
|
const std::vector <headerField*>::const_iterator end = m_fields.end();
|
||||||
|
|
||||||
|
for ( ; pos != end && (*pos)->type() != fieldType ; ++pos);
|
||||||
|
|
||||||
|
return (pos != end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool header::fieldsContainer::has(const string& fieldName) const
|
||||||
|
{
|
||||||
|
headerField::Types type = headerField::nameToType(fieldName);
|
||||||
|
if (type != headerField::Custom) return (has(type));
|
||||||
|
|
||||||
|
const string name = toLower(fieldName);
|
||||||
|
|
||||||
|
std::vector <headerField*>::const_iterator pos = m_fields.begin();
|
||||||
|
const std::vector <headerField*>::const_iterator end = m_fields.end();
|
||||||
|
|
||||||
|
for ( ; pos != end && toLower((*pos)->name()) != name ; ++pos);
|
||||||
|
|
||||||
|
return (pos != end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Find the first field that matches the specified type/name.
|
||||||
|
// If no field is found, an exception is thrown.
|
||||||
|
headerField& header::fieldsContainer::find(const headerField::Types fieldType) const
|
||||||
|
{
|
||||||
|
// Find the first field that matches the specified type
|
||||||
|
std::vector <headerField*>::const_iterator pos = m_fields.begin();
|
||||||
|
const std::vector <headerField*>::const_iterator end = m_fields.end();
|
||||||
|
|
||||||
|
for ( ; pos != end && (*pos)->type() != fieldType ; ++pos);
|
||||||
|
|
||||||
|
// No field with this type can be found
|
||||||
|
if (pos == end)
|
||||||
|
{
|
||||||
|
throw exceptions::no_such_field();
|
||||||
|
}
|
||||||
|
// Else, return a reference to the existing field
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (**pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
headerField& header::fieldsContainer::find(const string& fieldName) const
|
||||||
|
{
|
||||||
|
headerField::Types type = headerField::nameToType(fieldName);
|
||||||
|
if (type != headerField::Custom) return (find(type));
|
||||||
|
|
||||||
|
const string name = toLower(fieldName);
|
||||||
|
|
||||||
|
// Find the first field that matches the specified name
|
||||||
|
std::vector <headerField*>::const_iterator pos = m_fields.begin();
|
||||||
|
const std::vector <headerField*>::const_iterator end = m_fields.end();
|
||||||
|
|
||||||
|
for ( ; pos != end && toLower((*pos)->name()) != name ; ++pos);
|
||||||
|
|
||||||
|
// No field with this name can be found
|
||||||
|
if (pos == end)
|
||||||
|
{
|
||||||
|
throw exceptions::no_such_field();
|
||||||
|
}
|
||||||
|
// Else, return a reference to the existing field
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (**pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Find the first field that matches the specified type/name
|
||||||
|
headerField& header::fieldsContainer::get(const headerField::Types fieldType)
|
||||||
|
{
|
||||||
|
// Find the first field that matches the specified type
|
||||||
|
std::vector <headerField*>::const_iterator pos = m_fields.begin();
|
||||||
|
const std::vector <headerField*>::const_iterator end = m_fields.end();
|
||||||
|
|
||||||
|
for ( ; pos != end && (*pos)->type() != fieldType ; ++pos);
|
||||||
|
|
||||||
|
// If no field with this type can be found, create a new one
|
||||||
|
if (pos == end)
|
||||||
|
{
|
||||||
|
headerField* field = headerFieldFactory::getInstance()->create(fieldType);
|
||||||
|
insertSorted(field);
|
||||||
|
|
||||||
|
// Return a reference to the new field
|
||||||
|
return (*field);
|
||||||
|
}
|
||||||
|
// Else, return a reference to the existing field
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (**pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
headerField& header::fieldsContainer::get(const string& fieldName)
|
||||||
|
{
|
||||||
|
headerField::Types type = headerField::nameToType(fieldName);
|
||||||
|
if (type != headerField::Custom) return (get(type));
|
||||||
|
|
||||||
|
const string name = toLower(fieldName);
|
||||||
|
|
||||||
|
// Find the first field that matches the specified name
|
||||||
|
std::vector <headerField*>::const_iterator pos = m_fields.begin();
|
||||||
|
const std::vector <headerField*>::const_iterator end = m_fields.end();
|
||||||
|
|
||||||
|
for ( ; pos != end && toLower((*pos)->name()) != name ; ++pos);
|
||||||
|
|
||||||
|
// If no field with this name can be found, create a new one
|
||||||
|
if (pos == end)
|
||||||
|
{
|
||||||
|
headerField* field = headerFieldFactory::getInstance()->create(fieldName);
|
||||||
|
insertSorted(field);
|
||||||
|
|
||||||
|
// Return a reference to the new field
|
||||||
|
return (*field);
|
||||||
|
}
|
||||||
|
// Else, return a reference to the existing field
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (**pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void header::fieldsContainer::insertSorted(headerField* field)
|
||||||
|
{
|
||||||
|
const headerField::Types type = field->type();
|
||||||
|
std::vector <headerField*>::iterator i;
|
||||||
|
|
||||||
|
for (i = m_fields.begin() ; (i != m_fields.end()) && ((*i)->type() < type) ; ++i);
|
||||||
|
|
||||||
|
m_fields.insert(i, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Field insertion
|
||||||
|
void header::fieldsContainer::append(const headerField& field)
|
||||||
|
{
|
||||||
|
m_fields.push_back(field.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void header::fieldsContainer::insert(const iterator it, const headerField& field)
|
||||||
|
{
|
||||||
|
m_fields.insert(it.m_iterator, field.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Field removing
|
||||||
|
void header::fieldsContainer::remove(const iterator it)
|
||||||
|
{
|
||||||
|
delete (*it.m_iterator);
|
||||||
|
m_fields.erase(it.m_iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void header::fieldsContainer::clear()
|
||||||
|
{
|
||||||
|
for (std::vector <headerField*>::iterator it = m_fields.begin() ; it != m_fields.end() ; ++it)
|
||||||
|
delete (*it);
|
||||||
|
|
||||||
|
m_fields.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
header::fieldsContainer& header::fieldsContainer::operator=(const fieldsContainer& c)
|
||||||
|
{
|
||||||
|
std::vector <headerField*> fields;
|
||||||
|
|
||||||
|
for (std::vector <headerField*>::const_iterator it = c.m_fields.begin() ; it != c.m_fields.end() ; ++it)
|
||||||
|
fields.push_back((*it)->clone());
|
||||||
|
|
||||||
|
for (std::vector <headerField*>::iterator it = m_fields.begin() ; it != m_fields.end() ; ++it)
|
||||||
|
delete (*it);
|
||||||
|
|
||||||
|
m_fields.resize(fields.size());
|
||||||
|
std::copy(fields.begin(), fields.end(), m_fields.begin());
|
||||||
|
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
266
src/header.hpp
Normal file
266
src/header.hpp
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_HEADER_HPP_INCLUDED
|
||||||
|
#define VMIME_HEADER_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
|
||||||
|
#include "headerField.hpp"
|
||||||
|
#include "headerFieldFactory.hpp"
|
||||||
|
|
||||||
|
#include "addressListField.hpp"
|
||||||
|
#include "mailboxListField.hpp"
|
||||||
|
#include "mailboxField.hpp"
|
||||||
|
#include "textField.hpp"
|
||||||
|
#include "dateField.hpp"
|
||||||
|
#include "contentTypeField.hpp"
|
||||||
|
#include "contentEncodingField.hpp"
|
||||||
|
#include "defaultField.hpp"
|
||||||
|
#include "contentDispositionField.hpp"
|
||||||
|
#include "messageIdField.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class bodyPart;
|
||||||
|
|
||||||
|
|
||||||
|
/** Header section of a MIME part.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class header : public component
|
||||||
|
{
|
||||||
|
friend class bodyPart;
|
||||||
|
friend class body;
|
||||||
|
friend class message;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
header();
|
||||||
|
~header();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// A sub-class for field manipulation
|
||||||
|
class fieldsContainer
|
||||||
|
{
|
||||||
|
friend class header;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
fieldsContainer();
|
||||||
|
~fieldsContainer();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Field access
|
||||||
|
mailboxField& From() { return (dynamic_cast<mailboxField&>(get(headerField::From))); }
|
||||||
|
mailboxField& Sender() { return (dynamic_cast<mailboxField&>(get(headerField::Sender))); }
|
||||||
|
mailboxField& ReplyTo() { return (dynamic_cast<mailboxField&>(get(headerField::ReplyTo))); }
|
||||||
|
mailboxField& DeliveredTo() { return (dynamic_cast<mailboxField&>(get(headerField::DeliveredTo))); }
|
||||||
|
addressListField& To() { return (dynamic_cast<addressListField&>(get(headerField::To))); }
|
||||||
|
addressListField& Cc() { return (dynamic_cast<addressListField&>(get(headerField::Cc))); }
|
||||||
|
addressListField& Bcc() { return (dynamic_cast<addressListField&>(get(headerField::Bcc))); }
|
||||||
|
dateField& Date() { return (dynamic_cast<dateField&>(get(headerField::Date))); }
|
||||||
|
textField& Subject() { return (dynamic_cast<textField&>(get(headerField::Subject))); }
|
||||||
|
textField& Organization() { return (dynamic_cast<textField&>(get(headerField::Organization))); }
|
||||||
|
textField& UserAgent() { return (dynamic_cast<textField&>(get(headerField::UserAgent))); }
|
||||||
|
contentTypeField& ContentType() { return (dynamic_cast<contentTypeField&>(get(headerField::ContentType))); }
|
||||||
|
textField& ContentDescription() { return (dynamic_cast<textField&>(get(headerField::ContentDescription))); }
|
||||||
|
contentEncodingField& ContentTransferEncoding() { return (dynamic_cast<contentEncodingField&>(get(headerField::ContentTransferEncoding))); }
|
||||||
|
defaultField& MimeVersion() { return (dynamic_cast<defaultField&>(get(headerField::MimeVersion))); }
|
||||||
|
contentDispositionField& ContentDisposition() { return (dynamic_cast<contentDispositionField&>(get(headerField::ContentDisposition))); }
|
||||||
|
messageIdField& ContentId() { return (dynamic_cast<messageIdField&>(get(headerField::ContentId))); }
|
||||||
|
messageIdField& MessageId() { return (dynamic_cast<messageIdField&>(get(headerField::MessageId))); }
|
||||||
|
defaultField& ContentLocation() { return (dynamic_cast<defaultField&>(get(headerField::ContentLocation))); }
|
||||||
|
|
||||||
|
const mailboxField& From() const { return (dynamic_cast<mailboxField&>(find(headerField::From))); }
|
||||||
|
const mailboxField& Sender() const { return (dynamic_cast<mailboxField&>(find(headerField::Sender))); }
|
||||||
|
const mailboxField& ReplyTo() const { return (dynamic_cast<mailboxField&>(find(headerField::ReplyTo))); }
|
||||||
|
const mailboxField& DeliveredTo() const { return (dynamic_cast<mailboxField&>(find(headerField::DeliveredTo))); }
|
||||||
|
const addressListField& To() const { return (dynamic_cast<addressListField&>(find(headerField::To))); }
|
||||||
|
const addressListField& Cc() const { return (dynamic_cast<addressListField&>(find(headerField::Cc))); }
|
||||||
|
const addressListField& Bcc() const { return (dynamic_cast<addressListField&>(find(headerField::Bcc))); }
|
||||||
|
const dateField& Date() const { return (dynamic_cast<dateField&>(find(headerField::Date))); }
|
||||||
|
const textField& Subject() const { return (dynamic_cast<textField&>(find(headerField::Subject))); }
|
||||||
|
const textField& Organization() const { return (dynamic_cast<textField&>(find(headerField::Organization))); }
|
||||||
|
const textField& UserAgent() const { return (dynamic_cast<textField&>(find(headerField::UserAgent))); }
|
||||||
|
const contentTypeField& ContentType() const { return (dynamic_cast<contentTypeField&>(find(headerField::ContentType))); }
|
||||||
|
const textField& ContentDescription() const { return (dynamic_cast<textField&>(find(headerField::ContentDescription))); }
|
||||||
|
const contentEncodingField& ContentTransferEncoding() const { return (dynamic_cast<contentEncodingField&>(find(headerField::ContentTransferEncoding))); }
|
||||||
|
const defaultField& MimeVersion() const { return (dynamic_cast<defaultField&>(find(headerField::MimeVersion))); }
|
||||||
|
const contentDispositionField& ContentDisposition() const { return (dynamic_cast<contentDispositionField&>(find(headerField::ContentDisposition))); }
|
||||||
|
const messageIdField& ContentId() const { return (dynamic_cast<messageIdField&>(find(headerField::ContentId))); }
|
||||||
|
const messageIdField& MessageId() const { return (dynamic_cast<messageIdField&>(find(headerField::MessageId))); }
|
||||||
|
const defaultField& ContentLocation() const { return (dynamic_cast<defaultField&>(find(headerField::ContentLocation))); }
|
||||||
|
|
||||||
|
// Checks whether (at least) one field with this type/name exists
|
||||||
|
const bool has(const headerField::Types fieldType) const;
|
||||||
|
const bool has(const string& fieldName) const;
|
||||||
|
|
||||||
|
// Find the first field that matches the specified type/name.
|
||||||
|
// If no field is found, an exception is thrown.
|
||||||
|
headerField& find(const headerField::Types fieldType) const;
|
||||||
|
headerField& find(const string& fieldName) const;
|
||||||
|
|
||||||
|
// Find the first field that matches the specified type/name.
|
||||||
|
// If no field is found, one will be created.
|
||||||
|
headerField& get(const headerField::Types fieldType);
|
||||||
|
headerField& get(const string& fieldName);
|
||||||
|
|
||||||
|
// Field iterator
|
||||||
|
class const_iterator;
|
||||||
|
|
||||||
|
class iterator
|
||||||
|
{
|
||||||
|
friend class header::fieldsContainer::const_iterator;
|
||||||
|
friend class header::fieldsContainer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::vector <headerField*>::iterator::difference_type difference_type;
|
||||||
|
|
||||||
|
iterator(std::vector <headerField*>::iterator it) : m_iterator(it) { }
|
||||||
|
iterator(const iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
|
||||||
|
iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
|
||||||
|
headerField& operator*() const { return (**m_iterator); }
|
||||||
|
headerField* operator->() const { return (*m_iterator); }
|
||||||
|
|
||||||
|
iterator& operator++() { ++m_iterator; return (*this); }
|
||||||
|
iterator operator++(int) { iterator i(*this); ++m_iterator; return (i); }
|
||||||
|
|
||||||
|
iterator& operator--() { --m_iterator; return (*this); }
|
||||||
|
iterator operator--(int) { iterator i(*this); --m_iterator; return (i); }
|
||||||
|
|
||||||
|
iterator& operator+=(difference_type n) { m_iterator += n; return (*this); }
|
||||||
|
iterator& operator-=(difference_type n) { m_iterator -= n; return (*this); }
|
||||||
|
|
||||||
|
iterator operator-(difference_type x) const { return iterator(m_iterator - x); }
|
||||||
|
|
||||||
|
headerField& operator[](difference_type n) const { return *(m_iterator[n]); }
|
||||||
|
|
||||||
|
const bool operator==(const iterator& it) const { return (it.m_iterator == m_iterator); }
|
||||||
|
const bool operator!=(const iterator& it) const { return (!(*this == it)); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::vector <headerField*>::iterator m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
class const_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::vector <headerField*>::const_iterator::difference_type difference_type;
|
||||||
|
|
||||||
|
const_iterator(std::vector <headerField*>::const_iterator it) : m_iterator(it) { }
|
||||||
|
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
|
||||||
|
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
|
||||||
|
const headerField& operator*() const { return (**m_iterator); }
|
||||||
|
const headerField* operator->() const { return (*m_iterator); }
|
||||||
|
|
||||||
|
const_iterator& operator++() { ++m_iterator; return (*this); }
|
||||||
|
const_iterator operator++(int) { const_iterator i(*this); ++m_iterator; return (i); }
|
||||||
|
|
||||||
|
const_iterator& operator--() { --m_iterator; return (*this); }
|
||||||
|
const_iterator operator--(int) { const_iterator i(*this); --m_iterator; return (i); }
|
||||||
|
|
||||||
|
const_iterator& operator+=(difference_type n) { m_iterator += n; return (*this); }
|
||||||
|
const_iterator& operator-=(difference_type n) { m_iterator -= n; return (*this); }
|
||||||
|
|
||||||
|
const_iterator operator-(difference_type x) const { return const_iterator(m_iterator - x); }
|
||||||
|
|
||||||
|
const headerField& operator[](difference_type n) const { return *(m_iterator[n]); }
|
||||||
|
|
||||||
|
const bool operator==(const const_iterator& it) const { return (it.m_iterator == m_iterator); }
|
||||||
|
const bool operator!=(const const_iterator& it) const { return (!(*this == it)); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::vector <headerField*>::const_iterator m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
iterator begin() { return (m_fields.begin()); }
|
||||||
|
iterator end() { return (m_fields.end()); }
|
||||||
|
|
||||||
|
const_iterator begin() const { return (const_iterator(m_fields.begin())); }
|
||||||
|
const_iterator end() const { return (const_iterator(m_fields.end())); }
|
||||||
|
|
||||||
|
// Field insertion
|
||||||
|
void append(const headerField& field);
|
||||||
|
void insert(const iterator it, const headerField& field);
|
||||||
|
|
||||||
|
// Field removing
|
||||||
|
void remove(const iterator it);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// Field count
|
||||||
|
const std::vector <headerField*>::size_type count() const { return (m_fields.size()); }
|
||||||
|
const std::vector <headerField*>::size_type size() const { return (m_fields.size()); }
|
||||||
|
const bool empty() const { return (m_fields.empty()); }
|
||||||
|
|
||||||
|
headerField& front() { return (*m_fields.front()); }
|
||||||
|
const headerField& front() const { return (*m_fields.front()); }
|
||||||
|
headerField& back() { return (*m_fields.back()); }
|
||||||
|
const headerField& back() const { return (*m_fields.back()); }
|
||||||
|
|
||||||
|
fieldsContainer& operator=(const fieldsContainer& c);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void insertSorted(headerField* field);
|
||||||
|
|
||||||
|
std::vector <headerField*> m_fields;
|
||||||
|
|
||||||
|
} fields;
|
||||||
|
|
||||||
|
typedef fieldsContainer::iterator iterator;
|
||||||
|
typedef fieldsContainer::const_iterator const_iterator;
|
||||||
|
|
||||||
|
header& operator=(const header& h);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using component::parse;
|
||||||
|
using component::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HEADER_HPP_INCLUDED
|
266
src/headerField.cpp
Normal file
266
src/headerField.cpp
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "headerField.hpp"
|
||||||
|
#include "headerFieldFactory.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
headerField::headerField()
|
||||||
|
: m_type(Custom), m_name("Undefined")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
headerField::headerField(const string& fieldName)
|
||||||
|
: m_type(Custom), m_name(fieldName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
headerField::~headerField()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
headerField* headerField::clone() const
|
||||||
|
{
|
||||||
|
headerField* field = NULL;
|
||||||
|
|
||||||
|
if (m_type == Custom)
|
||||||
|
field = headerFieldFactory::getInstance()->create(m_name);
|
||||||
|
else
|
||||||
|
field = headerFieldFactory::getInstance()->create(m_type);
|
||||||
|
|
||||||
|
field->copyFrom(*this);
|
||||||
|
|
||||||
|
return (field);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool headerField::operator<(const headerField& field) const
|
||||||
|
{
|
||||||
|
return (m_type < field.m_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
headerField& headerField::operator=(const headerField& field)
|
||||||
|
{
|
||||||
|
copyFrom(field);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void headerField::copyFrom(const headerField& field)
|
||||||
|
{
|
||||||
|
m_type = field.m_type;
|
||||||
|
m_name = field.m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void headerField::generate(utility::outputStream& os, const string::size_type /* maxLineLength */,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
if (m_type == Custom)
|
||||||
|
{
|
||||||
|
os << m_name + ": ";
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
*newLinePos = curLinePos + m_name.length() + 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const string name = typeToName(m_type);
|
||||||
|
|
||||||
|
os << name + ": ";
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
*newLinePos = curLinePos + name.length() + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Return the field type corresponding to the specified name.
|
||||||
|
*
|
||||||
|
* @param name field name
|
||||||
|
* @return field type (see headerField::Types) or headerField::custom
|
||||||
|
* if this is a custom field
|
||||||
|
*/
|
||||||
|
|
||||||
|
const headerField::Types headerField::nameToType(const string& name)
|
||||||
|
{
|
||||||
|
switch (name[0])
|
||||||
|
{
|
||||||
|
case 'B':
|
||||||
|
case 'b':
|
||||||
|
{
|
||||||
|
if (isStringEqualNoCase(name, "bcc", 3)) return (Bcc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'C':
|
||||||
|
case 'c':
|
||||||
|
{
|
||||||
|
if (isStringEqualNoCase(name, "cc", 2)) return (Cc);
|
||||||
|
else if (isStringEqualNoCase(name, "content-type", 12)) return (ContentType);
|
||||||
|
else if (isStringEqualNoCase(name, "content-transfer-encoding", 25)) return (ContentTransferEncoding);
|
||||||
|
else if (isStringEqualNoCase(name, "content-description", 19)) return (ContentDescription);
|
||||||
|
else if (isStringEqualNoCase(name, "content-disposition", 19)) return (ContentDisposition);
|
||||||
|
else if (isStringEqualNoCase(name, "content-id", 10)) return (ContentId);
|
||||||
|
else if (isStringEqualNoCase(name, "content-location", 16)) return (ContentLocation);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
{
|
||||||
|
if (isStringEqualNoCase(name, "date", 4)) return (Date);
|
||||||
|
else if (isStringEqualNoCase(name, "delivered-to", 12)) return (DeliveredTo);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'f':
|
||||||
|
case 'F':
|
||||||
|
{
|
||||||
|
if (isStringEqualNoCase(name, "from", 4)) return (From);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
{
|
||||||
|
if (isStringEqualNoCase(name, "mime-version", 12)) return (MimeVersion);
|
||||||
|
else if (isStringEqualNoCase(name, "message-id", 10)) return (MessageId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'o':
|
||||||
|
case 'O':
|
||||||
|
{
|
||||||
|
if (isStringEqualNoCase(name, "organization", 12)) return (Organization);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
{
|
||||||
|
if (isStringEqualNoCase(name, "received", 8)) return (Received);
|
||||||
|
else if (isStringEqualNoCase(name, "reply-to", 8)) return (ReplyTo);
|
||||||
|
else if (isStringEqualNoCase(name, "return-path", 11)) return (ReturnPath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
{
|
||||||
|
if (isStringEqualNoCase(name, "sender", 6)) return (Sender);
|
||||||
|
else if (isStringEqualNoCase(name, "subject", 7)) return (Subject);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 't':
|
||||||
|
case 'T':
|
||||||
|
{
|
||||||
|
if (isStringEqualNoCase(name, "to", 2)) return (To);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u':
|
||||||
|
case 'U':
|
||||||
|
{
|
||||||
|
if (isStringEqualNoCase(name, "user-agent", 10)) return (UserAgent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Custom);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Return the name for the specified field type.
|
||||||
|
* Eg: returns "From" for headerField::From.
|
||||||
|
*
|
||||||
|
* @param type field type
|
||||||
|
* @return name for the specified field type
|
||||||
|
*/
|
||||||
|
|
||||||
|
const string headerField::typeToName(const Types type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case From: return "From";
|
||||||
|
case Sender: return "Sender";
|
||||||
|
case To: return "To";
|
||||||
|
case Cc: return "Cc";
|
||||||
|
case Bcc: return "Bcc";
|
||||||
|
case Date: return "Date";
|
||||||
|
case Received: return "Received";
|
||||||
|
case Subject: return "Subject";
|
||||||
|
case ReplyTo: return "Reply-To";
|
||||||
|
case Organization: return "Organization";
|
||||||
|
case DeliveredTo: return "Delivered-To";
|
||||||
|
case UserAgent: return "User-Agent";
|
||||||
|
case ReturnPath: return "Return-Path";
|
||||||
|
case ContentType: return "Content-Type";
|
||||||
|
case ContentTransferEncoding: return "Content-Transfer-Encoding";
|
||||||
|
case ContentDescription: return "Content-Description";
|
||||||
|
case MimeVersion: return "Mime-Version";
|
||||||
|
case ContentDisposition: return "Content-Disposition";
|
||||||
|
case ContentId: return "Content-Id";
|
||||||
|
case MessageId: return "Message-Id";
|
||||||
|
case ContentLocation: return "Content-Location";
|
||||||
|
|
||||||
|
case Custom:
|
||||||
|
case Last:
|
||||||
|
return "?";
|
||||||
|
};
|
||||||
|
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Return the type of this field.
|
||||||
|
*
|
||||||
|
* @return field type (see headerField::Types)
|
||||||
|
*/
|
||||||
|
|
||||||
|
const headerField::Types headerField::type() const
|
||||||
|
{
|
||||||
|
return (m_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Return the name of this field.
|
||||||
|
*
|
||||||
|
* @return field name
|
||||||
|
*/
|
||||||
|
|
||||||
|
const string headerField::name() const
|
||||||
|
{
|
||||||
|
return ((m_type == Custom) ? m_name : typeToName(m_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Check whether this field is a custom field.
|
||||||
|
*
|
||||||
|
* @return true if the field is a custom field, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
const bool headerField::isCustom() const
|
||||||
|
{
|
||||||
|
return (m_type == Custom);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
113
src/headerField.hpp
Normal file
113
src/headerField.hpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_HEADERFIELD_HPP_INCLUDED
|
||||||
|
#define VMIME_HEADERFIELD_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** Base class for header fields.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class headerField : public component
|
||||||
|
{
|
||||||
|
friend class headerFieldFactory;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
headerField();
|
||||||
|
headerField(const string& fieldName);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
~headerField();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Header field types (in the order in which they will appear
|
||||||
|
// in the message header)
|
||||||
|
enum Types
|
||||||
|
{
|
||||||
|
Received, // Relay
|
||||||
|
From, // Expeditor
|
||||||
|
Sender, // Sender
|
||||||
|
ReplyTo, // Reply-To
|
||||||
|
To, // Recipient(s)
|
||||||
|
Cc, // Carbon copy recipient(s)
|
||||||
|
Bcc, // Blind carbon-copy recipient(s)
|
||||||
|
Date, // Date sent
|
||||||
|
Subject, // Subject
|
||||||
|
Organization, // Organization
|
||||||
|
UserAgent, // User agent
|
||||||
|
DeliveredTo, // Delivered-To
|
||||||
|
ReturnPath, // Return-Path
|
||||||
|
MimeVersion, // Mime-Version
|
||||||
|
MessageId, // Message-Id
|
||||||
|
ContentType, // Content-Type
|
||||||
|
ContentTransferEncoding, // Content-Transfer-Encoding
|
||||||
|
ContentDescription, // Content-Description
|
||||||
|
ContentDisposition, // Content-Disposition
|
||||||
|
ContentId, // Content-Id
|
||||||
|
ContentLocation, // Content-Location
|
||||||
|
|
||||||
|
Custom, // Unknown or custom field (eg. X-Priority, X-Mailer, etc.)
|
||||||
|
|
||||||
|
Last
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Types m_type;
|
||||||
|
string m_name; // In case of custom field
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const bool operator<(const headerField& field) const;
|
||||||
|
|
||||||
|
const Types type() const;
|
||||||
|
const string name() const;
|
||||||
|
|
||||||
|
const bool isCustom() const;
|
||||||
|
|
||||||
|
virtual void copyFrom(const headerField& field);
|
||||||
|
headerField& operator=(const headerField& field);
|
||||||
|
headerField* clone() const;
|
||||||
|
|
||||||
|
static const Types nameToType(const string& name);
|
||||||
|
static const string typeToName(const Types type);
|
||||||
|
|
||||||
|
|
||||||
|
// Component assembling
|
||||||
|
using component::generate;
|
||||||
|
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HEADERFIELD_HPP_INCLUDED
|
139
src/headerFieldFactory.cpp
Normal file
139
src/headerFieldFactory.cpp
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "headerFieldFactory.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
|
||||||
|
#include "defaultField.hpp"
|
||||||
|
|
||||||
|
#include "mailboxField.hpp"
|
||||||
|
#include "addressListField.hpp"
|
||||||
|
#include "addressListField.hpp"
|
||||||
|
#include "addressListField.hpp"
|
||||||
|
#include "mailboxField.hpp"
|
||||||
|
#include "dateField.hpp"
|
||||||
|
#include "relayField.hpp"
|
||||||
|
#include "textField.hpp"
|
||||||
|
#include "mailboxField.hpp"
|
||||||
|
#include "contentTypeField.hpp"
|
||||||
|
#include "contentEncodingField.hpp"
|
||||||
|
#include "contentDispositionField.hpp"
|
||||||
|
#include "messageIdField.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
headerFieldFactory::headerFieldFactory()
|
||||||
|
{
|
||||||
|
// Register some default field types
|
||||||
|
registerType <mailboxField>(headerField::From);
|
||||||
|
registerType <addressListField>(headerField::To);
|
||||||
|
registerType <addressListField>(headerField::Cc);
|
||||||
|
registerType <addressListField>(headerField::Bcc);
|
||||||
|
registerType <mailboxField>(headerField::Sender);
|
||||||
|
registerType <dateField>(headerField::Date);
|
||||||
|
registerType <relayField>(headerField::Received);
|
||||||
|
registerType <textField>(headerField::Subject);
|
||||||
|
registerType <mailboxField>(headerField::ReplyTo);
|
||||||
|
registerType <mailboxField>(headerField::DeliveredTo);
|
||||||
|
registerType <textField>(headerField::Organization);
|
||||||
|
registerType <textField>(headerField::UserAgent);
|
||||||
|
registerType <mailboxField>(headerField::ReturnPath);
|
||||||
|
registerType <contentTypeField>(headerField::ContentType);
|
||||||
|
registerType <contentEncodingField>(headerField::ContentTransferEncoding);
|
||||||
|
registerType <textField>(headerField::ContentDescription);
|
||||||
|
registerType <defaultField>(headerField::MimeVersion);
|
||||||
|
registerType <contentDispositionField>(headerField::ContentDisposition);
|
||||||
|
registerType <messageIdField>(headerField::ContentId);
|
||||||
|
registerType <messageIdField>(headerField::MessageId);
|
||||||
|
registerType <defaultField>(headerField::ContentLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
headerFieldFactory::~headerFieldFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
headerField* headerFieldFactory::create
|
||||||
|
(const string& name, const string& body)
|
||||||
|
{
|
||||||
|
const headerField::Types type = headerField::nameToType(name);
|
||||||
|
|
||||||
|
if (type != headerField::Custom)
|
||||||
|
{
|
||||||
|
return (create(type, name, body));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NameMap::const_iterator pos = m_nameMap.find(toLower(name));
|
||||||
|
headerField* field = NULL;
|
||||||
|
|
||||||
|
if (pos != m_nameMap.end())
|
||||||
|
{
|
||||||
|
field = ((*pos).second)();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
field = new defaultField;
|
||||||
|
}
|
||||||
|
|
||||||
|
field->m_type = headerField::Custom;
|
||||||
|
field->m_name = name;
|
||||||
|
|
||||||
|
if (body != NULL_STRING)
|
||||||
|
field->parse(body);
|
||||||
|
|
||||||
|
return (field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
headerField* headerFieldFactory::create(const headerField::Types type,
|
||||||
|
const string& name, const string& body)
|
||||||
|
{
|
||||||
|
if (type == headerField::Custom)
|
||||||
|
{
|
||||||
|
return (create(name, body));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TypeMap::const_iterator pos = m_typeMap.find(type);
|
||||||
|
|
||||||
|
if (pos != m_typeMap.end())
|
||||||
|
{
|
||||||
|
headerField* field = ((*pos).second)();
|
||||||
|
|
||||||
|
field->m_type = type;
|
||||||
|
if (name != NULL_STRING) field->m_name = name;
|
||||||
|
if (body != NULL_STRING) field->parse(body);
|
||||||
|
|
||||||
|
return (field);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw exceptions::bad_field_type();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
85
src/headerFieldFactory.hpp
Normal file
85
src/headerFieldFactory.hpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_HEADERFIELDFACTORY_HPP_INCLUDED
|
||||||
|
#define VMIME_HEADERFIELDFACTORY_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "headerField.hpp"
|
||||||
|
#include "utility/singleton.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class headerFieldFactory : public utility::singleton <headerFieldFactory>
|
||||||
|
{
|
||||||
|
friend class utility::singleton <headerFieldFactory>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
headerFieldFactory();
|
||||||
|
~headerFieldFactory();
|
||||||
|
|
||||||
|
typedef headerField* (*AllocFunc)(void);
|
||||||
|
typedef std::map <string, AllocFunc> NameMap;
|
||||||
|
typedef std::map <headerField::Types, AllocFunc> TypeMap;
|
||||||
|
|
||||||
|
NameMap m_nameMap;
|
||||||
|
TypeMap m_typeMap;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
template <class TYPE>
|
||||||
|
class registerer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static headerField* creator()
|
||||||
|
{
|
||||||
|
// Allocate a new object
|
||||||
|
return new TYPE();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void registerName(const string& name)
|
||||||
|
{
|
||||||
|
m_nameMap.insert(NameMap::value_type(toLower(name), ®isterer<T>::creator));
|
||||||
|
}
|
||||||
|
|
||||||
|
headerField* create(const string& name, const string& body = NULL_STRING);
|
||||||
|
headerField* create(const headerField::Types type, const string& name = NULL_STRING, const string& body = NULL_STRING);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void registerType(const headerField::Types type)
|
||||||
|
{
|
||||||
|
m_typeMap.insert(TypeMap::value_type(type, ®isterer<T>::creator));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HEADERFIELDFACTORY_HPP_INCLUDED
|
371
src/htmlTextPart.cpp
Normal file
371
src/htmlTextPart.cpp
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "htmlTextPart.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
htmlTextPart::~htmlTextPart()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const mediaType htmlTextPart::type() const
|
||||||
|
{
|
||||||
|
return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const int htmlTextPart::getPartCount() const
|
||||||
|
{
|
||||||
|
return (m_plainText.empty() ? 1 : 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void htmlTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const
|
||||||
|
{
|
||||||
|
// Plain text
|
||||||
|
if (!m_plainText.empty())
|
||||||
|
{
|
||||||
|
// -- Create a new part
|
||||||
|
bodyPart* part = new bodyPart();
|
||||||
|
parent.body().parts.append(part);
|
||||||
|
|
||||||
|
// -- Set header fields
|
||||||
|
part->header().fields.ContentType() = mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN);
|
||||||
|
part->header().fields.ContentType().charset() = m_charset;
|
||||||
|
part->header().fields.ContentTransferEncoding() = encoding(encodingTypes::QUOTED_PRINTABLE);
|
||||||
|
|
||||||
|
// -- Set contents
|
||||||
|
part->body().contents() = m_plainText;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTML text
|
||||||
|
// -- Create a new part
|
||||||
|
bodyPart* htmlPart = new bodyPart();
|
||||||
|
|
||||||
|
// -- Set header fields
|
||||||
|
htmlPart->header().fields.ContentType() = mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML);
|
||||||
|
htmlPart->header().fields.ContentType().charset() = m_charset;
|
||||||
|
htmlPart->header().fields.ContentTransferEncoding() = encoding(encodingTypes::QUOTED_PRINTABLE);
|
||||||
|
|
||||||
|
// -- Set contents
|
||||||
|
htmlPart->body().contents() = m_text;
|
||||||
|
|
||||||
|
// Handle the case we have embedded objects
|
||||||
|
if (!embeddedObjects.empty())
|
||||||
|
{
|
||||||
|
// Create a "multipart/related" body part
|
||||||
|
bodyPart* relPart = new bodyPart();
|
||||||
|
parent.body().parts.append(relPart);
|
||||||
|
|
||||||
|
relPart->header().fields.ContentType() = mediaType
|
||||||
|
(mediaTypes::MULTIPART, mediaTypes::MULTIPART_RELATED);
|
||||||
|
|
||||||
|
// Add the HTML part into this part
|
||||||
|
relPart->body().parts.append(htmlPart);
|
||||||
|
|
||||||
|
// Also add images into this part
|
||||||
|
for (embeddedObjectsContainer::const_iterator i = embeddedObjects.begin() ;
|
||||||
|
i != embeddedObjects.end() ; ++i)
|
||||||
|
{
|
||||||
|
bodyPart* objPart = new bodyPart();
|
||||||
|
relPart->body().parts.append(objPart);
|
||||||
|
|
||||||
|
string id = (*i).id();
|
||||||
|
|
||||||
|
if (id.substr(0, 4) == "CID:")
|
||||||
|
id = id.substr(4);
|
||||||
|
|
||||||
|
objPart->header().fields.ContentType() = (*i).type();
|
||||||
|
objPart->header().fields.ContentId() = messageId("<" + id + ">");
|
||||||
|
objPart->header().fields.ContentDisposition() = disposition(dispositionTypes::INLINE);
|
||||||
|
objPart->header().fields.ContentTransferEncoding() = (*i).encoding();
|
||||||
|
//encoding(encodingTypes::BASE64);
|
||||||
|
|
||||||
|
objPart->body().contents() = (*i).data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Add the HTML part into the parent part
|
||||||
|
parent.body().parts.append(htmlPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void htmlTextPart::findEmbeddedParts(const bodyPart& part,
|
||||||
|
std::vector <const bodyPart*>& cidParts, std::vector <const bodyPart*>& locParts)
|
||||||
|
{
|
||||||
|
for (body::const_iterator p = part.body().parts.begin() ; p != part.body().parts.end() ; ++p)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dynamic_cast<messageIdField&>((*p).header().fields.find(headerField::ContentId));
|
||||||
|
cidParts.push_back(&(*p));
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_field)
|
||||||
|
{
|
||||||
|
// No "Content-id" field.
|
||||||
|
// Maybe there is a "Content-Location" field...
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dynamic_cast<messageIdField&>((*p).header().fields.find(headerField::ContentId));
|
||||||
|
locParts.push_back(&(*p));
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_field)
|
||||||
|
{
|
||||||
|
// No "Content-Location" field.
|
||||||
|
// Cannot be an embedded object since it cannot be referenced in HTML text.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
findEmbeddedParts((*p), cidParts, locParts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void htmlTextPart::addEmbeddedObject(const bodyPart& part, const string& id)
|
||||||
|
{
|
||||||
|
mediaType type;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
|
||||||
|
(part.header().fields.find(headerField::ContentType));
|
||||||
|
|
||||||
|
type = ctf.value();
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_field)
|
||||||
|
{
|
||||||
|
// No "Content-type" field: assume "application/octet-stream".
|
||||||
|
}
|
||||||
|
|
||||||
|
embeddedObjects.m_list.push_back(new embeddedObject
|
||||||
|
(part.body().contents(), part.body().encoding(), id, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void htmlTextPart::parse(const bodyPart& message, const bodyPart& parent, const bodyPart& textPart)
|
||||||
|
{
|
||||||
|
// Search for possible embedded objects in the _whole_ message.
|
||||||
|
std::vector <const bodyPart*> cidParts;
|
||||||
|
std::vector <const bodyPart*> locParts;
|
||||||
|
|
||||||
|
findEmbeddedParts(message, cidParts, locParts);
|
||||||
|
|
||||||
|
// Extract HTML text
|
||||||
|
std::ostringstream oss;
|
||||||
|
utility::outputStreamAdapter adapter(oss);
|
||||||
|
|
||||||
|
textPart.body().contents().extract(adapter);
|
||||||
|
|
||||||
|
const string data = oss.str();
|
||||||
|
|
||||||
|
m_text = textPart.body().contents();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
|
||||||
|
(textPart.header().fields.find(headerField::ContentType));
|
||||||
|
|
||||||
|
m_charset = ctf.charset();
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_field)
|
||||||
|
{
|
||||||
|
// No "Content-type" field.
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_parameter)
|
||||||
|
{
|
||||||
|
// No "charset" parameter.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract embedded objects. The algorithm is quite simple: for each previously
|
||||||
|
// found inline part, we check if its CID/Location is contained in the HTML text.
|
||||||
|
for (std::vector <const bodyPart*>::const_iterator p = cidParts.begin() ; p != cidParts.end() ; ++p)
|
||||||
|
{
|
||||||
|
const messageIdField& midField = dynamic_cast<messageIdField&>
|
||||||
|
((**p).header().fields.find(headerField::ContentId));
|
||||||
|
|
||||||
|
const string searchFor("CID:" + midField.value().id());
|
||||||
|
|
||||||
|
if (data.find(searchFor) != string::npos)
|
||||||
|
{
|
||||||
|
// This part is referenced in the HTML text.
|
||||||
|
// Add it to the embedded object list.
|
||||||
|
addEmbeddedObject(**p, "CID:" + midField.value().id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector <const bodyPart*>::const_iterator p = locParts.begin() ; p != locParts.end() ; ++p)
|
||||||
|
{
|
||||||
|
const defaultField& locField = dynamic_cast<defaultField&>
|
||||||
|
((**p).header().fields.find(headerField::ContentLocation));
|
||||||
|
|
||||||
|
if (data.find(locField.value()) != string::npos)
|
||||||
|
{
|
||||||
|
// This part is referenced in the HTML text.
|
||||||
|
// Add it to the embedded object list.
|
||||||
|
addEmbeddedObject(**p, locField.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract plain text, if any.
|
||||||
|
findPlainTextPart(message, parent, textPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& parent, const bodyPart& textPart)
|
||||||
|
{
|
||||||
|
// We search for the nearest "multipart/alternative" part.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
|
||||||
|
(part.header().fields.find(headerField::ContentType));
|
||||||
|
|
||||||
|
if (ctf.value().type() == mediaTypes::MULTIPART &&
|
||||||
|
ctf.value().subType() == mediaTypes::MULTIPART_ALTERNATIVE)
|
||||||
|
{
|
||||||
|
bodyPart const* foundPart = NULL;
|
||||||
|
|
||||||
|
for (body::const_iterator p = part.body().parts.begin() ; !foundPart && p != part.body().parts.end() ; ++p)
|
||||||
|
{
|
||||||
|
if (&(*p) == &parent || // if "text/html" is in "multipart/related"
|
||||||
|
&(*p) == &textPart) // if not...
|
||||||
|
{
|
||||||
|
foundPart = &(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundPart)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
// Now, search for the alternative plain text part
|
||||||
|
for (body::const_iterator p = part.body().parts.begin() ;
|
||||||
|
!found && p != part.body().parts.end() ; ++p)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const contentTypeField& ctf = dynamic_cast<contentTypeField&>
|
||||||
|
((*p).header().fields.find(headerField::ContentType));
|
||||||
|
|
||||||
|
if (ctf.value().type() == mediaTypes::TEXT &&
|
||||||
|
ctf.value().subType() == mediaTypes::TEXT_PLAIN)
|
||||||
|
{
|
||||||
|
m_plainText = (*p).body().contents();
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_field)
|
||||||
|
{
|
||||||
|
// No "Content-type" field.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we don't have found the plain text part here, it means that
|
||||||
|
// it does not exists (the MUA which built this message probably
|
||||||
|
// did not include it...).
|
||||||
|
return (found);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (exceptions::no_such_field)
|
||||||
|
{
|
||||||
|
// No "Content-type" field.
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (body::const_iterator p = part.body().parts.begin() ; !found && p != part.body().parts.end() ; ++p)
|
||||||
|
{
|
||||||
|
found = findPlainTextPart(*p, parent, textPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (found);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Embedded objects container //
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
htmlTextPart::embeddedObjectsContainer::~embeddedObjectsContainer()
|
||||||
|
{
|
||||||
|
free_container(m_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const htmlTextPart::embeddedObject& htmlTextPart::embeddedObjectsContainer::find(const string& id) const
|
||||||
|
{
|
||||||
|
for (std::vector <embeddedObject*>::const_iterator o = m_list.begin() ; o != m_list.end() ; ++o)
|
||||||
|
{
|
||||||
|
if ((**o).id() == id)
|
||||||
|
return (**o);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw exceptions::no_object_found();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool htmlTextPart::embeddedObjectsContainer::has(const string& id) const
|
||||||
|
{
|
||||||
|
for (std::vector <embeddedObject*>::const_iterator o = m_list.begin() ; o != m_list.end() ; ++o)
|
||||||
|
{
|
||||||
|
if ((**o).id() == id)
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string htmlTextPart::embeddedObjectsContainer::add
|
||||||
|
(const contentHandler& data, const vmime::encoding& enc, const mediaType& type)
|
||||||
|
{
|
||||||
|
const messageId mid(messageId::generateId());
|
||||||
|
const string id = "CID:" + mid.id();
|
||||||
|
|
||||||
|
m_list.push_back(new embeddedObject(data, enc, id, type));
|
||||||
|
|
||||||
|
return (id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string htmlTextPart::embeddedObjectsContainer::add
|
||||||
|
(const contentHandler& data, const mediaType& type)
|
||||||
|
{
|
||||||
|
return (add(data, encoding::decide(data), type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const string htmlTextPart::embeddedObjectsContainer::add
|
||||||
|
(const string& data, const mediaType& type)
|
||||||
|
{
|
||||||
|
return (add(contentHandler(data), encoding::decide(data), type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
180
src/htmlTextPart.hpp
Normal file
180
src/htmlTextPart.hpp
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_HTMLTEXTPART_HPP_INCLUDED
|
||||||
|
#define VMIME_HTMLTEXTPART_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "textPart.hpp"
|
||||||
|
#include "messageId.hpp"
|
||||||
|
#include "encoding.hpp"
|
||||||
|
|
||||||
|
#include "contentHandler.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class htmlTextPart : public textPart
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
~htmlTextPart();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const mediaType type() const;
|
||||||
|
|
||||||
|
const vmime::charset& charset() const { return (m_charset); }
|
||||||
|
vmime::charset& charset() { return (m_charset); }
|
||||||
|
|
||||||
|
const contentHandler& plainText() const { return (m_plainText); }
|
||||||
|
contentHandler& plainText() { return (m_plainText); }
|
||||||
|
|
||||||
|
const contentHandler& text() const { return (m_text); }
|
||||||
|
contentHandler& text() { return (m_text); }
|
||||||
|
|
||||||
|
// Embedded object (eg. image for <IMG> tag)
|
||||||
|
class embeddedObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
embeddedObject(const contentHandler& data, const vmime::encoding& enc,
|
||||||
|
const string& id, const mediaType& type)
|
||||||
|
: m_data(data), m_encoding(enc), m_id(id), m_type(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const contentHandler& data() const { return (m_data); }
|
||||||
|
const vmime::encoding& encoding() const { return (m_encoding); }
|
||||||
|
const string& id() const { return (m_id); }
|
||||||
|
const mediaType& type() const { return (m_type); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
contentHandler m_data;
|
||||||
|
vmime::encoding m_encoding;
|
||||||
|
string m_id;
|
||||||
|
mediaType m_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Embedded objects container
|
||||||
|
class embeddedObjectsContainer
|
||||||
|
{
|
||||||
|
friend class htmlTextPart;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
~embeddedObjectsContainer();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Test the existence/get an embedded object given its identifier.
|
||||||
|
const bool has(const string& id) const;
|
||||||
|
const embeddedObject& find(const string& id) const;
|
||||||
|
|
||||||
|
// Embed an object and returns a string which identifies it.
|
||||||
|
const string add(const string& data, const mediaType& type);
|
||||||
|
const string add(const contentHandler& data, const mediaType& type);
|
||||||
|
const string add(const contentHandler& data, const encoding& enc, const mediaType& type);
|
||||||
|
|
||||||
|
// Embedded objects enumerator
|
||||||
|
class const_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::vector <embeddedObject*>::const_iterator::difference_type difference_type;
|
||||||
|
|
||||||
|
const_iterator(std::vector <embeddedObject*>::const_iterator it) : m_iterator(it) { }
|
||||||
|
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
|
||||||
|
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
|
||||||
|
const embeddedObject& operator*() const { return (**m_iterator); }
|
||||||
|
const embeddedObject* operator->() const { return (*m_iterator); }
|
||||||
|
|
||||||
|
const_iterator& operator++() { ++m_iterator; return (*this); }
|
||||||
|
const_iterator operator++(int) { const_iterator i(*this); ++m_iterator; return (i); }
|
||||||
|
|
||||||
|
const_iterator& operator--() { --m_iterator; return (*this); }
|
||||||
|
const_iterator operator--(int) { const_iterator i(*this); --m_iterator; return (i); }
|
||||||
|
|
||||||
|
const_iterator& operator+=(difference_type n) { m_iterator += n; return (*this); }
|
||||||
|
const_iterator& operator-=(difference_type n) { m_iterator -= n; return (*this); }
|
||||||
|
|
||||||
|
const_iterator operator-(difference_type x) const { return const_iterator(m_iterator - x); }
|
||||||
|
|
||||||
|
const embeddedObject& operator[](difference_type n) const { return *(m_iterator[n]); }
|
||||||
|
|
||||||
|
const bool operator==(const const_iterator& it) const { return (it.m_iterator == m_iterator); }
|
||||||
|
const bool operator!=(const const_iterator& it) const { return (!(*this == it)); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::vector <embeddedObject*>::const_iterator m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const_iterator begin() const { return (const_iterator(m_list.begin())); }
|
||||||
|
const_iterator end() const { return (const_iterator(m_list.end())); }
|
||||||
|
|
||||||
|
// Object count
|
||||||
|
const std::vector <embeddedObject*>::size_type count() const { return (m_list.size()); }
|
||||||
|
const std::vector <embeddedObject*>::size_type size() const { return (m_list.size()); }
|
||||||
|
const bool empty() const { return (m_list.empty()); }
|
||||||
|
|
||||||
|
embeddedObject& front() { return (*m_list.front()); }
|
||||||
|
const embeddedObject& front() const { return (*m_list.front()); }
|
||||||
|
embeddedObject& back() { return (*m_list.back()); }
|
||||||
|
const embeddedObject& back() const { return (*m_list.back()); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::vector <embeddedObject*> m_list;
|
||||||
|
|
||||||
|
} embeddedObjects;
|
||||||
|
|
||||||
|
typedef embeddedObjectsContainer::const_iterator const_iterator;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
contentHandler m_plainText;
|
||||||
|
contentHandler m_text;
|
||||||
|
vmime::charset m_charset;
|
||||||
|
|
||||||
|
void findEmbeddedParts(const bodyPart& part, std::vector <const bodyPart*>& cidParts, std::vector <const bodyPart*>& locParts);
|
||||||
|
void addEmbeddedObject(const bodyPart& part, const string& id);
|
||||||
|
|
||||||
|
bool findPlainTextPart(const bodyPart& part, const bodyPart& parent, const bodyPart& textPart);
|
||||||
|
|
||||||
|
const int getPartCount() const;
|
||||||
|
|
||||||
|
void generateIn(bodyPart& message, bodyPart& parent) const;
|
||||||
|
virtual void parse(const bodyPart& message, const bodyPart& parent, const bodyPart& textPart);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_HTMLTEXTPART_HPP_INCLUDED
|
450
src/mailbox.cpp
Normal file
450
src/mailbox.cpp
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "mailbox.hpp"
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
mailbox::mailbox()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mailbox::mailbox(const class mailbox& mailbox)
|
||||||
|
: address(), m_name(mailbox.m_name), m_email(mailbox.m_email)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mailbox::mailbox(const string& email)
|
||||||
|
: m_email(email)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mailbox::mailbox(const text& name, const string& email)
|
||||||
|
: m_name(name), m_email(email)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
RFC #2822:
|
||||||
|
3.4. ADDRESS SPECIFICATION
|
||||||
|
|
||||||
|
mailbox = name-addr / addr-spec
|
||||||
|
|
||||||
|
name-addr = [display-name] angle-addr
|
||||||
|
|
||||||
|
angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void mailbox::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
const string::value_type* const pend = buffer.data() + end;
|
||||||
|
const string::value_type* const pstart = buffer.data() + position;
|
||||||
|
const string::value_type* p = pstart;
|
||||||
|
|
||||||
|
// Ignore blank spaces at the beginning
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
|
||||||
|
// Current state for parsing machine
|
||||||
|
enum States
|
||||||
|
{
|
||||||
|
State_None,
|
||||||
|
State_Name,
|
||||||
|
State_Address
|
||||||
|
};
|
||||||
|
|
||||||
|
States state = State_Name; // let's start with name, we will see later (*)
|
||||||
|
|
||||||
|
// Temporary buffers for extracted name and address
|
||||||
|
string name;
|
||||||
|
string address;
|
||||||
|
|
||||||
|
while (p < pend)
|
||||||
|
{
|
||||||
|
if (state == State_Name)
|
||||||
|
{
|
||||||
|
if (*p == '<')
|
||||||
|
{
|
||||||
|
state = State_Address;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == '"') // Quoted string
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
|
||||||
|
bool escaped = false;
|
||||||
|
|
||||||
|
while (p < pend)
|
||||||
|
{
|
||||||
|
if (escaped)
|
||||||
|
{
|
||||||
|
name += *p;
|
||||||
|
escaped = false;
|
||||||
|
}
|
||||||
|
else if (*p == '\\')
|
||||||
|
{
|
||||||
|
escaped = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*p == '"')
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name += *p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool escaped = false;
|
||||||
|
int comment = 0;
|
||||||
|
|
||||||
|
while (p < pend)
|
||||||
|
{
|
||||||
|
if (escaped)
|
||||||
|
{
|
||||||
|
if (!comment) name += *p;
|
||||||
|
escaped = false;
|
||||||
|
}
|
||||||
|
else if (comment)
|
||||||
|
{
|
||||||
|
if (*p == '\\')
|
||||||
|
escaped = true;
|
||||||
|
else if (*p == '(')
|
||||||
|
++comment;
|
||||||
|
else if (*p == ')')
|
||||||
|
--comment;
|
||||||
|
}
|
||||||
|
else if (*p == '\\')
|
||||||
|
{
|
||||||
|
escaped = true;
|
||||||
|
}
|
||||||
|
else if (*p == '(')
|
||||||
|
{
|
||||||
|
++comment;
|
||||||
|
}
|
||||||
|
else if (*p == '<')
|
||||||
|
{
|
||||||
|
// Erase any space between display name and <address>
|
||||||
|
string::iterator q = name.end();
|
||||||
|
for ( ; q != name.begin() && isspace(*(q - 1)) ; --q);
|
||||||
|
name.erase(q, name.end());
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (/* isspace(*p) || */ *p == '@')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name += *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p < pend && *p == '@')
|
||||||
|
{
|
||||||
|
// (*) Actually, we were parsing the local-part of an address
|
||||||
|
// and not a display name...
|
||||||
|
address = name;
|
||||||
|
name.clear();
|
||||||
|
|
||||||
|
bool escaped = false;
|
||||||
|
int comment = 0;
|
||||||
|
|
||||||
|
while (p < pend)
|
||||||
|
{
|
||||||
|
if (escaped)
|
||||||
|
{
|
||||||
|
if (!comment) address += *p;
|
||||||
|
escaped = false;
|
||||||
|
}
|
||||||
|
else if (comment)
|
||||||
|
{
|
||||||
|
if (*p == '\\')
|
||||||
|
escaped = true;
|
||||||
|
else if (*p == '(')
|
||||||
|
++comment;
|
||||||
|
else if (*p == ')')
|
||||||
|
--comment;
|
||||||
|
}
|
||||||
|
else if (*p == '\\')
|
||||||
|
{
|
||||||
|
escaped = true;
|
||||||
|
}
|
||||||
|
else if (*p == '(')
|
||||||
|
{
|
||||||
|
++comment;
|
||||||
|
}
|
||||||
|
else if (isspace(*p))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
address += *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
state = State_None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (state == State_Address)
|
||||||
|
{
|
||||||
|
// Skip '<' character
|
||||||
|
if (*p == '<')
|
||||||
|
++p;
|
||||||
|
|
||||||
|
bool escaped = false;
|
||||||
|
int comment = 0;
|
||||||
|
|
||||||
|
while (p < pend)
|
||||||
|
{
|
||||||
|
if (escaped)
|
||||||
|
{
|
||||||
|
if (!comment) address += *p;
|
||||||
|
escaped = false;
|
||||||
|
}
|
||||||
|
else if (comment)
|
||||||
|
{
|
||||||
|
if (*p == '\\')
|
||||||
|
escaped = true;
|
||||||
|
else if (*p == '(')
|
||||||
|
++comment;
|
||||||
|
else if (*p == ')')
|
||||||
|
--comment;
|
||||||
|
}
|
||||||
|
else if (*p == '(')
|
||||||
|
{
|
||||||
|
++comment;
|
||||||
|
}
|
||||||
|
else if (*p == '\\')
|
||||||
|
{
|
||||||
|
escaped = true;
|
||||||
|
}
|
||||||
|
else if (*p == '<')
|
||||||
|
{
|
||||||
|
// If we found a '<' here, it means that the address
|
||||||
|
// starts _only_ here...and the stuff we have parsed
|
||||||
|
// before belongs actually to the display name!
|
||||||
|
name += address;
|
||||||
|
address.clear();
|
||||||
|
}
|
||||||
|
else if (*p == '>')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!isspace(*p))
|
||||||
|
{
|
||||||
|
address += *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (p < pend && isspace(*p)) ++p;
|
||||||
|
|
||||||
|
if (p < pend)
|
||||||
|
{
|
||||||
|
//if (*p == '<')
|
||||||
|
state = State_Address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeAndUnfoldText(name, m_name);
|
||||||
|
m_email = address;
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = position + (p - pstart);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailbox::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
if (m_name.empty())
|
||||||
|
{
|
||||||
|
bool newLine = false;
|
||||||
|
|
||||||
|
// No display name is specified, only email address.
|
||||||
|
if (curLinePos /* + 2 */ + m_email.length() > maxLineLength)
|
||||||
|
{
|
||||||
|
os << NEW_LINE_SEQUENCE;
|
||||||
|
newLine = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//os << "<" << m_email << ">";
|
||||||
|
os << m_email;
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
{
|
||||||
|
*newLinePos = curLinePos + m_email.length() /* + 2 */;
|
||||||
|
if (newLine) *newLinePos += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We have to encode the name:
|
||||||
|
// - if it contains characters in a charset different from "US-ASCII",
|
||||||
|
// - and/or if it contains one or more of these special chars:
|
||||||
|
// SPACE TAB " ; , < > ( ) @ / ? . = :
|
||||||
|
|
||||||
|
// Check whether there are words that are not "US-ASCII"
|
||||||
|
// and/or contain the special chars.
|
||||||
|
bool forceEncode = false;
|
||||||
|
|
||||||
|
for (text::const_iterator w = m_name.begin() ; !forceEncode && w != m_name.end() ; ++w)
|
||||||
|
{
|
||||||
|
if ((*w).charset() == charset(charsets::US_ASCII))
|
||||||
|
{
|
||||||
|
const string& buffer = (*w).buffer();
|
||||||
|
|
||||||
|
for (string::const_iterator c = buffer.begin() ;
|
||||||
|
!forceEncode && c != buffer.end() ; ++c)
|
||||||
|
{
|
||||||
|
switch (*c)
|
||||||
|
{
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
case ';':
|
||||||
|
case ',':
|
||||||
|
case '<': case '>':
|
||||||
|
case '(': case ')':
|
||||||
|
case '@':
|
||||||
|
case '/':
|
||||||
|
case '?':
|
||||||
|
case '.':
|
||||||
|
case '=':
|
||||||
|
case ':':
|
||||||
|
case '"':
|
||||||
|
|
||||||
|
forceEncode = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
forceEncode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string::size_type pos = curLinePos;
|
||||||
|
bool newLine = true;
|
||||||
|
|
||||||
|
encodeAndFoldText(os, m_name, maxLineLength, pos, &pos,
|
||||||
|
forceEncode ? encodeAndFoldFlags::forceEncoding : encodeAndFoldFlags::none);
|
||||||
|
|
||||||
|
if (pos + m_email.length() + 3 > maxLineLength)
|
||||||
|
{
|
||||||
|
os << NEW_LINE_SEQUENCE;
|
||||||
|
newLine = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
os << " <" << m_email << ">";
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
{
|
||||||
|
*newLinePos = pos + m_email.length() + 3;
|
||||||
|
if (newLine) *newLinePos += NEW_LINE_SEQUENCE.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool mailbox::operator==(const class mailbox& mailbox) const
|
||||||
|
{
|
||||||
|
return (m_name == mailbox.m_name && m_email == mailbox.m_email);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool mailbox::operator!=(const class mailbox& mailbox) const
|
||||||
|
{
|
||||||
|
return !(*this == mailbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailbox::copyFrom(const address& addr)
|
||||||
|
{
|
||||||
|
const mailbox& source = dynamic_cast<const mailbox&>(addr);
|
||||||
|
|
||||||
|
m_name = source.m_name;
|
||||||
|
m_email = source.m_email;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
address* mailbox::clone() const
|
||||||
|
{
|
||||||
|
return new mailbox(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool mailbox::empty() const
|
||||||
|
{
|
||||||
|
return (m_email.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailbox::clear()
|
||||||
|
{
|
||||||
|
m_name.clear();
|
||||||
|
m_email.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool mailbox::isGroup() const
|
||||||
|
{
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
105
src/mailbox.hpp
Normal file
105
src/mailbox.hpp
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_MAILBOX_HPP_INCLUDED
|
||||||
|
#define VMIME_MAILBOX_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "address.hpp"
|
||||||
|
#include "text.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** A mailbox: full name + email (basic type).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class mailbox : public address
|
||||||
|
{
|
||||||
|
friend class mailboxGroup;
|
||||||
|
friend class mailboxField;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
mailbox();
|
||||||
|
mailbox(const class mailbox& mailbox);
|
||||||
|
mailbox(const string& email);
|
||||||
|
mailbox(const text& name, const string& email);
|
||||||
|
|
||||||
|
/** Return the full name of the mailbox (empty if not specified).
|
||||||
|
*
|
||||||
|
* @return full name of the mailbox
|
||||||
|
*/
|
||||||
|
const text& name() const { return (m_name); }
|
||||||
|
|
||||||
|
/** Return the full name of the mailbox (empty if not specified).
|
||||||
|
*
|
||||||
|
* @return full name of the mailbox
|
||||||
|
*/
|
||||||
|
text& name() { return (m_name); }
|
||||||
|
|
||||||
|
/** Return the email of the mailbox.
|
||||||
|
*
|
||||||
|
* @return email of the mailbox
|
||||||
|
*/
|
||||||
|
const string& email() const { return (m_email); }
|
||||||
|
|
||||||
|
/** Return the email of the mailbox.
|
||||||
|
*
|
||||||
|
* @return email of the mailbox
|
||||||
|
*/
|
||||||
|
string& email() { return (m_email); }
|
||||||
|
|
||||||
|
// Comparison
|
||||||
|
const bool operator==(const class mailbox& mailbox) const;
|
||||||
|
const bool operator!=(const class mailbox& mailbox) const;
|
||||||
|
|
||||||
|
// Assignment
|
||||||
|
void copyFrom(const address& addr);
|
||||||
|
address* clone() const;
|
||||||
|
|
||||||
|
const bool empty() const;
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
|
||||||
|
const bool isGroup() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
text m_name;
|
||||||
|
string m_email;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using address::parse;
|
||||||
|
using address::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_MAILBOX_HPP_INCLUDED
|
95
src/mailboxField.cpp
Normal file
95
src/mailboxField.cpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "mailboxField.hpp"
|
||||||
|
#include "mailboxGroup.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
mailboxField::mailboxField()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailboxField::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
m_mailbox.clear();
|
||||||
|
|
||||||
|
// Here, we cannot simply call "m_mailbox.parse()" because it
|
||||||
|
// may have more than one address specified (even if this field
|
||||||
|
// should contain only one). We are never too much careful...
|
||||||
|
address* parsedAddress = address::parseNext(buffer, position, end, newPosition);
|
||||||
|
|
||||||
|
if (parsedAddress)
|
||||||
|
{
|
||||||
|
if (parsedAddress->isGroup())
|
||||||
|
{
|
||||||
|
// If it is a group of mailboxes, take the first
|
||||||
|
// mailbox of the group
|
||||||
|
mailboxGroup* group = static_cast <mailboxGroup*>(parsedAddress);
|
||||||
|
|
||||||
|
if (!group->empty())
|
||||||
|
m_mailbox = *(group->begin());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Parse only if it is a mailbox
|
||||||
|
m_mailbox = *static_cast <mailbox*>(parsedAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete (parsedAddress);
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailboxField::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
string::size_type pos = curLinePos;
|
||||||
|
|
||||||
|
headerField::generate(os, maxLineLength, pos, &pos);
|
||||||
|
|
||||||
|
m_mailbox.generate(os, maxLineLength, pos, newLinePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mailboxField& mailboxField::operator=(const class mailbox& mailbox)
|
||||||
|
{
|
||||||
|
m_mailbox = mailbox;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailboxField::copyFrom(const headerField& field)
|
||||||
|
{
|
||||||
|
const mailboxField& source = dynamic_cast<const mailboxField&>(field);
|
||||||
|
m_mailbox = source.m_mailbox;
|
||||||
|
|
||||||
|
headerField::copyFrom(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
70
src/mailboxField.hpp
Normal file
70
src/mailboxField.hpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_MAILBOXFIELD_HPP_INCLUDED
|
||||||
|
#define VMIME_MAILBOXFIELD_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.hpp"
|
||||||
|
#include "component.hpp"
|
||||||
|
|
||||||
|
#include "headerFieldFactory.hpp"
|
||||||
|
#include "mailbox.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class mailboxField : public headerField
|
||||||
|
{
|
||||||
|
friend class headerFieldFactory::registerer <mailboxField>;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
mailboxField();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void copyFrom(const headerField& field);
|
||||||
|
|
||||||
|
mailboxField& operator=(const class mailbox& mailbox);
|
||||||
|
|
||||||
|
const mailbox& value() const { return (m_mailbox); }
|
||||||
|
mailbox& value() { return (m_mailbox); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
mailbox m_mailbox;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using headerField::parse;
|
||||||
|
using headerField::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_MAILBOXFIELD_HPP_INCLUDED
|
237
src/mailboxGroup.cpp
Normal file
237
src/mailboxGroup.cpp
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "mailboxGroup.hpp"
|
||||||
|
#include "parserHelpers.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
mailboxGroup::mailboxGroup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mailboxGroup::mailboxGroup(const class mailboxGroup& mailboxGroup)
|
||||||
|
: address()
|
||||||
|
{
|
||||||
|
copyFrom(mailboxGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mailboxGroup::mailboxGroup(const text& name)
|
||||||
|
: m_name(name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mailboxGroup::~mailboxGroup()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailboxGroup::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
const string::value_type* const pend = buffer.data() + end;
|
||||||
|
const string::value_type* const pstart = buffer.data() + position;
|
||||||
|
const string::value_type* p = pstart;
|
||||||
|
|
||||||
|
while (p < pend && isspace(*p))
|
||||||
|
++p;
|
||||||
|
|
||||||
|
string name;
|
||||||
|
|
||||||
|
while (p < pend && *p != ':')
|
||||||
|
{
|
||||||
|
name += *p;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p < pend && *p == ':')
|
||||||
|
++p;
|
||||||
|
|
||||||
|
|
||||||
|
string::size_type pos = position + (p - pstart);
|
||||||
|
|
||||||
|
while (pos < end)
|
||||||
|
{
|
||||||
|
address* parsedAddress = address::parseNext(buffer, pos, end, &pos);
|
||||||
|
|
||||||
|
if (parsedAddress)
|
||||||
|
{
|
||||||
|
if (parsedAddress->isGroup())
|
||||||
|
{
|
||||||
|
mailboxGroup* group = static_cast <mailboxGroup*>(parsedAddress);
|
||||||
|
|
||||||
|
// Sub-groups are not allowed in mailbox groups: so, we add all
|
||||||
|
// the contents of the sub-group into this group...
|
||||||
|
for (mailboxGroup::const_iterator
|
||||||
|
it = group->begin() ; it != group->end() ; ++it)
|
||||||
|
{
|
||||||
|
m_list.push_back(static_cast <mailbox*>((*it).clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
delete (parsedAddress);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_list.push_back(static_cast <mailbox*>(parsedAddress));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeAndUnfoldText(name, m_name);
|
||||||
|
|
||||||
|
if (newPosition)
|
||||||
|
*newPosition = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailboxGroup::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
// We have to encode the name:
|
||||||
|
// - if it contains characters in a charset different from "US-ASCII",
|
||||||
|
// - and/or if it contains one or more of these special chars:
|
||||||
|
// SPACE TAB " ; , < > ( ) @ / ? . = :
|
||||||
|
|
||||||
|
// Check whether there are words that are not "US-ASCII"
|
||||||
|
// and/or contain the special chars.
|
||||||
|
bool forceEncode = false;
|
||||||
|
|
||||||
|
for (text::const_iterator w = m_name.begin() ; !forceEncode && w != m_name.end() ; ++w)
|
||||||
|
{
|
||||||
|
if ((*w).charset() == charset(charsets::US_ASCII))
|
||||||
|
{
|
||||||
|
const string& buffer = (*w).buffer();
|
||||||
|
|
||||||
|
for (string::const_iterator c = buffer.begin() ;
|
||||||
|
!forceEncode && c != buffer.end() ; ++c)
|
||||||
|
{
|
||||||
|
switch (*c)
|
||||||
|
{
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
case ';':
|
||||||
|
case ',':
|
||||||
|
case '<': case '>':
|
||||||
|
case '(': case ')':
|
||||||
|
case '@':
|
||||||
|
case '/':
|
||||||
|
case '?':
|
||||||
|
case '.':
|
||||||
|
case '=':
|
||||||
|
case ':':
|
||||||
|
|
||||||
|
forceEncode = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string::size_type pos = curLinePos;
|
||||||
|
|
||||||
|
encodeAndFoldText(os, m_name, maxLineLength - 2, pos, &pos,
|
||||||
|
forceEncode ? encodeAndFoldFlags::forceEncoding : encodeAndFoldFlags::none);
|
||||||
|
|
||||||
|
os << ":";
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
for (const_iterator it = m_list.begin() ; it != m_list.end() ; ++it)
|
||||||
|
{
|
||||||
|
if (it != m_list.begin())
|
||||||
|
{
|
||||||
|
os << ", ";
|
||||||
|
pos += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << " ";
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*it).generate(os, maxLineLength - 2, pos, &pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
os << ";";
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
if (newLinePos)
|
||||||
|
*newLinePos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
address* mailboxGroup::clone() const
|
||||||
|
{
|
||||||
|
return new mailboxGroup(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Mailbox insertion
|
||||||
|
void mailboxGroup::append(const mailbox& field)
|
||||||
|
{
|
||||||
|
m_list.push_back(static_cast<mailbox*>(field.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailboxGroup::insert(const iterator it, const mailbox& field)
|
||||||
|
{
|
||||||
|
m_list.insert(it.m_iterator, static_cast<mailbox*>(field.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Mailbox removing
|
||||||
|
void mailboxGroup::erase(const iterator it)
|
||||||
|
{
|
||||||
|
delete (*it.m_iterator);
|
||||||
|
m_list.erase(it.m_iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailboxGroup::clear()
|
||||||
|
{
|
||||||
|
free_container(m_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailboxGroup::copyFrom(const address& addr)
|
||||||
|
{
|
||||||
|
const mailboxGroup& source = dynamic_cast<const mailboxGroup&>(addr);
|
||||||
|
|
||||||
|
m_name = source.m_name;
|
||||||
|
|
||||||
|
clear();
|
||||||
|
|
||||||
|
for (std::vector <mailbox*>::const_iterator i = source.m_list.begin() ; i != source.m_list.end() ; ++i)
|
||||||
|
m_list.push_back(static_cast<mailbox*>((*i)->clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool mailboxGroup::isGroup() const
|
||||||
|
{
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
155
src/mailboxGroup.hpp
Normal file
155
src/mailboxGroup.hpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_MAILBOXGROUP_HPP_INCLUDED
|
||||||
|
#define VMIME_MAILBOXGROUP_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "address.hpp"
|
||||||
|
#include "mailbox.hpp"
|
||||||
|
#include "text.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** A group of mailboxes (basic type).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class mailboxGroup : public address
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
mailboxGroup();
|
||||||
|
mailboxGroup(const class mailboxGroup& mailboxGroup);
|
||||||
|
mailboxGroup(const text& name);
|
||||||
|
|
||||||
|
~mailboxGroup();
|
||||||
|
|
||||||
|
// Properties set/get
|
||||||
|
const text& name() const { return (m_name); }
|
||||||
|
text& name() { return (m_name); }
|
||||||
|
|
||||||
|
// Assignment
|
||||||
|
void copyFrom(const address& addr);
|
||||||
|
address* clone() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Mailbox iterator
|
||||||
|
class const_iterator;
|
||||||
|
|
||||||
|
class iterator
|
||||||
|
{
|
||||||
|
friend class mailboxGroup;
|
||||||
|
friend class const_iterator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
iterator(std::vector <mailbox*>::iterator it) : m_iterator(it) { }
|
||||||
|
iterator(const iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
|
||||||
|
iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
|
||||||
|
mailbox& operator*() const { return (**m_iterator); }
|
||||||
|
mailbox* operator->() const { return (*m_iterator); }
|
||||||
|
|
||||||
|
iterator& operator++() { ++m_iterator; return (*this); }
|
||||||
|
iterator& operator++(int) { ++m_iterator; return (*this); }
|
||||||
|
|
||||||
|
const bool operator==(const iterator& it) const { return (it.m_iterator == m_iterator); }
|
||||||
|
const bool operator!=(const iterator& it) const { return (!(*this == it)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector <mailbox*>::iterator m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
class const_iterator
|
||||||
|
{
|
||||||
|
friend class mailboxGroup;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const_iterator(std::vector <mailbox*>::const_iterator it) : m_iterator(it) { }
|
||||||
|
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
|
||||||
|
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
|
||||||
|
const mailbox& operator*() const { return (**m_iterator); }
|
||||||
|
const mailbox* operator->() const { return (*m_iterator); }
|
||||||
|
|
||||||
|
const_iterator& operator++() { ++m_iterator; return (*this); }
|
||||||
|
const_iterator& operator++(int) { ++m_iterator; return (*this); }
|
||||||
|
|
||||||
|
const bool operator==(const const_iterator& it) const { return (it.m_iterator == m_iterator); }
|
||||||
|
const bool operator!=(const const_iterator& it) const { return (!(*this == it)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector <mailbox*>::const_iterator m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator begin() { return (m_list.begin()); }
|
||||||
|
iterator end() { return (m_list.end()); }
|
||||||
|
|
||||||
|
const_iterator begin() const { return (const_iterator(m_list.begin())); }
|
||||||
|
const_iterator end() const { return (const_iterator(m_list.end())); }
|
||||||
|
|
||||||
|
const std::vector <mailbox*>::size_type size() const { return (m_list.size()); }
|
||||||
|
const std::vector <mailbox*>::size_type count() const { return (m_list.size()); }
|
||||||
|
const bool empty() const { return (m_list.empty()); }
|
||||||
|
|
||||||
|
const mailbox& operator[](const std::vector <mailbox*>::size_type x) const { return (*m_list[x]); }
|
||||||
|
mailbox& operator[](const std::vector <mailbox*>::size_type x) { return (*m_list[x]); }
|
||||||
|
|
||||||
|
// Mailbox insertion
|
||||||
|
virtual void append(const mailbox& field);
|
||||||
|
virtual void insert(const iterator it, const mailbox& field);
|
||||||
|
|
||||||
|
// Mailbox removing
|
||||||
|
void erase(const iterator it);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
|
||||||
|
const bool isGroup() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
text m_name;
|
||||||
|
std::vector <mailbox*> m_list;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using address::parse;
|
||||||
|
using address::generate;
|
||||||
|
|
||||||
|
// Component parsing & assembling
|
||||||
|
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
|
||||||
|
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_MAILBOXGROUP_HPP_INCLUDED
|
46
src/mailboxList.cpp
Normal file
46
src/mailboxList.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "mailboxList.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// Address insertion
|
||||||
|
void mailboxList::append(const address& addr)
|
||||||
|
{
|
||||||
|
// Ensure this is a "mailbox" object
|
||||||
|
const mailbox& mb = dynamic_cast<const mailbox&>(addr);
|
||||||
|
|
||||||
|
m_list.push_back(mb.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailboxList::insert(const iterator it, const address& addr)
|
||||||
|
{
|
||||||
|
// Ensure this is a "mailbox" object
|
||||||
|
const mailbox& mb = dynamic_cast<const mailbox&>(addr);
|
||||||
|
|
||||||
|
m_list.insert(it.m_iterator, mb.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
127
src/mailboxList.hpp
Normal file
127
src/mailboxList.hpp
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VMIME_MAILBOXLIST_HPP_INCLUDED
|
||||||
|
#define VMIME_MAILBOXLIST_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "addressList.hpp"
|
||||||
|
#include "mailbox.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** A list of mailboxes (basic type).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class mailboxList : public addressList
|
||||||
|
{
|
||||||
|
friend class mailboxGroup;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//
|
||||||
|
// The following functions have the same name and work *exactly* like
|
||||||
|
// the ones in "addressList", except we don't accept anything other
|
||||||
|
// than objects of type "mailbox" (instead of a generic "address").
|
||||||
|
//
|
||||||
|
// This prevents user from inserting mailbox groups where it is not
|
||||||
|
// allowed by the RFC.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Address iterator
|
||||||
|
class const_iterator;
|
||||||
|
|
||||||
|
class iterator
|
||||||
|
{
|
||||||
|
friend class mailboxList;
|
||||||
|
friend class const_iterator;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
iterator(std::vector <address*>::iterator it) : m_iterator(it) { }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
iterator(const iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
|
||||||
|
iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
|
||||||
|
mailbox& operator*() const { return static_cast<mailbox&>(**m_iterator); }
|
||||||
|
mailbox* operator->() const { return static_cast<mailbox*>(*m_iterator); }
|
||||||
|
|
||||||
|
iterator& operator++() { ++m_iterator; return (*this); }
|
||||||
|
iterator& operator++(int) { ++m_iterator; return (*this); }
|
||||||
|
|
||||||
|
const bool operator==(const iterator& it) const { return (it.m_iterator == m_iterator); }
|
||||||
|
const bool operator!=(const iterator& it) const { return (!(*this == it)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector <address*>::iterator m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
class const_iterator
|
||||||
|
{
|
||||||
|
friend class mailboxList;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const_iterator(std::vector <address*>::const_iterator it) : m_iterator(it) { }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
const_iterator(const iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
const_iterator(const const_iterator& it) : m_iterator(it.m_iterator) { }
|
||||||
|
|
||||||
|
const_iterator& operator=(const const_iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
const_iterator& operator=(const iterator& it) { m_iterator = it.m_iterator; return (*this); }
|
||||||
|
|
||||||
|
const mailbox& operator*() const { return static_cast<const mailbox&>(**m_iterator); }
|
||||||
|
const mailbox* operator->() const { return static_cast<const mailbox*>(*m_iterator); }
|
||||||
|
|
||||||
|
const_iterator& operator++() { ++m_iterator; return (*this); }
|
||||||
|
const_iterator& operator++(int) { ++m_iterator; return (*this); }
|
||||||
|
|
||||||
|
const bool operator==(const const_iterator& it) const { return (it.m_iterator == m_iterator); }
|
||||||
|
const bool operator!=(const const_iterator& it) const { return (!(*this == it)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector <address*>::const_iterator m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator begin() { return (m_list.begin()); }
|
||||||
|
iterator end() { return (m_list.end()); }
|
||||||
|
|
||||||
|
const_iterator begin() const { return (const_iterator(m_list.begin())); }
|
||||||
|
const_iterator end() const { return (const_iterator(m_list.end())); }
|
||||||
|
|
||||||
|
// Address insertion
|
||||||
|
void append(const address& addr);
|
||||||
|
void insert(const iterator it, const address& addr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VMIME_MAILBOXLIST_HPP_INCLUDED
|
60
src/mailboxListField.cpp
Normal file
60
src/mailboxListField.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://vmime.sourceforge.net)
|
||||||
|
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "mailboxListField.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace vmime
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
mailboxListField::mailboxListField()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailboxListField::parse(const string& buffer, const string::size_type position,
|
||||||
|
const string::size_type end, string::size_type* newPosition)
|
||||||
|
{
|
||||||
|
m_list.parse(buffer, position, end, newPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailboxListField::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
||||||
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
||||||
|
{
|
||||||
|
string::size_type pos = curLinePos;
|
||||||
|
|
||||||
|
headerField::generate(os, maxLineLength, pos, &pos);
|
||||||
|
|
||||||
|
m_list.generate(os, maxLineLength, pos, newLinePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mailboxListField::copyFrom(const headerField& field)
|
||||||
|
{
|
||||||
|
const mailboxListField& source = dynamic_cast<const mailboxListField&>(field);
|
||||||
|
m_list = source.m_list;
|
||||||
|
|
||||||
|
headerField::copyFrom(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // vmime
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user