Merge branch 'master' into master

This commit is contained in:
Vincent Richard 2018-09-07 20:32:51 +02:00 committed by GitHub
commit 71968d978d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
558 changed files with 26544 additions and 22623 deletions

View File

@ -12,7 +12,7 @@
# http://www.cmake.org # http://www.cmake.org
# #
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.6 FATAL_ERROR) CMAKE_MINIMUM_REQUIRED(VERSION 3.1 FATAL_ERROR)
INCLUDE(cmake/Utils.cmake) INCLUDE(cmake/Utils.cmake)
@ -68,6 +68,11 @@ SET(VMIME_API_VERSION ${VMIME_API_VERSION_CURRENT}.${VMIME_API_VERSION_REVISION}
# Set base name # Set base name
SET(VMIME_LIBRARY_NAME vmime) SET(VMIME_LIBRARY_NAME vmime)
# Enable C++11
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF)
# Source files # Source files
FILE( FILE(
GLOB_RECURSE GLOB_RECURSE
@ -109,6 +114,10 @@ IF(VMIME_BUILD_SHARED_LIBRARY)
${VMIME_LIBRARY_INCLUDE_FILES} ${VMIME_LIBRARY_INCLUDE_FILES}
) )
TARGET_INCLUDE_DIRECTORIES(${VMIME_LIBRARY_NAME} PUBLIC
$<INSTALL_INTERFACE:include>
)
GENERATE_EXPORT_HEADER( GENERATE_EXPORT_HEADER(
${VMIME_LIBRARY_NAME} ${VMIME_LIBRARY_NAME}
BASE_NAME VMIME BASE_NAME VMIME
@ -154,6 +163,10 @@ IF(VMIME_BUILD_STATIC_LIBRARY)
${VMIME_LIBRARY_INCLUDE_FILES} ${VMIME_LIBRARY_INCLUDE_FILES}
) )
TARGET_INCLUDE_DIRECTORIES(${VMIME_LIBRARY_NAME}-static PUBLIC
$<INSTALL_INTERFACE:include>
)
GENERATE_EXPORT_HEADER( GENERATE_EXPORT_HEADER(
${VMIME_LIBRARY_NAME}-static ${VMIME_LIBRARY_NAME}-static
BASE_NAME VMIME BASE_NAME VMIME
@ -199,6 +212,7 @@ SET(CMAKE_INSTALL_LIBDIR lib CACHE PATH "Output directory for libraries")
IF(VMIME_BUILD_SHARED_LIBRARY) IF(VMIME_BUILD_SHARED_LIBRARY)
INSTALL( INSTALL(
TARGETS ${VMIME_LIBRARY_NAME} TARGETS ${VMIME_LIBRARY_NAME}
EXPORT ${VMIME_LIBRARY_NAME}-config
LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" COMPONENT sharedlibs LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" COMPONENT sharedlibs
ARCHIVE DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" COMPONENT sharedlibs ARCHIVE DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" COMPONENT sharedlibs
) )
@ -207,6 +221,7 @@ ENDIF()
IF(VMIME_BUILD_STATIC_LIBRARY) IF(VMIME_BUILD_STATIC_LIBRARY)
INSTALL( INSTALL(
TARGETS ${VMIME_LIBRARY_NAME}-static TARGETS ${VMIME_LIBRARY_NAME}-static
EXPORT ${VMIME_LIBRARY_NAME}-config
LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" COMPONENT staticlibs LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" COMPONENT staticlibs
ARCHIVE DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" COMPONENT staticlibs ARCHIVE DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" COMPONENT staticlibs
) )
@ -222,6 +237,8 @@ INSTALL_HEADERS_WITH_DIRECTORY(VMIME_LIBRARY_GENERATED_INCLUDE_FILES headers "${
# COMPONENT headers # COMPONENT headers
#) #)
install(EXPORT ${VMIME_LIBRARY_NAME}-config DESTINATION cmake)
############################################################################## ##############################################################################
# Tests # Tests
@ -783,89 +800,6 @@ ELSE()
ENDIF() ENDIF()
##############################################################################
# Language features
# C++11
INCLUDE(cmake/cmake-cxx11/Modules/CheckCXX11Features.cmake)
# Smart pointers
#
# If a C++11-compliant compiler is available and supports std::shared_ptr<>,
# use the standard implementation. Else, use boost::shared_ptr<>.
# In any case, let the user override the choice with VMIME_SHARED_PTR_USE_CXX
# and VMIME_SHARED_PTR_USE_BOOST variables.
CHECK_CXX_SOURCE_COMPILES(
"
#include <memory>
struct A { int foo; };
int main() {
std::shared_ptr <A> a = std::make_shared <A>();
return 0;
}
"
VMIME_HAS_CXX11_SHARED_PTR
)
IF(NOT VMIME_SHARED_PTR_USE_CXX AND NOT VMIME_SHARED_PTR_USE_BOOST)
IF(CXX11_COMPILER_FLAGS AND VMIME_HAS_CXX11_SHARED_PTR)
# If std::shared_ptr<> is available, use it by default
SET(VMIME_SHARED_PTR_USE_CXX_DEFAULT ON)
SET(VMIME_SHARED_PTR_USE_BOOST_DEFAULT OFF)
ELSE()
# Else, set default to boost::shared_ptr<>
SET(VMIME_SHARED_PTR_USE_CXX_DEFAULT OFF)
SET(VMIME_SHARED_PTR_USE_BOOST_DEFAULT ON)
ENDIF()
ENDIF()
OPTION(
VMIME_SHARED_PTR_USE_CXX
"Use standard std::shared_ptr<> (requires a C++11 compiler)"
${VMIME_SHARED_PTR_USE_CXX_DEFAULT}
)
OPTION(
VMIME_SHARED_PTR_USE_BOOST
"Use boost::shared_ptr<> (requires Boost)"
${VMIME_SHARED_PTR_USE_BOOST_DEFAULT}
)
IF(VMIME_SHARED_PTR_USE_CXX AND VMIME_SHARED_PTR_USE_BOOST)
MESSAGE(FATAL_ERROR "Options VMIME_SHARED_PTR_USE_CXX and VMIME_SHARED_PTR_USE_BOOST are mutually exclusive (select one or the other, but not both!)")
ENDIF()
IF(VMIME_SHARED_PTR_USE_CXX)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX11_COMPILER_FLAGS}")
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
ENDIF()
MESSAGE(STATUS "Checking support for shared_ptr<>: built-in (C++11)")
ELSEIF(VMIME_SHARED_PTR_USE_BOOST)
# Depends on Boost library if C++11 is not supported
FIND_PACKAGE(Boost)
IF(Boost_FOUND)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
ELSE()
MESSAGE(FATAL_ERROR "Boost library is required for shared_ptr<>, unless you compile using C++11")
ENDIF()
MESSAGE(STATUS "Checking support for shared_ptr<>: boost library")
ELSE()
MESSAGE(FATAL_ERROR "No implementation for shared_ptr<> was selected/found")
ENDIF()
############################################################################## ##############################################################################
# Platform # Platform
@ -997,12 +931,12 @@ IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
SET( SET(
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -D_REENTRANT=1 -W -Wall -pedantic -Warray-bounds-pointer-arithmetic -Wold-style-cast -Wconversion -Wcast-align -Wno-sign-conversion" "-D_REENTRANT=1 -W -Wall -pedantic -Warray-bounds-pointer-arithmetic -Wold-style-cast -Wconversion -Wcast-align -Wno-sign-conversion ${CMAKE_CXX_FLAGS}"
) )
SET(CMAKE_CXX_FLAGS_RELEASE "-O2") SET(CMAKE_CXX_FLAGS_RELEASE "-O2 ${CMAKE_CXX_FLAGS_RELEASE}")
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") SET(CMAKE_CXX_FLAGS_DEBUG "-O0 ${CMAKE_CXX_FLAGS_DEBUG}")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
#SET(CMAKE_EXE_LINKER_FLAGS "-s") #SET(CMAKE_EXE_LINKER_FLAGS "-s")
@ -1012,12 +946,12 @@ ELSE()
SET( SET(
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -D_REENTRANT=1 -W -Wall -pedantic -Wpointer-arith -Wold-style-cast -Wconversion -Wcast-align -Wno-long-long" "-D_REENTRANT=1 -W -Wall -pedantic -Wpointer-arith -Wold-style-cast -Wconversion -Wcast-align -Wno-long-long ${CMAKE_CXX_FLAGS}"
) )
SET(CMAKE_CXX_FLAGS_RELEASE "-O2") SET(CMAKE_CXX_FLAGS_RELEASE "-O2 ${CMAKE_CXX_FLAGS_RELEASE}")
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") SET(CMAKE_CXX_FLAGS_DEBUG "-O0 ${CMAKE_CXX_FLAGS_DEBUG}")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
#SET(CMAKE_EXE_LINKER_FLAGS "-s") #SET(CMAKE_EXE_LINKER_FLAGS "-s")

94
HACKING
View File

@ -80,73 +80,91 @@ width to its preferred settings (eg. 4 or 8 spaces).
2.2. Brace position 2.2. Brace position
------------------- -------------------
Open braces should always be at the beginning of the line after the statement Open braces should always be at the end of the line of the statement that
that begins the block. Contents of the brace should be indented by 1 tab. begins the block. Contents of the brace should be indented by 1 tab.
if (expr) {
if (expr)
{
do_something(); do_something();
do_another_thing(); do_another_thing();
}
else } else {
{
do_something_else(); do_something_else();
} }
In a function, the opening brace must always be followed by an empty line:
void header::appendField(const shared_ptr <headerField>& field) {
m_fields.push_back(field);
}
A function with few arguments:
bool header::hasField(const string& fieldName) const {
...
}
A function with more arguments:
void header::parseImpl(
const parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
size_t* newPosition
) {
...
}
2.3. "switch" statement 2.3. "switch" statement
----------------------- -----------------------
switch (expr) switch (expr) {
{
case 0:
something; case 0:
break;
case 1: something;
break;
something_else; case 1:
break;
case 2: something_else;
{ break;
int var = 42;
another_thing;
break;
}
case 2: {
int var = 42;
another_thing;
break;
}
} }
2.4. Single instruction 2.4. Single instruction
----------------------- -----------------------
Omit braces around simple single-statement body: Don't omit braces around simple single-statement body:
if (...) if (...) {
something; something;
}
and not: and not:
if (...) if (...)
{
something; something;
}
Except when body spans over multiple lines:
if (...)
{
something_too_long_for(
a_single_line);
}
2.5. Line length 2.5. Line length
---------------- ----------------
Each line of text should not exceed 80 characters. If possible, each line of text should not exceed 100 characters, except if
manual line wrapping breaks code clarity.
Exception: if a comment line contains an example command or a literal URL Exception: if a comment line contains an example command or a literal URL
longer than 100 characters, that line may be longer than 100 characters longer than 100 characters, that line may be longer than 100 characters
@ -290,8 +308,8 @@ Where ever possible, place comments above the code instead of beside it.
Comments can be placed at the end of a line when one or more spaces follow. Comments can be placed at the end of a line when one or more spaces follow.
Tabs should NOT be used to indent at the end of a line: Tabs should NOT be used to indent at the end of a line:
class myClass class myClass {
{
private: private:
int m_member1; // first member int m_member1; // first member
@ -322,8 +340,8 @@ the purpose of the functions/classes and the meaning of the parameters.
* No more than one class per file (except for inner classes). * No more than one class per file (except for inner classes).
* Put the inclusion for the class's header file as the first inclusion in * Put the #include for the class's header file first in the implementation
the implementation file. file.
* Put the copyright header at the top of each file. * Put the copyright header at the top of each file.

View File

@ -1 +0,0 @@
build

View File

@ -1,7 +0,0 @@
These things need to be changed when this module is merged into CMake:
-change include(CheckCXXCompilerFlag) in CheckCXX11Features.cmake to
include(${CMAKE_CURRENT_LIST_DIR}/CheckCXXCompilerFlag.cmake)
-remove the setting of CMAKE_MODULE_PATH from the testcase CMakeLists.txt
-change all tabs to spaces in the cpp files

View File

@ -1,142 +0,0 @@
# - Check which parts of the C++11 standard the compiler supports
#
# When found it will set the following variables
#
# CXX11_COMPILER_FLAGS - the compiler flags needed to get C++11 features
#
# HAS_CXX11_AUTO - auto keyword
# HAS_CXX11_AUTO_RET_TYPE - function declaration with deduced return types
# HAS_CXX11_CLASS_OVERRIDE - override and final keywords for classes and methods
# HAS_CXX11_CONSTEXPR - constexpr keyword
# HAS_CXX11_CSTDINT_H - cstdint header
# HAS_CXX11_DECLTYPE - decltype keyword
# HAS_CXX11_FUNC - __func__ preprocessor constant
# HAS_CXX11_INITIALIZER_LIST - initializer list
# HAS_CXX11_LAMBDA - lambdas
# HAS_CXX11_LIB_REGEX - regex library
# HAS_CXX11_LONG_LONG - long long signed & unsigned types
# HAS_CXX11_NULLPTR - nullptr
# HAS_CXX11_RVALUE_REFERENCES - rvalue references
# HAS_CXX11_SIZEOF_MEMBER - sizeof() non-static members
# HAS_CXX11_STATIC_ASSERT - static_assert()
# HAS_CXX11_VARIADIC_TEMPLATES - variadic templates
#=============================================================================
# Copyright 2011,2012 Rolf Eike Beer <eike@sf-mail.de>
# Copyright 2012 Andreas Weis
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
#
# Each feature may have up to 3 checks, every one of them in it's own file
# FEATURE.cpp - example that must build and return 0 when run
# FEATURE_fail.cpp - example that must build, but may not return 0 when run
# FEATURE_fail_compile.cpp - example that must fail compilation
#
# The first one is mandatory, the latter 2 are optional and do not depend on
# each other (i.e. only one may be present).
#
if (NOT CMAKE_CXX_COMPILER_LOADED)
message(FATAL_ERROR "CheckCXX11Features modules only works if language CXX is enabled")
endif ()
cmake_minimum_required(VERSION 2.8.3)
#
### Check for needed compiler flags
#
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-std=c++11" _HAS_CXX11_FLAG)
if (NOT _HAS_CXX11_FLAG)
check_cxx_compiler_flag("-std=c++0x" _HAS_CXX0X_FLAG)
endif ()
if (_HAS_CXX11_FLAG)
set(CXX11_COMPILER_FLAGS "-std=c++11")
elseif (_HAS_CXX0X_FLAG)
set(CXX11_COMPILER_FLAGS "-std=c++0x")
endif ()
function(cxx11_check_feature FEATURE_NAME RESULT_VAR)
if (NOT DEFINED ${RESULT_VAR})
set(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx11_${FEATURE_NAME}")
set(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/CheckCXX11Features/cxx11-test-${FEATURE_NAME})
set(_LOG_NAME "\"${FEATURE_NAME}\"")
message(STATUS "Checking C++11 support for ${_LOG_NAME}")
set(_SRCFILE "${_SRCFILE_BASE}.cpp")
set(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp")
set(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp")
if (CMAKE_CROSSCOMPILING)
try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}"
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}"
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
else (CMAKE_CROSSCOMPILING)
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
"${_bindir}" "${_SRCFILE}"
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
if (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
set(${RESULT_VAR} TRUE)
else (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
set(${RESULT_VAR} FALSE)
endif (_COMPILE_RESULT_VAR AND NOT _RUN_RESULT_VAR)
if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
"${_bindir}_fail" "${_SRCFILE_FAIL}"
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
if (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
set(${RESULT_VAR} TRUE)
else (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
set(${RESULT_VAR} FALSE)
endif (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
endif (CMAKE_CROSSCOMPILING)
if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}"
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
if (_TMP_RESULT)
set(${RESULT_VAR} FALSE)
else (_TMP_RESULT)
set(${RESULT_VAR} TRUE)
endif (_TMP_RESULT)
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
if (${RESULT_VAR})
message(STATUS "Checking C++11 support for ${_LOG_NAME}: works")
else (${RESULT_VAR})
message(STATUS "Checking C++11 support for ${_LOG_NAME}: not supported")
endif (${RESULT_VAR})
set(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++11 support for ${_LOG_NAME}")
endif (NOT DEFINED ${RESULT_VAR})
endfunction(cxx11_check_feature)
cxx11_check_feature("__func__" HAS_CXX11_FUNC)
cxx11_check_feature("auto" HAS_CXX11_AUTO)
cxx11_check_feature("auto_ret_type" HAS_CXX11_AUTO_RET_TYPE)
cxx11_check_feature("class_override_final" HAS_CXX11_CLASS_OVERRIDE)
cxx11_check_feature("constexpr" HAS_CXX11_CONSTEXPR)
cxx11_check_feature("cstdint" HAS_CXX11_CSTDINT_H)
cxx11_check_feature("decltype" HAS_CXX11_DECLTYPE)
cxx11_check_feature("initializer_list" HAS_CXX11_INITIALIZER_LIST)
cxx11_check_feature("lambda" HAS_CXX11_LAMBDA)
cxx11_check_feature("long_long" HAS_CXX11_LONG_LONG)
cxx11_check_feature("nullptr" HAS_CXX11_NULLPTR)
cxx11_check_feature("regex" HAS_CXX11_LIB_REGEX)
cxx11_check_feature("rvalue-references" HAS_CXX11_RVALUE_REFERENCES)
cxx11_check_feature("sizeof_member" HAS_CXX11_SIZEOF_MEMBER)
cxx11_check_feature("static_assert" HAS_CXX11_STATIC_ASSERT)
cxx11_check_feature("variadic_templates" HAS_CXX11_VARIADIC_TEMPLATES)

View File

@ -1,8 +0,0 @@
int main(void)
{
if (!__func__)
return 1;
if (!(*__func__))
return 1;
return 0;
}

View File

@ -1,12 +0,0 @@
int main()
{
auto i = 5;
auto f = 3.14159f;
auto d = 3.14159;
bool ret = (
(sizeof(f) < sizeof(d)) &&
(sizeof(i) == sizeof(int))
);
return ret ? 0 : 1;
}

View File

@ -1,7 +0,0 @@
int main(void)
{
// must fail because there is no initializer
auto i;
return 0;
}

View File

@ -1,8 +0,0 @@
auto foo(int i) -> int {
return i - 1;
}
int main()
{
return foo(1);
}

View File

@ -1,21 +0,0 @@
class base {
public:
virtual int foo(int a)
{ return 4 + a; }
int bar(int a) final
{ return a - 2; }
};
class sub final : public base {
public:
virtual int foo(int a) override
{ return 8 + 2 * a; };
};
int main(void)
{
base b;
sub s;
return (b.foo(2) * 2 == s.foo(2)) ? 0 : 1;
}

View File

@ -1,25 +0,0 @@
class base {
public:
virtual int foo(int a)
{ return 4 + a; }
virtual int bar(int a) final
{ return a - 2; }
};
class sub final : public base {
public:
virtual int foo(int a) override
{ return 8 + 2 * a; };
virtual int bar(int a)
{ return a; }
};
class impossible : public sub { };
int main(void)
{
base b;
sub s;
return 1;
}

View File

@ -1,19 +0,0 @@
constexpr int square(int x)
{
return x*x;
}
constexpr int the_answer()
{
return 42;
}
int main()
{
int test_arr[square(3)];
bool ret = (
(square(the_answer()) == 1764) &&
(sizeof(test_arr)/sizeof(test_arr[0]) == 9)
);
return ret ? 0 : 1;
}

View File

@ -1,11 +0,0 @@
#include <cstdint>
int main()
{
bool test =
(sizeof(int8_t) == 1) &&
(sizeof(int16_t) == 2) &&
(sizeof(int32_t) == 4) &&
(sizeof(int64_t) == 8);
return test ? 0 : 1;
}

View File

@ -1,10 +0,0 @@
bool check_size(int i)
{
return sizeof(int) == sizeof(decltype(i));
}
int main()
{
bool ret = check_size(42);
return ret ? 0 : 1;
}

View File

@ -1,27 +0,0 @@
#include <vector>
class seq {
public:
seq(std::initializer_list<int> list);
int length() const;
private:
std::vector<int> m_v;
};
seq::seq(std::initializer_list<int> list)
: m_v(list)
{
}
int seq::length() const
{
return m_v.size();
}
int main(void)
{
seq a = {18, 20, 2, 0, 4, 7};
return (a.length() == 6) ? 0 : 1;
}

View File

@ -1,5 +0,0 @@
int main()
{
int ret = 0;
return ([&ret]() -> int { return ret; })();
}

View File

@ -1,7 +0,0 @@
int main(void)
{
long long l;
unsigned long long ul;
return ((sizeof(l) >= 8) && (sizeof(ul) >= 8)) ? 0 : 1;
}

View File

@ -1,6 +0,0 @@
int main(void)
{
void *v = nullptr;
return v ? 1 : 0;
}

View File

@ -1,6 +0,0 @@
int main(void)
{
int i = nullptr;
return 1;
}

View File

@ -1,26 +0,0 @@
#include <algorithm>
#include <regex>
int parse_line(std::string const& line)
{
std::string tmp;
if(std::regex_search(line, std::regex("(\\s)+(-)?(\\d)+//(-)?(\\d)+(\\s)+"))) {
tmp = std::regex_replace(line, std::regex("(-)?(\\d)+//(-)?(\\d)+"), std::string("V"));
} else if(std::regex_search(line, std::regex("(\\s)+(-)?(\\d)+/(-)?(\\d)+(\\s)+"))) {
tmp = std::regex_replace(line, std::regex("(-)?(\\d)+/(-)?(\\d)+"), std::string("V"));
} else if(std::regex_search(line, std::regex("(\\s)+(-)?(\\d)+/(-)?(\\d)+/(-)?(\\d)+(\\s)+"))) {
tmp = std::regex_replace(line, std::regex("(-)?(\\d)+/(-)?(\\d)+/(-)?(\\d)+"), std::string("V"));
} else {
tmp = std::regex_replace(line, std::regex("(-)?(\\d)+"), std::string("V"));
}
return static_cast<int>(std::count(tmp.begin(), tmp.end(), 'V'));
}
int main()
{
bool test = (parse_line("f 7/7/7 -3/3/-3 2/-2/2") == 3) &&
(parse_line("f 7//7 3//-3 -2//2") == 3) &&
(parse_line("f 7/7 3/-3 -2/2") == 3) &&
(parse_line("f 7 3 -2") == 3);
return test ? 0 : 1;
}

View File

@ -1,57 +0,0 @@
#include <cassert>
class rvmove {
public:
void *ptr;
char *array;
rvmove()
: ptr(0),
array(new char[10])
{
ptr = this;
}
rvmove(rvmove &&other)
: ptr(other.ptr),
array(other.array)
{
other.array = 0;
other.ptr = 0;
}
~rvmove()
{
assert(((ptr != 0) && (array != 0)) || ((ptr == 0) && (array == 0)));
delete[] array;
}
rvmove &operator=(rvmove &&other)
{
delete[] array;
ptr = other.ptr;
array = other.array;
other.array = 0;
other.ptr = 0;
return *this;
}
static rvmove create()
{
return rvmove();
}
private:
rvmove(const rvmove &);
rvmove &operator=(const rvmove &);
};
int main()
{
rvmove mine;
if (mine.ptr != &mine)
return 1;
mine = rvmove::create();
if (mine.ptr == &mine)
return 1;
return 0;
}

View File

@ -1,14 +0,0 @@
struct foo {
char bar;
int baz;
};
int main(void)
{
bool ret = (
(sizeof(foo::bar) == 1) &&
(sizeof(foo::baz) >= sizeof(foo::bar)) &&
(sizeof(foo) >= sizeof(foo::bar) + sizeof(foo::baz))
);
return ret ? 0 : 1;
}

View File

@ -1,9 +0,0 @@
struct foo {
int baz;
double bar;
};
int main(void)
{
return (sizeof(foo::bar) == 4) ? 0 : 1;
}

View File

@ -1,5 +0,0 @@
int main(void)
{
static_assert(0 < 1, "your ordering of integers is screwed");
return 0;
}

View File

@ -1,5 +0,0 @@
int main(void)
{
static_assert(1 < 0, "your ordering of integers is screwed");
return 0;
}

View File

@ -1,23 +0,0 @@
int Accumulate()
{
return 0;
}
template<typename T, typename... Ts>
int Accumulate(T v, Ts... vs)
{
return v + Accumulate(vs...);
}
template<int... Is>
int CountElements()
{
return sizeof...(Is);
}
int main()
{
int acc = Accumulate(1, 2, 3, 4, -5);
int count = CountElements<1,2,3,4,5>();
return ((acc == 5) && (count == 5)) ? 0 : 1;
}

View File

@ -1,33 +0,0 @@
cmake_minimum_required(VERSION 2.8.3 FATAL_ERROR)
project(Cxx11Features CXX)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../Modules")
include(CheckCXX11Features)
foreach (flag IN ITEMS
HAS_CXX11_AUTO
HAS_CXX11_AUTO_RET_TYPE
HAS_CXX11_CLASS_OVERRIDE
HAS_CXX11_CONSTEXPR
HAS_CXX11_CSTDINT_H
HAS_CXX11_DECLTYPE
HAS_CXX11_FUNC
HAS_CXX11_INITIALIZER_LIST
HAS_CXX11_LAMBDA
HAS_CXX11_LIB_REGEX
HAS_CXX11_LONG_LONG
HAS_CXX11_NULLPTR
HAS_CXX11_RVALUE_REFERENCES
HAS_CXX11_SIZEOF_MEMBER
HAS_CXX11_STATIC_ASSERT
HAS_CXX11_VARIADIC_TEMPLATES
)
if (${flag})
add_definitions("-D${flag}")
message(STATUS "Compiler C++11 support flag ${flag} set")
endif ()
endforeach (flag)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${CXX11_COMPILER_FLAGS})
add_executable(CXX11Features cxx11features.cxx)

View File

@ -1,57 +0,0 @@
#if defined(HAS_CXX0X_CSTDINT_H)
#include <cstdint>
#endif
#include <sys/types.h>
struct thing {
unsigned char one;
#if defined(HAS_CXX0X_CSTDINT_H)
uint32_t four;
#endif
#if defined(HAS_CXX0X_LONG_LONG)
long long eight;
#endif
};
#include <stdio.h>
int main()
{
#if defined (HAS_CXX0X_NULLPTR)
void *nix = nullptr;
#else /* HAS_CXX0X_NULLPTR */
void *nix = 0;
#endif /* HAS_CXX0X_NULLPTR */
#if defined(HAS_CXX0X_STATIC_ASSERT)
static_assert(1 < 42, "Your C++ compiler is b0rked");
#endif /* HAS_CXX0X_STATIC_ASSERT */
#if defined(HAS_CXX0X_FUNC)
const char *funcname = __func__;
printf("the name of main() function is: %s\n", funcname);
#endif /* HAS_CXX0X_FUNC */
#if defined(HAS_CXX0X_SIZEOF_MEMBER)
size_t onesize = sizeof(thing::one);
#if defined(HAS_CXX0X_STATIC_ASSERT)
static_assert(sizeof(thing::one) == 1, "Your char is not one byte long");
#endif /* HAS_CXX0X_STATIC_ASSERT */
#if defined(HAS_CXX0X_CSTDINT_H)
size_t foursize = sizeof(thing::four);
#if defined(HAS_CXX0X_STATIC_ASSERT)
static_assert(sizeof(thing::four) == 4, "Your uint32_t is not 32 bit long");
#endif /* HAS_CXX0X_STATIC_ASSERT */
#endif /* HAS_CXX0X_CSTDINT_H */
#if defined(HAS_CXX0X_LONG_LONG)
size_t eightsize = sizeof(thing::eight);
#if defined(HAS_CXX0X_STATIC_ASSERT)
static_assert(sizeof(thing::eight) == 8, "Your long long is not 64 bit long");
#endif /* HAS_CXX0X_STATIC_ASSERT */
#endif /* HAS_CXX0X_LONG_LONG */
#endif /* HAS_CXX0X_SIZEOF_MEMBER */
return 0;
}

View File

@ -46,17 +46,17 @@ use the function {\vcode vmime::make\_shared} instead of the {\vcode new}
operator. operator.
\begin{lstlisting}[caption={Smarts pointers and creating objects}] \begin{lstlisting}[caption={Smarts pointers and creating objects}]
class myObject : public vmime::object class myObject : public vmime::object {
{
public: public:
myObject(const vmime::string& name) myObject(const vmime::string& name)
: m_name(name) : m_name(name) {
{
} }
void sayHello() void sayHello() {
{
std::cout << "Hello " << m_name << std::endl; std::cout << "Hello " << m_name << std::endl;
} }
@ -65,8 +65,8 @@ private:
vmime::string m_name; vmime::string m_name;
}; };
int main() int main() {
{
vmime::shared_ptr <myObject> obj = vmime::shared_ptr <myObject> obj =
vmime::make_shared <myObject>("world"); vmime::make_shared <myObject>("world");
@ -105,12 +105,12 @@ directly or indirectly to itself). The following example illustrates a
typical problem of reference counting: typical problem of reference counting:
\begin{lstlisting} \begin{lstlisting}
class parent : public vmime::object class parent : public vmime::object {
{
public: public:
void createChild(vmime::shared_ptr <child> c) void createChild(vmime::shared_ptr <child> c) {
{
m_child = c; m_child = c;
} }
@ -119,13 +119,13 @@ private:
vmime::shared_ptr <child> m_child; vmime::shared_ptr <child> m_child;
}; };
class child : public vmime::object class child : public vmime::object {
{
public: public:
child(vmime::shared_ptr <parent> p) child(vmime::shared_ptr <parent> p)
: m_parent(p) : m_parent(p) {
{
} }
private: private:
@ -133,8 +133,8 @@ private:
vmime::shared_ptr <parent> m_parent; vmime::shared_ptr <parent> m_parent;
}; };
int main() int main() {
{
vmime::shared_ptr <parent> p = vmime::make_shared <parent>(); vmime::shared_ptr <parent> p = vmime::make_shared <parent>();
vmime::shared_ptr <child> c = vmime::make_shared <child>(); vmime::shared_ptr <child> c = vmime::make_shared <child>();
@ -179,30 +179,31 @@ Following is an example code for catching VMime exceptions and writing error
messages to the console: messages to the console:
\begin{lstlisting}[caption={Catching VMime exceptions}] \begin{lstlisting}[caption={Catching VMime exceptions}]
std::ostream& operator<<(std::ostream& os, const vmime::exception& e) std::ostream& operator<<(std::ostream& os, const vmime::exception& e) {
{
os << "* vmime::exceptions::" << e.name() << std::endl; os << "* vmime::exceptions::" << e.name() << std::endl;
os << " what = " << e.what() << std::endl; os << " what = " << e.what() << std::endl;
// Recursively print all encapsuled exceptions // Recursively print all encapsuled exceptions
if (e.other() != NULL) if (e.other() != NULL) {
os << *e.other(); os << *e.other();
}
return os; return os;
} }
... ...
try try {
{
// ...some call to VMime... // ...some call to VMime...
}
catch (vmime::exception& e) } catch (vmime::exception& e) {
{
std::cerr << e; // VMime exception std::cerr << e; // VMime exception
}
catch (std::exception& e) } catch (std::exception& e) {
{
std::cerr << e.what(); // standard exception std::cerr << e.what(); // standard exception
} }
\end{lstlisting} \end{lstlisting}
@ -250,7 +251,8 @@ vmime::datetime d1("Sat, 08 Oct 2005 14:07:52 +0200");
vmime::datetime d2( vmime::datetime d2(
/* date */ 2005, vmime::datetime::OCTOBER, 8, /* date */ 2005, vmime::datetime::OCTOBER, 8,
/* time */ 14, 7, 52, /* time */ 14, 7, 52,
/* zone */ vmime::datetime::GMT2); /* zone */ vmime::datetime::GMT2
);
// Getting day of week // Getting day of week
const int dow = d2.getWeekDay(); // 'dow' should be datetime::SATURDAY const int dow = d2.getWeekDay(); // 'dow' should be datetime::SATURDAY
@ -275,7 +277,8 @@ media type with:
\begin{lstlisting} \begin{lstlisting}
vmime::mediaType theType( vmime::mediaType theType(
/* top-level type */ vmime::mediaTypes::IMAGE, /* top-level type */ vmime::mediaTypes::IMAGE,
/* sub-type */ vmime::mediaTypes::IMAGE_JPEG); /* sub-type */ vmime::mediaTypes::IMAGE_JPEG
);
// theType.getType() is "image" // theType.getType() is "image"
// theType.getSubType() is "jpeg" // theType.getSubType() is "jpeg"
@ -594,8 +597,9 @@ std::ifstream* fileStream = new std::ifstream();
fileStream->open("/home/vincent/paris.jpg", std::ios::binary); fileStream->open("/home/vincent/paris.jpg", std::ios::binary);
if (!*fileStream) if (!*fileStream) {
// handle error // handle error
}
vmime::shared_ptr <utility::stream> dataStream = vmime::shared_ptr <utility::stream> dataStream =
vmime::make_shared <vmime::utility::inputStreamPointerAdapter>(fileStream); vmime::make_shared <vmime::utility::inputStreamPointerAdapter>(fileStream);
@ -608,13 +612,12 @@ vmime::shared_ptr <contentHandler> data =
vmime::make_shared <vmime::streamContentHandler>(dataStream, 0); vmime::make_shared <vmime::streamContentHandler>(dataStream, 0);
// Now create the attachment // Now create the attachment
ref <vmime::attachment> att = vmime::make_shared <vmime::defaultAttachment> ref <vmime::attachment> att = vmime::make_shared <vmime::defaultAttachment>(
( /* attachment data */ data,
/* attachment data */ data, /* content type */ vmime::mediaType("image/jpeg"),
/* content type */ vmime::mediaType("image/jpeg"), /* description */ vmime::text("Holiday photo"),
/* description */ vmime::text("Holiday photo"), /* filename */ vmime::word("paris.jpg")
/* filename */ vmime::word("paris.jpg") );
);
\end{lstlisting} \end{lstlisting}
You will see later that the {\vcode vmime::fileAttachment} class already You will see later that the {\vcode vmime::fileAttachment} class already
@ -647,10 +650,11 @@ vmime::shared_ptr <const vmime::contentHandler> cth = body->getContents();
// Then, extract and convert the contents // Then, extract and convert the contents
vmime::utility::outputStreamAdapter out(std::cout); vmime::utility::outputStreamAdapter out(std::cout);
vmime::utility::charsetFilteredOutputStream fout vmime::utility::charsetFilteredOutputStream fout(
(/* source charset */ body->getCharset(), /* source charset */ body->getCharset(),
/* dest charset */ vmime::charset("utf-8"), /* dest charset */ vmime::charset("utf-8"),
/* dest stream */ out); /* dest stream */ out
);
cth->extract(fout); cth->extract(fout);
@ -778,8 +782,8 @@ vmime::shared_ptr <vmime::utility::encoder::encoderFactory> ef =
std::cout << "Available encoders:" << std::endl; std::cout << "Available encoders:" << std::endl;
for (int i = 0 ; i < ef->getEncoderCount() ; ++i) for (int i = 0 ; i < ef->getEncoderCount() ; ++i) {
{
// Output encoder name // Output encoder name
vmime::shared_ptr <const vmime::utility::encoder::encoderFactory::registeredEncoder> vmime::shared_ptr <const vmime::utility::encoder::encoderFactory::registeredEncoder>
enc = ef->getEncoderAt(i); enc = ef->getEncoderAt(i);
@ -792,8 +796,9 @@ for (int i = 0 ; i < ef->getEncoderCount() ; ++i)
std::vector <vmime::string> props = e->getAvailableProperties(); std::vector <vmime::string> props = e->getAvailableProperties();
std::vector <vmime::string>::const_iterator it; std::vector <vmime::string>::const_iterator it;
for (it = props.begin() ; it != props.end() ; ++it) for (it = props.begin() ; it != props.end() ; ++it) {
std::cout << " - " << *it << std::endl; std::cout << " - " << *it << std::endl;
}
\end{lstlisting} \end{lstlisting}

View File

@ -25,8 +25,6 @@ want SASL\footnote{Simple Authentication and Security Layer} support ;
\item either the \href{http://www.openssl.org}{OpenSSL library} or the \item either the \href{http://www.openssl.org}{OpenSSL library} or the
\href{http://www.gnu.org/software/gnutls/}{GNU TLS Library} if you \href{http://www.gnu.org/software/gnutls/}{GNU TLS Library} if you
want SSL and TLS\footnote{Transport Layer Security} support ; want SSL and TLS\footnote{Transport Layer Security} support ;
\item the \href{http://www.boost.org}{Boost C++ library} if you are not using
C++11 (or your compiler does not support it), for {\vcode shared\_ptr<>}.
\end{itemize} \end{itemize}
% ============================================================================ % ============================================================================

View File

@ -55,7 +55,7 @@ General Public License\footnote{See Appendix \ref{appendix_license} and
\url{http://www.gnu.org/copyleft/gpl.html}} (GPL) version 3: \url{http://www.gnu.org/copyleft/gpl.html}} (GPL) version 3:
\begin{verbatim} \begin{verbatim}
Copyright (C) 2002-2013 Vincent Richard Copyright (C) 2002 Vincent Richard
VMime library is free software; you can redistribute it and/or VMime library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as modify it under the terms of the GNU General Public License as
@ -79,7 +79,7 @@ GNU Free Documentation
License\footnote{See \url{http://www.gnu.org/copyleft/fdl.html}} (FDL): License\footnote{See \url{http://www.gnu.org/copyleft/fdl.html}} (FDL):
\begin{verbatim} \begin{verbatim}
Copyright (C) 2004-2013 Vincent Richard Copyright (C) 2004 Vincent Richard
Permission is granted to copy, distribute and/or modify Permission is granted to copy, distribute and/or modify
this document under the terms of the GNU Free Documentation this document under the terms of the GNU Free Documentation

View File

@ -94,8 +94,8 @@ vmime::messageParser mp(msg);
std::cout << "Message has " << mp.getAttachmentCount() std::cout << "Message has " << mp.getAttachmentCount()
<< " attachment(s)" << std::endl; << " attachment(s)" << std::endl;
for (int i = 0 ; i < mp.getAttachmentCount() ; ++i) for (int i = 0 ; i < mp.getAttachmentCount() ; ++i) {
{
vmime::shared_ptr <const vmime::attachment> att = mp.getAttachmentAt(i); vmime::shared_ptr <const vmime::attachment> att = mp.getAttachmentAt(i);
std::cout << " - " << att->getType().generate() << std::endl; std::cout << " - " << att->getType().generate() << std::endl;
} }
@ -104,13 +104,13 @@ for (int i = 0 ; i < mp.getAttachmentCount() ; ++i)
std::cout << "Message has " << mp.getTextPartCount() std::cout << "Message has " << mp.getTextPartCount()
<< " text part(s)" << std::endl; << " text part(s)" << std::endl;
for (int i = 0 ; i < mp.getTextPartCount() ; ++i) for (int i = 0 ; i < mp.getTextPartCount() ; ++i) {
{
vmime::shared_ptr <const vmime::textPart> tp = mp.getTextPartAt(i); vmime::shared_ptr <const vmime::textPart> tp = mp.getTextPartAt(i);
// text/html // text/html
if (tp->getType().getSubType() == vmime::mediaTypes::TEXT_HTML) if (tp->getType().getSubType() == vmime::mediaTypes::TEXT_HTML) {
{
vmime::shared_ptr <const vmime::htmlTextPart> htp = vmime::shared_ptr <const vmime::htmlTextPart> htp =
vmime::dynamicCast <const vmime::htmlTextPart>(tp); vmime::dynamicCast <const vmime::htmlTextPart>(tp);
@ -118,18 +118,18 @@ for (int i = 0 ; i < mp.getTextPartCount() ; ++i)
// Plain text is in tp->getPlainText() // Plain text is in tp->getPlainText()
// Enumerate embedded objects // Enumerate embedded objects
for (int j = 0 ; j < htp->getObjectCount() ; ++j) for (int j = 0 ; j < htp->getObjectCount() ; ++j) {
{
vmime::shared_ptr <const vmime::htmlTextPart::embeddedObject> obj = vmime::shared_ptr <const vmime::htmlTextPart::embeddedObject> obj =
htp->getObjectAt(j); htp->getObjectAt(j);
// Identifier (Content-Id or Content-Location) is obj->getId() // Identifier (Content-Id or Content-Location) is obj->getId()
// Object data is in obj->getData() // Object data is in obj->getData()
} }
}
// text/plain or anything else // text/plain or anything else
else } else {
{
// Text is in tp->getText() // Text is in tp->getText()
} }
} }
@ -172,8 +172,7 @@ hdr->appendField(subjectField);
vmime::shared_ptr <vmime::headerField> fromField = vmime::shared_ptr <vmime::headerField> fromField =
hfFactory->create(vmime::fields::FROM); hfFactory->create(vmime::fields::FROM);
fromField->setValue fromField->setValue(vmime::make_shared <vmime::mailbox>("me@vmime.org"));
(vmime::make_shared <vmime::mailbox>("me@vmime.org"));
hdr->appendField(fromField); hdr->appendField(fromField);
// Append a 'To:' field // Append a 'To:' field
@ -190,8 +189,11 @@ toField->setValue(recipients);
hdr->appendField(toField); hdr->appendField(toField);
// Set the body contents // Set the body contents
bdy->setContents(vmime::make_shared <vmime::stringContentHandler> bdy->setContents(
("This is the text of your message...")); vmime::make_shared <vmime::stringContentHandler>(
"This is the text of your message..."
)
);
// Output raw message data to standard output // Output raw message data to standard output
vmime::utility::outputStreamAdapter out(std::cout); vmime::utility::outputStreamAdapter out(std::cout);
@ -207,19 +209,23 @@ previous example, using the {\vcode vmime::messageBuilder} object:
\begin{lstlisting}[caption={Building a simple message \begin{lstlisting}[caption={Building a simple message
using {\vcode vmime::messageBuilder}}] using {\vcode vmime::messageBuilder}}]
try try {
{
vmime::messageBuilder mb; vmime::messageBuilder mb;
// Fill in some header fields and message body // Fill in some header fields and message body
mb.setSubject(vmime::text("Message subject")); mb.setSubject(vmime::text("Message subject"));
mb.setExpeditor(vmime::mailbox("me@vmime.org")); mb.setExpeditor(vmime::mailbox("me@vmime.org"));
mb.getRecipients().appendAddress mb.getRecipients().appendAddress(
(vmime::make_shared <vmime::mailbox>("you@vmime.org")); vmime::make_shared <vmime::mailbox>("you@vmime.org")
);
mb.getTextPart()->setCharset(vmime::charsets::ISO8859_15); mb.getTextPart()->setCharset(vmime::charsets::ISO8859_15);
mb.getTextPart()->setText(vmime::make_shared <vmime::stringContentHandler> mb.getTextPart()->setText(
("This is the text of your message...")); vmime::make_shared <vmime::stringContentHandler>(
"This is the text of your message..."
)
);
// Message construction // Message construction
vmime::shared_ptr <vmime::message> msg = mb.construct(); vmime::shared_ptr <vmime::message> msg = mb.construct();
@ -227,15 +233,15 @@ try
// Output raw message data to standard output // Output raw message data to standard output
vmime::utility::outputStreamAdapter out(std::cout); vmime::utility::outputStreamAdapter out(std::cout);
msg->generate(out); msg->generate(out);
}
// VMime exception // VMime exception
catch (vmime::exception& e) } catch (vmime::exception& e) {
{
std::cerr << "vmime::exception: " << e.what() << std::endl; std::cerr << "vmime::exception: " << e.what() << std::endl;
}
// Standard exception // Standard exception
catch (std::exception& e) } catch (std::exception& e) {
{
std::cerr << "std::exception: " << e.what() << std::endl; std::cerr << "std::exception: " << e.what() << std::endl;
} }
\end{lstlisting} \end{lstlisting}
@ -250,17 +256,17 @@ previous example to attach a file to the message:
{\vcode vmime::messageBuilder}}] {\vcode vmime::messageBuilder}}]
// Create an attachment // Create an attachment
vmime::shared_ptr <vmime::fileAttachment> att = vmime::shared_ptr <vmime::fileAttachment> att =
vmime::make_shared <vmime::fileAttachment> vmime::make_shared <vmime::fileAttachment>(
( /* full path to file */ "/home/vincent/paris.jpg",
/* full path to file */ "/home/vincent/paris.jpg", /* content type */ vmime::mediaType("image/jpeg),
/* content type */ vmime::mediaType("image/jpeg), /* description */ vmime::text("My holidays in Paris")
/* description */ vmime::text("My holidays in Paris")
); );
// You can also set some infos about the file // You can also set some infos about the file
att->getFileInfo().setFilename("paris.jpg"); att->getFileInfo().setFilename("paris.jpg");
att->getFileInfo().setCreationDate att->getFileInfo().setCreationDate(
(vmime::datetime("30 Apr 2003 14:30:00 +0200")); vmime::datetime("30 Apr 2003 14:30:00 +0200")
);
// Add this attachment to the message // Add this attachment to the message
mb.appendAttachment(att); mb.appendAttachment(att);
@ -283,14 +289,19 @@ using the {\vcode vmime::messageBuilder}}]
// Fill in some header fields // Fill in some header fields
mb.setSubject(vmime::text("An HTML message")); mb.setSubject(vmime::text("An HTML message"));
mb.setExpeditor(vmime::mailbox("me@vmime.org")); mb.setExpeditor(vmime::mailbox("me@vmime.org"));
mb.getRecipients().appendAddress mb.getRecipients().appendAddress(
(vmime::make_shared <vmime::mailbox>("you@vmime.org")); vmime::make_shared <vmime::mailbox>("you@vmime.org")
);
// Set the content-type to "text/html": a text part factory must be // Set the content-type to "text/html": a text part factory must be
// available for the type you are using. The following code will make // available for the type you are using. The following code will make
// the message builder construct the two text parts. // the message builder construct the two text parts.
mb.constructTextPart(vmime::mediaType mb.constructTextPart(
(vmime::mediaTypes::TEXT, vmime::mediaTypes::TEXT_HTML)); vmime::mediaType(
vmime::mediaTypes::TEXT,
vmime::mediaTypes::TEXT_HTML
)
);
// Set contents of the text parts; the message is available in two formats: // Set contents of the text parts; the message is available in two formats:
// HTML and plain text. The HTML format also includes an embedded image. // HTML and plain text. The HTML format also includes an embedded image.
@ -306,12 +317,18 @@ const vmime::string id = textPart->addObject("<...image data...>",
// -- Set the text // -- Set the text
textPart->setCharset(vmime::charsets::ISO8859_15); textPart->setCharset(vmime::charsets::ISO8859_15);
textPart->setText(vmime::make_shared <vmime::stringContentHandler> textPart->setText(
("This is the <b>HTML text</b>, and the image:<br/>" vmime::make_shared <vmime::stringContentHandler>(
"<img src=\"") + id + vmime::string("\"/>")); "This is the <b>HTML text</b>, and the image:<br/>"
"<img src=\"") + id + vmime::string("\"/>"
)
);
textPart->setPlainText(vmime::make_shared <vmime::stringContentHandler> textPart->setPlainText(
("This is the plain text.")); vmime::make_shared <vmime::stringContentHandler>(
"This is the plain text."
)
);
\end{lstlisting} \end{lstlisting}
This will create a message having the following structure: This will create a message having the following structure:
@ -336,11 +353,18 @@ vmime::shared_ptr <vmime::utility::file> imageFile =
fs->create(fs->stringToPath("/path/to/image.jpg")); fs->create(fs->stringToPath("/path/to/image.jpg"));
vmime::shared_ptr <vmime::contentHandler> imageCts = vmime::shared_ptr <vmime::contentHandler> imageCts =
vmime::make_shared <vmime::streamContentHandler> vmime::make_shared <vmime::streamContentHandler>(
(imageFile->getFileReader()->getInputStream(), imageFile->getLength()); imageFile->getFileReader()->getInputStream(),
imageFile->getLength()
);
const vmime::string cid = textPart.addObject(imageCts, const vmime::string cid = textPart.addObject(
vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG)); imageCts,
vmime::mediaType(
vmime::mediaTypes::IMAGE,
vmime::mediaTypes::IMAGE_JPEG
)
);
\end{lstlisting} \end{lstlisting}
@ -361,8 +385,8 @@ extract its contents to the standard output:
\begin{lstlisting}[caption={Testing if a body part is an attachment}] \begin{lstlisting}[caption={Testing if a body part is an attachment}]
vmime::shared_ptr <vmime::bodyPart> part; // suppose we have a body part vmime::shared_ptr <vmime::bodyPart> part; // suppose we have a body part
if (vmime::attachmentHelper::isBodyPartAnAttachment(part)) if (vmime::attachmentHelper::isBodyPartAnAttachment(part)) {
{
// The body part contains an attachment, get it // The body part contains an attachment, get it
vmime::shared_ptr <const vmime::attachment> attach = vmime::shared_ptr <const vmime::attachment> attach =
attachmentHelper::getBodyPartAttachment(part); attachmentHelper::getBodyPartAttachment(part);
@ -394,11 +418,10 @@ vmime::shared_ptr <vmime::message> msg; // suppose we have a message
// Create an attachment // Create an attachment
vmime::shared_ptr <vmime::fileAttachment> att = vmime::shared_ptr <vmime::fileAttachment> att =
vmime::make_shared <vmime::fileAttachment> vmime::make_shared <vmime::fileAttachment>(
( /* full path to file */ "/home/vincent/paris.jpg",
/* full path to file */ "/home/vincent/paris.jpg", /* content type */ vmime::mediaType("image/jpeg),
/* content type */ vmime::mediaType("image/jpeg), /* description */ vmime::text("My holidays in Paris")
/* description */ vmime::text("My holidays in Paris")
); );
// Attach it to the message // Attach it to the message

View File

@ -300,10 +300,10 @@ The following example shows how to use a custom authenticator to request
the user to enter her/his credentials: the user to enter her/his credentials:
\begin{lstlisting}[caption={A simple interactive authenticator}] \begin{lstlisting}[caption={A simple interactive authenticator}]
class myAuthenticator : public vmime::security::defaultAuthenticator class myAuthenticator : public vmime::security::defaultAuthenticator {
{
const string getUsername() const const string getUsername() const {
{
std::cout << "Enter your username: " << std::endl; std::cout << "Enter your username: " << std::endl;
vmime::string res; vmime::string res;
@ -312,8 +312,8 @@ class myAuthenticator : public vmime::security::defaultAuthenticator
return res; return res;
} }
const string getPassword() const const string getPassword() const {
{
std::cout << "Enter your password: " << std::endl; std::cout << "Enter your password: " << std::endl;
vmime::string res; vmime::string res;
@ -331,9 +331,10 @@ This is how to use it:
vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create(); vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create();
// Next, initialize a service which will use our authenticator // Next, initialize a service which will use our authenticator
vmime::shared_ptr <vmime::net::store> st = vmime::shared_ptr <vmime::net::store> st = sess->getStore(
sess->getStore(vmime::utility::url("imap://imap.example.com"), vmime::utility::url("imap://imap.example.com"),
/* use our authenticator */ vmime::make_shared <myAuthenticator>()); /* use our authenticator */ vmime::make_shared <myAuthenticator>()
);
\end{lstlisting} \end{lstlisting}
\vnote{An authenticator object should be used with one and only one service \vnote{An authenticator object should be used with one and only one service
@ -354,14 +355,15 @@ use the SASL-specific methods {\vcode getAcceptableMechanisms()} and
implementation of an SASL authenticator. implementation of an SASL authenticator.
\begin{lstlisting}[caption={A simple SASL authenticator}] \begin{lstlisting}[caption={A simple SASL authenticator}]
class mySASLAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator class mySASLAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator {
{
typedef vmime::security::sasl::SASLMechanism mechanism; // save us typing typedef vmime::security::sasl::SASLMechanism mechanism; // save us typing
const std::vector <vmime::shared_ptr <mechanism> > getAcceptableMechanisms const std::vector <vmime::shared_ptr <mechanism> > getAcceptableMechanisms(
(const std::vector <vmime::shared_ptr <mechanism> >& available, const std::vector <vmime::shared_ptr <mechanism> >& available,
vmime::shared_ptr <mechanism> suggested) const const vmime::shared_ptr <mechanism>& suggested
{ ) const {
// Here, you can sort the SASL mechanisms in the order they will be // Here, you can sort the SASL mechanisms in the order they will be
// tried. If no SASL mechanism is acceptable (ie. for example, not // tried. If no SASL mechanism is acceptable (ie. for example, not
// enough secure), you can return an empty list. // enough secure), you can return an empty list.
@ -372,8 +374,8 @@ class mySASLAuthenticator : public vmime::security::sasl::defaultSASLAuthenticat
getAcceptableMechanisms(available, suggested); getAcceptableMechanisms(available, suggested);
} }
void setSASLMechanism(vmime::shared_ptr <mechanism> mech) void setSASLMechanism(const vmime::shared_ptr <mechanism>& mech) {
{
// This is called when the authentication process is going to // This is called when the authentication process is going to
// try the specified mechanism. // try the specified mechanism.
// //
@ -435,7 +437,8 @@ tr->send(
/* expeditor */ from, /* expeditor */ from,
/* recipient(s) */ to, /* recipient(s) */ to,
/* data */ is, /* data */ is,
/* total length */ msgData.length()); /* total length */ msgData.length()
);
// We have finished using the service // We have finished using the service
tr->disconnect(); tr->disconnect();
@ -556,22 +559,26 @@ std::vector <ref <vmime::net::message> > allMessages =
folder->getMessages(vmime::net::messageSet::byNumber(1, -1)); folder->getMessages(vmime::net::messageSet::byNumber(1, -1));
// -1 is a special value to mean "the number of the last message in the folder" // -1 is a special value to mean "the number of the last message in the folder"
folder->fetchMessages(allMessages, folder->fetchMessages(
allMessages,
vmime::net::fetchAttributes::FLAGS | vmime::net::fetchAttributes::FLAGS |
vmime::net::fetchAttributes::ENVELOPE); vmime::net::fetchAttributes::ENVELOPE
);
for (unsigned int i = 0 ; i < allMessages.size() ; ++i) {
for (unsigned int i = 0 ; i < allMessages.size() ; ++i)
{
vmime::shared_ptr <vmime::net::message> msg = allMessages[i]; vmime::shared_ptr <vmime::net::message> msg = allMessages[i];
const int flags = msg->getFlags(); const int flags = msg->getFlags();
std::cout << "Message " << i << ":" << std::endl; std::cout << "Message " << i << ":" << std::endl;
if (flags & vmime::net::message::FLAG_SEEN) if (flags & vmime::net::message::FLAG_SEEN) {
std::cout << " - is read" << std::endl; std::cout << " - is read" << std::endl;
if (flags & vmime::net::message::FLAG_DELETED) }
if (flags & vmime::net::message::FLAG_DELETED) {
std::cout << " - is deleted" << std::endl; std::cout << " - is deleted" << std::endl;
}
vmime::shared_ptr <const vmime::header> hdr = msg->getHeader(); vmime::shared_ptr <const vmime::header> hdr = msg->getHeader();
@ -698,8 +705,8 @@ running.
An interface called {\vcode timeoutHandler} is provided: An interface called {\vcode timeoutHandler} is provided:
\begin{lstlisting} \begin{lstlisting}
class timeoutHandler : public object class timeoutHandler : public object {
{
/** Called to test if the time limit has been reached. /** Called to test if the time limit has been reached.
* *
* @return true if the timeout delay is elapsed * @return true if the timeout delay is elapsed
@ -738,27 +745,27 @@ is thrown.
The following example shows how to implement a simple timeout handler: The following example shows how to implement a simple timeout handler:
\begin{lstlisting}[caption={Implementing a simple timeout handler}] \begin{lstlisting}[caption={Implementing a simple timeout handler}]
class myTimeoutHandler : public vmime::net::timeoutHandler class myTimeoutHandler : public vmime::net::timeoutHandler {
{
public: public:
myTimeoutHandler() myTimeoutHandler() {
{
m_startTime = time(NULL); m_startTime = time(NULL);
} }
const bool isTimeOut() const bool isTimeOut() {
{
return (time(NULL) >= m_startTime + 30); // 30 seconds timeout return time(NULL) >= m_startTime + 30; // 30 seconds timeout
} }
void resetTimeOut() void resetTimeOut() {
{
m_startTime = time(NULL); m_startTime = time(NULL);
} }
const bool handleTimeOut() const bool handleTimeOut() {
{
std::cout << "Operation timed out." << std::endl; std::cout << "Operation timed out." << std::endl;
<< "Press [Y] to continue, or [N] to " << "Press [Y] to continue, or [N] to "
<< "cancel the operation." << std::endl; << "cancel the operation." << std::endl;
@ -766,7 +773,7 @@ public:
std::string response; std::string response;
std::cin >> response; std::cin >> response;
return (response == "y" || response == "Y"); return response == "y" || response == "Y";
} }
private: private:
@ -781,12 +788,12 @@ is required because the service can use several connections to the server
simultaneously, and each connection needs its own timeout handler. simultaneously, and each connection needs its own timeout handler.
\begin{lstlisting} \begin{lstlisting}
class myTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory class myTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory {
{
public: public:
ref <timeoutHandler> create() ref <timeoutHandler> create() {
{
return vmime::make_shared <myTimeoutHandler>(); return vmime::make_shared <myTimeoutHandler>();
} }
}; };
@ -918,30 +925,19 @@ First, we need some code to load existing X.509 certificates:
\begin{lstlisting}[caption={Reading a X.509 certificate from a file}] \begin{lstlisting}[caption={Reading a X.509 certificate from a file}]
vmime::shared_ptr <vmime::security::cert::X509Certificate> vmime::shared_ptr <vmime::security::cert::X509Certificate>
loadX509CertificateFromFile(const std::string& path) loadX509CertificateFromFile(const std::string& path) {
{
std::ifstream certFile; std::ifstream certFile;
certFile.open(path.c_str(), std::ios::in | std::ios::binary); certFile.open(path.c_str(), std::ios::in | std::ios::binary);
if (!certFile) if (!certFile) {
{
// ...handle error... // ...handle error...
} }
vmime::utility::inputStreamAdapter is(certFile); vmime::utility::inputStreamAdapter is(certFile);
vmime::shared_ptr <vmime::security::cert::X509Certificate> cert; vmime::shared_ptr <vmime::security::cert::X509Certificate> cert;
// Try DER format cert = vmime::security::cert::X509Certificate::import(is);
cert = vmime::security::cert::X509Certificate::import
(is, vmime::security::cert::X509Certificate::FORMAT_DER);
if (cert != NULL)
return cert;
// Try PEM format
is.reset();
cert = vmime::security::cert::X509Certificate::import
(is, vmime::security::cert::X509Certificate::FORMAT_PEM);
return cert; return cert;
} }
@ -988,12 +984,12 @@ use this in a production application as this is obviously a serious security
issue): issue):
\begin{lstlisting}[caption={A custom certificate verifier}] \begin{lstlisting}[caption={A custom certificate verifier}]
class myCertVerifier : public vmime::security::cert::certificateVerifier class myCertVerifier : public vmime::security::cert::certificateVerifier {
{
public: public:
void verify(vmime::shared_ptr <certificateChain> certs) void verify(const vmime::shared_ptr <certificateChain>& certs) {
{
// Obtain the subject's certificate // Obtain the subject's certificate
vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0); vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0);
@ -1006,8 +1002,9 @@ public:
std::string answer; std::string answer;
std::getline(std::cin, answer); std::getline(std::cin, answer);
if (answer.length() != 0 && (answer[0] == 'Y' || answer[0] == 'y')) if (answer.length() != 0 && (answer[0] == 'Y' || answer[0] == 'y')) {
return; // OK, we trust the certificate return; // OK, we trust the certificate
}
// Don't trust this certificate // Don't trust this certificate
throw vmime::security::cert::certificateException(); throw vmime::security::cert::certificateException();
@ -1090,3 +1087,117 @@ The following constants are available:
\hline \hline
\end{tabularx} \end{tabularx}
% ============================================================================
\section{Tracing connection}
Connection tracing is used to log what is sent and received on the wire
between the client and the server, and may help debugging.
First, you have to create your own tracer, which must implement the
{\vcode vmime::net::tracer} interface. Here is an example of a tracer which
simply logs to the standard output:
\begin{lstlisting}[caption={A simple tracer}]
class myTracer : public vmime::net::tracer {
public:
myTracer(const vmime::string& proto, const int connectionId)
: m_proto(proto),
m_connectionId(connectionId) {
}
// Called by VMime to trace what is sent on the socket
void traceSend(const vmime::string& line) {
std::cout << "[" << m_proto << ":" << m_connectionId
<< "] C: " << line << std::endl;
}
// Called by VMime to trace what is received from the socket
void traceReceive(const vmime::string& line) {
std::cout << "[" < < m_proto << ":" << m_connectionId
<< "] S: " << line << std::endl;
}
private:
const vmime::string m_proto;
const int m_connectionId;
};
\end{lstlisting}
Also create a factory class, used to instanciate your tracer objects:
\begin{lstlisting}
class myTracerFactory : public vmime::net::tracerFactory {
public:
vmime::shared_ptr <vmime::net::tracer> create(
const vmime::shared_ptr <vmime::net::service>& serv,
const int connectionId
) {
return vmime::make_shared <myTracer>(
serv->getProtocolName(), connectionId
);
}
};
\end{lstlisting}
Next, we have to tell VMime to use it. When you create your service
(either store or transport), simply call the {\vcode setTracerFactory}
on the service and pass an instance of your factory class:
\begin{lstlisting}[caption={Enabling tracer on a connection}]
vmime::shared_ptr <vmime::net::transport> store =
session->getStore("imaps://user:password@imap.myserver.com");
// Enable tracing communication between client and server
store->setTracerFactory(vmime::make_shared <myTracerFactory>());
\end{lstlisting}
That's all! Now, everything which is sent on/received from the socket
will be logged using your tracer object. Here is an example of a trace
session for IMAP:
\begin{verbatim}
[imaps:1] S: * OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR
LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN] Dovecot ready.
[imaps:1] C: a001 AUTHENTICATE PLAIN
[imaps:1] S: +
[imaps:1] C: {...SASL exchange: 52 bytes of data...}
[imaps:1] S: a001 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR
LOGIN-REFERRALS ID ENABLE IDLE SORT SPECIAL-USE QUOTA] Logged in
[imaps:1] C: a002 LIST "" ""
[imaps:1] S: * LIST (\Noselect) "." ""
[imaps:1] S: a002 OK List completed.
[imaps:1] C: a003 CAPABILITY
[imaps:1] S: * CAPABILITY IMAP4rev1 LITERAL+ SASL-IR
LOGIN-REFERRALS ID ENABLE IDLE SORT SPECIAL-USE QUOTA
[imaps:1] S: a003 OK Capability completed.
[imaps:1] C: a003 SELECT INBOX (CONDSTORE)
[imaps:1] S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft
$NotJunk NonJunk JunkRecorded $MDNSent NotJunk $Forwarded
Junk $Junk Forwarded $MailFlagBit1)
[imaps:1] S: * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted
\Seen \Draft $NotJunk NonJunk JunkRecorded $MDNSent NotJunk
$Forwarded Junk $Junk Forwarded $MailFlagBit1 \*)]
Flags permitted.
[imaps:1] S: * 104 EXISTS
[imaps:1] S: * 0 RECENT
[imaps:1] S: * OK [UNSEEN 6] First unseen.
[imaps:1] S: * OK [UIDVALIDITY 1268127585] UIDs valid
[imaps:1] S: * OK [UIDNEXT 32716] Predicted next UID
[imaps:1] S: * OK [HIGHESTMODSEQ 148020] Highest
[imaps:1] S: a003 OK [READ-WRITE] Select completed.
\end{verbatim}
Please note that no sensitive data (ie. login or password) will be traced.
Same, {\em blob} data such as message content or SASL exchanges will be logged
as a marker which indicates how many bytes were sent/received (eg. "{...SASL
exchange: 52 bytes of data...}"").

View File

@ -26,7 +26,7 @@ You can simply build your program with:
to use the static version, or with: to use the static version, or with:
\begin{verbatim} \begin{verbatim}
$ g++ `pkg-config --cflags --libs vmime` -o myprog myprog.cpp $ g++ `pkg-config --cflags vmime` -o myprog myprog.cpp `pkg-config --libs vmime`
\end{verbatim} \end{verbatim}
to use the shared version. to use the shared version.
@ -82,8 +82,8 @@ So, if your platform is POSIX, your program should look like this:
#include <vmime/vmime.hpp> #include <vmime/vmime.hpp>
#include <vmime/platforms/posix/posixHandler.hpp> #include <vmime/platforms/posix/posixHandler.hpp>
int main() int main() {
{
vmime::platform:: vmime::platform::
setHandler <vmime::platforms::posix::posixHandler>(); setHandler <vmime::platforms::posix::posixHandler>();

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -39,23 +39,20 @@
#include "vmime/platforms/posix/posixHandler.hpp" #include "vmime/platforms/posix/posixHandler.hpp"
int main() int main() {
{
std::cout << std::endl; std::cout << std::endl;
// Set the global C and C++ locale to the user-configured locale. // Set the global C and C++ locale to the user-configured locale.
// The locale should use UTF-8 encoding for these tests to run successfully. // The locale should use UTF-8 encoding for these tests to run successfully.
try try {
{
std::locale::global(std::locale("")); std::locale::global(std::locale(""));
} } catch (std::exception &) {
catch (std::exception &)
{
std::setlocale(LC_ALL, ""); std::setlocale(LC_ALL, "");
} }
try try {
{
vmime::messageBuilder mb; vmime::messageBuilder mb;
// Fill in the basic fields // Fill in the basic fields
@ -74,9 +71,12 @@ int main()
mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder")); mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder"));
// Message body // Message body
mb.getTextPart()->setText(vmime::make_shared <vmime::stringContentHandler>( mb.getTextPart()->setText(
"I'm writing this short text to test message construction " \ vmime::make_shared <vmime::stringContentHandler>(
"using the vmime::messageBuilder component.")); "I'm writing this short text to test message construction " \
"using the vmime::messageBuilder component."
)
);
// Construction // Construction
vmime::shared_ptr <vmime::message> msg = mb.construct(); vmime::shared_ptr <vmime::message> msg = mb.construct();
@ -87,20 +87,21 @@ int main()
vmime::utility::outputStreamAdapter out(std::cout); vmime::utility::outputStreamAdapter out(std::cout);
msg->generate(out); msg->generate(out);
}
// VMime exception // VMime exception
catch (vmime::exception& e) } catch (vmime::exception& e) {
{
std::cout << "vmime::exception: " << e.what() << std::endl; std::cout << "vmime::exception: " << e.what() << std::endl;
throw; throw;
}
// Standard exception // Standard exception
catch (std::exception& e) } catch (std::exception& e) {
{
std::cout << "std::exception: " << e.what() << std::endl; std::cout << "std::exception: " << e.what() << std::endl;
//throw; throw;
} }
std::cout << std::endl; std::cout << std::endl;
}
return 0;
}

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -39,23 +39,20 @@
#include "vmime/platforms/posix/posixHandler.hpp" #include "vmime/platforms/posix/posixHandler.hpp"
int main() int main() {
{
std::cout << std::endl; std::cout << std::endl;
// Set the global C and C++ locale to the user-configured locale. // Set the global C and C++ locale to the user-configured locale.
// The locale should use UTF-8 encoding for these tests to run successfully. // The locale should use UTF-8 encoding for these tests to run successfully.
try try {
{
std::locale::global(std::locale("")); std::locale::global(std::locale(""));
} } catch (std::exception &) {
catch (std::exception &)
{
std::setlocale(LC_ALL, ""); std::setlocale(LC_ALL, "");
} }
try try {
{
vmime::messageBuilder mb; vmime::messageBuilder mb;
// Fill in the basic fields // Fill in the basic fields
@ -74,17 +71,20 @@ int main()
mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder")); mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder"));
// Message body // Message body
mb.getTextPart()->setText(vmime::make_shared <vmime::stringContentHandler>( mb.getTextPart()->setText(
"I'm writing this short text to test message construction " \ vmime::make_shared <vmime::stringContentHandler>(
"with attachment, using the vmime::messageBuilder component.")); "I'm writing this short text to test message construction " \
"with attachment, using the vmime::messageBuilder component."
)
);
// Adding an attachment // Adding an attachment
vmime::shared_ptr <vmime::fileAttachment> a = vmime::make_shared <vmime::fileAttachment> vmime::shared_ptr <vmime::fileAttachment> a =
( vmime::make_shared <vmime::fileAttachment>(
__FILE__, // full path to file __FILE__, // full path to file
vmime::mediaType("application/octet-stream"), // content type vmime::mediaType("application/octet-stream"), // content type
vmime::text("My first attachment") // description vmime::text("My first attachment") // description
); );
a->getFileInfo().setFilename("example2.cpp"); a->getFileInfo().setFilename("example2.cpp");
a->getFileInfo().setCreationDate(vmime::datetime("30 Apr 2003 14:30:00 +0200")); a->getFileInfo().setCreationDate(vmime::datetime("30 Apr 2003 14:30:00 +0200"));
@ -101,20 +101,21 @@ int main()
std::cout << "==================" << std::endl; std::cout << "==================" << std::endl;
std::cout << std::endl; std::cout << std::endl;
std::cout << dataToSend << std::endl; std::cout << dataToSend << std::endl;
}
// VMime exception // VMime exception
catch (vmime::exception& e) } catch (vmime::exception& e) {
{
std::cout << "vmime::exception: " << e.what() << std::endl; std::cout << "vmime::exception: " << e.what() << std::endl;
throw; throw;
}
// Standard exception // Standard exception
catch (std::exception& e) } catch (std::exception& e) {
{
std::cout << "std::exception: " << e.what() << std::endl; std::cout << "std::exception: " << e.what() << std::endl;
throw; throw;
} }
std::cout << std::endl; std::cout << std::endl;
}
return 0;
}

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -39,23 +39,20 @@
#include "vmime/platforms/posix/posixHandler.hpp" #include "vmime/platforms/posix/posixHandler.hpp"
int main() int main() {
{
std::cout << std::endl; std::cout << std::endl;
// Set the global C and C++ locale to the user-configured locale. // Set the global C and C++ locale to the user-configured locale.
// The locale should use UTF-8 encoding for these tests to run successfully. // The locale should use UTF-8 encoding for these tests to run successfully.
try try {
{
std::locale::global(std::locale("")); std::locale::global(std::locale(""));
} } catch (std::exception &) {
catch (std::exception &)
{
std::setlocale(LC_ALL, ""); std::setlocale(LC_ALL, "");
} }
try try {
{
vmime::messageBuilder mb; vmime::messageBuilder mb;
// Fill in the basic fields // Fill in the basic fields
@ -74,12 +71,17 @@ int main()
mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder")); mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder"));
// Set the content-type to "text/html" // Set the content-type to "text/html"
mb.constructTextPart(vmime::mediaType mb.constructTextPart(
(vmime::mediaTypes::TEXT, vmime::mediaTypes::TEXT_HTML)); 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. // 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). // HTML text part also includes an inline image (embedded into the message).
vmime::htmlTextPart& textPart = *vmime::dynamicCast <vmime::htmlTextPart>(mb.getTextPart()); vmime::htmlTextPart& textPart =
*vmime::dynamicCast <vmime::htmlTextPart>(mb.getTextPart());
// -- embed an image (the returned "CID" (content identifier) is used to reference // -- embed an image (the returned "CID" (content identifier) is used to reference
// -- the image into HTML content). // -- the image into HTML content).
@ -93,18 +95,33 @@ int main()
imageFile->getFileReader(); imageFile->getFileReader();
vmime::shared_ptr <vmime::contentHandler> imageCts = vmime::shared_ptr <vmime::contentHandler> imageCts =
vmime::make_shared <vmime::streamContentHandler> vmime::make_shared <vmime::streamContentHandler>(
(fileReader->getInputStream(), imageFile->getLength()); fileReader->getInputStream(),
imageFile->getLength()
);
vmime::shared_ptr <const vmime::htmlTextPart::embeddedObject> obj = textPart.addObject vmime::shared_ptr <const vmime::htmlTextPart::embeddedObject> obj =
(imageCts, vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG)); textPart.addObject(
imageCts,
vmime::mediaType(
vmime::mediaTypes::IMAGE,
vmime::mediaTypes::IMAGE_JPEG
)
);
// -- message text // -- message text
textPart.setText(vmime::make_shared <vmime::stringContentHandler> textPart.setText(
(vmime::string("This is the <b>HTML text</b>.<br/>" vmime::make_shared <vmime::stringContentHandler>(
"<img src=\"") + obj->getReferenceId() + vmime::string("\"/>"))); vmime::string("This is the <b>HTML text</b>.<br/>"
textPart.setPlainText(vmime::make_shared <vmime::stringContentHandler> "<img src=\"") + obj->getReferenceId() + vmime::string("\"/>")
("This is the plain text (without HTML formatting).")); )
);
textPart.setPlainText(
vmime::make_shared <vmime::stringContentHandler>(
"This is the plain text (without HTML formatting)."
)
);
// Construction // Construction
vmime::shared_ptr <vmime::message> msg = mb.construct(); vmime::shared_ptr <vmime::message> msg = mb.construct();
@ -116,20 +133,21 @@ int main()
std::cout << "==================" << std::endl; std::cout << "==================" << std::endl;
std::cout << std::endl; std::cout << std::endl;
std::cout << dataToSend << std::endl; std::cout << dataToSend << std::endl;
}
// VMime exception // VMime exception
catch (vmime::exception& e) } catch (vmime::exception& e) {
{
std::cout << "vmime::exception: " << e.what() << std::endl; std::cout << "vmime::exception: " << e.what() << std::endl;
throw; throw;
}
// Standard exception // Standard exception
catch (std::exception& e) } catch (std::exception& e) {
{
std::cout << "std::exception: " << e.what() << std::endl; std::cout << "std::exception: " << e.what() << std::endl;
throw; throw;
} }
std::cout << std::endl; std::cout << std::endl;
}
return 0;
}

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -39,71 +39,70 @@
#include "vmime/platforms/posix/posixHandler.hpp" #include "vmime/platforms/posix/posixHandler.hpp"
int main() int main() {
{
std::cout << std::endl; std::cout << std::endl;
// Set the global C and C++ locale to the user-configured locale. // Set the global C and C++ locale to the user-configured locale.
// The locale should use UTF-8 encoding for these tests to run successfully. // The locale should use UTF-8 encoding for these tests to run successfully.
try try {
{
std::locale::global(std::locale("")); std::locale::global(std::locale(""));
} } catch (std::exception &) {
catch (std::exception &)
{
std::setlocale(LC_ALL, ""); std::setlocale(LC_ALL, "");
} }
try try {
{
vmime::messageParser mp("<...MIME message content...>"); vmime::messageParser mp("<...MIME message content...>");
// Enumerate text parts // Enumerate text parts
for (size_t i = 0 ; i < mp.getTextPartCount() ; ++i) for (size_t i = 0 ; i < mp.getTextPartCount() ; ++i) {
{
const vmime::textPart& part = *mp.getTextPartAt(i); const vmime::textPart& part = *mp.getTextPartAt(i);
// Output content-type of the part // Output content-type of the part
std::cout << part.getType().generate() << std::endl; std::cout << part.getType().generate() << std::endl;
// text/html // text/html
if (part.getType().getSubType() == vmime::mediaTypes::TEXT_HTML) if (part.getType().getSubType() == vmime::mediaTypes::TEXT_HTML) {
{
const vmime::htmlTextPart& hp = dynamic_cast<const vmime::htmlTextPart&>(part); const vmime::htmlTextPart& hp = dynamic_cast<const vmime::htmlTextPart&>(part);
// HTML text is in "hp.getText()" // HTML text is in "hp.getText()"
// Corresponding plain text is in "hp.getPlainText()" // Corresponding plain text is in "hp.getPlainText()"
// Enumerate embedded objects (eg. images) // Enumerate embedded objects (eg. images)
for (size_t j = 0 ; j < hp.getObjectCount() ; ++j) for (size_t j = 0 ; j < hp.getObjectCount() ; ++j) {
{
const vmime::htmlTextPart::embeddedObject& obj = *hp.getObjectAt(j); const vmime::htmlTextPart::embeddedObject& obj = *hp.getObjectAt(j);
// Identifier (content-id or content-location) is in "obj.getId()" // Identifier (content-id or content-location) is in "obj.getId()"
// Object data is in "obj.getData()" // Object data is in "obj.getData()"
} }
}
// text/plain // text/plain
else } else {
{
const vmime::textPart& tp = dynamic_cast<const vmime::textPart&>(part); const vmime::textPart& tp = dynamic_cast<const vmime::textPart&>(part);
// Text is in "tp.getText()" // Text is in "tp.getText()"
} }
} }
}
// VMime exception // VMime exception
catch (vmime::exception& e) } catch (vmime::exception& e) {
{
std::cout << "vmime::exception: " << e.what() << std::endl; std::cout << "vmime::exception: " << e.what() << std::endl;
throw; throw;
}
// Standard exception // Standard exception
catch (std::exception& e) } catch (std::exception& e) {
{
std::cout << "std::exception: " << e.what() << std::endl; std::cout << "std::exception: " << e.what() << std::endl;
throw; throw;
} }
std::cout << std::endl; std::cout << std::endl;
return 0;
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -39,28 +39,25 @@
#include "vmime/platforms/posix/posixHandler.hpp" #include "vmime/platforms/posix/posixHandler.hpp"
int main() int main() {
{
std::cout << std::endl; std::cout << std::endl;
// Set the global C and C++ locale to the user-configured locale. // Set the global C and C++ locale to the user-configured locale.
// The locale should use UTF-8 encoding for these tests to run successfully. // The locale should use UTF-8 encoding for these tests to run successfully.
try try {
{
std::locale::global(std::locale("")); std::locale::global(std::locale(""));
} } catch (std::exception &) {
catch (std::exception &)
{
std::setlocale(LC_ALL, ""); std::setlocale(LC_ALL, "");
} }
try try {
{
vmime::messageParser mp("<...MIME message content...>"); vmime::messageParser mp("<...MIME message content...>");
// Enumerate attachments // Enumerate attachments
for (size_t i = 0 ; i < mp.getAttachmentCount() ; ++i) for (size_t i = 0 ; i < mp.getAttachmentCount() ; ++i) {
{
const vmime::attachment& att = *mp.getAttachmentAt(i); const vmime::attachment& att = *mp.getAttachmentAt(i);
// Media type (content type) is in "att.getType()" // Media type (content type) is in "att.getType()"
@ -68,19 +65,21 @@ int main()
// Description is in "att.getDescription()" // Description is in "att.getDescription()"
// Data is in "att.getData()" // Data is in "att.getData()"
} }
}
// VMime exception // VMime exception
catch (vmime::exception& e) } catch (vmime::exception& e) {
{
std::cout << "vmime::exception: " << e.what() << std::endl; std::cout << "vmime::exception: " << e.what() << std::endl;
throw; throw;
}
// Standard exception // Standard exception
catch (std::exception& e) } catch (std::exception& e) {
{
std::cout << "std::exception: " << e.what() << std::endl; std::cout << "std::exception: " << e.what() << std::endl;
throw; throw;
} }
std::cout << std::endl; std::cout << std::endl;
return 0;
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -46,22 +46,23 @@ static vmime::shared_ptr <vmime::net::session> g_session = vmime::net::session::
* @param type service type (vmime::net::service::TYPE_STORE or * @param type service type (vmime::net::service::TYPE_STORE or
* vmime::net::service::TYPE_TRANSPORT) * vmime::net::service::TYPE_TRANSPORT)
*/ */
static const std::string findAvailableProtocols(const vmime::net::service::Type type) static const std::string findAvailableProtocols(const vmime::net::service::Type type) {
{
vmime::shared_ptr <vmime::net::serviceFactory> sf = vmime::shared_ptr <vmime::net::serviceFactory> sf =
vmime::net::serviceFactory::getInstance(); vmime::net::serviceFactory::getInstance();
std::ostringstream res; std::ostringstream res;
size_t count = 0; size_t count = 0;
for (size_t i = 0 ; i < sf->getServiceCount() ; ++i) for (size_t i = 0 ; i < sf->getServiceCount() ; ++i) {
{
const vmime::net::serviceFactory::registeredService& serv = *sf->getServiceAt(i); const vmime::net::serviceFactory::registeredService& serv = *sf->getServiceAt(i);
if (serv.getType() == type) if (serv.getType() == type) {
{
if (count != 0) if (count != 0) {
res << ", "; res << ", ";
}
res << serv.getName(); res << serv.getName();
++count; ++count;
@ -73,14 +74,14 @@ static const std::string findAvailableProtocols(const vmime::net::service::Type
// Exception helper // Exception helper
static std::ostream& operator<<(std::ostream& os, const vmime::exception& e) static std::ostream& operator<<(std::ostream& os, const vmime::exception& e) {
{
os << "* vmime::exceptions::" << e.name() << std::endl; os << "* vmime::exceptions::" << e.name() << std::endl;
os << " what = " << e.what() << std::endl; os << " what = " << e.what() << std::endl;
// More information for special exceptions // More information for special exceptions
if (dynamic_cast <const vmime::exceptions::command_error*>(&e)) if (dynamic_cast <const vmime::exceptions::command_error*>(&e)) {
{
const vmime::exceptions::command_error& cee = const vmime::exceptions::command_error& cee =
dynamic_cast <const vmime::exceptions::command_error&>(e); dynamic_cast <const vmime::exceptions::command_error&>(e);
@ -88,32 +89,32 @@ static std::ostream& operator<<(std::ostream& os, const vmime::exception& e)
os << " response = " << cee.response() << std::endl; os << " response = " << cee.response() << std::endl;
} }
if (dynamic_cast <const vmime::exceptions::invalid_response*>(&e)) if (dynamic_cast <const vmime::exceptions::invalid_response*>(&e)) {
{
const vmime::exceptions::invalid_response& ir = const vmime::exceptions::invalid_response& ir =
dynamic_cast <const vmime::exceptions::invalid_response&>(e); dynamic_cast <const vmime::exceptions::invalid_response&>(e);
os << " response = " << ir.response() << std::endl; os << " response = " << ir.response() << std::endl;
} }
if (dynamic_cast <const vmime::exceptions::connection_greeting_error*>(&e)) if (dynamic_cast <const vmime::exceptions::connection_greeting_error*>(&e)) {
{
const vmime::exceptions::connection_greeting_error& cgee = const vmime::exceptions::connection_greeting_error& cgee =
dynamic_cast <const vmime::exceptions::connection_greeting_error&>(e); dynamic_cast <const vmime::exceptions::connection_greeting_error&>(e);
os << " response = " << cgee.response() << std::endl; os << " response = " << cgee.response() << std::endl;
} }
if (dynamic_cast <const vmime::exceptions::authentication_error*>(&e)) if (dynamic_cast <const vmime::exceptions::authentication_error*>(&e)) {
{
const vmime::exceptions::authentication_error& aee = const vmime::exceptions::authentication_error& aee =
dynamic_cast <const vmime::exceptions::authentication_error&>(e); dynamic_cast <const vmime::exceptions::authentication_error&>(e);
os << " response = " << aee.response() << std::endl; os << " response = " << aee.response() << std::endl;
} }
if (dynamic_cast <const vmime::exceptions::filesystem_exception*>(&e)) if (dynamic_cast <const vmime::exceptions::filesystem_exception*>(&e)) {
{
const vmime::exceptions::filesystem_exception& fse = const vmime::exceptions::filesystem_exception& fse =
dynamic_cast <const vmime::exceptions::filesystem_exception&>(e); dynamic_cast <const vmime::exceptions::filesystem_exception&>(e);
@ -121,8 +122,9 @@ static std::ostream& operator<<(std::ostream& os, const vmime::exception& e)
getFileSystemFactory()->pathToString(fse.path()) << std::endl; getFileSystemFactory()->pathToString(fse.path()) << std::endl;
} }
if (e.other() != NULL) if (e.other()) {
os << *e.other(); os << *e.other();
}
return os; return os;
} }
@ -133,35 +135,40 @@ static std::ostream& operator<<(std::ostream& os, const vmime::exception& e)
* @param s structure object * @param s structure object
* @param level current depth * @param level current depth
*/ */
static void printStructure(vmime::shared_ptr <const vmime::net::messageStructure> s, const int level = 0) static void printStructure(
{ vmime::shared_ptr <const vmime::net::messageStructure> s,
for (size_t i = 0 ; i < s->getPartCount() ; ++i) const int level = 0
{ ) {
for (size_t i = 0 ; i < s->getPartCount() ; ++i) {
vmime::shared_ptr <const vmime::net::messagePart> part = s->getPartAt(i); vmime::shared_ptr <const vmime::net::messagePart> part = s->getPartAt(i);
for (int j = 0 ; j < level * 2 ; ++j) for (int j = 0 ; j < level * 2 ; ++j) {
std::cout << " "; std::cout << " ";
}
std::cout << (part->getNumber() + 1) << ". " std::cout
<< part->getType().generate() << (part->getNumber() + 1) << ". "
<< " [" << part->getSize() << " byte(s)]" << part->getType().generate()
<< std::endl; << " [" << part->getSize() << " byte(s)]"
<< std::endl;
printStructure(part->getStructure(), level + 1); printStructure(part->getStructure(), level + 1);
} }
} }
static const vmime::string getFolderPathString(vmime::shared_ptr <vmime::net::folder> f) static const vmime::string getFolderPathString(vmime::shared_ptr <vmime::net::folder> f) {
{
const vmime::string n = f->getName().getBuffer(); const vmime::string n = f->getName().getBuffer();
if (n.empty()) // root folder if (n.empty()) { // root folder
{
return "/"; return "/";
}
else } else {
{
vmime::shared_ptr <vmime::net::folder> p = f->getParent(); vmime::shared_ptr <vmime::net::folder> p = f->getParent();
return getFolderPathString(p) + n + "/"; return getFolderPathString(p) + n + "/";
} }
@ -172,38 +179,43 @@ static const vmime::string getFolderPathString(vmime::shared_ptr <vmime::net::fo
* *
* @param folder current folder * @param folder current folder
*/ */
static void printFolders(vmime::shared_ptr <vmime::net::folder> folder, const int level = 0) static void printFolders(vmime::shared_ptr <vmime::net::folder> folder, const int level = 0) {
{
for (int j = 0 ; j < level * 2 ; ++j) for (int j = 0 ; j < level * 2 ; ++j) {
std::cout << " "; std::cout << " ";
}
const vmime::net::folderAttributes attr = folder->getAttributes(); const vmime::net::folderAttributes attr = folder->getAttributes();
std::ostringstream attrStr; std::ostringstream attrStr;
if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_ALL) if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_ALL) {
attrStr << " \\use:All"; attrStr << " \\use:All";
else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_ARCHIVE) } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_ARCHIVE) {
attrStr << " \\use:Archive"; attrStr << " \\use:Archive";
else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_DRAFTS) } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_DRAFTS) {
attrStr << " \\use:Drafts"; attrStr << " \\use:Drafts";
else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_FLAGGED) } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_FLAGGED) {
attrStr << " \\use:Flagged"; attrStr << " \\use:Flagged";
else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_JUNK) } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_JUNK) {
attrStr << " \\use:Junk"; attrStr << " \\use:Junk";
else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_SENT) } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_SENT) {
attrStr << " \\use:Sent"; attrStr << " \\use:Sent";
else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_TRASH) } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_TRASH) {
attrStr << " \\use:Trash"; attrStr << " \\use:Trash";
else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_IMPORTANT) } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_IMPORTANT) {
attrStr << " \\use:Important"; attrStr << " \\use:Important";
}
if (attr.getFlags() & vmime::net::folderAttributes::FLAG_HAS_CHILDREN) if (attr.getFlags() & vmime::net::folderAttributes::FLAG_HAS_CHILDREN) {
attrStr << " \\flag:HasChildren"; attrStr << " \\flag:HasChildren";
if (attr.getFlags() & vmime::net::folderAttributes::FLAG_NO_OPEN) }
if (attr.getFlags() & vmime::net::folderAttributes::FLAG_NO_OPEN) {
attrStr << " \\flag:NoOpen"; attrStr << " \\flag:NoOpen";
}
for (size_t i = 0, n = attr.getUserFlags().size() ; i < n ; ++i) for (size_t i = 0, n = attr.getUserFlags().size() ; i < n ; ++i) {
attrStr << " \\" << attr.getUserFlags()[i]; attrStr << " \\" << attr.getUserFlags()[i];
}
std::cout << getFolderPathString(folder); std::cout << getFolderPathString(folder);
std::cout << " " << attrStr.str(); std::cout << " " << attrStr.str();
@ -211,8 +223,9 @@ static void printFolders(vmime::shared_ptr <vmime::net::folder> folder, const in
std::vector <vmime::shared_ptr <vmime::net::folder> > subFolders = folder->getFolders(false); std::vector <vmime::shared_ptr <vmime::net::folder> > subFolders = folder->getFolders(false);
for (unsigned int i = 0 ; i < subFolders.size() ; ++i) for (unsigned int i = 0 ; i < subFolders.size() ; ++i) {
printFolders(subFolders[i], level + 1); printFolders(subFolders[i], level + 1);
}
} }
@ -220,12 +233,13 @@ static void printFolders(vmime::shared_ptr <vmime::net::folder> folder, const in
* *
* @param choices menu choices * @param choices menu choices
*/ */
static unsigned int printMenu(const std::vector <std::string>& choices) static unsigned int printMenu(const std::vector <std::string>& choices) {
{
std::cout << std::endl; std::cout << std::endl;
for (unsigned int i = 0 ; i < choices.size() ; ++i) for (unsigned int i = 0 ; i < choices.size() ; ++i) {
std::cout << " " << (i + 1) << ". " << choices[i] << std::endl; std::cout << " " << (i + 1) << ". " << choices[i] << std::endl;
}
std::cout << std::endl; std::cout << std::endl;
std::cout << " Your choice? [1-" << choices.size() << "] "; std::cout << " Your choice? [1-" << choices.size() << "] ";
@ -241,19 +255,20 @@ static unsigned int printMenu(const std::vector <std::string>& choices)
std::cout << std::endl; std::cout << std::endl;
if (choice < 1 || choice > choices.size()) if (choice < 1 || choice > choices.size()) {
return 0; return 0;
else } else {
return choice; return choice;
}
} }
/** Send a message interactively. /** Send a message interactively.
*/ */
static void sendMessage() static void sendMessage() {
{
try try {
{
// Request user to enter an URL // Request user to enter an URL
std::cout << "Enter an URL to connect to transport service." << std::endl; std::cout << "Enter an URL to connect to transport service." << std::endl;
std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_TRANSPORT) << std::endl; std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_TRANSPORT) << std::endl;
@ -268,10 +283,11 @@ static void sendMessage()
vmime::shared_ptr <vmime::net::transport> tr; vmime::shared_ptr <vmime::net::transport> tr;
if (url.getUsername().empty() || url.getPassword().empty()) if (url.getUsername().empty() || url.getPassword().empty()) {
tr = g_session->getTransport(url, vmime::make_shared <interactiveAuthenticator>()); tr = g_session->getTransport(url, vmime::make_shared <interactiveAuthenticator>());
else } else {
tr = g_session->getTransport(url); tr = g_session->getTransport(url);
}
#if VMIME_HAVE_TLS_SUPPORT #if VMIME_HAVE_TLS_SUPPORT
@ -283,15 +299,17 @@ static void sendMessage()
// Set the object responsible for verifying certificates, in the // Set the object responsible for verifying certificates, in the
// case a secured connection is used (TLS/SSL) // case a secured connection is used (TLS/SSL)
tr->setCertificateVerifier tr->setCertificateVerifier(
(vmime::make_shared <interactiveCertificateVerifier>()); vmime::make_shared <interactiveCertificateVerifier>()
);
#endif // VMIME_HAVE_TLS_SUPPORT #endif // VMIME_HAVE_TLS_SUPPORT
// You can also set some properties (see example7 to know the properties // You can also set some properties (see example7 to know the properties
// available for each service). For example, for SMTP: // available for each service). For example, for SMTP:
if (!url.getUsername().empty() || !url.getPassword().empty()) if (!url.getUsername().empty() || !url.getPassword().empty()) {
tr->setProperty("options.need-authentication", true); tr->setProperty("options.need-authentication", true);
}
// Trace communication between client and server // Trace communication between client and server
vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>(); vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>();
@ -307,8 +325,8 @@ static void sendMessage()
vmime::mailbox from(fromString); vmime::mailbox from(fromString);
vmime::mailboxList to; vmime::mailboxList to;
for (bool cont = true ; cont ; ) for (bool cont = true ; cont ; ) {
{
std::cout << "Enter email of the recipient (empty to stop): "; std::cout << "Enter email of the recipient (empty to stop): ";
std::cout.flush(); std::cout.flush();
@ -317,23 +335,25 @@ static void sendMessage()
cont = (toString.size() != 0); cont = (toString.size() != 0);
if (cont) if (cont) {
to.appendMailbox(vmime::make_shared <vmime::mailbox>(toString)); to.appendMailbox(vmime::make_shared <vmime::mailbox>(toString));
}
} }
std::cout << "Enter message data, including headers (end with '.' on a single line):" << std::endl; std::cout << "Enter message data, including headers (end with '.' on a single line):" << std::endl;
std::ostringstream data; std::ostringstream data;
for (bool cont = true ; cont ; ) for (bool cont = true ; cont ; ) {
{
std::string line; std::string line;
std::getline(std::cin, line); std::getline(std::cin, line);
if (line == ".") if (line == ".") {
cont = false; cont = false;
else } else {
data << line << "\r\n"; data << line << "\r\n";
}
} }
// Connect to server // Connect to server
@ -357,15 +377,15 @@ static void sendMessage()
std::cout << traceStream->str(); std::cout << traceStream->str();
tr->disconnect(); tr->disconnect();
}
catch (vmime::exception& e) } catch (vmime::exception& e) {
{
std::cerr << std::endl; std::cerr << std::endl;
std::cerr << e << std::endl; std::cerr << e << std::endl;
throw; throw;
}
catch (std::exception& e) } catch (std::exception& e) {
{
std::cerr << std::endl; std::cerr << std::endl;
std::cerr << "std::exception: " << e.what() << std::endl; std::cerr << "std::exception: " << e.what() << std::endl;
throw; throw;
@ -375,10 +395,10 @@ static void sendMessage()
/** Connect to a message store interactively. /** Connect to a message store interactively.
*/ */
static void connectStore() static void connectStore() {
{
try try {
{
// Request user to enter an URL // Request user to enter an URL
std::cout << "Enter an URL to connect to store service." << std::endl; std::cout << "Enter an URL to connect to store service." << std::endl;
std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_STORE) << std::endl; std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_STORE) << std::endl;
@ -396,10 +416,11 @@ static void connectStore()
// session properties "auth.username" and "auth.password". // session properties "auth.username" and "auth.password".
vmime::shared_ptr <vmime::net::store> st; vmime::shared_ptr <vmime::net::store> st;
if (url.getUsername().empty() || url.getPassword().empty()) if (url.getUsername().empty() || url.getPassword().empty()) {
st = g_session->getStore(url, vmime::make_shared <interactiveAuthenticator>()); st = g_session->getStore(url, vmime::make_shared <interactiveAuthenticator>());
else } else {
st = g_session->getStore(url); st = g_session->getStore(url);
}
#if VMIME_HAVE_TLS_SUPPORT #if VMIME_HAVE_TLS_SUPPORT
@ -411,8 +432,9 @@ static void connectStore()
// Set the object responsible for verifying certificates, in the // Set the object responsible for verifying certificates, in the
// case a secured connection is used (TLS/SSL) // case a secured connection is used (TLS/SSL)
st->setCertificateVerifier st->setCertificateVerifier(
(vmime::make_shared <interactiveCertificateVerifier>()); vmime::make_shared <interactiveCertificateVerifier>()
);
#endif // VMIME_HAVE_TLS_SUPPORT #endif // VMIME_HAVE_TLS_SUPPORT
@ -441,13 +463,13 @@ static void connectStore()
std::cout << std::endl; std::cout << std::endl;
std::cout << count << " message(s) in your inbox" << std::endl; std::cout << count << " message(s) in your inbox" << std::endl;
for (bool cont = true ; cont ; ) for (bool cont = true ; cont ; ) {
{
typedef std::map <vmime::size_t, vmime::shared_ptr <vmime::net::message> > MessageList; typedef std::map <vmime::size_t, vmime::shared_ptr <vmime::net::message> > MessageList;
MessageList msgList; MessageList msgList;
try try {
{
std::vector <std::string> choices; std::vector <std::string> choices;
choices.push_back("Show message flags"); choices.push_back("Show message flags");
@ -470,8 +492,8 @@ static void connectStore()
vmime::shared_ptr <vmime::net::message> msg; vmime::shared_ptr <vmime::net::message> msg;
if (choice == 1 || choice == 2 || choice == 3 || choice == 4 || if (choice == 1 || choice == 2 || choice == 3 || choice == 4 ||
choice == 5 || choice == 6 || choice == 11) choice == 5 || choice == 6 || choice == 11) {
{
std::cout << "Enter message number: "; std::cout << "Enter message number: ";
std::cout.flush(); std::cout.flush();
@ -483,20 +505,20 @@ static void connectStore()
vmime::size_t num = 0; vmime::size_t num = 0;
iss >> num; iss >> num;
if (num < 1 || num > f->getMessageCount()) if (num < 1 || num > f->getMessageCount()) {
{
std::cerr << "Invalid message number." << std::endl; std::cerr << "Invalid message number." << std::endl;
continue; continue;
} }
MessageList::iterator it = msgList.find(num); MessageList::iterator it = msgList.find(num);
if (it != msgList.end()) if (it != msgList.end()) {
{
msg = (*it).second; msg = (*it).second;
}
else } else {
{
msg = f->getMessage(num); msg = f->getMessage(num);
msgList.insert(MessageList::value_type(num, msg)); msgList.insert(MessageList::value_type(num, msg));
} }
@ -504,25 +526,31 @@ static void connectStore()
std::cout << std::endl; std::cout << std::endl;
} }
switch (choice) switch (choice) {
{
// Show message flags // Show message flags
case 1: case 1:
f->fetchMessage(msg, vmime::net::fetchAttributes::FLAGS); f->fetchMessage(msg, vmime::net::fetchAttributes::FLAGS);
if (msg->getFlags() & vmime::net::message::FLAG_SEEN) if (msg->getFlags() & vmime::net::message::FLAG_SEEN) {
std::cout << "FLAG_SEEN" << std::endl; std::cout << "FLAG_SEEN" << std::endl;
if (msg->getFlags() & vmime::net::message::FLAG_RECENT) }
if (msg->getFlags() & vmime::net::message::FLAG_RECENT) {
std::cout << "FLAG_RECENT" << std::endl; std::cout << "FLAG_RECENT" << std::endl;
if (msg->getFlags() & vmime::net::message::FLAG_REPLIED) }
if (msg->getFlags() & vmime::net::message::FLAG_REPLIED) {
std::cout << "FLAG_REPLIED" << std::endl; std::cout << "FLAG_REPLIED" << std::endl;
if (msg->getFlags() & vmime::net::message::FLAG_DELETED) }
if (msg->getFlags() & vmime::net::message::FLAG_DELETED) {
std::cout << "FLAG_DELETED" << std::endl; std::cout << "FLAG_DELETED" << std::endl;
if (msg->getFlags() & vmime::net::message::FLAG_MARKED) }
if (msg->getFlags() & vmime::net::message::FLAG_MARKED) {
std::cout << "FLAG_MARKED" << std::endl; std::cout << "FLAG_MARKED" << std::endl;
if (msg->getFlags() & vmime::net::message::FLAG_PASSED) }
if (msg->getFlags() & vmime::net::message::FLAG_PASSED) {
std::cout << "FLAG_PASSED" << std::endl; std::cout << "FLAG_PASSED" << std::endl;
}
break; break;
@ -541,8 +569,8 @@ static void connectStore()
break; break;
// Show message envelope // Show message envelope
case 4: case 4: {
{
vmime::net::fetchAttributes attr(vmime::net::fetchAttributes::ENVELOPE); vmime::net::fetchAttributes attr(vmime::net::fetchAttributes::ENVELOPE);
// If you also want to fetch "Received: " fields: // If you also want to fetch "Received: " fields:
@ -555,37 +583,38 @@ static void connectStore()
break; break;
} }
// Extract whole message // Extract whole message
case 5: case 5: {
{
vmime::utility::outputStreamAdapter out(std::cout); vmime::utility::outputStreamAdapter out(std::cout);
msg->extract(out); msg->extract(out);
break; break;
} }
// Extract attachments // Extract attachments
case 6: case 6: {
{
vmime::shared_ptr <vmime::message> parsedMsg = msg->getParsedMessage(); vmime::shared_ptr <vmime::message> parsedMsg = msg->getParsedMessage();
std::vector <vmime::shared_ptr <const vmime::attachment> > attchs = std::vector <vmime::shared_ptr <const vmime::attachment> > attchs =
vmime::attachmentHelper::findAttachmentsInMessage(parsedMsg); vmime::attachmentHelper::findAttachmentsInMessage(parsedMsg);
if (attchs.size() > 0) if (attchs.size() > 0) {
{
std::cout << attchs.size() << " attachments found." << std::endl; std::cout << attchs.size() << " attachments found." << std::endl;
for (std::vector <vmime::shared_ptr <const vmime::attachment> >::iterator for (std::vector <vmime::shared_ptr <const vmime::attachment> >::iterator
it = attchs.begin() ; it != attchs.end() ; ++it) it = attchs.begin() ; it != attchs.end() ; ++it) {
{
vmime::shared_ptr <const vmime::attachment> att = *it; vmime::shared_ptr <const vmime::attachment> att = *it;
// Get attachment size // Get attachment size
vmime::size_t size = 0; vmime::size_t size = 0;
if (att->getData()->isEncoded()) if (att->getData()->isEncoded()) {
size = att->getData()->getEncoding().getEncoder()->getDecodedSize(att->getData()->getLength()); size = att->getData()->getEncoding().getEncoder()->getDecodedSize(att->getData()->getLength());
else } else {
size = att->getData()->getLength(); size = att->getData()->getLength();
}
std::cout << "Found attachment '" << att->getName().getBuffer() << "'" std::cout << "Found attachment '" << att->getName().getBuffer() << "'"
<< ", size is " << size << " bytes:" << std::endl; << ", size is " << size << " bytes:" << std::endl;
@ -618,17 +647,17 @@ static void connectStore()
att->getData()->extract(*output.get()); att->getData()->extract(*output.get());
*/ */
} }
}
else } else {
{
std::cout << "No attachments found." << std::endl; std::cout << "No attachments found." << std::endl;
} }
break; break;
} }
// Status // Status
case 7: case 7: {
{
vmime::size_t count, unseen; vmime::size_t count, unseen;
f->status(count, unseen); f->status(count, unseen);
@ -636,17 +665,16 @@ static void connectStore()
break; break;
} }
// List folders // List folders
case 8: case 8: {
{
vmime::shared_ptr <vmime::net::folder> vmime::shared_ptr <vmime::net::folder> root = st->getRootFolder();
root = st->getRootFolder();
printFolders(root); printFolders(root);
break; break;
} }
// Change folder // Change folder
case 9: case 9: {
{
std::cout << "Enter folder path (eg. /root/subfolder):" << std::endl; std::cout << "Enter folder path (eg. /root/subfolder):" << std::endl;
std::cout.flush(); std::cout.flush();
@ -655,19 +683,21 @@ static void connectStore()
vmime::shared_ptr <vmime::net::folder> newFolder = st->getRootFolder(); vmime::shared_ptr <vmime::net::folder> newFolder = st->getRootFolder();
for (std::string::size_type s = 0, p = 0 ; ; s = p + 1) for (std::string::size_type s = 0, p = 0 ; ; s = p + 1) {
{
p = path.find_first_of('/', s); p = path.find_first_of('/', s);
const std::string x = (p == std::string::npos) const std::string x = (p == std::string::npos)
? std::string(path.begin() + s, path.end()) ? std::string(path.begin() + s, path.end())
: std::string(path.begin() + s, path.begin() + p); : std::string(path.begin() + s, path.begin() + p);
if (!x.empty()) if (!x.empty()) {
newFolder = newFolder->getFolder(vmime::utility::path::component(x)); newFolder = newFolder->getFolder(vmime::utility::path::component(x));
}
if (p == std::string::npos) if (p == std::string::npos) {
break; break;
}
} }
newFolder->open(vmime::net::folder::MODE_READ_WRITE); newFolder->open(vmime::net::folder::MODE_READ_WRITE);
@ -683,8 +713,8 @@ static void connectStore()
break; break;
} }
// Add message // Add message
case 10: case 10: {
{
vmime::messageBuilder mb; vmime::messageBuilder mb;
mb.setExpeditor(vmime::mailbox("me@somewhere.com")); mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
@ -694,32 +724,35 @@ static void connectStore()
mb.setRecipients(to); mb.setRecipients(to);
mb.setSubject(vmime::text("Test message from VMime example6")); mb.setSubject(vmime::text("Test message from VMime example6"));
mb.getTextPart()->setText(vmime::make_shared <vmime::stringContentHandler>( mb.getTextPart()->setText(
"Body of test message from VMime example6.")); vmime::make_shared <vmime::stringContentHandler>(
"Body of test message from VMime example6."
)
);
vmime::shared_ptr <vmime::message> msg = mb.construct(); vmime::shared_ptr <vmime::message> msg = mb.construct();
vmime::net::messageSet set = f->addMessage(msg); vmime::net::messageSet set = f->addMessage(msg);
if (set.isEmpty()) if (set.isEmpty()) {
{
std::cout << "Message has successfully been added, " std::cout << "Message has successfully been added, "
<< "but its UID/number is not known." << std::endl; << "but its UID/number is not known." << std::endl;
}
else } else {
{
const vmime::net::messageRange& range = set.getRangeAt(0); const vmime::net::messageRange& range = set.getRangeAt(0);
if (set.isUIDSet()) if (set.isUIDSet()) {
{
const vmime::net::message::uid uid = const vmime::net::message::uid uid =
dynamic_cast <const vmime::net::UIDMessageRange&>(range).getFirst(); dynamic_cast <const vmime::net::UIDMessageRange&>(range).getFirst();
std::cout << "Message has successfully been added, " std::cout << "Message has successfully been added, "
<< "its UID is '" << uid << "'." << std::endl; << "its UID is '" << uid << "'." << std::endl;
}
else } else {
{
const vmime::size_t number = const vmime::size_t number =
dynamic_cast <const vmime::net::numberMessageRange&>(range).getFirst(); dynamic_cast <const vmime::net::numberMessageRange&>(range).getFirst();
@ -731,30 +764,30 @@ static void connectStore()
break; break;
} }
// Copy message // Copy message
case 11: case 11: {
{
vmime::net::messageSet set = f->copyMessages(f->getFullPath(), vmime::net::messageSet set = f->copyMessages(f->getFullPath(),
vmime::net::messageSet::byNumber(msg->getNumber())); vmime::net::messageSet::byNumber(msg->getNumber()));
if (set.isEmpty()) if (set.isEmpty()) {
{
std::cout << "Message has successfully been copied, " std::cout << "Message has successfully been copied, "
<< "but its UID/number is not known." << std::endl; << "but its UID/number is not known." << std::endl;
}
else } else {
{
const vmime::net::messageRange& range = set.getRangeAt(0); const vmime::net::messageRange& range = set.getRangeAt(0);
if (set.isUIDSet()) if (set.isUIDSet()) {
{
const vmime::net::message::uid uid = const vmime::net::message::uid uid =
dynamic_cast <const vmime::net::UIDMessageRange&>(range).getFirst(); dynamic_cast <const vmime::net::UIDMessageRange&>(range).getFirst();
std::cout << "Message has successfully been copied, " std::cout << "Message has successfully been copied, "
<< "its UID is '" << uid << "'." << std::endl; << "its UID is '" << uid << "'." << std::endl;
}
else } else {
{
const vmime::size_t number = const vmime::size_t number =
dynamic_cast <const vmime::net::numberMessageRange&>(range).getFirst(); dynamic_cast <const vmime::net::numberMessageRange&>(range).getFirst();
@ -808,35 +841,37 @@ static void connectStore()
{ {
vmime::shared_ptr <vmime::net::folder> g = st->getFolder(vmime::net::folder::path("TEMP")); vmime::shared_ptr <vmime::net::folder> g = st->getFolder(vmime::net::folder::path("TEMP"));
if (!g->exists()) if (!g->exists()) {
g->create(vmime::net::folder::TYPE_CONTAINS_MESSAGES); g->create(vmime::net::folder::TYPE_CONTAINS_MESSAGES);
}
f->copyMessages(g->getFullPath()); f->copyMessages(g->getFullPath());
} }
*/ */
}
catch (vmime::exception& e) } catch (vmime::exception& e) {
{
std::cerr << std::endl; std::cerr << std::endl;
std::cerr << e << std::endl; std::cerr << e << std::endl;
}
catch (std::exception& e) } catch (std::exception& e) {
{
std::cerr << std::endl; std::cerr << std::endl;
std::cerr << "std::exception: " << e.what() << std::endl; std::cerr << "std::exception: " << e.what() << std::endl;
} }
} // for(cont) } // for(cont)
st->disconnect(); st->disconnect();
}
catch (vmime::exception& e) } catch (vmime::exception& e) {
{
std::cerr << std::endl; std::cerr << std::endl;
std::cerr << e << std::endl; std::cerr << e << std::endl;
throw; throw;
}
catch (std::exception& e) } catch (std::exception& e) {
{
std::cerr << std::endl; std::cerr << std::endl;
std::cerr << "std::exception: " << e.what() << std::endl; std::cerr << "std::exception: " << e.what() << std::endl;
throw; throw;
@ -848,16 +883,16 @@ static void connectStore()
* *
* @return true to quit the program, false to continue * @return true to quit the program, false to continue
*/ */
static bool menu() static bool menu() {
{
std::vector <std::string> items; std::vector <std::string> items;
items.push_back("Connect to a message store"); items.push_back("Connect to a message store");
items.push_back("Send a message"); items.push_back("Send a message");
items.push_back("Quit"); items.push_back("Quit");
switch (printMenu(items)) switch (printMenu(items)) {
{
// Connect to store // Connect to store
case 1: case 1:
@ -883,25 +918,21 @@ static bool menu()
} }
int main() int main() {
{
// Set the global C and C++ locale to the user-configured locale. // Set the global C and C++ locale to the user-configured locale.
// The locale should use UTF-8 encoding for these tests to run successfully. // The locale should use UTF-8 encoding for these tests to run successfully.
try try {
{
std::locale::global(std::locale("")); std::locale::global(std::locale(""));
} } catch (std::exception &) {
catch (std::exception &)
{
std::setlocale(LC_ALL, ""); std::setlocale(LC_ALL, "");
} }
for (bool quit = false ; !quit ; ) for (bool quit = false ; !quit ; ) {
{
// Loop on main menu // Loop on main menu
quit = menu(); quit = menu();
} }
return 0; return 0;
} }

View File

@ -3,20 +3,23 @@
#if VMIME_HAVE_SASL_SUPPORT #if VMIME_HAVE_SASL_SUPPORT
// SASL authentication handler // SASL authentication handler
class interactiveAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator class interactiveAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator {
{
const std::vector <vmime::shared_ptr <vmime::security::sasl::SASLMechanism> > getAcceptableMechanisms const std::vector <vmime::shared_ptr <vmime::security::sasl::SASLMechanism> >
(const std::vector <vmime::shared_ptr <vmime::security::sasl::SASLMechanism> >& available, getAcceptableMechanisms(
vmime::shared_ptr <vmime::security::sasl::SASLMechanism> suggested) const const std::vector <vmime::shared_ptr <vmime::security::sasl::SASLMechanism> >& available,
{ const vmime::shared_ptr <vmime::security::sasl::SASLMechanism>& suggested
) const {
std::cout << std::endl << "Available SASL mechanisms:" << std::endl; std::cout << std::endl << "Available SASL mechanisms:" << std::endl;
for (unsigned int i = 0 ; i < available.size() ; ++i) for (unsigned int i = 0 ; i < available.size() ; ++i) {
{
std::cout << " " << available[i]->getName(); std::cout << " " << available[i]->getName();
if (suggested && available[i]->getName() == suggested->getName()) if (suggested && available[i]->getName() == suggested->getName()) {
std::cout << "(suggested)"; std::cout << "(suggested)";
}
} }
std::cout << std::endl << std::endl; std::cout << std::endl << std::endl;
@ -24,31 +27,33 @@ class interactiveAuthenticator : public vmime::security::sasl::defaultSASLAuthen
return defaultSASLAuthenticator::getAcceptableMechanisms(available, suggested); return defaultSASLAuthenticator::getAcceptableMechanisms(available, suggested);
} }
void setSASLMechanism(vmime::shared_ptr <vmime::security::sasl::SASLMechanism> mech) void setSASLMechanism(const vmime::shared_ptr <vmime::security::sasl::SASLMechanism>& mech) {
{
std::cout << "Trying '" << mech->getName() << "' authentication mechanism" << std::endl; std::cout << "Trying '" << mech->getName() << "' authentication mechanism" << std::endl;
defaultSASLAuthenticator::setSASLMechanism(mech); defaultSASLAuthenticator::setSASLMechanism(mech);
} }
const vmime::string getUsername() const const vmime::string getUsername() const {
{
if (m_username.empty()) if (m_username.empty()) {
m_username = getUserInput("Username"); m_username = getUserInput("Username");
}
return m_username; return m_username;
} }
const vmime::string getPassword() const const vmime::string getPassword() const {
{
if (m_password.empty()) if (m_password.empty()) {
m_password = getUserInput("Password"); m_password = getUserInput("Password");
}
return m_password; return m_password;
} }
static const vmime::string getUserInput(const std::string& prompt) static const vmime::string getUserInput(const std::string& prompt) {
{
std::cout << prompt << ": "; std::cout << prompt << ": ";
std::cout.flush(); std::cout.flush();
@ -67,26 +72,28 @@ private:
#else // !VMIME_HAVE_SASL_SUPPORT #else // !VMIME_HAVE_SASL_SUPPORT
// Simple authentication handler // Simple authentication handler
class interactiveAuthenticator : public vmime::security::defaultAuthenticator class interactiveAuthenticator : public vmime::security::defaultAuthenticator {
{
const vmime::string getUsername() const const vmime::string getUsername() const {
{
if (m_username.empty()) if (m_username.empty()) {
m_username = getUserInput("Username"); m_username = getUserInput("Username");
}
return m_username; return m_username;
} }
const vmime::string getPassword() const const vmime::string getPassword() const {
{
if (m_password.empty()) if (m_password.empty()) {
m_password = getUserInput("Password"); m_password = getUserInput("Password");
}
return m_password; return m_password;
} }
static const vmime::string getUserInput(const std::string& prompt) static const vmime::string getUserInput(const std::string& prompt) {
{
std::cout << prompt << ": "; std::cout << prompt << ": ";
std::cout.flush(); std::cout.flush();
@ -103,4 +110,3 @@ private:
}; };
#endif // VMIME_HAVE_SASL_SUPPORT #endif // VMIME_HAVE_SASL_SUPPORT

View File

@ -3,20 +3,23 @@
#if VMIME_HAVE_TLS_SUPPORT #if VMIME_HAVE_TLS_SUPPORT
// Certificate verifier (TLS/SSL) // Certificate verifier (TLS/SSL)
class interactiveCertificateVerifier : public vmime::security::cert::defaultCertificateVerifier class interactiveCertificateVerifier : public vmime::security::cert::defaultCertificateVerifier {
{
public: public:
void verify(vmime::shared_ptr <vmime::security::cert::certificateChain> chain, const vmime::string& hostname) void verify(
{ const vmime::shared_ptr <vmime::security::cert::certificateChain>& chain,
try const vmime::string& hostname
{ ) {
try {
setX509TrustedCerts(m_trustedCerts); setX509TrustedCerts(m_trustedCerts);
defaultCertificateVerifier::verify(chain, hostname); defaultCertificateVerifier::verify(chain, hostname);
}
catch (vmime::security::cert::certificateException&) } catch (vmime::security::cert::certificateException&) {
{
// Obtain subject's certificate // Obtain subject's certificate
vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0); vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0);
@ -29,13 +32,14 @@ public:
std::getline(std::cin, answer); std::getline(std::cin, answer);
if (answer.length() != 0 && if (answer.length() != 0 &&
(answer[0] == 'Y' || answer[0] == 'y')) (answer[0] == 'Y' || answer[0] == 'y')) {
{
// Accept it, and remember user's choice for later // Accept it, and remember user's choice for later
if (cert->getType() == "X.509") if (cert->getType() == "X.509") {
{
m_trustedCerts.push_back(vmime::dynamicCast m_trustedCerts.push_back(
<vmime::security::cert::X509Certificate>(cert)); vmime::dynamicCast <vmime::security::cert::X509Certificate>(cert)
);
setX509TrustedCerts(m_trustedCerts); setX509TrustedCerts(m_trustedCerts);
defaultCertificateVerifier::verify(chain, hostname); defaultCertificateVerifier::verify(chain, hostname);
@ -44,8 +48,7 @@ public:
return; return;
} }
throw vmime::security::cert::certificateException throw vmime::security::cert::certificateException("User did not accept the certificate.");
("User did not accept the certificate.");
} }
} }
@ -59,4 +62,3 @@ std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> >
interactiveCertificateVerifier::m_trustedCerts; interactiveCertificateVerifier::m_trustedCerts;
#endif // VMIME_HAVE_TLS_SUPPORT #endif // VMIME_HAVE_TLS_SUPPORT

View File

@ -5,17 +5,17 @@
* Used to stop the current operation after too much time, or if the user * Used to stop the current operation after too much time, or if the user
* requested cancellation. * requested cancellation.
*/ */
class timeoutHandler : public vmime::net::timeoutHandler class timeoutHandler : public vmime::net::timeoutHandler {
{
public: public:
timeoutHandler() timeoutHandler()
: m_start(time(NULL)) : m_start(time(NULL)) {
{
} }
bool isTimeOut() bool isTimeOut() {
{
// This is a cancellation point: return true if you want to cancel // This is a cancellation point: return true if you want to cancel
// the current operation. If you return true, handleTimeOut() will // the current operation. If you return true, handleTimeOut() will
// be called just after this, and before actually cancelling the // be called just after this, and before actually cancelling the
@ -25,15 +25,15 @@ public:
return (time(NULL) - m_start) >= 10; // seconds return (time(NULL) - m_start) >= 10; // seconds
} }
void resetTimeOut() void resetTimeOut() {
{
// Called at the beginning of an operation (eg. connecting, // Called at the beginning of an operation (eg. connecting,
// a read() or a write() on a socket...) // a read() or a write() on a socket...)
m_start = time(NULL); m_start = time(NULL);
} }
bool handleTimeOut() bool handleTimeOut() {
{
// If isTimeOut() returned true, this function will be called. This // If isTimeOut() returned true, this function will be called. This
// allows you to interact with the user, ie. display a prompt to // allows you to interact with the user, ie. display a prompt to
// know whether he wants to cancel the operation. // know whether he wants to cancel the operation.
@ -49,13 +49,12 @@ private:
}; };
class timeoutHandlerFactory : public vmime::net::timeoutHandlerFactory class timeoutHandlerFactory : public vmime::net::timeoutHandlerFactory {
{
public: public:
vmime::shared_ptr <vmime::net::timeoutHandler> create() vmime::shared_ptr <vmime::net::timeoutHandler> create() {
{
return vmime::make_shared <timeoutHandler>(); return vmime::make_shared <timeoutHandler>();
} }
}; };

View File

@ -1,25 +1,29 @@
/** Tracer used to demonstrate logging communication between client and server. /** Tracer used to demonstrate logging communication between client and server.
*/ */
class myTracer : public vmime::net::tracer {
class myTracer : public vmime::net::tracer
{
public: public:
myTracer(vmime::shared_ptr <std::ostringstream> stream, myTracer(
vmime::shared_ptr <vmime::net::service> serv, const int connectionId) const vmime::shared_ptr <std::ostringstream>& stream,
: m_stream(stream), m_service(serv), m_connectionId(connectionId) const vmime::shared_ptr <vmime::net::service>& serv,
{ const int connectionId
)
: m_stream(stream),
m_service(serv),
m_connectionId(connectionId) {
} }
void traceSend(const vmime::string& line) void traceSend(const vmime::string& line) {
{
*m_stream << "[" << m_service->getProtocolName() << ":" << m_connectionId *m_stream << "[" << m_service->getProtocolName() << ":" << m_connectionId
<< "] C: " << line << std::endl; << "] C: " << line << std::endl;
} }
void traceReceive(const vmime::string& line) void traceReceive(const vmime::string& line) {
{
*m_stream << "[" << m_service->getProtocolName() << ":" << m_connectionId *m_stream << "[" << m_service->getProtocolName() << ":" << m_connectionId
<< "] S: " << line << std::endl; << "] S: " << line << std::endl;
} }
@ -31,18 +35,21 @@ private:
const int m_connectionId; const int m_connectionId;
}; };
class myTracerFactory : public vmime::net::tracerFactory
{ class myTracerFactory : public vmime::net::tracerFactory {
public: public:
myTracerFactory(vmime::shared_ptr <std::ostringstream> stream) myTracerFactory(const vmime::shared_ptr <std::ostringstream>& stream)
: m_stream(stream) : m_stream(stream) {
{
} }
vmime::shared_ptr <vmime::net::tracer> create vmime::shared_ptr <vmime::net::tracer> create(
(vmime::shared_ptr <vmime::net::service> serv, const int connectionId) const vmime::shared_ptr <vmime::net::service>& serv,
{ const int connectionId
) {
return vmime::make_shared <myTracer>(m_stream, serv, connectionId); return vmime::make_shared <myTracer>(m_stream, serv, connectionId);
} }
@ -50,4 +57,3 @@ private:
vmime::shared_ptr <std::ostringstream> m_stream; vmime::shared_ptr <std::ostringstream> m_stream;
}; };

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -39,16 +39,16 @@
#include "vmime/platforms/posix/posixHandler.hpp" #include "vmime/platforms/posix/posixHandler.hpp"
int main() int main() {
{
// Enumerate encoders // Enumerate encoders
vmime::shared_ptr <vmime::utility::encoder::encoderFactory> ef = vmime::shared_ptr <vmime::utility::encoder::encoderFactory> ef =
vmime::utility::encoder::encoderFactory::getInstance(); vmime::utility::encoder::encoderFactory::getInstance();
std::cout << "Available encoders:" << std::endl; std::cout << "Available encoders:" << std::endl;
for (size_t i = 0 ; i < ef->getEncoderCount() ; ++i) for (size_t i = 0 ; i < ef->getEncoderCount() ; ++i) {
{
vmime::shared_ptr <const vmime::utility::encoder::encoderFactory::registeredEncoder> vmime::shared_ptr <const vmime::utility::encoder::encoderFactory::registeredEncoder>
enc = ef->getEncoderAt(i); enc = ef->getEncoderAt(i);
@ -59,8 +59,9 @@ int main()
std::vector <vmime::string> props = e->getAvailableProperties(); std::vector <vmime::string> props = e->getAvailableProperties();
for (std::vector <vmime::string>::const_iterator it = props.begin() ; it != props.end() ; ++it) for (std::vector <vmime::string>::const_iterator it = props.begin() ; it != props.end() ; ++it) {
std::cout << " - " << *it << std::endl; std::cout << " - " << *it << std::endl;
}
} }
std::cout << std::endl; std::cout << std::endl;
@ -71,8 +72,8 @@ int main()
std::cout << "Available messaging services:" << std::endl; std::cout << "Available messaging services:" << std::endl;
for (size_t i = 0 ; i < sf->getServiceCount() ; ++i) for (size_t i = 0 ; i < sf->getServiceCount() ; ++i) {
{
const vmime::net::serviceFactory::registeredService& serv = *sf->getServiceAt(i); const vmime::net::serviceFactory::registeredService& serv = *sf->getServiceAt(i);
std::cout << " * " << serv.getName() << std::endl; std::cout << " * " << serv.getName() << std::endl;
@ -81,28 +82,29 @@ int main()
serv.getInfos().getAvailableProperties(); serv.getInfos().getAvailableProperties();
for (std::vector <vmime::net::serviceInfos::property>::const_iterator it = props.begin() ; for (std::vector <vmime::net::serviceInfos::property>::const_iterator it = props.begin() ;
it != props.end() ; ++it) it != props.end() ; ++it) {
{
const vmime::net::serviceInfos::property& p = *it; const vmime::net::serviceInfos::property& p = *it;
const vmime::string name = serv.getInfos().getPropertyPrefix() + p.getName(); const vmime::string name = serv.getInfos().getPropertyPrefix() + p.getName();
vmime::string type; vmime::string type;
switch (p.getType()) switch (p.getType()) {
{ case vmime::net::serviceInfos::property::TYPE_INTEGER: type = "TYPE_INTEGER"; break;
case vmime::net::serviceInfos::property::TYPE_INTEGER: type = "TYPE_INTEGER"; break; case vmime::net::serviceInfos::property::TYPE_STRING: type = "TYPE_STRING"; break;
case vmime::net::serviceInfos::property::TYPE_STRING: type = "TYPE_STRING"; break; case vmime::net::serviceInfos::property::TYPE_BOOLEAN: type = "TYPE_BOOLEAN"; break;
case vmime::net::serviceInfos::property::TYPE_BOOLEAN: type = "TYPE_BOOLEAN"; break; default: type = "(unknown)"; break;
default: type = "(unknown)"; break;
} }
vmime::string flags; vmime::string flags;
if (p.getFlags() & vmime::net::serviceInfos::property::FLAG_REQUIRED) if (p.getFlags() & vmime::net::serviceInfos::property::FLAG_REQUIRED) {
flags += " FLAG_REQUIRED"; flags += " FLAG_REQUIRED";
if (p.getFlags() & vmime::net::serviceInfos::property::FLAG_HIDDEN) }
if (p.getFlags() & vmime::net::serviceInfos::property::FLAG_HIDDEN) {
flags += " FLAG_HIDDEN"; flags += " FLAG_HIDDEN";
}
std::cout << " - " << serv.getInfos().getPropertyPrefix() + p.getName(); std::cout << " - " << serv.getInfos().getPropertyPrefix() + p.getName();
std::cout << " (type=" << type << ", flags=" << flags; std::cout << " (type=" << type << ", flags=" << flags;
@ -111,5 +113,6 @@ int main()
} }
std::cout << std::endl; std::cout << std::endl;
}
return 0;
}

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -53,8 +53,12 @@ vmime::shared_ptr <vmime::message> currentMessage;
void insertRowInModel(GtkTreeStore* model, vmime::shared_ptr <vmime::component> comp, GtkTreeIter* parent = NULL) void insertRowInModel(
{ GtkTreeStore* model,
vmime::shared_ptr <vmime::component> comp,
GtkTreeIter* parent = NULL
) {
GtkTreeIter iter; GtkTreeIter iter;
gtk_tree_store_append(model, &iter, parent); gtk_tree_store_append(model, &iter, parent);
@ -62,15 +66,14 @@ void insertRowInModel(GtkTreeStore* model, vmime::shared_ptr <vmime::component>
const std::vector <vmime::shared_ptr <vmime::component> > children = comp->getChildComponents(); const std::vector <vmime::shared_ptr <vmime::component> > children = comp->getChildComponents();
for (int i = 0 ; i < children.size() ; ++i) for (int i = 0 ; i < children.size() ; ++i) {
{
insertRowInModel(model, children[i], &iter); insertRowInModel(model, children[i], &iter);
} }
} }
void updateTreeView() void updateTreeView() {
{
GtkTreeStore* model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeView))); GtkTreeStore* model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeView)));
g_object_ref(model); g_object_ref(model);
@ -85,8 +88,8 @@ void updateTreeView()
} }
static void treeViewSelChanged(GtkTreeView* treeView, gpointer userData) static void treeViewSelChanged(GtkTreeView* treeView, gpointer userData) {
{
GtkTreePath* path = NULL; GtkTreePath* path = NULL;
GtkTreeViewColumn* col = NULL; GtkTreeViewColumn* col = NULL;
@ -112,19 +115,18 @@ static void treeViewSelChanged(GtkTreeView* treeView, gpointer userData)
} }
static void destroy(GtkWidget* widget, gpointer data) static void destroy(GtkWidget* widget, gpointer data) {
{
gtk_main_quit(); gtk_main_quit();
} }
void openFile(const std::string& filename) void openFile(const std::string& filename) {
{
std::ifstream file; std::ifstream file;
file.open(filename.c_str(), std::ios::in | std::ios::binary); file.open(filename.c_str(), std::ios::in | std::ios::binary);
if (!file) if (!file) {
{
std::cerr << "Can't open file '" << filename << "'." << std::endl; std::cerr << "Can't open file '" << filename << "'." << std::endl;
return; return;
} }
@ -132,12 +134,10 @@ void openFile(const std::string& filename)
vmime::string data; vmime::string data;
char buffer[16384]; char buffer[16384];
do do {
{
file.read(buffer, sizeof(buffer)); file.read(buffer, sizeof(buffer));
data += vmime::string(buffer, file.gcount()); data += vmime::string(buffer, file.gcount());
} } while (file.gcount());
while (file.gcount());
vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>(); vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>();
msg->parse(data); msg->parse(data);
@ -147,13 +147,13 @@ void openFile(const std::string& filename)
char* convData = g_convert_with_fallback(data.c_str(), data.length(), char* convData = g_convert_with_fallback(data.c_str(), data.length(),
"UTF-8", "ISO-8859-1", "?", NULL, NULL, NULL); "UTF-8", "ISO-8859-1", "?", NULL, NULL, NULL);
if (convData == NULL) if (!convData) {
{
gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textArea)), gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textArea)),
"GLib UTF-8 conversion error.", -1); "GLib UTF-8 conversion error.", -1);
}
else } else {
{
gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textArea)), gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textArea)),
convData, strlen(convData)); convData, strlen(convData));
@ -164,16 +164,19 @@ void openFile(const std::string& filename)
} }
static void onFileOpen() static void onFileOpen() {
{
GtkWidget* dlg = gtk_file_chooser_dialog_new GtkWidget* dlg = gtk_file_chooser_dialog_new(
("Open Message File", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN, "Open Message File",
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_WINDOW(window),
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, GTK_FILE_CHOOSER_ACTION_OPEN,
NULL); GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL
);
if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_ACCEPT) {
if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_ACCEPT)
{
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg)); char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg));
openFile(filename); openFile(filename);
@ -187,8 +190,7 @@ static void onFileOpen()
// UI definitions // UI definitions
static const GtkActionEntry uiActions[] = static const GtkActionEntry uiActions[] = {
{
{ "FileMenu", NULL, "_File" }, { "FileMenu", NULL, "_File" },
{ "FileOpen", GTK_STOCK_OPEN, "_Open...", "<control>O", NULL, G_CALLBACK(onFileOpen) }, { "FileOpen", GTK_STOCK_OPEN, "_Open...", "<control>O", NULL, G_CALLBACK(onFileOpen) },
{ "FileExit", GTK_STOCK_QUIT, "_Exit", "<control>Q", NULL, G_CALLBACK(gtk_main_quit) } { "FileExit", GTK_STOCK_QUIT, "_Exit", "<control>Q", NULL, G_CALLBACK(gtk_main_quit) }
@ -205,8 +207,8 @@ static const char* uiDefinition =
"</ui>"; "</ui>";
int main(int argc, char* argv[]) int main(int argc, char* argv[]) {
{
// VMime initialization // VMime initialization
vmime::platform::setHandler<vmime::platforms::posix::posixHandler>(); vmime::platform::setHandler<vmime::platforms::posix::posixHandler>();
@ -290,5 +292,3 @@ int main(int argc, char* argv[])
return 0; return 0;
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -29,12 +29,11 @@
#include "vmime/parserHelpers.hpp" #include "vmime/parserHelpers.hpp"
namespace vmime namespace vmime {
{
address::address() address::address() {
{
} }
@ -66,10 +65,15 @@ address-list = (address *("," address)) / obs-addr-list
*/ */
shared_ptr <address> address::parseNext shared_ptr <address> address::parseNext(
(const parsingContext& ctx, const string& buffer, const size_t position, const parsingContext& ctx,
const size_t end, size_t* newPosition, bool *isLastAddressOfGroup) const string& buffer,
{ const size_t position,
const size_t end,
size_t* newPosition,
bool *isLastAddressOfGroup
) {
bool escaped = false; bool escaped = false;
bool quoted = false; bool quoted = false;
bool quotedRFC2047 = false; bool quotedRFC2047 = false;
@ -78,135 +82,151 @@ shared_ptr <address> address::parseNext
bool stop = false; bool stop = false;
int commentLevel = 0; int commentLevel = 0;
if (isLastAddressOfGroup) if (isLastAddressOfGroup) {
*isLastAddressOfGroup = false; *isLastAddressOfGroup = false;
}
size_t pos = position; size_t pos = position;
while (pos < end && parserHelpers::isSpace(buffer[pos])) while (pos < end && parserHelpers::isSpace(buffer[pos])) {
++pos; ++pos;
}
const size_t start = pos; const size_t start = pos;
while (!stop && pos < end) while (!stop && pos < end) {
{
if (escaped) if (escaped) {
{
escaped = false; escaped = false;
}
else
{
switch (buffer[pos])
{
case '\\':
escaped = true;
break;
case '"':
quoted = !quoted;
break;
case '<':
inRouteAddr = true;
break;
case '>':
inRouteAddr = false;
break;
case '(': } else {
++commentLevel; switch (buffer[pos]) {
break;
case ')': case '\\':
if (commentLevel > 0) escaped = true;
--commentLevel; break;
break; case '"':
case '=': quoted = !quoted;
break;
if (commentLevel == 0 && !quoted && !quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '?') case '<':
{
++pos;
quotedRFC2047 = true;
}
break; inRouteAddr = true;
break;
case '?': case '>':
if (commentLevel == 0 && quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '=') inRouteAddr = false;
{ break;
++pos;
quotedRFC2047 = false;
}
break; case '(':
default: ++commentLevel;
{ break;
if (commentLevel == 0 && !quoted && !quotedRFC2047 && !inRouteAddr)
{
switch (buffer[pos])
{
case ';':
if (isGroup) case ')':
{
if (pos + 1 < end && buffer[pos + 1] == ',')
++pos;
}
if (isLastAddressOfGroup) if (commentLevel > 0) {
*isLastAddressOfGroup = true; --commentLevel;
stop = true;
break;
case ':':
isGroup = true;
break;
case ',':
if (!isGroup) stop = true;
break;
} }
}
break; break;
}
case '=':
if (commentLevel == 0 && !quoted && !quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '?') {
++pos;
quotedRFC2047 = true;
}
break;
case '?':
if (commentLevel == 0 && quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '=') {
++pos;
quotedRFC2047 = false;
}
break;
default:
{
if (commentLevel == 0 && !quoted && !quotedRFC2047 && !inRouteAddr) {
switch (buffer[pos]) {
case ';':
if (isGroup) {
if (pos + 1 < end && buffer[pos + 1] == ',') {
++pos;
}
}
if (isLastAddressOfGroup) {
*isLastAddressOfGroup = true;
}
stop = true;
break;
case ':':
isGroup = true;
break;
case ',':
if (!isGroup) {
stop = true;
}
break;
}
}
break;
}
} }
} }
if (!stop) if (!stop) {
++pos; ++pos;
}
} }
if (newPosition) if (newPosition) {
{
if (pos == end) if (pos == end) {
*newPosition = end; *newPosition = end;
else } else {
*newPosition = pos + 1; // ',' or ';' *newPosition = pos + 1; // ',' or ';'
}
} }
// Parse extracted address (mailbox or group) // Parse extracted address (mailbox or group)
if (pos != start) if (pos != start) {
{
shared_ptr <address> parsedAddress; shared_ptr <address> parsedAddress;
if (isGroup) if (isGroup) {
parsedAddress = make_shared <mailboxGroup>(); parsedAddress = make_shared <mailboxGroup>();
else } else {
parsedAddress = make_shared <mailbox>(); parsedAddress = make_shared <mailbox>();
}
parsedAddress->parse(ctx, buffer, start, pos, NULL); parsedAddress->parse(ctx, buffer, start, pos, NULL);
parsedAddress->setParsedBounds(start, pos); parsedAddress->setParsedBounds(start, pos);
return (parsedAddress); return parsedAddress;
} }
return null; return null;

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -29,8 +29,7 @@
#include "vmime/headerFieldValue.hpp" #include "vmime/headerFieldValue.hpp"
namespace vmime namespace vmime {
{
/** Abstract class representing a mailbox or a group of mailboxes. /** Abstract class representing a mailbox or a group of mailboxes.
@ -38,9 +37,8 @@ namespace vmime
* This class define a common behaviour for the mailbox * This class define a common behaviour for the mailbox
* and mailboxGroup classes. * and mailboxGroup classes.
*/ */
class VMIME_EXPORT address : public headerFieldValue {
class VMIME_EXPORT address : public headerFieldValue
{
protected: protected:
address(); address();
@ -74,10 +72,14 @@ public:
* of a group (end delimiter was found), or false otherwise (may be set to NULL) * of a group (end delimiter was found), or false otherwise (may be set to NULL)
* @return a new address object, or null if no more address is available in the input buffer * @return a new address object, or null if no more address is available in the input buffer
*/ */
static shared_ptr <address> parseNext static shared_ptr <address> parseNext(
(const parsingContext& ctx, const string& buffer, const parsingContext& ctx,
const size_t position, const size_t end, const string& buffer,
size_t* newPosition, bool *isLastAddressOfGroup); const size_t position,
const size_t end,
size_t* newPosition,
bool *isLastAddressOfGroup
);
}; };

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -28,181 +28,204 @@
#include "vmime/mailboxGroup.hpp" #include "vmime/mailboxGroup.hpp"
namespace vmime namespace vmime {
{
addressList::addressList() addressList::addressList() {
{
} }
addressList::addressList(const addressList& addrList) addressList::addressList(const addressList& addrList)
: headerFieldValue() : headerFieldValue() {
{
copyFrom(addrList); copyFrom(addrList);
} }
addressList::~addressList() addressList::~addressList() {
{
removeAllAddresses(); removeAllAddresses();
} }
void addressList::parseImpl void addressList::parseImpl(
(const parsingContext& ctx, const string& buffer, const size_t position, const parsingContext& ctx,
const size_t end, size_t* newPosition) const string& buffer,
{ const size_t position,
const size_t end,
size_t* newPosition
) {
removeAllAddresses(); removeAllAddresses();
size_t pos = position; size_t pos = position;
while (pos < end) while (pos < end) {
{
shared_ptr <address> parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, NULL); shared_ptr <address> parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, NULL);
if (parsedAddress != NULL) if (parsedAddress) {
m_list.push_back(parsedAddress); m_list.push_back(parsedAddress);
}
} }
setParsedBounds(position, end); setParsedBounds(position, end);
if (newPosition) if (newPosition) {
*newPosition = end; *newPosition = end;
}
} }
void addressList::generateImpl void addressList::generateImpl(
(const generationContext& ctx, utility::outputStream& os, const generationContext& ctx,
const size_t curLinePos, size_t* newLinePos) const utility::outputStream& os,
{ const size_t curLinePos,
size_t* newLinePos
) const {
size_t pos = curLinePos; size_t pos = curLinePos;
generationContext tmpCtx(ctx); generationContext tmpCtx(ctx);
tmpCtx.setMaxLineLength(tmpCtx.getMaxLineLength() - 2); tmpCtx.setMaxLineLength(tmpCtx.getMaxLineLength() - 2);
if (!m_list.empty()) if (!m_list.empty()) {
{
for (std::vector <shared_ptr <address> >::const_iterator i = m_list.begin() ; ; ) for (std::vector <shared_ptr <address> >::const_iterator i = m_list.begin() ; ; ) {
{
(*i)->generate(ctx, os, pos, &pos); (*i)->generate(ctx, os, pos, &pos);
if (++i == m_list.end()) if (++i == m_list.end()) {
break; break;
}
os << ", "; os << ", ";
pos += 2; pos += 2;
} }
} }
if (newLinePos) if (newLinePos) {
*newLinePos = pos; *newLinePos = pos;
}
} }
void addressList::copyFrom(const component& other) void addressList::copyFrom(const component& other) {
{
const addressList& addrList = dynamic_cast <const addressList&>(other); const addressList& addrList = dynamic_cast <const addressList&>(other);
removeAllAddresses(); removeAllAddresses();
for (std::vector <shared_ptr <address> >::const_iterator it = addrList.m_list.begin() ; for (std::vector <shared_ptr <address> >::const_iterator it = addrList.m_list.begin() ;
it != addrList.m_list.end() ; ++it) it != addrList.m_list.end() ; ++it) {
{
m_list.push_back(vmime::clone(*it)); m_list.push_back(vmime::clone(*it));
} }
} }
addressList& addressList::operator=(const addressList& other) addressList& addressList::operator=(const addressList& other) {
{
copyFrom(other); copyFrom(other);
return (*this); return *this;
} }
addressList& addressList::operator=(const mailboxList& other) addressList& addressList::operator=(const mailboxList& other) {
{
removeAllAddresses(); removeAllAddresses();
for (size_t i = 0 ; i < other.getMailboxCount() ; ++i) for (size_t i = 0 ; i < other.getMailboxCount() ; ++i) {
m_list.push_back(dynamicCast <address>(other.getMailboxAt(i)->clone())); m_list.push_back(dynamicCast <address>(other.getMailboxAt(i)->clone()));
}
return (*this); return *this;
} }
shared_ptr <component> addressList::clone() const shared_ptr <component> addressList::clone() const {
{
return make_shared <addressList>(*this); return make_shared <addressList>(*this);
} }
void addressList::appendAddress(shared_ptr <address> addr) void addressList::appendAddress(const shared_ptr <address> &addr) {
{
m_list.push_back(addr); m_list.push_back(addr);
} }
void addressList::insertAddressBefore(shared_ptr <address> beforeAddress, shared_ptr <address> addr) void addressList::insertAddressBefore(const shared_ptr <address>& beforeAddress, const shared_ptr <address>& addr) {
{
const std::vector <shared_ptr <address> >::iterator it = std::find
(m_list.begin(), m_list.end(), beforeAddress);
if (it == m_list.end()) const std::vector <shared_ptr <address> >::iterator it = std::find(
m_list.begin(), m_list.end(), beforeAddress
);
if (it == m_list.end()) {
throw std::out_of_range("Invalid position"); throw std::out_of_range("Invalid position");
}
m_list.insert(it, addr); m_list.insert(it, addr);
} }
void addressList::insertAddressBefore(const size_t pos, shared_ptr <address> addr) void addressList::insertAddressBefore(const size_t pos, const shared_ptr <address>& addr) {
{
if (pos >= m_list.size()) if (pos >= m_list.size()) {
throw std::out_of_range("Invalid position"); throw std::out_of_range("Invalid position");
}
m_list.insert(m_list.begin() + pos, addr); m_list.insert(m_list.begin() + pos, addr);
} }
void addressList::insertAddressAfter(shared_ptr <address> afterAddress, shared_ptr <address> addr) void addressList::insertAddressAfter(
{ const shared_ptr <address>& afterAddress,
const std::vector <shared_ptr <address> >::iterator it = std::find const shared_ptr <address>& addr
(m_list.begin(), m_list.end(), afterAddress); ) {
if (it == m_list.end()) const std::vector <shared_ptr <address> >::iterator it = std::find(
m_list.begin(), m_list.end(), afterAddress
);
if (it == m_list.end()) {
throw std::out_of_range("Invalid position"); throw std::out_of_range("Invalid position");
}
m_list.insert(it + 1, addr); m_list.insert(it + 1, addr);
} }
void addressList::insertAddressAfter(const size_t pos, shared_ptr <address> addr) void addressList::insertAddressAfter(const size_t pos, const shared_ptr <address>& addr) {
{
if (pos >= m_list.size()) if (pos >= m_list.size()) {
throw std::out_of_range("Invalid position"); throw std::out_of_range("Invalid position");
}
m_list.insert(m_list.begin() + pos + 1, addr); m_list.insert(m_list.begin() + pos + 1, addr);
} }
void addressList::removeAddress(shared_ptr <address> addr) void addressList::removeAddress(const shared_ptr <address>& addr) {
{
const std::vector <shared_ptr <address> >::iterator it = std::find
(m_list.begin(), m_list.end(), addr);
if (it == m_list.end()) const std::vector <shared_ptr <address> >::iterator it = std::find(
m_list.begin(), m_list.end(), addr
);
if (it == m_list.end()) {
throw std::out_of_range("Invalid position"); throw std::out_of_range("Invalid position");
}
m_list.erase(it); m_list.erase(it);
} }
void addressList::removeAddress(const size_t pos) void addressList::removeAddress(const size_t pos) {
{
if (pos >= m_list.size()) if (pos >= m_list.size()) {
throw std::out_of_range("Invalid position"); throw std::out_of_range("Invalid position");
}
const std::vector <shared_ptr <address> >::iterator it = m_list.begin() + pos; const std::vector <shared_ptr <address> >::iterator it = m_list.begin() + pos;
@ -210,90 +233,90 @@ void addressList::removeAddress(const size_t pos)
} }
void addressList::removeAllAddresses() void addressList::removeAllAddresses() {
{
m_list.clear(); m_list.clear();
} }
size_t addressList::getAddressCount() const size_t addressList::getAddressCount() const {
{
return (m_list.size()); return m_list.size();
} }
bool addressList::isEmpty() const bool addressList::isEmpty() const {
{
return (m_list.empty()); return m_list.empty();
} }
shared_ptr <address> addressList::getAddressAt(const size_t pos) shared_ptr <address> addressList::getAddressAt(const size_t pos) {
{
return (m_list[pos]); return m_list[pos];
} }
const shared_ptr <const address> addressList::getAddressAt(const size_t pos) const const shared_ptr <const address> addressList::getAddressAt(const size_t pos) const {
{
return (m_list[pos]); return m_list[pos];
} }
const std::vector <shared_ptr <const address> > addressList::getAddressList() const const std::vector <shared_ptr <const address> > addressList::getAddressList() const {
{
std::vector <shared_ptr <const address> > list; std::vector <shared_ptr <const address> > list;
list.reserve(m_list.size()); list.reserve(m_list.size());
for (std::vector <shared_ptr <address> >::const_iterator it = m_list.begin() ; for (std::vector <shared_ptr <address> >::const_iterator it = m_list.begin() ;
it != m_list.end() ; ++it) it != m_list.end() ; ++it) {
{
list.push_back(*it); list.push_back(*it);
} }
return (list); return list;
} }
const std::vector <shared_ptr <address> > addressList::getAddressList() const std::vector <shared_ptr <address> > addressList::getAddressList() {
{
return (m_list); return m_list;
} }
const std::vector <shared_ptr <component> > addressList::getChildComponents() const std::vector <shared_ptr <component> > addressList::getChildComponents() {
{
std::vector <shared_ptr <component> > list; std::vector <shared_ptr <component> > list;
copy_vector(m_list, list); copy_vector(m_list, list);
return (list); return list;
} }
shared_ptr <mailboxList> addressList::toMailboxList() const shared_ptr <mailboxList> addressList::toMailboxList() const {
{
shared_ptr <mailboxList> res = make_shared <mailboxList>(); shared_ptr <mailboxList> res = make_shared <mailboxList>();
for (std::vector <shared_ptr <address> >::const_iterator it = m_list.begin() ; for (std::vector <shared_ptr <address> >::const_iterator it = m_list.begin() ;
it != m_list.end() ; ++it) it != m_list.end() ; ++it) {
{
shared_ptr <const address> addr = *it; shared_ptr <const address> addr = *it;
if (addr->isGroup()) if (addr->isGroup()) {
{
const std::vector <shared_ptr <const mailbox> > mailboxes = const std::vector <shared_ptr <const mailbox> > mailboxes =
dynamicCast <const mailboxGroup>(addr)->getMailboxList(); dynamicCast <const mailboxGroup>(addr)->getMailboxList();
for (std::vector <shared_ptr <const mailbox> >::const_iterator jt = mailboxes.begin() ; for (std::vector <shared_ptr <const mailbox> >::const_iterator jt = mailboxes.begin() ;
jt != mailboxes.end() ; ++jt) jt != mailboxes.end() ; ++jt) {
{
res->appendMailbox(vmime::clone(*jt)); res->appendMailbox(vmime::clone(*jt));
} }
}
else } else {
{
res->appendMailbox(dynamicCast <mailbox>(addr->clone())); res->appendMailbox(dynamicCast <mailbox>(addr->clone()));
} }
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -31,8 +31,7 @@
#include "vmime/address.hpp" #include "vmime/address.hpp"
namespace vmime namespace vmime {
{
class mailboxList; class mailboxList;
@ -40,9 +39,8 @@ class mailboxList;
/** A list of addresses. /** A list of addresses.
*/ */
class VMIME_EXPORT addressList : public headerFieldValue {
class VMIME_EXPORT addressList : public headerFieldValue
{
public: public:
addressList(); addressList();
@ -63,7 +61,7 @@ public:
* *
* @param addr address to append * @param addr address to append
*/ */
void appendAddress(shared_ptr <address> addr); void appendAddress(const shared_ptr <address>& addr);
/** Insert a new address before the specified address. /** Insert a new address before the specified address.
* *
@ -71,7 +69,10 @@ public:
* @param addr address to insert * @param addr address to insert
* @throw std::out_of_range if the address is not in the list * @throw std::out_of_range if the address is not in the list
*/ */
void insertAddressBefore(shared_ptr <address> beforeAddress, shared_ptr <address> addr); void insertAddressBefore(
const shared_ptr <address>& beforeAddress,
const shared_ptr <address>& addr
);
/** Insert a new address before the specified position. /** Insert a new address before the specified position.
* *
@ -80,7 +81,7 @@ public:
* @param addr address to insert * @param addr address to insert
* @throw std::out_of_range if the position is out of range * @throw std::out_of_range if the position is out of range
*/ */
void insertAddressBefore(const size_t pos, shared_ptr <address> addr); void insertAddressBefore(const size_t pos, const shared_ptr <address>& addr);
/** Insert a new address after the specified address. /** Insert a new address after the specified address.
* *
@ -88,7 +89,10 @@ public:
* @param addr address to insert * @param addr address to insert
* @throw std::out_of_range if the address is not in the list * @throw std::out_of_range if the address is not in the list
*/ */
void insertAddressAfter(shared_ptr <address> afterAddress, shared_ptr <address> addr); void insertAddressAfter(
const shared_ptr <address>& afterAddress,
const shared_ptr <address>& addr
);
/** Insert a new address after the specified position. /** Insert a new address after the specified position.
* *
@ -96,14 +100,14 @@ public:
* @param addr address to insert * @param addr address to insert
* @throw std::out_of_range if the position is out of range * @throw std::out_of_range if the position is out of range
*/ */
void insertAddressAfter(const size_t pos, shared_ptr <address> addr); void insertAddressAfter(const size_t pos, const shared_ptr <address>& addr);
/** Remove the specified address from the list. /** Remove the specified address from the list.
* *
* @param addr address to remove * @param addr address to remove
* @throw std::out_of_range if the address is not in the list * @throw std::out_of_range if the address is not in the list
*/ */
void removeAddress(shared_ptr <address> addr); void removeAddress(const shared_ptr <address>& addr);
/** Remove the address at the specified position. /** Remove the address at the specified position.
* *
@ -171,18 +175,20 @@ private:
protected: protected:
// Component parsing & assembling // Component parsing & assembling
void parseImpl void parseImpl(
(const parsingContext& ctx, const parsingContext& ctx,
const string& buffer, const string& buffer,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
void generateImpl void generateImpl(
(const generationContext& ctx, const generationContext& ctx,
utility::outputStream& os, utility::outputStream& os,
const size_t curLinePos = 0, const size_t curLinePos = 0,
size_t* newLinePos = NULL) const; size_t* newLinePos = NULL
) const;
}; };

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -34,15 +34,13 @@
#include "vmime/encoding.hpp" #include "vmime/encoding.hpp"
namespace vmime namespace vmime {
{
/** Base class for all types of attachment. /** Base class for all types of attachment.
*/ */
class VMIME_EXPORT attachment : public object {
class VMIME_EXPORT attachment : public object
{
friend class messageBuilder; friend class messageBuilder;
friend class messageParser; friend class messageParser;
friend class attachmentHelper; friend class attachmentHelper;
@ -108,7 +106,7 @@ protected:
* *
* @param parent body part in which to generate the attachment * @param parent body part in which to generate the attachment
*/ */
virtual void generateIn(shared_ptr <bodyPart> parent) const = 0; virtual void generateIn(const shared_ptr <bodyPart>& parent) const = 0;
}; };

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -33,36 +33,39 @@
#include <iterator> #include <iterator>
namespace vmime namespace vmime {
{
// static // static
bool attachmentHelper::isBodyPartAnAttachment bool attachmentHelper::isBodyPartAnAttachment(
(shared_ptr <const bodyPart> part, const unsigned int options) const shared_ptr <const bodyPart>& part,
{ const unsigned int options
) {
// First, try with "Content-Disposition" field. // First, try with "Content-Disposition" field.
// If not present, we will try with "Content-Type" field. // If not present, we will try with "Content-Type" field.
shared_ptr <const contentDispositionField> cdf = shared_ptr <const contentDispositionField> cdf =
part->getHeader()->findField <contentDispositionField>(fields::CONTENT_DISPOSITION); part->getHeader()->findField <contentDispositionField>(fields::CONTENT_DISPOSITION);
if (cdf) if (cdf) {
{
const contentDisposition disp = *cdf->getValue <contentDisposition>(); const contentDisposition disp = *cdf->getValue <contentDisposition>();
if (disp.getName() != contentDispositionTypes::INLINE) if (disp.getName() != contentDispositionTypes::INLINE) {
return true; return true;
}
if ((options & INLINE_OBJECTS) == 0) {
if ((options & INLINE_OBJECTS) == 0)
{
// If the Content-Disposition is 'inline' and there is no // If the Content-Disposition is 'inline' and there is no
// Content-Id or Content-Location field, it may be an attachment // Content-Id or Content-Location field, it may be an attachment
if (!part->getHeader()->hasField(vmime::fields::CONTENT_ID) && if (!part->getHeader()->hasField(vmime::fields::CONTENT_ID) &&
!part->getHeader()->hasField(vmime::fields::CONTENT_LOCATION)) !part->getHeader()->hasField(vmime::fields::CONTENT_LOCATION)) {
{
// If this is the root part, it might not be an attachment // If this is the root part, it might not be an attachment
if (part->getParentPart() == NULL) if (!part->getParentPart()) {
return false; return false;
}
return true; return true;
} }
@ -78,40 +81,46 @@ bool attachmentHelper::isBodyPartAnAttachment
shared_ptr <const contentTypeField> ctf = shared_ptr <const contentTypeField> ctf =
part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE); part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
if (ctf) if (ctf) {
{
type = *ctf->getValue <mediaType>(); type = *ctf->getValue <mediaType>();
if (ctf->hasParameter("name")) if (ctf->hasParameter("name")) {
hasContentTypeName = true; hasContentTypeName = true;
} }
else
{ } else {
// If this is the root part and no Content-Type field is present, // If this is the root part and no Content-Type field is present,
// then this may not be a MIME message, so do not assume it is // then this may not be a MIME message, so do not assume it is
// an attachment // an attachment
if (part->getParentPart() == NULL) if (!part->getParentPart()) {
return false; return false;
}
// No "Content-type" field: assume "application/octet-stream". // No "Content-type" field: assume "application/octet-stream".
type = mediaType(mediaTypes::APPLICATION, type = mediaType(
mediaTypes::APPLICATION_OCTET_STREAM); mediaTypes::APPLICATION,
mediaTypes::APPLICATION_OCTET_STREAM
);
} }
if (type.getType() != mediaTypes::TEXT && if (type.getType() != mediaTypes::TEXT &&
type.getType() != mediaTypes::MULTIPART) type.getType() != mediaTypes::MULTIPART) {
{
// Compatibility with (obsolete) RFC-1341: if there is a "name" parameter // Compatibility with (obsolete) RFC-1341: if there is a "name" parameter
// on the "Content-Type" field, then we assume it is an attachment // on the "Content-Type" field, then we assume it is an attachment
if (hasContentTypeName) if (hasContentTypeName) {
return true; return true;
}
if ((options & INLINE_OBJECTS) == 0) {
if ((options & INLINE_OBJECTS) == 0)
{
// If a "Content-Id" field is present, it might be an // If a "Content-Id" field is present, it might be an
// embedded object (MHTML messages) // embedded object (MHTML messages)
if (part->getHeader()->hasField(vmime::fields::CONTENT_ID)) if (part->getHeader()->hasField(vmime::fields::CONTENT_ID)) {
return false; return false;
}
} }
return true; return true;
@ -122,35 +131,40 @@ bool attachmentHelper::isBodyPartAnAttachment
// static // static
shared_ptr <const attachment> attachmentHelper::getBodyPartAttachment shared_ptr <const attachment> attachmentHelper::getBodyPartAttachment(
(shared_ptr <const bodyPart> part, const unsigned int options) const shared_ptr <const bodyPart>& part,
{ const unsigned int options
if (!isBodyPartAnAttachment(part, options)) ) {
if (!isBodyPartAnAttachment(part, options)) {
return null; return null;
}
mediaType type; mediaType type;
shared_ptr <const contentTypeField> ctf = shared_ptr <const contentTypeField> ctf =
part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE); part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
if (ctf) if (ctf) {
{
type = *ctf->getValue <mediaType>(); type = *ctf->getValue <mediaType>();
}
else } else {
{
// No "Content-type" field: assume "application/octet-stream". // No "Content-type" field: assume "application/octet-stream".
type = mediaType(mediaTypes::APPLICATION, type = mediaType(
mediaTypes::APPLICATION_OCTET_STREAM); mediaTypes::APPLICATION,
mediaTypes::APPLICATION_OCTET_STREAM
);
} }
if (type.getType() == mediaTypes::MESSAGE && if (type.getType() == mediaTypes::MESSAGE &&
type.getSubType() == mediaTypes::MESSAGE_RFC822) type.getSubType() == mediaTypes::MESSAGE_RFC822) {
{
return make_shared <generatedMessageAttachment>(part); return make_shared <generatedMessageAttachment>(part);
}
else } else {
{
return make_shared <bodyPartAttachment>(part); return make_shared <bodyPartAttachment>(part);
} }
} }
@ -158,32 +172,36 @@ shared_ptr <const attachment> attachmentHelper::getBodyPartAttachment
// static // static
const std::vector <shared_ptr <const attachment> > const std::vector <shared_ptr <const attachment> >
attachmentHelper::findAttachmentsInMessage attachmentHelper::findAttachmentsInMessage(
(shared_ptr <const message> msg, const unsigned int options) const shared_ptr <const message>& msg,
{ const unsigned int options
) {
return findAttachmentsInBodyPart(msg, options); return findAttachmentsInBodyPart(msg, options);
} }
// static // static
const std::vector <shared_ptr <const attachment> > const std::vector <shared_ptr <const attachment> >
attachmentHelper::findAttachmentsInBodyPart attachmentHelper::findAttachmentsInBodyPart(
(shared_ptr <const bodyPart> part, const unsigned int options) const shared_ptr <const bodyPart>& part,
{ const unsigned int options
) {
std::vector <shared_ptr <const attachment> > atts; std::vector <shared_ptr <const attachment> > atts;
// Test this part // Test this part
if (isBodyPartAnAttachment(part, options)) if (isBodyPartAnAttachment(part, options)) {
{
atts.push_back(getBodyPartAttachment(part, options)); atts.push_back(getBodyPartAttachment(part, options));
}
// Find in sub-parts // Find in sub-parts
else } else {
{
shared_ptr <const body> bdy = part->getBody(); shared_ptr <const body> bdy = part->getBody();
for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) {
{
std::vector <shared_ptr <const attachment> > partAtts = std::vector <shared_ptr <const attachment> > partAtts =
findAttachmentsInBodyPart(bdy->getPartAt(i), options); findAttachmentsInBodyPart(bdy->getPartAt(i), options);
@ -196,35 +214,39 @@ const std::vector <shared_ptr <const attachment> >
// static // static
void attachmentHelper::addAttachment(shared_ptr <message> msg, shared_ptr <attachment> att) void attachmentHelper::addAttachment(const shared_ptr <message>& msg, const shared_ptr <attachment>& att) {
{
// We simply search for a "multipart/mixed" part. If no one exists, // We simply search for a "multipart/mixed" part. If no one exists,
// create it in the root part. This (very simple) algorithm should // create it in the root part. This (very simple) algorithm should
// work in the most cases. // work in the most cases.
vmime::mediaType mpMixed(vmime::mediaTypes::MULTIPART, vmime::mediaType mpMixed(
vmime::mediaTypes::MULTIPART_MIXED); vmime::mediaTypes::MULTIPART,
vmime::mediaTypes::MULTIPART_MIXED
);
shared_ptr <bodyPart> part = findBodyPart(msg, mpMixed); shared_ptr <bodyPart> part = findBodyPart(msg, mpMixed);
if (part == NULL) // create it if (!part) { // create it
{
if (msg->getBody()->getPartCount() != 0) if (msg->getBody()->getPartCount() != 0) {
{
// Create a new container part for the parts that were in // Create a new container part for the parts that were in
// the root part of the message // the root part of the message
shared_ptr <bodyPart> container = make_shared <bodyPart>(); shared_ptr <bodyPart> container = make_shared <bodyPart>();
if (msg->getHeader()->hasField(fields::CONTENT_TYPE)) if (msg->getHeader()->hasField(fields::CONTENT_TYPE)) {
{
container->getHeader()->ContentType()->setValue container->getHeader()->ContentType()->setValue(
(msg->getHeader()->ContentType()->getValue()); msg->getHeader()->ContentType()->getValue()
);
} }
if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING)) if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING)) {
{
container->getHeader()->ContentTransferEncoding()->setValue container->getHeader()->ContentTransferEncoding()->setValue(
(msg->getHeader()->ContentTransferEncoding()->getValue()); msg->getHeader()->ContentTransferEncoding()->getValue()
);
} }
// Move parts from the root part to this new part // Move parts from the root part to this new part
@ -233,28 +255,31 @@ void attachmentHelper::addAttachment(shared_ptr <message> msg, shared_ptr <attac
msg->getBody()->removeAllParts(); msg->getBody()->removeAllParts();
for (unsigned int i = 0 ; i < partList.size() ; ++i) for (unsigned int i = 0 ; i < partList.size() ; ++i) {
container->getBody()->appendPart(partList[i]); container->getBody()->appendPart(partList[i]);
}
msg->getBody()->appendPart(container); msg->getBody()->appendPart(container);
}
else } else {
{
// The message is a simple (RFC-822) message, and do not // The message is a simple (RFC-822) message, and do not
// contains any MIME part. Move the contents from the // contains any MIME part. Move the contents from the
// root to a new child part. // root to a new child part.
shared_ptr <bodyPart> child = make_shared <bodyPart>(); shared_ptr <bodyPart> child = make_shared <bodyPart>();
if (msg->getHeader()->hasField(fields::CONTENT_TYPE)) if (msg->getHeader()->hasField(fields::CONTENT_TYPE)) {
{
child->getHeader()->ContentType()->setValue child->getHeader()->ContentType()->setValue(
(msg->getHeader()->ContentType()->getValue()); msg->getHeader()->ContentType()->getValue()
);
} }
if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING)) if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING)) {
{
child->getHeader()->ContentTransferEncoding()->setValue child->getHeader()->ContentTransferEncoding()->setValue(
(msg->getHeader()->ContentTransferEncoding()->getValue()); msg->getHeader()->ContentTransferEncoding()->getValue()
);
} }
child->getBody()->setContents(msg->getBody()->getContents()); child->getBody()->setContents(msg->getBody()->getContents());
@ -278,22 +303,25 @@ void attachmentHelper::addAttachment(shared_ptr <message> msg, shared_ptr <attac
// static // static
shared_ptr <bodyPart> attachmentHelper::findBodyPart shared_ptr <bodyPart> attachmentHelper::findBodyPart(
(shared_ptr <bodyPart> part, const mediaType& type) const shared_ptr <bodyPart>& part,
{ const mediaType& type
if (part->getBody()->getContentType() == type) ) {
if (part->getBody()->getContentType() == type) {
return part; return part;
}
// Try in sub-parts // Try in sub-parts
shared_ptr <body> bdy = part->getBody(); shared_ptr <body> bdy = part->getBody();
for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) {
{
shared_ptr <bodyPart> found =
findBodyPart(bdy->getPartAt(i), type);
if (found != NULL) shared_ptr <bodyPart> found = findBodyPart(bdy->getPartAt(i), type);
if (found) {
return found; return found;
}
} }
return null; return null;
@ -301,12 +329,11 @@ shared_ptr <bodyPart> attachmentHelper::findBodyPart
// static // static
void attachmentHelper::addAttachment(shared_ptr <message> msg, shared_ptr <message> amsg) void attachmentHelper::addAttachment(const shared_ptr <message>& msg, const shared_ptr <message>& amsg) {
{
shared_ptr <attachment> att = make_shared <parsedMessageAttachment>(amsg); shared_ptr <attachment> att = make_shared <parsedMessageAttachment>(amsg);
addAttachment(msg, att); addAttachment(msg, att);
} }
} // vmime } // vmime

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -31,14 +31,13 @@
#include "vmime/message.hpp" #include "vmime/message.hpp"
namespace vmime namespace vmime {
{
/** Retrieve attachment information from message parts. /** Retrieve attachment information from message parts.
*/ */
class VMIME_EXPORT attachmentHelper class VMIME_EXPORT attachmentHelper {
{
public: public:
/** Options for use with the following functions: /** Options for use with the following functions:
@ -46,8 +45,7 @@ public:
* getBodyPartAttachment, * getBodyPartAttachment,
* and isBodyPartAnAttachment. * and isBodyPartAnAttachment.
*/ */
enum FindOptions enum FindOptions {
{
INLINE_OBJECTS = (1 << 0) /**< Recognize and return inline objects. The aim is to INLINE_OBJECTS = (1 << 0) /**< Recognize and return inline objects. The aim is to
consider MHTML objects (parts with a "Content-Id" or consider MHTML objects (parts with a "Content-Id" or
a "Content-Location", such as inline images) as attachments. */ a "Content-Location", such as inline images) as attachments. */
@ -59,7 +57,10 @@ public:
* @param options search options (see FindOptions) * @param options search options (see FindOptions)
* @return true if the part is an attachment, false otherwise * @return true if the part is an attachment, false otherwise
*/ */
static bool isBodyPartAnAttachment(shared_ptr <const bodyPart> part, const unsigned int options = 0); static bool isBodyPartAnAttachment(
const shared_ptr <const bodyPart>& part,
const unsigned int options = 0
);
/** Return attachment information in the specified body part. /** Return attachment information in the specified body part.
* If the specified body part does not contain attachment * If the specified body part does not contain attachment
@ -69,8 +70,10 @@ public:
* @param options search options (see FindOptions) * @param options search options (see FindOptions)
* @return attachment found in the part, or NULL * @return attachment found in the part, or NULL
*/ */
static shared_ptr <const attachment> static shared_ptr <const attachment> getBodyPartAttachment(
getBodyPartAttachment(shared_ptr <const bodyPart> part, const unsigned int options = 0); const shared_ptr <const bodyPart>& part,
const unsigned int options = 0
);
/** Find all attachments contained in the specified part /** Find all attachments contained in the specified part
* and all its children parts. * and all its children parts.
@ -81,7 +84,10 @@ public:
* @return a list of attachments found * @return a list of attachments found
*/ */
static const std::vector <shared_ptr <const attachment> > static const std::vector <shared_ptr <const attachment> >
findAttachmentsInBodyPart(shared_ptr <const bodyPart> part, const unsigned int options = 0); findAttachmentsInBodyPart(
const shared_ptr <const bodyPart>& part,
const unsigned int options = 0
);
/** Find all attachments contained in the specified message. /** Find all attachments contained in the specified message.
* This is simply a recursive call to getBodyPartAttachment(). * This is simply a recursive call to getBodyPartAttachment().
@ -91,26 +97,37 @@ public:
* @return a list of attachments found * @return a list of attachments found
*/ */
static const std::vector <shared_ptr <const attachment> > static const std::vector <shared_ptr <const attachment> >
findAttachmentsInMessage(shared_ptr <const message> msg, const unsigned int options = 0); findAttachmentsInMessage(
const shared_ptr <const message>& msg,
const unsigned int options = 0
);
/** Add an attachment to the specified message. /** Add an attachment to the specified message.
* *
* @param msg message into which to add the attachment * @param msg message into which to add the attachment
* @param att attachment to add * @param att attachment to add
*/ */
static void addAttachment(shared_ptr <message> msg, shared_ptr <attachment> att); static void addAttachment(
const shared_ptr <message>& msg,
const shared_ptr <attachment>& att
);
/** Add a message attachment to the specified message. /** Add a message attachment to the specified message.
* *
* @param msg message into which to add the attachment * @param msg message into which to add the attachment
* @param amsg message to attach * @param amsg message to attach
*/ */
static void addAttachment(shared_ptr <message> msg, shared_ptr <message> amsg); static void addAttachment(
const shared_ptr <message>& msg,
const shared_ptr <message>& amsg
);
protected: protected:
static shared_ptr <bodyPart> findBodyPart static shared_ptr <bodyPart> findBodyPart(
(shared_ptr <bodyPart> part, const mediaType& type); const shared_ptr <bodyPart>& part,
const mediaType& type
);
}; };
@ -118,4 +135,3 @@ protected:
#endif // VMIME_ATTACHMENTHELPER_HPP_INCLUDED #endif // VMIME_ATTACHMENTHELPER_HPP_INCLUDED

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -48,8 +48,7 @@
#endif #endif
namespace vmime namespace vmime {
{
/** "Null" (empty) string. /** "Null" (empty) string.
@ -108,8 +107,8 @@ nullPtrType null;
// Line length limits // Line length limits
namespace lineLengthLimits namespace lineLengthLimits {
{
const size_t infinite = std::numeric_limits <size_t>::max(); const size_t infinite = std::numeric_limits <size_t>::max();
} }
@ -134,12 +133,10 @@ const size_t npos = std::numeric_limits <size_t>::max();
// constructor, for example). // constructor, for example).
// //
class initializer struct initializer {
{
public: initializer() {
initializer()
{
parsingContext::getDefaultContext(); parsingContext::getDefaultContext();
generationContext::getDefaultContext(); generationContext::getDefaultContext();

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -37,8 +37,8 @@
#include "vmime/constants.hpp" #include "vmime/constants.hpp"
namespace vmime namespace vmime {
{
class text; class text;
class word; class word;
class charset; class charset;
@ -53,9 +53,9 @@ namespace vmime
#ifndef VMIME_BUILDING_DOC #ifndef VMIME_BUILDING_DOC
// Null pointer // Null pointer
struct nullPtrType struct nullPtrType {
{
template<typename T> template <typename T>
operator shared_ptr <T>() { return shared_ptr <T>(); } operator shared_ptr <T>() { return shared_ptr <T>(); }
}; };
@ -78,47 +78,48 @@ namespace vmime
// //
template <typename T, size_t N> template <typename T, size_t N>
inline T const* cbegin(T const (&array)[N]) inline T const* cbegin(T const (&array)[N]) {
{
return (array); return array;
} }
template <typename T, size_t N> template <typename T, size_t N>
inline T const* cend(T const (&array)[N]) inline T const* cend(T const (&array)[N]) {
{
return (array + N); return array + N;
} }
template <typename T, size_t N> template <typename T, size_t N>
inline T* begin(T (&array)[N]) inline T* begin(T (&array)[N]) {
{
return (array); return array;
} }
template <typename T, size_t N> template <typename T, size_t N>
inline T* end(T (&array)[N]) inline T* end(T (&array)[N]) {
{
return (array + N); return array + N;
} }
template <typename T, size_t N> template <typename T, size_t N>
inline size_t count(T const (&/* array */)[N]) inline size_t count(T const (&/* array */)[N]) {
{
return (N); return N;
} }
// Copy one vector to another, with type conversion // Copy one vector to another, with type conversion
template <class T1, class T2> template <class T1, class T2>
void copy_vector(const T1& v1, T2& v2) void copy_vector(const T1& v1, T2& v2) {
{
const typename T1::size_type count = v1.size(); const typename T1::size_type count = v1.size();
v2.resize(count); v2.resize(count);
for (typename T1::size_type i = 0 ; i < count ; ++i) for (typename T1::size_type i = 0 ; i < count ; ++i) {
v2[i] = v1[i]; v2[i] = v1[i];
}
} }
@ -154,12 +155,11 @@ namespace vmime
character limit) for the sake of robustness. character limit) for the sake of robustness.
*/ */
namespace lineLengthLimits namespace lineLengthLimits {
{
extern VMIME_EXPORT const size_t infinite; extern VMIME_EXPORT const size_t infinite;
enum enum {
{
max = 998, max = 998,
convenient = 78 convenient = 78
}; };
@ -192,8 +192,8 @@ namespace vmime
* This is an alias for dynamic_pointer_cast <T>(obj->clone()). * This is an alias for dynamic_pointer_cast <T>(obj->clone()).
*/ */
template <class T> template <class T>
shared_ptr <T> clone(shared_ptr <T> obj) shared_ptr <T> clone(const shared_ptr <T>& obj) {
{
return dynamic_pointer_cast <T>(obj->clone()); return dynamic_pointer_cast <T>(obj->clone());
} }
@ -201,8 +201,8 @@ namespace vmime
* This is an alias for dynamic_pointer_cast <T>(obj->clone()). * This is an alias for dynamic_pointer_cast <T>(obj->clone()).
*/ */
template <class T> template <class T>
shared_ptr <T> clone(shared_ptr <const T> obj) shared_ptr <T> clone(const shared_ptr <const T>& obj) {
{
return dynamic_pointer_cast <T>(obj->clone()); return dynamic_pointer_cast <T>(obj->clone());
} }
@ -210,8 +210,8 @@ namespace vmime
* This is an alias for dynamic_pointer_cast <T>(obj.clone()). * This is an alias for dynamic_pointer_cast <T>(obj.clone()).
*/ */
template <class T> template <class T>
shared_ptr <T> clone(const T& obj) shared_ptr <T> clone(const T& obj) {
{
return dynamic_pointer_cast <T>(obj.clone()); return dynamic_pointer_cast <T>(obj.clone());
} }
@ -220,24 +220,24 @@ namespace vmime
* type Type, and DerivedType is derived from Type. * type Type, and DerivedType is derived from Type.
*/ */
template <class X, class Y> template <class X, class Y>
shared_ptr <X> dynamicCast(shared_ptr <Y> obj) shared_ptr <X> dynamicCast(const shared_ptr <Y>& obj) {
{
return dynamic_pointer_cast <X, Y>(obj); return dynamic_pointer_cast <X, Y>(obj);
} }
/** Const cast helper. /** Const cast helper.
*/ */
template <class X, class Y> template <class X, class Y>
shared_ptr <X> constCast(const shared_ptr <Y>& obj) shared_ptr <X> constCast(const shared_ptr <Y>& obj) {
{
return const_pointer_cast <X, Y>(obj); return const_pointer_cast <X, Y>(obj);
} }
/** Inherit from this class to indicate the subclass is not copyable, /** Inherit from this class to indicate the subclass is not copyable,
* ie. you want to prohibit copy construction and copy assignment. * ie. you want to prohibit copy construction and copy assignment.
*/ */
class VMIME_EXPORT noncopyable class VMIME_EXPORT noncopyable {
{
protected: protected:
noncopyable() { } noncopyable() { }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -37,8 +37,7 @@
#include "vmime/contentHandler.hpp" #include "vmime/contentHandler.hpp"
namespace vmime namespace vmime {
{
class bodyPart; class bodyPart;
@ -46,9 +45,8 @@ class bodyPart;
/** Body section of a MIME part. /** Body section of a MIME part.
*/ */
class VMIME_EXPORT body : public component {
class VMIME_EXPORT body : public component
{
friend class bodyPart; friend class bodyPart;
public: public:
@ -60,7 +58,7 @@ public:
* *
* @param part part to append * @param part part to append
*/ */
void appendPart(shared_ptr <bodyPart> part); void appendPart(const shared_ptr <bodyPart>& part);
/** Insert a new part before the specified part. /** Insert a new part before the specified part.
* *
@ -68,7 +66,10 @@ public:
* @param part part to insert * @param part part to insert
* @throw exceptions::no_such_part if the part is not in the list * @throw exceptions::no_such_part if the part is not in the list
*/ */
void insertPartBefore(shared_ptr <bodyPart> beforePart, shared_ptr <bodyPart> part); void insertPartBefore(
const shared_ptr <bodyPart>& beforePart,
const shared_ptr <bodyPart>& part
);
/** Insert a new part before the specified position. /** Insert a new part before the specified position.
* *
@ -76,7 +77,7 @@ public:
* the beginning of the list) * the beginning of the list)
* @param part part to insert * @param part part to insert
*/ */
void insertPartBefore(const size_t pos, shared_ptr <bodyPart> part); void insertPartBefore(const size_t pos, const shared_ptr <bodyPart>& part);
/** Insert a new part after the specified part. /** Insert a new part after the specified part.
* *
@ -84,21 +85,24 @@ public:
* @param part part to insert * @param part part to insert
* @throw exceptions::no_such_part if the part is not in the list * @throw exceptions::no_such_part if the part is not in the list
*/ */
void insertPartAfter(shared_ptr <bodyPart> afterPart, shared_ptr <bodyPart> part); void insertPartAfter(
const shared_ptr <bodyPart>& afterPart,
const shared_ptr <bodyPart>& part
);
/** Insert a new part after the specified position. /** Insert a new part after the specified position.
* *
* @param pos position of the part before the new part * @param pos position of the part before the new part
* @param part part to insert * @param part part to insert
*/ */
void insertPartAfter(const size_t pos, shared_ptr <bodyPart> part); void insertPartAfter(const size_t pos, const shared_ptr <bodyPart>& part);
/** Remove the specified part from the list. /** Remove the specified part from the list.
* *
* @param part part to remove * @param part part to remove
* @throw exceptions::no_such_part if the part is not in the list * @throw exceptions::no_such_part if the part is not in the list
*/ */
void removePart(shared_ptr <bodyPart> part); void removePart(const shared_ptr <bodyPart>& part);
/** Remove the part at the specified position. /** Remove the part at the specified position.
* *
@ -182,14 +186,17 @@ public:
* *
* @param contents new body contents * @param contents new body contents
*/ */
void setContents(shared_ptr <const contentHandler> contents); void setContents(const shared_ptr <const contentHandler>& contents);
/** Set the body contents and type. /** Set the body contents and type.
* *
* @param contents new body contents * @param contents new body contents
* @param type type of contents * @param type type of contents
*/ */
void setContents(shared_ptr <const contentHandler> contents, const mediaType& type); void setContents(
const shared_ptr <const contentHandler>& contents,
const mediaType& type
);
/** Set the body contents, type and charset. /** Set the body contents, type and charset.
* *
@ -197,7 +204,11 @@ public:
* @param type type of contents * @param type type of contents
* @param chset charset of contents * @param chset charset of contents
*/ */
void setContents(shared_ptr <const contentHandler> contents, const mediaType& type, const charset& chset); void setContents(
const shared_ptr <const contentHandler>& contents,
const mediaType& type,
const charset& chset
);
/** Set the body contents, type, charset and encoding. /** Set the body contents, type, charset and encoding.
* *
@ -206,8 +217,12 @@ public:
* @param chset charset of contents * @param chset charset of contents
* @param enc contents encoding * @param enc contents encoding
*/ */
void setContents(shared_ptr <const contentHandler> contents, const mediaType& type, void setContents(
const charset& chset, const encoding& enc); const shared_ptr <const contentHandler>& contents,
const mediaType& type,
const charset& chset,
const encoding& enc
);
/** Set the MIME type and charset of contents. /** Set the MIME type and charset of contents.
* If a charset is defined, it will not be modified. * If a charset is defined, it will not be modified.
@ -301,7 +316,7 @@ private:
bool isRootPart() const; bool isRootPart() const;
void initNewPart(shared_ptr <bodyPart> part); void initNewPart(const shared_ptr <bodyPart>& part);
protected: protected:
@ -317,24 +332,30 @@ protected:
* before the CRLF or "--" which follows) * before the CRLF or "--" which follows)
* @return the position of the boundary string, or npos if not found * @return the position of the boundary string, or npos if not found
*/ */
size_t findNextBoundaryPosition size_t findNextBoundaryPosition(
(shared_ptr <utility::parserInputStreamAdapter> parser, const string& boundary, const shared_ptr <utility::parserInputStreamAdapter>& parser,
const size_t position, const size_t end, const string& boundary,
size_t* boundaryStart, size_t* boundaryEnd); const size_t position,
const size_t end,
size_t* boundaryStart,
size_t* boundaryEnd
);
// Component parsing & assembling // Component parsing & assembling
void parseImpl void parseImpl(
(const parsingContext& ctx, const parsingContext& ctx,
shared_ptr <utility::parserInputStreamAdapter> parser, const shared_ptr <utility::parserInputStreamAdapter>& parser,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
void generateImpl void generateImpl(
(const generationContext& ctx, const generationContext& ctx,
utility::outputStream& os, utility::outputStream& os,
const size_t curLinePos = 0, const size_t curLinePos = 0,
size_t* newLinePos = NULL) const; size_t* newLinePos = NULL
) const;
}; };

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -24,23 +24,26 @@
#include "vmime/bodyPart.hpp" #include "vmime/bodyPart.hpp"
namespace vmime namespace vmime {
{
bodyPart::bodyPart() bodyPart::bodyPart()
: m_header(make_shared <header>()), : m_header(make_shared <header>()),
m_body(make_shared <body>()), m_body(make_shared <body>()),
m_parent() m_parent() {
{
m_body->setParentPart(this); m_body->setParentPart(this);
} }
void bodyPart::parseImpl void bodyPart::parseImpl(
(const parsingContext& ctx, shared_ptr <utility::parserInputStreamAdapter> parser, const parsingContext& ctx,
const size_t position, const size_t end, size_t* newPosition) const shared_ptr <utility::parserInputStreamAdapter>& parser,
{ const size_t position,
const size_t end,
size_t* newPosition
) {
// Parse the headers // Parse the headers
size_t pos = position; size_t pos = position;
m_header->parse(ctx, parser, pos, end, &pos); m_header->parse(ctx, parser, pos, end, &pos);
@ -50,34 +53,39 @@ void bodyPart::parseImpl
setParsedBounds(position, end); setParsedBounds(position, end);
if (newPosition) if (newPosition) {
*newPosition = end; *newPosition = end;
}
} }
void bodyPart::generateImpl void bodyPart::generateImpl(
(const generationContext& ctx, utility::outputStream& os, const generationContext& ctx,
const size_t /* curLinePos */, size_t* newLinePos) const utility::outputStream& os,
{ const size_t /* curLinePos */,
size_t* newLinePos
) const {
m_header->generate(ctx, os); m_header->generate(ctx, os);
os << CRLF; os << CRLF;
m_body->generate(ctx, os); m_body->generate(ctx, os);
if (newLinePos) if (newLinePos) {
*newLinePos = 0; *newLinePos = 0;
}
} }
size_t bodyPart::getGeneratedSize(const generationContext& ctx) size_t bodyPart::getGeneratedSize(const generationContext& ctx) {
{
return m_header->getGeneratedSize(ctx) + 2 /* CRLF */ + m_body->getGeneratedSize(ctx); return m_header->getGeneratedSize(ctx) + 2 /* CRLF */ + m_body->getGeneratedSize(ctx);
} }
shared_ptr <component> bodyPart::clone() const shared_ptr <component> bodyPart::clone() const {
{
shared_ptr <bodyPart> p = make_shared <bodyPart>(); shared_ptr <bodyPart> p = make_shared <bodyPart>();
p->m_parent = NULL; p->m_parent = NULL;
@ -85,12 +93,12 @@ shared_ptr <component> bodyPart::clone() const
p->m_header->copyFrom(*m_header); p->m_header->copyFrom(*m_header);
p->m_body->copyFrom(*m_body); p->m_body->copyFrom(*m_body);
return (p); return p;
} }
void bodyPart::copyFrom(const component& other) void bodyPart::copyFrom(const component& other) {
{
const bodyPart& bp = dynamic_cast <const bodyPart&>(other); const bodyPart& bp = dynamic_cast <const bodyPart&>(other);
m_header->copyFrom(*(bp.m_header)); m_header->copyFrom(*(bp.m_header));
@ -98,70 +106,71 @@ void bodyPart::copyFrom(const component& other)
} }
bodyPart& bodyPart::operator=(const bodyPart& other) bodyPart& bodyPart::operator=(const bodyPart& other) {
{
copyFrom(other); copyFrom(other);
return (*this); return *this;
} }
const shared_ptr <const header> bodyPart::getHeader() const const shared_ptr <const header> bodyPart::getHeader() const {
{
return (m_header); return m_header;
} }
shared_ptr <header> bodyPart::getHeader() shared_ptr <header> bodyPart::getHeader() {
{
return (m_header); return m_header;
} }
void bodyPart::setHeader(shared_ptr <header> h) void bodyPart::setHeader(const shared_ptr <header>& h) {
{
m_header = h; m_header = h;
} }
const shared_ptr <const body> bodyPart::getBody() const const shared_ptr <const body> bodyPart::getBody() const {
{
return (m_body); return m_body;
} }
shared_ptr <body> bodyPart::getBody() shared_ptr <body> bodyPart::getBody() {
{
return (m_body); return m_body;
} }
void bodyPart::setBody(shared_ptr <body> b) void bodyPart::setBody(const shared_ptr <body>& b) {
{
bodyPart* oldPart = b->m_part; bodyPart* oldPart = b->m_part;
m_body = b; m_body = b;
m_body->setParentPart(this); m_body->setParentPart(this);
// A body is associated to one and only one part // A body is associated to one and only one part
if (oldPart != NULL) if (oldPart) {
oldPart->setBody(make_shared <body>()); oldPart->setBody(make_shared <body>());
}
} }
bodyPart* bodyPart::getParentPart() bodyPart* bodyPart::getParentPart() {
{
return m_parent; return m_parent;
} }
const bodyPart* bodyPart::getParentPart() const const bodyPart* bodyPart::getParentPart() const {
{
return m_parent; return m_parent;
} }
shared_ptr <bodyPart> bodyPart::createChildPart() shared_ptr <bodyPart> bodyPart::createChildPart() {
{
shared_ptr <bodyPart> part = make_shared <bodyPart>(); shared_ptr <bodyPart> part = make_shared <bodyPart>();
part->m_parent = this; part->m_parent = this;
@ -169,22 +178,21 @@ shared_ptr <bodyPart> bodyPart::createChildPart()
} }
void bodyPart::importChildPart(shared_ptr <bodyPart> part) void bodyPart::importChildPart(const shared_ptr <bodyPart>& part) {
{
part->m_parent = this; part->m_parent = this;
} }
const std::vector <shared_ptr <component> > bodyPart::getChildComponents() const std::vector <shared_ptr <component> > bodyPart::getChildComponents() {
{
std::vector <shared_ptr <component> > list; std::vector <shared_ptr <component> > list;
list.push_back(m_header); list.push_back(m_header);
list.push_back(m_body); list.push_back(m_body);
return (list); return list;
} }
} // vmime } // vmime

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -32,15 +32,13 @@
#include "vmime/body.hpp" #include "vmime/body.hpp"
namespace vmime namespace vmime {
{
/** A MIME part. /** A MIME part.
*/ */
class VMIME_EXPORT bodyPart : public component {
class VMIME_EXPORT bodyPart : public component
{
friend class body; friend class body;
public: public:
@ -63,7 +61,7 @@ public:
* *
* @param header the new header of this part * @param header the new header of this part
*/ */
void setHeader(shared_ptr <header> header); void setHeader(const shared_ptr <header>& header);
/** Return the body section of this part. /** Return the body section of this part.
* *
@ -81,7 +79,7 @@ public:
* *
* @param body new body section * @param body new body section
*/ */
void setBody(shared_ptr <body> body); void setBody(const shared_ptr <body>& body);
/** Return the parent part of this part. /** Return the parent part of this part.
* *
@ -131,21 +129,23 @@ protected:
* *
* @param part child part to attach * @param part child part to attach
*/ */
void importChildPart(shared_ptr <bodyPart> part); void importChildPart(const shared_ptr <bodyPart>& part);
// Component parsing & assembling // Component parsing & assembling
void parseImpl void parseImpl(
(const parsingContext& ctx, const parsingContext& ctx,
shared_ptr <utility::parserInputStreamAdapter> parser, const shared_ptr <utility::parserInputStreamAdapter>& parser,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
void generateImpl void generateImpl(
(const generationContext& ctx, const generationContext& ctx,
utility::outputStream& os, utility::outputStream& os,
const size_t curLinePos = 0, const size_t curLinePos = 0,
size_t* newLinePos = NULL) const; size_t* newLinePos = NULL
) const;
}; };

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -24,55 +24,57 @@
#include "vmime/bodyPartAttachment.hpp" #include "vmime/bodyPartAttachment.hpp"
namespace vmime namespace vmime {
{
bodyPartAttachment::bodyPartAttachment(shared_ptr <const bodyPart> part) bodyPartAttachment::bodyPartAttachment(const shared_ptr <const bodyPart>& part)
: m_part(part) : m_part(part) {
{
} }
const mediaType bodyPartAttachment::getType() const const mediaType bodyPartAttachment::getType() const {
{
shared_ptr <const contentTypeField> ctf = getContentType(); shared_ptr <const contentTypeField> ctf = getContentType();
if (ctf) if (ctf) {
{
return *ctf->getValue <mediaType>(); return *ctf->getValue <mediaType>();
}
else } else {
{
// No "Content-type" field: assume "application/octet-stream". // No "Content-type" field: assume "application/octet-stream".
return mediaType(mediaTypes::APPLICATION, return mediaType(
mediaTypes::APPLICATION_OCTET_STREAM); mediaTypes::APPLICATION,
mediaTypes::APPLICATION_OCTET_STREAM
);
} }
} }
const word bodyPartAttachment::getName() const const word bodyPartAttachment::getName() const {
{
word name; word name;
// Try the 'filename' parameter of 'Content-Disposition' field // Try the 'filename' parameter of 'Content-Disposition' field
shared_ptr <const contentDispositionField> cdf = getContentDisposition(); shared_ptr <const contentDispositionField> cdf = getContentDisposition();
if (cdf && cdf->hasFilename()) if (cdf && cdf->hasFilename()) {
{
name = cdf->getFilename(); name = cdf->getFilename();
}
// Try the 'name' parameter of 'Content-Type' field // Try the 'name' parameter of 'Content-Type' field
else } else {
{
shared_ptr <const contentTypeField> ctf = getContentType(); shared_ptr <const contentTypeField> ctf = getContentType();
if (ctf) if (ctf) {
{
shared_ptr <const parameter> prm = ctf->findParameter("name"); shared_ptr <const parameter> prm = ctf->findParameter("name");
if (prm != NULL) if (prm) {
name = prm->getValue(); name = prm->getValue();
}
} }
} }
@ -80,19 +82,19 @@ const word bodyPartAttachment::getName() const
} }
const text bodyPartAttachment::getDescription() const const text bodyPartAttachment::getDescription() const {
{
text description; text description;
shared_ptr <const headerField> cd = shared_ptr <const headerField> cd =
getHeader()->findField(fields::CONTENT_DESCRIPTION); getHeader()->findField(fields::CONTENT_DESCRIPTION);
if (cd) if (cd) {
{
description = *cd->getValue <text>(); description = *cd->getValue <text>();
}
else } else {
{
// No description available. // No description available.
} }
@ -100,47 +102,46 @@ const text bodyPartAttachment::getDescription() const
} }
const encoding bodyPartAttachment::getEncoding() const const encoding bodyPartAttachment::getEncoding() const {
{
return m_part->getBody()->getEncoding(); return m_part->getBody()->getEncoding();
} }
const shared_ptr <const contentHandler> bodyPartAttachment::getData() const const shared_ptr <const contentHandler> bodyPartAttachment::getData() const {
{
return m_part->getBody()->getContents(); return m_part->getBody()->getContents();
} }
shared_ptr <const object> bodyPartAttachment::getPart() const shared_ptr <const object> bodyPartAttachment::getPart() const {
{
return m_part; return m_part;
} }
shared_ptr <const header> bodyPartAttachment::getHeader() const shared_ptr <const header> bodyPartAttachment::getHeader() const {
{
return m_part->getHeader(); return m_part->getHeader();
} }
shared_ptr <const contentDispositionField> bodyPartAttachment::getContentDisposition() const shared_ptr <const contentDispositionField> bodyPartAttachment::getContentDisposition() const {
{
return getHeader()->findField <contentDispositionField>(fields::CONTENT_DISPOSITION); return getHeader()->findField <contentDispositionField>(fields::CONTENT_DISPOSITION);
} }
shared_ptr <const contentTypeField> bodyPartAttachment::getContentType() const shared_ptr <const contentTypeField> bodyPartAttachment::getContentType() const {
{
return getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE); return getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
} }
void bodyPartAttachment::generateIn(shared_ptr <bodyPart> /* parent */) const void bodyPartAttachment::generateIn(const shared_ptr <bodyPart>& /* parent */) const {
{
// Not used // Not used
} }
} // vmime } // vmime

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -34,17 +34,16 @@
#include "vmime/contentTypeField.hpp" #include "vmime/contentTypeField.hpp"
namespace vmime namespace vmime {
{
/** An attachment related to a local body part. /** An attachment related to a local body part.
*/ */
class VMIME_EXPORT bodyPartAttachment : public attachment class VMIME_EXPORT bodyPartAttachment : public attachment {
{
public: public:
bodyPartAttachment(shared_ptr <const bodyPart> part); bodyPartAttachment(const shared_ptr <const bodyPart>& part);
const mediaType getType() const; const mediaType getType() const;
const word getName() const; const word getName() const;
@ -58,7 +57,7 @@ public:
private: private:
void generateIn(shared_ptr <bodyPart> parent) const; void generateIn(const shared_ptr <bodyPart>& parent) const;
shared_ptr <const contentDispositionField> getContentDisposition() const; shared_ptr <const contentDispositionField> getContentDisposition() const;
shared_ptr <const contentTypeField> getContentType() const; shared_ptr <const contentTypeField> getContentType() const;
@ -75,4 +74,3 @@ private:
#endif // VMIME_BODYPARTATTACHMENT_HPP_INCLUDED #endif // VMIME_BODYPARTATTACHMENT_HPP_INCLUDED

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -32,74 +32,93 @@
namespace vmime namespace vmime {
{
charset::charset() charset::charset()
: m_name(charsets::US_ASCII) : m_name(charsets::US_ASCII) {
{
} }
charset::charset(const string& name) charset::charset(const string& name)
: m_name(name) : m_name(name) {
{
// If we receive this rfc-1642 valid MIME charset, convert it to something usefull for iconv // If we receive this rfc-1642 valid MIME charset, convert it to something usefull for iconv
if (utility::stringUtils::isStringEqualNoCase(m_name, "unicode-1-1-utf-7")) if (utility::stringUtils::isStringEqualNoCase(m_name, "unicode-1-1-utf-7")) {
m_name = "utf-7"; m_name = "utf-7";
}
} }
charset::charset(const char* name) charset::charset(const char* name)
: m_name(name) : m_name(name) {
{
} }
void charset::parseImpl void charset::parseImpl(
(const parsingContext& /* ctx */, const string& buffer, const size_t position, const parsingContext& /* ctx */,
const size_t end, size_t* newPosition) const string& buffer,
{ const size_t position,
m_name = utility::stringUtils::trim const size_t end,
(string(buffer.begin() + position, buffer.begin() + end)); size_t* newPosition
) {
m_name = utility::stringUtils::trim(
string(buffer.begin() + position, buffer.begin() + end)
);
// If we parsed this rfc-1642 valid MIME charset, convert it to something usefull for iconv // If we parsed this rfc-1642 valid MIME charset, convert it to something usefull for iconv
if (utility::stringUtils::isStringEqualNoCase(m_name, "unicode-1-1-utf-7")) if (utility::stringUtils::isStringEqualNoCase(m_name, "unicode-1-1-utf-7")) {
m_name = "utf-7"; m_name = "utf-7";
}
setParsedBounds(position, end); setParsedBounds(position, end);
if (newPosition) if (newPosition) {
*newPosition = end; *newPosition = end;
}
} }
void charset::generateImpl void charset::generateImpl(
(const generationContext& /* ctx */, utility::outputStream& os, const generationContext& /* ctx */,
const size_t curLinePos, size_t* newLinePos) const utility::outputStream& os,
{ const size_t curLinePos,
size_t* newLinePos
) const {
os << m_name; os << m_name;
if (newLinePos) if (newLinePos) {
*newLinePos = curLinePos + m_name.length(); *newLinePos = curLinePos + m_name.length();
}
} }
void charset::convert(utility::inputStream& in, utility::outputStream& out, void charset::convert(
const charset& source, const charset& dest, utility::inputStream& in,
const charsetConverterOptions& opts) utility::outputStream& out,
{ const charset& source,
const charset& dest,
const charsetConverterOptions& opts
) {
shared_ptr <charsetConverter> conv = charsetConverter::create(source, dest, opts); shared_ptr <charsetConverter> conv = charsetConverter::create(source, dest, opts);
conv->convert(in, out); conv->convert(in, out);
} }
void charset::convert(const string& in, string& out, const charset& source, const charset& dest, void charset::convert(
const charsetConverterOptions& opts) const string& in,
{ string& out,
if (source == dest) const charset& source,
{ const charset& dest,
const charsetConverterOptions& opts
) {
if (source == dest) {
out = in; out = in;
return; return;
} }
@ -109,27 +128,26 @@ void charset::convert(const string& in, string& out, const charset& source, cons
} }
bool charset::isValidText bool charset::isValidText(const string& text, string::size_type* firstInvalidByte) const {
(const string& text, string::size_type* firstInvalidByte) const
{
charsetConverterOptions opts; charsetConverterOptions opts;
opts.silentlyReplaceInvalidSequences = false; opts.silentlyReplaceInvalidSequences = false;
charsetConverter::status st; charsetConverter::status st;
try try {
{
std::string out; std::string out;
// Try converting to UTF-8 // Try converting to UTF-8
shared_ptr <charsetConverter> conv = charsetConverter::create(*this, vmime::charset("utf-8"), opts); shared_ptr <charsetConverter> conv = charsetConverter::create(*this, vmime::charset("utf-8"), opts);
conv->convert(text, out, &st); conv->convert(text, out, &st);
}
catch (exceptions::illegal_byte_sequence_for_charset& e) } catch (exceptions::illegal_byte_sequence_for_charset& e) {
{
// An illegal byte sequence was found in the input buffer // An illegal byte sequence was found in the input buffer
if (firstInvalidByte) if (firstInvalidByte) {
{
if (st.inputBytesRead < text.length()) if (st.inputBytesRead < text.length())
*firstInvalidByte = st.inputBytesRead; *firstInvalidByte = st.inputBytesRead;
else else
@ -139,77 +157,79 @@ bool charset::isValidText
return false; return false;
} }
if (firstInvalidByte) if (firstInvalidByte) {
*firstInvalidByte = text.length(); *firstInvalidByte = text.length();
}
return true; return true;
} }
const charset charset::getLocalCharset() const charset charset::getLocalCharset() {
{
return (platform::getHandler()->getLocalCharset()); return platform::getHandler()->getLocalCharset();
} }
charset& charset::operator=(const charset& other) charset& charset::operator=(const charset& other) {
{
copyFrom(other); copyFrom(other);
return (*this); return *this;
} }
bool charset::operator==(const charset& value) const bool charset::operator==(const charset& value) const {
{
return (utility::stringUtils::isStringEqualNoCase(m_name, value.m_name)); return utility::stringUtils::isStringEqualNoCase(m_name, value.m_name);
} }
bool charset::operator!=(const charset& value) const bool charset::operator!=(const charset& value) const {
{
return !(*this == value); return !(*this == value);
} }
shared_ptr <component> charset::clone() const shared_ptr <component> charset::clone() const {
{
return make_shared <charset>(m_name); return make_shared <charset>(m_name);
} }
const string& charset::getName() const const string& charset::getName() const {
{
return (m_name); return m_name;
} }
void charset::copyFrom(const component& other) void charset::copyFrom(const component& other) {
{
m_name = dynamic_cast <const charset&>(other).m_name; m_name = dynamic_cast <const charset&>(other).m_name;
} }
const std::vector <shared_ptr <component> > charset::getChildComponents() const std::vector <shared_ptr <component> > charset::getChildComponents() {
{
return std::vector <shared_ptr <component> >(); return std::vector <shared_ptr <component> >();
} }
// Explicitly force encoding for some charsets // Explicitly force encoding for some charsets
struct CharsetEncodingEntry struct CharsetEncodingEntry {
{
CharsetEncodingEntry(const string& charset_, const string& encoding_) CharsetEncodingEntry(const string& charset_, const string& encoding_)
: charset(charset_), encoding(encoding_) : charset(charset_), encoding(encoding_) {
{
} }
const string charset; const string charset;
const string encoding; const string encoding;
}; };
CharsetEncodingEntry g_charsetEncodingMap[] =
{ CharsetEncodingEntry g_charsetEncodingMap[] = {
// Use QP encoding for ISO-8859-x charsets // Use QP encoding for ISO-8859-x charsets
CharsetEncodingEntry("iso-8859", encodingTypes::QUOTED_PRINTABLE), CharsetEncodingEntry("iso-8859", encodingTypes::QUOTED_PRINTABLE),
CharsetEncodingEntry("iso8859", encodingTypes::QUOTED_PRINTABLE), CharsetEncodingEntry("iso8859", encodingTypes::QUOTED_PRINTABLE),
@ -226,15 +246,16 @@ CharsetEncodingEntry g_charsetEncodingMap[] =
}; };
bool charset::getRecommendedEncoding(encoding& enc) const bool charset::getRecommendedEncoding(encoding& enc) const {
{
// Special treatment for some charsets // Special treatment for some charsets
const string cset = utility::stringUtils::toLower(getName()); const string cset = utility::stringUtils::toLower(getName());
for (unsigned int i = 0 ; i < (sizeof(g_charsetEncodingMap) / sizeof(g_charsetEncodingMap[0])) - 1 ; ++i) for (unsigned int i = 0 ;
{ i < (sizeof(g_charsetEncodingMap) / sizeof(g_charsetEncodingMap[0])) - 1 ;
if (cset.find(g_charsetEncodingMap[i].charset) != string::npos) ++i) {
{
if (cset.find(g_charsetEncodingMap[i].charset) != string::npos) {
enc = g_charsetEncodingMap[i].encoding; enc = g_charsetEncodingMap[i].encoding;
return true; return true;
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -32,8 +32,7 @@
#include "vmime/component.hpp" #include "vmime/component.hpp"
namespace vmime namespace vmime {
{
class encoding; // forward reference class encoding; // forward reference
@ -41,9 +40,8 @@ class encoding; // forward reference
/** Charset description (basic type). /** Charset description (basic type).
*/ */
class VMIME_EXPORT charset : public component {
class VMIME_EXPORT charset : public component
{
public: public:
charset(); charset();
@ -102,9 +100,13 @@ public:
* @throws exceptions::charset_conv_error if an unexpected error occurred * @throws exceptions::charset_conv_error if an unexpected error occurred
* during the conversion * during the conversion
*/ */
static void convert(const string& in, string& out, static void convert(
const charset& source, const charset& dest, const string& in,
const charsetConverterOptions& opts = charsetConverterOptions()); string& out,
const charset& source,
const charset& dest,
const charsetConverterOptions& opts = charsetConverterOptions()
);
/** Convert the contents of an input stream in a specified charset /** Convert the contents of an input stream in a specified charset
* to another charset and write the result to an output stream. * to another charset and write the result to an output stream.
@ -121,9 +123,13 @@ public:
* @throws exceptions::charset_conv_error if an unexpected error occurred * @throws exceptions::charset_conv_error if an unexpected error occurred
* during the conversion * during the conversion
*/ */
static void convert(utility::inputStream& in, utility::outputStream& out, static void convert(
const charset& source, const charset& dest, utility::inputStream& in,
const charsetConverterOptions& opts = charsetConverterOptions()); utility::outputStream& out,
const charset& source,
const charset& dest,
const charsetConverterOptions& opts = charsetConverterOptions()
);
/** Checks whether the specified text is valid in this charset. /** Checks whether the specified text is valid in this charset.
* *
@ -147,18 +153,20 @@ private:
protected: protected:
// Component parsing & assembling // Component parsing & assembling
void parseImpl void parseImpl(
(const parsingContext& ctx, const parsingContext& ctx,
const string& buffer, const string& buffer,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
void generateImpl void generateImpl(
(const generationContext& ctx, const generationContext& ctx,
utility::outputStream& os, utility::outputStream& os,
const size_t curLinePos = 0, const size_t curLinePos = 0,
size_t* newLinePos = NULL) const; size_t* newLinePos = NULL
) const;
}; };

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -26,25 +26,26 @@
#include "vmime/charsetConverter_idna.hpp" #include "vmime/charsetConverter_idna.hpp"
namespace vmime namespace vmime {
{
// static // static
shared_ptr <charsetConverter> charsetConverter::create shared_ptr <charsetConverter> charsetConverter::create(
(const charset& source, const charset& dest, const charset& source,
const charsetConverterOptions& opts) const charset& dest,
{ const charsetConverterOptions& opts
if (source == "idna" || dest == "idna") ) {
if (source == "idna" || dest == "idna") {
return make_shared <charsetConverter_idna>(source, dest, opts); return make_shared <charsetConverter_idna>(source, dest, opts);
else } else {
return createGenericConverter(source, dest, opts); return createGenericConverter(source, dest, opts);
}
} }
charsetConverter::status::status() charsetConverter::status::status()
: inputBytesRead(0), outputBytesWritten(0) : inputBytesRead(0), outputBytesWritten(0) {
{
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -33,12 +33,10 @@
#include "vmime/utility/filteredStream.hpp" #include "vmime/utility/filteredStream.hpp"
namespace vmime namespace vmime {
{
namespace utility namespace utility {
{
/** A filtered output stream which applies a charset conversion /** A filtered output stream which applies a charset conversion
@ -52,9 +50,8 @@ namespace utility
* 'silentlyReplaceInvalidSequences' flag is set to false in * 'silentlyReplaceInvalidSequences' flag is set to false in
* the charsetConverterOptions. * the charsetConverterOptions.
*/ */
class VMIME_EXPORT charsetFilteredOutputStream : public filteredOutputStream {
class VMIME_EXPORT charsetFilteredOutputStream : public filteredOutputStream
{
}; };
@ -63,15 +60,14 @@ class VMIME_EXPORT charsetFilteredOutputStream : public filteredOutputStream
/** Convert between charsets. /** Convert between charsets.
*/ */
class VMIME_EXPORT charsetConverter : public object {
class VMIME_EXPORT charsetConverter : public object
{
public: public:
/** Holds information about a conversion. /** Holds information about a conversion.
*/ */
struct status struct status {
{
status(); status();
@ -91,9 +87,11 @@ public:
* @param dest output charset * @param dest output charset
* @param opts conversion options * @param opts conversion options
*/ */
static shared_ptr <charsetConverter> create static shared_ptr <charsetConverter> create(
(const charset& source, const charset& dest, const charset& source,
const charsetConverterOptions& opts = charsetConverterOptions()); const charset& dest,
const charsetConverterOptions& opts = charsetConverterOptions()
);
/** Convert a string buffer from one charset to another /** Convert a string buffer from one charset to another
* charset (in-memory conversion) * charset (in-memory conversion)
@ -128,7 +126,11 @@ public:
* @throws exceptions::charset_conv_error if an unexpected error occurred * @throws exceptions::charset_conv_error if an unexpected error occurred
* during the conversion * during the conversion
*/ */
virtual void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL) = 0; virtual void convert(
utility::inputStream& in,
utility::outputStream& out,
status* st = NULL
) = 0;
/** Returns a filtered output stream which applies a charset /** Returns a filtered output stream which applies a charset
* conversion to input bytes. Please note that it may not be * conversion to input bytes. Please note that it may not be
@ -138,15 +140,19 @@ public:
* @param opts conversion options * @param opts conversion options
* @return a filtered output stream, or NULL if not supported * @return a filtered output stream, or NULL if not supported
*/ */
virtual shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream virtual shared_ptr <utility::charsetFilteredOutputStream>
(utility::outputStream& os, getFilteredOutputStream(
const charsetConverterOptions& opts = charsetConverterOptions()) = 0; utility::outputStream& os,
const charsetConverterOptions& opts = charsetConverterOptions()
) = 0;
private: private:
static shared_ptr <charsetConverter> createGenericConverter static shared_ptr <charsetConverter> createGenericConverter(
(const charset& source, const charset& dest, const charset& source,
const charsetConverterOptions& opts); const charset& dest,
const charsetConverterOptions& opts
);
}; };

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -24,14 +24,13 @@
#include "vmime/charsetConverterOptions.hpp" #include "vmime/charsetConverterOptions.hpp"
namespace vmime namespace vmime {
{
charsetConverterOptions::charsetConverterOptions() charsetConverterOptions::charsetConverterOptions()
: silentlyReplaceInvalidSequences(true), : silentlyReplaceInvalidSequences(true),
invalidSequence("?") invalidSequence("?") {
{
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -28,15 +28,13 @@
#include "vmime/base.hpp" #include "vmime/base.hpp"
namespace vmime namespace vmime {
{
/** Options for charset conversion. /** Options for charset conversion.
*/ */
class VMIME_EXPORT charsetConverterOptions : public object {
class VMIME_EXPORT charsetConverterOptions : public object
{
public: public:
charsetConverterOptions(); charsetConverterOptions();

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -34,8 +34,8 @@
#include "vmime/utility/outputStreamStringAdapter.hpp" #include "vmime/utility/outputStreamStringAdapter.hpp"
extern "C" extern "C" {
{
#ifndef VMIME_BUILDING_DOC #ifndef VMIME_BUILDING_DOC
#include <iconv.h> #include <iconv.h>
@ -45,8 +45,8 @@ extern "C"
// second parameter may or may not be 'const'). This relies on the compiler // second parameter may or may not be 'const'). This relies on the compiler
// for choosing the right type. // for choosing the right type.
class ICONV_IN_TYPE class ICONV_IN_TYPE {
{
public: public:
ICONV_IN_TYPE(const char** ptr) : m_ptr(ptr) { } ICONV_IN_TYPE(const char** ptr) : m_ptr(ptr) { }
@ -62,8 +62,8 @@ extern "C"
const char** m_ptr; const char** m_ptr;
}; };
class ICONV_OUT_TYPE class ICONV_OUT_TYPE {
{
public: public:
ICONV_OUT_TYPE(char** ptr) : m_ptr(ptr) { } ICONV_OUT_TYPE(char** ptr) : m_ptr(ptr) { }
@ -85,9 +85,12 @@ extern "C"
// Output replacement char when an invalid sequence is encountered // Output replacement char when an invalid sequence is encountered
template <typename OUTPUT_CLASS, typename ICONV_DESC> template <typename OUTPUT_CLASS, typename ICONV_DESC>
void outputInvalidChar(OUTPUT_CLASS& out, ICONV_DESC cd, void outputInvalidChar(
const vmime::charsetConverterOptions& opts = vmime::charsetConverterOptions()) OUTPUT_CLASS& out,
{ ICONV_DESC cd,
const vmime::charsetConverterOptions& opts = vmime::charsetConverterOptions()
) {
const char* invalidCharIn = opts.invalidSequence.c_str(); const char* invalidCharIn = opts.invalidSequence.c_str();
vmime::size_t invalidCharInLen = opts.invalidSequence.length(); vmime::size_t invalidCharInLen = opts.invalidSequence.length();
@ -96,36 +99,43 @@ void outputInvalidChar(OUTPUT_CLASS& out, ICONV_DESC cd,
vmime::size_t invalidCharOutLen = 16; vmime::size_t invalidCharOutLen = 16;
if (iconv(cd, ICONV_IN_TYPE(&invalidCharIn), &invalidCharInLen, if (iconv(cd, ICONV_IN_TYPE(&invalidCharIn), &invalidCharInLen,
ICONV_OUT_TYPE(&invalidCharOutPtr), &invalidCharOutLen) != static_cast <size_t>(-1)) ICONV_OUT_TYPE(&invalidCharOutPtr), &invalidCharOutLen) != static_cast <size_t>(-1)) {
{
out.write(invalidCharOutBuffer, 16 - invalidCharOutLen); out.write(invalidCharOutBuffer, 16 - invalidCharOutLen);
} }
} }
namespace vmime namespace vmime {
{
// static // static
shared_ptr <charsetConverter> charsetConverter::createGenericConverter shared_ptr <charsetConverter> charsetConverter::createGenericConverter(
(const charset& source, const charset& dest, const charset& source,
const charsetConverterOptions& opts) const charset& dest,
{ const charsetConverterOptions& opts
) {
return make_shared <charsetConverter_iconv>(source, dest, opts); return make_shared <charsetConverter_iconv>(source, dest, opts);
} }
charsetConverter_iconv::charsetConverter_iconv charsetConverter_iconv::charsetConverter_iconv(
(const charset& source, const charset& dest, const charsetConverterOptions& opts) const charset& source,
: m_desc(NULL), m_source(source), m_dest(dest), m_options(opts) const charset& dest,
{ const charsetConverterOptions& opts
)
: m_desc(NULL),
m_source(source),
m_dest(dest),
m_options(opts) {
// Get an iconv descriptor // Get an iconv descriptor
const iconv_t cd = iconv_open(dest.getName().c_str(), source.getName().c_str()); const iconv_t cd = iconv_open(dest.getName().c_str(), source.getName().c_str());
if (cd != reinterpret_cast <iconv_t>(-1)) if (cd != reinterpret_cast <iconv_t>(-1)) {
{
iconv_t* p = new iconv_t; iconv_t* p = new iconv_t;
*p= cd; *p= cd;
@ -134,10 +144,10 @@ charsetConverter_iconv::charsetConverter_iconv
} }
charsetConverter_iconv::~charsetConverter_iconv() charsetConverter_iconv::~charsetConverter_iconv() {
{
if (m_desc != NULL) if (m_desc) {
{
// Close iconv handle // Close iconv handle
iconv_close(*static_cast <iconv_t*>(m_desc)); iconv_close(*static_cast <iconv_t*>(m_desc));
@ -147,14 +157,19 @@ charsetConverter_iconv::~charsetConverter_iconv()
} }
void charsetConverter_iconv::convert void charsetConverter_iconv::convert(
(utility::inputStream& in, utility::outputStream& out, status* st) utility::inputStream& in,
{ utility::outputStream& out,
if (st) status* st
new (st) status(); ) {
if (m_desc == NULL) if (st) {
new (st) status();
}
if (!m_desc) {
throw exceptions::charset_conv_error("Cannot initialize converter."); throw exceptions::charset_conv_error("Cannot initialize converter.");
}
const iconv_t cd = *static_cast <iconv_t*>(m_desc); const iconv_t cd = *static_cast <iconv_t*>(m_desc);
@ -165,8 +180,8 @@ void charsetConverter_iconv::convert
bool prevIsInvalid = false; bool prevIsInvalid = false;
bool breakAfterNext = false; bool breakAfterNext = false;
while (true) while (true) {
{
// Fullfill the buffer // Fullfill the buffer
size_t inLength = static_cast <size_t>(in.read(inBuffer + inPos, sizeof(inBuffer) - inPos) + inPos); size_t inLength = static_cast <size_t>(in.read(inBuffer + inPos, sizeof(inBuffer) - inPos) + inPos);
size_t outLength = sizeof(outBuffer); size_t outLength = sizeof(outBuffer);
@ -177,23 +192,23 @@ void charsetConverter_iconv::convert
// Convert input bytes // Convert input bytes
if (iconv(cd, ICONV_IN_TYPE(&inPtr), ptrLength, if (iconv(cd, ICONV_IN_TYPE(&inPtr), ptrLength,
ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast <size_t>(-1)) ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast <size_t>(-1)) {
{
if (st && inPtr) if (st && inPtr) {
{
st->inputBytesRead += (inPtr - inBuffer); st->inputBytesRead += (inPtr - inBuffer);
st->outputBytesWritten += (outPtr - outBuffer); st->outputBytesWritten += (outPtr - outBuffer);
} }
// Illegal input sequence or input sequence has no equivalent // Illegal input sequence or input sequence has no equivalent
// sequence in the destination charset. // sequence in the destination charset.
if (prevIsInvalid) if (prevIsInvalid) {
{
// Write successfully converted bytes // Write successfully converted bytes
out.write(outBuffer, sizeof(outBuffer) - outLength); out.write(outBuffer, sizeof(outBuffer) - outLength);
if (!m_options.silentlyReplaceInvalidSequences) if (!m_options.silentlyReplaceInvalidSequences) {
throw exceptions::illegal_byte_sequence_for_charset(); throw exceptions::illegal_byte_sequence_for_charset();
}
// Output a special character to indicate we don't known how to // Output a special character to indicate we don't known how to
// convert the sequence at this position // convert the sequence at this position
@ -202,9 +217,9 @@ void charsetConverter_iconv::convert
// Skip a byte and leave unconverted bytes in the input buffer // Skip a byte and leave unconverted bytes in the input buffer
std::copy(const_cast <byte_t*>(inPtr + 1), inBuffer + sizeof(inBuffer), inBuffer); std::copy(const_cast <byte_t*>(inPtr + 1), inBuffer + sizeof(inBuffer), inBuffer);
inPos = inLength - 1; inPos = inLength - 1;
}
else } else {
{
// Write successfully converted bytes // Write successfully converted bytes
out.write(outBuffer, sizeof(outBuffer) - outLength); out.write(outBuffer, sizeof(outBuffer) - outLength);
@ -212,17 +227,17 @@ void charsetConverter_iconv::convert
std::copy(const_cast <byte_t*>(inPtr), inBuffer + sizeof(inBuffer), inBuffer); std::copy(const_cast <byte_t*>(inPtr), inBuffer + sizeof(inBuffer), inBuffer);
inPos = inLength; inPos = inLength;
if (errno != E2BIG) if (errno != E2BIG) {
prevIsInvalid = true; prevIsInvalid = true;
}
} }
}
else } else {
{
// Write successfully converted bytes // Write successfully converted bytes
out.write(outBuffer, sizeof(outBuffer) - outLength); out.write(outBuffer, sizeof(outBuffer) - outLength);
if (st && inPtr) if (st && inPtr) {
{
st->inputBytesRead += (inPtr - inBuffer); st->inputBytesRead += (inPtr - inBuffer);
st->outputBytesWritten += (outPtr - outBuffer); st->outputBytesWritten += (outPtr - outBuffer);
} }
@ -231,20 +246,23 @@ void charsetConverter_iconv::convert
prevIsInvalid = false; prevIsInvalid = false;
} }
if (breakAfterNext) if (breakAfterNext) {
break; break;
}
// Check for end of data, loop again to flush stateful data from iconv // Check for end of data, loop again to flush stateful data from iconv
if (in.eof() && inPos == 0) if (in.eof() && inPos == 0) {
breakAfterNext = true; breakAfterNext = true;
}
} }
} }
void charsetConverter_iconv::convert(const string& in, string& out, status* st) void charsetConverter_iconv::convert(const string& in, string& out, status* st) {
{
if (st) if (st) {
new (st) status(); new (st) status();
}
out.clear(); out.clear();
@ -258,9 +276,11 @@ void charsetConverter_iconv::convert(const string& in, string& out, status* st)
shared_ptr <utility::charsetFilteredOutputStream> shared_ptr <utility::charsetFilteredOutputStream>
charsetConverter_iconv::getFilteredOutputStream charsetConverter_iconv::getFilteredOutputStream(
(utility::outputStream& os, const charsetConverterOptions& opts) utility::outputStream& os,
{ const charsetConverterOptions& opts
) {
return make_shared <utility::charsetFilteredOutputStream_iconv>(m_source, m_dest, &os, opts); return make_shared <utility::charsetFilteredOutputStream_iconv>(m_source, m_dest, &os, opts);
} }
@ -271,17 +291,23 @@ shared_ptr <utility::charsetFilteredOutputStream>
namespace utility { namespace utility {
charsetFilteredOutputStream_iconv::charsetFilteredOutputStream_iconv charsetFilteredOutputStream_iconv::charsetFilteredOutputStream_iconv(
(const charset& source, const charset& dest, outputStream* os, const charset& source,
const charsetConverterOptions& opts) const charset& dest, outputStream* os,
: m_desc(NULL), m_sourceCharset(source), m_destCharset(dest), const charsetConverterOptions& opts
m_stream(*os), m_unconvCount(0), m_options(opts) )
{ : m_desc(NULL),
m_sourceCharset(source),
m_destCharset(dest),
m_stream(*os),
m_unconvCount(0),
m_options(opts) {
// Get an iconv descriptor // Get an iconv descriptor
const iconv_t cd = iconv_open(dest.getName().c_str(), source.getName().c_str()); const iconv_t cd = iconv_open(dest.getName().c_str(), source.getName().c_str());
if (cd != reinterpret_cast <iconv_t>(-1)) if (cd != reinterpret_cast <iconv_t>(-1)) {
{
iconv_t* p = new iconv_t; iconv_t* p = new iconv_t;
*p= cd; *p= cd;
@ -290,10 +316,10 @@ charsetFilteredOutputStream_iconv::charsetFilteredOutputStream_iconv
} }
charsetFilteredOutputStream_iconv::~charsetFilteredOutputStream_iconv() charsetFilteredOutputStream_iconv::~charsetFilteredOutputStream_iconv() {
{
if (m_desc != NULL) if (m_desc) {
{
// Close iconv handle // Close iconv handle
iconv_close(*static_cast <iconv_t*>(m_desc)); iconv_close(*static_cast <iconv_t*>(m_desc));
@ -303,17 +329,20 @@ charsetFilteredOutputStream_iconv::~charsetFilteredOutputStream_iconv()
} }
outputStream& charsetFilteredOutputStream_iconv::getNextOutputStream() outputStream& charsetFilteredOutputStream_iconv::getNextOutputStream() {
{
return m_stream; return m_stream;
} }
void charsetFilteredOutputStream_iconv::writeImpl void charsetFilteredOutputStream_iconv::writeImpl(
(const byte_t* const data, const size_t count) const byte_t* const data,
{ const size_t count
if (m_desc == NULL) ) {
if (!m_desc) {
throw exceptions::charset_conv_error("Cannot initialize converter."); throw exceptions::charset_conv_error("Cannot initialize converter.");
}
const iconv_t cd = *static_cast <iconv_t*>(m_desc); const iconv_t cd = *static_cast <iconv_t*>(m_desc);
@ -322,23 +351,26 @@ void charsetFilteredOutputStream_iconv::writeImpl
// If there is some unconverted bytes left, add more data from this // If there is some unconverted bytes left, add more data from this
// chunk to see if it can now be converted. // chunk to see if it can now be converted.
while (m_unconvCount != 0 || curDataLen != 0) while (m_unconvCount != 0 || curDataLen != 0) {
{
if (m_unconvCount != 0) if (m_unconvCount != 0) {
{
// Check if an incomplete input sequence is larger than the // Check if an incomplete input sequence is larger than the
// input buffer size: should not happen except if something // input buffer size: should not happen except if something
// in the input sequence is invalid. If so, output a special // in the input sequence is invalid. If so, output a special
// character and skip one byte in the invalid sequence. // character and skip one byte in the invalid sequence.
if (m_unconvCount >= sizeof(m_unconvBuffer)) if (m_unconvCount >= sizeof(m_unconvBuffer)) {
{
if (!m_options.silentlyReplaceInvalidSequences) if (!m_options.silentlyReplaceInvalidSequences) {
throw exceptions::illegal_byte_sequence_for_charset(); throw exceptions::illegal_byte_sequence_for_charset();
}
outputInvalidChar(m_stream, cd); outputInvalidChar(m_stream, cd);
std::copy(m_unconvBuffer + 1, std::copy(
m_unconvBuffer + m_unconvCount, m_unconvBuffer); m_unconvBuffer + 1,
m_unconvBuffer + m_unconvCount, m_unconvBuffer
);
m_unconvCount--; m_unconvCount--;
} }
@ -365,16 +397,18 @@ void charsetFilteredOutputStream_iconv::writeImpl
const size_t inLength0 = inLength; const size_t inLength0 = inLength;
if (iconv(cd, ICONV_IN_TYPE(&inPtr), &inLength, if (iconv(cd, ICONV_IN_TYPE(&inPtr), &inLength,
ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast <size_t>(-1)) ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast <size_t>(-1)) {
{
const size_t inputConverted = inLength0 - inLength; const size_t inputConverted = inLength0 - inLength;
// Write successfully converted bytes // Write successfully converted bytes
m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength); m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
// Shift unconverted bytes // Shift unconverted bytes
std::copy(m_unconvBuffer + inputConverted, std::copy(
m_unconvBuffer + m_unconvCount, m_unconvBuffer); m_unconvBuffer + inputConverted,
m_unconvBuffer + m_unconvCount, m_unconvBuffer
);
m_unconvCount -= inputConverted; m_unconvCount -= inputConverted;
@ -388,8 +422,9 @@ void charsetFilteredOutputStream_iconv::writeImpl
m_unconvCount = 0; m_unconvCount = 0;
} }
if (curDataLen == 0) if (curDataLen == 0) {
return; // no more data return; // no more data
}
// Now, convert the current data buffer // Now, convert the current data buffer
const byte_t* inPtr = curData; const byte_t* inPtr = curData;
@ -400,8 +435,8 @@ void charsetFilteredOutputStream_iconv::writeImpl
const size_t inLength0 = inLength; const size_t inLength0 = inLength;
if (iconv(cd, ICONV_IN_TYPE(&inPtr), &inLength, if (iconv(cd, ICONV_IN_TYPE(&inPtr), &inLength,
ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast <size_t>(-1)) ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast <size_t>(-1)) {
{
// Write successfully converted bytes // Write successfully converted bytes
m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength); m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
@ -412,17 +447,17 @@ void charsetFilteredOutputStream_iconv::writeImpl
// Put one byte byte into the unconverted buffer so // Put one byte byte into the unconverted buffer so
// that the next iteration fill it // that the next iteration fill it
if (curDataLen != 0) if (curDataLen != 0) {
{
m_unconvCount = 1; m_unconvCount = 1;
m_unconvBuffer[0] = *curData; m_unconvBuffer[0] = *curData;
curData++; curData++;
curDataLen--; curDataLen--;
} }
}
else } else {
{
// Write successfully converted bytes // Write successfully converted bytes
m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength); m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
@ -433,18 +468,19 @@ void charsetFilteredOutputStream_iconv::writeImpl
} }
void charsetFilteredOutputStream_iconv::flush() void charsetFilteredOutputStream_iconv::flush() {
{
if (m_desc == NULL) if (!m_desc) {
throw exceptions::charset_conv_error("Cannot initialize converter."); throw exceptions::charset_conv_error("Cannot initialize converter.");
}
const iconv_t cd = *static_cast <iconv_t*>(m_desc); const iconv_t cd = *static_cast <iconv_t*>(m_desc);
size_t offset = 0; size_t offset = 0;
// Process unconverted bytes // Process unconverted bytes
while (m_unconvCount != 0) while (m_unconvCount != 0) {
{
// Try a conversion // Try a conversion
const byte_t* inPtr = m_unconvBuffer + offset; const byte_t* inPtr = m_unconvBuffer + offset;
size_t inLength = m_unconvCount; size_t inLength = m_unconvCount;
@ -453,32 +489,34 @@ void charsetFilteredOutputStream_iconv::flush()
const size_t inLength0 = inLength; const size_t inLength0 = inLength;
if (iconv(cd, ICONV_IN_TYPE(&inPtr), &inLength, ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast <size_t>(-1)) if (iconv(cd, ICONV_IN_TYPE(&inPtr), &inLength,
{ ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast <size_t>(-1)) {
const size_t inputConverted = inLength0 - inLength; const size_t inputConverted = inLength0 - inLength;
// Skip a "blocking" character // Skip a "blocking" character
if (inputConverted == 0) if (inputConverted == 0) {
{
if (!m_options.silentlyReplaceInvalidSequences) if (!m_options.silentlyReplaceInvalidSequences) {
throw exceptions::illegal_byte_sequence_for_charset(); throw exceptions::illegal_byte_sequence_for_charset();
}
outputInvalidChar(m_stream, cd); outputInvalidChar(m_stream, cd);
offset++; offset++;
m_unconvCount--; m_unconvCount--;
}
else } else {
{
// Write successfully converted bytes // Write successfully converted bytes
m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength); m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
offset += inputConverted; offset += inputConverted;
m_unconvCount -= inputConverted; m_unconvCount -= inputConverted;
} }
}
else } else {
{
// Write successfully converted bytes // Write successfully converted bytes
m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength); m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -34,15 +34,13 @@
#include "vmime/charsetConverter.hpp" #include "vmime/charsetConverter.hpp"
namespace vmime namespace vmime {
{
/** A generic charset converter which uses iconv library. /** A generic charset converter which uses iconv library.
*/ */
class charsetConverter_iconv : public charsetConverter {
class charsetConverter_iconv : public charsetConverter
{
public: public:
/** Construct and initialize an iconv charset converter. /** Construct and initialize an iconv charset converter.
@ -51,17 +49,21 @@ public:
* @param dest output charset * @param dest output charset
* @param opts conversion options * @param opts conversion options
*/ */
charsetConverter_iconv(const charset& source, const charset& dest, charsetConverter_iconv(
const charsetConverterOptions& opts = charsetConverterOptions()); const charset& source,
const charset& dest,
const charsetConverterOptions& opts = charsetConverterOptions()
);
~charsetConverter_iconv(); ~charsetConverter_iconv();
void convert(const string& in, string& out, status* st = NULL); void convert(const string& in, string& out, status* st = NULL);
void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL); void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL);
shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream(
(utility::outputStream& os, utility::outputStream& os,
const charsetConverterOptions& opts = charsetConverterOptions()); const charsetConverterOptions& opts = charsetConverterOptions()
);
private: private:
@ -77,8 +79,8 @@ private:
namespace utility { namespace utility {
class charsetFilteredOutputStream_iconv : public charsetFilteredOutputStream class charsetFilteredOutputStream_iconv : public charsetFilteredOutputStream {
{
public: public:
/** Construct a new filter for the specified output stream. /** Construct a new filter for the specified output stream.
@ -88,9 +90,11 @@ public:
* @param os stream into which write filtered data * @param os stream into which write filtered data
* @param opts conversion options * @param opts conversion options
*/ */
charsetFilteredOutputStream_iconv charsetFilteredOutputStream_iconv(
(const charset& source, const charset& dest, outputStream* os, const charset& source,
const charsetConverterOptions& opts = charsetConverterOptions()); const charset& dest, outputStream* os,
const charsetConverterOptions& opts = charsetConverterOptions()
);
~charsetFilteredOutputStream_iconv(); ~charsetFilteredOutputStream_iconv();

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -34,8 +34,8 @@
#include "vmime/utility/outputStreamStringAdapter.hpp" #include "vmime/utility/outputStreamStringAdapter.hpp"
extern "C" extern "C" {
{
#ifndef VMIME_BUILDING_DOC #ifndef VMIME_BUILDING_DOC
#include <unicode/ucnv.h> #include <unicode/ucnv.h>
@ -48,59 +48,75 @@ extern "C"
#include <unicode/unistr.h> #include <unicode/unistr.h>
namespace vmime namespace vmime {
{
// static // static
shared_ptr <charsetConverter> charsetConverter::createGenericConverter shared_ptr <charsetConverter> charsetConverter::createGenericConverter(
(const charset& source, const charset& dest, const charset& source,
const charsetConverterOptions& opts) const charset& dest,
{ const charsetConverterOptions& opts
) {
return make_shared <charsetConverter_icu>(source, dest, opts); return make_shared <charsetConverter_icu>(source, dest, opts);
} }
charsetConverter_icu::charsetConverter_icu charsetConverter_icu::charsetConverter_icu(
(const charset& source, const charset& dest, const charsetConverterOptions& opts) const charset& source,
: m_from(NULL), m_to(NULL), m_source(source), m_dest(dest), m_options(opts) const charset& dest,
{ const charsetConverterOptions& opts
)
: m_from(NULL),
m_to(NULL),
m_source(source),
m_dest(dest),
m_options(opts) {
UErrorCode err = U_ZERO_ERROR; UErrorCode err = U_ZERO_ERROR;
m_from = ucnv_open(source.getName().c_str(), &err); m_from = ucnv_open(source.getName().c_str(), &err);
if (!U_SUCCESS(err)) if (!U_SUCCESS(err)) {
{
throw exceptions::charset_conv_error throw exceptions::charset_conv_error(
("Cannot initialize ICU converter for source charset '" + source.getName() + "' (error code: " + u_errorName(err) + "."); "Cannot initialize ICU converter for source charset '" + source.getName()
+ "' (error code: " + u_errorName(err) + "."
);
} }
m_to = ucnv_open(dest.getName().c_str(), &err); m_to = ucnv_open(dest.getName().c_str(), &err);
if (!U_SUCCESS(err)) if (!U_SUCCESS(err)) {
{
throw exceptions::charset_conv_error throw exceptions::charset_conv_error(
("Cannot initialize ICU converter for destination charset '" + dest.getName() + "' (error code: " + u_errorName(err) + "."); "Cannot initialize ICU converter for destination charset '" + dest.getName()
+ "' (error code: " + u_errorName(err) + "."
);
} }
} }
charsetConverter_icu::~charsetConverter_icu() charsetConverter_icu::~charsetConverter_icu() {
{
if (m_from) ucnv_close(m_from); if (m_from) ucnv_close(m_from);
if (m_to) ucnv_close(m_to); if (m_to) ucnv_close(m_to);
} }
void charsetConverter_icu::convert void charsetConverter_icu::convert(
(utility::inputStream& in, utility::outputStream& out, status* st) utility::inputStream& in,
{ utility::outputStream& out,
status* st
) {
UErrorCode err = U_ZERO_ERROR; UErrorCode err = U_ZERO_ERROR;
ucnv_reset(m_from); ucnv_reset(m_from);
ucnv_reset(m_to); ucnv_reset(m_to);
if (st) if (st) {
new (st) status(); new (st) status();
}
// From buffers // From buffers
byte_t cpInBuffer[16]; // stream data put here byte_t cpInBuffer[16]; // stream data put here
@ -113,34 +129,39 @@ void charsetConverter_icu::convert
std::vector <char> cpOutBuffer(cpOutBufferSz); std::vector <char> cpOutBuffer(cpOutBufferSz);
// Tell ICU what to do when encountering an illegal byte sequence // Tell ICU what to do when encountering an illegal byte sequence
if (m_options.silentlyReplaceInvalidSequences) if (m_options.silentlyReplaceInvalidSequences) {
{
// Set replacement chars for when converting from Unicode to codepage // Set replacement chars for when converting from Unicode to codepage
icu::UnicodeString substString(m_options.invalidSequence.c_str()); icu::UnicodeString substString(m_options.invalidSequence.c_str());
ucnv_setSubstString(m_to, substString.getTerminatedBuffer(), -1, &err); ucnv_setSubstString(m_to, substString.getTerminatedBuffer(), -1, &err);
if (U_FAILURE(err)) if (U_FAILURE(err)) {
throw exceptions::charset_conv_error("[ICU] Error when setting substitution string."); throw exceptions::charset_conv_error("[ICU] Error when setting substitution string.");
} }
else
{ } else {
// Tell ICU top stop (and return an error) on illegal byte sequences // Tell ICU top stop (and return an error) on illegal byte sequences
ucnv_setToUCallBack ucnv_setToUCallBack(
(m_from, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err); m_from, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err
);
if (U_FAILURE(err)) if (U_FAILURE(err)) {
throw exceptions::charset_conv_error("[ICU] Error when setting ToU callback."); throw exceptions::charset_conv_error("[ICU] Error when setting ToU callback.");
}
ucnv_setFromUCallBack ucnv_setFromUCallBack(
(m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err); m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err
);
if (U_FAILURE(err)) if (U_FAILURE(err)) {
throw exceptions::charset_conv_error("[ICU] Error when setting FromU callback."); throw exceptions::charset_conv_error("[ICU] Error when setting FromU callback.");
}
} }
// Input data available // Input data available
while (!in.eof()) while (!in.eof()) {
{
// Read input data into buffer // Read input data into buffer
size_t inLength = in.read(cpInBuffer, sizeof(cpInBuffer)); size_t inLength = in.read(cpInBuffer, sizeof(cpInBuffer));
@ -153,30 +174,36 @@ void charsetConverter_icu::convert
UErrorCode toErr; UErrorCode toErr;
// Loop until all source has been processed // Loop until all source has been processed
do do {
{
// Set up target pointers // Set up target pointers
UChar* target = &uOutBuffer[0]; UChar* target = &uOutBuffer[0];
UChar* targetLimit = &target[0] + outSize; UChar* targetLimit = &target[0] + outSize;
toErr = U_ZERO_ERROR; toErr = U_ZERO_ERROR;
ucnv_toUnicode(m_from, &target, targetLimit,
&source, sourceLimit, NULL, flush, &toErr);
if (st) ucnv_toUnicode(
m_from, &target, targetLimit,
&source, sourceLimit, NULL, flush, &toErr
);
if (st) {
st->inputBytesRead += (source - reinterpret_cast <const char*>(&cpInBuffer[0])); st->inputBytesRead += (source - reinterpret_cast <const char*>(&cpInBuffer[0]));
}
if (toErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(toErr)) {
if (toErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(toErr))
{
if (toErr == U_INVALID_CHAR_FOUND || if (toErr == U_INVALID_CHAR_FOUND ||
toErr == U_TRUNCATED_CHAR_FOUND || toErr == U_TRUNCATED_CHAR_FOUND ||
toErr == U_ILLEGAL_CHAR_FOUND) toErr == U_ILLEGAL_CHAR_FOUND) {
{
// Error will be thrown later (*) // Error will be thrown later (*)
}
else } else {
{
throw exceptions::charset_conv_error("[ICU] Error converting to Unicode from " + m_source.getName()); throw exceptions::charset_conv_error(
"[ICU] Error converting to Unicode from " + m_source.getName()
);
} }
} }
@ -187,19 +214,21 @@ void charsetConverter_icu::convert
UErrorCode fromErr; UErrorCode fromErr;
// Loop until converted chars are fully written // Loop until converted chars are fully written
do do {
{
char* cpTarget = &cpOutBuffer[0]; char* cpTarget = &cpOutBuffer[0];
const char* cpTargetLimit = &cpOutBuffer[0] + cpOutBufferSz; const char* cpTargetLimit = &cpOutBuffer[0] + cpOutBufferSz;
fromErr = U_ZERO_ERROR; fromErr = U_ZERO_ERROR;
// Write converted bytes (Unicode) to destination codepage // Write converted bytes (Unicode) to destination codepage
ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit, ucnv_fromUnicode(
&uSource, uSourceLimit, NULL, flush, &fromErr); m_to, &cpTarget, cpTargetLimit,
&uSource, uSourceLimit, NULL, flush, &fromErr
);
if (st) {
if (st)
{
// Decrement input bytes count by the number of input bytes in error // Decrement input bytes count by the number of input bytes in error
char errBytes[16]; char errBytes[16];
int8_t errBytesLen = sizeof(errBytes); int8_t errBytesLen = sizeof(errBytes);
@ -214,22 +243,24 @@ void charsetConverter_icu::convert
// (*) If an error occurred while converting from input charset, throw it now // (*) If an error occurred while converting from input charset, throw it now
if (toErr == U_INVALID_CHAR_FOUND || if (toErr == U_INVALID_CHAR_FOUND ||
toErr == U_TRUNCATED_CHAR_FOUND || toErr == U_TRUNCATED_CHAR_FOUND ||
toErr == U_ILLEGAL_CHAR_FOUND) toErr == U_ILLEGAL_CHAR_FOUND) {
{
throw exceptions::illegal_byte_sequence_for_charset(); throw exceptions::illegal_byte_sequence_for_charset();
} }
if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) {
{
if (fromErr == U_INVALID_CHAR_FOUND || if (fromErr == U_INVALID_CHAR_FOUND ||
fromErr == U_TRUNCATED_CHAR_FOUND || fromErr == U_TRUNCATED_CHAR_FOUND ||
fromErr == U_ILLEGAL_CHAR_FOUND) fromErr == U_ILLEGAL_CHAR_FOUND) {
{
throw exceptions::illegal_byte_sequence_for_charset(); throw exceptions::illegal_byte_sequence_for_charset();
}
else } else {
{
throw exceptions::charset_conv_error("[ICU] Error converting from Unicode to " + m_dest.getName()); throw exceptions::charset_conv_error(
"[ICU] Error converting from Unicode to " + m_dest.getName()
);
} }
} }
@ -243,10 +274,11 @@ void charsetConverter_icu::convert
} }
void charsetConverter_icu::convert(const string& in, string& out, status* st) void charsetConverter_icu::convert(const string& in, string& out, status* st) {
{
if (st) if (st) {
new (st) status(); new (st) status();
}
out.clear(); out.clear();
@ -260,9 +292,11 @@ void charsetConverter_icu::convert(const string& in, string& out, status* st)
shared_ptr <utility::charsetFilteredOutputStream> shared_ptr <utility::charsetFilteredOutputStream>
charsetConverter_icu::getFilteredOutputStream charsetConverter_icu::getFilteredOutputStream(
(utility::outputStream& os, const charsetConverterOptions& opts) utility::outputStream& os,
{ const charsetConverterOptions& opts
) {
return make_shared <utility::charsetFilteredOutputStream_icu>(m_source, m_dest, &os, opts); return make_shared <utility::charsetFilteredOutputStream_icu>(m_source, m_dest, &os, opts);
} }
@ -273,75 +307,94 @@ shared_ptr <utility::charsetFilteredOutputStream>
namespace utility { namespace utility {
charsetFilteredOutputStream_icu::charsetFilteredOutputStream_icu charsetFilteredOutputStream_icu::charsetFilteredOutputStream_icu(
(const charset& source, const charset& dest, outputStream* os, const charset& source,
const charsetConverterOptions& opts) const charset& dest,
: m_from(NULL), m_to(NULL), m_sourceCharset(source), outputStream* os,
m_destCharset(dest), m_stream(*os), m_options(opts) const charsetConverterOptions& opts
{ )
: m_from(NULL),
m_to(NULL),
m_sourceCharset(source),
m_destCharset(dest),
m_stream(*os),
m_options(opts) {
UErrorCode err = U_ZERO_ERROR; UErrorCode err = U_ZERO_ERROR;
m_from = ucnv_open(source.getName().c_str(), &err); m_from = ucnv_open(source.getName().c_str(), &err);
if (!U_SUCCESS(err)) if (!U_SUCCESS(err)) {
{
throw exceptions::charset_conv_error throw exceptions::charset_conv_error(
("Cannot initialize ICU converter for source charset '" + source.getName() + "' (error code: " + u_errorName(err) + "."); "Cannot initialize ICU converter for source charset '" + source.getName()
+ "' (error code: " + u_errorName(err) + "."
);
} }
m_to = ucnv_open(dest.getName().c_str(), &err); m_to = ucnv_open(dest.getName().c_str(), &err);
if (!U_SUCCESS(err)) if (!U_SUCCESS(err)) {
{
throw exceptions::charset_conv_error throw exceptions::charset_conv_error(
("Cannot initialize ICU converter for destination charset '" + dest.getName() + "' (error code: " + u_errorName(err) + "."); "Cannot initialize ICU converter for destination charset '" + dest.getName()
+ "' (error code: " + u_errorName(err) + "."
);
} }
// Tell ICU what to do when encountering an illegal byte sequence // Tell ICU what to do when encountering an illegal byte sequence
if (m_options.silentlyReplaceInvalidSequences) if (m_options.silentlyReplaceInvalidSequences) {
{
// Set replacement chars for when converting from Unicode to codepage // Set replacement chars for when converting from Unicode to codepage
icu::UnicodeString substString(m_options.invalidSequence.c_str()); icu::UnicodeString substString(m_options.invalidSequence.c_str());
ucnv_setSubstString(m_to, substString.getTerminatedBuffer(), -1, &err); ucnv_setSubstString(m_to, substString.getTerminatedBuffer(), -1, &err);
if (U_FAILURE(err)) if (U_FAILURE(err)) {
throw exceptions::charset_conv_error("[ICU] Error when setting substitution string."); throw exceptions::charset_conv_error("[ICU] Error when setting substitution string.");
} }
else
{ } else {
// Tell ICU top stop (and return an error) on illegal byte sequences // Tell ICU top stop (and return an error) on illegal byte sequences
ucnv_setToUCallBack ucnv_setToUCallBack(
(m_to, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err); m_to, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err
);
if (U_FAILURE(err)) if (U_FAILURE(err)) {
throw exceptions::charset_conv_error("[ICU] Error when setting ToU callback."); throw exceptions::charset_conv_error("[ICU] Error when setting ToU callback.");
}
ucnv_setFromUCallBack ucnv_setFromUCallBack(
(m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err); m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err
);
if (U_FAILURE(err)) if (U_FAILURE(err)) {
throw exceptions::charset_conv_error("[ICU] Error when setting FromU callback."); throw exceptions::charset_conv_error("[ICU] Error when setting FromU callback.");
}
} }
} }
charsetFilteredOutputStream_icu::~charsetFilteredOutputStream_icu() charsetFilteredOutputStream_icu::~charsetFilteredOutputStream_icu() {
{
if (m_from) ucnv_close(m_from); if (m_from) ucnv_close(m_from);
if (m_to) ucnv_close(m_to); if (m_to) ucnv_close(m_to);
} }
outputStream& charsetFilteredOutputStream_icu::getNextOutputStream() outputStream& charsetFilteredOutputStream_icu::getNextOutputStream() {
{
return m_stream; return m_stream;
} }
void charsetFilteredOutputStream_icu::writeImpl void charsetFilteredOutputStream_icu::writeImpl(
(const byte_t* const data, const size_t count) const byte_t* const data,
{ const size_t count
if (m_from == NULL || m_to == NULL) ) {
if (!m_from || !m_to) {
throw exceptions::charset_conv_error("Cannot initialize converters."); throw exceptions::charset_conv_error("Cannot initialize converters.");
}
// Allocate buffer for Unicode chars // Allocate buffer for Unicode chars
const size_t uniSize = ucnv_getMinCharSize(m_from) * count * sizeof(UChar); const size_t uniSize = ucnv_getMinCharSize(m_from) * count * sizeof(UChar);
@ -353,29 +406,32 @@ void charsetFilteredOutputStream_icu::writeImpl
const char* uniSource = reinterpret_cast <const char*>(data); const char* uniSource = reinterpret_cast <const char*>(data);
const char* uniSourceLimit = uniSource + count; const char* uniSourceLimit = uniSource + count;
do do {
{
// Convert from source charset to Unicode // Convert from source charset to Unicode
UChar* uniTarget = &uniBuffer[0]; UChar* uniTarget = &uniBuffer[0];
UChar* uniTargetLimit = &uniBuffer[0] + uniSize; UChar* uniTargetLimit = &uniBuffer[0] + uniSize;
toErr = U_ZERO_ERROR; toErr = U_ZERO_ERROR;
ucnv_toUnicode(m_from, &uniTarget, uniTargetLimit, ucnv_toUnicode(
&uniSource, uniSourceLimit, NULL, /* flush */ FALSE, &toErr); m_from, &uniTarget, uniTargetLimit,
&uniSource, uniSourceLimit, NULL, /* flush */ FALSE, &toErr
);
if (U_FAILURE(toErr) && toErr != U_BUFFER_OVERFLOW_ERROR) {
if (U_FAILURE(toErr) && toErr != U_BUFFER_OVERFLOW_ERROR)
{
if (toErr == U_INVALID_CHAR_FOUND || if (toErr == U_INVALID_CHAR_FOUND ||
toErr == U_TRUNCATED_CHAR_FOUND || toErr == U_TRUNCATED_CHAR_FOUND ||
toErr == U_ILLEGAL_CHAR_FOUND) toErr == U_ILLEGAL_CHAR_FOUND) {
{
throw exceptions::illegal_byte_sequence_for_charset(); throw exceptions::illegal_byte_sequence_for_charset();
}
else } else {
{
throw exceptions::charset_conv_error throw exceptions::charset_conv_error(
("[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'."); "[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'."
);
} }
} }
@ -391,28 +447,31 @@ void charsetFilteredOutputStream_icu::writeImpl
const UChar* cpSource = &uniBuffer[0]; const UChar* cpSource = &uniBuffer[0];
const UChar* cpSourceLimit = &uniBuffer[0] + uniLength; const UChar* cpSourceLimit = &uniBuffer[0] + uniLength;
do do {
{
char* cpTarget = &cpBuffer[0]; char* cpTarget = &cpBuffer[0];
char* cpTargetLimit = &cpBuffer[0] + cpSize; char* cpTargetLimit = &cpBuffer[0] + cpSize;
fromErr = U_ZERO_ERROR; fromErr = U_ZERO_ERROR;
ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit, ucnv_fromUnicode(
&cpSource, cpSourceLimit, NULL, /* flush */ FALSE, &fromErr); m_to, &cpTarget, cpTargetLimit,
&cpSource, cpSourceLimit, NULL, /* flush */ FALSE, &fromErr
);
if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) {
if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr))
{
if (fromErr == U_INVALID_CHAR_FOUND || if (fromErr == U_INVALID_CHAR_FOUND ||
fromErr == U_TRUNCATED_CHAR_FOUND || fromErr == U_TRUNCATED_CHAR_FOUND ||
fromErr == U_ILLEGAL_CHAR_FOUND) fromErr == U_ILLEGAL_CHAR_FOUND) {
{
throw exceptions::illegal_byte_sequence_for_charset(); throw exceptions::illegal_byte_sequence_for_charset();
}
else } else {
{
throw exceptions::charset_conv_error throw exceptions::charset_conv_error(
("[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'."); "[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'."
);
} }
} }
@ -427,10 +486,11 @@ void charsetFilteredOutputStream_icu::writeImpl
} }
void charsetFilteredOutputStream_icu::flush() void charsetFilteredOutputStream_icu::flush() {
{
if (m_from == NULL || m_to == NULL) if (!m_from || !m_to) {
throw exceptions::charset_conv_error("Cannot initialize converters."); throw exceptions::charset_conv_error("Cannot initialize converters.");
}
// Allocate buffer for Unicode chars // Allocate buffer for Unicode chars
const size_t uniSize = ucnv_getMinCharSize(m_from) * 1024 * sizeof(UChar); const size_t uniSize = ucnv_getMinCharSize(m_from) * 1024 * sizeof(UChar);
@ -442,21 +502,24 @@ void charsetFilteredOutputStream_icu::flush()
const char* uniSource = 0; const char* uniSource = 0;
const char* uniSourceLimit = 0; const char* uniSourceLimit = 0;
do do {
{
// Convert from source charset to Unicode // Convert from source charset to Unicode
UChar* uniTarget = &uniBuffer[0]; UChar* uniTarget = &uniBuffer[0];
UChar* uniTargetLimit = &uniBuffer[0] + uniSize; UChar* uniTargetLimit = &uniBuffer[0] + uniSize;
toErr = U_ZERO_ERROR; toErr = U_ZERO_ERROR;
ucnv_toUnicode(m_from, &uniTarget, uniTargetLimit, ucnv_toUnicode(
&uniSource, uniSourceLimit, NULL, /* flush */ TRUE, &toErr); m_from, &uniTarget, uniTargetLimit,
&uniSource, uniSourceLimit, NULL, /* flush */ TRUE, &toErr
);
if (U_FAILURE(toErr) && toErr != U_BUFFER_OVERFLOW_ERROR) if (U_FAILURE(toErr) && toErr != U_BUFFER_OVERFLOW_ERROR) {
{
throw exceptions::charset_conv_error throw exceptions::charset_conv_error(
("[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'."); "[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'."
);
} }
const size_t uniLength = uniTarget - &uniBuffer[0]; const size_t uniLength = uniTarget - &uniBuffer[0];
@ -471,20 +534,23 @@ void charsetFilteredOutputStream_icu::flush()
const UChar* cpSource = &uniBuffer[0]; const UChar* cpSource = &uniBuffer[0];
const UChar* cpSourceLimit = &uniBuffer[0] + uniLength; const UChar* cpSourceLimit = &uniBuffer[0] + uniLength;
do do {
{
char* cpTarget = &cpBuffer[0]; char* cpTarget = &cpBuffer[0];
char* cpTargetLimit = &cpBuffer[0] + cpSize; char* cpTargetLimit = &cpBuffer[0] + cpSize;
fromErr = U_ZERO_ERROR; fromErr = U_ZERO_ERROR;
ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit, ucnv_fromUnicode(
&cpSource, cpSourceLimit, NULL, /* flush */ TRUE, &fromErr); m_to, &cpTarget, cpTargetLimit,
&cpSource, cpSourceLimit, NULL, /* flush */ TRUE, &fromErr
);
if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) {
{
throw exceptions::charset_conv_error throw exceptions::charset_conv_error(
("[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'."); "[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'."
);
} }
const size_t cpLength = cpTarget - &cpBuffer[0]; const size_t cpLength = cpTarget - &cpBuffer[0];

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -37,15 +37,13 @@
struct UConverter; struct UConverter;
namespace vmime namespace vmime {
{
/** A generic charset converter which uses ICU library. /** A generic charset converter which uses ICU library.
*/ */
class charsetConverter_icu : public charsetConverter {
class charsetConverter_icu : public charsetConverter
{
public: public:
/** Construct and initialize an ICU charset converter. /** Construct and initialize an ICU charset converter.
@ -54,17 +52,21 @@ public:
* @param dest output charset * @param dest output charset
* @param opts conversion options * @param opts conversion options
*/ */
charsetConverter_icu(const charset& source, const charset& dest, charsetConverter_icu(
const charsetConverterOptions& opts = charsetConverterOptions()); const charset& source,
const charset& dest,
const charsetConverterOptions& opts = charsetConverterOptions()
);
~charsetConverter_icu(); ~charsetConverter_icu();
void convert(const string& in, string& out, status* st = NULL); void convert(const string& in, string& out, status* st = NULL);
void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL); void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL);
shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream(
(utility::outputStream& os, utility::outputStream& os,
const charsetConverterOptions& opts = charsetConverterOptions()); const charsetConverterOptions& opts = charsetConverterOptions()
);
private: private:
@ -81,8 +83,8 @@ private:
namespace utility { namespace utility {
class charsetFilteredOutputStream_icu : public charsetFilteredOutputStream class charsetFilteredOutputStream_icu : public charsetFilteredOutputStream {
{
public: public:
/** Construct a new filter for the specified output stream. /** Construct a new filter for the specified output stream.
@ -92,9 +94,12 @@ public:
* @param os stream into which write filtered data * @param os stream into which write filtered data
* @param opts conversion options * @param opts conversion options
*/ */
charsetFilteredOutputStream_icu charsetFilteredOutputStream_icu(
(const charset& source, const charset& dest, outputStream* os, const charset& source,
const charsetConverterOptions& opts = charsetConverterOptions()); const charset& dest,
outputStream* os,
const charsetConverterOptions& opts = charsetConverterOptions()
);
~charsetFilteredOutputStream_icu(); ~charsetFilteredOutputStream_icu();

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -30,8 +30,7 @@
#include "vmime/utility/outputStreamStringAdapter.hpp" #include "vmime/utility/outputStreamStringAdapter.hpp"
extern "C" extern "C" {
{
#include "contrib/punycode/punycode.h" #include "contrib/punycode/punycode.h"
#include "contrib/punycode/punycode.c" #include "contrib/punycode/punycode.c"
@ -41,26 +40,31 @@ extern "C"
#include "contrib/utf8/utf8.h" #include "contrib/utf8/utf8.h"
namespace vmime namespace vmime {
{
charsetConverter_idna::charsetConverter_idna charsetConverter_idna::charsetConverter_idna(
(const charset& source, const charset& dest, const charsetConverterOptions& opts) const charset& source,
: m_source(source), m_dest(dest), m_options(opts) const charset& dest,
{ const charsetConverterOptions& opts
)
: m_source(source),
m_dest(dest),
m_options(opts) {
} }
charsetConverter_idna::~charsetConverter_idna() charsetConverter_idna::~charsetConverter_idna() {
{
} }
void charsetConverter_idna::convert(utility::inputStream& in, utility::outputStream& out, status* st) void charsetConverter_idna::convert(utility::inputStream& in, utility::outputStream& out, status* st) {
{
if (st) if (st) {
new (st) status(); new (st) status();
}
// IDNA should be used for short strings, so it does not matter if we // IDNA should be used for short strings, so it does not matter if we
// do not work directly on the stream // do not work directly on the stream
@ -75,19 +79,19 @@ void charsetConverter_idna::convert(utility::inputStream& in, utility::outputStr
} }
void charsetConverter_idna::convert(const string& in, string& out, status* st) void charsetConverter_idna::convert(const string& in, string& out, status* st) {
{
if (st) if (st) {
new (st) status(); new (st) status();
}
out.clear(); out.clear();
if (m_dest == "idna") if (m_dest == "idna") {
{
if (utility::stringUtils::is7bit(in)) if (utility::stringUtils::is7bit(in)) {
{
if (st) if (st) {
{
st->inputBytesRead = in.length(); st->inputBytesRead = in.length();
st->outputBytesWritten = in.length(); st->outputBytesWritten = in.length();
} }
@ -106,41 +110,42 @@ void charsetConverter_idna::convert(const string& in, string& out, status* st)
std::vector <punycode_uint> unichars; std::vector <punycode_uint> unichars;
unichars.reserve(inUTF8.length()); unichars.reserve(inUTF8.length());
while (ch < end) while (ch < end) {
{
const utf8::uint32_t uc = utf8::unchecked::next(ch); const utf8::uint32_t uc = utf8::unchecked::next(ch);
unichars.push_back(uc); unichars.push_back(uc);
} }
if (st) if (st) {
st->inputBytesRead = in.length(); st->inputBytesRead = in.length();
}
punycode_uint inputLen = static_cast <punycode_uint>(unichars.size()); punycode_uint inputLen = static_cast <punycode_uint>(unichars.size());
std::vector <char> output(inUTF8.length() * 2); std::vector <char> output(inUTF8.length() * 2);
punycode_uint outputLen = static_cast <punycode_uint>(output.size()); punycode_uint outputLen = static_cast <punycode_uint>(output.size());
const punycode_status status = punycode_encode const punycode_status status = punycode_encode(
(inputLen, &unichars[0], /* case_flags */ NULL, &outputLen, &output[0]); inputLen, &unichars[0], /* case_flags */ NULL, &outputLen, &output[0]
);
if (status == punycode_success) {
if (status == punycode_success)
{
out = string("xn--") + string(output.begin(), output.begin() + outputLen); out = string("xn--") + string(output.begin(), output.begin() + outputLen);
if (st) if (st) {
st->outputBytesWritten = out.length(); st->outputBytesWritten = out.length();
} }
else
{ } else {
// TODO // TODO
} }
}
else if (m_source == "idna") } else if (m_source == "idna") {
{
if (in.length() < 5 || in.substr(0, 4) != "xn--") if (in.length() < 5 || in.substr(0, 4) != "xn--") {
{
if (st) if (st) {
{
st->inputBytesRead = in.length(); st->inputBytesRead = in.length();
st->outputBytesWritten = in.length(); st->outputBytesWritten = in.length();
} }
@ -155,31 +160,34 @@ void charsetConverter_idna::convert(const string& in, string& out, status* st)
std::vector <punycode_uint> output(in.length() - 4); std::vector <punycode_uint> output(in.length() - 4);
punycode_uint outputLen = static_cast <punycode_uint>(output.size()); punycode_uint outputLen = static_cast <punycode_uint>(output.size());
const punycode_status status = punycode_decode const punycode_status status = punycode_decode(
(inputLen, &in[4], &outputLen, &output[0], /* case_flags */ NULL); inputLen, &in[4], &outputLen, &output[0], /* case_flags */ NULL
);
if (st) if (st) {
st->inputBytesRead = in.length(); st->inputBytesRead = in.length();
}
if (status == punycode_success) {
if (status == punycode_success)
{
std::vector <char> outUTF8Bytes(outputLen * 4); std::vector <char> outUTF8Bytes(outputLen * 4);
char* p = &outUTF8Bytes[0]; char* p = &outUTF8Bytes[0];
for (std::vector <punycode_uint>::const_iterator it = output.begin() ; for (std::vector <punycode_uint>::const_iterator it = output.begin() ;
it != output.begin() + outputLen ; ++it) it != output.begin() + outputLen ; ++it) {
{
p = utf8::unchecked::append(*it, p); p = utf8::unchecked::append(*it, p);
} }
string outUTF8(&outUTF8Bytes[0], p); string outUTF8(&outUTF8Bytes[0], p);
charset::convert(outUTF8, out, vmime::charsets::UTF_8, m_dest); charset::convert(outUTF8, out, vmime::charsets::UTF_8, m_dest);
if (st) if (st) {
st->outputBytesWritten = out.length(); st->outputBytesWritten = out.length();
} }
else
{ } else {
// TODO // TODO
} }
} }
@ -187,9 +195,12 @@ void charsetConverter_idna::convert(const string& in, string& out, status* st)
shared_ptr <utility::charsetFilteredOutputStream> shared_ptr <utility::charsetFilteredOutputStream>
charsetConverter_idna::getFilteredOutputStream charsetConverter_idna::getFilteredOutputStream(
(utility::outputStream& /* os */, const charsetConverterOptions& /* opts */) utility::outputStream& /* os */,
{ const charsetConverterOptions& /* opts */
) {
// Not supported
return null; return null;
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -28,15 +28,13 @@
#include "vmime/charsetConverter.hpp" #include "vmime/charsetConverter.hpp"
namespace vmime namespace vmime {
{
/** A charset converter which can convert to and from Punycode (for IDNA). /** A charset converter which can convert to and from Punycode (for IDNA).
*/ */
class charsetConverter_idna : public charsetConverter {
class charsetConverter_idna : public charsetConverter
{
public: public:
/** Construct and initialize an IDNA charset converter. /** Construct and initialize an IDNA charset converter.
@ -45,17 +43,21 @@ public:
* @param dest output charset * @param dest output charset
* @param opts conversion options * @param opts conversion options
*/ */
charsetConverter_idna(const charset& source, const charset& dest, charsetConverter_idna(
const charsetConverterOptions& opts = charsetConverterOptions()); const charset& source,
const charset& dest,
const charsetConverterOptions& opts = charsetConverterOptions()
);
~charsetConverter_idna(); ~charsetConverter_idna();
void convert(const string& in, string& out, status* st = NULL); void convert(const string& in, string& out, status* st = NULL);
void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL); void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL);
shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream(
(utility::outputStream& os, utility::outputStream& os,
const charsetConverterOptions& opts = charsetConverterOptions()); const charsetConverterOptions& opts = charsetConverterOptions()
);
private: private:

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -49,37 +49,46 @@
#define CP_UNICODE 1200 #define CP_UNICODE 1200
namespace vmime namespace vmime {
{
// static // static
shared_ptr <charsetConverter> charsetConverter::createGenericConverter shared_ptr <charsetConverter> charsetConverter::createGenericConverter(
(const charset& source, const charset& dest, const charset& source,
const charsetConverterOptions& opts) const charset& dest,
{ const charsetConverterOptions& opts
) {
return make_shared <charsetConverter_win>(source, dest, opts); return make_shared <charsetConverter_win>(source, dest, opts);
} }
charsetConverter_win::charsetConverter_win charsetConverter_win::charsetConverter_win(
(const charset& source, const charset& dest, const charsetConverterOptions& opts) const charset& source,
: m_source(source), m_dest(dest), m_options(opts) const charset& dest,
{ const charsetConverterOptions& opts
)
: m_source(source),
m_dest(dest),
m_options(opts) {
} }
void charsetConverter_win::convert void charsetConverter_win::convert(
(utility::inputStream& in, utility::outputStream& out, status* st) utility::inputStream& in,
{ utility::outputStream& out,
if (st) status* st
) {
if (st) {
new (st) status(); new (st) status();
}
byte_t buffer[32768]; byte_t buffer[32768];
string inStr, outStr; string inStr, outStr;
while (!in.eof()) while (!in.eof()) {
{
const size_t len = in.read(buffer, sizeof(buffer)); const size_t len = in.read(buffer, sizeof(buffer));
utility::stringUtils::appendBytesToString(inStr, buffer, len); utility::stringUtils::appendBytesToString(inStr, buffer, len);
} }
@ -90,10 +99,11 @@ void charsetConverter_win::convert
} }
void charsetConverter_win::convert(const string& in, string& out, status* st) void charsetConverter_win::convert(const string& in, string& out, status* st) {
{
if (st) if (st) {
new (st) status(); new (st) status();
}
const int sourceCodePage = getCodePage(m_source.getName().c_str()); const int sourceCodePage = getCodePage(m_source.getName().c_str());
const int destCodePage = getCodePage(m_dest.getName().c_str()); const int destCodePage = getCodePage(m_dest.getName().c_str());
@ -103,69 +113,77 @@ void charsetConverter_win::convert(const string& in, string& out, status* st)
const WCHAR* unicodePtr = NULL; const WCHAR* unicodePtr = NULL;
size_t unicodeLen = 0; size_t unicodeLen = 0;
if (sourceCodePage == CP_UNICODE) if (sourceCodePage == CP_UNICODE) {
{
unicodePtr = reinterpret_cast <const WCHAR*>(in.c_str()); unicodePtr = reinterpret_cast <const WCHAR*>(in.c_str());
unicodeLen = in.length() / 2; unicodeLen = in.length() / 2;
}
else } else {
{
const size_t bufferSize = MultiByteToWideChar const size_t bufferSize = MultiByteToWideChar(
(sourceCodePage, 0, in.c_str(), static_cast <int>(in.length()), sourceCodePage, 0, in.c_str(), static_cast <int>(in.length()), NULL, 0
NULL, 0) * sizeof(WCHAR); // in wide characters ) * sizeof(WCHAR); // in wide characters
unicodeBuffer.resize(bufferSize); unicodeBuffer.resize(bufferSize);
DWORD flags = 0; DWORD flags = 0;
if (!m_options.silentlyReplaceInvalidSequences) if (!m_options.silentlyReplaceInvalidSequences) {
flags |= MB_ERR_INVALID_CHARS; flags |= MB_ERR_INVALID_CHARS;
}
unicodePtr = reinterpret_cast <const WCHAR*>(&unicodeBuffer[0]); unicodePtr = reinterpret_cast <const WCHAR*>(&unicodeBuffer[0]);
unicodeLen = MultiByteToWideChar unicodeLen = MultiByteToWideChar(
(sourceCodePage, 0, in.c_str(), static_cast <int>(in.length()), sourceCodePage, 0, in.c_str(), static_cast <int>(in.length()),
reinterpret_cast <WCHAR*>(&unicodeBuffer[0]), static_cast <int>(bufferSize)); reinterpret_cast <WCHAR*>(&unicodeBuffer[0]), static_cast <int>(bufferSize)
);
if (unicodeLen == 0) {
if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) {
if (unicodeLen == 0)
{
if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION)
{
throw exceptions::illegal_byte_sequence_for_charset(); throw exceptions::illegal_byte_sequence_for_charset();
}
else } else {
{
throw exceptions::charset_conv_error("MultiByteToWideChar() failed when converting to Unicode from " + m_source.getName()); throw exceptions::charset_conv_error(
"MultiByteToWideChar() failed when converting to Unicode from " + m_source.getName()
);
} }
} }
} }
// Convert from Unicode to destination charset // Convert from Unicode to destination charset
if (destCodePage == CP_UNICODE) if (destCodePage == CP_UNICODE) {
{
out.assign(reinterpret_cast <const char*>(unicodePtr), unicodeLen * 2); out.assign(reinterpret_cast <const char*>(unicodePtr), unicodeLen * 2);
}
else } else {
{
const size_t bufferSize = WideCharToMultiByte const size_t bufferSize = WideCharToMultiByte(
(destCodePage, 0, unicodePtr, static_cast <int>(unicodeLen), destCodePage, 0, unicodePtr, static_cast <int>(unicodeLen),
NULL, 0, 0, NULL); // in multibyte characters NULL, 0, 0, NULL
); // in multibyte characters
std::vector <char> buffer; std::vector <char> buffer;
buffer.resize(bufferSize); buffer.resize(bufferSize);
const size_t len = WideCharToMultiByte const size_t len = WideCharToMultiByte(
(destCodePage, 0, unicodePtr, static_cast <int>(unicodeLen), destCodePage, 0, unicodePtr, static_cast <int>(unicodeLen),
&buffer[0], static_cast <int>(bufferSize), 0, NULL); &buffer[0], static_cast <int>(bufferSize), 0, NULL
);
if (len == 0) {
if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) {
if (len == 0)
{
if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION)
{
throw exceptions::illegal_byte_sequence_for_charset(); throw exceptions::illegal_byte_sequence_for_charset();
}
else } else {
{
throw exceptions::charset_conv_error("WideCharToMultiByte() failed when converting from Unicode to " + m_source.getName()); throw exceptions::charset_conv_error(
"WideCharToMultiByte() failed when converting from Unicode to " + m_source.getName()
);
} }
} }
@ -175,15 +193,16 @@ void charsetConverter_win::convert(const string& in, string& out, status* st)
// static // static
int charsetConverter_win::getCodePage(const char* name) int charsetConverter_win::getCodePage(const char* name) {
{
if (_stricmp(name, charsets::UTF_16) == 0) // wchar_t is UTF-16 on Windows if (_stricmp(name, charsets::UTF_16) == 0) { // wchar_t is UTF-16 on Windows
return CP_UNICODE; return CP_UNICODE;
}
// "cp1252" --> return 1252 // "cp1252" --> return 1252
if ((name[0] == 'c' || name[0] == 'C') && if ((name[0] == 'c' || name[0] == 'C') &&
(name[1] == 'p' || name[1] == 'P')) (name[1] == 'p' || name[1] == 'P')) {
{
return atoi(name + 2); return atoi(name + 2);
} }
@ -192,9 +211,11 @@ int charsetConverter_win::getCodePage(const char* name)
shared_ptr <utility::charsetFilteredOutputStream> shared_ptr <utility::charsetFilteredOutputStream>
charsetConverter_win::getFilteredOutputStream charsetConverter_win::getFilteredOutputStream(
(utility::outputStream& /* os */, const charsetConverterOptions& /* opts */) utility::outputStream& /* os */,
{ const charsetConverterOptions& /* opts */
) {
// TODO: implement me! // TODO: implement me!
return null; return null;
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -34,8 +34,7 @@
#include "vmime/charsetConverter.hpp" #include "vmime/charsetConverter.hpp"
namespace vmime namespace vmime {
{
/** A generic charset converter which uses Windows MultiByteToWideChar /** A generic charset converter which uses Windows MultiByteToWideChar
@ -49,9 +48,8 @@ namespace vmime
* *
* Also, "status" is not supported by this converter for the same reason. * Also, "status" is not supported by this converter for the same reason.
*/ */
class charsetConverter_win : public charsetConverter {
class charsetConverter_win : public charsetConverter
{
public: public:
/** Construct and initialize a Windows charset converter. /** Construct and initialize a Windows charset converter.
@ -60,14 +58,19 @@ public:
* @param dest output charset * @param dest output charset
* @param opts conversion options * @param opts conversion options
*/ */
charsetConverter_win(const charset& source, const charset& dest, charsetConverter_win(
const charsetConverterOptions& opts = charsetConverterOptions()); const charset& source,
const charset& dest,
const charsetConverterOptions& opts = charsetConverterOptions()
);
void convert(const string& in, string& out, status* st); void convert(const string& in, string& out, status* st);
void convert(utility::inputStream& in, utility::outputStream& out, status* st); void convert(utility::inputStream& in, utility::outputStream& out, status* st);
shared_ptr <utility::charsetFilteredOutputStream> shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream(
getFilteredOutputStream(utility::outputStream& os, const charsetConverterOptions& opts); utility::outputStream& os,
const charsetConverterOptions& opts
);
private: private:

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -31,48 +31,54 @@
#include <sstream> #include <sstream>
namespace vmime namespace vmime {
{
component::component() component::component()
: m_parsedOffset(0), m_parsedLength(0) : m_parsedOffset(0), m_parsedLength(0) {
{
} }
component::~component() component::~component() {
{
} }
void component::parse void component::parse(
(shared_ptr <utility::inputStream> inputStream, const size_t length) const shared_ptr <utility::inputStream>& inputStream,
{ const size_t length
) {
parse(inputStream, 0, length, NULL); parse(inputStream, 0, length, NULL);
} }
void component::parse void component::parse(
(shared_ptr <utility::inputStream> inputStream, const size_t position, const shared_ptr <utility::inputStream>& inputStream,
const size_t end, size_t* newPosition) const size_t position,
{ const size_t end,
size_t* newPosition) {
parse(parsingContext::getDefaultContext(), inputStream, position, end, newPosition); parse(parsingContext::getDefaultContext(), inputStream, position, end, newPosition);
} }
void component::parse void component::parse(
(const parsingContext& ctx, const parsingContext& ctx,
shared_ptr <utility::inputStream> inputStream, const size_t position, const shared_ptr <utility::inputStream>& inputStream,
const size_t end, size_t* newPosition) const size_t position,
{ const size_t end,
size_t* newPosition
) {
m_parsedOffset = m_parsedLength = 0; m_parsedOffset = m_parsedLength = 0;
shared_ptr <utility::seekableInputStream> seekableStream = shared_ptr <utility::seekableInputStream> seekableStream =
dynamicCast <utility::seekableInputStream>(inputStream); dynamicCast <utility::seekableInputStream>(inputStream);
if (seekableStream == NULL || end == 0) if (!seekableStream || end == 0) {
{
// Read the whole stream into a buffer // Read the whole stream into a buffer
std::ostringstream oss; std::ostringstream oss;
utility::outputStreamAdapter ossAdapter(oss); utility::outputStreamAdapter ossAdapter(oss);
@ -81,9 +87,9 @@ void component::parse
const string buffer = oss.str(); const string buffer = oss.str();
parseImpl(ctx, buffer, 0, buffer.length(), NULL); parseImpl(ctx, buffer, 0, buffer.length(), NULL);
}
else } else {
{
shared_ptr <utility::parserInputStreamAdapter> parser = shared_ptr <utility::parserInputStreamAdapter> parser =
make_shared <utility::parserInputStreamAdapter>(seekableStream); make_shared <utility::parserInputStreamAdapter>(seekableStream);
@ -92,79 +98,95 @@ void component::parse
} }
void component::parse(const string& buffer) void component::parse(const string& buffer) {
{
m_parsedOffset = m_parsedLength = 0; m_parsedOffset = m_parsedLength = 0;
parseImpl(parsingContext::getDefaultContext(), buffer, 0, buffer.length(), NULL); parseImpl(parsingContext::getDefaultContext(), buffer, 0, buffer.length(), NULL);
} }
void component::parse(const parsingContext& ctx, const string& buffer) void component::parse(const parsingContext& ctx, const string& buffer) {
{
m_parsedOffset = m_parsedLength = 0; m_parsedOffset = m_parsedLength = 0;
parseImpl(ctx, buffer, 0, buffer.length(), NULL); parseImpl(ctx, buffer, 0, buffer.length(), NULL);
} }
void component::parse void component::parse(
(const string& buffer, const size_t position, const string& buffer,
const size_t end, size_t* newPosition) const size_t position,
{ const size_t end,
size_t* newPosition
) {
m_parsedOffset = m_parsedLength = 0; m_parsedOffset = m_parsedLength = 0;
parseImpl(parsingContext::getDefaultContext(), buffer, position, end, newPosition); parseImpl(parsingContext::getDefaultContext(), buffer, position, end, newPosition);
} }
void component::parse void component::parse(
(const parsingContext& ctx, const parsingContext& ctx,
const string& buffer, const size_t position, const string& buffer,
const size_t end, size_t* newPosition) const size_t position,
{ const size_t end, size_t* newPosition
) {
m_parsedOffset = m_parsedLength = 0; m_parsedOffset = m_parsedLength = 0;
parseImpl(ctx, buffer, position, end, newPosition); parseImpl(ctx, buffer, position, end, newPosition);
} }
void component::offsetParsedBounds(const size_t offset) void component::offsetParsedBounds(const size_t offset) {
{
// Offset parsed bounds of this component // Offset parsed bounds of this component
if (m_parsedLength != 0) if (m_parsedLength != 0) {
m_parsedOffset += offset; m_parsedOffset += offset;
}
// Offset parsed bounds of our children // Offset parsed bounds of our children
std::vector <shared_ptr <component> > children = getChildComponents(); std::vector <shared_ptr <component> > children = getChildComponents();
for (size_t i = 0, n = children.size() ; i < n ; ++i) for (size_t i = 0, n = children.size() ; i < n ; ++i) {
children[i]->offsetParsedBounds(offset); children[i]->offsetParsedBounds(offset);
}
} }
void component::parseImpl void component::parseImpl(
(const parsingContext& ctx, shared_ptr <utility::parserInputStreamAdapter> parser, const parsingContext& ctx,
const size_t position, const size_t end, size_t* newPosition) const shared_ptr <utility::parserInputStreamAdapter>& parser,
{ const size_t position,
const size_t end,
size_t* newPosition
) {
// This is the default implementation for parsing from an input stream: // This is the default implementation for parsing from an input stream:
// actually, we extract the substring and use the "parse from string" implementation // actually, we extract the substring and use the "parse from string" implementation
const string buffer = parser->extract(position, end); const string buffer = parser->extract(position, end);
parseImpl(ctx, buffer, 0, buffer.length(), newPosition); parseImpl(ctx, buffer, 0, buffer.length(), newPosition);
// Recursivey offset parsed bounds on children // Recursivey offset parsed bounds on children
if (position != 0) if (position != 0) {
offsetParsedBounds(position); offsetParsedBounds(position);
}
if (newPosition != NULL) if (newPosition) {
*newPosition += position; *newPosition += position;
}
} }
void component::parseImpl void component::parseImpl(
(const parsingContext& ctx, const string& buffer, const size_t position, const parsingContext& ctx,
const size_t end, size_t* newPosition) const string& buffer,
{ const size_t position,
const size_t end,
size_t* newPosition) {
// This is the default implementation for parsing from a string: // This is the default implementation for parsing from a string:
// actually, we encapsulate the string buffer in an input stream, then use // actually, we encapsulate the string buffer in an input stream, then use
// the "parse from input stream" implementation // the "parse from input stream" implementation
@ -178,9 +200,11 @@ void component::parseImpl
} }
const string component::generate const string component::generate(
(const size_t maxLineLength, const size_t curLinePos) const const size_t maxLineLength,
{ const size_t curLinePos
) const {
std::ostringstream oss; std::ostringstream oss;
utility::outputStreamAdapter adapter(oss); utility::outputStreamAdapter adapter(oss);
@ -189,56 +213,63 @@ const string component::generate
generateImpl(ctx, adapter, curLinePos, NULL); generateImpl(ctx, adapter, curLinePos, NULL);
return (oss.str()); return oss.str();
} }
void component::generate void component::generate(
(utility::outputStream& os, const size_t curLinePos, size_t* newLinePos) const utility::outputStream& os,
{ const size_t curLinePos,
generateImpl(generationContext::getDefaultContext(), size_t* newLinePos
os, curLinePos, newLinePos); ) const {
generateImpl(generationContext::getDefaultContext(), os, curLinePos, newLinePos);
} }
void component::generate void component::generate(
(const generationContext& ctx, utility::outputStream& outputStream, const generationContext& ctx,
const size_t curLinePos, size_t* newLinePos) const utility::outputStream& outputStream,
{ const size_t curLinePos,
size_t* newLinePos
) const {
generateImpl(ctx, outputStream, curLinePos, newLinePos); generateImpl(ctx, outputStream, curLinePos, newLinePos);
} }
size_t component::getParsedOffset() const size_t component::getParsedOffset() const {
{
return (m_parsedOffset); return m_parsedOffset;
} }
size_t component::getParsedLength() const size_t component::getParsedLength() const {
{
return (m_parsedLength); return m_parsedLength;
} }
void component::setParsedBounds(const size_t start, const size_t end) void component::setParsedBounds(const size_t start, const size_t end) {
{
m_parsedOffset = start; m_parsedOffset = start;
m_parsedLength = end - start; m_parsedLength = end - start;
} }
size_t component::getGeneratedSize(const generationContext& ctx) size_t component::getGeneratedSize(const generationContext& ctx) {
{
std::vector <shared_ptr <component> > children = getChildComponents(); std::vector <shared_ptr <component> > children = getChildComponents();
size_t totalSize = 0; size_t totalSize = 0;
for (std::vector <shared_ptr <component> >::iterator it = children.begin() ; it != children.end() ; ++it) for (std::vector <shared_ptr <component> >::iterator it = children.begin() ;
it != children.end() ; ++it) {
totalSize += (*it)->getGeneratedSize(ctx); totalSize += (*it)->getGeneratedSize(ctx);
}
return totalSize; return totalSize;
} }
} // vmime } // vmime

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -34,16 +34,14 @@
#include "vmime/parsingContext.hpp" #include "vmime/parsingContext.hpp"
namespace vmime namespace vmime {
{
/** This abstract class is the base class for all the components of a message. /** This abstract class is the base class for all the components of a message.
* It defines methods for parsing and generating a component. * It defines methods for parsing and generating a component.
*/ */
class VMIME_EXPORT component : public object {
class VMIME_EXPORT component : public object
{
public: public:
component(); component();
@ -70,7 +68,7 @@ public:
* @param inputStream stream from which to read data * @param inputStream stream from which to read data
* @param length data length, in bytes (0 = unknown/not specified) * @param length data length, in bytes (0 = unknown/not specified)
*/ */
void parse(shared_ptr <utility::inputStream> inputStream, const size_t length); void parse(const shared_ptr <utility::inputStream>& inputStream, const size_t length);
/** Parse RFC-822/MIME data for this component, using the default /** Parse RFC-822/MIME data for this component, using the default
* parsing context. * parsing context.
@ -80,11 +78,12 @@ public:
* @param end end position in the input buffer * @param end end position in the input buffer
* @param newPosition will receive the new position in the input buffer * @param newPosition will receive the new position in the input buffer
*/ */
void parse void parse(
(const string& buffer, const string& buffer,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
/** Parse RFC-822/MIME data for this component. /** Parse RFC-822/MIME data for this component.
* *
@ -94,12 +93,13 @@ public:
* @param end end position in the input buffer * @param end end position in the input buffer
* @param newPosition will receive the new position in the input buffer * @param newPosition will receive the new position in the input buffer
*/ */
void parse void parse(
(const parsingContext& ctx, const parsingContext& ctx,
const string& buffer, const string& buffer,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
/** Parse RFC-822/MIME data for this component. If stream is not seekable, /** Parse RFC-822/MIME data for this component. If stream is not seekable,
* or if end position is not specified, entire contents of the stream will * or if end position is not specified, entire contents of the stream will
@ -111,11 +111,12 @@ public:
* @param end end position in the input stream * @param end end position in the input stream
* @param newPosition will receive the new position in the input stream * @param newPosition will receive the new position in the input stream
*/ */
void parse void parse(
(shared_ptr <utility::inputStream> inputStream, const shared_ptr <utility::inputStream>& inputStream,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
/** Parse RFC-822/MIME data for this component. If stream is not seekable, /** Parse RFC-822/MIME data for this component. If stream is not seekable,
* or if end position is not specified, entire contents of the stream will * or if end position is not specified, entire contents of the stream will
@ -127,12 +128,13 @@ public:
* @param end end position in the input stream * @param end end position in the input stream
* @param newPosition will receive the new position in the input stream * @param newPosition will receive the new position in the input stream
*/ */
void parse void parse(
(const parsingContext& ctx, const parsingContext& ctx,
shared_ptr <utility::inputStream> inputStream, const shared_ptr <utility::inputStream>& inputStream,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
/** Generate RFC-2822/MIME data for this component. /** Generate RFC-2822/MIME data for this component.
* *
@ -142,9 +144,10 @@ public:
* @param curLinePos length of the current line in the output buffer * @param curLinePos length of the current line in the output buffer
* @return generated data * @return generated data
*/ */
virtual const string generate virtual const string generate(
(const size_t maxLineLength = lineLengthLimits::infinite, const size_t maxLineLength = lineLengthLimits::infinite,
const size_t curLinePos = 0) const; const size_t curLinePos = 0
) const;
/** Generate RFC-2822/MIME data for this component, using the default generation context. /** Generate RFC-2822/MIME data for this component, using the default generation context.
* *
@ -152,10 +155,11 @@ public:
* @param curLinePos length of the current line in the output buffer * @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) * @param newLinePos will receive the new line position (length of the last line written)
*/ */
virtual void generate virtual void generate(
(utility::outputStream& outputStream, utility::outputStream& outputStream,
const size_t curLinePos = 0, const size_t curLinePos = 0,
size_t* newLinePos = NULL) const; size_t* newLinePos = NULL
) const;
/** Generate RFC-2822/MIME data for this component, using the default generation context. /** Generate RFC-2822/MIME data for this component, using the default generation context.
* *
@ -164,11 +168,12 @@ public:
* @param curLinePos length of the current line in the output buffer * @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) * @param newLinePos will receive the new line position (length of the last line written)
*/ */
virtual void generate virtual void generate(
(const generationContext& ctx, const generationContext& ctx,
utility::outputStream& outputStream, utility::outputStream& outputStream,
const size_t curLinePos = 0, const size_t curLinePos = 0,
size_t* newLinePos = NULL) const; size_t* newLinePos = NULL
) const;
/** Clone this component. /** Clone this component.
* *
@ -222,25 +227,28 @@ protected:
void setParsedBounds(const size_t start, const size_t end); void setParsedBounds(const size_t start, const size_t end);
// AT LEAST ONE of these parseImpl() functions MUST be implemented in derived class // AT LEAST ONE of these parseImpl() functions MUST be implemented in derived class
virtual void parseImpl virtual void parseImpl(
(const parsingContext& ctx, const parsingContext& ctx,
shared_ptr <utility::parserInputStreamAdapter> parser, const shared_ptr <utility::parserInputStreamAdapter>& parser,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
virtual void parseImpl virtual void parseImpl(
(const parsingContext& ctx, const parsingContext& ctx,
const string& buffer, const string& buffer,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
virtual void generateImpl virtual void generateImpl(
(const generationContext& ctx, const generationContext& ctx,
utility::outputStream& os, utility::outputStream& os,
const size_t curLinePos = 0, const size_t curLinePos = 0,
size_t* newLinePos = NULL) const = 0; size_t* newLinePos = NULL
) const = 0;
private: private:

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -24,13 +24,12 @@
#include "vmime/constants.hpp" #include "vmime/constants.hpp"
namespace vmime namespace vmime {
{
// Media Types // Media Types
namespace mediaTypes namespace mediaTypes {
{
// Types // Types
const char* const TEXT = "text"; const char* const TEXT = "text";
const char* const MULTIPART = "multipart"; const char* const MULTIPART = "multipart";
@ -72,8 +71,8 @@ namespace mediaTypes
// Encoding types // Encoding types
namespace encodingTypes namespace encodingTypes {
{
const char* const SEVEN_BIT = "7bit"; const char* const SEVEN_BIT = "7bit";
const char* const EIGHT_BIT = "8bit"; const char* const EIGHT_BIT = "8bit";
const char* const BASE64 = "base64"; const char* const BASE64 = "base64";
@ -84,16 +83,16 @@ namespace encodingTypes
// Content disposition types // Content disposition types
namespace contentDispositionTypes namespace contentDispositionTypes {
{
const char* const INLINE = "inline"; const char* const INLINE = "inline";
const char* const ATTACHMENT = "attachment"; const char* const ATTACHMENT = "attachment";
} }
// Charsets // Charsets
namespace charsets namespace charsets {
{
const char* const ISO8859_1 = "iso-8859-1"; const char* const ISO8859_1 = "iso-8859-1";
const char* const ISO8859_2 = "iso-8859-2"; const char* const ISO8859_2 = "iso-8859-2";
const char* const ISO8859_3 = "iso-8859-3"; const char* const ISO8859_3 = "iso-8859-3";
@ -159,8 +158,8 @@ namespace charsets
// Fields // Fields
namespace fields namespace fields {
{
const char* const RECEIVED = "Received"; const char* const RECEIVED = "Received";
const char* const FROM = "From"; const char* const FROM = "From";
const char* const SENDER = "Sender"; const char* const SENDER = "Sender";
@ -204,32 +203,32 @@ namespace fields
// Constants for disposition action modes (RFC-3978). // Constants for disposition action modes (RFC-3978).
namespace dispositionActionModes namespace dispositionActionModes {
{
const char* const MANUAL = "manual"; const char* const MANUAL = "manual";
const char* const AUTOMATIC = "automatic"; const char* const AUTOMATIC = "automatic";
} }
// Constants for disposition sending modes (RFC-3798). // Constants for disposition sending modes (RFC-3798).
namespace dispositionSendingModes namespace dispositionSendingModes {
{
const char* const SENT_MANUALLY = "MDN-sent-manually"; const char* const SENT_MANUALLY = "MDN-sent-manually";
const char* const SENT_AUTOMATICALLY ="MDN-sent-automatically"; const char* const SENT_AUTOMATICALLY ="MDN-sent-automatically";
} }
// Constants for disposition types (RFC-3798). // Constants for disposition types (RFC-3798).
namespace dispositionTypes namespace dispositionTypes {
{
const char* const DISPLAYED = "displayed"; const char* const DISPLAYED = "displayed";
const char* const DELETED = "deleted"; const char* const DELETED = "deleted";
} }
// Constants for disposition modifiers (RFC-3798). // Constants for disposition modifiers (RFC-3798).
namespace dispositionModifiers namespace dispositionModifiers {
{
const char* const ERROR = "error"; const char* const ERROR = "error";
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free SOFTWARE; you can redistribute it and/or // This program is free SOFTWARE; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -37,11 +37,11 @@
#endif #endif
namespace vmime namespace vmime {
{
/** Constants for media types. */ /** Constants for media types. */
namespace mediaTypes namespace mediaTypes {
{
// Types // Types
extern VMIME_EXPORT const char* const TEXT; extern VMIME_EXPORT const char* const TEXT;
extern VMIME_EXPORT const char* const MULTIPART; extern VMIME_EXPORT const char* const MULTIPART;
@ -83,8 +83,8 @@ namespace vmime
/** Constants for encoding types. */ /** Constants for encoding types. */
namespace encodingTypes namespace encodingTypes {
{
extern VMIME_EXPORT const char* const SEVEN_BIT; extern VMIME_EXPORT const char* const SEVEN_BIT;
extern VMIME_EXPORT const char* const EIGHT_BIT; extern VMIME_EXPORT const char* const EIGHT_BIT;
extern VMIME_EXPORT const char* const BASE64; extern VMIME_EXPORT const char* const BASE64;
@ -95,16 +95,16 @@ namespace vmime
/** Constants for content disposition types (RFC-2183). */ /** Constants for content disposition types (RFC-2183). */
namespace contentDispositionTypes namespace contentDispositionTypes {
{
extern VMIME_EXPORT const char* const INLINE; extern VMIME_EXPORT const char* const INLINE;
extern VMIME_EXPORT const char* const ATTACHMENT; extern VMIME_EXPORT const char* const ATTACHMENT;
} }
/** Constants for charsets. */ /** Constants for charsets. */
namespace charsets namespace charsets {
{
extern VMIME_EXPORT const char* const ISO8859_1; extern VMIME_EXPORT const char* const ISO8859_1;
extern VMIME_EXPORT const char* const ISO8859_2; extern VMIME_EXPORT const char* const ISO8859_2;
extern VMIME_EXPORT const char* const ISO8859_3; extern VMIME_EXPORT const char* const ISO8859_3;
@ -169,8 +169,8 @@ namespace vmime
} }
/** Constants for standard field names. */ /** Constants for standard field names. */
namespace fields namespace fields {
{
extern VMIME_EXPORT const char* const RECEIVED; extern VMIME_EXPORT const char* const RECEIVED;
extern VMIME_EXPORT const char* const FROM; extern VMIME_EXPORT const char* const FROM;
extern VMIME_EXPORT const char* const SENDER; extern VMIME_EXPORT const char* const SENDER;
@ -213,8 +213,8 @@ namespace vmime
} }
/** Constants for disposition action modes (RFC-3978). */ /** Constants for disposition action modes (RFC-3978). */
namespace dispositionActionModes namespace dispositionActionModes {
{
/** User implicitely displayed or deleted the message (filter or /** User implicitely displayed or deleted the message (filter or
* any other automatic action). */ * any other automatic action). */
extern VMIME_EXPORT const char* const AUTOMATIC; extern VMIME_EXPORT const char* const AUTOMATIC;
@ -224,8 +224,8 @@ namespace vmime
} }
/** Constants for disposition sending modes (RFC-3798). */ /** Constants for disposition sending modes (RFC-3798). */
namespace dispositionSendingModes namespace dispositionSendingModes {
{
/** The MDN was sent because the MUA had previously been configured /** The MDN was sent because the MUA had previously been configured
* to do so automatically. */ * to do so automatically. */
extern VMIME_EXPORT const char* const SENT_AUTOMATICALLY; extern VMIME_EXPORT const char* const SENT_AUTOMATICALLY;
@ -235,8 +235,8 @@ namespace vmime
} }
/** Constants for disposition types (RFC-3798). */ /** Constants for disposition types (RFC-3798). */
namespace dispositionTypes namespace dispositionTypes {
{
/** Message has been displayed to the user. */ /** Message has been displayed to the user. */
extern VMIME_EXPORT const char* const DISPLAYED; extern VMIME_EXPORT const char* const DISPLAYED;
/** Message has been deleted without being displayed. */ /** Message has been deleted without being displayed. */
@ -246,8 +246,8 @@ namespace vmime
} }
/** Constants for disposition modifiers (RFC-3798). */ /** Constants for disposition modifiers (RFC-3798). */
namespace dispositionModifiers namespace dispositionModifiers {
{
extern VMIME_EXPORT const char* const ERROR; extern VMIME_EXPORT const char* const ERROR;
} }
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -25,107 +25,118 @@
#include "vmime/utility/stringUtils.hpp" #include "vmime/utility/stringUtils.hpp"
namespace vmime namespace vmime {
{
contentDisposition::contentDisposition() contentDisposition::contentDisposition()
: m_name(contentDispositionTypes::INLINE) : m_name(contentDispositionTypes::INLINE) {
{
} }
contentDisposition::contentDisposition(const string& name) contentDisposition::contentDisposition(const string& name)
: m_name(utility::stringUtils::toLower(name)) : m_name(utility::stringUtils::toLower(name)) {
{
} }
contentDisposition::contentDisposition(const contentDisposition& type) contentDisposition::contentDisposition(const contentDisposition& type)
: headerFieldValue(), m_name(type.m_name) : headerFieldValue(), m_name(type.m_name) {
{
} }
void contentDisposition::parseImpl void contentDisposition::parseImpl(
(const parsingContext& /* ctx */, const string& buffer, const size_t position, const parsingContext& /* ctx */,
const size_t end, size_t* newPosition) const string& buffer,
{ const size_t position,
m_name = utility::stringUtils::trim(utility::stringUtils::toLower const size_t end,
(string(buffer.begin() + position, buffer.begin() + end))); size_t* newPosition
) {
m_name = utility::stringUtils::trim(
utility::stringUtils::toLower(
string(buffer.begin() + position, buffer.begin() + end)
)
);
setParsedBounds(position, end); setParsedBounds(position, end);
if (newPosition) if (newPosition) {
*newPosition = end; *newPosition = end;
}
} }
void contentDisposition::generateImpl void contentDisposition::generateImpl(
(const generationContext& /* ctx */, utility::outputStream& os, const generationContext& /* ctx */,
const size_t curLinePos, size_t* newLinePos) const utility::outputStream& os,
{ const size_t curLinePos,
size_t* newLinePos
) const {
os << m_name; os << m_name;
if (newLinePos) if (newLinePos) {
*newLinePos = curLinePos + m_name.length(); *newLinePos = curLinePos + m_name.length();
}
} }
contentDisposition& contentDisposition::operator=(const string& name) contentDisposition& contentDisposition::operator=(const string& name) {
{
m_name = utility::stringUtils::toLower(name); m_name = utility::stringUtils::toLower(name);
return (*this); return *this;
} }
bool contentDisposition::operator==(const contentDisposition& value) const bool contentDisposition::operator==(const contentDisposition& value) const {
{
return (utility::stringUtils::toLower(m_name) == value.m_name); return utility::stringUtils::toLower(m_name) == value.m_name;
} }
bool contentDisposition::operator!=(const contentDisposition& value) const bool contentDisposition::operator!=(const contentDisposition& value) const {
{
return !(*this == value); return !(*this == value);
} }
shared_ptr <component> contentDisposition::clone() const shared_ptr <component> contentDisposition::clone() const {
{
return make_shared <contentDisposition>(*this); return make_shared <contentDisposition>(*this);
} }
void contentDisposition::copyFrom(const component& other) void contentDisposition::copyFrom(const component& other) {
{
const contentDisposition& d = dynamic_cast <const contentDisposition&>(other); const contentDisposition& d = dynamic_cast <const contentDisposition&>(other);
m_name = d.m_name; m_name = d.m_name;
} }
contentDisposition& contentDisposition::operator=(const contentDisposition& other) contentDisposition& contentDisposition::operator=(const contentDisposition& other) {
{
copyFrom(other); copyFrom(other);
return (*this); return *this;
} }
const string& contentDisposition::getName() const const string& contentDisposition::getName() const {
{
return (m_name); return m_name;
} }
void contentDisposition::setName(const string& name) void contentDisposition::setName(const string& name) {
{
m_name = name; m_name = name;
} }
const std::vector <shared_ptr <component> > contentDisposition::getChildComponents() const std::vector <shared_ptr <component> > contentDisposition::getChildComponents() {
{
return std::vector <shared_ptr <component> >(); return std::vector <shared_ptr <component> >();
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -29,15 +29,13 @@
#include "vmime/headerFieldValue.hpp" #include "vmime/headerFieldValue.hpp"
namespace vmime namespace vmime {
{
/** Content disposition (basic type). /** Content disposition (basic type).
*/ */
class VMIME_EXPORT contentDisposition : public headerFieldValue {
class VMIME_EXPORT contentDisposition : public headerFieldValue
{
public: public:
contentDisposition(); contentDisposition();
@ -78,18 +76,20 @@ private:
protected: protected:
// Component parsing & assembling // Component parsing & assembling
void parseImpl void parseImpl(
(const parsingContext& ctx, const parsingContext& ctx,
const string& buffer, const string& buffer,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
void generateImpl void generateImpl(
(const generationContext& ctx, const generationContext& ctx,
utility::outputStream& os, utility::outputStream& os,
const size_t curLinePos = 0, const size_t curLinePos = 0,
size_t* newLinePos = NULL) const; size_t* newLinePos = NULL
) const;
}; };

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -25,132 +25,136 @@
#include "vmime/exception.hpp" #include "vmime/exception.hpp"
namespace vmime namespace vmime {
{
contentDispositionField::contentDispositionField() contentDispositionField::contentDispositionField() {
{
} }
contentDispositionField::contentDispositionField(contentDispositionField&) contentDispositionField::contentDispositionField(contentDispositionField&)
: parameterizedHeaderField() : parameterizedHeaderField() {
{
} }
bool contentDispositionField::hasCreationDate() const bool contentDispositionField::hasCreationDate() const {
{
return hasParameter("creation-date"); return hasParameter("creation-date");
} }
const datetime contentDispositionField::getCreationDate() const const datetime contentDispositionField::getCreationDate() const {
{
shared_ptr <parameter> param = findParameter("creation-date"); shared_ptr <parameter> param = findParameter("creation-date");
if (param) if (param) {
return param->getValueAs <datetime>(); return param->getValueAs <datetime>();
else } else {
return datetime::now(); return datetime::now();
}
} }
void contentDispositionField::setCreationDate(const datetime& creationDate) void contentDispositionField::setCreationDate(const datetime& creationDate) {
{
getParameter("creation-date")->setValue(creationDate); getParameter("creation-date")->setValue(creationDate);
} }
bool contentDispositionField::hasModificationDate() const bool contentDispositionField::hasModificationDate() const {
{
return hasParameter("modification-date"); return hasParameter("modification-date");
} }
const datetime contentDispositionField::getModificationDate() const const datetime contentDispositionField::getModificationDate() const {
{
shared_ptr <parameter> param = findParameter("modification-date"); shared_ptr <parameter> param = findParameter("modification-date");
if (param) if (param) {
return param->getValueAs <datetime>(); return param->getValueAs <datetime>();
else } else {
return datetime::now(); return datetime::now();
}
} }
void contentDispositionField::setModificationDate(const datetime& modificationDate) void contentDispositionField::setModificationDate(const datetime& modificationDate) {
{
getParameter("modification-date")->setValue(modificationDate); getParameter("modification-date")->setValue(modificationDate);
} }
bool contentDispositionField::hasReadDate() const bool contentDispositionField::hasReadDate() const {
{
return hasParameter("read-date"); return hasParameter("read-date");
} }
const datetime contentDispositionField::getReadDate() const const datetime contentDispositionField::getReadDate() const {
{
shared_ptr <parameter> param = findParameter("read-date"); shared_ptr <parameter> param = findParameter("read-date");
if (param) if (param) {
return param->getValueAs <datetime>(); return param->getValueAs <datetime>();
else } else {
return datetime::now(); return datetime::now();
}
} }
void contentDispositionField::setReadDate(const datetime& readDate) void contentDispositionField::setReadDate(const datetime& readDate) {
{
getParameter("read-date")->setValue(readDate); getParameter("read-date")->setValue(readDate);
} }
bool contentDispositionField::hasFilename() const bool contentDispositionField::hasFilename() const {
{
return hasParameter("filename"); return hasParameter("filename");
} }
const word contentDispositionField::getFilename() const const word contentDispositionField::getFilename() const {
{
shared_ptr <parameter> param = findParameter("filename"); shared_ptr <parameter> param = findParameter("filename");
if (param) if (param) {
return param->getValue(); return param->getValue();
else } else {
return word(); return word();
}
} }
void contentDispositionField::setFilename(const word& filename) void contentDispositionField::setFilename(const word& filename) {
{
getParameter("filename")->setValue(filename); getParameter("filename")->setValue(filename);
} }
bool contentDispositionField::hasSize() const bool contentDispositionField::hasSize() const {
{
return hasParameter("size"); return hasParameter("size");
} }
const string contentDispositionField::getSize() const const string contentDispositionField::getSize() const {
{
shared_ptr <parameter> param = findParameter("size"); shared_ptr <parameter> param = findParameter("size");
if (param) if (param) {
return param->getValue().getBuffer(); return param->getValue().getBuffer();
else } else {
return ""; return "";
}
} }
void contentDispositionField::setSize(const string& size) void contentDispositionField::setSize(const string& size) {
{
getParameter("size")->setValue(word(size, vmime::charsets::US_ASCII)); getParameter("size")->setValue(word(size, vmime::charsets::US_ASCII));
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -32,15 +32,13 @@
#include "vmime/word.hpp" #include "vmime/word.hpp"
namespace vmime namespace vmime {
{
/** Describes presentation information, as per RFC-2183. /** Describes presentation information, as per RFC-2183.
*/ */
class VMIME_EXPORT contentDispositionField : public parameterizedHeaderField {
class VMIME_EXPORT contentDispositionField : public parameterizedHeaderField
{
friend class headerFieldFactory; friend class headerFieldFactory;
protected: protected:

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -24,16 +24,15 @@
#include "vmime/contentHandler.hpp" #include "vmime/contentHandler.hpp"
namespace vmime namespace vmime {
{
// No encoding = "binary" encoding // No encoding = "binary" encoding
const encoding contentHandler::NO_ENCODING(encodingTypes::BINARY); const encoding contentHandler::NO_ENCODING(encodingTypes::BINARY);
contentHandler::~contentHandler() contentHandler::~contentHandler() {
{
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -34,12 +34,11 @@
#include "vmime/mediaType.hpp" #include "vmime/mediaType.hpp"
namespace vmime namespace vmime {
{
class VMIME_EXPORT contentHandler : public object class VMIME_EXPORT contentHandler : public object {
{
public: public:
/** Used to specify that enclosed data is not encoded. */ /** Used to specify that enclosed data is not encoded. */
@ -63,7 +62,11 @@ public:
* @param enc encoding for output * @param enc encoding for output
* @param maxLineLength maximum line length for output * @param maxLineLength maximum line length for output
*/ */
virtual void generate(utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength = lineLengthLimits::infinite) const = 0; virtual void generate(
utility::outputStream& os,
const vmime::encoding& enc,
const size_t maxLineLength = lineLengthLimits::infinite
) const = 0;
/** Extract the contents into the specified stream. If needed, data /** Extract the contents into the specified stream. If needed, data
* will be decoded before being written into the stream. * will be decoded before being written into the stream.
@ -74,7 +77,10 @@ public:
* @param progress progress listener, or NULL if you do not * @param progress progress listener, or NULL if you do not
* want to receive progress notifications * want to receive progress notifications
*/ */
virtual void extract(utility::outputStream& os, utility::progressListener* progress = NULL) const = 0; virtual void extract(
utility::outputStream& os,
utility::progressListener* progress = NULL
) const = 0;
/** Extract the contents into the specified stream, without /** Extract the contents into the specified stream, without
* decoding it. It may be useful in case the encoding is not * decoding it. It may be useful in case the encoding is not
@ -84,7 +90,10 @@ public:
* @param progress progress listener, or NULL if you do not * @param progress progress listener, or NULL if you do not
* want to receive progress notifications * want to receive progress notifications
*/ */
virtual void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const = 0; virtual void extractRaw(
utility::outputStream& os,
utility::progressListener* progress = NULL
) const = 0;
/** Returns the actual length of data. WARNING: this can return 0 if no /** Returns the actual length of data. WARNING: this can return 0 if no
* length was specified when setting data of this object, or if the * length was specified when setting data of this object, or if the

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -25,89 +25,90 @@
#include "vmime/exception.hpp" #include "vmime/exception.hpp"
namespace vmime namespace vmime {
{
contentTypeField::contentTypeField() contentTypeField::contentTypeField() {
{
} }
contentTypeField::contentTypeField(contentTypeField&) contentTypeField::contentTypeField(contentTypeField&)
: parameterizedHeaderField() : parameterizedHeaderField() {
{
} }
bool contentTypeField::hasBoundary() const bool contentTypeField::hasBoundary() const {
{
return hasParameter("boundary"); return hasParameter("boundary");
} }
const string contentTypeField::getBoundary() const const string contentTypeField::getBoundary() const {
{
shared_ptr <parameter> param = findParameter("boundary"); shared_ptr <parameter> param = findParameter("boundary");
if (param) if (param) {
return param->getValue().getBuffer(); return param->getValue().getBuffer();
else } else {
return ""; return "";
}
} }
void contentTypeField::setBoundary(const string& boundary) void contentTypeField::setBoundary(const string& boundary) {
{
getParameter("boundary")->setValue(word(boundary, vmime::charsets::US_ASCII)); getParameter("boundary")->setValue(word(boundary, vmime::charsets::US_ASCII));
} }
bool contentTypeField::hasCharset() const bool contentTypeField::hasCharset() const {
{
return hasParameter("charset"); return hasParameter("charset");
} }
const charset contentTypeField::getCharset() const const charset contentTypeField::getCharset() const {
{
shared_ptr <parameter> param = findParameter("charset"); shared_ptr <parameter> param = findParameter("charset");
if (param) if (param) {
return param->getValueAs <charset>(); return param->getValueAs <charset>();
else } else {
return charset(); return charset();
}
} }
void contentTypeField::setCharset(const charset& ch) void contentTypeField::setCharset(const charset& ch) {
{
getParameter("charset")->setValue(ch); getParameter("charset")->setValue(ch);
} }
bool contentTypeField::hasReportType() const bool contentTypeField::hasReportType() const {
{
return hasParameter("report-type"); return hasParameter("report-type");
} }
const string contentTypeField::getReportType() const const string contentTypeField::getReportType() const {
{
shared_ptr <parameter> param = findParameter("report-type"); shared_ptr <parameter> param = findParameter("report-type");
if (param) if (param) {
return param->getValue().getBuffer(); return param->getValue().getBuffer();
else } else {
return ""; return "";
}
} }
void contentTypeField::setReportType(const string& reportType) void contentTypeField::setReportType(const string& reportType) {
{
getParameter("report-type")->setValue(word(reportType, vmime::charsets::US_ASCII)); getParameter("report-type")->setValue(word(reportType, vmime::charsets::US_ASCII));
} }
} // vmime } // vmime

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -31,12 +31,11 @@
#include "vmime/charset.hpp" #include "vmime/charset.hpp"
namespace vmime namespace vmime {
{
class VMIME_EXPORT contentTypeField : public parameterizedHeaderField class VMIME_EXPORT contentTypeField : public parameterizedHeaderField {
{
friend class headerFieldFactory; friend class headerFieldFactory;
protected: protected:

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -24,61 +24,60 @@
#include "vmime/context.hpp" #include "vmime/context.hpp"
namespace vmime namespace vmime {
{
context::context() context::context()
: m_internationalizedEmail(false) : m_internationalizedEmail(false) {
{
} }
context::context(const context& ctx) context::context(const context& ctx)
: object(), : object(),
m_internationalizedEmail(ctx.m_internationalizedEmail) m_internationalizedEmail(ctx.m_internationalizedEmail) {
{
} }
context::~context() context::~context() {
{
} }
bool context::getInternationalizedEmailSupport() const bool context::getInternationalizedEmailSupport() const {
{
return m_internationalizedEmail; return m_internationalizedEmail;
} }
void context::setInternationalizedEmailSupport(const bool support) void context::setInternationalizedEmailSupport(const bool support) {
{
m_internationalizedEmail = support; m_internationalizedEmail = support;
} }
const charsetConverterOptions& context::getCharsetConversionOptions() const const charsetConverterOptions& context::getCharsetConversionOptions() const {
{
return m_charsetConvOptions; return m_charsetConvOptions;
} }
void context::setCharsetConversionOptions(const charsetConverterOptions& opts) void context::setCharsetConversionOptions(const charsetConverterOptions& opts) {
{
m_charsetConvOptions = opts; m_charsetConvOptions = opts;
} }
context& context::operator=(const context& ctx) context& context::operator=(const context& ctx) {
{
copyFrom(ctx); copyFrom(ctx);
return *this; return *this;
} }
void context::copyFrom(const context& ctx) void context::copyFrom(const context& ctx) {
{
m_internationalizedEmail = ctx.m_internationalizedEmail; m_internationalizedEmail = ctx.m_internationalizedEmail;
m_charsetConvOptions = ctx.m_charsetConvOptions; m_charsetConvOptions = ctx.m_charsetConvOptions;
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -29,15 +29,13 @@
#include "vmime/charsetConverterOptions.hpp" #include "vmime/charsetConverterOptions.hpp"
namespace vmime namespace vmime {
{
/** Holds configuration parameters used either for parsing or generating messages. /** Holds configuration parameters used either for parsing or generating messages.
*/ */
class VMIME_EXPORT context : public object {
class VMIME_EXPORT context : public object
{
public: public:
virtual ~context(); virtual ~context();
@ -74,8 +72,8 @@ public:
/** Switches between contexts temporarily. /** Switches between contexts temporarily.
*/ */
template <typename CTX_CLASS> template <typename CTX_CLASS>
class switcher class switcher {
{
public: public:
/** Switches to the specified context. /** Switches to the specified context.
@ -85,15 +83,15 @@ public:
* @param newCtx new context * @param newCtx new context
*/ */
switcher(CTX_CLASS& newCtx) switcher(CTX_CLASS& newCtx)
: m_oldCtxData(CTX_CLASS::getDefaultContext()), m_newCtx(&newCtx) : m_oldCtxData(CTX_CLASS::getDefaultContext()), m_newCtx(&newCtx) {
{
CTX_CLASS::getDefaultContext().copyFrom(newCtx); CTX_CLASS::getDefaultContext().copyFrom(newCtx);
} }
/** Restores back saved context. /** Restores back saved context.
*/ */
~switcher() ~switcher() {
{
CTX_CLASS::getDefaultContext().copyFrom(m_oldCtxData); CTX_CLASS::getDefaultContext().copyFrom(m_oldCtxData);
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -31,21 +31,31 @@
#include <ctime> #include <ctime>
namespace vmime namespace vmime {
{
/** Date and time (basic type). /** Date and time (basic type).
*/ */
class VMIME_EXPORT datetime : public headerFieldValue {
class VMIME_EXPORT datetime : public headerFieldValue
{
public: public:
// Constructors // Constructors
datetime(); datetime();
datetime(const int year, const int month, const int day); datetime(
datetime(const int year, const int month, const int day, const int hour, const int minute, const int second, const int zone = GMT); const int year,
const int month,
const int day
);
datetime(
const int year,
const int month,
const int day,
const int hour,
const int minute,
const int second,
const int zone = GMT
);
datetime(const datetime& d); datetime(const datetime& d);
datetime(const string& date); datetime(const string& date);
datetime(const time_t t, const int zone = GMT); datetime(const time_t t, const int zone = GMT);
@ -54,8 +64,8 @@ public:
~datetime(); ~datetime();
// Some time zones (in minutes) // Some time zones (in minutes)
enum TimeZones enum TimeZones {
{
GMT_12 = -720, // GMT-12h GMT_12 = -720, // GMT-12h
GMT_11 = -660, // GMT-11h GMT_11 = -660, // GMT-11h
GMT_10 = -600, // GMT-10h GMT_10 = -600, // GMT-10h
@ -124,8 +134,8 @@ public:
}; };
// Months list // Months list
enum Months enum Months {
{
// Long // Long
JANUARY = 1, JANUARY = 1,
FEBRUARY = 2, FEBRUARY = 2,
@ -155,8 +165,8 @@ public:
}; };
// Days of week list // Days of week list
enum DaysOfWeek enum DaysOfWeek {
{
// Long // Long
SUNDAY = 0, SUNDAY = 0,
MONDAY = 1, MONDAY = 1,
@ -242,18 +252,20 @@ public:
protected: protected:
// Component parsing & assembling // Component parsing & assembling
void parseImpl void parseImpl(
(const parsingContext& ctx, const parsingContext& ctx,
const string& buffer, const string& buffer,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
void generateImpl void generateImpl(
(const generationContext& ctx, const generationContext& ctx,
utility::outputStream& os, utility::outputStream& os,
const size_t curLinePos = 0, const size_t curLinePos = 0,
size_t* newLinePos = NULL) const; size_t* newLinePos = NULL
) const;
}; };

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -28,57 +28,75 @@
#include "vmime/encoding.hpp" #include "vmime/encoding.hpp"
namespace vmime namespace vmime {
{
defaultAttachment::defaultAttachment() defaultAttachment::defaultAttachment() {
{
} }
defaultAttachment::defaultAttachment(shared_ptr <const contentHandler> data, defaultAttachment::defaultAttachment(
const encoding& enc, const mediaType& type, const text& desc, const word& name) const shared_ptr <const contentHandler>& data,
: m_type(type), m_desc(desc), m_data(data), m_encoding(enc), m_name(name) const encoding& enc,
{ const mediaType& type,
const text& desc,
const word& name
)
: m_type(type),
m_desc(desc),
m_data(data),
m_encoding(enc),
m_name(name) {
} }
defaultAttachment::defaultAttachment(shared_ptr <const contentHandler> data, defaultAttachment::defaultAttachment(
const mediaType& type, const text& desc, const word& name) const shared_ptr <const contentHandler>& data,
: m_type(type), m_desc(desc), m_data(data), const mediaType& type,
m_encoding(encoding::decide(data)), m_name(name) const text& desc,
{ const word& name
)
: m_type(type),
m_desc(desc),
m_data(data),
m_encoding(encoding::decide(data)),
m_name(name) {
} }
defaultAttachment::defaultAttachment(const defaultAttachment& attach) defaultAttachment::defaultAttachment(const defaultAttachment& attach)
: attachment(), m_type(attach.m_type), m_desc(attach.m_desc), : attachment(),
m_type(attach.m_type),
m_desc(attach.m_desc),
m_data(vmime::clone(attach.m_data)), m_data(vmime::clone(attach.m_data)),
m_encoding(attach.m_encoding), m_name(attach.m_name) m_encoding(attach.m_encoding),
{ m_name(attach.m_name) {
} }
defaultAttachment::~defaultAttachment() defaultAttachment::~defaultAttachment() {
{
} }
defaultAttachment& defaultAttachment::operator=(const defaultAttachment& attach) defaultAttachment& defaultAttachment::operator=(const defaultAttachment& attach) {
{
m_type = attach.m_type; m_type = attach.m_type;
m_desc = attach.m_desc; m_desc = attach.m_desc;
m_name = attach.m_name; m_name = attach.m_name;
m_data = vmime::clone(attach.m_data); m_data = vmime::clone(attach.m_data);
m_encoding = attach.m_encoding; m_encoding = attach.m_encoding;
return (*this); return *this;
} }
void defaultAttachment::generateIn(shared_ptr <bodyPart> parent) const void defaultAttachment::generateIn(const shared_ptr <bodyPart>& parent) const {
{
// Create and append a new part for this attachment // Create and append a new part for this attachment
shared_ptr <bodyPart> part = make_shared <bodyPart>(); shared_ptr <bodyPart> part = make_shared <bodyPart>();
parent->getBody()->appendPart(part); parent->getBody()->appendPart(part);
@ -87,8 +105,8 @@ void defaultAttachment::generateIn(shared_ptr <bodyPart> parent) const
} }
void defaultAttachment::generatePart(shared_ptr <bodyPart> part) const void defaultAttachment::generatePart(const shared_ptr <bodyPart>& part) const {
{
// Set header fields // Set header fields
part->getHeader()->ContentType()->setValue(m_type); part->getHeader()->ContentType()->setValue(m_type);
if (!m_desc.isEmpty()) part->getHeader()->ContentDescription()->setValue(m_desc); if (!m_desc.isEmpty()) part->getHeader()->ContentDescription()->setValue(m_desc);
@ -101,44 +119,44 @@ void defaultAttachment::generatePart(shared_ptr <bodyPart> part) const
} }
const mediaType defaultAttachment::getType() const const mediaType defaultAttachment::getType() const {
{
return m_type; return m_type;
} }
const text defaultAttachment::getDescription() const const text defaultAttachment::getDescription() const {
{
return m_desc; return m_desc;
} }
const word defaultAttachment::getName() const const word defaultAttachment::getName() const {
{
return m_name; return m_name;
} }
const shared_ptr <const contentHandler> defaultAttachment::getData() const const shared_ptr <const contentHandler> defaultAttachment::getData() const {
{
return m_data; return m_data;
} }
const encoding defaultAttachment::getEncoding() const const encoding defaultAttachment::getEncoding() const {
{
return m_encoding; return m_encoding;
} }
shared_ptr <const object> defaultAttachment::getPart() const shared_ptr <const object> defaultAttachment::getPart() const {
{
return null; return null;
} }
shared_ptr <const header> defaultAttachment::getHeader() const shared_ptr <const header> defaultAttachment::getHeader() const {
{
return null; return null;
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -29,15 +29,13 @@
#include "vmime/encoding.hpp" #include "vmime/encoding.hpp"
namespace vmime namespace vmime {
{
/** Default implementation for attachments. /** Default implementation for attachments.
*/ */
class VMIME_EXPORT defaultAttachment : public attachment {
class VMIME_EXPORT defaultAttachment : public attachment
{
protected: protected:
// For use in derived classes. // For use in derived classes.
@ -45,8 +43,21 @@ protected:
public: public:
defaultAttachment(shared_ptr <const contentHandler> data, const encoding& enc, const mediaType& type, const text& desc = NULL_TEXT, const word& name = NULL_WORD); defaultAttachment(
defaultAttachment(shared_ptr <const contentHandler> data, const mediaType& type, const text& desc = NULL_TEXT, const word& name = NULL_WORD); const shared_ptr <const contentHandler>& data,
const encoding& enc,
const mediaType& type,
const text& desc = NULL_TEXT,
const word& name = NULL_WORD
);
defaultAttachment(
const shared_ptr <const contentHandler>& data,
const mediaType& type,
const text& desc = NULL_TEXT,
const word& name = NULL_WORD
);
defaultAttachment(const defaultAttachment& attach); defaultAttachment(const defaultAttachment& attach);
~defaultAttachment(); ~defaultAttachment();
@ -74,11 +85,11 @@ protected:
private: private:
// No need to override "generateIn", use "generatePart" instead (see below). // No need to override "generateIn", use "generatePart" instead (see below).
void generateIn(shared_ptr <bodyPart> parent) const; void generateIn(const shared_ptr <bodyPart>& parent) const;
protected: protected:
virtual void generatePart(shared_ptr <bodyPart> part) const; virtual void generatePart(const shared_ptr <bodyPart>& part) const;
}; };

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -27,25 +27,30 @@
#include "vmime/utility/stringUtils.hpp" #include "vmime/utility/stringUtils.hpp"
namespace vmime namespace vmime {
{
disposition::disposition() disposition::disposition() {
{
} }
disposition::disposition(const string& actionMode, const string& sendingMode, disposition::disposition(
const string& type, const string& modifier) const string& actionMode,
: m_actionMode(actionMode), m_sendingMode(sendingMode), m_type(type) const string& sendingMode,
{ const string& type,
const string& modifier
)
: m_actionMode(actionMode),
m_sendingMode(sendingMode),
m_type(type) {
m_modifiers.push_back(modifier); m_modifiers.push_back(modifier);
} }
shared_ptr <component> disposition::clone() const shared_ptr <component> disposition::clone() const {
{
shared_ptr <disposition> disp = make_shared <disposition>(); shared_ptr <disposition> disp = make_shared <disposition>();
disp->m_actionMode = m_actionMode; disp->m_actionMode = m_actionMode;
@ -55,12 +60,12 @@ shared_ptr <component> disposition::clone() const
std::copy(m_modifiers.begin(), m_modifiers.end(), disp->m_modifiers.begin()); std::copy(m_modifiers.begin(), m_modifiers.end(), disp->m_modifiers.begin());
return (disp); return disp;
} }
void disposition::copyFrom(const component& other) void disposition::copyFrom(const component& other) {
{
const disposition& disp = dynamic_cast <const disposition&>(other); const disposition& disp = dynamic_cast <const disposition&>(other);
m_actionMode = disp.m_actionMode; m_actionMode = disp.m_actionMode;
@ -72,71 +77,71 @@ void disposition::copyFrom(const component& other)
} }
disposition& disposition::operator=(const disposition& other) disposition& disposition::operator=(const disposition& other) {
{
copyFrom(other); copyFrom(other);
return (*this); return *this;
} }
const std::vector <shared_ptr <component> > disposition::getChildComponents() const std::vector <shared_ptr <component> > disposition::getChildComponents() {
{
return std::vector <shared_ptr <component> >(); return std::vector <shared_ptr <component> >();
} }
void disposition::setActionMode(const string& mode) void disposition::setActionMode(const string& mode) {
{
m_actionMode = mode; m_actionMode = mode;
} }
const string& disposition::getActionMode() const const string& disposition::getActionMode() const {
{
return (m_actionMode); return m_actionMode;
} }
void disposition::setSendingMode(const string& mode) void disposition::setSendingMode(const string& mode) {
{
m_sendingMode = mode; m_sendingMode = mode;
} }
const string& disposition::getSendingMode() const const string& disposition::getSendingMode() const {
{
return (m_sendingMode); return m_sendingMode;
} }
void disposition::setType(const string& type) void disposition::setType(const string& type) {
{
m_type = type; m_type = type;
} }
const string& disposition::getType() const const string& disposition::getType() const {
{
return (m_type); return m_type;
} }
void disposition::addModifier(const string& modifier) void disposition::addModifier(const string& modifier) {
{
if (!hasModifier(modifier)) if (!hasModifier(modifier)) {
m_modifiers.push_back(utility::stringUtils::toLower(modifier)); m_modifiers.push_back(utility::stringUtils::toLower(modifier));
}
} }
void disposition::removeModifier(const string& modifier) void disposition::removeModifier(const string& modifier) {
{
const string modifierLC = utility::stringUtils::toLower(modifier); const string modifierLC = utility::stringUtils::toLower(modifier);
for (std::vector <string>::iterator it = m_modifiers.begin() ; for (std::vector <string>::iterator it = m_modifiers.begin() ;
it != m_modifiers.end() ; ++it) it != m_modifiers.end() ; ++it) {
{
if (*it == modifierLC) if (*it == modifierLC) {
{
m_modifiers.erase(it); m_modifiers.erase(it);
break; break;
} }
@ -144,37 +149,42 @@ void disposition::removeModifier(const string& modifier)
} }
void disposition::removeAllModifiers() void disposition::removeAllModifiers() {
{
m_modifiers.clear(); m_modifiers.clear();
} }
bool disposition::hasModifier(const string& modifier) const bool disposition::hasModifier(const string& modifier) const {
{
const string modifierLC = utility::stringUtils::toLower(modifier); const string modifierLC = utility::stringUtils::toLower(modifier);
for (std::vector <string>::const_iterator it = m_modifiers.begin() ; for (std::vector <string>::const_iterator it = m_modifiers.begin() ;
it != m_modifiers.end() ; ++it) it != m_modifiers.end() ; ++it) {
{
if (*it == modifierLC) if (*it == modifierLC) {
return (true); return true;
}
} }
return (false); return false;
} }
const std::vector <string> disposition::getModifierList() const const std::vector <string> disposition::getModifierList() const {
{
return (m_modifiers); return m_modifiers;
} }
void disposition::parseImpl void disposition::parseImpl(
(const parsingContext& /* ctx */, const string& buffer, const size_t position, const parsingContext& /* ctx */,
const size_t end, size_t* newPosition) const string& buffer,
{ const size_t position,
const size_t end,
size_t* newPosition
) {
// disposition-mode ";" disposition-type // disposition-mode ";" disposition-type
// [ "/" disposition-modifier *( "," disposition-modifier ) ] // [ "/" disposition-modifier *( "," disposition-modifier ) ]
// //
@ -182,105 +192,116 @@ void disposition::parseImpl
size_t pos = position; size_t pos = position;
while (pos < end && parserHelpers::isSpace(buffer[pos])) while (pos < end && parserHelpers::isSpace(buffer[pos])) {
++pos; ++pos;
}
// -- disposition-mode // -- disposition-mode
const size_t modeStart = pos; const size_t modeStart = pos;
size_t modeEnd = pos; size_t modeEnd = pos;
while (pos < end && buffer[pos] != ';') while (pos < end && buffer[pos] != ';') {
{
++modeEnd; ++modeEnd;
++pos; ++pos;
} }
while (modeEnd > modeStart && parserHelpers::isSpace(buffer[modeEnd - 1])) while (modeEnd > modeStart && parserHelpers::isSpace(buffer[modeEnd - 1])) {
--modeEnd; --modeEnd;
}
const string mode = string(buffer.begin() + modeStart, buffer.begin() + modeEnd); const string mode = string(buffer.begin() + modeStart, buffer.begin() + modeEnd);
const size_t slash = mode.find('/'); const size_t slash = mode.find('/');
if (slash != string::npos) if (slash != string::npos) {
{
m_actionMode = string(mode.begin(), mode.begin() + slash); m_actionMode = string(mode.begin(), mode.begin() + slash);
m_sendingMode = string(mode.begin() + slash + 1, mode.end()); m_sendingMode = string(mode.begin() + slash + 1, mode.end());
}
else } else {
{
m_actionMode = mode; m_actionMode = mode;
m_sendingMode.clear(); m_sendingMode.clear();
} }
if (pos < end) if (pos < end) {
{
// Skip ';' // Skip ';'
++pos; ++pos;
} }
while (pos < end && parserHelpers::isSpace(buffer[pos])) while (pos < end && parserHelpers::isSpace(buffer[pos])) {
++pos; ++pos;
}
// -- disposition-type // -- disposition-type
const size_t typeStart = pos; const size_t typeStart = pos;
size_t typeEnd = pos; size_t typeEnd = pos;
while (pos < end && buffer[pos] != '/') while (pos < end && buffer[pos] != '/') {
{
++typeEnd; ++typeEnd;
++pos; ++pos;
} }
while (typeEnd > typeStart && parserHelpers::isSpace(buffer[typeEnd - 1])) while (typeEnd > typeStart && parserHelpers::isSpace(buffer[typeEnd - 1])) {
--typeEnd; --typeEnd;
}
m_type = string(buffer.begin() + typeStart, buffer.begin() + typeEnd); m_type = string(buffer.begin() + typeStart, buffer.begin() + typeEnd);
m_modifiers.clear(); m_modifiers.clear();
if (pos < end) // modifiers follow if (pos < end) { // modifiers follow
{
// Skip '/' // Skip '/'
++pos; ++pos;
while (pos < end) while (pos < end) {
{
while (pos < end && parserHelpers::isSpace(buffer[pos])) while (pos < end && parserHelpers::isSpace(buffer[pos])) {
++pos; ++pos;
}
const size_t modifierStart = pos; const size_t modifierStart = pos;
size_t modifierEnd = pos; size_t modifierEnd = pos;
while (pos < end && buffer[pos] != ',') while (pos < end && buffer[pos] != ',') {
{
++modifierEnd; ++modifierEnd;
++pos; ++pos;
} }
while (modifierEnd > modifierStart && parserHelpers::isSpace(buffer[modifierEnd - 1])) while (modifierEnd > modifierStart && parserHelpers::isSpace(buffer[modifierEnd - 1])) {
--modifierEnd; --modifierEnd;
}
if (modifierEnd > modifierStart) if (modifierEnd > modifierStart) {
{
m_modifiers.push_back(string(buffer.begin() + modifierStart, m_modifiers.push_back(
buffer.begin() + modifierEnd)); string(
buffer.begin() + modifierStart,
buffer.begin() + modifierEnd
)
);
} }
// Skip ',' // Skip ','
if (pos < end) if (pos < end) {
++pos; ++pos;
}
} }
} }
if (newPosition) if (newPosition) {
*newPosition = pos; *newPosition = pos;
}
} }
void disposition::generateImpl void disposition::generateImpl(
(const generationContext& ctx, utility::outputStream& os, const generationContext& ctx,
const size_t curLinePos, size_t* newLinePos) const utility::outputStream& os,
{ const size_t curLinePos,
size_t* newLinePos
) const {
size_t pos = curLinePos; size_t pos = curLinePos;
const string actionMode = (m_actionMode.empty() ? "automatic-action" : m_actionMode); const string actionMode = (m_actionMode.empty() ? "automatic-action" : m_actionMode);
@ -289,8 +310,7 @@ void disposition::generateImpl
os << actionMode << "/" << sendingMode << ";"; os << actionMode << "/" << sendingMode << ";";
pos += actionMode.length() + 1 + sendingMode.length() + 1; pos += actionMode.length() + 1 + sendingMode.length() + 1;
if (pos > ctx.getMaxLineLength()) if (pos > ctx.getMaxLineLength()) {
{
os << NEW_LINE_SEQUENCE; os << NEW_LINE_SEQUENCE;
pos = NEW_LINE_SEQUENCE_LENGTH; pos = NEW_LINE_SEQUENCE_LENGTH;
} }
@ -300,18 +320,19 @@ void disposition::generateImpl
os << type; os << type;
pos += type.length(); pos += type.length();
if (m_modifiers.size() >= 1) if (m_modifiers.size() >= 1) {
{
for (std::vector <string>::size_type i = 0, n = 0 ; i < m_modifiers.size() ; ++i) for (std::vector <string>::size_type i = 0, n = 0 ; i < m_modifiers.size() ; ++i) {
{
const string mod = utility::stringUtils::trim(m_modifiers[i]); const string mod = utility::stringUtils::trim(m_modifiers[i]);
if (!mod.empty()) if (!mod.empty()) {
{
if (n == 0) if (n == 0) {
os << "/"; os << "/";
else } else {
os << ","; os << ",";
}
os << mod; os << mod;
pos += 1 + mod.length(); pos += 1 + mod.length();
@ -321,8 +342,9 @@ void disposition::generateImpl
} }
} }
if (newLinePos) if (newLinePos) {
*newLinePos = pos; *newLinePos = pos;
}
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -31,19 +31,22 @@
#include <vector> #include <vector>
namespace vmime namespace vmime {
{
/** Disposition - from RFC-3798 (basic type). /** Disposition - from RFC-3798 (basic type).
*/ */
class VMIME_EXPORT disposition : public headerFieldValue {
class VMIME_EXPORT disposition : public headerFieldValue
{
public: public:
disposition(); disposition();
disposition(const string& actionMode, const string& sendingMode, const string& type, const string& modifier); disposition(
const string& actionMode,
const string& sendingMode,
const string& type,
const string& modifier
);
shared_ptr <component> clone() const; shared_ptr <component> clone() const;
@ -137,18 +140,20 @@ private:
protected: protected:
// Component parsing & assembling // Component parsing & assembling
void parseImpl void parseImpl(
(const parsingContext& ctx, const parsingContext& ctx,
const string& buffer, const string& buffer,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
void generateImpl void generateImpl(
(const generationContext& ctx, const generationContext& ctx,
utility::outputStream& os, utility::outputStream& os,
const size_t curLinePos = 0, const size_t curLinePos = 0,
size_t* newLinePos = NULL) const; size_t* newLinePos = NULL
) const;
}; };
@ -156,4 +161,3 @@ protected:
#endif // VMIME_DISPOSITION_HPP_INCLUDED #endif // VMIME_DISPOSITION_HPP_INCLUDED

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -31,8 +31,7 @@
#include "vmime/utility/stringUtils.hpp" #include "vmime/utility/stringUtils.hpp"
namespace vmime namespace vmime {
{
/** Decode an IDNA-encoded domain name ("xn--5rtw95l.xn--wgv71a") /** Decode an IDNA-encoded domain name ("xn--5rtw95l.xn--wgv71a")
@ -41,48 +40,52 @@ namespace vmime
* @param idnaDomain domain name encoded with IDNA * @param idnaDomain domain name encoded with IDNA
* @return decoded domain name in UTF-8 * @return decoded domain name in UTF-8
*/ */
static const string domainNameFromIDNA(const string& idnaDomain) static const string domainNameFromIDNA(const string& idnaDomain) {
{
std::ostringstream domainName; std::ostringstream domainName;
size_t p = 0; size_t p = 0;
for (size_t n = idnaDomain.find('.', p) ; for (size_t n = idnaDomain.find('.', p) ;
(n = idnaDomain.find('.', p)) != string::npos ; p = n + 1) (n = idnaDomain.find('.', p)) != string::npos ; p = n + 1) {
{
const string encodedPart(idnaDomain.begin() + p, idnaDomain.begin() + n); const string encodedPart(idnaDomain.begin() + p, idnaDomain.begin() + n);
if (encodedPart.length() > 4 && if (encodedPart.length() > 4 &&
encodedPart[0] == 'x' && encodedPart[1] == 'n' && encodedPart[0] == 'x' && encodedPart[1] == 'n' &&
encodedPart[2] == '-' && encodedPart[3] == '-') encodedPart[2] == '-' && encodedPart[3] == '-') {
{
string decodedPart; string decodedPart;
charset::convert(encodedPart, decodedPart, charset::convert(
vmime::charsets::IDNA, vmime::charsets::UTF_8); encodedPart, decodedPart,
vmime::charsets::IDNA, vmime::charsets::UTF_8
);
domainName << decodedPart << '.'; domainName << decodedPart << '.';
}
else } else {
{
domainName << encodedPart << '.'; // not encoded domainName << encodedPart << '.'; // not encoded
} }
} }
if (p < idnaDomain.length()) if (p < idnaDomain.length()) {
{
const string encodedPart(idnaDomain.begin() + p, idnaDomain.end()); const string encodedPart(idnaDomain.begin() + p, idnaDomain.end());
if (encodedPart.length() > 4 && if (encodedPart.length() > 4 &&
encodedPart[0] == 'x' && encodedPart[1] == 'n' && encodedPart[0] == 'x' && encodedPart[1] == 'n' &&
encodedPart[2] == '-' && encodedPart[3] == '-') encodedPart[2] == '-' && encodedPart[3] == '-') {
{
string decodedPart; string decodedPart;
charset::convert(encodedPart, decodedPart, charset::convert(
vmime::charsets::IDNA, vmime::charsets::UTF_8); encodedPart, decodedPart,
vmime::charsets::IDNA, vmime::charsets::UTF_8
);
domainName << decodedPart; domainName << decodedPart;
}
else } else {
{
domainName << encodedPart; // not encoded domainName << encodedPart; // not encoded
} }
} }
@ -97,26 +100,30 @@ static const string domainNameFromIDNA(const string& idnaDomain)
* @param domainName domain name in UTF-8 * @param domainName domain name in UTF-8
* @return domain name encoded with IDNA * @return domain name encoded with IDNA
*/ */
static const string domainNameToIDNA(const string& domainName) static const string domainNameToIDNA(const string& domainName) {
{
std::ostringstream idnaDomain; std::ostringstream idnaDomain;
size_t p = 0; size_t p = 0;
for (size_t n = domainName.find('.', p) ; for (size_t n = domainName.find('.', p) ;
(n = domainName.find('.', p)) != string::npos ; p = n + 1) (n = domainName.find('.', p)) != string::npos ; p = n + 1) {
{
string idnaPart; string idnaPart;
charset::convert(string(domainName.begin() + p, domainName.begin() + n), charset::convert(
idnaPart, vmime::charsets::UTF_8, vmime::charsets::IDNA); string(domainName.begin() + p, domainName.begin() + n), idnaPart,
vmime::charsets::UTF_8, vmime::charsets::IDNA
);
idnaDomain << idnaPart << '.'; idnaDomain << idnaPart << '.';
} }
if (p < domainName.length()) if (p < domainName.length()) {
{
string idnaPart; string idnaPart;
charset::convert(string(domainName.begin() + p, domainName.end()), charset::convert(
idnaPart, vmime::charsets::UTF_8, vmime::charsets::IDNA); string(domainName.begin() + p, domainName.end()), idnaPart,
vmime::charsets::UTF_8, vmime::charsets::IDNA
);
idnaDomain << idnaPart; idnaDomain << idnaPart;
} }
@ -127,52 +134,60 @@ static const string domainNameToIDNA(const string& domainName)
emailAddress::emailAddress() emailAddress::emailAddress() {
{
} }
emailAddress::emailAddress(const emailAddress& eml) emailAddress::emailAddress(const emailAddress& eml)
: component(), m_localName(eml.m_localName), m_domainName(eml.m_domainName) : component(),
{ m_localName(eml.m_localName),
m_domainName(eml.m_domainName) {
} }
emailAddress::emailAddress(const string& email) emailAddress::emailAddress(const string& email) {
{
parse(email); parse(email);
} }
emailAddress::emailAddress(const char* email) emailAddress::emailAddress(const char* email) {
{
parse(email); parse(email);
} }
emailAddress::emailAddress(const string& localName, const string& domainName) emailAddress::emailAddress(const string& localName, const string& domainName)
: component(), m_localName(word(localName, vmime::charsets::UTF_8)), : component(),
m_domainName(word(domainName, vmime::charsets::UTF_8)) m_localName(word(localName, vmime::charsets::UTF_8)),
{ m_domainName(word(domainName, vmime::charsets::UTF_8)) {
} }
emailAddress::emailAddress(const word& localName, const word& domainName) emailAddress::emailAddress(const word& localName, const word& domainName)
: component(), m_localName(localName), m_domainName(domainName) : component(),
{ m_localName(localName),
m_domainName(domainName) {
} }
void emailAddress::parseImpl void emailAddress::parseImpl(
(const parsingContext& /* ctx */, const string& buffer, const size_t position, const parsingContext& /* ctx */,
const size_t end, size_t* newPosition) const string& buffer,
{ const size_t position,
const size_t end,
size_t* newPosition
) {
const char* const pend = buffer.data() + end; const char* const pend = buffer.data() + end;
const char* const pstart = buffer.data() + position; const char* const pstart = buffer.data() + position;
const char* p = pstart; const char* p = pstart;
enum ParserStates enum ParserStates {
{
State_Before, State_Before,
State_LocalPartStart, State_LocalPartStart,
State_LocalPartMiddle, State_LocalPartMiddle,
@ -199,359 +214,367 @@ void emailAddress::parseImpl
int commentLevel = 0; int commentLevel = 0;
bool localPartIsRFC2047 = false; bool localPartIsRFC2047 = false;
while (p < pend && !stop) while (p < pend && !stop) {
{
const char c = *p; const char c = *p;
if ((localPart.str().length() + domainPart.str().length()) >= 256) if ((localPart.str().length() + domainPart.str().length()) >= 256) {
{
state = State_Error; state = State_Error;
break; break;
} }
switch (state) switch (state) {
{
case State_Before:
if (parserHelpers::isSpace(c)) case State_Before:
++p;
else
state = State_LocalPartStart;
case State_LocalPartStart: if (parserHelpers::isSpace(c)) {
++p;
if (c == '"') } else {
{ state = State_LocalPartStart;
state = State_LocalPartQuoted;
++p;
}
else if (c == '=')
{
state = State_LocalPartRFC2047Start;
++p;
}
else if (c == '(')
{
state = State_LocalPartComment;
++commentLevel;
++p;
}
else
{
state = State_LocalPartMiddle;
localPart << c;
++p;
}
break;
case State_LocalPartComment:
if (escapeNext)
{
escapeNext = false;
++p;
}
else if (c == '\\')
{
escapeNext = true;
++p;
}
else if (c == '(')
{
++commentLevel;
++p;
}
else if (c == ')')
{
if (--commentLevel == 0)
{
// End of comment
state = State_LocalPartMiddle;
} }
++p; break;
}
else
{
// Comment continues
++p;
}
break; case State_LocalPartStart:
case State_LocalPartQuoted: if (c == '"') {
if (escapeNext) state = State_LocalPartQuoted;
{ ++p;
escapeNext = false;
if (c == '"' || c == '\\') } else if (c == '=') {
{
state = State_LocalPartRFC2047Start;
++p;
} else if (c == '(') {
state = State_LocalPartComment;
++commentLevel;
++p;
} else {
state = State_LocalPartMiddle;
localPart << c; localPart << c;
++p; ++p;
} }
else
{ break;
// This char cannot be escaped
state = State_Error; case State_LocalPartComment:
if (escapeNext) {
escapeNext = false;
++p;
} else if (c == '\\') {
escapeNext = true;
++p;
} else if (c == '(') {
++commentLevel;
++p;
} else if (c == ')') {
if (--commentLevel == 0) {
// End of comment
state = State_LocalPartMiddle;
}
++p;
} else {
// Comment continues
++p;
} }
}
else if (c == '"')
{
// End of quoted string
state = State_LocalPartMiddle;
++p;
}
else if (c == '\\')
{
escapeNext = true;
++p;
}
else
{
localPart << c;
++p;
}
break; break;
case State_LocalPartRFC2047Start: case State_LocalPartQuoted:
if (c == '?') if (escapeNext) {
{
state = State_LocalPartRFC2047Middle;
localPart << "=?";
localPartIsRFC2047 = true;
++p;
}
else
{
state = State_LocalPartMiddle;
localPart << '=';
localPart << c;
++p;
}
break; escapeNext = false;
case State_LocalPartMiddle: if (c == '"' || c == '\\') {
if (c == '.') localPart << c;
{ ++p;
prevIsDot = true;
localPart << c;
++p;
}
else if (c == '"' && prevIsDot)
{
prevIsDot = false;
state = State_LocalPartQuoted;
++p;
}
else if (c == '(')
{
// By allowing comments anywhere in the local part,
// we are more permissive than RFC-2822
state = State_LocalPartComment;
++commentLevel;
++p;
}
else if (c == '@')
{
atFound = true;
state = State_DomainPartStart;
++p;
}
else if (parserHelpers::isSpace(c))
{
// Allow not specifying domain part
state = State_End;
}
else
{
prevIsDot = false;
localPart << c;
++p;
}
break; } else {
case State_LocalPartRFC2047Middle: // This char cannot be escaped
state = State_Error;
}
if (c == '?') } else if (c == '"') {
{
state = State_LocalPartRFC2047MiddleQM;
++p;
}
else
{
localPart << c;
++p;
}
break; // End of quoted string
state = State_LocalPartMiddle;
++p;
case State_LocalPartRFC2047MiddleQM: } else if (c == '\\') {
if (c == '=') escapeNext = true;
{ ++p;
// End of RFC-2047 encoded word
state = State_LocalPartRFC2047End;
localPart << "?=";
++p;
}
else
{
state = State_LocalPartRFC2047Middle;
localPart << '?';
localPart << c;
++p;
}
break; } else {
case State_LocalPartRFC2047End: localPart << c;
++p;
}
if (c == '@') break;
{
atFound = true;
state = State_DomainPartStart;
++p;
}
else
{
state = State_End;
}
break; case State_LocalPartRFC2047Start:
case State_DomainPartStart: if (c == '?') {
if (c == '(') state = State_LocalPartRFC2047Middle;
{ localPart << "=?";
state = State_DomainPartComment; localPartIsRFC2047 = true;
++commentLevel; ++p;
++p;
}
else
{
state = State_DomainPartMiddle;
domainPart << c;
++p;
}
break; } else {
case State_DomainPartMiddle: state = State_LocalPartMiddle;
localPart << '=';
localPart << c;
++p;
}
if (parserHelpers::isSpace(c)) break;
{
state = State_End;
}
else if (c == '(')
{
// By allowing comments anywhere in the domain part,
// we are more permissive than RFC-2822
state = State_DomainPartComment;
++commentLevel;
++p;
}
else
{
domainPart << c;
++p;
}
break; case State_LocalPartMiddle:
case State_DomainPartComment: if (c == '.') {
prevIsDot = true;
localPart << c;
++p;
} else if (c == '"' && prevIsDot) {
prevIsDot = false;
state = State_LocalPartQuoted;
++p;
} else if (c == '(') {
// By allowing comments anywhere in the local part,
// we are more permissive than RFC-2822
state = State_LocalPartComment;
++commentLevel;
++p;
} else if (c == '@') {
atFound = true;
state = State_DomainPartStart;
++p;
} else if (parserHelpers::isSpace(c)) {
// Allow not specifying domain part
state = State_End;
} else {
prevIsDot = false;
localPart << c;
++p;
}
break;
case State_LocalPartRFC2047Middle:
if (c == '?') {
state = State_LocalPartRFC2047MiddleQM;
++p;
} else {
localPart << c;
++p;
}
break;
case State_LocalPartRFC2047MiddleQM:
if (c == '=') {
// End of RFC-2047 encoded word
state = State_LocalPartRFC2047End;
localPart << "?=";
++p;
} else {
state = State_LocalPartRFC2047Middle;
localPart << '?';
localPart << c;
++p;
}
break;
case State_LocalPartRFC2047End:
if (c == '@') {
atFound = true;
state = State_DomainPartStart;
++p;
} else {
state = State_End;
}
break;
case State_DomainPartStart:
if (c == '(') {
state = State_DomainPartComment;
++commentLevel;
++p;
} else {
if (escapeNext)
{
escapeNext = false;
++p;
}
else if (c == '\\')
{
escapeNext = true;
++p;
}
else if (c == '(')
{
++commentLevel;
++p;
}
else if (c == ')')
{
if (--commentLevel == 0)
{
// End of comment
state = State_DomainPartMiddle; state = State_DomainPartMiddle;
domainPart << c;
++p;
} }
++p; break;
}
else
{
// Comment continues
++p;
}
break; case State_DomainPartMiddle:
case State_End: if (parserHelpers::isSpace(c)) {
case State_Error:
stop = true; state = State_End;
break;
} else if (c == '(') {
// By allowing comments anywhere in the domain part,
// we are more permissive than RFC-2822
state = State_DomainPartComment;
++commentLevel;
++p;
} else {
domainPart << c;
++p;
}
break;
case State_DomainPartComment:
if (escapeNext) {
escapeNext = false;
++p;
} else if (c == '\\') {
escapeNext = true;
++p;
} else if (c == '(') {
++commentLevel;
++p;
} else if (c == ')') {
if (--commentLevel == 0) {
// End of comment
state = State_DomainPartMiddle;
}
++p;
} else {
// Comment continues
++p;
}
break;
case State_End:
case State_Error:
stop = true;
break;
} }
} }
if (p == pend && state != State_Error) if (p == pend && state != State_Error) {
{
if (state == State_DomainPartMiddle) if (state == State_DomainPartMiddle) {
state = State_End; state = State_End;
else if (state == State_LocalPartMiddle) } else if (state == State_LocalPartMiddle) {
state = State_End; // allow not specifying domain part state = State_End; // allow not specifying domain part
}
} }
if (state != State_End) if (state != State_End) {
{
m_localName = word("invalid", vmime::charsets::UTF_8); m_localName = word("invalid", vmime::charsets::UTF_8);
m_domainName = word("invalid", vmime::charsets::UTF_8); m_domainName = word("invalid", vmime::charsets::UTF_8);
}
else
{
// If the domain part is missing, use local host name
if (domainPart.str().empty() && !atFound)
domainPart << platform::getHandler()->getHostName();
if (localPartIsRFC2047) } else {
// If the domain part is missing, use local host name
if (domainPart.str().empty() && !atFound) {
domainPart << platform::getHandler()->getHostName();
}
if (localPartIsRFC2047) {
m_localName.parse(localPart.str()); m_localName.parse(localPart.str());
else } else {
m_localName = word(localPart.str(), vmime::charsets::UTF_8); m_localName = word(localPart.str(), vmime::charsets::UTF_8);
}
m_domainName = word(domainNameFromIDNA(domainPart.str()), vmime::charsets::UTF_8); m_domainName = word(domainNameFromIDNA(domainPart.str()), vmime::charsets::UTF_8);
} }
setParsedBounds(position, p - pend); setParsedBounds(position, p - pend);
if (newPosition) if (newPosition) {
*newPosition = p - pend; *newPosition = p - pend;
}
} }
void emailAddress::generateImpl void emailAddress::generateImpl(
(const generationContext& ctx, utility::outputStream& os, const generationContext& ctx,
const size_t curLinePos, size_t* newLinePos) const utility::outputStream& os,
{ const size_t curLinePos,
size_t* newLinePos
) const {
string localPart, domainPart; string localPart, domainPart;
if (ctx.getInternationalizedEmailSupport() && if (ctx.getInternationalizedEmailSupport() &&
(!utility::stringUtils::is7bit(m_localName.getBuffer()) || (!utility::stringUtils::is7bit(m_localName.getBuffer()) ||
!utility::stringUtils::is7bit(m_domainName.getBuffer()))) !utility::stringUtils::is7bit(m_domainName.getBuffer()))) {
{
// Local part // Local part
string localPartUTF8(m_localName.getConvertedText(vmime::charsets::UTF_8)); string localPartUTF8(m_localName.getConvertedText(vmime::charsets::UTF_8));
word localPartWord(localPartUTF8, vmime::charsets::UTF_8); word localPartWord(localPartUTF8, vmime::charsets::UTF_8);
@ -561,9 +584,9 @@ void emailAddress::generateImpl
// Domain part // Domain part
domainPart = m_domainName.getConvertedText(vmime::charsets::UTF_8); domainPart = m_domainName.getConvertedText(vmime::charsets::UTF_8);
}
else } else {
{
// Local part // Local part
vmime::utility::outputStreamStringAdapter os(localPart); vmime::utility::outputStreamStringAdapter os(localPart);
m_localName.generate(ctx, os, 0, NULL, text::QUOTE_IF_NEEDED, NULL); m_localName.generate(ctx, os, 0, NULL, text::QUOTE_IF_NEEDED, NULL);
@ -576,8 +599,8 @@ void emailAddress::generateImpl
<< "@" << "@"
<< domainPart; << domainPart;
if (newLinePos) if (newLinePos) {
{
*newLinePos = curLinePos *newLinePos = curLinePos
+ localPart.length() + localPart.length()
+ 1 // @ + 1 // @
@ -586,21 +609,21 @@ void emailAddress::generateImpl
} }
bool emailAddress::operator==(const class emailAddress& eml) const bool emailAddress::operator==(const class emailAddress& eml) const {
{
return (m_localName == eml.m_localName && return m_localName == eml.m_localName &&
m_domainName == eml.m_domainName); m_domainName == eml.m_domainName;
} }
bool emailAddress::operator!=(const class emailAddress& eml) const bool emailAddress::operator!=(const class emailAddress& eml) const {
{
return !(*this == eml); return !(*this == eml);
} }
void emailAddress::copyFrom(const component& other) void emailAddress::copyFrom(const component& other) {
{
const emailAddress& source = dynamic_cast <const emailAddress&>(other); const emailAddress& source = dynamic_cast <const emailAddress&>(other);
m_localName = source.m_localName; m_localName = source.m_localName;
@ -608,57 +631,57 @@ void emailAddress::copyFrom(const component& other)
} }
emailAddress& emailAddress::operator=(const emailAddress& other) emailAddress& emailAddress::operator=(const emailAddress& other) {
{
copyFrom(other); copyFrom(other);
return (*this); return *this;
} }
shared_ptr <component>emailAddress::clone() const shared_ptr <component>emailAddress::clone() const {
{
return make_shared <emailAddress>(*this); return make_shared <emailAddress>(*this);
} }
const word& emailAddress::getLocalName() const const word& emailAddress::getLocalName() const {
{
return m_localName; return m_localName;
} }
void emailAddress::setLocalName(const word& localName) void emailAddress::setLocalName(const word& localName) {
{
m_localName = localName; m_localName = localName;
} }
const word& emailAddress::getDomainName() const const word& emailAddress::getDomainName() const {
{
return m_domainName; return m_domainName;
} }
void emailAddress::setDomainName(const word& domainName) void emailAddress::setDomainName(const word& domainName) {
{
m_domainName = domainName; m_domainName = domainName;
} }
const std::vector <shared_ptr <component> > emailAddress::getChildComponents() const std::vector <shared_ptr <component> > emailAddress::getChildComponents() {
{
return std::vector <shared_ptr <component> >(); return std::vector <shared_ptr <component> >();
} }
bool emailAddress::isEmpty() const bool emailAddress::isEmpty() const {
{
return m_localName.isEmpty(); return m_localName.isEmpty();
} }
const string emailAddress::toString() const const string emailAddress::toString() const {
{
std::ostringstream oss; std::ostringstream oss;
utility::outputStreamAdapter adapter(oss); utility::outputStreamAdapter adapter(oss);
@ -671,8 +694,8 @@ const string emailAddress::toString() const
} }
const text emailAddress::toText() const const text emailAddress::toText() const {
{
text txt; text txt;
txt.appendWord(make_shared <vmime::word>(m_localName)); txt.appendWord(make_shared <vmime::word>(m_localName));
txt.appendWord(make_shared <vmime::word>("@", vmime::charsets::US_ASCII)); txt.appendWord(make_shared <vmime::word>("@", vmime::charsets::US_ASCII));

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -29,15 +29,13 @@
#include "vmime/text.hpp" #include "vmime/text.hpp"
namespace vmime namespace vmime {
{
/** An email address: local name and domain name (basic type). /** An email address: local name and domain name (basic type).
*/ */
class VMIME_EXPORT emailAddress : public component {
class VMIME_EXPORT emailAddress : public component
{
public: public:
emailAddress(); emailAddress();
@ -114,18 +112,20 @@ public:
using component::generate; using component::generate;
// Component parsing & assembling // Component parsing & assembling
void parseImpl void parseImpl(
(const parsingContext& ctx, const parsingContext& ctx,
const string& buffer, const string& buffer,
const size_t position, const size_t position,
const size_t end, const size_t end,
size_t* newPosition = NULL); size_t* newPosition = NULL
);
void generateImpl void generateImpl(
(const generationContext& ctx, const generationContext& ctx,
utility::outputStream& os, utility::outputStream& os,
const size_t curLinePos = 0, const size_t curLinePos = 0,
size_t* newLinePos = NULL) const; size_t* newLinePos = NULL
) const;
}; };

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -24,92 +24,101 @@
#include "vmime/emptyContentHandler.hpp" #include "vmime/emptyContentHandler.hpp"
namespace vmime namespace vmime {
{
emptyContentHandler::emptyContentHandler() emptyContentHandler::emptyContentHandler() {
{
} }
shared_ptr <contentHandler> emptyContentHandler::clone() const shared_ptr <contentHandler> emptyContentHandler::clone() const {
{
return make_shared <emptyContentHandler>(); return make_shared <emptyContentHandler>();
} }
void emptyContentHandler::generate(utility::outputStream& /* os */, const vmime::encoding& /* enc */, void emptyContentHandler::generate(
const size_t /* maxLineLength */) const utility::outputStream& /* os */,
{ const vmime::encoding& /* enc */,
const size_t /* maxLineLength */
) const {
// Nothing to do. // Nothing to do.
} }
void emptyContentHandler::extract(utility::outputStream& /* os */, void emptyContentHandler::extract(
utility::outputStream& /* os */,
utility::progressListener* progress) const utility::progressListener* progress) const
{ {
if (progress) if (progress) {
progress->start(0); progress->start(0);
}
// Nothing to do. // Nothing to do.
if (progress) if (progress) {
progress->stop(0); progress->stop(0);
}
} }
void emptyContentHandler::extractRaw(utility::outputStream& /* os */, void emptyContentHandler::extractRaw(
utility::progressListener* progress) const utility::outputStream& /* os */,
{ utility::progressListener* progress
if (progress) ) const {
if (progress) {
progress->start(0); progress->start(0);
}
// Nothing to do. // Nothing to do.
if (progress) if (progress) {
progress->stop(0); progress->stop(0);
}
} }
size_t emptyContentHandler::getLength() const size_t emptyContentHandler::getLength() const {
{
return (0); return 0;
} }
bool emptyContentHandler::isEmpty() const bool emptyContentHandler::isEmpty() const {
{
return (true);
}
bool emptyContentHandler::isEncoded() const
{
return (false);
}
const vmime::encoding& emptyContentHandler::getEncoding() const
{
return (NO_ENCODING);
}
bool emptyContentHandler::isBuffered() const
{
return true; return true;
} }
void emptyContentHandler::setContentTypeHint(const mediaType& type) bool emptyContentHandler::isEncoded() const {
{
return false;
}
const vmime::encoding& emptyContentHandler::getEncoding() const {
return NO_ENCODING;
}
bool emptyContentHandler::isBuffered() const {
return true;
}
void emptyContentHandler::setContentTypeHint(const mediaType& type) {
m_contentType = type; m_contentType = type;
} }
const mediaType emptyContentHandler::getContentTypeHint() const const mediaType emptyContentHandler::getContentTypeHint() const {
{
return m_contentType; return m_contentType;
} }

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -28,22 +28,32 @@
#include "vmime/contentHandler.hpp" #include "vmime/contentHandler.hpp"
namespace vmime namespace vmime {
{
class VMIME_EXPORT emptyContentHandler : public contentHandler class VMIME_EXPORT emptyContentHandler : public contentHandler {
{
public: public:
emptyContentHandler(); emptyContentHandler();
shared_ptr <contentHandler> clone() const; shared_ptr <contentHandler> clone() const;
void generate(utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength = lineLengthLimits::infinite) const; void generate(
utility::outputStream& os,
const vmime::encoding& enc,
const size_t maxLineLength = lineLengthLimits::infinite
) const;
void extract(utility::outputStream& os, utility::progressListener* progress = NULL) const; void extract(
void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const; utility::outputStream& os,
utility::progressListener* progress = NULL
) const;
void extractRaw(
utility::outputStream& os,
utility::progressListener* progress = NULL
) const;
size_t getLength() const; size_t getLength() const;

View File

@ -1,6 +1,6 @@
// //
// VMime library (http://www.vmime.org) // VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org> // Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -30,118 +30,140 @@
#include <algorithm> #include <algorithm>
namespace vmime namespace vmime {
{
encoding::encoding() encoding::encoding()
: m_name(encodingTypes::SEVEN_BIT), : m_name(encodingTypes::SEVEN_BIT),
m_usage(USAGE_UNKNOWN) m_usage(USAGE_UNKNOWN) {
{
} }
encoding::encoding(const string& name) encoding::encoding(const string& name)
: m_name(utility::stringUtils::toLower(name)), : m_name(utility::stringUtils::toLower(name)),
m_usage(USAGE_UNKNOWN) m_usage(USAGE_UNKNOWN) {
{
} }
encoding::encoding(const string& name, const EncodingUsage usage) encoding::encoding(const string& name, const EncodingUsage usage)
: m_name(utility::stringUtils::toLower(name)), : m_name(utility::stringUtils::toLower(name)),
m_usage(usage) m_usage(usage) {
{
} }
encoding::encoding(const encoding& enc) encoding::encoding(const encoding& enc)
: headerFieldValue(), m_name(enc.m_name), m_usage(enc.m_usage) : headerFieldValue(),
{ m_name(enc.m_name),
m_usage(enc.m_usage) {
} }
void encoding::parseImpl void encoding::parseImpl(
(const parsingContext& /* ctx */, const string& buffer, const size_t position, const parsingContext& /* ctx */,
const size_t end, size_t* newPosition) const string& buffer,
{ const size_t position,
const size_t end,
size_t* newPosition
) {
m_usage = USAGE_UNKNOWN; m_usage = USAGE_UNKNOWN;
m_name = utility::stringUtils::toLower(utility::stringUtils::trim m_name = utility::stringUtils::toLower(
(utility::stringUtils::unquote(utility::stringUtils::trim utility::stringUtils::trim(
(string(buffer.begin() + position, buffer.begin() + end))))); utility::stringUtils::unquote(
utility::stringUtils::trim(
string(buffer.begin() + position, buffer.begin() + end)
)
)
)
);
if (m_name.empty()) if (m_name.empty()) {
m_name = encodingTypes::SEVEN_BIT; // assume default "7-bit" m_name = encodingTypes::SEVEN_BIT; // assume default "7-bit"
}
setParsedBounds(position, end); setParsedBounds(position, end);
if (newPosition) if (newPosition) {
*newPosition = end; *newPosition = end;
}
} }
void encoding::generateImpl void encoding::generateImpl(
(const generationContext& /* ctx */, utility::outputStream& os, const generationContext& /* ctx */,
const size_t curLinePos, size_t* newLinePos) const utility::outputStream& os,
{ const size_t curLinePos,
size_t* newLinePos
) const {
os << m_name; os << m_name;
if (newLinePos) if (newLinePos) {
*newLinePos = curLinePos + m_name.length(); *newLinePos = curLinePos + m_name.length();
}
} }
shared_ptr <utility::encoder::encoder> encoding::getEncoder() const shared_ptr <utility::encoder::encoder> encoding::getEncoder() const {
{
shared_ptr <utility::encoder::encoder> encoder = shared_ptr <utility::encoder::encoder> encoder =
utility::encoder::encoderFactory::getInstance()->create(generate()); utility::encoder::encoderFactory::getInstance()->create(generate());
// FIXME: this should not be here (move me into QP encoder instead?) // FIXME: this should not be here (move me into QP encoder instead?)
if (m_usage == USAGE_TEXT && m_name == encodingTypes::QUOTED_PRINTABLE) if (m_usage == USAGE_TEXT && m_name == encodingTypes::QUOTED_PRINTABLE) {
encoder->getProperties()["text"] = true; encoder->getProperties()["text"] = true;
}
return encoder; return encoder;
} }
encoding& encoding::operator=(const encoding& other) encoding& encoding::operator=(const encoding& other) {
{
copyFrom(other); copyFrom(other);
return (*this); return (*this);
} }
encoding& encoding::operator=(const string& name) encoding& encoding::operator=(const string& name) {
{
m_name = utility::stringUtils::toLower(name); m_name = utility::stringUtils::toLower(name);
m_usage = USAGE_UNKNOWN; m_usage = USAGE_UNKNOWN;
return (*this);
return *this;
} }
bool encoding::operator==(const encoding& value) const bool encoding::operator==(const encoding& value) const {
{
return (utility::stringUtils::toLower(m_name) == value.m_name); return utility::stringUtils::toLower(m_name) == value.m_name;
} }
bool encoding::operator!=(const encoding& value) const bool encoding::operator!=(const encoding& value) const {
{
return !(*this == value); return !(*this == value);
} }
const encoding encoding::decideImpl const encoding encoding::decideImpl(
(const string::const_iterator begin, const string::const_iterator end) const string::const_iterator begin,
{ const string::const_iterator end
) {
const string::difference_type length = end - begin; const string::difference_type length = end - begin;
const string::difference_type count = std::count_if const string::difference_type count = std::count_if(
(begin, end, std::bind2nd(std::less<unsigned char>(), 127)); begin, end,
std::bind2nd(std::less<unsigned char>(), 127)
);
// All is in 7-bit US-ASCII --> 7-bit (or Quoted-Printable...) // All is in 7-bit US-ASCII --> 7-bit (or Quoted-Printable...)
if (length == count) if (length == count) {
{
// Now, we check if there is any line with more than // Now, we check if there is any line with more than
// "lineLengthLimits::convenient" characters (7-bit requires that) // "lineLengthLimits::convenient" characters (7-bit requires that)
string::const_iterator p = begin; string::const_iterator p = begin;
@ -149,49 +171,51 @@ const encoding encoding::decideImpl
const size_t maxLen = lineLengthLimits::convenient; const size_t maxLen = lineLengthLimits::convenient;
size_t len = 0; size_t len = 0;
for ( ; p != end && len <= maxLen ; ) for ( ; p != end && len <= maxLen ; ) {
{
if (*p == '\n') if (*p == '\n') {
{
len = 0; len = 0;
++p; ++p;
// May or may not need to be encoded, we don't take // May or may not need to be encoded, we don't take
// any risk (avoid problems with SMTP) // any risk (avoid problems with SMTP)
if (p != end && *p == '.') if (p != end && *p == '.') {
len = maxLen + 1; len = maxLen + 1;
} }
else
{ } else {
++len; ++len;
++p; ++p;
} }
} }
if (len > maxLen) if (len > maxLen) {
return (encoding(encodingTypes::QUOTED_PRINTABLE)); return encoding(encodingTypes::QUOTED_PRINTABLE);
else } else {
return (encoding(encodingTypes::SEVEN_BIT)); return encoding(encodingTypes::SEVEN_BIT);
} }
// Less than 20% non US-ASCII --> Quoted-Printable // Less than 20% non US-ASCII --> Quoted-Printable
else if ((length - count) <= length / 5) } else if ((length - count) <= length / 5) {
{
return (encoding(encodingTypes::QUOTED_PRINTABLE)); return encoding(encodingTypes::QUOTED_PRINTABLE);
}
// Otherwise --> Base64 // Otherwise --> Base64
else } else {
{
return (encoding(encodingTypes::BASE64)); return encoding(encodingTypes::BASE64);
} }
} }
bool encoding::shouldReencode() const bool encoding::shouldReencode() const {
{
if (m_name == encodingTypes::BASE64 || if (m_name == encodingTypes::BASE64 ||
m_name == encodingTypes::QUOTED_PRINTABLE || m_name == encodingTypes::QUOTED_PRINTABLE ||
m_name == encodingTypes::UUENCODE) m_name == encodingTypes::UUENCODE) {
{
return false; return false;
} }
@ -199,18 +223,21 @@ bool encoding::shouldReencode() const
} }
const encoding encoding::decide const encoding encoding::decide(
(shared_ptr <const contentHandler> data, const EncodingUsage usage) const shared_ptr <const contentHandler>& data,
{ const EncodingUsage usage
) {
// Do not re-encode data if it is already encoded // Do not re-encode data if it is already encoded
if (data->isEncoded() && !data->getEncoding().shouldReencode()) if (data->isEncoded() && !data->getEncoding().shouldReencode()) {
return data->getEncoding(); return data->getEncoding();
}
encoding enc; encoding enc;
if (usage == USAGE_TEXT && data->isBuffered() && if (usage == USAGE_TEXT && data->isBuffered() &&
data->getLength() > 0 && data->getLength() < 32768) data->getLength() > 0 && data->getLength() < 32768) {
{
// Extract data into temporary buffer // Extract data into temporary buffer
string buffer; string buffer;
utility::outputStreamStringAdapter os(buffer); utility::outputStreamStringAdapter os(buffer);
@ -219,9 +246,9 @@ const encoding encoding::decide
os.flush(); os.flush();
enc = decideImpl(buffer.begin(), buffer.end()); enc = decideImpl(buffer.begin(), buffer.end());
}
else } else {
{
enc = encoding(encodingTypes::BASE64); enc = encoding(encodingTypes::BASE64);
} }
@ -231,19 +258,23 @@ const encoding encoding::decide
} }
const encoding encoding::decide(shared_ptr <const contentHandler> data, const encoding encoding::decide(
const charset& chset, const EncodingUsage usage) const shared_ptr <const contentHandler>& data,
{ const charset& chset,
// Do not re-encode data if it is already encoded const EncodingUsage usage
if (data->isEncoded() && !data->getEncoding().shouldReencode()) ) {
return data->getEncoding();
// Do not re-encode data if it is already encoded
if (data->isEncoded() && !data->getEncoding().shouldReencode()) {
return data->getEncoding();
}
if (usage == USAGE_TEXT) {
if (usage == USAGE_TEXT)
{
encoding recEncoding; encoding recEncoding;
if (chset.getRecommendedEncoding(recEncoding)) if (chset.getRecommendedEncoding(recEncoding)) {
{
recEncoding.setUsage(usage); recEncoding.setUsage(usage);
return recEncoding; return recEncoding;
} }
@ -253,46 +284,46 @@ const encoding encoding::decide(shared_ptr <const contentHandler> data,
} }
shared_ptr <component> encoding::clone() const shared_ptr <component> encoding::clone() const {
{
return make_shared <encoding>(*this); return make_shared <encoding>(*this);
} }
void encoding::copyFrom(const component& other) void encoding::copyFrom(const component& other) {
{
const encoding& e = dynamic_cast <const encoding&>(other); const encoding& e = dynamic_cast <const encoding&>(other);
m_name = e.m_name; m_name = e.m_name;
} }
const string& encoding::getName() const const string& encoding::getName() const {
{
return (m_name); return m_name;
} }
void encoding::setName(const string& name) void encoding::setName(const string& name) {
{
m_name = name; m_name = name;
} }
encoding::EncodingUsage encoding::getUsage() const encoding::EncodingUsage encoding::getUsage() const {
{
return m_usage; return m_usage;
} }
void encoding::setUsage(const EncodingUsage usage) void encoding::setUsage(const EncodingUsage usage) {
{
m_usage = usage; m_usage = usage;
} }
const std::vector <shared_ptr <component> > encoding::getChildComponents() const std::vector <shared_ptr <component> > encoding::getChildComponents() {
{
return std::vector <shared_ptr <component> >(); return std::vector <shared_ptr <component> >();
} }

Some files were not shown because too many files have changed in this diff Show More