Initial import.

This commit is contained in:
Vincent Richard 2004-10-05 10:28:21 +00:00
commit a3229a0513
255 changed files with 46187 additions and 0 deletions

0
AUTHORS Normal file
View File

0
COPYING Normal file
View File

434
ChangeLog Normal file
View 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.

0
INSTALL Normal file
View File

0
NEWS Normal file
View File

2
README Normal file
View File

@ -0,0 +1,2 @@
TODO

688
SConstruct Normal file
View 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)

1
VERSION Normal file
View File

@ -0,0 +1 @@
0.5.2

9
examples/README Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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> &lt;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> &lt:us-ascii> "Linux dans un "
* &lt;iso-8859-1> "t'el'ephone "
* &lt;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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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

View 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

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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), &registerer<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, &registerer<T>::creator));
}
};
} // vmime
#endif // VMIME_HEADERFIELDFACTORY_HPP_INCLUDED

371
src/htmlTextPart.cpp Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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