Merge branch 'master' into master
This commit is contained in:
commit
71968d978d
118
CMakeLists.txt
118
CMakeLists.txt
@ -12,7 +12,7 @@
|
||||
# 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)
|
||||
|
||||
@ -68,6 +68,11 @@ SET(VMIME_API_VERSION ${VMIME_API_VERSION_CURRENT}.${VMIME_API_VERSION_REVISION}
|
||||
# Set base name
|
||||
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
|
||||
FILE(
|
||||
GLOB_RECURSE
|
||||
@ -109,6 +114,10 @@ IF(VMIME_BUILD_SHARED_LIBRARY)
|
||||
${VMIME_LIBRARY_INCLUDE_FILES}
|
||||
)
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(${VMIME_LIBRARY_NAME} PUBLIC
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
GENERATE_EXPORT_HEADER(
|
||||
${VMIME_LIBRARY_NAME}
|
||||
BASE_NAME VMIME
|
||||
@ -154,6 +163,10 @@ IF(VMIME_BUILD_STATIC_LIBRARY)
|
||||
${VMIME_LIBRARY_INCLUDE_FILES}
|
||||
)
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(${VMIME_LIBRARY_NAME}-static PUBLIC
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
GENERATE_EXPORT_HEADER(
|
||||
${VMIME_LIBRARY_NAME}-static
|
||||
BASE_NAME VMIME
|
||||
@ -199,6 +212,7 @@ SET(CMAKE_INSTALL_LIBDIR lib CACHE PATH "Output directory for libraries")
|
||||
IF(VMIME_BUILD_SHARED_LIBRARY)
|
||||
INSTALL(
|
||||
TARGETS ${VMIME_LIBRARY_NAME}
|
||||
EXPORT ${VMIME_LIBRARY_NAME}-config
|
||||
LIBRARY 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)
|
||||
INSTALL(
|
||||
TARGETS ${VMIME_LIBRARY_NAME}-static
|
||||
EXPORT ${VMIME_LIBRARY_NAME}-config
|
||||
LIBRARY 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
|
||||
#)
|
||||
|
||||
install(EXPORT ${VMIME_LIBRARY_NAME}-config DESTINATION cmake)
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Tests
|
||||
@ -783,89 +800,6 @@ ELSE()
|
||||
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
|
||||
|
||||
@ -997,12 +931,12 @@ IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
|
||||
SET(
|
||||
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_DEBUG "-O0 -g")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-O2 ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
|
||||
#SET(CMAKE_EXE_LINKER_FLAGS "-s")
|
||||
|
||||
@ -1012,12 +946,12 @@ ELSE()
|
||||
|
||||
SET(
|
||||
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_DEBUG "-O0 -g")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-O2 ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
|
||||
#SET(CMAKE_EXE_LINKER_FLAGS "-s")
|
||||
|
||||
|
76
HACKING
76
HACKING
@ -80,25 +80,52 @@ width to its preferred settings (eg. 4 or 8 spaces).
|
||||
2.2. Brace position
|
||||
-------------------
|
||||
|
||||
Open braces should always be at the beginning of the line after the statement
|
||||
that begins the block. Contents of the brace should be indented by 1 tab.
|
||||
Open braces should always be at the end of the line of the statement that
|
||||
begins the block. Contents of the brace should be indented by 1 tab.
|
||||
|
||||
if (expr) {
|
||||
|
||||
if (expr)
|
||||
{
|
||||
do_something();
|
||||
do_another_thing();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} 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
|
||||
-----------------------
|
||||
|
||||
switch (expr)
|
||||
{
|
||||
switch (expr) {
|
||||
|
||||
case 0:
|
||||
|
||||
something;
|
||||
@ -109,44 +136,35 @@ that begins the block. Contents of the brace should be indented by 1 tab.
|
||||
something_else;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
case 2: {
|
||||
|
||||
int var = 42;
|
||||
another_thing;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
2.4. Single instruction
|
||||
-----------------------
|
||||
|
||||
Omit braces around simple single-statement body:
|
||||
Don't omit braces around simple single-statement body:
|
||||
|
||||
if (...)
|
||||
if (...) {
|
||||
something;
|
||||
}
|
||||
|
||||
and not:
|
||||
|
||||
if (...)
|
||||
{
|
||||
something;
|
||||
}
|
||||
|
||||
Except when body spans over multiple lines:
|
||||
|
||||
if (...)
|
||||
{
|
||||
something_too_long_for(
|
||||
a_single_line);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
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.
|
||||
Tabs should NOT be used to indent at the end of a line:
|
||||
|
||||
class myClass
|
||||
{
|
||||
class myClass {
|
||||
|
||||
private:
|
||||
|
||||
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).
|
||||
|
||||
* Put the inclusion for the class's header file as the first inclusion in
|
||||
the implementation file.
|
||||
* Put the #include for the class's header file first in the implementation
|
||||
file.
|
||||
|
||||
* Put the copyright header at the top of each file.
|
||||
|
||||
|
1
cmake/cmake-cxx11/.gitignore
vendored
1
cmake/cmake-cxx11/.gitignore
vendored
@ -1 +0,0 @@
|
||||
build
|
@ -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
|
||||
|
@ -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)
|
@ -1,8 +0,0 @@
|
||||
int main(void)
|
||||
{
|
||||
if (!__func__)
|
||||
return 1;
|
||||
if (!(*__func__))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
@ -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;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
int main(void)
|
||||
{
|
||||
// must fail because there is no initializer
|
||||
auto i;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
auto foo(int i) -> int {
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return foo(1);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
int main()
|
||||
{
|
||||
int ret = 0;
|
||||
return ([&ret]() -> int { return ret; })();
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
int main(void)
|
||||
{
|
||||
long long l;
|
||||
unsigned long long ul;
|
||||
|
||||
return ((sizeof(l) >= 8) && (sizeof(ul) >= 8)) ? 0 : 1;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
int main(void)
|
||||
{
|
||||
void *v = nullptr;
|
||||
|
||||
return v ? 1 : 0;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
int main(void)
|
||||
{
|
||||
int i = nullptr;
|
||||
|
||||
return 1;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
struct foo {
|
||||
int baz;
|
||||
double bar;
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return (sizeof(foo::bar) == 4) ? 0 : 1;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
int main(void)
|
||||
{
|
||||
static_assert(0 < 1, "your ordering of integers is screwed");
|
||||
return 0;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
int main(void)
|
||||
{
|
||||
static_assert(1 < 0, "your ordering of integers is screwed");
|
||||
return 0;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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)
|
@ -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;
|
||||
}
|
@ -46,17 +46,17 @@ use the function {\vcode vmime::make\_shared} instead of the {\vcode new}
|
||||
operator.
|
||||
|
||||
\begin{lstlisting}[caption={Smarts pointers and creating objects}]
|
||||
class myObject : public vmime::object
|
||||
{
|
||||
class myObject : public vmime::object {
|
||||
|
||||
public:
|
||||
|
||||
myObject(const vmime::string& name)
|
||||
: m_name(name)
|
||||
{
|
||||
: m_name(name) {
|
||||
|
||||
}
|
||||
|
||||
void sayHello()
|
||||
{
|
||||
void sayHello() {
|
||||
|
||||
std::cout << "Hello " << m_name << std::endl;
|
||||
}
|
||||
|
||||
@ -65,8 +65,8 @@ private:
|
||||
vmime::string m_name;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
|
||||
vmime::shared_ptr <myObject> obj =
|
||||
vmime::make_shared <myObject>("world");
|
||||
|
||||
@ -105,12 +105,12 @@ directly or indirectly to itself). The following example illustrates a
|
||||
typical problem of reference counting:
|
||||
|
||||
\begin{lstlisting}
|
||||
class parent : public vmime::object
|
||||
{
|
||||
class parent : public vmime::object {
|
||||
|
||||
public:
|
||||
|
||||
void createChild(vmime::shared_ptr <child> c)
|
||||
{
|
||||
void createChild(vmime::shared_ptr <child> c) {
|
||||
|
||||
m_child = c;
|
||||
}
|
||||
|
||||
@ -119,13 +119,13 @@ private:
|
||||
vmime::shared_ptr <child> m_child;
|
||||
};
|
||||
|
||||
class child : public vmime::object
|
||||
{
|
||||
class child : public vmime::object {
|
||||
|
||||
public:
|
||||
|
||||
child(vmime::shared_ptr <parent> p)
|
||||
: m_parent(p)
|
||||
{
|
||||
: m_parent(p) {
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
@ -133,8 +133,8 @@ private:
|
||||
vmime::shared_ptr <parent> m_parent;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
|
||||
vmime::shared_ptr <parent> p = vmime::make_shared <parent>();
|
||||
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:
|
||||
|
||||
\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 << " what = " << e.what() << std::endl;
|
||||
|
||||
// Recursively print all encapsuled exceptions
|
||||
if (e.other() != NULL)
|
||||
if (e.other() != NULL) {
|
||||
os << *e.other();
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
|
||||
// ...some call to VMime...
|
||||
}
|
||||
catch (vmime::exception& e)
|
||||
{
|
||||
|
||||
} catch (vmime::exception& e) {
|
||||
|
||||
std::cerr << e; // VMime exception
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
||||
} catch (std::exception& e) {
|
||||
|
||||
std::cerr << e.what(); // standard exception
|
||||
}
|
||||
\end{lstlisting}
|
||||
@ -250,7 +251,8 @@ vmime::datetime d1("Sat, 08 Oct 2005 14:07:52 +0200");
|
||||
vmime::datetime d2(
|
||||
/* date */ 2005, vmime::datetime::OCTOBER, 8,
|
||||
/* time */ 14, 7, 52,
|
||||
/* zone */ vmime::datetime::GMT2);
|
||||
/* zone */ vmime::datetime::GMT2
|
||||
);
|
||||
|
||||
// Getting day of week
|
||||
const int dow = d2.getWeekDay(); // 'dow' should be datetime::SATURDAY
|
||||
@ -275,7 +277,8 @@ media type with:
|
||||
\begin{lstlisting}
|
||||
vmime::mediaType theType(
|
||||
/* top-level type */ vmime::mediaTypes::IMAGE,
|
||||
/* sub-type */ vmime::mediaTypes::IMAGE_JPEG);
|
||||
/* sub-type */ vmime::mediaTypes::IMAGE_JPEG
|
||||
);
|
||||
|
||||
// theType.getType() is "image"
|
||||
// theType.getSubType() is "jpeg"
|
||||
@ -594,8 +597,9 @@ std::ifstream* fileStream = new std::ifstream();
|
||||
|
||||
fileStream->open("/home/vincent/paris.jpg", std::ios::binary);
|
||||
|
||||
if (!*fileStream)
|
||||
if (!*fileStream) {
|
||||
// handle error
|
||||
}
|
||||
|
||||
vmime::shared_ptr <utility::stream> dataStream =
|
||||
vmime::make_shared <vmime::utility::inputStreamPointerAdapter>(fileStream);
|
||||
@ -608,8 +612,7 @@ vmime::shared_ptr <contentHandler> data =
|
||||
vmime::make_shared <vmime::streamContentHandler>(dataStream, 0);
|
||||
|
||||
// Now create the attachment
|
||||
ref <vmime::attachment> att = vmime::make_shared <vmime::defaultAttachment>
|
||||
(
|
||||
ref <vmime::attachment> att = vmime::make_shared <vmime::defaultAttachment>(
|
||||
/* attachment data */ data,
|
||||
/* content type */ vmime::mediaType("image/jpeg"),
|
||||
/* description */ vmime::text("Holiday photo"),
|
||||
@ -647,10 +650,11 @@ vmime::shared_ptr <const vmime::contentHandler> cth = body->getContents();
|
||||
|
||||
// Then, extract and convert the contents
|
||||
vmime::utility::outputStreamAdapter out(std::cout);
|
||||
vmime::utility::charsetFilteredOutputStream fout
|
||||
(/* source charset */ body->getCharset(),
|
||||
vmime::utility::charsetFilteredOutputStream fout(
|
||||
/* source charset */ body->getCharset(),
|
||||
/* dest charset */ vmime::charset("utf-8"),
|
||||
/* dest stream */ out);
|
||||
/* dest stream */ out
|
||||
);
|
||||
|
||||
cth->extract(fout);
|
||||
|
||||
@ -778,8 +782,8 @@ vmime::shared_ptr <vmime::utility::encoder::encoderFactory> ef =
|
||||
|
||||
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
|
||||
vmime::shared_ptr <const vmime::utility::encoder::encoderFactory::registeredEncoder>
|
||||
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>::const_iterator it;
|
||||
|
||||
for (it = props.begin() ; it != props.end() ; ++it)
|
||||
for (it = props.begin() ; it != props.end() ; ++it) {
|
||||
std::cout << " - " << *it << std::endl;
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
|
@ -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
|
||||
\href{http://www.gnu.org/software/gnutls/}{GNU TLS Library} if you
|
||||
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}
|
||||
|
||||
% ============================================================================
|
||||
|
@ -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:
|
||||
|
||||
\begin{verbatim}
|
||||
Copyright (C) 2002-2013 Vincent Richard
|
||||
Copyright (C) 2002 Vincent Richard
|
||||
|
||||
VMime library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
@ -79,7 +79,7 @@ GNU Free Documentation
|
||||
License\footnote{See \url{http://www.gnu.org/copyleft/fdl.html}} (FDL):
|
||||
|
||||
\begin{verbatim}
|
||||
Copyright (C) 2004-2013 Vincent Richard
|
||||
Copyright (C) 2004 Vincent Richard
|
||||
|
||||
Permission is granted to copy, distribute and/or modify
|
||||
this document under the terms of the GNU Free Documentation
|
||||
|
119
doc/book/msg.tex
119
doc/book/msg.tex
@ -94,8 +94,8 @@ vmime::messageParser mp(msg);
|
||||
std::cout << "Message has " << mp.getAttachmentCount()
|
||||
<< " 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);
|
||||
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()
|
||||
<< " 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);
|
||||
|
||||
// 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::dynamicCast <const vmime::htmlTextPart>(tp);
|
||||
|
||||
@ -118,18 +118,18 @@ for (int i = 0 ; i < mp.getTextPartCount() ; ++i)
|
||||
// Plain text is in tp->getPlainText()
|
||||
|
||||
// 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 =
|
||||
htp->getObjectAt(j);
|
||||
|
||||
// Identifier (Content-Id or Content-Location) is obj->getId()
|
||||
// Object data is in obj->getData()
|
||||
}
|
||||
}
|
||||
|
||||
// text/plain or anything else
|
||||
else
|
||||
{
|
||||
} else {
|
||||
|
||||
// Text is in tp->getText()
|
||||
}
|
||||
}
|
||||
@ -172,8 +172,7 @@ hdr->appendField(subjectField);
|
||||
vmime::shared_ptr <vmime::headerField> fromField =
|
||||
hfFactory->create(vmime::fields::FROM);
|
||||
|
||||
fromField->setValue
|
||||
(vmime::make_shared <vmime::mailbox>("me@vmime.org"));
|
||||
fromField->setValue(vmime::make_shared <vmime::mailbox>("me@vmime.org"));
|
||||
hdr->appendField(fromField);
|
||||
|
||||
// Append a 'To:' field
|
||||
@ -190,8 +189,11 @@ toField->setValue(recipients);
|
||||
hdr->appendField(toField);
|
||||
|
||||
// Set the body contents
|
||||
bdy->setContents(vmime::make_shared <vmime::stringContentHandler>
|
||||
("This is the text of your message..."));
|
||||
bdy->setContents(
|
||||
vmime::make_shared <vmime::stringContentHandler>(
|
||||
"This is the text of your message..."
|
||||
)
|
||||
);
|
||||
|
||||
// Output raw message data to standard output
|
||||
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
|
||||
using {\vcode vmime::messageBuilder}}]
|
||||
try
|
||||
{
|
||||
try {
|
||||
|
||||
vmime::messageBuilder mb;
|
||||
|
||||
// Fill in some header fields and message body
|
||||
mb.setSubject(vmime::text("Message subject"));
|
||||
mb.setExpeditor(vmime::mailbox("me@vmime.org"));
|
||||
mb.getRecipients().appendAddress
|
||||
(vmime::make_shared <vmime::mailbox>("you@vmime.org"));
|
||||
mb.getRecipients().appendAddress(
|
||||
vmime::make_shared <vmime::mailbox>("you@vmime.org")
|
||||
);
|
||||
|
||||
mb.getTextPart()->setCharset(vmime::charsets::ISO8859_15);
|
||||
mb.getTextPart()->setText(vmime::make_shared <vmime::stringContentHandler>
|
||||
("This is the text of your message..."));
|
||||
mb.getTextPart()->setText(
|
||||
vmime::make_shared <vmime::stringContentHandler>(
|
||||
"This is the text of your message..."
|
||||
)
|
||||
);
|
||||
|
||||
// Message construction
|
||||
vmime::shared_ptr <vmime::message> msg = mb.construct();
|
||||
@ -227,15 +233,15 @@ try
|
||||
// Output raw message data to standard output
|
||||
vmime::utility::outputStreamAdapter out(std::cout);
|
||||
msg->generate(out);
|
||||
}
|
||||
|
||||
// VMime exception
|
||||
catch (vmime::exception& e)
|
||||
{
|
||||
} catch (vmime::exception& e) {
|
||||
|
||||
std::cerr << "vmime::exception: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
// Standard exception
|
||||
catch (std::exception& e)
|
||||
{
|
||||
} catch (std::exception& e) {
|
||||
|
||||
std::cerr << "std::exception: " << e.what() << std::endl;
|
||||
}
|
||||
\end{lstlisting}
|
||||
@ -250,8 +256,7 @@ previous example to attach a file to the message:
|
||||
{\vcode vmime::messageBuilder}}]
|
||||
// Create an attachment
|
||||
vmime::shared_ptr <vmime::fileAttachment> att =
|
||||
vmime::make_shared <vmime::fileAttachment>
|
||||
(
|
||||
vmime::make_shared <vmime::fileAttachment>(
|
||||
/* full path to file */ "/home/vincent/paris.jpg",
|
||||
/* content type */ vmime::mediaType("image/jpeg),
|
||||
/* description */ vmime::text("My holidays in Paris")
|
||||
@ -259,8 +264,9 @@ vmime::shared_ptr <vmime::fileAttachment> att =
|
||||
|
||||
// You can also set some infos about the file
|
||||
att->getFileInfo().setFilename("paris.jpg");
|
||||
att->getFileInfo().setCreationDate
|
||||
(vmime::datetime("30 Apr 2003 14:30:00 +0200"));
|
||||
att->getFileInfo().setCreationDate(
|
||||
vmime::datetime("30 Apr 2003 14:30:00 +0200")
|
||||
);
|
||||
|
||||
// Add this attachment to the message
|
||||
mb.appendAttachment(att);
|
||||
@ -283,14 +289,19 @@ using the {\vcode vmime::messageBuilder}}]
|
||||
// Fill in some header fields
|
||||
mb.setSubject(vmime::text("An HTML message"));
|
||||
mb.setExpeditor(vmime::mailbox("me@vmime.org"));
|
||||
mb.getRecipients().appendAddress
|
||||
(vmime::make_shared <vmime::mailbox>("you@vmime.org"));
|
||||
mb.getRecipients().appendAddress(
|
||||
vmime::make_shared <vmime::mailbox>("you@vmime.org")
|
||||
);
|
||||
|
||||
// Set the content-type to "text/html": a text part factory must be
|
||||
// available for the type you are using. The following code will make
|
||||
// the message builder construct the two text parts.
|
||||
mb.constructTextPart(vmime::mediaType
|
||||
(vmime::mediaTypes::TEXT, vmime::mediaTypes::TEXT_HTML));
|
||||
mb.constructTextPart(
|
||||
vmime::mediaType(
|
||||
vmime::mediaTypes::TEXT,
|
||||
vmime::mediaTypes::TEXT_HTML
|
||||
)
|
||||
);
|
||||
|
||||
// Set contents of the text parts; the message is available in two formats:
|
||||
// HTML and plain text. The HTML format also includes an embedded image.
|
||||
@ -306,12 +317,18 @@ const vmime::string id = textPart->addObject("<...image data...>",
|
||||
// -- Set the text
|
||||
textPart->setCharset(vmime::charsets::ISO8859_15);
|
||||
|
||||
textPart->setText(vmime::make_shared <vmime::stringContentHandler>
|
||||
("This is the <b>HTML text</b>, and the image:<br/>"
|
||||
"<img src=\"") + id + vmime::string("\"/>"));
|
||||
textPart->setText(
|
||||
vmime::make_shared <vmime::stringContentHandler>(
|
||||
"This is the <b>HTML text</b>, and the image:<br/>"
|
||||
"<img src=\"") + id + vmime::string("\"/>"
|
||||
)
|
||||
);
|
||||
|
||||
textPart->setPlainText(vmime::make_shared <vmime::stringContentHandler>
|
||||
("This is the plain text."));
|
||||
textPart->setPlainText(
|
||||
vmime::make_shared <vmime::stringContentHandler>(
|
||||
"This is the plain text."
|
||||
)
|
||||
);
|
||||
\end{lstlisting}
|
||||
|
||||
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"));
|
||||
|
||||
vmime::shared_ptr <vmime::contentHandler> imageCts =
|
||||
vmime::make_shared <vmime::streamContentHandler>
|
||||
(imageFile->getFileReader()->getInputStream(), imageFile->getLength());
|
||||
vmime::make_shared <vmime::streamContentHandler>(
|
||||
imageFile->getFileReader()->getInputStream(),
|
||||
imageFile->getLength()
|
||||
);
|
||||
|
||||
const vmime::string cid = textPart.addObject(imageCts,
|
||||
vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG));
|
||||
const vmime::string cid = textPart.addObject(
|
||||
imageCts,
|
||||
vmime::mediaType(
|
||||
vmime::mediaTypes::IMAGE,
|
||||
vmime::mediaTypes::IMAGE_JPEG
|
||||
)
|
||||
);
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
@ -361,8 +385,8 @@ extract its contents to the standard output:
|
||||
\begin{lstlisting}[caption={Testing if a body part is an attachment}]
|
||||
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
|
||||
vmime::shared_ptr <const vmime::attachment> attach =
|
||||
attachmentHelper::getBodyPartAttachment(part);
|
||||
@ -394,8 +418,7 @@ vmime::shared_ptr <vmime::message> msg; // suppose we have a message
|
||||
|
||||
// Create an attachment
|
||||
vmime::shared_ptr <vmime::fileAttachment> att =
|
||||
vmime::make_shared <vmime::fileAttachment>
|
||||
(
|
||||
vmime::make_shared <vmime::fileAttachment>(
|
||||
/* full path to file */ "/home/vincent/paris.jpg",
|
||||
/* content type */ vmime::mediaType("image/jpeg),
|
||||
/* description */ vmime::text("My holidays in Paris")
|
||||
|
235
doc/book/net.tex
235
doc/book/net.tex
@ -300,10 +300,10 @@ The following example shows how to use a custom authenticator to request
|
||||
the user to enter her/his credentials:
|
||||
|
||||
\begin{lstlisting}[caption={A simple interactive authenticator}]
|
||||
class myAuthenticator : public vmime::security::defaultAuthenticator
|
||||
{
|
||||
const string getUsername() const
|
||||
{
|
||||
class myAuthenticator : public vmime::security::defaultAuthenticator {
|
||||
|
||||
const string getUsername() const {
|
||||
|
||||
std::cout << "Enter your username: " << std::endl;
|
||||
|
||||
vmime::string res;
|
||||
@ -312,8 +312,8 @@ class myAuthenticator : public vmime::security::defaultAuthenticator
|
||||
return res;
|
||||
}
|
||||
|
||||
const string getPassword() const
|
||||
{
|
||||
const string getPassword() const {
|
||||
|
||||
std::cout << "Enter your password: " << std::endl;
|
||||
|
||||
vmime::string res;
|
||||
@ -331,9 +331,10 @@ This is how to use it:
|
||||
vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create();
|
||||
|
||||
// Next, initialize a service which will use our authenticator
|
||||
vmime::shared_ptr <vmime::net::store> st =
|
||||
sess->getStore(vmime::utility::url("imap://imap.example.com"),
|
||||
/* use our authenticator */ vmime::make_shared <myAuthenticator>());
|
||||
vmime::shared_ptr <vmime::net::store> st = sess->getStore(
|
||||
vmime::utility::url("imap://imap.example.com"),
|
||||
/* use our authenticator */ vmime::make_shared <myAuthenticator>()
|
||||
);
|
||||
\end{lstlisting}
|
||||
|
||||
\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.
|
||||
|
||||
\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
|
||||
|
||||
const std::vector <vmime::shared_ptr <mechanism> > getAcceptableMechanisms
|
||||
(const std::vector <vmime::shared_ptr <mechanism> >& available,
|
||||
vmime::shared_ptr <mechanism> suggested) const
|
||||
{
|
||||
const std::vector <vmime::shared_ptr <mechanism> > getAcceptableMechanisms(
|
||||
const std::vector <vmime::shared_ptr <mechanism> >& available,
|
||||
const vmime::shared_ptr <mechanism>& suggested
|
||||
) const {
|
||||
|
||||
// Here, you can sort the SASL mechanisms in the order they will be
|
||||
// tried. If no SASL mechanism is acceptable (ie. for example, not
|
||||
// enough secure), you can return an empty list.
|
||||
@ -372,8 +374,8 @@ class mySASLAuthenticator : public vmime::security::sasl::defaultSASLAuthenticat
|
||||
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
|
||||
// try the specified mechanism.
|
||||
//
|
||||
@ -435,7 +437,8 @@ tr->send(
|
||||
/* expeditor */ from,
|
||||
/* recipient(s) */ to,
|
||||
/* data */ is,
|
||||
/* total length */ msgData.length());
|
||||
/* total length */ msgData.length()
|
||||
);
|
||||
|
||||
// We have finished using the service
|
||||
tr->disconnect();
|
||||
@ -556,22 +559,26 @@ std::vector <ref <vmime::net::message> > allMessages =
|
||||
folder->getMessages(vmime::net::messageSet::byNumber(1, -1));
|
||||
// -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::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];
|
||||
|
||||
const int flags = msg->getFlags();
|
||||
|
||||
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;
|
||||
if (flags & vmime::net::message::FLAG_DELETED)
|
||||
}
|
||||
if (flags & vmime::net::message::FLAG_DELETED) {
|
||||
std::cout << " - is deleted" << std::endl;
|
||||
}
|
||||
|
||||
vmime::shared_ptr <const vmime::header> hdr = msg->getHeader();
|
||||
|
||||
@ -698,8 +705,8 @@ running.
|
||||
An interface called {\vcode timeoutHandler} is provided:
|
||||
|
||||
\begin{lstlisting}
|
||||
class timeoutHandler : public object
|
||||
{
|
||||
class timeoutHandler : public object {
|
||||
|
||||
/** Called to test if the time limit has been reached.
|
||||
*
|
||||
* @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:
|
||||
|
||||
\begin{lstlisting}[caption={Implementing a simple timeout handler}]
|
||||
class myTimeoutHandler : public vmime::net::timeoutHandler
|
||||
{
|
||||
class myTimeoutHandler : public vmime::net::timeoutHandler {
|
||||
|
||||
public:
|
||||
|
||||
myTimeoutHandler()
|
||||
{
|
||||
myTimeoutHandler() {
|
||||
|
||||
m_startTime = time(NULL);
|
||||
}
|
||||
|
||||
const bool isTimeOut()
|
||||
{
|
||||
return (time(NULL) >= m_startTime + 30); // 30 seconds timeout
|
||||
const bool isTimeOut() {
|
||||
|
||||
return time(NULL) >= m_startTime + 30; // 30 seconds timeout
|
||||
}
|
||||
|
||||
void resetTimeOut()
|
||||
{
|
||||
void resetTimeOut() {
|
||||
|
||||
m_startTime = time(NULL);
|
||||
}
|
||||
|
||||
const bool handleTimeOut()
|
||||
{
|
||||
const bool handleTimeOut() {
|
||||
|
||||
std::cout << "Operation timed out." << std::endl;
|
||||
<< "Press [Y] to continue, or [N] to "
|
||||
<< "cancel the operation." << std::endl;
|
||||
@ -766,7 +773,7 @@ public:
|
||||
std::string response;
|
||||
std::cin >> response;
|
||||
|
||||
return (response == "y" || response == "Y");
|
||||
return response == "y" || response == "Y";
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
\begin{lstlisting}
|
||||
class myTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory
|
||||
{
|
||||
class myTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory {
|
||||
|
||||
public:
|
||||
|
||||
ref <timeoutHandler> create()
|
||||
{
|
||||
ref <timeoutHandler> create() {
|
||||
|
||||
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}]
|
||||
vmime::shared_ptr <vmime::security::cert::X509Certificate>
|
||||
loadX509CertificateFromFile(const std::string& path)
|
||||
{
|
||||
loadX509CertificateFromFile(const std::string& path) {
|
||||
|
||||
std::ifstream certFile;
|
||||
certFile.open(path.c_str(), std::ios::in | std::ios::binary);
|
||||
|
||||
if (!certFile)
|
||||
{
|
||||
if (!certFile) {
|
||||
// ...handle error...
|
||||
}
|
||||
|
||||
vmime::utility::inputStreamAdapter is(certFile);
|
||||
vmime::shared_ptr <vmime::security::cert::X509Certificate> cert;
|
||||
|
||||
// Try DER format
|
||||
cert = vmime::security::cert::X509Certificate::import
|
||||
(is, vmime::security::cert::X509Certificate::FORMAT_DER);
|
||||
|
||||
if (cert != NULL)
|
||||
return cert;
|
||||
|
||||
// Try PEM format
|
||||
is.reset();
|
||||
cert = vmime::security::cert::X509Certificate::import
|
||||
(is, vmime::security::cert::X509Certificate::FORMAT_PEM);
|
||||
cert = vmime::security::cert::X509Certificate::import(is);
|
||||
|
||||
return cert;
|
||||
}
|
||||
@ -988,12 +984,12 @@ use this in a production application as this is obviously a serious security
|
||||
issue):
|
||||
|
||||
\begin{lstlisting}[caption={A custom certificate verifier}]
|
||||
class myCertVerifier : public vmime::security::cert::certificateVerifier
|
||||
{
|
||||
class myCertVerifier : public vmime::security::cert::certificateVerifier {
|
||||
|
||||
public:
|
||||
|
||||
void verify(vmime::shared_ptr <certificateChain> certs)
|
||||
{
|
||||
void verify(const vmime::shared_ptr <certificateChain>& certs) {
|
||||
|
||||
// Obtain the subject's certificate
|
||||
vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0);
|
||||
|
||||
@ -1006,8 +1002,9 @@ public:
|
||||
std::string 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
|
||||
}
|
||||
|
||||
// Don't trust this certificate
|
||||
throw vmime::security::cert::certificateException();
|
||||
@ -1090,3 +1087,117 @@ The following constants are available:
|
||||
\hline
|
||||
\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...}"").
|
||||
|
@ -26,7 +26,7 @@ You can simply build your program with:
|
||||
to use the static version, or with:
|
||||
|
||||
\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}
|
||||
|
||||
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/platforms/posix/posixHandler.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
|
||||
vmime::platform::
|
||||
setHandler <vmime::platforms::posix::posixHandler>();
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -39,23 +39,20 @@
|
||||
#include "vmime/platforms/posix/posixHandler.hpp"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
// 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.
|
||||
try
|
||||
{
|
||||
try {
|
||||
std::locale::global(std::locale(""));
|
||||
}
|
||||
catch (std::exception &)
|
||||
{
|
||||
} catch (std::exception &) {
|
||||
std::setlocale(LC_ALL, "");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
|
||||
vmime::messageBuilder mb;
|
||||
|
||||
// Fill in the basic fields
|
||||
@ -74,9 +71,12 @@ int main()
|
||||
mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder"));
|
||||
|
||||
// Message body
|
||||
mb.getTextPart()->setText(vmime::make_shared <vmime::stringContentHandler>(
|
||||
mb.getTextPart()->setText(
|
||||
vmime::make_shared <vmime::stringContentHandler>(
|
||||
"I'm writing this short text to test message construction " \
|
||||
"using the vmime::messageBuilder component."));
|
||||
"using the vmime::messageBuilder component."
|
||||
)
|
||||
);
|
||||
|
||||
// Construction
|
||||
vmime::shared_ptr <vmime::message> msg = mb.construct();
|
||||
@ -87,20 +87,21 @@ int main()
|
||||
|
||||
vmime::utility::outputStreamAdapter out(std::cout);
|
||||
msg->generate(out);
|
||||
}
|
||||
|
||||
// VMime exception
|
||||
catch (vmime::exception& e)
|
||||
{
|
||||
} catch (vmime::exception& e) {
|
||||
|
||||
std::cout << "vmime::exception: " << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
// Standard exception
|
||||
catch (std::exception& e)
|
||||
{
|
||||
} catch (std::exception& e) {
|
||||
|
||||
std::cout << "std::exception: " << e.what() << std::endl;
|
||||
//throw;
|
||||
throw;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -39,23 +39,20 @@
|
||||
#include "vmime/platforms/posix/posixHandler.hpp"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
// 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.
|
||||
try
|
||||
{
|
||||
try {
|
||||
std::locale::global(std::locale(""));
|
||||
}
|
||||
catch (std::exception &)
|
||||
{
|
||||
} catch (std::exception &) {
|
||||
std::setlocale(LC_ALL, "");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
|
||||
vmime::messageBuilder mb;
|
||||
|
||||
// Fill in the basic fields
|
||||
@ -74,13 +71,16 @@ int main()
|
||||
mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder"));
|
||||
|
||||
// Message body
|
||||
mb.getTextPart()->setText(vmime::make_shared <vmime::stringContentHandler>(
|
||||
mb.getTextPart()->setText(
|
||||
vmime::make_shared <vmime::stringContentHandler>(
|
||||
"I'm writing this short text to test message construction " \
|
||||
"with attachment, using the vmime::messageBuilder component."));
|
||||
"with attachment, using the vmime::messageBuilder component."
|
||||
)
|
||||
);
|
||||
|
||||
// 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
|
||||
vmime::mediaType("application/octet-stream"), // content type
|
||||
vmime::text("My first attachment") // description
|
||||
@ -101,20 +101,21 @@ int main()
|
||||
std::cout << "==================" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << dataToSend << std::endl;
|
||||
}
|
||||
|
||||
// VMime exception
|
||||
catch (vmime::exception& e)
|
||||
{
|
||||
} catch (vmime::exception& e) {
|
||||
|
||||
std::cout << "vmime::exception: " << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
// Standard exception
|
||||
catch (std::exception& e)
|
||||
{
|
||||
} catch (std::exception& e) {
|
||||
|
||||
std::cout << "std::exception: " << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -39,23 +39,20 @@
|
||||
#include "vmime/platforms/posix/posixHandler.hpp"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
// 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.
|
||||
try
|
||||
{
|
||||
try {
|
||||
std::locale::global(std::locale(""));
|
||||
}
|
||||
catch (std::exception &)
|
||||
{
|
||||
} catch (std::exception &) {
|
||||
std::setlocale(LC_ALL, "");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
|
||||
vmime::messageBuilder mb;
|
||||
|
||||
// Fill in the basic fields
|
||||
@ -74,12 +71,17 @@ int main()
|
||||
mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder"));
|
||||
|
||||
// Set the content-type to "text/html"
|
||||
mb.constructTextPart(vmime::mediaType
|
||||
(vmime::mediaTypes::TEXT, vmime::mediaTypes::TEXT_HTML));
|
||||
mb.constructTextPart(
|
||||
vmime::mediaType(
|
||||
vmime::mediaTypes::TEXT,
|
||||
vmime::mediaTypes::TEXT_HTML
|
||||
)
|
||||
);
|
||||
|
||||
// Fill in the text part: the message is available in two formats: HTML and plain text.
|
||||
// HTML text part also includes an inline image (embedded into the message).
|
||||
vmime::htmlTextPart& textPart = *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
|
||||
// -- the image into HTML content).
|
||||
@ -93,18 +95,33 @@ int main()
|
||||
imageFile->getFileReader();
|
||||
|
||||
vmime::shared_ptr <vmime::contentHandler> imageCts =
|
||||
vmime::make_shared <vmime::streamContentHandler>
|
||||
(fileReader->getInputStream(), imageFile->getLength());
|
||||
vmime::make_shared <vmime::streamContentHandler>(
|
||||
fileReader->getInputStream(),
|
||||
imageFile->getLength()
|
||||
);
|
||||
|
||||
vmime::shared_ptr <const vmime::htmlTextPart::embeddedObject> obj = textPart.addObject
|
||||
(imageCts, vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG));
|
||||
vmime::shared_ptr <const vmime::htmlTextPart::embeddedObject> obj =
|
||||
textPart.addObject(
|
||||
imageCts,
|
||||
vmime::mediaType(
|
||||
vmime::mediaTypes::IMAGE,
|
||||
vmime::mediaTypes::IMAGE_JPEG
|
||||
)
|
||||
);
|
||||
|
||||
// -- message text
|
||||
textPart.setText(vmime::make_shared <vmime::stringContentHandler>
|
||||
(vmime::string("This is the <b>HTML text</b>.<br/>"
|
||||
"<img src=\"") + obj->getReferenceId() + vmime::string("\"/>")));
|
||||
textPart.setPlainText(vmime::make_shared <vmime::stringContentHandler>
|
||||
("This is the plain text (without HTML formatting)."));
|
||||
textPart.setText(
|
||||
vmime::make_shared <vmime::stringContentHandler>(
|
||||
vmime::string("This is the <b>HTML text</b>.<br/>"
|
||||
"<img src=\"") + obj->getReferenceId() + vmime::string("\"/>")
|
||||
)
|
||||
);
|
||||
|
||||
textPart.setPlainText(
|
||||
vmime::make_shared <vmime::stringContentHandler>(
|
||||
"This is the plain text (without HTML formatting)."
|
||||
)
|
||||
);
|
||||
|
||||
// Construction
|
||||
vmime::shared_ptr <vmime::message> msg = mb.construct();
|
||||
@ -116,20 +133,21 @@ int main()
|
||||
std::cout << "==================" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << dataToSend << std::endl;
|
||||
}
|
||||
|
||||
// VMime exception
|
||||
catch (vmime::exception& e)
|
||||
{
|
||||
} catch (vmime::exception& e) {
|
||||
|
||||
std::cout << "vmime::exception: " << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
// Standard exception
|
||||
catch (std::exception& e)
|
||||
{
|
||||
} catch (std::exception& e) {
|
||||
|
||||
std::cout << "std::exception: " << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -39,71 +39,70 @@
|
||||
#include "vmime/platforms/posix/posixHandler.hpp"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
// 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.
|
||||
try
|
||||
{
|
||||
try {
|
||||
std::locale::global(std::locale(""));
|
||||
}
|
||||
catch (std::exception &)
|
||||
{
|
||||
} catch (std::exception &) {
|
||||
std::setlocale(LC_ALL, "");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
|
||||
vmime::messageParser mp("<...MIME message content...>");
|
||||
|
||||
// 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);
|
||||
|
||||
// Output content-type of the part
|
||||
std::cout << part.getType().generate() << std::endl;
|
||||
|
||||
// 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);
|
||||
|
||||
// HTML text is in "hp.getText()"
|
||||
// Corresponding plain text is in "hp.getPlainText()"
|
||||
|
||||
// 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);
|
||||
|
||||
// Identifier (content-id or content-location) is in "obj.getId()"
|
||||
// Object data is in "obj.getData()"
|
||||
}
|
||||
}
|
||||
|
||||
// text/plain
|
||||
else
|
||||
{
|
||||
} else {
|
||||
|
||||
const vmime::textPart& tp = dynamic_cast<const vmime::textPart&>(part);
|
||||
|
||||
// Text is in "tp.getText()"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// VMime exception
|
||||
catch (vmime::exception& e)
|
||||
{
|
||||
} catch (vmime::exception& e) {
|
||||
|
||||
std::cout << "vmime::exception: " << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
// Standard exception
|
||||
catch (std::exception& e)
|
||||
{
|
||||
} catch (std::exception& e) {
|
||||
|
||||
std::cout << "std::exception: " << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -39,28 +39,25 @@
|
||||
#include "vmime/platforms/posix/posixHandler.hpp"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
// 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.
|
||||
try
|
||||
{
|
||||
try {
|
||||
std::locale::global(std::locale(""));
|
||||
}
|
||||
catch (std::exception &)
|
||||
{
|
||||
} catch (std::exception &) {
|
||||
std::setlocale(LC_ALL, "");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
|
||||
vmime::messageParser mp("<...MIME message content...>");
|
||||
|
||||
// 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);
|
||||
|
||||
// Media type (content type) is in "att.getType()"
|
||||
@ -68,19 +65,21 @@ int main()
|
||||
// Description is in "att.getDescription()"
|
||||
// Data is in "att.getData()"
|
||||
}
|
||||
}
|
||||
|
||||
// VMime exception
|
||||
catch (vmime::exception& e)
|
||||
{
|
||||
} catch (vmime::exception& e) {
|
||||
|
||||
std::cout << "vmime::exception: " << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
// Standard exception
|
||||
catch (std::exception& e)
|
||||
{
|
||||
} catch (std::exception& e) {
|
||||
|
||||
std::cout << "std::exception: " << e.what() << std::endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
* 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::net::serviceFactory::getInstance();
|
||||
|
||||
std::ostringstream res;
|
||||
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);
|
||||
|
||||
if (serv.getType() == type)
|
||||
{
|
||||
if (count != 0)
|
||||
if (serv.getType() == type) {
|
||||
|
||||
if (count != 0) {
|
||||
res << ", ";
|
||||
}
|
||||
|
||||
res << serv.getName();
|
||||
++count;
|
||||
@ -73,14 +74,14 @@ static const std::string findAvailableProtocols(const vmime::net::service::Type
|
||||
|
||||
|
||||
// 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 << " what = " << e.what() << std::endl;
|
||||
|
||||
// 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 =
|
||||
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;
|
||||
}
|
||||
|
||||
if (dynamic_cast <const vmime::exceptions::invalid_response*>(&e))
|
||||
{
|
||||
if (dynamic_cast <const vmime::exceptions::invalid_response*>(&e)) {
|
||||
|
||||
const vmime::exceptions::invalid_response& ir =
|
||||
dynamic_cast <const vmime::exceptions::invalid_response&>(e);
|
||||
|
||||
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 =
|
||||
dynamic_cast <const vmime::exceptions::connection_greeting_error&>(e);
|
||||
|
||||
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 =
|
||||
dynamic_cast <const vmime::exceptions::authentication_error&>(e);
|
||||
|
||||
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 =
|
||||
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;
|
||||
}
|
||||
|
||||
if (e.other() != NULL)
|
||||
if (e.other()) {
|
||||
os << *e.other();
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
@ -133,16 +135,21 @@ static std::ostream& operator<<(std::ostream& os, const vmime::exception& e)
|
||||
* @param s structure object
|
||||
* @param level current depth
|
||||
*/
|
||||
static void printStructure(vmime::shared_ptr <const vmime::net::messageStructure> s, const int level = 0)
|
||||
{
|
||||
for (size_t i = 0 ; i < s->getPartCount() ; ++i)
|
||||
{
|
||||
static void printStructure(
|
||||
vmime::shared_ptr <const vmime::net::messageStructure> s,
|
||||
const int level = 0
|
||||
) {
|
||||
|
||||
for (size_t i = 0 ; i < s->getPartCount() ; ++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 << (part->getNumber() + 1) << ". "
|
||||
std::cout
|
||||
<< (part->getNumber() + 1) << ". "
|
||||
<< part->getType().generate()
|
||||
<< " [" << part->getSize() << " byte(s)]"
|
||||
<< std::endl;
|
||||
@ -152,16 +159,16 @@ static void printStructure(vmime::shared_ptr <const vmime::net::messageStructure
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
|
||||
if (n.empty()) // root folder
|
||||
{
|
||||
if (n.empty()) { // root folder
|
||||
|
||||
return "/";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
vmime::shared_ptr <vmime::net::folder> p = f->getParent();
|
||||
return getFolderPathString(p) + n + "/";
|
||||
}
|
||||
@ -172,38 +179,43 @@ static const vmime::string getFolderPathString(vmime::shared_ptr <vmime::net::fo
|
||||
*
|
||||
* @param folder current folder
|
||||
*/
|
||||
static void printFolders(vmime::shared_ptr <vmime::net::folder> folder, const int level = 0)
|
||||
{
|
||||
for (int j = 0 ; j < level * 2 ; ++j)
|
||||
static void printFolders(vmime::shared_ptr <vmime::net::folder> folder, const int level = 0) {
|
||||
|
||||
for (int j = 0 ; j < level * 2 ; ++j) {
|
||||
std::cout << " ";
|
||||
}
|
||||
|
||||
const vmime::net::folderAttributes attr = folder->getAttributes();
|
||||
std::ostringstream attrStr;
|
||||
|
||||
if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_ALL)
|
||||
if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_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";
|
||||
else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_DRAFTS)
|
||||
} else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_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";
|
||||
else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_JUNK)
|
||||
} else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_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";
|
||||
else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_TRASH)
|
||||
} else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_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";
|
||||
}
|
||||
|
||||
if (attr.getFlags() & vmime::net::folderAttributes::FLAG_HAS_CHILDREN)
|
||||
if (attr.getFlags() & vmime::net::folderAttributes::FLAG_HAS_CHILDREN) {
|
||||
attrStr << " \\flag:HasChildren";
|
||||
if (attr.getFlags() & vmime::net::folderAttributes::FLAG_NO_OPEN)
|
||||
}
|
||||
if (attr.getFlags() & vmime::net::folderAttributes::FLAG_NO_OPEN) {
|
||||
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];
|
||||
}
|
||||
|
||||
std::cout << getFolderPathString(folder);
|
||||
std::cout << " " << attrStr.str();
|
||||
@ -211,21 +223,23 @@ static void printFolders(vmime::shared_ptr <vmime::net::folder> folder, const in
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Print a menu on the standard output.
|
||||
*
|
||||
* @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;
|
||||
|
||||
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 << std::endl;
|
||||
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;
|
||||
|
||||
if (choice < 1 || choice > choices.size())
|
||||
if (choice < 1 || choice > choices.size()) {
|
||||
return 0;
|
||||
else
|
||||
} else {
|
||||
return choice;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Send a message interactively.
|
||||
*/
|
||||
static void sendMessage()
|
||||
{
|
||||
try
|
||||
{
|
||||
static void sendMessage() {
|
||||
|
||||
try {
|
||||
|
||||
// Request user to enter an URL
|
||||
std::cout << "Enter an URL to connect to transport service." << 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;
|
||||
|
||||
if (url.getUsername().empty() || url.getPassword().empty())
|
||||
if (url.getUsername().empty() || url.getPassword().empty()) {
|
||||
tr = g_session->getTransport(url, vmime::make_shared <interactiveAuthenticator>());
|
||||
else
|
||||
} else {
|
||||
tr = g_session->getTransport(url);
|
||||
}
|
||||
|
||||
#if VMIME_HAVE_TLS_SUPPORT
|
||||
|
||||
@ -283,15 +299,17 @@ static void sendMessage()
|
||||
|
||||
// Set the object responsible for verifying certificates, in the
|
||||
// case a secured connection is used (TLS/SSL)
|
||||
tr->setCertificateVerifier
|
||||
(vmime::make_shared <interactiveCertificateVerifier>());
|
||||
tr->setCertificateVerifier(
|
||||
vmime::make_shared <interactiveCertificateVerifier>()
|
||||
);
|
||||
|
||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||
|
||||
// You can also set some properties (see example7 to know the properties
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Trace communication between client and server
|
||||
vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>();
|
||||
@ -307,8 +325,8 @@ static void sendMessage()
|
||||
vmime::mailbox from(fromString);
|
||||
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.flush();
|
||||
|
||||
@ -317,24 +335,26 @@ static void sendMessage()
|
||||
|
||||
cont = (toString.size() != 0);
|
||||
|
||||
if (cont)
|
||||
if (cont) {
|
||||
to.appendMailbox(vmime::make_shared <vmime::mailbox>(toString));
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Enter message data, including headers (end with '.' on a single line):" << std::endl;
|
||||
|
||||
std::ostringstream data;
|
||||
|
||||
for (bool cont = true ; cont ; )
|
||||
{
|
||||
for (bool cont = true ; cont ; ) {
|
||||
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
|
||||
if (line == ".")
|
||||
if (line == ".") {
|
||||
cont = false;
|
||||
else
|
||||
} else {
|
||||
data << line << "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to server
|
||||
tr->connect();
|
||||
@ -357,15 +377,15 @@ static void sendMessage()
|
||||
std::cout << traceStream->str();
|
||||
|
||||
tr->disconnect();
|
||||
}
|
||||
catch (vmime::exception& e)
|
||||
{
|
||||
|
||||
} catch (vmime::exception& e) {
|
||||
|
||||
std::cerr << std::endl;
|
||||
std::cerr << e << std::endl;
|
||||
throw;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
||||
} catch (std::exception& e) {
|
||||
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "std::exception: " << e.what() << std::endl;
|
||||
throw;
|
||||
@ -375,10 +395,10 @@ static void sendMessage()
|
||||
|
||||
/** Connect to a message store interactively.
|
||||
*/
|
||||
static void connectStore()
|
||||
{
|
||||
try
|
||||
{
|
||||
static void connectStore() {
|
||||
|
||||
try {
|
||||
|
||||
// Request user to enter an URL
|
||||
std::cout << "Enter an URL to connect to store service." << 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".
|
||||
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>());
|
||||
else
|
||||
} else {
|
||||
st = g_session->getStore(url);
|
||||
}
|
||||
|
||||
#if VMIME_HAVE_TLS_SUPPORT
|
||||
|
||||
@ -411,8 +432,9 @@ static void connectStore()
|
||||
|
||||
// Set the object responsible for verifying certificates, in the
|
||||
// case a secured connection is used (TLS/SSL)
|
||||
st->setCertificateVerifier
|
||||
(vmime::make_shared <interactiveCertificateVerifier>());
|
||||
st->setCertificateVerifier(
|
||||
vmime::make_shared <interactiveCertificateVerifier>()
|
||||
);
|
||||
|
||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||
|
||||
@ -441,13 +463,13 @@ static void connectStore()
|
||||
std::cout << 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;
|
||||
MessageList msgList;
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
|
||||
std::vector <std::string> choices;
|
||||
|
||||
choices.push_back("Show message flags");
|
||||
@ -470,8 +492,8 @@ static void connectStore()
|
||||
vmime::shared_ptr <vmime::net::message> msg;
|
||||
|
||||
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.flush();
|
||||
|
||||
@ -483,20 +505,20 @@ static void connectStore()
|
||||
vmime::size_t num = 0;
|
||||
iss >> num;
|
||||
|
||||
if (num < 1 || num > f->getMessageCount())
|
||||
{
|
||||
if (num < 1 || num > f->getMessageCount()) {
|
||||
|
||||
std::cerr << "Invalid message number." << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
MessageList::iterator it = msgList.find(num);
|
||||
|
||||
if (it != msgList.end())
|
||||
{
|
||||
if (it != msgList.end()) {
|
||||
|
||||
msg = (*it).second;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
msg = f->getMessage(num);
|
||||
msgList.insert(MessageList::value_type(num, msg));
|
||||
}
|
||||
@ -504,25 +526,31 @@ static void connectStore()
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
switch (choice)
|
||||
{
|
||||
switch (choice) {
|
||||
|
||||
// Show message flags
|
||||
case 1:
|
||||
|
||||
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;
|
||||
if (msg->getFlags() & vmime::net::message::FLAG_RECENT)
|
||||
}
|
||||
if (msg->getFlags() & vmime::net::message::FLAG_RECENT) {
|
||||
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;
|
||||
if (msg->getFlags() & vmime::net::message::FLAG_DELETED)
|
||||
}
|
||||
if (msg->getFlags() & vmime::net::message::FLAG_DELETED) {
|
||||
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;
|
||||
if (msg->getFlags() & vmime::net::message::FLAG_PASSED)
|
||||
}
|
||||
if (msg->getFlags() & vmime::net::message::FLAG_PASSED) {
|
||||
std::cout << "FLAG_PASSED" << std::endl;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@ -541,8 +569,8 @@ static void connectStore()
|
||||
break;
|
||||
|
||||
// Show message envelope
|
||||
case 4:
|
||||
{
|
||||
case 4: {
|
||||
|
||||
vmime::net::fetchAttributes attr(vmime::net::fetchAttributes::ENVELOPE);
|
||||
|
||||
// If you also want to fetch "Received: " fields:
|
||||
@ -555,37 +583,38 @@ static void connectStore()
|
||||
break;
|
||||
}
|
||||
// Extract whole message
|
||||
case 5:
|
||||
{
|
||||
case 5: {
|
||||
|
||||
vmime::utility::outputStreamAdapter out(std::cout);
|
||||
msg->extract(out);
|
||||
|
||||
break;
|
||||
}
|
||||
// Extract attachments
|
||||
case 6:
|
||||
{
|
||||
case 6: {
|
||||
|
||||
vmime::shared_ptr <vmime::message> parsedMsg = msg->getParsedMessage();
|
||||
|
||||
std::vector <vmime::shared_ptr <const vmime::attachment> > attchs =
|
||||
vmime::attachmentHelper::findAttachmentsInMessage(parsedMsg);
|
||||
|
||||
if (attchs.size() > 0)
|
||||
{
|
||||
if (attchs.size() > 0) {
|
||||
|
||||
std::cout << attchs.size() << " attachments found." << std::endl;
|
||||
|
||||
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;
|
||||
|
||||
// Get attachment size
|
||||
vmime::size_t size = 0;
|
||||
|
||||
if (att->getData()->isEncoded())
|
||||
if (att->getData()->isEncoded()) {
|
||||
size = att->getData()->getEncoding().getEncoder()->getDecodedSize(att->getData()->getLength());
|
||||
else
|
||||
} else {
|
||||
size = att->getData()->getLength();
|
||||
}
|
||||
|
||||
std::cout << "Found attachment '" << att->getName().getBuffer() << "'"
|
||||
<< ", size is " << size << " bytes:" << std::endl;
|
||||
@ -618,17 +647,17 @@ static void connectStore()
|
||||
att->getData()->extract(*output.get());
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
std::cout << "No attachments found." << std::endl;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
// Status
|
||||
case 7:
|
||||
{
|
||||
case 7: {
|
||||
|
||||
vmime::size_t count, unseen;
|
||||
f->status(count, unseen);
|
||||
|
||||
@ -636,17 +665,16 @@ static void connectStore()
|
||||
break;
|
||||
}
|
||||
// List folders
|
||||
case 8:
|
||||
{
|
||||
vmime::shared_ptr <vmime::net::folder>
|
||||
root = st->getRootFolder();
|
||||
case 8: {
|
||||
|
||||
vmime::shared_ptr <vmime::net::folder> root = st->getRootFolder();
|
||||
|
||||
printFolders(root);
|
||||
break;
|
||||
}
|
||||
// Change folder
|
||||
case 9:
|
||||
{
|
||||
case 9: {
|
||||
|
||||
std::cout << "Enter folder path (eg. /root/subfolder):" << std::endl;
|
||||
std::cout.flush();
|
||||
|
||||
@ -655,20 +683,22 @@ static void connectStore()
|
||||
|
||||
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);
|
||||
|
||||
const std::string x = (p == std::string::npos)
|
||||
? std::string(path.begin() + s, path.end())
|
||||
: std::string(path.begin() + s, path.begin() + p);
|
||||
|
||||
if (!x.empty())
|
||||
if (!x.empty()) {
|
||||
newFolder = newFolder->getFolder(vmime::utility::path::component(x));
|
||||
}
|
||||
|
||||
if (p == std::string::npos)
|
||||
if (p == std::string::npos) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
newFolder->open(vmime::net::folder::MODE_READ_WRITE);
|
||||
|
||||
@ -683,8 +713,8 @@ static void connectStore()
|
||||
break;
|
||||
}
|
||||
// Add message
|
||||
case 10:
|
||||
{
|
||||
case 10: {
|
||||
|
||||
vmime::messageBuilder mb;
|
||||
|
||||
mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
|
||||
@ -694,32 +724,35 @@ static void connectStore()
|
||||
mb.setRecipients(to);
|
||||
|
||||
mb.setSubject(vmime::text("Test message from VMime example6"));
|
||||
mb.getTextPart()->setText(vmime::make_shared <vmime::stringContentHandler>(
|
||||
"Body of test message from VMime example6."));
|
||||
mb.getTextPart()->setText(
|
||||
vmime::make_shared <vmime::stringContentHandler>(
|
||||
"Body of test message from VMime example6."
|
||||
)
|
||||
);
|
||||
|
||||
vmime::shared_ptr <vmime::message> msg = mb.construct();
|
||||
|
||||
vmime::net::messageSet set = f->addMessage(msg);
|
||||
|
||||
if (set.isEmpty())
|
||||
{
|
||||
if (set.isEmpty()) {
|
||||
|
||||
std::cout << "Message has successfully been added, "
|
||||
<< "but its UID/number is not known." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
const vmime::net::messageRange& range = set.getRangeAt(0);
|
||||
|
||||
if (set.isUIDSet())
|
||||
{
|
||||
if (set.isUIDSet()) {
|
||||
|
||||
const vmime::net::message::uid uid =
|
||||
dynamic_cast <const vmime::net::UIDMessageRange&>(range).getFirst();
|
||||
|
||||
std::cout << "Message has successfully been added, "
|
||||
<< "its UID is '" << uid << "'." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
const vmime::size_t number =
|
||||
dynamic_cast <const vmime::net::numberMessageRange&>(range).getFirst();
|
||||
|
||||
@ -731,30 +764,30 @@ static void connectStore()
|
||||
break;
|
||||
}
|
||||
// Copy message
|
||||
case 11:
|
||||
{
|
||||
case 11: {
|
||||
|
||||
vmime::net::messageSet set = f->copyMessages(f->getFullPath(),
|
||||
vmime::net::messageSet::byNumber(msg->getNumber()));
|
||||
|
||||
if (set.isEmpty())
|
||||
{
|
||||
if (set.isEmpty()) {
|
||||
|
||||
std::cout << "Message has successfully been copied, "
|
||||
<< "but its UID/number is not known." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
const vmime::net::messageRange& range = set.getRangeAt(0);
|
||||
|
||||
if (set.isUIDSet())
|
||||
{
|
||||
if (set.isUIDSet()) {
|
||||
|
||||
const vmime::net::message::uid uid =
|
||||
dynamic_cast <const vmime::net::UIDMessageRange&>(range).getFirst();
|
||||
|
||||
std::cout << "Message has successfully been copied, "
|
||||
<< "its UID is '" << uid << "'." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
const vmime::size_t number =
|
||||
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"));
|
||||
|
||||
if (!g->exists())
|
||||
if (!g->exists()) {
|
||||
g->create(vmime::net::folder::TYPE_CONTAINS_MESSAGES);
|
||||
}
|
||||
|
||||
f->copyMessages(g->getFullPath());
|
||||
}
|
||||
*/
|
||||
}
|
||||
catch (vmime::exception& e)
|
||||
{
|
||||
|
||||
} catch (vmime::exception& e) {
|
||||
|
||||
std::cerr << std::endl;
|
||||
std::cerr << e << std::endl;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
||||
} catch (std::exception& e) {
|
||||
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "std::exception: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
} // for(cont)
|
||||
|
||||
st->disconnect();
|
||||
}
|
||||
catch (vmime::exception& e)
|
||||
{
|
||||
|
||||
} catch (vmime::exception& e) {
|
||||
|
||||
std::cerr << std::endl;
|
||||
std::cerr << e << std::endl;
|
||||
throw;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
||||
} catch (std::exception& e) {
|
||||
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "std::exception: " << e.what() << std::endl;
|
||||
throw;
|
||||
@ -848,16 +883,16 @@ static void connectStore()
|
||||
*
|
||||
* @return true to quit the program, false to continue
|
||||
*/
|
||||
static bool menu()
|
||||
{
|
||||
static bool menu() {
|
||||
|
||||
std::vector <std::string> items;
|
||||
|
||||
items.push_back("Connect to a message store");
|
||||
items.push_back("Send a message");
|
||||
items.push_back("Quit");
|
||||
|
||||
switch (printMenu(items))
|
||||
{
|
||||
switch (printMenu(items)) {
|
||||
|
||||
// Connect to store
|
||||
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.
|
||||
// The locale should use UTF-8 encoding for these tests to run successfully.
|
||||
try
|
||||
{
|
||||
try {
|
||||
std::locale::global(std::locale(""));
|
||||
}
|
||||
catch (std::exception &)
|
||||
{
|
||||
} catch (std::exception &) {
|
||||
std::setlocale(LC_ALL, "");
|
||||
}
|
||||
|
||||
for (bool quit = false ; !quit ; )
|
||||
{
|
||||
for (bool quit = false ; !quit ; ) {
|
||||
|
||||
// Loop on main menu
|
||||
quit = menu();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3,52 +3,57 @@
|
||||
#if VMIME_HAVE_SASL_SUPPORT
|
||||
|
||||
// SASL authentication handler
|
||||
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> >& available,
|
||||
vmime::shared_ptr <vmime::security::sasl::SASLMechanism> suggested) const
|
||||
{
|
||||
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> >& available,
|
||||
const vmime::shared_ptr <vmime::security::sasl::SASLMechanism>& suggested
|
||||
) const {
|
||||
|
||||
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();
|
||||
|
||||
if (suggested && available[i]->getName() == suggested->getName())
|
||||
if (suggested && available[i]->getName() == suggested->getName()) {
|
||||
std::cout << "(suggested)";
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << std::endl << std::endl;
|
||||
|
||||
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;
|
||||
|
||||
defaultSASLAuthenticator::setSASLMechanism(mech);
|
||||
}
|
||||
|
||||
const vmime::string getUsername() const
|
||||
{
|
||||
if (m_username.empty())
|
||||
const vmime::string getUsername() const {
|
||||
|
||||
if (m_username.empty()) {
|
||||
m_username = getUserInput("Username");
|
||||
}
|
||||
|
||||
return m_username;
|
||||
}
|
||||
|
||||
const vmime::string getPassword() const
|
||||
{
|
||||
if (m_password.empty())
|
||||
const vmime::string getPassword() const {
|
||||
|
||||
if (m_password.empty()) {
|
||||
m_password = getUserInput("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.flush();
|
||||
|
||||
@ -67,26 +72,28 @@ private:
|
||||
#else // !VMIME_HAVE_SASL_SUPPORT
|
||||
|
||||
// Simple authentication handler
|
||||
class interactiveAuthenticator : public vmime::security::defaultAuthenticator
|
||||
{
|
||||
const vmime::string getUsername() const
|
||||
{
|
||||
if (m_username.empty())
|
||||
class interactiveAuthenticator : public vmime::security::defaultAuthenticator {
|
||||
|
||||
const vmime::string getUsername() const {
|
||||
|
||||
if (m_username.empty()) {
|
||||
m_username = getUserInput("Username");
|
||||
}
|
||||
|
||||
return m_username;
|
||||
}
|
||||
|
||||
const vmime::string getPassword() const
|
||||
{
|
||||
if (m_password.empty())
|
||||
const vmime::string getPassword() const {
|
||||
|
||||
if (m_password.empty()) {
|
||||
m_password = getUserInput("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.flush();
|
||||
|
||||
@ -103,4 +110,3 @@ private:
|
||||
};
|
||||
|
||||
#endif // VMIME_HAVE_SASL_SUPPORT
|
||||
|
||||
|
@ -3,20 +3,23 @@
|
||||
#if VMIME_HAVE_TLS_SUPPORT
|
||||
|
||||
// Certificate verifier (TLS/SSL)
|
||||
class interactiveCertificateVerifier : public vmime::security::cert::defaultCertificateVerifier
|
||||
{
|
||||
class interactiveCertificateVerifier : public vmime::security::cert::defaultCertificateVerifier {
|
||||
|
||||
public:
|
||||
|
||||
void verify(vmime::shared_ptr <vmime::security::cert::certificateChain> chain, const vmime::string& hostname)
|
||||
{
|
||||
try
|
||||
{
|
||||
void verify(
|
||||
const vmime::shared_ptr <vmime::security::cert::certificateChain>& chain,
|
||||
const vmime::string& hostname
|
||||
) {
|
||||
|
||||
try {
|
||||
|
||||
setX509TrustedCerts(m_trustedCerts);
|
||||
|
||||
defaultCertificateVerifier::verify(chain, hostname);
|
||||
}
|
||||
catch (vmime::security::cert::certificateException&)
|
||||
{
|
||||
|
||||
} catch (vmime::security::cert::certificateException&) {
|
||||
|
||||
// Obtain subject's certificate
|
||||
vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0);
|
||||
|
||||
@ -29,13 +32,14 @@ public:
|
||||
std::getline(std::cin, answer);
|
||||
|
||||
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
|
||||
if (cert->getType() == "X.509")
|
||||
{
|
||||
m_trustedCerts.push_back(vmime::dynamicCast
|
||||
<vmime::security::cert::X509Certificate>(cert));
|
||||
if (cert->getType() == "X.509") {
|
||||
|
||||
m_trustedCerts.push_back(
|
||||
vmime::dynamicCast <vmime::security::cert::X509Certificate>(cert)
|
||||
);
|
||||
|
||||
setX509TrustedCerts(m_trustedCerts);
|
||||
defaultCertificateVerifier::verify(chain, hostname);
|
||||
@ -44,8 +48,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
throw vmime::security::cert::certificateException
|
||||
("User did not accept the certificate.");
|
||||
throw vmime::security::cert::certificateException("User did not accept the certificate.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,4 +62,3 @@ std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> >
|
||||
interactiveCertificateVerifier::m_trustedCerts;
|
||||
|
||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||
|
||||
|
@ -5,17 +5,17 @@
|
||||
* Used to stop the current operation after too much time, or if the user
|
||||
* requested cancellation.
|
||||
*/
|
||||
class timeoutHandler : public vmime::net::timeoutHandler
|
||||
{
|
||||
class timeoutHandler : public vmime::net::timeoutHandler {
|
||||
|
||||
public:
|
||||
|
||||
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
|
||||
// the current operation. If you return true, handleTimeOut() will
|
||||
// be called just after this, and before actually cancelling the
|
||||
@ -25,15 +25,15 @@ public:
|
||||
return (time(NULL) - m_start) >= 10; // seconds
|
||||
}
|
||||
|
||||
void resetTimeOut()
|
||||
{
|
||||
void resetTimeOut() {
|
||||
|
||||
// Called at the beginning of an operation (eg. connecting,
|
||||
// a read() or a write() on a socket...)
|
||||
m_start = time(NULL);
|
||||
}
|
||||
|
||||
bool handleTimeOut()
|
||||
{
|
||||
bool handleTimeOut() {
|
||||
|
||||
// If isTimeOut() returned true, this function will be called. This
|
||||
// allows you to interact with the user, ie. display a prompt to
|
||||
// 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:
|
||||
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> create()
|
||||
{
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> create() {
|
||||
|
||||
return vmime::make_shared <timeoutHandler>();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,25 +1,29 @@
|
||||
|
||||
/** Tracer used to demonstrate logging communication between client and server.
|
||||
*/
|
||||
class myTracer : public vmime::net::tracer {
|
||||
|
||||
class myTracer : public vmime::net::tracer
|
||||
{
|
||||
public:
|
||||
|
||||
myTracer(vmime::shared_ptr <std::ostringstream> stream,
|
||||
vmime::shared_ptr <vmime::net::service> serv, const int connectionId)
|
||||
: m_stream(stream), m_service(serv), m_connectionId(connectionId)
|
||||
{
|
||||
myTracer(
|
||||
const vmime::shared_ptr <std::ostringstream>& stream,
|
||||
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
|
||||
<< "] C: " << line << std::endl;
|
||||
}
|
||||
|
||||
void traceReceive(const vmime::string& line)
|
||||
{
|
||||
void traceReceive(const vmime::string& line) {
|
||||
|
||||
*m_stream << "[" << m_service->getProtocolName() << ":" << m_connectionId
|
||||
<< "] S: " << line << std::endl;
|
||||
}
|
||||
@ -31,18 +35,21 @@ private:
|
||||
const int m_connectionId;
|
||||
};
|
||||
|
||||
class myTracerFactory : public vmime::net::tracerFactory
|
||||
{
|
||||
|
||||
class myTracerFactory : public vmime::net::tracerFactory {
|
||||
|
||||
public:
|
||||
|
||||
myTracerFactory(vmime::shared_ptr <std::ostringstream> stream)
|
||||
: m_stream(stream)
|
||||
{
|
||||
myTracerFactory(const vmime::shared_ptr <std::ostringstream>& stream)
|
||||
: m_stream(stream) {
|
||||
|
||||
}
|
||||
|
||||
vmime::shared_ptr <vmime::net::tracer> create
|
||||
(vmime::shared_ptr <vmime::net::service> serv, const int connectionId)
|
||||
{
|
||||
vmime::shared_ptr <vmime::net::tracer> create(
|
||||
const vmime::shared_ptr <vmime::net::service>& serv,
|
||||
const int connectionId
|
||||
) {
|
||||
|
||||
return vmime::make_shared <myTracer>(m_stream, serv, connectionId);
|
||||
}
|
||||
|
||||
@ -50,4 +57,3 @@ private:
|
||||
|
||||
vmime::shared_ptr <std::ostringstream> m_stream;
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -39,16 +39,16 @@
|
||||
#include "vmime/platforms/posix/posixHandler.hpp"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
|
||||
// Enumerate encoders
|
||||
vmime::shared_ptr <vmime::utility::encoder::encoderFactory> ef =
|
||||
vmime::utility::encoder::encoderFactory::getInstance();
|
||||
|
||||
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>
|
||||
enc = ef->getEncoderAt(i);
|
||||
|
||||
@ -59,9 +59,10 @@ int main()
|
||||
|
||||
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 << std::endl;
|
||||
|
||||
@ -71,8 +72,8 @@ int main()
|
||||
|
||||
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);
|
||||
|
||||
std::cout << " * " << serv.getName() << std::endl;
|
||||
@ -81,16 +82,15 @@ int main()
|
||||
serv.getInfos().getAvailableProperties();
|
||||
|
||||
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::string name = serv.getInfos().getPropertyPrefix() + p.getName();
|
||||
|
||||
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_STRING: type = "TYPE_STRING"; break;
|
||||
case vmime::net::serviceInfos::property::TYPE_BOOLEAN: type = "TYPE_BOOLEAN"; break;
|
||||
@ -99,10 +99,12 @@ int main()
|
||||
|
||||
vmime::string flags;
|
||||
|
||||
if (p.getFlags() & vmime::net::serviceInfos::property::FLAG_REQUIRED)
|
||||
if (p.getFlags() & vmime::net::serviceInfos::property::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";
|
||||
}
|
||||
|
||||
std::cout << " - " << serv.getInfos().getPropertyPrefix() + p.getName();
|
||||
std::cout << " (type=" << type << ", flags=" << flags;
|
||||
@ -111,5 +113,6 @@ int main()
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// 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;
|
||||
|
||||
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();
|
||||
|
||||
for (int i = 0 ; i < children.size() ; ++i)
|
||||
{
|
||||
for (int i = 0 ; i < children.size() ; ++i) {
|
||||
insertRowInModel(model, children[i], &iter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void updateTreeView()
|
||||
{
|
||||
void updateTreeView() {
|
||||
|
||||
GtkTreeStore* model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeView)));
|
||||
|
||||
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;
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
void openFile(const std::string& filename)
|
||||
{
|
||||
void openFile(const std::string& filename) {
|
||||
|
||||
std::ifstream file;
|
||||
file.open(filename.c_str(), std::ios::in | std::ios::binary);
|
||||
|
||||
if (!file)
|
||||
{
|
||||
if (!file) {
|
||||
std::cerr << "Can't open file '" << filename << "'." << std::endl;
|
||||
return;
|
||||
}
|
||||
@ -132,12 +134,10 @@ void openFile(const std::string& filename)
|
||||
vmime::string data;
|
||||
char buffer[16384];
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
file.read(buffer, sizeof(buffer));
|
||||
data += vmime::string(buffer, file.gcount());
|
||||
}
|
||||
while (file.gcount());
|
||||
} while (file.gcount());
|
||||
|
||||
vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>();
|
||||
msg->parse(data);
|
||||
@ -147,13 +147,13 @@ void openFile(const std::string& filename)
|
||||
char* convData = g_convert_with_fallback(data.c_str(), data.length(),
|
||||
"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)),
|
||||
"GLib UTF-8 conversion error.", -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textArea)),
|
||||
convData, strlen(convData));
|
||||
|
||||
@ -164,16 +164,19 @@ void openFile(const std::string& filename)
|
||||
}
|
||||
|
||||
|
||||
static void onFileOpen()
|
||||
{
|
||||
GtkWidget* dlg = gtk_file_chooser_dialog_new
|
||||
("Open Message File", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
static void onFileOpen() {
|
||||
|
||||
GtkWidget* dlg = gtk_file_chooser_dialog_new(
|
||||
"Open Message File",
|
||||
GTK_WINDOW(window),
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
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));
|
||||
|
||||
openFile(filename);
|
||||
@ -187,8 +190,7 @@ static void onFileOpen()
|
||||
|
||||
|
||||
// UI definitions
|
||||
static const GtkActionEntry uiActions[] =
|
||||
{
|
||||
static const GtkActionEntry uiActions[] = {
|
||||
{ "FileMenu", NULL, "_File" },
|
||||
{ "FileOpen", GTK_STOCK_OPEN, "_Open...", "<control>O", NULL, G_CALLBACK(onFileOpen) },
|
||||
{ "FileExit", GTK_STOCK_QUIT, "_Exit", "<control>Q", NULL, G_CALLBACK(gtk_main_quit) }
|
||||
@ -205,8 +207,8 @@ static const char* uiDefinition =
|
||||
"</ui>";
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
// VMime initialization
|
||||
vmime::platform::setHandler<vmime::platforms::posix::posixHandler>();
|
||||
|
||||
@ -290,5 +292,3 @@ int main(int argc, char* argv[])
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -29,12 +29,11 @@
|
||||
#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
|
||||
(const parsingContext& ctx, const string& buffer, const size_t position,
|
||||
const size_t end, size_t* newPosition, bool *isLastAddressOfGroup)
|
||||
{
|
||||
shared_ptr <address> address::parseNext(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition,
|
||||
bool *isLastAddressOfGroup
|
||||
) {
|
||||
|
||||
bool escaped = false;
|
||||
bool quoted = false;
|
||||
bool quotedRFC2047 = false;
|
||||
@ -78,36 +82,45 @@ shared_ptr <address> address::parseNext
|
||||
bool stop = false;
|
||||
int commentLevel = 0;
|
||||
|
||||
if (isLastAddressOfGroup)
|
||||
if (isLastAddressOfGroup) {
|
||||
*isLastAddressOfGroup = false;
|
||||
}
|
||||
|
||||
size_t pos = position;
|
||||
|
||||
while (pos < end && parserHelpers::isSpace(buffer[pos]))
|
||||
while (pos < end && parserHelpers::isSpace(buffer[pos])) {
|
||||
++pos;
|
||||
}
|
||||
|
||||
const size_t start = pos;
|
||||
|
||||
while (!stop && pos < end)
|
||||
{
|
||||
if (escaped)
|
||||
{
|
||||
while (!stop && pos < end) {
|
||||
|
||||
if (escaped) {
|
||||
|
||||
escaped = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (buffer[pos])
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
switch (buffer[pos]) {
|
||||
|
||||
case '\\':
|
||||
|
||||
escaped = true;
|
||||
break;
|
||||
|
||||
case '"':
|
||||
|
||||
quoted = !quoted;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
|
||||
inRouteAddr = true;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
|
||||
inRouteAddr = false;
|
||||
break;
|
||||
|
||||
@ -118,15 +131,15 @@ shared_ptr <address> address::parseNext
|
||||
|
||||
case ')':
|
||||
|
||||
if (commentLevel > 0)
|
||||
if (commentLevel > 0) {
|
||||
--commentLevel;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '=':
|
||||
|
||||
if (commentLevel == 0 && !quoted && !quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '?')
|
||||
{
|
||||
if (commentLevel == 0 && !quoted && !quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '?') {
|
||||
++pos;
|
||||
quotedRFC2047 = true;
|
||||
}
|
||||
@ -135,8 +148,7 @@ shared_ptr <address> address::parseNext
|
||||
|
||||
case '?':
|
||||
|
||||
if (commentLevel == 0 && quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '=')
|
||||
{
|
||||
if (commentLevel == 0 && quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '=') {
|
||||
++pos;
|
||||
quotedRFC2047 = false;
|
||||
}
|
||||
@ -145,20 +157,22 @@ shared_ptr <address> address::parseNext
|
||||
|
||||
default:
|
||||
{
|
||||
if (commentLevel == 0 && !quoted && !quotedRFC2047 && !inRouteAddr)
|
||||
{
|
||||
switch (buffer[pos])
|
||||
{
|
||||
if (commentLevel == 0 && !quoted && !quotedRFC2047 && !inRouteAddr) {
|
||||
|
||||
switch (buffer[pos]) {
|
||||
|
||||
case ';':
|
||||
|
||||
if (isGroup)
|
||||
{
|
||||
if (pos + 1 < end && buffer[pos + 1] == ',')
|
||||
if (isGroup) {
|
||||
|
||||
if (pos + 1 < end && buffer[pos + 1] == ',') {
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (isLastAddressOfGroup)
|
||||
if (isLastAddressOfGroup) {
|
||||
*isLastAddressOfGroup = true;
|
||||
}
|
||||
|
||||
stop = true;
|
||||
break;
|
||||
@ -170,7 +184,10 @@ shared_ptr <address> address::parseNext
|
||||
|
||||
case ',':
|
||||
|
||||
if (!isGroup) stop = true;
|
||||
if (!isGroup) {
|
||||
stop = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -181,32 +198,35 @@ shared_ptr <address> address::parseNext
|
||||
}
|
||||
}
|
||||
|
||||
if (!stop)
|
||||
if (!stop) {
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (newPosition)
|
||||
{
|
||||
if (pos == end)
|
||||
if (newPosition) {
|
||||
|
||||
if (pos == end) {
|
||||
*newPosition = end;
|
||||
else
|
||||
} else {
|
||||
*newPosition = pos + 1; // ',' or ';'
|
||||
}
|
||||
}
|
||||
|
||||
// Parse extracted address (mailbox or group)
|
||||
if (pos != start)
|
||||
{
|
||||
if (pos != start) {
|
||||
|
||||
shared_ptr <address> parsedAddress;
|
||||
|
||||
if (isGroup)
|
||||
if (isGroup) {
|
||||
parsedAddress = make_shared <mailboxGroup>();
|
||||
else
|
||||
} else {
|
||||
parsedAddress = make_shared <mailbox>();
|
||||
}
|
||||
|
||||
parsedAddress->parse(ctx, buffer, start, pos, NULL);
|
||||
parsedAddress->setParsedBounds(start, pos);
|
||||
|
||||
return (parsedAddress);
|
||||
return parsedAddress;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -29,8 +29,7 @@
|
||||
#include "vmime/headerFieldValue.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** 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
|
||||
* and mailboxGroup classes.
|
||||
*/
|
||||
class VMIME_EXPORT address : public headerFieldValue {
|
||||
|
||||
class VMIME_EXPORT address : public headerFieldValue
|
||||
{
|
||||
protected:
|
||||
|
||||
address();
|
||||
@ -74,10 +72,14 @@ public:
|
||||
* 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
|
||||
*/
|
||||
static shared_ptr <address> parseNext
|
||||
(const parsingContext& ctx, const string& buffer,
|
||||
const size_t position, const size_t end,
|
||||
size_t* newPosition, bool *isLastAddressOfGroup);
|
||||
static shared_ptr <address> parseNext(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition,
|
||||
bool *isLastAddressOfGroup
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -28,181 +28,204 @@
|
||||
#include "vmime/mailboxGroup.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
addressList::addressList()
|
||||
{
|
||||
addressList::addressList() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
addressList::addressList(const addressList& addrList)
|
||||
: headerFieldValue()
|
||||
{
|
||||
: headerFieldValue() {
|
||||
|
||||
copyFrom(addrList);
|
||||
}
|
||||
|
||||
|
||||
addressList::~addressList()
|
||||
{
|
||||
addressList::~addressList() {
|
||||
|
||||
removeAllAddresses();
|
||||
}
|
||||
|
||||
|
||||
void addressList::parseImpl
|
||||
(const parsingContext& ctx, const string& buffer, const size_t position,
|
||||
const size_t end, size_t* newPosition)
|
||||
{
|
||||
void addressList::parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition
|
||||
) {
|
||||
|
||||
removeAllAddresses();
|
||||
|
||||
size_t pos = position;
|
||||
|
||||
while (pos < end)
|
||||
{
|
||||
while (pos < end) {
|
||||
|
||||
shared_ptr <address> parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, NULL);
|
||||
|
||||
if (parsedAddress != NULL)
|
||||
if (parsedAddress) {
|
||||
m_list.push_back(parsedAddress);
|
||||
}
|
||||
}
|
||||
|
||||
setParsedBounds(position, end);
|
||||
|
||||
if (newPosition)
|
||||
if (newPosition) {
|
||||
*newPosition = end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void addressList::generateImpl
|
||||
(const generationContext& ctx, utility::outputStream& os,
|
||||
const size_t curLinePos, size_t* newLinePos) const
|
||||
{
|
||||
void addressList::generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos,
|
||||
size_t* newLinePos
|
||||
) const {
|
||||
|
||||
size_t pos = curLinePos;
|
||||
|
||||
generationContext tmpCtx(ctx);
|
||||
tmpCtx.setMaxLineLength(tmpCtx.getMaxLineLength() - 2);
|
||||
|
||||
if (!m_list.empty())
|
||||
{
|
||||
for (std::vector <shared_ptr <address> >::const_iterator i = m_list.begin() ; ; )
|
||||
{
|
||||
if (!m_list.empty()) {
|
||||
|
||||
for (std::vector <shared_ptr <address> >::const_iterator i = m_list.begin() ; ; ) {
|
||||
|
||||
(*i)->generate(ctx, os, pos, &pos);
|
||||
|
||||
if (++i == m_list.end())
|
||||
if (++i == m_list.end()) {
|
||||
break;
|
||||
}
|
||||
|
||||
os << ", ";
|
||||
pos += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (newLinePos)
|
||||
if (newLinePos) {
|
||||
*newLinePos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void addressList::copyFrom(const component& other)
|
||||
{
|
||||
void addressList::copyFrom(const component& other) {
|
||||
|
||||
const addressList& addrList = dynamic_cast <const addressList&>(other);
|
||||
|
||||
removeAllAddresses();
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
addressList& addressList::operator=(const addressList& other)
|
||||
{
|
||||
addressList& addressList::operator=(const addressList& other) {
|
||||
|
||||
copyFrom(other);
|
||||
return (*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
addressList& addressList::operator=(const mailboxList& other)
|
||||
{
|
||||
addressList& addressList::operator=(const mailboxList& other) {
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
return (*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <component> addressList::clone() const
|
||||
{
|
||||
shared_ptr <component> addressList::clone() const {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void addressList::insertAddressBefore(shared_ptr <address> beforeAddress, shared_ptr <address> addr)
|
||||
{
|
||||
const std::vector <shared_ptr <address> >::iterator it = std::find
|
||||
(m_list.begin(), m_list.end(), beforeAddress);
|
||||
void addressList::insertAddressBefore(const shared_ptr <address>& beforeAddress, const shared_ptr <address>& addr) {
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
m_list.insert(it, addr);
|
||||
}
|
||||
|
||||
|
||||
void addressList::insertAddressBefore(const size_t pos, shared_ptr <address> addr)
|
||||
{
|
||||
if (pos >= m_list.size())
|
||||
void addressList::insertAddressBefore(const size_t pos, const shared_ptr <address>& addr) {
|
||||
|
||||
if (pos >= m_list.size()) {
|
||||
throw std::out_of_range("Invalid position");
|
||||
}
|
||||
|
||||
m_list.insert(m_list.begin() + pos, addr);
|
||||
}
|
||||
|
||||
|
||||
void addressList::insertAddressAfter(shared_ptr <address> afterAddress, shared_ptr <address> addr)
|
||||
{
|
||||
const std::vector <shared_ptr <address> >::iterator it = std::find
|
||||
(m_list.begin(), m_list.end(), afterAddress);
|
||||
void addressList::insertAddressAfter(
|
||||
const shared_ptr <address>& afterAddress,
|
||||
const shared_ptr <address>& addr
|
||||
) {
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
m_list.insert(it + 1, addr);
|
||||
}
|
||||
|
||||
|
||||
void addressList::insertAddressAfter(const size_t pos, shared_ptr <address> addr)
|
||||
{
|
||||
if (pos >= m_list.size())
|
||||
void addressList::insertAddressAfter(const size_t pos, const shared_ptr <address>& addr) {
|
||||
|
||||
if (pos >= m_list.size()) {
|
||||
throw std::out_of_range("Invalid position");
|
||||
}
|
||||
|
||||
m_list.insert(m_list.begin() + pos + 1, addr);
|
||||
}
|
||||
|
||||
|
||||
void addressList::removeAddress(shared_ptr <address> addr)
|
||||
{
|
||||
const std::vector <shared_ptr <address> >::iterator it = std::find
|
||||
(m_list.begin(), m_list.end(), addr);
|
||||
void addressList::removeAddress(const shared_ptr <address>& 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");
|
||||
}
|
||||
|
||||
m_list.erase(it);
|
||||
}
|
||||
|
||||
|
||||
void addressList::removeAddress(const size_t pos)
|
||||
{
|
||||
if (pos >= m_list.size())
|
||||
void addressList::removeAddress(const size_t pos) {
|
||||
|
||||
if (pos >= m_list.size()) {
|
||||
throw std::out_of_range("Invalid position");
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
size_t addressList::getAddressCount() const
|
||||
{
|
||||
return (m_list.size());
|
||||
size_t addressList::getAddressCount() const {
|
||||
|
||||
return m_list.size();
|
||||
}
|
||||
|
||||
|
||||
bool addressList::isEmpty() const
|
||||
{
|
||||
return (m_list.empty());
|
||||
bool addressList::isEmpty() const {
|
||||
|
||||
return m_list.empty();
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <address> addressList::getAddressAt(const size_t pos)
|
||||
{
|
||||
return (m_list[pos]);
|
||||
shared_ptr <address> addressList::getAddressAt(const size_t pos) {
|
||||
|
||||
return m_list[pos];
|
||||
}
|
||||
|
||||
|
||||
const shared_ptr <const address> addressList::getAddressAt(const size_t pos) const
|
||||
{
|
||||
return (m_list[pos]);
|
||||
const shared_ptr <const address> addressList::getAddressAt(const size_t pos) const {
|
||||
|
||||
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;
|
||||
|
||||
list.reserve(m_list.size());
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return (list);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
const std::vector <shared_ptr <address> > addressList::getAddressList()
|
||||
{
|
||||
return (m_list);
|
||||
const std::vector <shared_ptr <address> > addressList::getAddressList() {
|
||||
|
||||
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;
|
||||
|
||||
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>();
|
||||
|
||||
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;
|
||||
|
||||
if (addr->isGroup())
|
||||
{
|
||||
if (addr->isGroup()) {
|
||||
|
||||
const std::vector <shared_ptr <const mailbox> > mailboxes =
|
||||
dynamicCast <const mailboxGroup>(addr)->getMailboxList();
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
res->appendMailbox(dynamicCast <mailbox>(addr->clone()));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -31,8 +31,7 @@
|
||||
#include "vmime/address.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
class mailboxList;
|
||||
@ -40,9 +39,8 @@ class mailboxList;
|
||||
|
||||
/** A list of addresses.
|
||||
*/
|
||||
class VMIME_EXPORT addressList : public headerFieldValue {
|
||||
|
||||
class VMIME_EXPORT addressList : public headerFieldValue
|
||||
{
|
||||
public:
|
||||
|
||||
addressList();
|
||||
@ -63,7 +61,7 @@ public:
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
@ -71,7 +69,10 @@ public:
|
||||
* @param addr address to insert
|
||||
* @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.
|
||||
*
|
||||
@ -80,7 +81,7 @@ public:
|
||||
* @param addr address to insert
|
||||
* @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.
|
||||
*
|
||||
@ -88,7 +89,10 @@ public:
|
||||
* @param addr address to insert
|
||||
* @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.
|
||||
*
|
||||
@ -96,14 +100,14 @@ public:
|
||||
* @param addr address to insert
|
||||
* @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.
|
||||
*
|
||||
* @param addr address to remove
|
||||
* @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.
|
||||
*
|
||||
@ -171,18 +175,20 @@ private:
|
||||
protected:
|
||||
|
||||
// Component parsing & assembling
|
||||
void parseImpl
|
||||
(const parsingContext& ctx,
|
||||
void parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
void generateImpl
|
||||
(const generationContext& ctx,
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
size_t* newLinePos = NULL) const;
|
||||
size_t* newLinePos = NULL
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -34,15 +34,13 @@
|
||||
#include "vmime/encoding.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** Base class for all types of attachment.
|
||||
*/
|
||||
class VMIME_EXPORT attachment : public object {
|
||||
|
||||
class VMIME_EXPORT attachment : public object
|
||||
{
|
||||
friend class messageBuilder;
|
||||
friend class messageParser;
|
||||
friend class attachmentHelper;
|
||||
@ -108,7 +106,7 @@ protected:
|
||||
*
|
||||
* @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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -33,36 +33,39 @@
|
||||
#include <iterator>
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
// static
|
||||
bool attachmentHelper::isBodyPartAnAttachment
|
||||
(shared_ptr <const bodyPart> part, const unsigned int options)
|
||||
{
|
||||
bool attachmentHelper::isBodyPartAnAttachment(
|
||||
const shared_ptr <const bodyPart>& part,
|
||||
const unsigned int options
|
||||
) {
|
||||
|
||||
// First, try with "Content-Disposition" field.
|
||||
// If not present, we will try with "Content-Type" field.
|
||||
shared_ptr <const contentDispositionField> cdf =
|
||||
part->getHeader()->findField <contentDispositionField>(fields::CONTENT_DISPOSITION);
|
||||
|
||||
if (cdf)
|
||||
{
|
||||
if (cdf) {
|
||||
|
||||
const contentDisposition disp = *cdf->getValue <contentDisposition>();
|
||||
|
||||
if (disp.getName() != contentDispositionTypes::INLINE)
|
||||
if (disp.getName() != contentDispositionTypes::INLINE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((options & INLINE_OBJECTS) == 0) {
|
||||
|
||||
if ((options & INLINE_OBJECTS) == 0)
|
||||
{
|
||||
// If the Content-Disposition is 'inline' and there is no
|
||||
// Content-Id or Content-Location field, it may be an attachment
|
||||
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 (part->getParentPart() == NULL)
|
||||
if (!part->getParentPart()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -78,41 +81,47 @@ bool attachmentHelper::isBodyPartAnAttachment
|
||||
shared_ptr <const contentTypeField> ctf =
|
||||
part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
|
||||
|
||||
if (ctf)
|
||||
{
|
||||
if (ctf) {
|
||||
|
||||
type = *ctf->getValue <mediaType>();
|
||||
|
||||
if (ctf->hasParameter("name"))
|
||||
if (ctf->hasParameter("name")) {
|
||||
hasContentTypeName = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// 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
|
||||
// an attachment
|
||||
if (part->getParentPart() == NULL)
|
||||
if (!part->getParentPart()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// No "Content-type" field: assume "application/octet-stream".
|
||||
type = mediaType(mediaTypes::APPLICATION,
|
||||
mediaTypes::APPLICATION_OCTET_STREAM);
|
||||
type = mediaType(
|
||||
mediaTypes::APPLICATION,
|
||||
mediaTypes::APPLICATION_OCTET_STREAM
|
||||
);
|
||||
}
|
||||
|
||||
if (type.getType() != mediaTypes::TEXT &&
|
||||
type.getType() != mediaTypes::MULTIPART)
|
||||
{
|
||||
type.getType() != mediaTypes::MULTIPART) {
|
||||
|
||||
// Compatibility with (obsolete) RFC-1341: if there is a "name" parameter
|
||||
// on the "Content-Type" field, then we assume it is an attachment
|
||||
if (hasContentTypeName)
|
||||
if (hasContentTypeName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((options & INLINE_OBJECTS) == 0) {
|
||||
|
||||
if ((options & INLINE_OBJECTS) == 0)
|
||||
{
|
||||
// If a "Content-Id" field is present, it might be an
|
||||
// embedded object (MHTML messages)
|
||||
if (part->getHeader()->hasField(vmime::fields::CONTENT_ID))
|
||||
if (part->getHeader()->hasField(vmime::fields::CONTENT_ID)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -122,35 +131,40 @@ bool attachmentHelper::isBodyPartAnAttachment
|
||||
|
||||
|
||||
// static
|
||||
shared_ptr <const attachment> attachmentHelper::getBodyPartAttachment
|
||||
(shared_ptr <const bodyPart> part, const unsigned int options)
|
||||
{
|
||||
if (!isBodyPartAnAttachment(part, options))
|
||||
shared_ptr <const attachment> attachmentHelper::getBodyPartAttachment(
|
||||
const shared_ptr <const bodyPart>& part,
|
||||
const unsigned int options
|
||||
) {
|
||||
|
||||
if (!isBodyPartAnAttachment(part, options)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
mediaType type;
|
||||
|
||||
shared_ptr <const contentTypeField> ctf =
|
||||
part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
|
||||
|
||||
if (ctf)
|
||||
{
|
||||
if (ctf) {
|
||||
|
||||
type = *ctf->getValue <mediaType>();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// No "Content-type" field: assume "application/octet-stream".
|
||||
type = mediaType(mediaTypes::APPLICATION,
|
||||
mediaTypes::APPLICATION_OCTET_STREAM);
|
||||
type = mediaType(
|
||||
mediaTypes::APPLICATION,
|
||||
mediaTypes::APPLICATION_OCTET_STREAM
|
||||
);
|
||||
}
|
||||
|
||||
if (type.getType() == mediaTypes::MESSAGE &&
|
||||
type.getSubType() == mediaTypes::MESSAGE_RFC822)
|
||||
{
|
||||
type.getSubType() == mediaTypes::MESSAGE_RFC822) {
|
||||
|
||||
return make_shared <generatedMessageAttachment>(part);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
return make_shared <bodyPartAttachment>(part);
|
||||
}
|
||||
}
|
||||
@ -158,32 +172,36 @@ shared_ptr <const attachment> attachmentHelper::getBodyPartAttachment
|
||||
|
||||
// static
|
||||
const std::vector <shared_ptr <const attachment> >
|
||||
attachmentHelper::findAttachmentsInMessage
|
||||
(shared_ptr <const message> msg, const unsigned int options)
|
||||
{
|
||||
attachmentHelper::findAttachmentsInMessage(
|
||||
const shared_ptr <const message>& msg,
|
||||
const unsigned int options
|
||||
) {
|
||||
|
||||
return findAttachmentsInBodyPart(msg, options);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
const std::vector <shared_ptr <const attachment> >
|
||||
attachmentHelper::findAttachmentsInBodyPart
|
||||
(shared_ptr <const bodyPart> part, const unsigned int options)
|
||||
{
|
||||
attachmentHelper::findAttachmentsInBodyPart(
|
||||
const shared_ptr <const bodyPart>& part,
|
||||
const unsigned int options
|
||||
) {
|
||||
|
||||
std::vector <shared_ptr <const attachment> > atts;
|
||||
|
||||
// Test this part
|
||||
if (isBodyPartAnAttachment(part, options))
|
||||
{
|
||||
if (isBodyPartAnAttachment(part, options)) {
|
||||
|
||||
atts.push_back(getBodyPartAttachment(part, options));
|
||||
}
|
||||
|
||||
// Find in sub-parts
|
||||
else
|
||||
{
|
||||
} else {
|
||||
|
||||
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 =
|
||||
findAttachmentsInBodyPart(bdy->getPartAt(i), options);
|
||||
|
||||
@ -196,35 +214,39 @@ const std::vector <shared_ptr <const attachment> >
|
||||
|
||||
|
||||
// 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,
|
||||
// create it in the root part. This (very simple) algorithm should
|
||||
// work in the most cases.
|
||||
|
||||
vmime::mediaType mpMixed(vmime::mediaTypes::MULTIPART,
|
||||
vmime::mediaTypes::MULTIPART_MIXED);
|
||||
vmime::mediaType mpMixed(
|
||||
vmime::mediaTypes::MULTIPART,
|
||||
vmime::mediaTypes::MULTIPART_MIXED
|
||||
);
|
||||
|
||||
shared_ptr <bodyPart> part = findBodyPart(msg, mpMixed);
|
||||
|
||||
if (part == NULL) // create it
|
||||
{
|
||||
if (msg->getBody()->getPartCount() != 0)
|
||||
{
|
||||
if (!part) { // create it
|
||||
|
||||
if (msg->getBody()->getPartCount() != 0) {
|
||||
|
||||
// Create a new container part for the parts that were in
|
||||
// the root part of the message
|
||||
shared_ptr <bodyPart> container = make_shared <bodyPart>();
|
||||
|
||||
if (msg->getHeader()->hasField(fields::CONTENT_TYPE))
|
||||
{
|
||||
container->getHeader()->ContentType()->setValue
|
||||
(msg->getHeader()->ContentType()->getValue());
|
||||
if (msg->getHeader()->hasField(fields::CONTENT_TYPE)) {
|
||||
|
||||
container->getHeader()->ContentType()->setValue(
|
||||
msg->getHeader()->ContentType()->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING))
|
||||
{
|
||||
container->getHeader()->ContentTransferEncoding()->setValue
|
||||
(msg->getHeader()->ContentTransferEncoding()->getValue());
|
||||
if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING)) {
|
||||
|
||||
container->getHeader()->ContentTransferEncoding()->setValue(
|
||||
msg->getHeader()->ContentTransferEncoding()->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
for (unsigned int i = 0 ; i < partList.size() ; ++i)
|
||||
for (unsigned int i = 0 ; i < partList.size() ; ++i) {
|
||||
container->getBody()->appendPart(partList[i]);
|
||||
}
|
||||
|
||||
msg->getBody()->appendPart(container);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// The message is a simple (RFC-822) message, and do not
|
||||
// contains any MIME part. Move the contents from the
|
||||
// root to a new child part.
|
||||
shared_ptr <bodyPart> child = make_shared <bodyPart>();
|
||||
|
||||
if (msg->getHeader()->hasField(fields::CONTENT_TYPE))
|
||||
{
|
||||
child->getHeader()->ContentType()->setValue
|
||||
(msg->getHeader()->ContentType()->getValue());
|
||||
if (msg->getHeader()->hasField(fields::CONTENT_TYPE)) {
|
||||
|
||||
child->getHeader()->ContentType()->setValue(
|
||||
msg->getHeader()->ContentType()->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING))
|
||||
{
|
||||
child->getHeader()->ContentTransferEncoding()->setValue
|
||||
(msg->getHeader()->ContentTransferEncoding()->getValue());
|
||||
if (msg->getHeader()->hasField(fields::CONTENT_TRANSFER_ENCODING)) {
|
||||
|
||||
child->getHeader()->ContentTransferEncoding()->setValue(
|
||||
msg->getHeader()->ContentTransferEncoding()->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
child->getBody()->setContents(msg->getBody()->getContents());
|
||||
@ -278,35 +303,37 @@ void attachmentHelper::addAttachment(shared_ptr <message> msg, shared_ptr <attac
|
||||
|
||||
|
||||
// static
|
||||
shared_ptr <bodyPart> attachmentHelper::findBodyPart
|
||||
(shared_ptr <bodyPart> part, const mediaType& type)
|
||||
{
|
||||
if (part->getBody()->getContentType() == type)
|
||||
shared_ptr <bodyPart> attachmentHelper::findBodyPart(
|
||||
const shared_ptr <bodyPart>& part,
|
||||
const mediaType& type
|
||||
) {
|
||||
|
||||
if (part->getBody()->getContentType() == type) {
|
||||
return part;
|
||||
}
|
||||
|
||||
// Try in sub-parts
|
||||
shared_ptr <body> bdy = part->getBody();
|
||||
|
||||
for (size_t i = 0 ; i < bdy->getPartCount() ; ++i)
|
||||
{
|
||||
shared_ptr <bodyPart> found =
|
||||
findBodyPart(bdy->getPartAt(i), type);
|
||||
for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) {
|
||||
|
||||
if (found != NULL)
|
||||
shared_ptr <bodyPart> found = findBodyPart(bdy->getPartAt(i), type);
|
||||
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
addAttachment(msg, att);
|
||||
}
|
||||
|
||||
|
||||
} // vmime
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -31,14 +31,13 @@
|
||||
#include "vmime/message.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** Retrieve attachment information from message parts.
|
||||
*/
|
||||
class VMIME_EXPORT attachmentHelper
|
||||
{
|
||||
class VMIME_EXPORT attachmentHelper {
|
||||
|
||||
public:
|
||||
|
||||
/** Options for use with the following functions:
|
||||
@ -46,8 +45,7 @@ public:
|
||||
* getBodyPartAttachment,
|
||||
* and isBodyPartAnAttachment.
|
||||
*/
|
||||
enum FindOptions
|
||||
{
|
||||
enum FindOptions {
|
||||
INLINE_OBJECTS = (1 << 0) /**< Recognize and return inline objects. The aim is to
|
||||
consider MHTML objects (parts with a "Content-Id" or
|
||||
a "Content-Location", such as inline images) as attachments. */
|
||||
@ -59,7 +57,10 @@ public:
|
||||
* @param options search options (see FindOptions)
|
||||
* @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.
|
||||
* If the specified body part does not contain attachment
|
||||
@ -69,8 +70,10 @@ public:
|
||||
* @param options search options (see FindOptions)
|
||||
* @return attachment found in the part, or NULL
|
||||
*/
|
||||
static shared_ptr <const attachment>
|
||||
getBodyPartAttachment(shared_ptr <const bodyPart> part, const unsigned int options = 0);
|
||||
static shared_ptr <const attachment> getBodyPartAttachment(
|
||||
const shared_ptr <const bodyPart>& part,
|
||||
const unsigned int options = 0
|
||||
);
|
||||
|
||||
/** Find all attachments contained in the specified part
|
||||
* and all its children parts.
|
||||
@ -81,7 +84,10 @@ public:
|
||||
* @return a list of attachments found
|
||||
*/
|
||||
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.
|
||||
* This is simply a recursive call to getBodyPartAttachment().
|
||||
@ -91,26 +97,37 @@ public:
|
||||
* @return a list of attachments found
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param msg message into which to add the attachment
|
||||
* @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.
|
||||
*
|
||||
* @param msg message into which to add the attachment
|
||||
* @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:
|
||||
|
||||
static shared_ptr <bodyPart> findBodyPart
|
||||
(shared_ptr <bodyPart> part, const mediaType& type);
|
||||
static shared_ptr <bodyPart> findBodyPart(
|
||||
const shared_ptr <bodyPart>& part,
|
||||
const mediaType& type
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -118,4 +135,3 @@ protected:
|
||||
|
||||
|
||||
#endif // VMIME_ATTACHMENTHELPER_HPP_INCLUDED
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -48,8 +48,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** "Null" (empty) string.
|
||||
@ -108,8 +107,8 @@ nullPtrType null;
|
||||
|
||||
|
||||
// Line length limits
|
||||
namespace lineLengthLimits
|
||||
{
|
||||
namespace lineLengthLimits {
|
||||
|
||||
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).
|
||||
//
|
||||
|
||||
class initializer
|
||||
{
|
||||
public:
|
||||
struct initializer {
|
||||
|
||||
initializer() {
|
||||
|
||||
initializer()
|
||||
{
|
||||
parsingContext::getDefaultContext();
|
||||
generationContext::getDefaultContext();
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -37,8 +37,8 @@
|
||||
#include "vmime/constants.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
class text;
|
||||
class word;
|
||||
class charset;
|
||||
@ -53,8 +53,8 @@ namespace vmime
|
||||
#ifndef VMIME_BUILDING_DOC
|
||||
|
||||
// Null pointer
|
||||
struct nullPtrType
|
||||
{
|
||||
struct nullPtrType {
|
||||
|
||||
template <typename T>
|
||||
operator shared_ptr <T>() { return shared_ptr <T>(); }
|
||||
};
|
||||
@ -78,48 +78,49 @@ namespace vmime
|
||||
//
|
||||
|
||||
template <typename T, size_t N>
|
||||
inline T const* cbegin(T const (&array)[N])
|
||||
{
|
||||
return (array);
|
||||
inline T const* cbegin(T const (&array)[N]) {
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
template <typename T, size_t N>
|
||||
inline T const* cend(T const (&array)[N])
|
||||
{
|
||||
return (array + N);
|
||||
inline T const* cend(T const (&array)[N]) {
|
||||
|
||||
return array + N;
|
||||
}
|
||||
|
||||
template <typename T, size_t N>
|
||||
inline T* begin(T (&array)[N])
|
||||
{
|
||||
return (array);
|
||||
inline T* begin(T (&array)[N]) {
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
template <typename T, size_t N>
|
||||
inline T* end(T (&array)[N])
|
||||
{
|
||||
return (array + N);
|
||||
inline T* end(T (&array)[N]) {
|
||||
|
||||
return array + N;
|
||||
}
|
||||
|
||||
template <typename T, size_t N>
|
||||
inline size_t count(T const (&/* array */)[N])
|
||||
{
|
||||
return (N);
|
||||
inline size_t count(T const (&/* array */)[N]) {
|
||||
|
||||
return N;
|
||||
}
|
||||
|
||||
|
||||
// Copy one vector to another, with type conversion
|
||||
|
||||
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();
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@ -154,12 +155,11 @@ namespace vmime
|
||||
character limit) for the sake of robustness.
|
||||
*/
|
||||
|
||||
namespace lineLengthLimits
|
||||
{
|
||||
namespace lineLengthLimits {
|
||||
|
||||
extern VMIME_EXPORT const size_t infinite;
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
max = 998,
|
||||
convenient = 78
|
||||
};
|
||||
@ -192,8 +192,8 @@ namespace vmime
|
||||
* This is an alias for dynamic_pointer_cast <T>(obj->clone()).
|
||||
*/
|
||||
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());
|
||||
}
|
||||
|
||||
@ -201,8 +201,8 @@ namespace vmime
|
||||
* This is an alias for dynamic_pointer_cast <T>(obj->clone()).
|
||||
*/
|
||||
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());
|
||||
}
|
||||
|
||||
@ -210,8 +210,8 @@ namespace vmime
|
||||
* This is an alias for dynamic_pointer_cast <T>(obj.clone()).
|
||||
*/
|
||||
template <class T>
|
||||
shared_ptr <T> clone(const T& obj)
|
||||
{
|
||||
shared_ptr <T> clone(const T& obj) {
|
||||
|
||||
return dynamic_pointer_cast <T>(obj.clone());
|
||||
}
|
||||
|
||||
@ -220,24 +220,24 @@ namespace vmime
|
||||
* type Type, and DerivedType is derived from Type.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/** Const cast helper.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/** Inherit from this class to indicate the subclass is not copyable,
|
||||
* ie. you want to prohibit copy construction and copy assignment.
|
||||
*/
|
||||
class VMIME_EXPORT noncopyable
|
||||
{
|
||||
class VMIME_EXPORT noncopyable {
|
||||
|
||||
protected:
|
||||
|
||||
noncopyable() { }
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -37,8 +37,7 @@
|
||||
#include "vmime/contentHandler.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
class bodyPart;
|
||||
@ -46,9 +45,8 @@ class bodyPart;
|
||||
|
||||
/** Body section of a MIME part.
|
||||
*/
|
||||
class VMIME_EXPORT body : public component {
|
||||
|
||||
class VMIME_EXPORT body : public component
|
||||
{
|
||||
friend class bodyPart;
|
||||
|
||||
public:
|
||||
@ -60,7 +58,7 @@ public:
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
@ -68,7 +66,10 @@ public:
|
||||
* @param part part to insert
|
||||
* @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.
|
||||
*
|
||||
@ -76,7 +77,7 @@ public:
|
||||
* the beginning of the list)
|
||||
* @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.
|
||||
*
|
||||
@ -84,21 +85,24 @@ public:
|
||||
* @param part part to insert
|
||||
* @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.
|
||||
*
|
||||
* @param pos position of the part before the new part
|
||||
* @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.
|
||||
*
|
||||
* @param part part to remove
|
||||
* @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.
|
||||
*
|
||||
@ -182,14 +186,17 @@ public:
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param contents new body 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.
|
||||
*
|
||||
@ -197,7 +204,11 @@ public:
|
||||
* @param type type 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.
|
||||
*
|
||||
@ -206,8 +217,12 @@ public:
|
||||
* @param chset charset of contents
|
||||
* @param enc contents encoding
|
||||
*/
|
||||
void setContents(shared_ptr <const contentHandler> contents, const mediaType& type,
|
||||
const charset& chset, const encoding& enc);
|
||||
void setContents(
|
||||
const shared_ptr <const contentHandler>& contents,
|
||||
const mediaType& type,
|
||||
const charset& chset,
|
||||
const encoding& enc
|
||||
);
|
||||
|
||||
/** Set the MIME type and charset of contents.
|
||||
* If a charset is defined, it will not be modified.
|
||||
@ -301,7 +316,7 @@ private:
|
||||
|
||||
bool isRootPart() const;
|
||||
|
||||
void initNewPart(shared_ptr <bodyPart> part);
|
||||
void initNewPart(const shared_ptr <bodyPart>& part);
|
||||
|
||||
protected:
|
||||
|
||||
@ -317,24 +332,30 @@ protected:
|
||||
* before the CRLF or "--" which follows)
|
||||
* @return the position of the boundary string, or npos if not found
|
||||
*/
|
||||
size_t findNextBoundaryPosition
|
||||
(shared_ptr <utility::parserInputStreamAdapter> parser, const string& boundary,
|
||||
const size_t position, const size_t end,
|
||||
size_t* boundaryStart, size_t* boundaryEnd);
|
||||
|
||||
// Component parsing & assembling
|
||||
void parseImpl
|
||||
(const parsingContext& ctx,
|
||||
shared_ptr <utility::parserInputStreamAdapter> parser,
|
||||
size_t findNextBoundaryPosition(
|
||||
const shared_ptr <utility::parserInputStreamAdapter>& parser,
|
||||
const string& boundary,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
size_t* boundaryStart,
|
||||
size_t* boundaryEnd
|
||||
);
|
||||
|
||||
void generateImpl
|
||||
(const generationContext& ctx,
|
||||
// Component parsing & assembling
|
||||
void parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const shared_ptr <utility::parserInputStreamAdapter>& parser,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
size_t* newLinePos = NULL) const;
|
||||
size_t* newLinePos = NULL
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -24,23 +24,26 @@
|
||||
#include "vmime/bodyPart.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
bodyPart::bodyPart()
|
||||
: m_header(make_shared <header>()),
|
||||
m_body(make_shared <body>()),
|
||||
m_parent()
|
||||
{
|
||||
m_parent() {
|
||||
|
||||
m_body->setParentPart(this);
|
||||
}
|
||||
|
||||
|
||||
void bodyPart::parseImpl
|
||||
(const parsingContext& ctx, shared_ptr <utility::parserInputStreamAdapter> parser,
|
||||
const size_t position, const size_t end, size_t* newPosition)
|
||||
{
|
||||
void bodyPart::parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const shared_ptr <utility::parserInputStreamAdapter>& parser,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition
|
||||
) {
|
||||
|
||||
// Parse the headers
|
||||
size_t pos = position;
|
||||
m_header->parse(ctx, parser, pos, end, &pos);
|
||||
@ -50,34 +53,39 @@ void bodyPart::parseImpl
|
||||
|
||||
setParsedBounds(position, end);
|
||||
|
||||
if (newPosition)
|
||||
if (newPosition) {
|
||||
*newPosition = end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void bodyPart::generateImpl
|
||||
(const generationContext& ctx, utility::outputStream& os,
|
||||
const size_t /* curLinePos */, size_t* newLinePos) const
|
||||
{
|
||||
void bodyPart::generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t /* curLinePos */,
|
||||
size_t* newLinePos
|
||||
) const {
|
||||
|
||||
m_header->generate(ctx, os);
|
||||
|
||||
os << CRLF;
|
||||
|
||||
m_body->generate(ctx, os);
|
||||
|
||||
if (newLinePos)
|
||||
if (newLinePos) {
|
||||
*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);
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <component> bodyPart::clone() const
|
||||
{
|
||||
shared_ptr <component> bodyPart::clone() const {
|
||||
|
||||
shared_ptr <bodyPart> p = make_shared <bodyPart>();
|
||||
|
||||
p->m_parent = NULL;
|
||||
@ -85,12 +93,12 @@ shared_ptr <component> bodyPart::clone() const
|
||||
p->m_header->copyFrom(*m_header);
|
||||
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);
|
||||
|
||||
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);
|
||||
return (*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
const shared_ptr <const header> bodyPart::getHeader() const
|
||||
{
|
||||
return (m_header);
|
||||
const shared_ptr <const header> bodyPart::getHeader() const {
|
||||
|
||||
return m_header;
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <header> bodyPart::getHeader()
|
||||
{
|
||||
return (m_header);
|
||||
shared_ptr <header> bodyPart::getHeader() {
|
||||
|
||||
return m_header;
|
||||
}
|
||||
|
||||
|
||||
void bodyPart::setHeader(shared_ptr <header> h)
|
||||
{
|
||||
void bodyPart::setHeader(const shared_ptr <header>& h) {
|
||||
|
||||
m_header = h;
|
||||
}
|
||||
|
||||
|
||||
const shared_ptr <const body> bodyPart::getBody() const
|
||||
{
|
||||
return (m_body);
|
||||
const shared_ptr <const body> bodyPart::getBody() const {
|
||||
|
||||
return m_body;
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <body> bodyPart::getBody()
|
||||
{
|
||||
return (m_body);
|
||||
shared_ptr <body> bodyPart::getBody() {
|
||||
|
||||
return m_body;
|
||||
}
|
||||
|
||||
|
||||
void bodyPart::setBody(shared_ptr <body> b)
|
||||
{
|
||||
void bodyPart::setBody(const shared_ptr <body>& b) {
|
||||
|
||||
bodyPart* oldPart = b->m_part;
|
||||
|
||||
m_body = b;
|
||||
m_body->setParentPart(this);
|
||||
|
||||
// A body is associated to one and only one part
|
||||
if (oldPart != NULL)
|
||||
if (oldPart) {
|
||||
oldPart->setBody(make_shared <body>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bodyPart* bodyPart::getParentPart()
|
||||
{
|
||||
bodyPart* bodyPart::getParentPart() {
|
||||
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
|
||||
const bodyPart* bodyPart::getParentPart() const
|
||||
{
|
||||
const bodyPart* bodyPart::getParentPart() const {
|
||||
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <bodyPart> bodyPart::createChildPart()
|
||||
{
|
||||
shared_ptr <bodyPart> bodyPart::createChildPart() {
|
||||
|
||||
shared_ptr <bodyPart> part = make_shared <bodyPart>();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
const std::vector <shared_ptr <component> > bodyPart::getChildComponents()
|
||||
{
|
||||
const std::vector <shared_ptr <component> > bodyPart::getChildComponents() {
|
||||
|
||||
std::vector <shared_ptr <component> > list;
|
||||
|
||||
list.push_back(m_header);
|
||||
list.push_back(m_body);
|
||||
|
||||
return (list);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
} // vmime
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -32,15 +32,13 @@
|
||||
#include "vmime/body.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** A MIME part.
|
||||
*/
|
||||
class VMIME_EXPORT bodyPart : public component {
|
||||
|
||||
class VMIME_EXPORT bodyPart : public component
|
||||
{
|
||||
friend class body;
|
||||
|
||||
public:
|
||||
@ -63,7 +61,7 @@ public:
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
@ -81,7 +79,7 @@ public:
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
@ -131,21 +129,23 @@ protected:
|
||||
*
|
||||
* @param part child part to attach
|
||||
*/
|
||||
void importChildPart(shared_ptr <bodyPart> part);
|
||||
void importChildPart(const shared_ptr <bodyPart>& part);
|
||||
|
||||
// Component parsing & assembling
|
||||
void parseImpl
|
||||
(const parsingContext& ctx,
|
||||
shared_ptr <utility::parserInputStreamAdapter> parser,
|
||||
void parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const shared_ptr <utility::parserInputStreamAdapter>& parser,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
void generateImpl
|
||||
(const generationContext& ctx,
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
size_t* newLinePos = NULL) const;
|
||||
size_t* newLinePos = NULL
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -24,75 +24,77 @@
|
||||
#include "vmime/bodyPartAttachment.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
bodyPartAttachment::bodyPartAttachment(shared_ptr <const bodyPart> part)
|
||||
: m_part(part)
|
||||
{
|
||||
bodyPartAttachment::bodyPartAttachment(const shared_ptr <const bodyPart>& part)
|
||||
: m_part(part) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
const mediaType bodyPartAttachment::getType() const
|
||||
{
|
||||
const mediaType bodyPartAttachment::getType() const {
|
||||
|
||||
shared_ptr <const contentTypeField> ctf = getContentType();
|
||||
|
||||
if (ctf)
|
||||
{
|
||||
if (ctf) {
|
||||
|
||||
return *ctf->getValue <mediaType>();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// No "Content-type" field: assume "application/octet-stream".
|
||||
return mediaType(mediaTypes::APPLICATION,
|
||||
mediaTypes::APPLICATION_OCTET_STREAM);
|
||||
return mediaType(
|
||||
mediaTypes::APPLICATION,
|
||||
mediaTypes::APPLICATION_OCTET_STREAM
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const word bodyPartAttachment::getName() const
|
||||
{
|
||||
const word bodyPartAttachment::getName() const {
|
||||
|
||||
word name;
|
||||
|
||||
// Try the 'filename' parameter of 'Content-Disposition' field
|
||||
shared_ptr <const contentDispositionField> cdf = getContentDisposition();
|
||||
|
||||
if (cdf && cdf->hasFilename())
|
||||
{
|
||||
if (cdf && cdf->hasFilename()) {
|
||||
|
||||
name = cdf->getFilename();
|
||||
}
|
||||
|
||||
// Try the 'name' parameter of 'Content-Type' field
|
||||
else
|
||||
{
|
||||
} else {
|
||||
|
||||
shared_ptr <const contentTypeField> ctf = getContentType();
|
||||
|
||||
if (ctf)
|
||||
{
|
||||
if (ctf) {
|
||||
|
||||
shared_ptr <const parameter> prm = ctf->findParameter("name");
|
||||
|
||||
if (prm != NULL)
|
||||
if (prm) {
|
||||
name = prm->getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
const text bodyPartAttachment::getDescription() const
|
||||
{
|
||||
const text bodyPartAttachment::getDescription() const {
|
||||
|
||||
text description;
|
||||
|
||||
shared_ptr <const headerField> cd =
|
||||
getHeader()->findField(fields::CONTENT_DESCRIPTION);
|
||||
|
||||
if (cd)
|
||||
{
|
||||
if (cd) {
|
||||
|
||||
description = *cd->getValue <text>();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
||||
const shared_ptr <const contentHandler> bodyPartAttachment::getData() const
|
||||
{
|
||||
const shared_ptr <const contentHandler> bodyPartAttachment::getData() const {
|
||||
|
||||
return m_part->getBody()->getContents();
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <const object> bodyPartAttachment::getPart() const
|
||||
{
|
||||
shared_ptr <const object> bodyPartAttachment::getPart() const {
|
||||
|
||||
return m_part;
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <const header> bodyPartAttachment::getHeader() const
|
||||
{
|
||||
shared_ptr <const header> bodyPartAttachment::getHeader() const {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <const contentTypeField> bodyPartAttachment::getContentType() const
|
||||
{
|
||||
shared_ptr <const contentTypeField> bodyPartAttachment::getContentType() const {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
} // vmime
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -34,17 +34,16 @@
|
||||
#include "vmime/contentTypeField.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** An attachment related to a local body part.
|
||||
*/
|
||||
class VMIME_EXPORT bodyPartAttachment : public attachment
|
||||
{
|
||||
class VMIME_EXPORT bodyPartAttachment : public attachment {
|
||||
|
||||
public:
|
||||
|
||||
bodyPartAttachment(shared_ptr <const bodyPart> part);
|
||||
bodyPartAttachment(const shared_ptr <const bodyPart>& part);
|
||||
|
||||
const mediaType getType() const;
|
||||
const word getName() const;
|
||||
@ -58,7 +57,7 @@ public:
|
||||
|
||||
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 contentTypeField> getContentType() const;
|
||||
@ -75,4 +74,3 @@ private:
|
||||
|
||||
|
||||
#endif // VMIME_BODYPARTATTACHMENT_HPP_INCLUDED
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -32,74 +32,93 @@
|
||||
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
charset::charset()
|
||||
: m_name(charsets::US_ASCII)
|
||||
{
|
||||
: m_name(charsets::US_ASCII) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
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 (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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
charset::charset(const char* name)
|
||||
: m_name(name)
|
||||
{
|
||||
: m_name(name) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void charset::parseImpl
|
||||
(const parsingContext& /* ctx */, const string& buffer, const size_t position,
|
||||
const size_t end, size_t* newPosition)
|
||||
{
|
||||
m_name = utility::stringUtils::trim
|
||||
(string(buffer.begin() + position, buffer.begin() + end));
|
||||
void charset::parseImpl(
|
||||
const parsingContext& /* ctx */,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t 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 (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";
|
||||
}
|
||||
|
||||
setParsedBounds(position, end);
|
||||
|
||||
if (newPosition)
|
||||
if (newPosition) {
|
||||
*newPosition = end;
|
||||
}
|
||||
|
||||
|
||||
void charset::generateImpl
|
||||
(const generationContext& /* ctx */, utility::outputStream& os,
|
||||
const size_t curLinePos, size_t* newLinePos) const
|
||||
{
|
||||
os << m_name;
|
||||
|
||||
if (newLinePos)
|
||||
*newLinePos = curLinePos + m_name.length();
|
||||
}
|
||||
|
||||
|
||||
void charset::convert(utility::inputStream& in, utility::outputStream& out,
|
||||
const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts)
|
||||
{
|
||||
void charset::generateImpl(
|
||||
const generationContext& /* ctx */,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos,
|
||||
size_t* newLinePos
|
||||
) const {
|
||||
|
||||
os << m_name;
|
||||
|
||||
if (newLinePos) {
|
||||
*newLinePos = curLinePos + m_name.length();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void charset::convert(
|
||||
utility::inputStream& in,
|
||||
utility::outputStream& out,
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts
|
||||
) {
|
||||
|
||||
shared_ptr <charsetConverter> conv = charsetConverter::create(source, dest, opts);
|
||||
conv->convert(in, out);
|
||||
}
|
||||
|
||||
|
||||
void charset::convert(const string& in, string& out, const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts)
|
||||
{
|
||||
if (source == dest)
|
||||
{
|
||||
void charset::convert(
|
||||
const string& in,
|
||||
string& out,
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts
|
||||
) {
|
||||
|
||||
if (source == dest) {
|
||||
out = in;
|
||||
return;
|
||||
}
|
||||
@ -109,27 +128,26 @@ void charset::convert(const string& in, string& out, const charset& source, cons
|
||||
}
|
||||
|
||||
|
||||
bool charset::isValidText
|
||||
(const string& text, string::size_type* firstInvalidByte) const
|
||||
{
|
||||
bool charset::isValidText(const string& text, string::size_type* firstInvalidByte) const {
|
||||
|
||||
charsetConverterOptions opts;
|
||||
opts.silentlyReplaceInvalidSequences = false;
|
||||
|
||||
charsetConverter::status st;
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
|
||||
std::string out;
|
||||
|
||||
// Try converting to UTF-8
|
||||
shared_ptr <charsetConverter> conv = charsetConverter::create(*this, vmime::charset("utf-8"), opts);
|
||||
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
|
||||
if (firstInvalidByte)
|
||||
{
|
||||
if (firstInvalidByte) {
|
||||
|
||||
if (st.inputBytesRead < text.length())
|
||||
*firstInvalidByte = st.inputBytesRead;
|
||||
else
|
||||
@ -139,77 +157,79 @@ bool charset::isValidText
|
||||
return false;
|
||||
}
|
||||
|
||||
if (firstInvalidByte)
|
||||
if (firstInvalidByte) {
|
||||
*firstInvalidByte = text.length();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const charset charset::getLocalCharset()
|
||||
{
|
||||
return (platform::getHandler()->getLocalCharset());
|
||||
const charset charset::getLocalCharset() {
|
||||
|
||||
return platform::getHandler()->getLocalCharset();
|
||||
}
|
||||
|
||||
|
||||
charset& charset::operator=(const charset& other)
|
||||
{
|
||||
charset& charset::operator=(const charset& other) {
|
||||
|
||||
copyFrom(other);
|
||||
return (*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool charset::operator==(const charset& value) const
|
||||
{
|
||||
return (utility::stringUtils::isStringEqualNoCase(m_name, value.m_name));
|
||||
bool charset::operator==(const charset& value) const {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <component> charset::clone() const
|
||||
{
|
||||
shared_ptr <component> charset::clone() const {
|
||||
|
||||
return make_shared <charset>(m_name);
|
||||
}
|
||||
|
||||
|
||||
const string& charset::getName() const
|
||||
{
|
||||
return (m_name);
|
||||
const string& charset::getName() const {
|
||||
|
||||
return m_name;
|
||||
}
|
||||
|
||||
|
||||
void charset::copyFrom(const component& other)
|
||||
{
|
||||
void charset::copyFrom(const component& other) {
|
||||
|
||||
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> >();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Explicitly force encoding for some charsets
|
||||
struct CharsetEncodingEntry
|
||||
{
|
||||
struct CharsetEncodingEntry {
|
||||
|
||||
CharsetEncodingEntry(const string& charset_, const string& encoding_)
|
||||
: charset(charset_), encoding(encoding_)
|
||||
{
|
||||
: charset(charset_), encoding(encoding_) {
|
||||
|
||||
}
|
||||
|
||||
const string charset;
|
||||
const string encoding;
|
||||
};
|
||||
|
||||
CharsetEncodingEntry g_charsetEncodingMap[] =
|
||||
{
|
||||
|
||||
CharsetEncodingEntry g_charsetEncodingMap[] = {
|
||||
|
||||
// Use QP encoding for ISO-8859-x charsets
|
||||
CharsetEncodingEntry("iso-8859", 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
|
||||
const string cset = utility::stringUtils::toLower(getName());
|
||||
|
||||
for (unsigned int i = 0 ; i < (sizeof(g_charsetEncodingMap) / sizeof(g_charsetEncodingMap[0])) - 1 ; ++i)
|
||||
{
|
||||
if (cset.find(g_charsetEncodingMap[i].charset) != string::npos)
|
||||
{
|
||||
for (unsigned int i = 0 ;
|
||||
i < (sizeof(g_charsetEncodingMap) / sizeof(g_charsetEncodingMap[0])) - 1 ;
|
||||
++i) {
|
||||
|
||||
if (cset.find(g_charsetEncodingMap[i].charset) != string::npos) {
|
||||
enc = g_charsetEncodingMap[i].encoding;
|
||||
return true;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -32,8 +32,7 @@
|
||||
#include "vmime/component.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
class encoding; // forward reference
|
||||
@ -41,9 +40,8 @@ class encoding; // forward reference
|
||||
|
||||
/** Charset description (basic type).
|
||||
*/
|
||||
class VMIME_EXPORT charset : public component {
|
||||
|
||||
class VMIME_EXPORT charset : public component
|
||||
{
|
||||
public:
|
||||
|
||||
charset();
|
||||
@ -102,9 +100,13 @@ public:
|
||||
* @throws exceptions::charset_conv_error if an unexpected error occurred
|
||||
* during the conversion
|
||||
*/
|
||||
static void convert(const string& in, string& out,
|
||||
const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions());
|
||||
static void convert(
|
||||
const string& in,
|
||||
string& out,
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
);
|
||||
|
||||
/** Convert the contents of an input stream in a specified charset
|
||||
* 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
|
||||
* during the conversion
|
||||
*/
|
||||
static void convert(utility::inputStream& in, utility::outputStream& out,
|
||||
const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions());
|
||||
static void convert(
|
||||
utility::inputStream& in,
|
||||
utility::outputStream& out,
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
);
|
||||
|
||||
/** Checks whether the specified text is valid in this charset.
|
||||
*
|
||||
@ -147,18 +153,20 @@ private:
|
||||
protected:
|
||||
|
||||
// Component parsing & assembling
|
||||
void parseImpl
|
||||
(const parsingContext& ctx,
|
||||
void parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
void generateImpl
|
||||
(const generationContext& ctx,
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
size_t* newLinePos = NULL) const;
|
||||
size_t* newLinePos = NULL
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -26,25 +26,26 @@
|
||||
#include "vmime/charsetConverter_idna.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
// static
|
||||
shared_ptr <charsetConverter> charsetConverter::create
|
||||
(const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts)
|
||||
{
|
||||
if (source == "idna" || dest == "idna")
|
||||
shared_ptr <charsetConverter> charsetConverter::create(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts
|
||||
) {
|
||||
|
||||
if (source == "idna" || dest == "idna") {
|
||||
return make_shared <charsetConverter_idna>(source, dest, opts);
|
||||
else
|
||||
} else {
|
||||
return createGenericConverter(source, dest, opts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
charsetConverter::status::status()
|
||||
: inputBytesRead(0), outputBytesWritten(0)
|
||||
{
|
||||
: inputBytesRead(0), outputBytesWritten(0) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -33,12 +33,10 @@
|
||||
#include "vmime/utility/filteredStream.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
namespace utility
|
||||
{
|
||||
namespace utility {
|
||||
|
||||
|
||||
/** A filtered output stream which applies a charset conversion
|
||||
@ -52,9 +50,8 @@ namespace utility
|
||||
* 'silentlyReplaceInvalidSequences' flag is set to false in
|
||||
* 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.
|
||||
*/
|
||||
class VMIME_EXPORT charsetConverter : public object {
|
||||
|
||||
class VMIME_EXPORT charsetConverter : public object
|
||||
{
|
||||
public:
|
||||
|
||||
/** Holds information about a conversion.
|
||||
*/
|
||||
struct status
|
||||
{
|
||||
struct status {
|
||||
|
||||
status();
|
||||
|
||||
|
||||
@ -91,9 +87,11 @@ public:
|
||||
* @param dest output charset
|
||||
* @param opts conversion options
|
||||
*/
|
||||
static shared_ptr <charsetConverter> create
|
||||
(const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions());
|
||||
static shared_ptr <charsetConverter> create(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
);
|
||||
|
||||
/** Convert a string buffer from one charset to another
|
||||
* charset (in-memory conversion)
|
||||
@ -128,7 +126,11 @@ public:
|
||||
* @throws exceptions::charset_conv_error if an unexpected error occurred
|
||||
* 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
|
||||
* conversion to input bytes. Please note that it may not be
|
||||
@ -138,15 +140,19 @@ public:
|
||||
* @param opts conversion options
|
||||
* @return a filtered output stream, or NULL if not supported
|
||||
*/
|
||||
virtual shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream
|
||||
(utility::outputStream& os,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()) = 0;
|
||||
virtual shared_ptr <utility::charsetFilteredOutputStream>
|
||||
getFilteredOutputStream(
|
||||
utility::outputStream& os,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
) = 0;
|
||||
|
||||
private:
|
||||
|
||||
static shared_ptr <charsetConverter> createGenericConverter
|
||||
(const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts);
|
||||
static shared_ptr <charsetConverter> createGenericConverter(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -24,14 +24,13 @@
|
||||
#include "vmime/charsetConverterOptions.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
charsetConverterOptions::charsetConverterOptions()
|
||||
: silentlyReplaceInvalidSequences(true),
|
||||
invalidSequence("?")
|
||||
{
|
||||
invalidSequence("?") {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -28,15 +28,13 @@
|
||||
#include "vmime/base.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** Options for charset conversion.
|
||||
*/
|
||||
class VMIME_EXPORT charsetConverterOptions : public object {
|
||||
|
||||
class VMIME_EXPORT charsetConverterOptions : public object
|
||||
{
|
||||
public:
|
||||
|
||||
charsetConverterOptions();
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -34,8 +34,8 @@
|
||||
#include "vmime/utility/outputStreamStringAdapter.hpp"
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern "C" {
|
||||
|
||||
#ifndef VMIME_BUILDING_DOC
|
||||
|
||||
#include <iconv.h>
|
||||
@ -45,8 +45,8 @@ extern "C"
|
||||
// second parameter may or may not be 'const'). This relies on the compiler
|
||||
// for choosing the right type.
|
||||
|
||||
class ICONV_IN_TYPE
|
||||
{
|
||||
class ICONV_IN_TYPE {
|
||||
|
||||
public:
|
||||
|
||||
ICONV_IN_TYPE(const char** ptr) : m_ptr(ptr) { }
|
||||
@ -62,8 +62,8 @@ extern "C"
|
||||
const char** m_ptr;
|
||||
};
|
||||
|
||||
class ICONV_OUT_TYPE
|
||||
{
|
||||
class ICONV_OUT_TYPE {
|
||||
|
||||
public:
|
||||
|
||||
ICONV_OUT_TYPE(char** ptr) : m_ptr(ptr) { }
|
||||
@ -85,9 +85,12 @@ extern "C"
|
||||
|
||||
// Output replacement char when an invalid sequence is encountered
|
||||
template <typename OUTPUT_CLASS, typename ICONV_DESC>
|
||||
void outputInvalidChar(OUTPUT_CLASS& out, ICONV_DESC cd,
|
||||
const vmime::charsetConverterOptions& opts = vmime::charsetConverterOptions())
|
||||
{
|
||||
void outputInvalidChar(
|
||||
OUTPUT_CLASS& out,
|
||||
ICONV_DESC cd,
|
||||
const vmime::charsetConverterOptions& opts = vmime::charsetConverterOptions()
|
||||
) {
|
||||
|
||||
const char* invalidCharIn = opts.invalidSequence.c_str();
|
||||
vmime::size_t invalidCharInLen = opts.invalidSequence.length();
|
||||
|
||||
@ -96,36 +99,43 @@ void outputInvalidChar(OUTPUT_CLASS& out, ICONV_DESC cd,
|
||||
vmime::size_t invalidCharOutLen = 16;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
// static
|
||||
shared_ptr <charsetConverter> charsetConverter::createGenericConverter
|
||||
(const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts)
|
||||
{
|
||||
shared_ptr <charsetConverter> charsetConverter::createGenericConverter(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts
|
||||
) {
|
||||
|
||||
return make_shared <charsetConverter_iconv>(source, dest, opts);
|
||||
}
|
||||
|
||||
|
||||
charsetConverter_iconv::charsetConverter_iconv
|
||||
(const charset& source, const charset& dest, const charsetConverterOptions& opts)
|
||||
: m_desc(NULL), m_source(source), m_dest(dest), m_options(opts)
|
||||
{
|
||||
charsetConverter_iconv::charsetConverter_iconv(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts
|
||||
)
|
||||
: m_desc(NULL),
|
||||
m_source(source),
|
||||
m_dest(dest),
|
||||
m_options(opts) {
|
||||
|
||||
// Get an iconv descriptor
|
||||
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;
|
||||
*p= cd;
|
||||
|
||||
@ -134,10 +144,10 @@ charsetConverter_iconv::charsetConverter_iconv
|
||||
}
|
||||
|
||||
|
||||
charsetConverter_iconv::~charsetConverter_iconv()
|
||||
{
|
||||
if (m_desc != NULL)
|
||||
{
|
||||
charsetConverter_iconv::~charsetConverter_iconv() {
|
||||
|
||||
if (m_desc) {
|
||||
|
||||
// Close iconv handle
|
||||
iconv_close(*static_cast <iconv_t*>(m_desc));
|
||||
|
||||
@ -147,14 +157,19 @@ charsetConverter_iconv::~charsetConverter_iconv()
|
||||
}
|
||||
|
||||
|
||||
void charsetConverter_iconv::convert
|
||||
(utility::inputStream& in, utility::outputStream& out, status* st)
|
||||
{
|
||||
if (st)
|
||||
new (st) status();
|
||||
void charsetConverter_iconv::convert(
|
||||
utility::inputStream& in,
|
||||
utility::outputStream& out,
|
||||
status* st
|
||||
) {
|
||||
|
||||
if (m_desc == NULL)
|
||||
if (st) {
|
||||
new (st) status();
|
||||
}
|
||||
|
||||
if (!m_desc) {
|
||||
throw exceptions::charset_conv_error("Cannot initialize converter.");
|
||||
}
|
||||
|
||||
const iconv_t cd = *static_cast <iconv_t*>(m_desc);
|
||||
|
||||
@ -165,8 +180,8 @@ void charsetConverter_iconv::convert
|
||||
bool prevIsInvalid = false;
|
||||
bool breakAfterNext = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
while (true) {
|
||||
|
||||
// Fullfill the buffer
|
||||
size_t inLength = static_cast <size_t>(in.read(inBuffer + inPos, sizeof(inBuffer) - inPos) + inPos);
|
||||
size_t outLength = sizeof(outBuffer);
|
||||
@ -177,23 +192,23 @@ void charsetConverter_iconv::convert
|
||||
|
||||
// Convert input bytes
|
||||
if (iconv(cd, ICONV_IN_TYPE(&inPtr), ptrLength,
|
||||
ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast <size_t>(-1))
|
||||
{
|
||||
if (st && inPtr)
|
||||
{
|
||||
ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast <size_t>(-1)) {
|
||||
|
||||
if (st && inPtr) {
|
||||
st->inputBytesRead += (inPtr - inBuffer);
|
||||
st->outputBytesWritten += (outPtr - outBuffer);
|
||||
}
|
||||
|
||||
// Illegal input sequence or input sequence has no equivalent
|
||||
// sequence in the destination charset.
|
||||
if (prevIsInvalid)
|
||||
{
|
||||
if (prevIsInvalid) {
|
||||
|
||||
// Write successfully converted bytes
|
||||
out.write(outBuffer, sizeof(outBuffer) - outLength);
|
||||
|
||||
if (!m_options.silentlyReplaceInvalidSequences)
|
||||
if (!m_options.silentlyReplaceInvalidSequences) {
|
||||
throw exceptions::illegal_byte_sequence_for_charset();
|
||||
}
|
||||
|
||||
// Output a special character to indicate we don't known how to
|
||||
// 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
|
||||
std::copy(const_cast <byte_t*>(inPtr + 1), inBuffer + sizeof(inBuffer), inBuffer);
|
||||
inPos = inLength - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// Write successfully converted bytes
|
||||
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);
|
||||
inPos = inLength;
|
||||
|
||||
if (errno != E2BIG)
|
||||
if (errno != E2BIG) {
|
||||
prevIsInvalid = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// Write successfully converted bytes
|
||||
out.write(outBuffer, sizeof(outBuffer) - outLength);
|
||||
|
||||
if (st && inPtr)
|
||||
{
|
||||
if (st && inPtr) {
|
||||
st->inputBytesRead += (inPtr - inBuffer);
|
||||
st->outputBytesWritten += (outPtr - outBuffer);
|
||||
}
|
||||
@ -231,20 +246,23 @@ void charsetConverter_iconv::convert
|
||||
prevIsInvalid = false;
|
||||
}
|
||||
|
||||
if (breakAfterNext)
|
||||
if (breakAfterNext) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void charsetConverter_iconv::convert(const string& in, string& out, status* st)
|
||||
{
|
||||
if (st)
|
||||
void charsetConverter_iconv::convert(const string& in, string& out, status* st) {
|
||||
|
||||
if (st) {
|
||||
new (st) status();
|
||||
}
|
||||
|
||||
out.clear();
|
||||
|
||||
@ -258,9 +276,11 @@ void charsetConverter_iconv::convert(const string& in, string& out, status* st)
|
||||
|
||||
|
||||
shared_ptr <utility::charsetFilteredOutputStream>
|
||||
charsetConverter_iconv::getFilteredOutputStream
|
||||
(utility::outputStream& os, const charsetConverterOptions& opts)
|
||||
{
|
||||
charsetConverter_iconv::getFilteredOutputStream(
|
||||
utility::outputStream& os,
|
||||
const charsetConverterOptions& opts
|
||||
) {
|
||||
|
||||
return make_shared <utility::charsetFilteredOutputStream_iconv>(m_source, m_dest, &os, opts);
|
||||
}
|
||||
|
||||
@ -271,17 +291,23 @@ shared_ptr <utility::charsetFilteredOutputStream>
|
||||
namespace utility {
|
||||
|
||||
|
||||
charsetFilteredOutputStream_iconv::charsetFilteredOutputStream_iconv
|
||||
(const charset& source, const charset& dest, outputStream* os,
|
||||
const charsetConverterOptions& opts)
|
||||
: m_desc(NULL), m_sourceCharset(source), m_destCharset(dest),
|
||||
m_stream(*os), m_unconvCount(0), m_options(opts)
|
||||
{
|
||||
charsetFilteredOutputStream_iconv::charsetFilteredOutputStream_iconv(
|
||||
const charset& source,
|
||||
const charset& dest, outputStream* os,
|
||||
const charsetConverterOptions& opts
|
||||
)
|
||||
: m_desc(NULL),
|
||||
m_sourceCharset(source),
|
||||
m_destCharset(dest),
|
||||
m_stream(*os),
|
||||
m_unconvCount(0),
|
||||
m_options(opts) {
|
||||
|
||||
// Get an iconv descriptor
|
||||
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;
|
||||
*p= cd;
|
||||
|
||||
@ -290,10 +316,10 @@ charsetFilteredOutputStream_iconv::charsetFilteredOutputStream_iconv
|
||||
}
|
||||
|
||||
|
||||
charsetFilteredOutputStream_iconv::~charsetFilteredOutputStream_iconv()
|
||||
{
|
||||
if (m_desc != NULL)
|
||||
{
|
||||
charsetFilteredOutputStream_iconv::~charsetFilteredOutputStream_iconv() {
|
||||
|
||||
if (m_desc) {
|
||||
|
||||
// Close iconv handle
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void charsetFilteredOutputStream_iconv::writeImpl
|
||||
(const byte_t* const data, const size_t count)
|
||||
{
|
||||
if (m_desc == NULL)
|
||||
void charsetFilteredOutputStream_iconv::writeImpl(
|
||||
const byte_t* const data,
|
||||
const size_t count
|
||||
) {
|
||||
|
||||
if (!m_desc) {
|
||||
throw exceptions::charset_conv_error("Cannot initialize converter.");
|
||||
}
|
||||
|
||||
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
|
||||
// chunk to see if it can now be converted.
|
||||
while (m_unconvCount != 0 || curDataLen != 0)
|
||||
{
|
||||
if (m_unconvCount != 0)
|
||||
{
|
||||
while (m_unconvCount != 0 || curDataLen != 0) {
|
||||
|
||||
if (m_unconvCount != 0) {
|
||||
|
||||
// Check if an incomplete input sequence is larger than the
|
||||
// input buffer size: should not happen except if something
|
||||
// in the input sequence is invalid. If so, output a special
|
||||
// character and skip one byte in the invalid sequence.
|
||||
if (m_unconvCount >= sizeof(m_unconvBuffer))
|
||||
{
|
||||
if (!m_options.silentlyReplaceInvalidSequences)
|
||||
if (m_unconvCount >= sizeof(m_unconvBuffer)) {
|
||||
|
||||
if (!m_options.silentlyReplaceInvalidSequences) {
|
||||
throw exceptions::illegal_byte_sequence_for_charset();
|
||||
}
|
||||
|
||||
outputInvalidChar(m_stream, cd);
|
||||
|
||||
std::copy(m_unconvBuffer + 1,
|
||||
m_unconvBuffer + m_unconvCount, m_unconvBuffer);
|
||||
std::copy(
|
||||
m_unconvBuffer + 1,
|
||||
m_unconvBuffer + m_unconvCount, m_unconvBuffer
|
||||
);
|
||||
|
||||
m_unconvCount--;
|
||||
}
|
||||
@ -365,16 +397,18 @@ void charsetFilteredOutputStream_iconv::writeImpl
|
||||
const size_t inLength0 = 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;
|
||||
|
||||
// Write successfully converted bytes
|
||||
m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
|
||||
|
||||
// Shift unconverted bytes
|
||||
std::copy(m_unconvBuffer + inputConverted,
|
||||
m_unconvBuffer + m_unconvCount, m_unconvBuffer);
|
||||
std::copy(
|
||||
m_unconvBuffer + inputConverted,
|
||||
m_unconvBuffer + m_unconvCount, m_unconvBuffer
|
||||
);
|
||||
|
||||
m_unconvCount -= inputConverted;
|
||||
|
||||
@ -388,8 +422,9 @@ void charsetFilteredOutputStream_iconv::writeImpl
|
||||
m_unconvCount = 0;
|
||||
}
|
||||
|
||||
if (curDataLen == 0)
|
||||
if (curDataLen == 0) {
|
||||
return; // no more data
|
||||
}
|
||||
|
||||
// Now, convert the current data buffer
|
||||
const byte_t* inPtr = curData;
|
||||
@ -400,8 +435,8 @@ void charsetFilteredOutputStream_iconv::writeImpl
|
||||
const size_t inLength0 = 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
|
||||
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
|
||||
// that the next iteration fill it
|
||||
if (curDataLen != 0)
|
||||
{
|
||||
if (curDataLen != 0) {
|
||||
|
||||
m_unconvCount = 1;
|
||||
m_unconvBuffer[0] = *curData;
|
||||
|
||||
curData++;
|
||||
curDataLen--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// Write successfully converted bytes
|
||||
m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
|
||||
|
||||
@ -433,18 +468,19 @@ void charsetFilteredOutputStream_iconv::writeImpl
|
||||
}
|
||||
|
||||
|
||||
void charsetFilteredOutputStream_iconv::flush()
|
||||
{
|
||||
if (m_desc == NULL)
|
||||
void charsetFilteredOutputStream_iconv::flush() {
|
||||
|
||||
if (!m_desc) {
|
||||
throw exceptions::charset_conv_error("Cannot initialize converter.");
|
||||
}
|
||||
|
||||
const iconv_t cd = *static_cast <iconv_t*>(m_desc);
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
// Process unconverted bytes
|
||||
while (m_unconvCount != 0)
|
||||
{
|
||||
while (m_unconvCount != 0) {
|
||||
|
||||
// Try a conversion
|
||||
const byte_t* inPtr = m_unconvBuffer + offset;
|
||||
size_t inLength = m_unconvCount;
|
||||
@ -453,32 +489,34 @@ void charsetFilteredOutputStream_iconv::flush()
|
||||
|
||||
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;
|
||||
|
||||
// Skip a "blocking" character
|
||||
if (inputConverted == 0)
|
||||
{
|
||||
if (!m_options.silentlyReplaceInvalidSequences)
|
||||
if (inputConverted == 0) {
|
||||
|
||||
if (!m_options.silentlyReplaceInvalidSequences) {
|
||||
throw exceptions::illegal_byte_sequence_for_charset();
|
||||
}
|
||||
|
||||
outputInvalidChar(m_stream, cd);
|
||||
|
||||
offset++;
|
||||
m_unconvCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// Write successfully converted bytes
|
||||
m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
|
||||
|
||||
offset += inputConverted;
|
||||
m_unconvCount -= inputConverted;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// Write successfully converted bytes
|
||||
m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -34,15 +34,13 @@
|
||||
#include "vmime/charsetConverter.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** A generic charset converter which uses iconv library.
|
||||
*/
|
||||
class charsetConverter_iconv : public charsetConverter {
|
||||
|
||||
class charsetConverter_iconv : public charsetConverter
|
||||
{
|
||||
public:
|
||||
|
||||
/** Construct and initialize an iconv charset converter.
|
||||
@ -51,17 +49,21 @@ public:
|
||||
* @param dest output charset
|
||||
* @param opts conversion options
|
||||
*/
|
||||
charsetConverter_iconv(const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions());
|
||||
charsetConverter_iconv(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
);
|
||||
|
||||
~charsetConverter_iconv();
|
||||
|
||||
void convert(const string& in, string& out, status* st = NULL);
|
||||
void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL);
|
||||
|
||||
shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream
|
||||
(utility::outputStream& os,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions());
|
||||
shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream(
|
||||
utility::outputStream& os,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
@ -77,8 +79,8 @@ private:
|
||||
namespace utility {
|
||||
|
||||
|
||||
class charsetFilteredOutputStream_iconv : public charsetFilteredOutputStream
|
||||
{
|
||||
class charsetFilteredOutputStream_iconv : public charsetFilteredOutputStream {
|
||||
|
||||
public:
|
||||
|
||||
/** Construct a new filter for the specified output stream.
|
||||
@ -88,9 +90,11 @@ public:
|
||||
* @param os stream into which write filtered data
|
||||
* @param opts conversion options
|
||||
*/
|
||||
charsetFilteredOutputStream_iconv
|
||||
(const charset& source, const charset& dest, outputStream* os,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions());
|
||||
charsetFilteredOutputStream_iconv(
|
||||
const charset& source,
|
||||
const charset& dest, outputStream* os,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
);
|
||||
|
||||
~charsetFilteredOutputStream_iconv();
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -34,8 +34,8 @@
|
||||
#include "vmime/utility/outputStreamStringAdapter.hpp"
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern "C" {
|
||||
|
||||
#ifndef VMIME_BUILDING_DOC
|
||||
|
||||
#include <unicode/ucnv.h>
|
||||
@ -48,59 +48,75 @@ extern "C"
|
||||
#include <unicode/unistr.h>
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
// static
|
||||
shared_ptr <charsetConverter> charsetConverter::createGenericConverter
|
||||
(const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts)
|
||||
{
|
||||
shared_ptr <charsetConverter> charsetConverter::createGenericConverter(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts
|
||||
) {
|
||||
|
||||
return make_shared <charsetConverter_icu>(source, dest, opts);
|
||||
}
|
||||
|
||||
|
||||
charsetConverter_icu::charsetConverter_icu
|
||||
(const charset& source, const charset& dest, const charsetConverterOptions& opts)
|
||||
: m_from(NULL), m_to(NULL), m_source(source), m_dest(dest), m_options(opts)
|
||||
{
|
||||
charsetConverter_icu::charsetConverter_icu(
|
||||
const charset& source,
|
||||
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;
|
||||
m_from = ucnv_open(source.getName().c_str(), &err);
|
||||
|
||||
if (!U_SUCCESS(err))
|
||||
{
|
||||
throw exceptions::charset_conv_error
|
||||
("Cannot initialize ICU converter for source charset '" + source.getName() + "' (error code: " + u_errorName(err) + ".");
|
||||
if (!U_SUCCESS(err)) {
|
||||
|
||||
throw exceptions::charset_conv_error(
|
||||
"Cannot initialize ICU converter for source charset '" + source.getName()
|
||||
+ "' (error code: " + u_errorName(err) + "."
|
||||
);
|
||||
}
|
||||
|
||||
m_to = ucnv_open(dest.getName().c_str(), &err);
|
||||
|
||||
if (!U_SUCCESS(err))
|
||||
{
|
||||
throw exceptions::charset_conv_error
|
||||
("Cannot initialize ICU converter for destination charset '" + dest.getName() + "' (error code: " + u_errorName(err) + ".");
|
||||
if (!U_SUCCESS(err)) {
|
||||
|
||||
throw exceptions::charset_conv_error(
|
||||
"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_to) ucnv_close(m_to);
|
||||
}
|
||||
|
||||
|
||||
void charsetConverter_icu::convert
|
||||
(utility::inputStream& in, utility::outputStream& out, status* st)
|
||||
{
|
||||
void charsetConverter_icu::convert(
|
||||
utility::inputStream& in,
|
||||
utility::outputStream& out,
|
||||
status* st
|
||||
) {
|
||||
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
|
||||
ucnv_reset(m_from);
|
||||
ucnv_reset(m_to);
|
||||
|
||||
if (st)
|
||||
if (st) {
|
||||
new (st) status();
|
||||
}
|
||||
|
||||
// From buffers
|
||||
byte_t cpInBuffer[16]; // stream data put here
|
||||
@ -113,34 +129,39 @@ void charsetConverter_icu::convert
|
||||
std::vector <char> cpOutBuffer(cpOutBufferSz);
|
||||
|
||||
// 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
|
||||
icu::UnicodeString substString(m_options.invalidSequence.c_str());
|
||||
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.");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// Tell ICU top stop (and return an error) on illegal byte sequences
|
||||
ucnv_setToUCallBack
|
||||
(m_from, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err);
|
||||
ucnv_setToUCallBack(
|
||||
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.");
|
||||
}
|
||||
|
||||
ucnv_setFromUCallBack
|
||||
(m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err);
|
||||
ucnv_setFromUCallBack(
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
// Input data available
|
||||
while (!in.eof())
|
||||
{
|
||||
while (!in.eof()) {
|
||||
|
||||
// Read input data into buffer
|
||||
size_t inLength = in.read(cpInBuffer, sizeof(cpInBuffer));
|
||||
|
||||
@ -153,30 +174,36 @@ void charsetConverter_icu::convert
|
||||
UErrorCode toErr;
|
||||
|
||||
// Loop until all source has been processed
|
||||
do
|
||||
{
|
||||
do {
|
||||
|
||||
// Set up target pointers
|
||||
UChar* target = &uOutBuffer[0];
|
||||
UChar* targetLimit = &target[0] + outSize;
|
||||
|
||||
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]));
|
||||
}
|
||||
|
||||
if (toErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(toErr)) {
|
||||
|
||||
if (toErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(toErr))
|
||||
{
|
||||
if (toErr == U_INVALID_CHAR_FOUND ||
|
||||
toErr == U_TRUNCATED_CHAR_FOUND ||
|
||||
toErr == U_ILLEGAL_CHAR_FOUND)
|
||||
{
|
||||
toErr == U_ILLEGAL_CHAR_FOUND) {
|
||||
|
||||
// Error will be thrown later (*)
|
||||
}
|
||||
else
|
||||
{
|
||||
throw exceptions::charset_conv_error("[ICU] Error converting to Unicode from " + m_source.getName());
|
||||
|
||||
} else {
|
||||
|
||||
throw exceptions::charset_conv_error(
|
||||
"[ICU] Error converting to Unicode from " + m_source.getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,19 +214,21 @@ void charsetConverter_icu::convert
|
||||
UErrorCode fromErr;
|
||||
|
||||
// Loop until converted chars are fully written
|
||||
do
|
||||
{
|
||||
do {
|
||||
|
||||
char* cpTarget = &cpOutBuffer[0];
|
||||
const char* cpTargetLimit = &cpOutBuffer[0] + cpOutBufferSz;
|
||||
|
||||
fromErr = U_ZERO_ERROR;
|
||||
|
||||
// Write converted bytes (Unicode) to destination codepage
|
||||
ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit,
|
||||
&uSource, uSourceLimit, NULL, flush, &fromErr);
|
||||
ucnv_fromUnicode(
|
||||
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
|
||||
char errBytes[16];
|
||||
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 (toErr == U_INVALID_CHAR_FOUND ||
|
||||
toErr == U_TRUNCATED_CHAR_FOUND ||
|
||||
toErr == U_ILLEGAL_CHAR_FOUND)
|
||||
{
|
||||
toErr == U_ILLEGAL_CHAR_FOUND) {
|
||||
|
||||
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 ||
|
||||
fromErr == U_TRUNCATED_CHAR_FOUND ||
|
||||
fromErr == U_ILLEGAL_CHAR_FOUND)
|
||||
{
|
||||
fromErr == U_ILLEGAL_CHAR_FOUND) {
|
||||
|
||||
throw exceptions::illegal_byte_sequence_for_charset();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw exceptions::charset_conv_error("[ICU] Error converting from Unicode to " + m_dest.getName());
|
||||
|
||||
} else {
|
||||
|
||||
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)
|
||||
{
|
||||
if (st)
|
||||
void charsetConverter_icu::convert(const string& in, string& out, status* st) {
|
||||
|
||||
if (st) {
|
||||
new (st) status();
|
||||
}
|
||||
|
||||
out.clear();
|
||||
|
||||
@ -260,9 +292,11 @@ void charsetConverter_icu::convert(const string& in, string& out, status* st)
|
||||
|
||||
|
||||
shared_ptr <utility::charsetFilteredOutputStream>
|
||||
charsetConverter_icu::getFilteredOutputStream
|
||||
(utility::outputStream& os, const charsetConverterOptions& opts)
|
||||
{
|
||||
charsetConverter_icu::getFilteredOutputStream(
|
||||
utility::outputStream& os,
|
||||
const charsetConverterOptions& opts
|
||||
) {
|
||||
|
||||
return make_shared <utility::charsetFilteredOutputStream_icu>(m_source, m_dest, &os, opts);
|
||||
}
|
||||
|
||||
@ -273,75 +307,94 @@ shared_ptr <utility::charsetFilteredOutputStream>
|
||||
namespace utility {
|
||||
|
||||
|
||||
charsetFilteredOutputStream_icu::charsetFilteredOutputStream_icu
|
||||
(const charset& source, const charset& dest, outputStream* os,
|
||||
const charsetConverterOptions& opts)
|
||||
: m_from(NULL), m_to(NULL), m_sourceCharset(source),
|
||||
m_destCharset(dest), m_stream(*os), m_options(opts)
|
||||
{
|
||||
charsetFilteredOutputStream_icu::charsetFilteredOutputStream_icu(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
outputStream* os,
|
||||
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;
|
||||
m_from = ucnv_open(source.getName().c_str(), &err);
|
||||
|
||||
if (!U_SUCCESS(err))
|
||||
{
|
||||
throw exceptions::charset_conv_error
|
||||
("Cannot initialize ICU converter for source charset '" + source.getName() + "' (error code: " + u_errorName(err) + ".");
|
||||
if (!U_SUCCESS(err)) {
|
||||
|
||||
throw exceptions::charset_conv_error(
|
||||
"Cannot initialize ICU converter for source charset '" + source.getName()
|
||||
+ "' (error code: " + u_errorName(err) + "."
|
||||
);
|
||||
}
|
||||
|
||||
m_to = ucnv_open(dest.getName().c_str(), &err);
|
||||
|
||||
if (!U_SUCCESS(err))
|
||||
{
|
||||
throw exceptions::charset_conv_error
|
||||
("Cannot initialize ICU converter for destination charset '" + dest.getName() + "' (error code: " + u_errorName(err) + ".");
|
||||
if (!U_SUCCESS(err)) {
|
||||
|
||||
throw exceptions::charset_conv_error(
|
||||
"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
|
||||
if (m_options.silentlyReplaceInvalidSequences)
|
||||
{
|
||||
if (m_options.silentlyReplaceInvalidSequences) {
|
||||
|
||||
// Set replacement chars for when converting from Unicode to codepage
|
||||
icu::UnicodeString substString(m_options.invalidSequence.c_str());
|
||||
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.");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// Tell ICU top stop (and return an error) on illegal byte sequences
|
||||
ucnv_setToUCallBack
|
||||
(m_to, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err);
|
||||
ucnv_setToUCallBack(
|
||||
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.");
|
||||
}
|
||||
|
||||
ucnv_setFromUCallBack
|
||||
(m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err);
|
||||
ucnv_setFromUCallBack(
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
charsetFilteredOutputStream_icu::~charsetFilteredOutputStream_icu()
|
||||
{
|
||||
charsetFilteredOutputStream_icu::~charsetFilteredOutputStream_icu() {
|
||||
|
||||
if (m_from) ucnv_close(m_from);
|
||||
if (m_to) ucnv_close(m_to);
|
||||
}
|
||||
|
||||
|
||||
outputStream& charsetFilteredOutputStream_icu::getNextOutputStream()
|
||||
{
|
||||
outputStream& charsetFilteredOutputStream_icu::getNextOutputStream() {
|
||||
|
||||
return m_stream;
|
||||
}
|
||||
|
||||
|
||||
void charsetFilteredOutputStream_icu::writeImpl
|
||||
(const byte_t* const data, const size_t count)
|
||||
{
|
||||
if (m_from == NULL || m_to == NULL)
|
||||
void charsetFilteredOutputStream_icu::writeImpl(
|
||||
const byte_t* const data,
|
||||
const size_t count
|
||||
) {
|
||||
|
||||
if (!m_from || !m_to) {
|
||||
throw exceptions::charset_conv_error("Cannot initialize converters.");
|
||||
}
|
||||
|
||||
// Allocate buffer for Unicode chars
|
||||
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* uniSourceLimit = uniSource + count;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
|
||||
// Convert from source charset to Unicode
|
||||
UChar* uniTarget = &uniBuffer[0];
|
||||
UChar* uniTargetLimit = &uniBuffer[0] + uniSize;
|
||||
|
||||
toErr = U_ZERO_ERROR;
|
||||
|
||||
ucnv_toUnicode(m_from, &uniTarget, uniTargetLimit,
|
||||
&uniSource, uniSourceLimit, NULL, /* flush */ FALSE, &toErr);
|
||||
ucnv_toUnicode(
|
||||
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 ||
|
||||
toErr == U_TRUNCATED_CHAR_FOUND ||
|
||||
toErr == U_ILLEGAL_CHAR_FOUND)
|
||||
{
|
||||
toErr == U_ILLEGAL_CHAR_FOUND) {
|
||||
|
||||
throw exceptions::illegal_byte_sequence_for_charset();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw exceptions::charset_conv_error
|
||||
("[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'.");
|
||||
|
||||
} else {
|
||||
|
||||
throw exceptions::charset_conv_error(
|
||||
"[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,28 +447,31 @@ void charsetFilteredOutputStream_icu::writeImpl
|
||||
const UChar* cpSource = &uniBuffer[0];
|
||||
const UChar* cpSourceLimit = &uniBuffer[0] + uniLength;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
|
||||
char* cpTarget = &cpBuffer[0];
|
||||
char* cpTargetLimit = &cpBuffer[0] + cpSize;
|
||||
|
||||
fromErr = U_ZERO_ERROR;
|
||||
|
||||
ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit,
|
||||
&cpSource, cpSourceLimit, NULL, /* flush */ FALSE, &fromErr);
|
||||
ucnv_fromUnicode(
|
||||
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 ||
|
||||
fromErr == U_TRUNCATED_CHAR_FOUND ||
|
||||
fromErr == U_ILLEGAL_CHAR_FOUND)
|
||||
{
|
||||
fromErr == U_ILLEGAL_CHAR_FOUND) {
|
||||
|
||||
throw exceptions::illegal_byte_sequence_for_charset();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw exceptions::charset_conv_error
|
||||
("[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'.");
|
||||
|
||||
} else {
|
||||
|
||||
throw exceptions::charset_conv_error(
|
||||
"[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,10 +486,11 @@ void charsetFilteredOutputStream_icu::writeImpl
|
||||
}
|
||||
|
||||
|
||||
void charsetFilteredOutputStream_icu::flush()
|
||||
{
|
||||
if (m_from == NULL || m_to == NULL)
|
||||
void charsetFilteredOutputStream_icu::flush() {
|
||||
|
||||
if (!m_from || !m_to) {
|
||||
throw exceptions::charset_conv_error("Cannot initialize converters.");
|
||||
}
|
||||
|
||||
// Allocate buffer for Unicode chars
|
||||
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* uniSourceLimit = 0;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
|
||||
// Convert from source charset to Unicode
|
||||
UChar* uniTarget = &uniBuffer[0];
|
||||
UChar* uniTargetLimit = &uniBuffer[0] + uniSize;
|
||||
|
||||
toErr = U_ZERO_ERROR;
|
||||
|
||||
ucnv_toUnicode(m_from, &uniTarget, uniTargetLimit,
|
||||
&uniSource, uniSourceLimit, NULL, /* flush */ TRUE, &toErr);
|
||||
ucnv_toUnicode(
|
||||
m_from, &uniTarget, uniTargetLimit,
|
||||
&uniSource, uniSourceLimit, NULL, /* flush */ TRUE, &toErr
|
||||
);
|
||||
|
||||
if (U_FAILURE(toErr) && toErr != U_BUFFER_OVERFLOW_ERROR)
|
||||
{
|
||||
throw exceptions::charset_conv_error
|
||||
("[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'.");
|
||||
if (U_FAILURE(toErr) && toErr != U_BUFFER_OVERFLOW_ERROR) {
|
||||
|
||||
throw exceptions::charset_conv_error(
|
||||
"[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'."
|
||||
);
|
||||
}
|
||||
|
||||
const size_t uniLength = uniTarget - &uniBuffer[0];
|
||||
@ -471,20 +534,23 @@ void charsetFilteredOutputStream_icu::flush()
|
||||
const UChar* cpSource = &uniBuffer[0];
|
||||
const UChar* cpSourceLimit = &uniBuffer[0] + uniLength;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
|
||||
char* cpTarget = &cpBuffer[0];
|
||||
char* cpTargetLimit = &cpBuffer[0] + cpSize;
|
||||
|
||||
fromErr = U_ZERO_ERROR;
|
||||
|
||||
ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit,
|
||||
&cpSource, cpSourceLimit, NULL, /* flush */ TRUE, &fromErr);
|
||||
ucnv_fromUnicode(
|
||||
m_to, &cpTarget, cpTargetLimit,
|
||||
&cpSource, cpSourceLimit, NULL, /* flush */ TRUE, &fromErr
|
||||
);
|
||||
|
||||
if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr))
|
||||
{
|
||||
throw exceptions::charset_conv_error
|
||||
("[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'.");
|
||||
if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) {
|
||||
|
||||
throw exceptions::charset_conv_error(
|
||||
"[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'."
|
||||
);
|
||||
}
|
||||
|
||||
const size_t cpLength = cpTarget - &cpBuffer[0];
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -37,15 +37,13 @@
|
||||
struct UConverter;
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** A generic charset converter which uses ICU library.
|
||||
*/
|
||||
class charsetConverter_icu : public charsetConverter {
|
||||
|
||||
class charsetConverter_icu : public charsetConverter
|
||||
{
|
||||
public:
|
||||
|
||||
/** Construct and initialize an ICU charset converter.
|
||||
@ -54,17 +52,21 @@ public:
|
||||
* @param dest output charset
|
||||
* @param opts conversion options
|
||||
*/
|
||||
charsetConverter_icu(const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions());
|
||||
charsetConverter_icu(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
);
|
||||
|
||||
~charsetConverter_icu();
|
||||
|
||||
void convert(const string& in, string& out, status* st = NULL);
|
||||
void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL);
|
||||
|
||||
shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream
|
||||
(utility::outputStream& os,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions());
|
||||
shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream(
|
||||
utility::outputStream& os,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
@ -81,8 +83,8 @@ private:
|
||||
namespace utility {
|
||||
|
||||
|
||||
class charsetFilteredOutputStream_icu : public charsetFilteredOutputStream
|
||||
{
|
||||
class charsetFilteredOutputStream_icu : public charsetFilteredOutputStream {
|
||||
|
||||
public:
|
||||
|
||||
/** Construct a new filter for the specified output stream.
|
||||
@ -92,9 +94,12 @@ public:
|
||||
* @param os stream into which write filtered data
|
||||
* @param opts conversion options
|
||||
*/
|
||||
charsetFilteredOutputStream_icu
|
||||
(const charset& source, const charset& dest, outputStream* os,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions());
|
||||
charsetFilteredOutputStream_icu(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
outputStream* os,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
);
|
||||
|
||||
~charsetFilteredOutputStream_icu();
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -30,8 +30,7 @@
|
||||
#include "vmime/utility/outputStreamStringAdapter.hpp"
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern "C" {
|
||||
|
||||
#include "contrib/punycode/punycode.h"
|
||||
#include "contrib/punycode/punycode.c"
|
||||
@ -41,26 +40,31 @@ extern "C"
|
||||
#include "contrib/utf8/utf8.h"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
charsetConverter_idna::charsetConverter_idna
|
||||
(const charset& source, const charset& dest, const charsetConverterOptions& opts)
|
||||
: m_source(source), m_dest(dest), m_options(opts)
|
||||
{
|
||||
charsetConverter_idna::charsetConverter_idna(
|
||||
const charset& source,
|
||||
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)
|
||||
{
|
||||
if (st)
|
||||
void charsetConverter_idna::convert(utility::inputStream& in, utility::outputStream& out, status* st) {
|
||||
|
||||
if (st) {
|
||||
new (st) status();
|
||||
}
|
||||
|
||||
// IDNA should be used for short strings, so it does not matter if we
|
||||
// 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)
|
||||
{
|
||||
if (st)
|
||||
void charsetConverter_idna::convert(const string& in, string& out, status* st) {
|
||||
|
||||
if (st) {
|
||||
new (st) status();
|
||||
}
|
||||
|
||||
out.clear();
|
||||
|
||||
if (m_dest == "idna")
|
||||
{
|
||||
if (utility::stringUtils::is7bit(in))
|
||||
{
|
||||
if (st)
|
||||
{
|
||||
if (m_dest == "idna") {
|
||||
|
||||
if (utility::stringUtils::is7bit(in)) {
|
||||
|
||||
if (st) {
|
||||
st->inputBytesRead = 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;
|
||||
unichars.reserve(inUTF8.length());
|
||||
|
||||
while (ch < end)
|
||||
{
|
||||
while (ch < end) {
|
||||
const utf8::uint32_t uc = utf8::unchecked::next(ch);
|
||||
unichars.push_back(uc);
|
||||
}
|
||||
|
||||
if (st)
|
||||
if (st) {
|
||||
st->inputBytesRead = in.length();
|
||||
}
|
||||
|
||||
punycode_uint inputLen = static_cast <punycode_uint>(unichars.size());
|
||||
|
||||
std::vector <char> output(inUTF8.length() * 2);
|
||||
punycode_uint outputLen = static_cast <punycode_uint>(output.size());
|
||||
|
||||
const punycode_status status = punycode_encode
|
||||
(inputLen, &unichars[0], /* case_flags */ NULL, &outputLen, &output[0]);
|
||||
const punycode_status status = punycode_encode(
|
||||
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);
|
||||
|
||||
if (st)
|
||||
if (st) {
|
||||
st->outputBytesWritten = out.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
else if (m_source == "idna")
|
||||
{
|
||||
if (in.length() < 5 || in.substr(0, 4) != "xn--")
|
||||
{
|
||||
if (st)
|
||||
{
|
||||
|
||||
} else if (m_source == "idna") {
|
||||
|
||||
if (in.length() < 5 || in.substr(0, 4) != "xn--") {
|
||||
|
||||
if (st) {
|
||||
st->inputBytesRead = 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);
|
||||
punycode_uint outputLen = static_cast <punycode_uint>(output.size());
|
||||
|
||||
const punycode_status status = punycode_decode
|
||||
(inputLen, &in[4], &outputLen, &output[0], /* case_flags */ NULL);
|
||||
const punycode_status status = punycode_decode(
|
||||
inputLen, &in[4], &outputLen, &output[0], /* case_flags */ NULL
|
||||
);
|
||||
|
||||
if (st)
|
||||
if (st) {
|
||||
st->inputBytesRead = in.length();
|
||||
}
|
||||
|
||||
if (status == punycode_success) {
|
||||
|
||||
if (status == punycode_success)
|
||||
{
|
||||
std::vector <char> outUTF8Bytes(outputLen * 4);
|
||||
char* p = &outUTF8Bytes[0];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
string outUTF8(&outUTF8Bytes[0], p);
|
||||
charset::convert(outUTF8, out, vmime::charsets::UTF_8, m_dest);
|
||||
|
||||
if (st)
|
||||
if (st) {
|
||||
st->outputBytesWritten = out.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
@ -187,9 +195,12 @@ void charsetConverter_idna::convert(const string& in, string& out, status* st)
|
||||
|
||||
|
||||
shared_ptr <utility::charsetFilteredOutputStream>
|
||||
charsetConverter_idna::getFilteredOutputStream
|
||||
(utility::outputStream& /* os */, const charsetConverterOptions& /* opts */)
|
||||
{
|
||||
charsetConverter_idna::getFilteredOutputStream(
|
||||
utility::outputStream& /* os */,
|
||||
const charsetConverterOptions& /* opts */
|
||||
) {
|
||||
|
||||
// Not supported
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -28,15 +28,13 @@
|
||||
#include "vmime/charsetConverter.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** A charset converter which can convert to and from Punycode (for IDNA).
|
||||
*/
|
||||
class charsetConverter_idna : public charsetConverter {
|
||||
|
||||
class charsetConverter_idna : public charsetConverter
|
||||
{
|
||||
public:
|
||||
|
||||
/** Construct and initialize an IDNA charset converter.
|
||||
@ -45,17 +43,21 @@ public:
|
||||
* @param dest output charset
|
||||
* @param opts conversion options
|
||||
*/
|
||||
charsetConverter_idna(const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions());
|
||||
charsetConverter_idna(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
);
|
||||
|
||||
~charsetConverter_idna();
|
||||
|
||||
void convert(const string& in, string& out, status* st = NULL);
|
||||
void convert(utility::inputStream& in, utility::outputStream& out, status* st = NULL);
|
||||
|
||||
shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream
|
||||
(utility::outputStream& os,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions());
|
||||
shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream(
|
||||
utility::outputStream& os,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -49,37 +49,46 @@
|
||||
#define CP_UNICODE 1200
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
// static
|
||||
shared_ptr <charsetConverter> charsetConverter::createGenericConverter
|
||||
(const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts)
|
||||
{
|
||||
shared_ptr <charsetConverter> charsetConverter::createGenericConverter(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts
|
||||
) {
|
||||
|
||||
return make_shared <charsetConverter_win>(source, dest, opts);
|
||||
}
|
||||
|
||||
|
||||
charsetConverter_win::charsetConverter_win
|
||||
(const charset& source, const charset& dest, const charsetConverterOptions& opts)
|
||||
: m_source(source), m_dest(dest), m_options(opts)
|
||||
{
|
||||
charsetConverter_win::charsetConverter_win(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts
|
||||
)
|
||||
: m_source(source),
|
||||
m_dest(dest),
|
||||
m_options(opts) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void charsetConverter_win::convert
|
||||
(utility::inputStream& in, utility::outputStream& out, status* st)
|
||||
{
|
||||
if (st)
|
||||
void charsetConverter_win::convert(
|
||||
utility::inputStream& in,
|
||||
utility::outputStream& out,
|
||||
status* st
|
||||
) {
|
||||
|
||||
if (st) {
|
||||
new (st) status();
|
||||
}
|
||||
|
||||
byte_t buffer[32768];
|
||||
string inStr, outStr;
|
||||
|
||||
while (!in.eof())
|
||||
{
|
||||
while (!in.eof()) {
|
||||
const size_t len = in.read(buffer, sizeof(buffer));
|
||||
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)
|
||||
{
|
||||
if (st)
|
||||
void charsetConverter_win::convert(const string& in, string& out, status* st) {
|
||||
|
||||
if (st) {
|
||||
new (st) status();
|
||||
}
|
||||
|
||||
const int sourceCodePage = getCodePage(m_source.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;
|
||||
size_t unicodeLen = 0;
|
||||
|
||||
if (sourceCodePage == CP_UNICODE)
|
||||
{
|
||||
if (sourceCodePage == CP_UNICODE) {
|
||||
|
||||
unicodePtr = reinterpret_cast <const WCHAR*>(in.c_str());
|
||||
unicodeLen = in.length() / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t bufferSize = MultiByteToWideChar
|
||||
(sourceCodePage, 0, in.c_str(), static_cast <int>(in.length()),
|
||||
NULL, 0) * sizeof(WCHAR); // in wide characters
|
||||
|
||||
} else {
|
||||
|
||||
const size_t bufferSize = MultiByteToWideChar(
|
||||
sourceCodePage, 0, in.c_str(), static_cast <int>(in.length()), NULL, 0
|
||||
) * sizeof(WCHAR); // in wide characters
|
||||
|
||||
unicodeBuffer.resize(bufferSize);
|
||||
|
||||
DWORD flags = 0;
|
||||
|
||||
if (!m_options.silentlyReplaceInvalidSequences)
|
||||
if (!m_options.silentlyReplaceInvalidSequences) {
|
||||
flags |= MB_ERR_INVALID_CHARS;
|
||||
}
|
||||
|
||||
unicodePtr = reinterpret_cast <const WCHAR*>(&unicodeBuffer[0]);
|
||||
unicodeLen = MultiByteToWideChar
|
||||
(sourceCodePage, 0, in.c_str(), static_cast <int>(in.length()),
|
||||
reinterpret_cast <WCHAR*>(&unicodeBuffer[0]), static_cast <int>(bufferSize));
|
||||
unicodeLen = MultiByteToWideChar(
|
||||
sourceCodePage, 0, in.c_str(), static_cast <int>(in.length()),
|
||||
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();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw exceptions::charset_conv_error("MultiByteToWideChar() failed when converting to Unicode from " + m_source.getName());
|
||||
|
||||
} else {
|
||||
|
||||
throw exceptions::charset_conv_error(
|
||||
"MultiByteToWideChar() failed when converting to Unicode from " + m_source.getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert from Unicode to destination charset
|
||||
if (destCodePage == CP_UNICODE)
|
||||
{
|
||||
if (destCodePage == CP_UNICODE) {
|
||||
|
||||
out.assign(reinterpret_cast <const char*>(unicodePtr), unicodeLen * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t bufferSize = WideCharToMultiByte
|
||||
(destCodePage, 0, unicodePtr, static_cast <int>(unicodeLen),
|
||||
NULL, 0, 0, NULL); // in multibyte characters
|
||||
|
||||
} else {
|
||||
|
||||
const size_t bufferSize = WideCharToMultiByte(
|
||||
destCodePage, 0, unicodePtr, static_cast <int>(unicodeLen),
|
||||
NULL, 0, 0, NULL
|
||||
); // in multibyte characters
|
||||
|
||||
std::vector <char> buffer;
|
||||
buffer.resize(bufferSize);
|
||||
|
||||
const size_t len = WideCharToMultiByte
|
||||
(destCodePage, 0, unicodePtr, static_cast <int>(unicodeLen),
|
||||
&buffer[0], static_cast <int>(bufferSize), 0, NULL);
|
||||
const size_t len = WideCharToMultiByte(
|
||||
destCodePage, 0, unicodePtr, static_cast <int>(unicodeLen),
|
||||
&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();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw exceptions::charset_conv_error("WideCharToMultiByte() failed when converting from Unicode to " + m_source.getName());
|
||||
|
||||
} else {
|
||||
|
||||
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
|
||||
int charsetConverter_win::getCodePage(const char* name)
|
||||
{
|
||||
if (_stricmp(name, charsets::UTF_16) == 0) // wchar_t is UTF-16 on Windows
|
||||
int charsetConverter_win::getCodePage(const char* name) {
|
||||
|
||||
if (_stricmp(name, charsets::UTF_16) == 0) { // wchar_t is UTF-16 on Windows
|
||||
return CP_UNICODE;
|
||||
}
|
||||
|
||||
// "cp1252" --> return 1252
|
||||
if ((name[0] == 'c' || name[0] == 'C') &&
|
||||
(name[1] == 'p' || name[1] == 'P'))
|
||||
{
|
||||
(name[1] == 'p' || name[1] == 'P')) {
|
||||
|
||||
return atoi(name + 2);
|
||||
}
|
||||
|
||||
@ -192,9 +211,11 @@ int charsetConverter_win::getCodePage(const char* name)
|
||||
|
||||
|
||||
shared_ptr <utility::charsetFilteredOutputStream>
|
||||
charsetConverter_win::getFilteredOutputStream
|
||||
(utility::outputStream& /* os */, const charsetConverterOptions& /* opts */)
|
||||
{
|
||||
charsetConverter_win::getFilteredOutputStream(
|
||||
utility::outputStream& /* os */,
|
||||
const charsetConverterOptions& /* opts */
|
||||
) {
|
||||
|
||||
// TODO: implement me!
|
||||
return null;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -34,8 +34,7 @@
|
||||
#include "vmime/charsetConverter.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
class charsetConverter_win : public charsetConverter {
|
||||
|
||||
class charsetConverter_win : public charsetConverter
|
||||
{
|
||||
public:
|
||||
|
||||
/** Construct and initialize a Windows charset converter.
|
||||
@ -60,14 +58,19 @@ public:
|
||||
* @param dest output charset
|
||||
* @param opts conversion options
|
||||
*/
|
||||
charsetConverter_win(const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions());
|
||||
charsetConverter_win(
|
||||
const charset& source,
|
||||
const charset& dest,
|
||||
const charsetConverterOptions& opts = charsetConverterOptions()
|
||||
);
|
||||
|
||||
void convert(const string& in, string& out, status* st);
|
||||
void convert(utility::inputStream& in, utility::outputStream& out, status* st);
|
||||
|
||||
shared_ptr <utility::charsetFilteredOutputStream>
|
||||
getFilteredOutputStream(utility::outputStream& os, const charsetConverterOptions& opts);
|
||||
shared_ptr <utility::charsetFilteredOutputStream> getFilteredOutputStream(
|
||||
utility::outputStream& os,
|
||||
const charsetConverterOptions& opts
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -31,48 +31,54 @@
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
component::component()
|
||||
: m_parsedOffset(0), m_parsedLength(0)
|
||||
{
|
||||
: m_parsedOffset(0), m_parsedLength(0) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
component::~component()
|
||||
{
|
||||
component::~component() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void component::parse
|
||||
(shared_ptr <utility::inputStream> inputStream, const size_t length)
|
||||
{
|
||||
void component::parse(
|
||||
const shared_ptr <utility::inputStream>& inputStream,
|
||||
const size_t length
|
||||
) {
|
||||
|
||||
parse(inputStream, 0, length, NULL);
|
||||
}
|
||||
|
||||
|
||||
void component::parse
|
||||
(shared_ptr <utility::inputStream> inputStream, const size_t position,
|
||||
const size_t end, size_t* newPosition)
|
||||
{
|
||||
void component::parse(
|
||||
const shared_ptr <utility::inputStream>& inputStream,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition) {
|
||||
|
||||
parse(parsingContext::getDefaultContext(), inputStream, position, end, newPosition);
|
||||
}
|
||||
|
||||
|
||||
void component::parse
|
||||
(const parsingContext& ctx,
|
||||
shared_ptr <utility::inputStream> inputStream, const size_t position,
|
||||
const size_t end, size_t* newPosition)
|
||||
{
|
||||
void component::parse(
|
||||
const parsingContext& ctx,
|
||||
const shared_ptr <utility::inputStream>& inputStream,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition
|
||||
) {
|
||||
|
||||
m_parsedOffset = m_parsedLength = 0;
|
||||
|
||||
shared_ptr <utility::seekableInputStream> seekableStream =
|
||||
dynamicCast <utility::seekableInputStream>(inputStream);
|
||||
|
||||
if (seekableStream == NULL || end == 0)
|
||||
{
|
||||
if (!seekableStream || end == 0) {
|
||||
|
||||
// Read the whole stream into a buffer
|
||||
std::ostringstream oss;
|
||||
utility::outputStreamAdapter ossAdapter(oss);
|
||||
@ -81,9 +87,9 @@ void component::parse
|
||||
|
||||
const string buffer = oss.str();
|
||||
parseImpl(ctx, buffer, 0, buffer.length(), NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
shared_ptr <utility::parserInputStreamAdapter> parser =
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
parseImpl(ctx, buffer, 0, buffer.length(), NULL);
|
||||
}
|
||||
|
||||
|
||||
void component::parse
|
||||
(const string& buffer, const size_t position,
|
||||
const size_t end, size_t* newPosition)
|
||||
{
|
||||
void component::parse(
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition
|
||||
) {
|
||||
|
||||
m_parsedOffset = m_parsedLength = 0;
|
||||
|
||||
parseImpl(parsingContext::getDefaultContext(), buffer, position, end, newPosition);
|
||||
}
|
||||
|
||||
|
||||
void component::parse
|
||||
(const parsingContext& ctx,
|
||||
const string& buffer, const size_t position,
|
||||
const size_t end, size_t* newPosition)
|
||||
{
|
||||
void component::parse(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end, size_t* newPosition
|
||||
) {
|
||||
|
||||
m_parsedOffset = m_parsedLength = 0;
|
||||
|
||||
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
|
||||
if (m_parsedLength != 0)
|
||||
if (m_parsedLength != 0) {
|
||||
m_parsedOffset += offset;
|
||||
}
|
||||
|
||||
// Offset parsed bounds of our children
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void component::parseImpl
|
||||
(const parsingContext& ctx, shared_ptr <utility::parserInputStreamAdapter> parser,
|
||||
const size_t position, const size_t end, size_t* newPosition)
|
||||
{
|
||||
void component::parseImpl(
|
||||
const parsingContext& ctx,
|
||||
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:
|
||||
// actually, we extract the substring and use the "parse from string" implementation
|
||||
const string buffer = parser->extract(position, end);
|
||||
parseImpl(ctx, buffer, 0, buffer.length(), newPosition);
|
||||
|
||||
// Recursivey offset parsed bounds on children
|
||||
if (position != 0)
|
||||
if (position != 0) {
|
||||
offsetParsedBounds(position);
|
||||
}
|
||||
|
||||
if (newPosition != NULL)
|
||||
if (newPosition) {
|
||||
*newPosition += position;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void component::parseImpl
|
||||
(const parsingContext& ctx, const string& buffer, const size_t position,
|
||||
const size_t end, size_t* newPosition)
|
||||
{
|
||||
void component::parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition) {
|
||||
|
||||
// This is the default implementation for parsing from a string:
|
||||
// actually, we encapsulate the string buffer in an input stream, then use
|
||||
// the "parse from input stream" implementation
|
||||
@ -178,9 +200,11 @@ void component::parseImpl
|
||||
}
|
||||
|
||||
|
||||
const string component::generate
|
||||
(const size_t maxLineLength, const size_t curLinePos) const
|
||||
{
|
||||
const string component::generate(
|
||||
const size_t maxLineLength,
|
||||
const size_t curLinePos
|
||||
) const {
|
||||
|
||||
std::ostringstream oss;
|
||||
utility::outputStreamAdapter adapter(oss);
|
||||
|
||||
@ -189,56 +213,63 @@ const string component::generate
|
||||
|
||||
generateImpl(ctx, adapter, curLinePos, NULL);
|
||||
|
||||
return (oss.str());
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
void component::generate
|
||||
(utility::outputStream& os, const size_t curLinePos, size_t* newLinePos) const
|
||||
{
|
||||
generateImpl(generationContext::getDefaultContext(),
|
||||
os, curLinePos, newLinePos);
|
||||
void component::generate(
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos,
|
||||
size_t* newLinePos
|
||||
) const {
|
||||
|
||||
generateImpl(generationContext::getDefaultContext(), os, curLinePos, newLinePos);
|
||||
}
|
||||
|
||||
|
||||
void component::generate
|
||||
(const generationContext& ctx, utility::outputStream& outputStream,
|
||||
const size_t curLinePos, size_t* newLinePos) const
|
||||
{
|
||||
void component::generate(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& outputStream,
|
||||
const size_t curLinePos,
|
||||
size_t* newLinePos
|
||||
) const {
|
||||
|
||||
generateImpl(ctx, outputStream, curLinePos, newLinePos);
|
||||
}
|
||||
|
||||
|
||||
size_t component::getParsedOffset() const
|
||||
{
|
||||
return (m_parsedOffset);
|
||||
size_t component::getParsedOffset() const {
|
||||
|
||||
return m_parsedOffset;
|
||||
}
|
||||
|
||||
|
||||
size_t component::getParsedLength() const
|
||||
{
|
||||
return (m_parsedLength);
|
||||
size_t component::getParsedLength() const {
|
||||
|
||||
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_parsedLength = end - start;
|
||||
}
|
||||
|
||||
|
||||
size_t component::getGeneratedSize(const generationContext& ctx)
|
||||
{
|
||||
size_t component::getGeneratedSize(const generationContext& ctx) {
|
||||
|
||||
std::vector <shared_ptr <component> > children = getChildComponents();
|
||||
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);
|
||||
}
|
||||
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
|
||||
} // vmime
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -34,16 +34,14 @@
|
||||
#include "vmime/parsingContext.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** This abstract class is the base class for all the components of a message.
|
||||
* It defines methods for parsing and generating a component.
|
||||
*/
|
||||
class VMIME_EXPORT component : public object {
|
||||
|
||||
class VMIME_EXPORT component : public object
|
||||
{
|
||||
public:
|
||||
|
||||
component();
|
||||
@ -70,7 +68,7 @@ public:
|
||||
* @param inputStream stream from which to read data
|
||||
* @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
|
||||
* parsing context.
|
||||
@ -80,11 +78,12 @@ public:
|
||||
* @param end end position in the input buffer
|
||||
* @param newPosition will receive the new position in the input buffer
|
||||
*/
|
||||
void parse
|
||||
(const string& buffer,
|
||||
void parse(
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
/** Parse RFC-822/MIME data for this component.
|
||||
*
|
||||
@ -94,12 +93,13 @@ public:
|
||||
* @param end end position in the input buffer
|
||||
* @param newPosition will receive the new position in the input buffer
|
||||
*/
|
||||
void parse
|
||||
(const parsingContext& ctx,
|
||||
void parse(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
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,
|
||||
* 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 newPosition will receive the new position in the input stream
|
||||
*/
|
||||
void parse
|
||||
(shared_ptr <utility::inputStream> inputStream,
|
||||
void parse(
|
||||
const shared_ptr <utility::inputStream>& inputStream,
|
||||
const size_t position,
|
||||
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,
|
||||
* 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 newPosition will receive the new position in the input stream
|
||||
*/
|
||||
void parse
|
||||
(const parsingContext& ctx,
|
||||
shared_ptr <utility::inputStream> inputStream,
|
||||
void parse(
|
||||
const parsingContext& ctx,
|
||||
const shared_ptr <utility::inputStream>& inputStream,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
/** Generate RFC-2822/MIME data for this component.
|
||||
*
|
||||
@ -142,9 +144,10 @@ public:
|
||||
* @param curLinePos length of the current line in the output buffer
|
||||
* @return generated data
|
||||
*/
|
||||
virtual const string generate
|
||||
(const size_t maxLineLength = lineLengthLimits::infinite,
|
||||
const size_t curLinePos = 0) const;
|
||||
virtual const string generate(
|
||||
const size_t maxLineLength = lineLengthLimits::infinite,
|
||||
const size_t curLinePos = 0
|
||||
) const;
|
||||
|
||||
/** 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 newLinePos will receive the new line position (length of the last line written)
|
||||
*/
|
||||
virtual void generate
|
||||
(utility::outputStream& outputStream,
|
||||
virtual void generate(
|
||||
utility::outputStream& outputStream,
|
||||
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.
|
||||
*
|
||||
@ -164,11 +168,12 @@ public:
|
||||
* @param curLinePos length of the current line in the output buffer
|
||||
* @param newLinePos will receive the new line position (length of the last line written)
|
||||
*/
|
||||
virtual void generate
|
||||
(const generationContext& ctx,
|
||||
virtual void generate(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& outputStream,
|
||||
const size_t curLinePos = 0,
|
||||
size_t* newLinePos = NULL) const;
|
||||
size_t* newLinePos = NULL
|
||||
) const;
|
||||
|
||||
/** Clone this component.
|
||||
*
|
||||
@ -222,25 +227,28 @@ protected:
|
||||
void setParsedBounds(const size_t start, const size_t end);
|
||||
|
||||
// AT LEAST ONE of these parseImpl() functions MUST be implemented in derived class
|
||||
virtual void parseImpl
|
||||
(const parsingContext& ctx,
|
||||
shared_ptr <utility::parserInputStreamAdapter> parser,
|
||||
virtual void parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const shared_ptr <utility::parserInputStreamAdapter>& parser,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
virtual void parseImpl
|
||||
(const parsingContext& ctx,
|
||||
virtual void parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
virtual void generateImpl
|
||||
(const generationContext& ctx,
|
||||
virtual void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
size_t* newLinePos = NULL) const = 0;
|
||||
size_t* newLinePos = NULL
|
||||
) const = 0;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -24,13 +24,12 @@
|
||||
#include "vmime/constants.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
// Media Types
|
||||
namespace mediaTypes
|
||||
{
|
||||
namespace mediaTypes {
|
||||
|
||||
// Types
|
||||
const char* const TEXT = "text";
|
||||
const char* const MULTIPART = "multipart";
|
||||
@ -72,8 +71,8 @@ namespace mediaTypes
|
||||
|
||||
|
||||
// Encoding types
|
||||
namespace encodingTypes
|
||||
{
|
||||
namespace encodingTypes {
|
||||
|
||||
const char* const SEVEN_BIT = "7bit";
|
||||
const char* const EIGHT_BIT = "8bit";
|
||||
const char* const BASE64 = "base64";
|
||||
@ -84,16 +83,16 @@ namespace encodingTypes
|
||||
|
||||
|
||||
// Content disposition types
|
||||
namespace contentDispositionTypes
|
||||
{
|
||||
namespace contentDispositionTypes {
|
||||
|
||||
const char* const INLINE = "inline";
|
||||
const char* const ATTACHMENT = "attachment";
|
||||
}
|
||||
|
||||
|
||||
// Charsets
|
||||
namespace charsets
|
||||
{
|
||||
namespace charsets {
|
||||
|
||||
const char* const ISO8859_1 = "iso-8859-1";
|
||||
const char* const ISO8859_2 = "iso-8859-2";
|
||||
const char* const ISO8859_3 = "iso-8859-3";
|
||||
@ -159,8 +158,8 @@ namespace charsets
|
||||
|
||||
|
||||
// Fields
|
||||
namespace fields
|
||||
{
|
||||
namespace fields {
|
||||
|
||||
const char* const RECEIVED = "Received";
|
||||
const char* const FROM = "From";
|
||||
const char* const SENDER = "Sender";
|
||||
@ -204,32 +203,32 @@ namespace fields
|
||||
|
||||
|
||||
// Constants for disposition action modes (RFC-3978).
|
||||
namespace dispositionActionModes
|
||||
{
|
||||
namespace dispositionActionModes {
|
||||
|
||||
const char* const MANUAL = "manual";
|
||||
const char* const AUTOMATIC = "automatic";
|
||||
}
|
||||
|
||||
|
||||
// Constants for disposition sending modes (RFC-3798).
|
||||
namespace dispositionSendingModes
|
||||
{
|
||||
namespace dispositionSendingModes {
|
||||
|
||||
const char* const SENT_MANUALLY = "MDN-sent-manually";
|
||||
const char* const SENT_AUTOMATICALLY ="MDN-sent-automatically";
|
||||
}
|
||||
|
||||
|
||||
// Constants for disposition types (RFC-3798).
|
||||
namespace dispositionTypes
|
||||
{
|
||||
namespace dispositionTypes {
|
||||
|
||||
const char* const DISPLAYED = "displayed";
|
||||
const char* const DELETED = "deleted";
|
||||
}
|
||||
|
||||
|
||||
// Constants for disposition modifiers (RFC-3798).
|
||||
namespace dispositionModifiers
|
||||
{
|
||||
namespace dispositionModifiers {
|
||||
|
||||
const char* const ERROR = "error";
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -37,11 +37,11 @@
|
||||
#endif
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
/** Constants for media types. */
|
||||
namespace mediaTypes
|
||||
{
|
||||
namespace mediaTypes {
|
||||
|
||||
// Types
|
||||
extern VMIME_EXPORT const char* const TEXT;
|
||||
extern VMIME_EXPORT const char* const MULTIPART;
|
||||
@ -83,8 +83,8 @@ namespace vmime
|
||||
|
||||
|
||||
/** Constants for encoding types. */
|
||||
namespace encodingTypes
|
||||
{
|
||||
namespace encodingTypes {
|
||||
|
||||
extern VMIME_EXPORT const char* const SEVEN_BIT;
|
||||
extern VMIME_EXPORT const char* const EIGHT_BIT;
|
||||
extern VMIME_EXPORT const char* const BASE64;
|
||||
@ -95,16 +95,16 @@ namespace vmime
|
||||
|
||||
|
||||
/** Constants for content disposition types (RFC-2183). */
|
||||
namespace contentDispositionTypes
|
||||
{
|
||||
namespace contentDispositionTypes {
|
||||
|
||||
extern VMIME_EXPORT const char* const INLINE;
|
||||
extern VMIME_EXPORT const char* const ATTACHMENT;
|
||||
}
|
||||
|
||||
|
||||
/** Constants for charsets. */
|
||||
namespace charsets
|
||||
{
|
||||
namespace charsets {
|
||||
|
||||
extern VMIME_EXPORT const char* const ISO8859_1;
|
||||
extern VMIME_EXPORT const char* const ISO8859_2;
|
||||
extern VMIME_EXPORT const char* const ISO8859_3;
|
||||
@ -169,8 +169,8 @@ namespace vmime
|
||||
}
|
||||
|
||||
/** Constants for standard field names. */
|
||||
namespace fields
|
||||
{
|
||||
namespace fields {
|
||||
|
||||
extern VMIME_EXPORT const char* const RECEIVED;
|
||||
extern VMIME_EXPORT const char* const FROM;
|
||||
extern VMIME_EXPORT const char* const SENDER;
|
||||
@ -213,8 +213,8 @@ namespace vmime
|
||||
}
|
||||
|
||||
/** Constants for disposition action modes (RFC-3978). */
|
||||
namespace dispositionActionModes
|
||||
{
|
||||
namespace dispositionActionModes {
|
||||
|
||||
/** User implicitely displayed or deleted the message (filter or
|
||||
* any other automatic action). */
|
||||
extern VMIME_EXPORT const char* const AUTOMATIC;
|
||||
@ -224,8 +224,8 @@ namespace vmime
|
||||
}
|
||||
|
||||
/** Constants for disposition sending modes (RFC-3798). */
|
||||
namespace dispositionSendingModes
|
||||
{
|
||||
namespace dispositionSendingModes {
|
||||
|
||||
/** The MDN was sent because the MUA had previously been configured
|
||||
* to do so automatically. */
|
||||
extern VMIME_EXPORT const char* const SENT_AUTOMATICALLY;
|
||||
@ -235,8 +235,8 @@ namespace vmime
|
||||
}
|
||||
|
||||
/** Constants for disposition types (RFC-3798). */
|
||||
namespace dispositionTypes
|
||||
{
|
||||
namespace dispositionTypes {
|
||||
|
||||
/** Message has been displayed to the user. */
|
||||
extern VMIME_EXPORT const char* const DISPLAYED;
|
||||
/** Message has been deleted without being displayed. */
|
||||
@ -246,8 +246,8 @@ namespace vmime
|
||||
}
|
||||
|
||||
/** Constants for disposition modifiers (RFC-3798). */
|
||||
namespace dispositionModifiers
|
||||
{
|
||||
namespace dispositionModifiers {
|
||||
|
||||
extern VMIME_EXPORT const char* const ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -25,107 +25,118 @@
|
||||
#include "vmime/utility/stringUtils.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
contentDisposition::contentDisposition()
|
||||
: m_name(contentDispositionTypes::INLINE)
|
||||
{
|
||||
: m_name(contentDispositionTypes::INLINE) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
contentDisposition::contentDisposition(const string& name)
|
||||
: m_name(utility::stringUtils::toLower(name))
|
||||
{
|
||||
: m_name(utility::stringUtils::toLower(name)) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
contentDisposition::contentDisposition(const contentDisposition& type)
|
||||
: headerFieldValue(), m_name(type.m_name)
|
||||
{
|
||||
: headerFieldValue(), m_name(type.m_name) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void contentDisposition::parseImpl
|
||||
(const parsingContext& /* ctx */, const string& buffer, const size_t position,
|
||||
const size_t end, size_t* newPosition)
|
||||
{
|
||||
m_name = utility::stringUtils::trim(utility::stringUtils::toLower
|
||||
(string(buffer.begin() + position, buffer.begin() + end)));
|
||||
void contentDisposition::parseImpl(
|
||||
const parsingContext& /* ctx */,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition
|
||||
) {
|
||||
|
||||
m_name = utility::stringUtils::trim(
|
||||
utility::stringUtils::toLower(
|
||||
string(buffer.begin() + position, buffer.begin() + end)
|
||||
)
|
||||
);
|
||||
|
||||
setParsedBounds(position, end);
|
||||
|
||||
if (newPosition)
|
||||
if (newPosition) {
|
||||
*newPosition = end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void contentDisposition::generateImpl
|
||||
(const generationContext& /* ctx */, utility::outputStream& os,
|
||||
const size_t curLinePos, size_t* newLinePos) const
|
||||
{
|
||||
void contentDisposition::generateImpl(
|
||||
const generationContext& /* ctx */,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos,
|
||||
size_t* newLinePos
|
||||
) const {
|
||||
|
||||
os << m_name;
|
||||
|
||||
if (newLinePos)
|
||||
if (newLinePos) {
|
||||
*newLinePos = curLinePos + m_name.length();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contentDisposition& contentDisposition::operator=(const string& name)
|
||||
{
|
||||
contentDisposition& contentDisposition::operator=(const string& name) {
|
||||
|
||||
m_name = utility::stringUtils::toLower(name);
|
||||
return (*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool contentDisposition::operator==(const contentDisposition& value) const
|
||||
{
|
||||
return (utility::stringUtils::toLower(m_name) == value.m_name);
|
||||
bool contentDisposition::operator==(const contentDisposition& value) const {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <component> contentDisposition::clone() const
|
||||
{
|
||||
shared_ptr <component> contentDisposition::clone() const {
|
||||
|
||||
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);
|
||||
|
||||
m_name = d.m_name;
|
||||
}
|
||||
|
||||
|
||||
contentDisposition& contentDisposition::operator=(const contentDisposition& other)
|
||||
{
|
||||
contentDisposition& contentDisposition::operator=(const contentDisposition& other) {
|
||||
|
||||
copyFrom(other);
|
||||
return (*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
const string& contentDisposition::getName() const
|
||||
{
|
||||
return (m_name);
|
||||
const string& contentDisposition::getName() const {
|
||||
|
||||
return m_name;
|
||||
}
|
||||
|
||||
|
||||
void contentDisposition::setName(const string& name)
|
||||
{
|
||||
void contentDisposition::setName(const string& 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> >();
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -29,15 +29,13 @@
|
||||
#include "vmime/headerFieldValue.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** Content disposition (basic type).
|
||||
*/
|
||||
class VMIME_EXPORT contentDisposition : public headerFieldValue {
|
||||
|
||||
class VMIME_EXPORT contentDisposition : public headerFieldValue
|
||||
{
|
||||
public:
|
||||
|
||||
contentDisposition();
|
||||
@ -78,18 +76,20 @@ private:
|
||||
protected:
|
||||
|
||||
// Component parsing & assembling
|
||||
void parseImpl
|
||||
(const parsingContext& ctx,
|
||||
void parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
void generateImpl
|
||||
(const generationContext& ctx,
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
size_t* newLinePos = NULL) const;
|
||||
size_t* newLinePos = NULL
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -25,132 +25,136 @@
|
||||
#include "vmime/exception.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
contentDispositionField::contentDispositionField()
|
||||
{
|
||||
contentDispositionField::contentDispositionField() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
contentDispositionField::contentDispositionField(contentDispositionField&)
|
||||
: parameterizedHeaderField()
|
||||
{
|
||||
: parameterizedHeaderField() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool contentDispositionField::hasCreationDate() const
|
||||
{
|
||||
bool contentDispositionField::hasCreationDate() const {
|
||||
|
||||
return hasParameter("creation-date");
|
||||
}
|
||||
|
||||
|
||||
const datetime contentDispositionField::getCreationDate() const
|
||||
{
|
||||
const datetime contentDispositionField::getCreationDate() const {
|
||||
|
||||
shared_ptr <parameter> param = findParameter("creation-date");
|
||||
|
||||
if (param)
|
||||
if (param) {
|
||||
return param->getValueAs <datetime>();
|
||||
else
|
||||
} else {
|
||||
return datetime::now();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void contentDispositionField::setCreationDate(const datetime& creationDate)
|
||||
{
|
||||
void contentDispositionField::setCreationDate(const datetime& creationDate) {
|
||||
|
||||
getParameter("creation-date")->setValue(creationDate);
|
||||
}
|
||||
|
||||
|
||||
bool contentDispositionField::hasModificationDate() const
|
||||
{
|
||||
bool contentDispositionField::hasModificationDate() const {
|
||||
|
||||
return hasParameter("modification-date");
|
||||
}
|
||||
|
||||
|
||||
const datetime contentDispositionField::getModificationDate() const
|
||||
{
|
||||
const datetime contentDispositionField::getModificationDate() const {
|
||||
|
||||
shared_ptr <parameter> param = findParameter("modification-date");
|
||||
|
||||
if (param)
|
||||
if (param) {
|
||||
return param->getValueAs <datetime>();
|
||||
else
|
||||
} else {
|
||||
return datetime::now();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void contentDispositionField::setModificationDate(const datetime& modificationDate)
|
||||
{
|
||||
void contentDispositionField::setModificationDate(const datetime& modificationDate) {
|
||||
|
||||
getParameter("modification-date")->setValue(modificationDate);
|
||||
}
|
||||
|
||||
|
||||
bool contentDispositionField::hasReadDate() const
|
||||
{
|
||||
bool contentDispositionField::hasReadDate() const {
|
||||
|
||||
return hasParameter("read-date");
|
||||
}
|
||||
|
||||
|
||||
const datetime contentDispositionField::getReadDate() const
|
||||
{
|
||||
const datetime contentDispositionField::getReadDate() const {
|
||||
|
||||
shared_ptr <parameter> param = findParameter("read-date");
|
||||
|
||||
if (param)
|
||||
if (param) {
|
||||
return param->getValueAs <datetime>();
|
||||
else
|
||||
} else {
|
||||
return datetime::now();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void contentDispositionField::setReadDate(const datetime& readDate)
|
||||
{
|
||||
void contentDispositionField::setReadDate(const datetime& readDate) {
|
||||
|
||||
getParameter("read-date")->setValue(readDate);
|
||||
}
|
||||
|
||||
|
||||
bool contentDispositionField::hasFilename() const
|
||||
{
|
||||
bool contentDispositionField::hasFilename() const {
|
||||
|
||||
return hasParameter("filename");
|
||||
}
|
||||
|
||||
|
||||
const word contentDispositionField::getFilename() const
|
||||
{
|
||||
const word contentDispositionField::getFilename() const {
|
||||
|
||||
shared_ptr <parameter> param = findParameter("filename");
|
||||
|
||||
if (param)
|
||||
if (param) {
|
||||
return param->getValue();
|
||||
else
|
||||
} else {
|
||||
return word();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void contentDispositionField::setFilename(const word& filename)
|
||||
{
|
||||
void contentDispositionField::setFilename(const word& filename) {
|
||||
|
||||
getParameter("filename")->setValue(filename);
|
||||
}
|
||||
|
||||
|
||||
bool contentDispositionField::hasSize() const
|
||||
{
|
||||
bool contentDispositionField::hasSize() const {
|
||||
|
||||
return hasParameter("size");
|
||||
}
|
||||
|
||||
|
||||
const string contentDispositionField::getSize() const
|
||||
{
|
||||
const string contentDispositionField::getSize() const {
|
||||
|
||||
shared_ptr <parameter> param = findParameter("size");
|
||||
|
||||
if (param)
|
||||
if (param) {
|
||||
return param->getValue().getBuffer();
|
||||
else
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void contentDispositionField::setSize(const string& size)
|
||||
{
|
||||
void contentDispositionField::setSize(const string& size) {
|
||||
|
||||
getParameter("size")->setValue(word(size, vmime::charsets::US_ASCII));
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -32,15 +32,13 @@
|
||||
#include "vmime/word.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** Describes presentation information, as per RFC-2183.
|
||||
*/
|
||||
class VMIME_EXPORT contentDispositionField : public parameterizedHeaderField {
|
||||
|
||||
class VMIME_EXPORT contentDispositionField : public parameterizedHeaderField
|
||||
{
|
||||
friend class headerFieldFactory;
|
||||
|
||||
protected:
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -24,16 +24,15 @@
|
||||
#include "vmime/contentHandler.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
// No encoding = "binary" encoding
|
||||
const encoding contentHandler::NO_ENCODING(encodingTypes::BINARY);
|
||||
|
||||
|
||||
contentHandler::~contentHandler()
|
||||
{
|
||||
contentHandler::~contentHandler() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -34,12 +34,11 @@
|
||||
#include "vmime/mediaType.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
class VMIME_EXPORT contentHandler : public object
|
||||
{
|
||||
class VMIME_EXPORT contentHandler : public object {
|
||||
|
||||
public:
|
||||
|
||||
/** Used to specify that enclosed data is not encoded. */
|
||||
@ -63,7 +62,11 @@ public:
|
||||
* @param enc encoding 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
|
||||
* will be decoded before being written into the stream.
|
||||
@ -74,7 +77,10 @@ public:
|
||||
* @param progress progress listener, or NULL if you do not
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* length was specified when setting data of this object, or if the
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -25,89 +25,90 @@
|
||||
#include "vmime/exception.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
contentTypeField::contentTypeField()
|
||||
{
|
||||
contentTypeField::contentTypeField() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
contentTypeField::contentTypeField(contentTypeField&)
|
||||
: parameterizedHeaderField()
|
||||
{
|
||||
: parameterizedHeaderField() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool contentTypeField::hasBoundary() const
|
||||
{
|
||||
bool contentTypeField::hasBoundary() const {
|
||||
|
||||
return hasParameter("boundary");
|
||||
}
|
||||
|
||||
|
||||
const string contentTypeField::getBoundary() const
|
||||
{
|
||||
const string contentTypeField::getBoundary() const {
|
||||
|
||||
shared_ptr <parameter> param = findParameter("boundary");
|
||||
|
||||
if (param)
|
||||
if (param) {
|
||||
return param->getValue().getBuffer();
|
||||
else
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void contentTypeField::setBoundary(const string& boundary)
|
||||
{
|
||||
void contentTypeField::setBoundary(const string& boundary) {
|
||||
|
||||
getParameter("boundary")->setValue(word(boundary, vmime::charsets::US_ASCII));
|
||||
}
|
||||
|
||||
|
||||
bool contentTypeField::hasCharset() const
|
||||
{
|
||||
bool contentTypeField::hasCharset() const {
|
||||
|
||||
return hasParameter("charset");
|
||||
}
|
||||
|
||||
|
||||
const charset contentTypeField::getCharset() const
|
||||
{
|
||||
const charset contentTypeField::getCharset() const {
|
||||
|
||||
shared_ptr <parameter> param = findParameter("charset");
|
||||
|
||||
if (param)
|
||||
if (param) {
|
||||
return param->getValueAs <charset>();
|
||||
else
|
||||
} else {
|
||||
return charset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void contentTypeField::setCharset(const charset& ch)
|
||||
{
|
||||
void contentTypeField::setCharset(const charset& ch) {
|
||||
|
||||
getParameter("charset")->setValue(ch);
|
||||
}
|
||||
|
||||
|
||||
bool contentTypeField::hasReportType() const
|
||||
{
|
||||
bool contentTypeField::hasReportType() const {
|
||||
|
||||
return hasParameter("report-type");
|
||||
}
|
||||
|
||||
|
||||
const string contentTypeField::getReportType() const
|
||||
{
|
||||
const string contentTypeField::getReportType() const {
|
||||
|
||||
shared_ptr <parameter> param = findParameter("report-type");
|
||||
|
||||
if (param)
|
||||
if (param) {
|
||||
return param->getValue().getBuffer();
|
||||
else
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void contentTypeField::setReportType(const string& reportType)
|
||||
{
|
||||
void contentTypeField::setReportType(const string& reportType) {
|
||||
|
||||
getParameter("report-type")->setValue(word(reportType, vmime::charsets::US_ASCII));
|
||||
}
|
||||
|
||||
|
||||
} // vmime
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -31,12 +31,11 @@
|
||||
#include "vmime/charset.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
class VMIME_EXPORT contentTypeField : public parameterizedHeaderField
|
||||
{
|
||||
class VMIME_EXPORT contentTypeField : public parameterizedHeaderField {
|
||||
|
||||
friend class headerFieldFactory;
|
||||
|
||||
protected:
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -24,61 +24,60 @@
|
||||
#include "vmime/context.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
context::context()
|
||||
: m_internationalizedEmail(false)
|
||||
{
|
||||
: m_internationalizedEmail(false) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
context::context(const context& ctx)
|
||||
: 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;
|
||||
}
|
||||
|
||||
|
||||
void context::setInternationalizedEmailSupport(const bool support)
|
||||
{
|
||||
void context::setInternationalizedEmailSupport(const bool support) {
|
||||
|
||||
m_internationalizedEmail = support;
|
||||
}
|
||||
|
||||
|
||||
const charsetConverterOptions& context::getCharsetConversionOptions() const
|
||||
{
|
||||
const charsetConverterOptions& context::getCharsetConversionOptions() const {
|
||||
|
||||
return m_charsetConvOptions;
|
||||
}
|
||||
|
||||
|
||||
void context::setCharsetConversionOptions(const charsetConverterOptions& opts)
|
||||
{
|
||||
void context::setCharsetConversionOptions(const charsetConverterOptions& opts) {
|
||||
|
||||
m_charsetConvOptions = opts;
|
||||
}
|
||||
|
||||
|
||||
context& context::operator=(const context& ctx)
|
||||
{
|
||||
context& context::operator=(const context& ctx) {
|
||||
|
||||
copyFrom(ctx);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void context::copyFrom(const context& ctx)
|
||||
{
|
||||
void context::copyFrom(const context& ctx) {
|
||||
|
||||
m_internationalizedEmail = ctx.m_internationalizedEmail;
|
||||
m_charsetConvOptions = ctx.m_charsetConvOptions;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -29,15 +29,13 @@
|
||||
#include "vmime/charsetConverterOptions.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** Holds configuration parameters used either for parsing or generating messages.
|
||||
*/
|
||||
class VMIME_EXPORT context : public object {
|
||||
|
||||
class VMIME_EXPORT context : public object
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~context();
|
||||
@ -74,8 +72,8 @@ public:
|
||||
/** Switches between contexts temporarily.
|
||||
*/
|
||||
template <typename CTX_CLASS>
|
||||
class switcher
|
||||
{
|
||||
class switcher {
|
||||
|
||||
public:
|
||||
|
||||
/** Switches to the specified context.
|
||||
@ -85,15 +83,15 @@ public:
|
||||
* @param newCtx new context
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/** Restores back saved context.
|
||||
*/
|
||||
~switcher()
|
||||
{
|
||||
~switcher() {
|
||||
|
||||
CTX_CLASS::getDefaultContext().copyFrom(m_oldCtxData);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -31,21 +31,31 @@
|
||||
#include <ctime>
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** Date and time (basic type).
|
||||
*/
|
||||
class VMIME_EXPORT datetime : public headerFieldValue {
|
||||
|
||||
class VMIME_EXPORT datetime : public headerFieldValue
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
datetime();
|
||||
datetime(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 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 string& date);
|
||||
datetime(const time_t t, const int zone = GMT);
|
||||
@ -54,8 +64,8 @@ public:
|
||||
~datetime();
|
||||
|
||||
// Some time zones (in minutes)
|
||||
enum TimeZones
|
||||
{
|
||||
enum TimeZones {
|
||||
|
||||
GMT_12 = -720, // GMT-12h
|
||||
GMT_11 = -660, // GMT-11h
|
||||
GMT_10 = -600, // GMT-10h
|
||||
@ -124,8 +134,8 @@ public:
|
||||
};
|
||||
|
||||
// Months list
|
||||
enum Months
|
||||
{
|
||||
enum Months {
|
||||
|
||||
// Long
|
||||
JANUARY = 1,
|
||||
FEBRUARY = 2,
|
||||
@ -155,8 +165,8 @@ public:
|
||||
};
|
||||
|
||||
// Days of week list
|
||||
enum DaysOfWeek
|
||||
{
|
||||
enum DaysOfWeek {
|
||||
|
||||
// Long
|
||||
SUNDAY = 0,
|
||||
MONDAY = 1,
|
||||
@ -242,18 +252,20 @@ public:
|
||||
protected:
|
||||
|
||||
// Component parsing & assembling
|
||||
void parseImpl
|
||||
(const parsingContext& ctx,
|
||||
void parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
void generateImpl
|
||||
(const generationContext& ctx,
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
size_t* newLinePos = NULL) const;
|
||||
size_t* newLinePos = NULL
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -28,57 +28,75 @@
|
||||
#include "vmime/encoding.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
defaultAttachment::defaultAttachment()
|
||||
{
|
||||
defaultAttachment::defaultAttachment() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
defaultAttachment::defaultAttachment(shared_ptr <const contentHandler> data,
|
||||
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(
|
||||
const shared_ptr <const contentHandler>& data,
|
||||
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,
|
||||
const mediaType& type, 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 shared_ptr <const contentHandler>& data,
|
||||
const mediaType& type,
|
||||
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)
|
||||
: 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_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_desc = attach.m_desc;
|
||||
m_name = attach.m_name;
|
||||
m_data = vmime::clone(attach.m_data);
|
||||
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
|
||||
shared_ptr <bodyPart> part = make_shared <bodyPart>();
|
||||
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
|
||||
part->getHeader()->ContentType()->setValue(m_type);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
const text defaultAttachment::getDescription() const
|
||||
{
|
||||
const text defaultAttachment::getDescription() const {
|
||||
|
||||
return m_desc;
|
||||
}
|
||||
|
||||
|
||||
const word defaultAttachment::getName() const
|
||||
{
|
||||
const word defaultAttachment::getName() const {
|
||||
|
||||
return m_name;
|
||||
}
|
||||
|
||||
|
||||
const shared_ptr <const contentHandler> defaultAttachment::getData() const
|
||||
{
|
||||
const shared_ptr <const contentHandler> defaultAttachment::getData() const {
|
||||
|
||||
return m_data;
|
||||
}
|
||||
|
||||
|
||||
const encoding defaultAttachment::getEncoding() const
|
||||
{
|
||||
const encoding defaultAttachment::getEncoding() const {
|
||||
|
||||
return m_encoding;
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <const object> defaultAttachment::getPart() const
|
||||
{
|
||||
shared_ptr <const object> defaultAttachment::getPart() const {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <const header> defaultAttachment::getHeader() const
|
||||
{
|
||||
shared_ptr <const header> defaultAttachment::getHeader() const {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -29,15 +29,13 @@
|
||||
#include "vmime/encoding.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** Default implementation for attachments.
|
||||
*/
|
||||
class VMIME_EXPORT defaultAttachment : public attachment {
|
||||
|
||||
class VMIME_EXPORT defaultAttachment : public attachment
|
||||
{
|
||||
protected:
|
||||
|
||||
// For use in derived classes.
|
||||
@ -45,8 +43,21 @@ protected:
|
||||
|
||||
public:
|
||||
|
||||
defaultAttachment(shared_ptr <const contentHandler> data, const encoding& enc, const mediaType& type, const text& desc = NULL_TEXT, const word& name = NULL_WORD);
|
||||
defaultAttachment(shared_ptr <const contentHandler> data, const mediaType& type, const text& desc = NULL_TEXT, const word& name = NULL_WORD);
|
||||
defaultAttachment(
|
||||
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();
|
||||
@ -74,11 +85,11 @@ protected:
|
||||
private:
|
||||
|
||||
// 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:
|
||||
|
||||
virtual void generatePart(shared_ptr <bodyPart> part) const;
|
||||
virtual void generatePart(const shared_ptr <bodyPart>& part) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -27,25 +27,30 @@
|
||||
#include "vmime/utility/stringUtils.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
disposition::disposition()
|
||||
{
|
||||
disposition::disposition() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
disposition::disposition(const string& actionMode, const string& sendingMode,
|
||||
const string& type, const string& modifier)
|
||||
: m_actionMode(actionMode), m_sendingMode(sendingMode), m_type(type)
|
||||
{
|
||||
disposition::disposition(
|
||||
const string& actionMode,
|
||||
const string& sendingMode,
|
||||
const string& type,
|
||||
const string& modifier
|
||||
)
|
||||
: m_actionMode(actionMode),
|
||||
m_sendingMode(sendingMode),
|
||||
m_type(type) {
|
||||
|
||||
m_modifiers.push_back(modifier);
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <component> disposition::clone() const
|
||||
{
|
||||
shared_ptr <component> disposition::clone() const {
|
||||
|
||||
shared_ptr <disposition> disp = make_shared <disposition>();
|
||||
|
||||
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());
|
||||
|
||||
return (disp);
|
||||
return disp;
|
||||
}
|
||||
|
||||
|
||||
void disposition::copyFrom(const component& other)
|
||||
{
|
||||
void disposition::copyFrom(const component& other) {
|
||||
|
||||
const disposition& disp = dynamic_cast <const disposition&>(other);
|
||||
|
||||
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);
|
||||
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> >();
|
||||
}
|
||||
|
||||
|
||||
void disposition::setActionMode(const string& mode)
|
||||
{
|
||||
void disposition::setActionMode(const string& mode) {
|
||||
|
||||
m_actionMode = mode;
|
||||
}
|
||||
|
||||
|
||||
const string& disposition::getActionMode() const
|
||||
{
|
||||
return (m_actionMode);
|
||||
const string& disposition::getActionMode() const {
|
||||
|
||||
return m_actionMode;
|
||||
}
|
||||
|
||||
|
||||
void disposition::setSendingMode(const string& mode)
|
||||
{
|
||||
void disposition::setSendingMode(const string& mode) {
|
||||
|
||||
m_sendingMode = mode;
|
||||
}
|
||||
|
||||
|
||||
const string& disposition::getSendingMode() const
|
||||
{
|
||||
return (m_sendingMode);
|
||||
const string& disposition::getSendingMode() const {
|
||||
|
||||
return m_sendingMode;
|
||||
}
|
||||
|
||||
|
||||
void disposition::setType(const string& type)
|
||||
{
|
||||
void disposition::setType(const string& type) {
|
||||
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
|
||||
const string& disposition::getType() const
|
||||
{
|
||||
return (m_type);
|
||||
const string& disposition::getType() const {
|
||||
|
||||
return m_type;
|
||||
}
|
||||
|
||||
|
||||
void disposition::addModifier(const string& modifier)
|
||||
{
|
||||
if (!hasModifier(modifier))
|
||||
void disposition::addModifier(const string& modifier) {
|
||||
|
||||
if (!hasModifier(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);
|
||||
|
||||
for (std::vector <string>::iterator it = m_modifiers.begin() ;
|
||||
it != m_modifiers.end() ; ++it)
|
||||
{
|
||||
if (*it == modifierLC)
|
||||
{
|
||||
it != m_modifiers.end() ; ++it) {
|
||||
|
||||
if (*it == modifierLC) {
|
||||
m_modifiers.erase(it);
|
||||
break;
|
||||
}
|
||||
@ -144,37 +149,42 @@ void disposition::removeModifier(const string& modifier)
|
||||
}
|
||||
|
||||
|
||||
void disposition::removeAllModifiers()
|
||||
{
|
||||
void disposition::removeAllModifiers() {
|
||||
|
||||
m_modifiers.clear();
|
||||
}
|
||||
|
||||
|
||||
bool disposition::hasModifier(const string& modifier) const
|
||||
{
|
||||
bool disposition::hasModifier(const string& modifier) const {
|
||||
|
||||
const string modifierLC = utility::stringUtils::toLower(modifier);
|
||||
|
||||
for (std::vector <string>::const_iterator it = m_modifiers.begin() ;
|
||||
it != m_modifiers.end() ; ++it)
|
||||
{
|
||||
if (*it == modifierLC)
|
||||
return (true);
|
||||
it != m_modifiers.end() ; ++it) {
|
||||
|
||||
if (*it == modifierLC) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return (false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const std::vector <string> disposition::getModifierList() const
|
||||
{
|
||||
return (m_modifiers);
|
||||
const std::vector <string> disposition::getModifierList() const {
|
||||
|
||||
return m_modifiers;
|
||||
}
|
||||
|
||||
|
||||
void disposition::parseImpl
|
||||
(const parsingContext& /* ctx */, const string& buffer, const size_t position,
|
||||
const size_t end, size_t* newPosition)
|
||||
{
|
||||
void disposition::parseImpl(
|
||||
const parsingContext& /* ctx */,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition
|
||||
) {
|
||||
|
||||
// disposition-mode ";" disposition-type
|
||||
// [ "/" disposition-modifier *( "," disposition-modifier ) ]
|
||||
//
|
||||
@ -182,105 +192,116 @@ void disposition::parseImpl
|
||||
|
||||
size_t pos = position;
|
||||
|
||||
while (pos < end && parserHelpers::isSpace(buffer[pos]))
|
||||
while (pos < end && parserHelpers::isSpace(buffer[pos])) {
|
||||
++pos;
|
||||
}
|
||||
|
||||
// -- disposition-mode
|
||||
const size_t modeStart = pos;
|
||||
size_t modeEnd = pos;
|
||||
|
||||
while (pos < end && buffer[pos] != ';')
|
||||
{
|
||||
while (pos < end && buffer[pos] != ';') {
|
||||
++modeEnd;
|
||||
++pos;
|
||||
}
|
||||
|
||||
while (modeEnd > modeStart && parserHelpers::isSpace(buffer[modeEnd - 1]))
|
||||
while (modeEnd > modeStart && parserHelpers::isSpace(buffer[modeEnd - 1])) {
|
||||
--modeEnd;
|
||||
}
|
||||
|
||||
const string mode = string(buffer.begin() + modeStart, buffer.begin() + modeEnd);
|
||||
const size_t slash = mode.find('/');
|
||||
|
||||
if (slash != string::npos)
|
||||
{
|
||||
if (slash != string::npos) {
|
||||
|
||||
m_actionMode = string(mode.begin(), mode.begin() + slash);
|
||||
m_sendingMode = string(mode.begin() + slash + 1, mode.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
m_actionMode = mode;
|
||||
m_sendingMode.clear();
|
||||
}
|
||||
|
||||
if (pos < end)
|
||||
{
|
||||
if (pos < end) {
|
||||
// Skip ';'
|
||||
++pos;
|
||||
}
|
||||
|
||||
while (pos < end && parserHelpers::isSpace(buffer[pos]))
|
||||
while (pos < end && parserHelpers::isSpace(buffer[pos])) {
|
||||
++pos;
|
||||
}
|
||||
|
||||
// -- disposition-type
|
||||
const size_t typeStart = pos;
|
||||
size_t typeEnd = pos;
|
||||
|
||||
while (pos < end && buffer[pos] != '/')
|
||||
{
|
||||
while (pos < end && buffer[pos] != '/') {
|
||||
++typeEnd;
|
||||
++pos;
|
||||
}
|
||||
|
||||
while (typeEnd > typeStart && parserHelpers::isSpace(buffer[typeEnd - 1]))
|
||||
while (typeEnd > typeStart && parserHelpers::isSpace(buffer[typeEnd - 1])) {
|
||||
--typeEnd;
|
||||
}
|
||||
|
||||
m_type = string(buffer.begin() + typeStart, buffer.begin() + typeEnd);
|
||||
|
||||
m_modifiers.clear();
|
||||
|
||||
if (pos < end) // modifiers follow
|
||||
{
|
||||
if (pos < end) { // modifiers follow
|
||||
|
||||
// Skip '/'
|
||||
++pos;
|
||||
|
||||
while (pos < end)
|
||||
{
|
||||
while (pos < end && parserHelpers::isSpace(buffer[pos]))
|
||||
while (pos < end) {
|
||||
|
||||
while (pos < end && parserHelpers::isSpace(buffer[pos])) {
|
||||
++pos;
|
||||
}
|
||||
|
||||
const size_t modifierStart = pos;
|
||||
size_t modifierEnd = pos;
|
||||
|
||||
while (pos < end && buffer[pos] != ',')
|
||||
{
|
||||
while (pos < end && buffer[pos] != ',') {
|
||||
++modifierEnd;
|
||||
++pos;
|
||||
}
|
||||
|
||||
while (modifierEnd > modifierStart && parserHelpers::isSpace(buffer[modifierEnd - 1]))
|
||||
while (modifierEnd > modifierStart && parserHelpers::isSpace(buffer[modifierEnd - 1])) {
|
||||
--modifierEnd;
|
||||
}
|
||||
|
||||
if (modifierEnd > modifierStart)
|
||||
{
|
||||
m_modifiers.push_back(string(buffer.begin() + modifierStart,
|
||||
buffer.begin() + modifierEnd));
|
||||
if (modifierEnd > modifierStart) {
|
||||
|
||||
m_modifiers.push_back(
|
||||
string(
|
||||
buffer.begin() + modifierStart,
|
||||
buffer.begin() + modifierEnd
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Skip ','
|
||||
if (pos < end)
|
||||
if (pos < end) {
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newPosition)
|
||||
if (newPosition) {
|
||||
*newPosition = pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void disposition::generateImpl
|
||||
(const generationContext& ctx, utility::outputStream& os,
|
||||
const size_t curLinePos, size_t* newLinePos) const
|
||||
{
|
||||
void disposition::generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos,
|
||||
size_t* newLinePos
|
||||
) const {
|
||||
|
||||
size_t pos = curLinePos;
|
||||
|
||||
const string actionMode = (m_actionMode.empty() ? "automatic-action" : m_actionMode);
|
||||
@ -289,8 +310,7 @@ void disposition::generateImpl
|
||||
os << actionMode << "/" << sendingMode << ";";
|
||||
pos += actionMode.length() + 1 + sendingMode.length() + 1;
|
||||
|
||||
if (pos > ctx.getMaxLineLength())
|
||||
{
|
||||
if (pos > ctx.getMaxLineLength()) {
|
||||
os << NEW_LINE_SEQUENCE;
|
||||
pos = NEW_LINE_SEQUENCE_LENGTH;
|
||||
}
|
||||
@ -300,18 +320,19 @@ void disposition::generateImpl
|
||||
os << type;
|
||||
pos += type.length();
|
||||
|
||||
if (m_modifiers.size() >= 1)
|
||||
{
|
||||
for (std::vector <string>::size_type i = 0, n = 0 ; i < m_modifiers.size() ; ++i)
|
||||
{
|
||||
if (m_modifiers.size() >= 1) {
|
||||
|
||||
for (std::vector <string>::size_type i = 0, n = 0 ; i < m_modifiers.size() ; ++i) {
|
||||
|
||||
const string mod = utility::stringUtils::trim(m_modifiers[i]);
|
||||
|
||||
if (!mod.empty())
|
||||
{
|
||||
if (n == 0)
|
||||
if (!mod.empty()) {
|
||||
|
||||
if (n == 0) {
|
||||
os << "/";
|
||||
else
|
||||
} else {
|
||||
os << ",";
|
||||
}
|
||||
|
||||
os << mod;
|
||||
pos += 1 + mod.length();
|
||||
@ -321,9 +342,10 @@ void disposition::generateImpl
|
||||
}
|
||||
}
|
||||
|
||||
if (newLinePos)
|
||||
if (newLinePos) {
|
||||
*newLinePos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -31,19 +31,22 @@
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** Disposition - from RFC-3798 (basic type).
|
||||
*/
|
||||
class VMIME_EXPORT disposition : public headerFieldValue {
|
||||
|
||||
class VMIME_EXPORT disposition : public headerFieldValue
|
||||
{
|
||||
public:
|
||||
|
||||
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;
|
||||
@ -137,18 +140,20 @@ private:
|
||||
protected:
|
||||
|
||||
// Component parsing & assembling
|
||||
void parseImpl
|
||||
(const parsingContext& ctx,
|
||||
void parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
void generateImpl
|
||||
(const generationContext& ctx,
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
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
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -31,8 +31,7 @@
|
||||
#include "vmime/utility/stringUtils.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** Decode an IDNA-encoded domain name ("xn--5rtw95l.xn--wgv71a")
|
||||
@ -41,48 +40,52 @@ namespace vmime
|
||||
* @param idnaDomain domain name encoded with IDNA
|
||||
* @return decoded domain name in UTF-8
|
||||
*/
|
||||
static const string domainNameFromIDNA(const string& idnaDomain)
|
||||
{
|
||||
static const string domainNameFromIDNA(const string& idnaDomain) {
|
||||
|
||||
std::ostringstream domainName;
|
||||
size_t p = 0;
|
||||
|
||||
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);
|
||||
|
||||
if (encodedPart.length() > 4 &&
|
||||
encodedPart[0] == 'x' && encodedPart[1] == 'n' &&
|
||||
encodedPart[2] == '-' && encodedPart[3] == '-')
|
||||
{
|
||||
encodedPart[2] == '-' && encodedPart[3] == '-') {
|
||||
|
||||
string decodedPart;
|
||||
charset::convert(encodedPart, decodedPart,
|
||||
vmime::charsets::IDNA, vmime::charsets::UTF_8);
|
||||
charset::convert(
|
||||
encodedPart, decodedPart,
|
||||
vmime::charsets::IDNA, vmime::charsets::UTF_8
|
||||
);
|
||||
|
||||
domainName << decodedPart << '.';
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
domainName << encodedPart << '.'; // not encoded
|
||||
}
|
||||
}
|
||||
|
||||
if (p < idnaDomain.length())
|
||||
{
|
||||
if (p < idnaDomain.length()) {
|
||||
|
||||
const string encodedPart(idnaDomain.begin() + p, idnaDomain.end());
|
||||
|
||||
if (encodedPart.length() > 4 &&
|
||||
encodedPart[0] == 'x' && encodedPart[1] == 'n' &&
|
||||
encodedPart[2] == '-' && encodedPart[3] == '-')
|
||||
{
|
||||
encodedPart[2] == '-' && encodedPart[3] == '-') {
|
||||
|
||||
string decodedPart;
|
||||
charset::convert(encodedPart, decodedPart,
|
||||
vmime::charsets::IDNA, vmime::charsets::UTF_8);
|
||||
charset::convert(
|
||||
encodedPart, decodedPart,
|
||||
vmime::charsets::IDNA, vmime::charsets::UTF_8
|
||||
);
|
||||
|
||||
domainName << decodedPart;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
domainName << encodedPart; // not encoded
|
||||
}
|
||||
}
|
||||
@ -97,26 +100,30 @@ static const string domainNameFromIDNA(const string& idnaDomain)
|
||||
* @param domainName domain name in UTF-8
|
||||
* @return domain name encoded with IDNA
|
||||
*/
|
||||
static const string domainNameToIDNA(const string& domainName)
|
||||
{
|
||||
static const string domainNameToIDNA(const string& domainName) {
|
||||
|
||||
std::ostringstream idnaDomain;
|
||||
size_t p = 0;
|
||||
|
||||
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;
|
||||
charset::convert(string(domainName.begin() + p, domainName.begin() + n),
|
||||
idnaPart, vmime::charsets::UTF_8, vmime::charsets::IDNA);
|
||||
charset::convert(
|
||||
string(domainName.begin() + p, domainName.begin() + n), idnaPart,
|
||||
vmime::charsets::UTF_8, vmime::charsets::IDNA
|
||||
);
|
||||
|
||||
idnaDomain << idnaPart << '.';
|
||||
}
|
||||
|
||||
if (p < domainName.length())
|
||||
{
|
||||
if (p < domainName.length()) {
|
||||
|
||||
string idnaPart;
|
||||
charset::convert(string(domainName.begin() + p, domainName.end()),
|
||||
idnaPart, vmime::charsets::UTF_8, vmime::charsets::IDNA);
|
||||
charset::convert(
|
||||
string(domainName.begin() + p, domainName.end()), idnaPart,
|
||||
vmime::charsets::UTF_8, vmime::charsets::IDNA
|
||||
);
|
||||
|
||||
idnaDomain << idnaPart;
|
||||
}
|
||||
@ -127,52 +134,60 @@ static const string domainNameToIDNA(const string& domainName)
|
||||
|
||||
|
||||
|
||||
emailAddress::emailAddress()
|
||||
{
|
||||
emailAddress::emailAddress() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
emailAddress::emailAddress(const char* email)
|
||||
{
|
||||
emailAddress::emailAddress(const char* email) {
|
||||
|
||||
parse(email);
|
||||
}
|
||||
|
||||
|
||||
emailAddress::emailAddress(const string& localName, const string& domainName)
|
||||
: component(), m_localName(word(localName, vmime::charsets::UTF_8)),
|
||||
m_domainName(word(domainName, vmime::charsets::UTF_8))
|
||||
{
|
||||
: component(),
|
||||
m_localName(word(localName, vmime::charsets::UTF_8)),
|
||||
m_domainName(word(domainName, vmime::charsets::UTF_8)) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
(const parsingContext& /* ctx */, const string& buffer, const size_t position,
|
||||
const size_t end, size_t* newPosition)
|
||||
{
|
||||
void emailAddress::parseImpl(
|
||||
const parsingContext& /* ctx */,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition
|
||||
) {
|
||||
|
||||
const char* const pend = buffer.data() + end;
|
||||
const char* const pstart = buffer.data() + position;
|
||||
const char* p = pstart;
|
||||
|
||||
enum ParserStates
|
||||
{
|
||||
enum ParserStates {
|
||||
State_Before,
|
||||
State_LocalPartStart,
|
||||
State_LocalPartMiddle,
|
||||
@ -199,45 +214,47 @@ void emailAddress::parseImpl
|
||||
int commentLevel = 0;
|
||||
bool localPartIsRFC2047 = false;
|
||||
|
||||
while (p < pend && !stop)
|
||||
{
|
||||
while (p < pend && !stop) {
|
||||
|
||||
const char c = *p;
|
||||
|
||||
if ((localPart.str().length() + domainPart.str().length()) >= 256)
|
||||
{
|
||||
if ((localPart.str().length() + domainPart.str().length()) >= 256) {
|
||||
state = State_Error;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (state)
|
||||
{
|
||||
switch (state) {
|
||||
|
||||
case State_Before:
|
||||
|
||||
if (parserHelpers::isSpace(c))
|
||||
if (parserHelpers::isSpace(c)) {
|
||||
++p;
|
||||
else
|
||||
} else {
|
||||
state = State_LocalPartStart;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case State_LocalPartStart:
|
||||
|
||||
if (c == '"')
|
||||
{
|
||||
if (c == '"') {
|
||||
|
||||
state = State_LocalPartQuoted;
|
||||
++p;
|
||||
}
|
||||
else if (c == '=')
|
||||
{
|
||||
|
||||
} else if (c == '=') {
|
||||
|
||||
state = State_LocalPartRFC2047Start;
|
||||
++p;
|
||||
}
|
||||
else if (c == '(')
|
||||
{
|
||||
|
||||
} else if (c == '(') {
|
||||
|
||||
state = State_LocalPartComment;
|
||||
++commentLevel;
|
||||
++p;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
state = State_LocalPartMiddle;
|
||||
localPart << c;
|
||||
++p;
|
||||
@ -247,33 +264,32 @@ void emailAddress::parseImpl
|
||||
|
||||
case State_LocalPartComment:
|
||||
|
||||
if (escapeNext)
|
||||
{
|
||||
if (escapeNext) {
|
||||
|
||||
escapeNext = false;
|
||||
++p;
|
||||
}
|
||||
else if (c == '\\')
|
||||
{
|
||||
|
||||
} else if (c == '\\') {
|
||||
|
||||
escapeNext = true;
|
||||
++p;
|
||||
}
|
||||
else if (c == '(')
|
||||
{
|
||||
|
||||
} else if (c == '(') {
|
||||
|
||||
++commentLevel;
|
||||
++p;
|
||||
}
|
||||
else if (c == ')')
|
||||
{
|
||||
if (--commentLevel == 0)
|
||||
{
|
||||
|
||||
} else if (c == ')') {
|
||||
|
||||
if (--commentLevel == 0) {
|
||||
// End of comment
|
||||
state = State_LocalPartMiddle;
|
||||
}
|
||||
|
||||
++p;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// Comment continues
|
||||
++p;
|
||||
}
|
||||
@ -282,34 +298,34 @@ void emailAddress::parseImpl
|
||||
|
||||
case State_LocalPartQuoted:
|
||||
|
||||
if (escapeNext)
|
||||
{
|
||||
if (escapeNext) {
|
||||
|
||||
escapeNext = false;
|
||||
|
||||
if (c == '"' || c == '\\')
|
||||
{
|
||||
if (c == '"' || c == '\\') {
|
||||
|
||||
localPart << c;
|
||||
++p;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// This char cannot be escaped
|
||||
state = State_Error;
|
||||
}
|
||||
}
|
||||
else if (c == '"')
|
||||
{
|
||||
|
||||
} else if (c == '"') {
|
||||
|
||||
// End of quoted string
|
||||
state = State_LocalPartMiddle;
|
||||
++p;
|
||||
}
|
||||
else if (c == '\\')
|
||||
{
|
||||
|
||||
} else if (c == '\\') {
|
||||
|
||||
escapeNext = true;
|
||||
++p;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
localPart << c;
|
||||
++p;
|
||||
}
|
||||
@ -318,15 +334,15 @@ void emailAddress::parseImpl
|
||||
|
||||
case State_LocalPartRFC2047Start:
|
||||
|
||||
if (c == '?')
|
||||
{
|
||||
if (c == '?') {
|
||||
|
||||
state = State_LocalPartRFC2047Middle;
|
||||
localPart << "=?";
|
||||
localPartIsRFC2047 = true;
|
||||
++p;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
state = State_LocalPartMiddle;
|
||||
localPart << '=';
|
||||
localPart << c;
|
||||
@ -337,39 +353,39 @@ void emailAddress::parseImpl
|
||||
|
||||
case State_LocalPartMiddle:
|
||||
|
||||
if (c == '.')
|
||||
{
|
||||
if (c == '.') {
|
||||
|
||||
prevIsDot = true;
|
||||
localPart << c;
|
||||
++p;
|
||||
}
|
||||
else if (c == '"' && prevIsDot)
|
||||
{
|
||||
|
||||
} else if (c == '"' && prevIsDot) {
|
||||
|
||||
prevIsDot = false;
|
||||
state = State_LocalPartQuoted;
|
||||
++p;
|
||||
}
|
||||
else if (c == '(')
|
||||
{
|
||||
|
||||
} 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 == '@')
|
||||
{
|
||||
|
||||
} else if (c == '@') {
|
||||
|
||||
atFound = true;
|
||||
state = State_DomainPartStart;
|
||||
++p;
|
||||
}
|
||||
else if (parserHelpers::isSpace(c))
|
||||
{
|
||||
|
||||
} else if (parserHelpers::isSpace(c)) {
|
||||
|
||||
// Allow not specifying domain part
|
||||
state = State_End;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
prevIsDot = false;
|
||||
localPart << c;
|
||||
++p;
|
||||
@ -379,13 +395,13 @@ void emailAddress::parseImpl
|
||||
|
||||
case State_LocalPartRFC2047Middle:
|
||||
|
||||
if (c == '?')
|
||||
{
|
||||
if (c == '?') {
|
||||
|
||||
state = State_LocalPartRFC2047MiddleQM;
|
||||
++p;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
localPart << c;
|
||||
++p;
|
||||
}
|
||||
@ -394,15 +410,15 @@ void emailAddress::parseImpl
|
||||
|
||||
case State_LocalPartRFC2047MiddleQM:
|
||||
|
||||
if (c == '=')
|
||||
{
|
||||
if (c == '=') {
|
||||
|
||||
// End of RFC-2047 encoded word
|
||||
state = State_LocalPartRFC2047End;
|
||||
localPart << "?=";
|
||||
++p;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
state = State_LocalPartRFC2047Middle;
|
||||
localPart << '?';
|
||||
localPart << c;
|
||||
@ -413,14 +429,14 @@ void emailAddress::parseImpl
|
||||
|
||||
case State_LocalPartRFC2047End:
|
||||
|
||||
if (c == '@')
|
||||
{
|
||||
if (c == '@') {
|
||||
|
||||
atFound = true;
|
||||
state = State_DomainPartStart;
|
||||
++p;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
state = State_End;
|
||||
}
|
||||
|
||||
@ -428,14 +444,14 @@ void emailAddress::parseImpl
|
||||
|
||||
case State_DomainPartStart:
|
||||
|
||||
if (c == '(')
|
||||
{
|
||||
if (c == '(') {
|
||||
|
||||
state = State_DomainPartComment;
|
||||
++commentLevel;
|
||||
++p;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
state = State_DomainPartMiddle;
|
||||
domainPart << c;
|
||||
++p;
|
||||
@ -445,20 +461,20 @@ void emailAddress::parseImpl
|
||||
|
||||
case State_DomainPartMiddle:
|
||||
|
||||
if (parserHelpers::isSpace(c))
|
||||
{
|
||||
if (parserHelpers::isSpace(c)) {
|
||||
|
||||
state = State_End;
|
||||
}
|
||||
else if (c == '(')
|
||||
{
|
||||
|
||||
} else if (c == '(') {
|
||||
|
||||
// By allowing comments anywhere in the domain part,
|
||||
// we are more permissive than RFC-2822
|
||||
state = State_DomainPartComment;
|
||||
++commentLevel;
|
||||
++p;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
domainPart << c;
|
||||
++p;
|
||||
}
|
||||
@ -467,33 +483,33 @@ void emailAddress::parseImpl
|
||||
|
||||
case State_DomainPartComment:
|
||||
|
||||
if (escapeNext)
|
||||
{
|
||||
if (escapeNext) {
|
||||
|
||||
escapeNext = false;
|
||||
++p;
|
||||
}
|
||||
else if (c == '\\')
|
||||
{
|
||||
|
||||
} else if (c == '\\') {
|
||||
|
||||
escapeNext = true;
|
||||
++p;
|
||||
}
|
||||
else if (c == '(')
|
||||
{
|
||||
|
||||
} else if (c == '(') {
|
||||
|
||||
++commentLevel;
|
||||
++p;
|
||||
}
|
||||
else if (c == ')')
|
||||
{
|
||||
if (--commentLevel == 0)
|
||||
{
|
||||
|
||||
} else if (c == ')') {
|
||||
|
||||
if (--commentLevel == 0) {
|
||||
|
||||
// End of comment
|
||||
state = State_DomainPartMiddle;
|
||||
}
|
||||
|
||||
++p;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// Comment continues
|
||||
++p;
|
||||
}
|
||||
@ -508,50 +524,57 @@ void emailAddress::parseImpl
|
||||
}
|
||||
}
|
||||
|
||||
if (p == pend && state != State_Error)
|
||||
{
|
||||
if (state == State_DomainPartMiddle)
|
||||
if (p == pend && state != State_Error) {
|
||||
|
||||
if (state == State_DomainPartMiddle) {
|
||||
state = State_End;
|
||||
else if (state == State_LocalPartMiddle)
|
||||
} else if (state == State_LocalPartMiddle) {
|
||||
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_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());
|
||||
else
|
||||
} else {
|
||||
m_localName = word(localPart.str(), vmime::charsets::UTF_8);
|
||||
}
|
||||
|
||||
m_domainName = word(domainNameFromIDNA(domainPart.str()), vmime::charsets::UTF_8);
|
||||
}
|
||||
|
||||
setParsedBounds(position, p - pend);
|
||||
|
||||
if (newPosition)
|
||||
if (newPosition) {
|
||||
*newPosition = p - pend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void emailAddress::generateImpl
|
||||
(const generationContext& ctx, utility::outputStream& os,
|
||||
const size_t curLinePos, size_t* newLinePos) const
|
||||
{
|
||||
void emailAddress::generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos,
|
||||
size_t* newLinePos
|
||||
) const {
|
||||
|
||||
string localPart, domainPart;
|
||||
|
||||
if (ctx.getInternationalizedEmailSupport() &&
|
||||
(!utility::stringUtils::is7bit(m_localName.getBuffer()) ||
|
||||
!utility::stringUtils::is7bit(m_domainName.getBuffer())))
|
||||
{
|
||||
!utility::stringUtils::is7bit(m_domainName.getBuffer()))) {
|
||||
|
||||
// Local part
|
||||
string localPartUTF8(m_localName.getConvertedText(vmime::charsets::UTF_8));
|
||||
word localPartWord(localPartUTF8, vmime::charsets::UTF_8);
|
||||
@ -561,9 +584,9 @@ void emailAddress::generateImpl
|
||||
|
||||
// Domain part
|
||||
domainPart = m_domainName.getConvertedText(vmime::charsets::UTF_8);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
// Local part
|
||||
vmime::utility::outputStreamStringAdapter os(localPart);
|
||||
m_localName.generate(ctx, os, 0, NULL, text::QUOTE_IF_NEEDED, NULL);
|
||||
@ -576,8 +599,8 @@ void emailAddress::generateImpl
|
||||
<< "@"
|
||||
<< domainPart;
|
||||
|
||||
if (newLinePos)
|
||||
{
|
||||
if (newLinePos) {
|
||||
|
||||
*newLinePos = curLinePos
|
||||
+ localPart.length()
|
||||
+ 1 // @
|
||||
@ -586,21 +609,21 @@ void emailAddress::generateImpl
|
||||
}
|
||||
|
||||
|
||||
bool emailAddress::operator==(const class emailAddress& eml) const
|
||||
{
|
||||
return (m_localName == eml.m_localName &&
|
||||
m_domainName == eml.m_domainName);
|
||||
bool emailAddress::operator==(const class emailAddress& eml) const {
|
||||
|
||||
return m_localName == eml.m_localName &&
|
||||
m_domainName == eml.m_domainName;
|
||||
}
|
||||
|
||||
|
||||
bool emailAddress::operator!=(const class emailAddress& eml) const
|
||||
{
|
||||
bool emailAddress::operator!=(const class emailAddress& eml) const {
|
||||
|
||||
return !(*this == eml);
|
||||
}
|
||||
|
||||
|
||||
void emailAddress::copyFrom(const component& other)
|
||||
{
|
||||
void emailAddress::copyFrom(const component& other) {
|
||||
|
||||
const emailAddress& source = dynamic_cast <const emailAddress&>(other);
|
||||
|
||||
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);
|
||||
return (*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <component>emailAddress::clone() const
|
||||
{
|
||||
shared_ptr <component>emailAddress::clone() const {
|
||||
|
||||
return make_shared <emailAddress>(*this);
|
||||
}
|
||||
|
||||
|
||||
const word& emailAddress::getLocalName() const
|
||||
{
|
||||
const word& emailAddress::getLocalName() const {
|
||||
|
||||
return m_localName;
|
||||
}
|
||||
|
||||
|
||||
void emailAddress::setLocalName(const word& localName)
|
||||
{
|
||||
void emailAddress::setLocalName(const word& localName) {
|
||||
|
||||
m_localName = localName;
|
||||
}
|
||||
|
||||
|
||||
const word& emailAddress::getDomainName() const
|
||||
{
|
||||
const word& emailAddress::getDomainName() const {
|
||||
|
||||
return m_domainName;
|
||||
}
|
||||
|
||||
|
||||
void emailAddress::setDomainName(const word& domainName)
|
||||
{
|
||||
void emailAddress::setDomainName(const word& 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> >();
|
||||
}
|
||||
|
||||
|
||||
bool emailAddress::isEmpty() const
|
||||
{
|
||||
bool emailAddress::isEmpty() const {
|
||||
|
||||
return m_localName.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
const string emailAddress::toString() const
|
||||
{
|
||||
const string emailAddress::toString() const {
|
||||
|
||||
std::ostringstream 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;
|
||||
txt.appendWord(make_shared <vmime::word>(m_localName));
|
||||
txt.appendWord(make_shared <vmime::word>("@", vmime::charsets::US_ASCII));
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -29,15 +29,13 @@
|
||||
#include "vmime/text.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** An email address: local name and domain name (basic type).
|
||||
*/
|
||||
class VMIME_EXPORT emailAddress : public component {
|
||||
|
||||
class VMIME_EXPORT emailAddress : public component
|
||||
{
|
||||
public:
|
||||
|
||||
emailAddress();
|
||||
@ -114,18 +112,20 @@ public:
|
||||
using component::generate;
|
||||
|
||||
// Component parsing & assembling
|
||||
void parseImpl
|
||||
(const parsingContext& ctx,
|
||||
void parseImpl(
|
||||
const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
void generateImpl
|
||||
(const generationContext& ctx,
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
size_t* newLinePos = NULL) const;
|
||||
size_t* newLinePos = NULL
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -24,92 +24,101 @@
|
||||
#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>();
|
||||
}
|
||||
|
||||
|
||||
void emptyContentHandler::generate(utility::outputStream& /* os */, const vmime::encoding& /* enc */,
|
||||
const size_t /* maxLineLength */) const
|
||||
{
|
||||
void emptyContentHandler::generate(
|
||||
utility::outputStream& /* os */,
|
||||
const vmime::encoding& /* enc */,
|
||||
const size_t /* maxLineLength */
|
||||
) const {
|
||||
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
|
||||
void emptyContentHandler::extract(utility::outputStream& /* os */,
|
||||
void emptyContentHandler::extract(
|
||||
utility::outputStream& /* os */,
|
||||
utility::progressListener* progress) const
|
||||
{
|
||||
if (progress)
|
||||
if (progress) {
|
||||
progress->start(0);
|
||||
}
|
||||
|
||||
// Nothing to do.
|
||||
|
||||
if (progress)
|
||||
if (progress) {
|
||||
progress->stop(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void emptyContentHandler::extractRaw(utility::outputStream& /* os */,
|
||||
utility::progressListener* progress) const
|
||||
{
|
||||
if (progress)
|
||||
void emptyContentHandler::extractRaw(
|
||||
utility::outputStream& /* os */,
|
||||
utility::progressListener* progress
|
||||
) const {
|
||||
|
||||
if (progress) {
|
||||
progress->start(0);
|
||||
}
|
||||
|
||||
// Nothing to do.
|
||||
|
||||
if (progress)
|
||||
if (progress) {
|
||||
progress->stop(0);
|
||||
}
|
||||
|
||||
|
||||
size_t emptyContentHandler::getLength() const
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
bool emptyContentHandler::isEmpty() const
|
||||
{
|
||||
return (true);
|
||||
size_t emptyContentHandler::getLength() const {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool emptyContentHandler::isEncoded() const
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
bool emptyContentHandler::isEmpty() const {
|
||||
|
||||
|
||||
const vmime::encoding& emptyContentHandler::getEncoding() const
|
||||
{
|
||||
return (NO_ENCODING);
|
||||
}
|
||||
|
||||
|
||||
bool emptyContentHandler::isBuffered() const
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
const mediaType emptyContentHandler::getContentTypeHint() const
|
||||
{
|
||||
const mediaType emptyContentHandler::getContentTypeHint() const {
|
||||
|
||||
return m_contentType;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -28,22 +28,32 @@
|
||||
#include "vmime/contentHandler.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
class VMIME_EXPORT emptyContentHandler : public contentHandler
|
||||
{
|
||||
class VMIME_EXPORT emptyContentHandler : public contentHandler {
|
||||
|
||||
public:
|
||||
|
||||
emptyContentHandler();
|
||||
|
||||
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 extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const;
|
||||
void extract(
|
||||
utility::outputStream& os,
|
||||
utility::progressListener* progress = NULL
|
||||
) const;
|
||||
|
||||
void extractRaw(
|
||||
utility::outputStream& os,
|
||||
utility::progressListener* progress = NULL
|
||||
) const;
|
||||
|
||||
size_t getLength() const;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
@ -30,118 +30,140 @@
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
encoding::encoding()
|
||||
: m_name(encodingTypes::SEVEN_BIT),
|
||||
m_usage(USAGE_UNKNOWN)
|
||||
{
|
||||
m_usage(USAGE_UNKNOWN) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
encoding::encoding(const string& name)
|
||||
: m_name(utility::stringUtils::toLower(name)),
|
||||
m_usage(USAGE_UNKNOWN)
|
||||
{
|
||||
m_usage(USAGE_UNKNOWN) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
encoding::encoding(const string& name, const EncodingUsage usage)
|
||||
: m_name(utility::stringUtils::toLower(name)),
|
||||
m_usage(usage)
|
||||
{
|
||||
m_usage(usage) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
(const parsingContext& /* ctx */, const string& buffer, const size_t position,
|
||||
const size_t end, size_t* newPosition)
|
||||
{
|
||||
void encoding::parseImpl(
|
||||
const parsingContext& /* ctx */,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition
|
||||
) {
|
||||
|
||||
m_usage = USAGE_UNKNOWN;
|
||||
|
||||
m_name = utility::stringUtils::toLower(utility::stringUtils::trim
|
||||
(utility::stringUtils::unquote(utility::stringUtils::trim
|
||||
(string(buffer.begin() + position, buffer.begin() + end)))));
|
||||
m_name = utility::stringUtils::toLower(
|
||||
utility::stringUtils::trim(
|
||||
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"
|
||||
}
|
||||
|
||||
setParsedBounds(position, end);
|
||||
|
||||
if (newPosition)
|
||||
if (newPosition) {
|
||||
*newPosition = end;
|
||||
}
|
||||
|
||||
|
||||
void encoding::generateImpl
|
||||
(const generationContext& /* ctx */, utility::outputStream& os,
|
||||
const size_t curLinePos, size_t* newLinePos) const
|
||||
{
|
||||
os << m_name;
|
||||
|
||||
if (newLinePos)
|
||||
*newLinePos = curLinePos + m_name.length();
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <utility::encoder::encoder> encoding::getEncoder() const
|
||||
{
|
||||
void encoding::generateImpl(
|
||||
const generationContext& /* ctx */,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos,
|
||||
size_t* newLinePos
|
||||
) const {
|
||||
|
||||
os << m_name;
|
||||
|
||||
if (newLinePos) {
|
||||
*newLinePos = curLinePos + m_name.length();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <utility::encoder::encoder> encoding::getEncoder() const {
|
||||
|
||||
shared_ptr <utility::encoder::encoder> encoder =
|
||||
utility::encoder::encoderFactory::getInstance()->create(generate());
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
return encoder;
|
||||
}
|
||||
|
||||
|
||||
encoding& encoding::operator=(const encoding& other)
|
||||
{
|
||||
encoding& encoding::operator=(const encoding& other) {
|
||||
|
||||
copyFrom(other);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
|
||||
encoding& encoding::operator=(const string& name)
|
||||
{
|
||||
encoding& encoding::operator=(const string& name) {
|
||||
|
||||
m_name = utility::stringUtils::toLower(name);
|
||||
m_usage = USAGE_UNKNOWN;
|
||||
return (*this);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool encoding::operator==(const encoding& value) const
|
||||
{
|
||||
return (utility::stringUtils::toLower(m_name) == value.m_name);
|
||||
bool encoding::operator==(const encoding& value) const {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
const encoding encoding::decideImpl
|
||||
(const string::const_iterator begin, const string::const_iterator end)
|
||||
{
|
||||
const encoding encoding::decideImpl(
|
||||
const string::const_iterator begin,
|
||||
const string::const_iterator end
|
||||
) {
|
||||
|
||||
const string::difference_type length = end - begin;
|
||||
const string::difference_type count = std::count_if
|
||||
(begin, end, std::bind2nd(std::less<unsigned char>(), 127));
|
||||
const string::difference_type count = std::count_if(
|
||||
begin, end,
|
||||
std::bind2nd(std::less<unsigned char>(), 127)
|
||||
);
|
||||
|
||||
// All is in 7-bit US-ASCII --> 7-bit (or Quoted-Printable...)
|
||||
if (length == count)
|
||||
{
|
||||
if (length == count) {
|
||||
|
||||
// Now, we check if there is any line with more than
|
||||
// "lineLengthLimits::convenient" characters (7-bit requires that)
|
||||
string::const_iterator p = begin;
|
||||
@ -149,49 +171,51 @@ const encoding encoding::decideImpl
|
||||
const size_t maxLen = lineLengthLimits::convenient;
|
||||
size_t len = 0;
|
||||
|
||||
for ( ; p != end && len <= maxLen ; )
|
||||
{
|
||||
if (*p == '\n')
|
||||
{
|
||||
for ( ; p != end && len <= maxLen ; ) {
|
||||
|
||||
if (*p == '\n') {
|
||||
|
||||
len = 0;
|
||||
++p;
|
||||
|
||||
// May or may not need to be encoded, we don't take
|
||||
// any risk (avoid problems with SMTP)
|
||||
if (p != end && *p == '.')
|
||||
if (p != end && *p == '.') {
|
||||
len = maxLen + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
++len;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > maxLen)
|
||||
return (encoding(encodingTypes::QUOTED_PRINTABLE));
|
||||
else
|
||||
return (encoding(encodingTypes::SEVEN_BIT));
|
||||
if (len > maxLen) {
|
||||
return encoding(encodingTypes::QUOTED_PRINTABLE);
|
||||
} else {
|
||||
return encoding(encodingTypes::SEVEN_BIT);
|
||||
}
|
||||
|
||||
// Less than 20% non US-ASCII --> Quoted-Printable
|
||||
else if ((length - count) <= length / 5)
|
||||
{
|
||||
return (encoding(encodingTypes::QUOTED_PRINTABLE));
|
||||
}
|
||||
} else if ((length - count) <= length / 5) {
|
||||
|
||||
return encoding(encodingTypes::QUOTED_PRINTABLE);
|
||||
|
||||
// Otherwise --> Base64
|
||||
else
|
||||
{
|
||||
return (encoding(encodingTypes::BASE64));
|
||||
} else {
|
||||
|
||||
return encoding(encodingTypes::BASE64);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool encoding::shouldReencode() const
|
||||
{
|
||||
bool encoding::shouldReencode() const {
|
||||
|
||||
if (m_name == encodingTypes::BASE64 ||
|
||||
m_name == encodingTypes::QUOTED_PRINTABLE ||
|
||||
m_name == encodingTypes::UUENCODE)
|
||||
{
|
||||
m_name == encodingTypes::UUENCODE) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -199,18 +223,21 @@ bool encoding::shouldReencode() const
|
||||
}
|
||||
|
||||
|
||||
const encoding encoding::decide
|
||||
(shared_ptr <const contentHandler> data, const EncodingUsage usage)
|
||||
{
|
||||
const encoding encoding::decide(
|
||||
const shared_ptr <const contentHandler>& data,
|
||||
const EncodingUsage usage
|
||||
) {
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
encoding enc;
|
||||
|
||||
if (usage == USAGE_TEXT && data->isBuffered() &&
|
||||
data->getLength() > 0 && data->getLength() < 32768)
|
||||
{
|
||||
data->getLength() > 0 && data->getLength() < 32768) {
|
||||
|
||||
// Extract data into temporary buffer
|
||||
string buffer;
|
||||
utility::outputStreamStringAdapter os(buffer);
|
||||
@ -219,9 +246,9 @@ const encoding encoding::decide
|
||||
os.flush();
|
||||
|
||||
enc = decideImpl(buffer.begin(), buffer.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else {
|
||||
|
||||
enc = encoding(encodingTypes::BASE64);
|
||||
}
|
||||
|
||||
@ -231,19 +258,23 @@ const encoding encoding::decide
|
||||
}
|
||||
|
||||
|
||||
const encoding encoding::decide(shared_ptr <const contentHandler> data,
|
||||
const charset& chset, const EncodingUsage usage)
|
||||
{
|
||||
// Do not re-encode data if it is already encoded
|
||||
if (data->isEncoded() && !data->getEncoding().shouldReencode())
|
||||
return data->getEncoding();
|
||||
const encoding encoding::decide(
|
||||
const shared_ptr <const contentHandler>& data,
|
||||
const charset& chset,
|
||||
const EncodingUsage usage
|
||||
) {
|
||||
|
||||
// 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;
|
||||
|
||||
if (chset.getRecommendedEncoding(recEncoding))
|
||||
{
|
||||
if (chset.getRecommendedEncoding(recEncoding)) {
|
||||
|
||||
recEncoding.setUsage(usage);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void encoding::copyFrom(const component& other)
|
||||
{
|
||||
void encoding::copyFrom(const component& other) {
|
||||
|
||||
const encoding& e = dynamic_cast <const encoding&>(other);
|
||||
|
||||
m_name = e.m_name;
|
||||
}
|
||||
|
||||
|
||||
const string& encoding::getName() const
|
||||
{
|
||||
return (m_name);
|
||||
const string& encoding::getName() const {
|
||||
|
||||
return m_name;
|
||||
}
|
||||
|
||||
|
||||
void encoding::setName(const string& name)
|
||||
{
|
||||
void encoding::setName(const string& name) {
|
||||
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
|
||||
encoding::EncodingUsage encoding::getUsage() const
|
||||
{
|
||||
encoding::EncodingUsage encoding::getUsage() const {
|
||||
|
||||
return m_usage;
|
||||
}
|
||||
|
||||
|
||||
void encoding::setUsage(const EncodingUsage usage)
|
||||
{
|
||||
void encoding::setUsage(const EncodingUsage 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> >();
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user