Compare commits
206 Commits
Author | SHA1 | Date | |
---|---|---|---|
52f6184e88 | |||
fd0b5f7a21 | |||
193a9ee85b | |||
![]() |
43b262bd8c | ||
![]() |
beb238b5e7 | ||
![]() |
aa60d00496 | ||
![]() |
0f7014ab57 | ||
![]() |
fb5b82746a | ||
![]() |
5f8fa22602 | ||
![]() |
a2636bd4ae | ||
![]() |
d296c2d1d5 | ||
![]() |
c105165c6e | ||
![]() |
b447adbe37 | ||
![]() |
97d15b8cd7 | ||
![]() |
15f3b94580 | ||
![]() |
d03ad5f0f6 | ||
![]() |
0ce327abee | ||
![]() |
c6b01fcc32 | ||
![]() |
c3c6242ed1 | ||
![]() |
874a1d8c33 | ||
![]() |
8bed1cc743 | ||
![]() |
a5623d695f | ||
![]() |
6fd4de8fb5 | ||
![]() |
9b65b4de6c | ||
![]() |
acfc0bbf82 | ||
![]() |
022303bbc9 | ||
![]() |
7ada1c974c | ||
![]() |
82377e0342 | ||
![]() |
6e11c9c9f8 | ||
![]() |
1a35bb6d71 | ||
![]() |
c6b9ad3c78 | ||
![]() |
fc69321d53 | ||
![]() |
56b77ca3b7 | ||
![]() |
6fd3632912 | ||
![]() |
46c09fa8a5 | ||
![]() |
cd59fabe79 | ||
![]() |
561746081f | ||
![]() |
23ab2a6a3c | ||
![]() |
80ad529d5a | ||
![]() |
c6e3b759bc | ||
![]() |
1a0a22a311 | ||
![]() |
edcb4b4b1f | ||
![]() |
f5fa6434aa | ||
![]() |
5d78d879bb | ||
![]() |
c86e4bcd3a | ||
![]() |
7503cd3747 | ||
![]() |
c6904bd7cf | ||
![]() |
a6226e8cbc | ||
![]() |
8024c650a2 | ||
![]() |
c0f2380aac | ||
![]() |
e5186e6710 | ||
![]() |
6feb658bfb | ||
![]() |
7d64105dee | ||
![]() |
b2d08d4f71 | ||
![]() |
9ec84cf80f | ||
![]() |
db486520f2 | ||
![]() |
a0d02afc69 | ||
![]() |
d7eaba1007 | ||
![]() |
68f8eb0d39 | ||
![]() |
115d232483 | ||
![]() |
cb5adc3a23 | ||
![]() |
025c155919 | ||
![]() |
408ffb13ea | ||
![]() |
98ec456ed1 | ||
![]() |
8416534992 | ||
![]() |
98e9759da2 | ||
![]() |
39a0cfbcc3 | ||
![]() |
47c6f35f5a | ||
![]() |
ea9775c4f1 | ||
![]() |
9116feac76 | ||
![]() |
7f9a0eb148 | ||
![]() |
13ca7fa6e5 | ||
![]() |
817358854d | ||
![]() |
ec5b8f7cfe | ||
![]() |
3733af5191 | ||
![]() |
2e07dc4c31 | ||
![]() |
c750e899b8 | ||
![]() |
9e2c286c0b | ||
![]() |
f4c611b736 | ||
![]() |
6c4bd0dda9 | ||
![]() |
9205c9d0ab | ||
![]() |
e25751cc0d | ||
![]() |
84294f6543 | ||
![]() |
7000792fa0 | ||
![]() |
6eb63399a1 | ||
![]() |
4edb9ed949 | ||
![]() |
d14038dd66 | ||
![]() |
22ae6a91f5 | ||
![]() |
d4cc5cfc9b | ||
![]() |
4c330bc623 | ||
![]() |
c137bc55af | ||
![]() |
1806e0be0e | ||
![]() |
83a2669a51 | ||
![]() |
e02ea9d178 | ||
![]() |
64ef65e03c | ||
![]() |
e30766cf2a | ||
![]() |
0f99387648 | ||
![]() |
3052e5b998 | ||
![]() |
5c00f7867a | ||
![]() |
9a10a839ec | ||
![]() |
16912a5ed7 | ||
![]() |
fe5492ceb3 | ||
![]() |
6d90a15bc5 | ||
![]() |
f23cc90a6d | ||
![]() |
2d369b9ac9 | ||
![]() |
36cc0c65c8 | ||
![]() |
749a2a0f85 | ||
![]() |
8ac5b7f5fc | ||
![]() |
893726c3d8 | ||
![]() |
39ece29fed | ||
![]() |
3c372b08ac | ||
![]() |
44eb473c9a | ||
![]() |
19fb3c2491 | ||
![]() |
86b59de8d0 | ||
![]() |
ab340b561d | ||
![]() |
b06e9e6f86 | ||
![]() |
df32418df5 | ||
![]() |
c9119effd7 | ||
![]() |
6de75f0c95 | ||
![]() |
0fcf45b131 | ||
![]() |
7168f3c4ee | ||
![]() |
e96aeeb14d | ||
![]() |
182e8f5dd8 | ||
![]() |
523aacb499 | ||
![]() |
8f4db13e7f | ||
![]() |
e2fc1911f1 | ||
![]() |
b59e97d0a7 | ||
![]() |
dad5b4a855 | ||
![]() |
e1faa92593 | ||
![]() |
414661858d | ||
![]() |
d1190b496f | ||
![]() |
cc18aa39c1 | ||
![]() |
0368adade1 | ||
![]() |
df135b5a8b | ||
![]() |
0c81108cc8 | ||
![]() |
71968d978d | ||
![]() |
ea0d24809d | ||
![]() |
cfd4492915 | ||
![]() |
7e29cf01fa | ||
![]() |
258f943ded | ||
![]() |
3bd864efc2 | ||
![]() |
b55bdc9c0b | ||
![]() |
71a0fa4b26 | ||
![]() |
5cd1f2990a | ||
![]() |
d4c386beda | ||
![]() |
f173b0a535 | ||
![]() |
997616c629 | ||
![]() |
81e73c0f56 | ||
![]() |
1e56a3617d | ||
![]() |
5eae3b1bd6 | ||
![]() |
f9a4099837 | ||
![]() |
52042b2b5b | ||
![]() |
df8051d8db | ||
![]() |
6ad4c1a0d5 | ||
![]() |
a9b822140b | ||
![]() |
8495ce1116 | ||
![]() |
8564b2f8b0 | ||
![]() |
ed825ba255 | ||
![]() |
f04190bafa | ||
![]() |
abba40e97d | ||
![]() |
754e556aeb | ||
![]() |
b73d765f51 | ||
![]() |
680057bacd | ||
![]() |
d7a1b5817e | ||
![]() |
1592cccb61 | ||
![]() |
dff676572a | ||
![]() |
6cfe2c5f6c | ||
![]() |
9e97519186 | ||
![]() |
eb5d9db693 | ||
![]() |
e83937ba42 | ||
![]() |
51af739f8e | ||
![]() |
b848dec86a | ||
![]() |
79e96398cd | ||
![]() |
a965f64262 | ||
![]() |
e14fd4f2c9 | ||
![]() |
a370654a32 | ||
![]() |
c6cf359ffc | ||
![]() |
243efb267f | ||
![]() |
f61efd2f36 | ||
![]() |
5ea19601d5 | ||
![]() |
3d3ed7b260 | ||
![]() |
50b312f98a | ||
![]() |
ea66541338 | ||
![]() |
8d3ea37b55 | ||
![]() |
d2b3f98ba1 | ||
![]() |
8146d80e0c | ||
![]() |
1806073524 | ||
![]() |
1862f165c2 | ||
![]() |
8e6db1c7a6 | ||
![]() |
604b713562 | ||
![]() |
1bc9f457be | ||
![]() |
041854731c | ||
![]() |
428c49b69f | ||
![]() |
522ec147a3 | ||
![]() |
975f555f22 | ||
![]() |
e6f2ed341a | ||
![]() |
8fb7b007f9 | ||
![]() |
68fd4e1e42 | ||
![]() |
05a65a3bfa | ||
![]() |
3cfcdca2ff | ||
![]() |
9a3d6880e8 | ||
![]() |
e973619d7e | ||
![]() |
ec5f4370b6 | ||
![]() |
f29edeb887 | ||
![]() |
08b8ce3dc7 | ||
![]() |
8a63b02764 |
25
.github/workflows/build.yml
vendored
Normal file
25
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
name: Compilation test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: install-deps
|
||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
with:
|
||||
packages: binutils cmake doxygen g++ libcppunit-dev libgnutls28-dev libgsasl7-dev libgtk-3-dev libssl-dev make pkg-config
|
||||
version: 1.2
|
||||
- name: clone-vmime
|
||||
uses: actions/checkout@v3
|
||||
- name: buildall
|
||||
run: |
|
||||
set -x
|
||||
lscpu -b --online --parse | grep -v '^#' | wc -l >/tmp/ncpus
|
||||
cmake . -DVMIME_SENDMAIL_PATH:STRING="/usr/sbin/sendmail" -DVMIME_HAVE_TLS_SUPPORT:BOOL=ON -DVMIME_BUILD_TESTS=ON -DVMIME_BUILD_SAMPLES=ON && make "-j$(cat /tmp/ncpus)" && sudo make install
|
||||
make test
|
503
CMakeLists.txt
503
CMakeLists.txt
@ -12,7 +12,7 @@
|
||||
# http://www.cmake.org
|
||||
#
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.6 FATAL_ERROR)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.12 FATAL_ERROR)
|
||||
|
||||
INCLUDE(cmake/Utils.cmake)
|
||||
|
||||
@ -23,6 +23,7 @@ INCLUDE(CheckSymbolExists)
|
||||
INCLUDE(CheckTypeSize)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
INCLUDE(CheckCXXSourceCompiles)
|
||||
INCLUDE(GNUInstallDirs)
|
||||
|
||||
|
||||
# CMake configuration
|
||||
@ -33,9 +34,6 @@ SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY build/lib)
|
||||
SET(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
|
||||
|
||||
# Project
|
||||
PROJECT(vmime)
|
||||
|
||||
# Package version number
|
||||
SET(VMIME_VERSION_MAJOR 0)
|
||||
SET(VMIME_VERSION_MINOR 9)
|
||||
@ -64,8 +62,59 @@ SET(VMIME_API_VERSION ${VMIME_API_VERSION_CURRENT}.${VMIME_API_VERSION_REVISION}
|
||||
##############################################################################
|
||||
# VMime Library
|
||||
|
||||
# Project
|
||||
PROJECT(
|
||||
vmime
|
||||
LANGUAGES CXX C
|
||||
VERSION ${VMIME_VERSION}
|
||||
)
|
||||
|
||||
# Install directories
|
||||
IF(IS_ABSOLUTE ${CMAKE_INSTALL_LIBDIR})
|
||||
SET(VMIME_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR})
|
||||
ELSE()
|
||||
SET(VMIME_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||
ENDIF()
|
||||
MESSAGE("CMAKE_INSTALL_LIBDIR='${CMAKE_INSTALL_LIBDIR}")
|
||||
MESSAGE("VMIME_INSTALL_LIBDIR='${VMIME_INSTALL_LIBDIR}")
|
||||
|
||||
IF(IS_ABSOLUTE ${CMAKE_INSTALL_BINDIR})
|
||||
SET(VMIME_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR})
|
||||
ELSE()
|
||||
SET(VMIME_INSTALL_BINDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
|
||||
ENDIF()
|
||||
|
||||
IF(IS_ABSOLUTE ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
SET(VMIME_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
ELSE()
|
||||
SET(VMIME_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
ENDIF()
|
||||
|
||||
# Set base name
|
||||
SET(VMIME_LIBRARY_NAME vmime)
|
||||
SET(VMIME_LIBRARY_VENDOR Kisli)
|
||||
|
||||
# Enable C++11
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
SET(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
##############################################################################
|
||||
# Charset conversion library (1/2)
|
||||
|
||||
INCLUDE(cmake/FindIconv.cmake)
|
||||
INCLUDE(cmake/FindICU.cmake)
|
||||
|
||||
FIND_PACKAGE(ICU QUIET)
|
||||
|
||||
IF(ICU_LIBRARIES)
|
||||
SET(VMIME_CHARSETCONV_LIB_DETECTED "icu")
|
||||
SET(CMAKE_CXX_STANDARD 17)
|
||||
ELSEIF(ICONV_FOUND)
|
||||
SET(VMIME_CHARSETCONV_LIB_DETECTED "iconv")
|
||||
ELSEIF(WIN32)
|
||||
SET(VMIME_CHARSETCONV_LIB_DETECTED "win")
|
||||
ENDIF()
|
||||
|
||||
# Source files
|
||||
FILE(
|
||||
@ -80,12 +129,10 @@ FILE(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/vmime/*.hpp
|
||||
)
|
||||
|
||||
LIST(APPEND VMIME_LIBRARY_GENERATED_INCLUDE_FILES "${CMAKE_BINARY_DIR}/src/vmime/config.hpp")
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${CMAKE_CURRENT_SOURCE_DIR} # for "contrib/"
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src # for "vmime/
|
||||
${CMAKE_BINARY_DIR}/src # for "config.hpp"
|
||||
${CMAKE_SOURCE_DIR} # for "contrib/"
|
||||
${CMAKE_SOURCE_DIR}/src # for "vmime/
|
||||
${CMAKE_BINARY_DIR}/src # for "config.hpp" and other generated sources
|
||||
)
|
||||
|
||||
INCLUDE(GenerateExportHeader)
|
||||
@ -107,18 +154,16 @@ IF(VMIME_BUILD_SHARED_LIBRARY)
|
||||
${VMIME_LIBRARY_INCLUDE_FILES}
|
||||
)
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(${VMIME_LIBRARY_NAME} PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
GENERATE_EXPORT_HEADER(
|
||||
${VMIME_LIBRARY_NAME}
|
||||
BASE_NAME VMIME
|
||||
STATIC_DEFINE VMIME_STATIC
|
||||
EXPORT_FILE_NAME export-shared.hpp
|
||||
)
|
||||
|
||||
FILE(
|
||||
COPY
|
||||
${CMAKE_CURRENT_BINARY_DIR}/export-shared.hpp
|
||||
DESTINATION
|
||||
${CMAKE_BINARY_DIR}/src/vmime
|
||||
EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/src/vmime/export-shared.hpp
|
||||
)
|
||||
|
||||
LIST(APPEND VMIME_LIBRARY_GENERATED_INCLUDE_FILES "${CMAKE_BINARY_DIR}/src/vmime/export-shared.hpp")
|
||||
@ -152,18 +197,16 @@ IF(VMIME_BUILD_STATIC_LIBRARY)
|
||||
${VMIME_LIBRARY_INCLUDE_FILES}
|
||||
)
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(${VMIME_LIBRARY_NAME}-static PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
GENERATE_EXPORT_HEADER(
|
||||
${VMIME_LIBRARY_NAME}-static
|
||||
BASE_NAME VMIME
|
||||
STATIC_DEFINE VMIME_STATIC
|
||||
EXPORT_FILE_NAME export-static.hpp
|
||||
)
|
||||
|
||||
FILE(
|
||||
COPY
|
||||
${CMAKE_CURRENT_BINARY_DIR}/export-static.hpp
|
||||
DESTINATION
|
||||
${CMAKE_BINARY_DIR}/src/vmime
|
||||
EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/src/vmime/export-static.hpp
|
||||
)
|
||||
|
||||
LIST(APPEND VMIME_LIBRARY_GENERATED_INCLUDE_FILES "${CMAKE_BINARY_DIR}/src/vmime/export-static.hpp")
|
||||
@ -182,80 +225,6 @@ IF(NOT(VMIME_BUILD_SHARED_LIBRARY OR VMIME_BUILD_STATIC_LIBRARY))
|
||||
MESSAGE(FATAL_ERROR "You should select at least one library to build (either VMIME_BUILD_SHARED_LIBRARY or VMIME_BUILD_STATIC_LIBRARY must be set to YES.")
|
||||
ENDIF()
|
||||
|
||||
# These next two lines are required but it is unclear exactly what they do.
|
||||
# The CMake FAQ mentions they are necessary and it does not work otherwise.
|
||||
IF(VMIME_BUILD_SHARED_LIBRARY)
|
||||
SET_TARGET_PROPERTIES(${VMIME_LIBRARY_NAME} PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
ENDIF()
|
||||
IF(VMIME_BUILD_STATIC_LIBRARY)
|
||||
SET_TARGET_PROPERTIES(${VMIME_LIBRARY_NAME}-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_INSTALL_LIBDIR lib CACHE PATH "Output directory for libraries")
|
||||
|
||||
# Automatically set lib suffix
|
||||
IF(UNIX AND NOT APPLE AND NOT CMAKE_CROSSCOMPILING AND NOT EXISTS "/etc/debian_version")
|
||||
IF(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT LIB_SUFFIX)
|
||||
# ...only if LIB_SUFFIX is not defined...
|
||||
IF(NOT DEFINED LIB_SUFFIX)
|
||||
# ...and if CMAKE_INSTALL_LIBDIR does not already contain the suffix
|
||||
IF(NOT "${CMAKE_INSTALL_LIBDIR}" MATCHES ".*64.*")
|
||||
SET(LIB_SUFFIX 64)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Determine library installation dir, in this order:
|
||||
# 1) use VMIME_INSTALL_LIBDIR if set
|
||||
# 2) use LIB_INSTALL_DIR if defined
|
||||
# 3) use CMAKE_INSTALL_LIBDIR if set
|
||||
# if it is a relative path, prepend CMAKE_INSTALL_PREFIX to it
|
||||
# 4) use CMAKE_INSTALL_PREFIX/lib
|
||||
IF(NOT DEFINED VMIME_INSTALL_LIBDIR)
|
||||
IF(DEFINED LIB_INSTALL_DIR)
|
||||
SET(VMIME_INSTALL_LIBDIR ${LIB_INSTALL_DIR})
|
||||
# respect CMAKE_INSTALL_LIBDIR if set
|
||||
ELSEIF(DEFINED CMAKE_INSTALL_LIBDIR)
|
||||
SET(VMIME_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR})
|
||||
IF(IS_ABSOLUTE ${VMIME_INSTALL_LIBDIR})
|
||||
SET(VMIME_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}${LIB_SUFFIX})
|
||||
ELSE()
|
||||
SET(VMIME_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}${LIB_SUFFIX})
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(VMIME_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Installation of libraries
|
||||
IF(VMIME_BUILD_SHARED_LIBRARY)
|
||||
INSTALL(
|
||||
TARGETS ${VMIME_LIBRARY_NAME}
|
||||
LIBRARY DESTINATION "${VMIME_INSTALL_LIBDIR}" COMPONENT sharedlibs
|
||||
ARCHIVE DESTINATION "${VMIME_INSTALL_LIBDIR}" COMPONENT sharedlibs
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(VMIME_BUILD_STATIC_LIBRARY)
|
||||
INSTALL(
|
||||
TARGETS ${VMIME_LIBRARY_NAME}-static
|
||||
LIBRARY DESTINATION "${VMIME_INSTALL_LIBDIR}" COMPONENT staticlibs
|
||||
ARCHIVE DESTINATION "${VMIME_INSTALL_LIBDIR}" COMPONENT staticlibs
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
# Installation of header files
|
||||
INSTALL_HEADERS_WITH_DIRECTORY(VMIME_LIBRARY_INCLUDE_FILES headers "${CMAKE_SOURCE_DIR}/src/")
|
||||
INSTALL_HEADERS_WITH_DIRECTORY(VMIME_LIBRARY_GENERATED_INCLUDE_FILES headers "${CMAKE_BINARY_DIR}/src")
|
||||
|
||||
#INSTALL(
|
||||
# FILES ${VMIME_LIBRARY_INCLUDE_FILES}
|
||||
# DESTINATION include
|
||||
# COMPONENT headers
|
||||
#)
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Tests
|
||||
|
||||
@ -275,12 +244,12 @@ IF(VMIME_BUILD_TESTS)
|
||||
FILE(
|
||||
GLOB_RECURSE
|
||||
VMIME_TESTS_SRC_FILES
|
||||
${CMAKE_SOURCE_DIR}/tests/*Test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/*Test.cpp
|
||||
)
|
||||
|
||||
ADD_LIBRARY(
|
||||
test-runner
|
||||
${CMAKE_SOURCE_DIR}/tests/testRunner.cpp ${CMAKE_SOURCE_DIR}/tests/testUtils.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/testRunner.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/testUtils.cpp
|
||||
)
|
||||
|
||||
# Build one file for each test
|
||||
@ -288,7 +257,7 @@ IF(VMIME_BUILD_TESTS)
|
||||
|
||||
# "/path/to/vmime/tests/module/testFile.cpp" --> "module_testFile"
|
||||
GET_FILENAME_COMPONENT(VMIME_TEST_SRC_PATH "${VMIME_TEST_SRC_FILE}" PATH)
|
||||
STRING(REPLACE "${CMAKE_SOURCE_DIR}" "" VMIME_TEST_SRC_PATH "${VMIME_TEST_SRC_PATH}")
|
||||
STRING(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "" VMIME_TEST_SRC_PATH "${VMIME_TEST_SRC_PATH}")
|
||||
GET_FILENAME_COMPONENT(VMIME_TEST_NAME "${VMIME_TEST_SRC_FILE}" NAME_WE)
|
||||
SET(VMIME_TEST_NAME "${VMIME_TEST_SRC_PATH}/${VMIME_TEST_NAME}")
|
||||
STRING(REPLACE "/" "_" VMIME_TEST_NAME "${VMIME_TEST_NAME}")
|
||||
@ -343,35 +312,44 @@ ENDIF()
|
||||
OPTION(
|
||||
VMIME_BUILD_SAMPLES
|
||||
"Build samples (in 'examples' directory)"
|
||||
ON
|
||||
OFF
|
||||
)
|
||||
|
||||
IF(VMIME_BUILD_SAMPLES)
|
||||
ADD_SUBDIRECTORY(examples)
|
||||
ENDIF()
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Packaging / Distribution
|
||||
|
||||
# Package information
|
||||
SET(VMIME_PACKAGE_NAME ${VMIME_LIBRARY_NAME})
|
||||
SET(VMIME_PACKAGE_VENDOR ${VMIME_LIBRARY_VENDOR})
|
||||
SET(VMIME_PACKAGE_VERSION ${VMIME_VERSION})
|
||||
SET(VMIME_PACKAGE_CONTACT "Vincent Richard <vincent@vmime.org>")
|
||||
SET(VMIME_PACKAGE_DESCRIPTION "VMime C++ Mail Library (http://www.vmime.org)")
|
||||
SET(VMIME_PACKAGE_HOMEPAGE_URL "https://www.vmime.org")
|
||||
|
||||
SET(CPACK_PACKAGE_NAME "${VMIME_PACKAGE_NAME}")
|
||||
SET(CPACK_PACKAGE_VENDOR "${VMIME_PACKAGE_VENDOR}")
|
||||
SET(CPACK_PACKAGE_CONTACT "${VMIME_PACKAGE_CONTACT}")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION "${VMIME_PACKAGE_DESCRIPTION}")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${CPACK_PACKAGE_DESCRIPTION}")
|
||||
SET(CPACK_PACKAGE_HOMEPAGE_URL "${VMIME_PACKAGE_HOMEPAGE_URL}")
|
||||
SET(CPACK_PACKAGE_VERSION "${VMIME_PACKAGE_VERSION}")
|
||||
|
||||
# Package settings
|
||||
SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/COPYING)
|
||||
|
||||
IF(APPLE)
|
||||
# CPack/PackageManager won't allow file without recognized extension
|
||||
# to be used as license file.
|
||||
CONFIGURE_FILE("${CMAKE_SOURCE_DIR}/COPYING" "${CMAKE_BINARY_DIR}/COPYING.txt" COPYONLY)
|
||||
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/COPYING" "${CMAKE_BINARY_DIR}/COPYING.txt" COPYONLY)
|
||||
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_BINARY_DIR}/COPYING.txt")
|
||||
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/README" "${CMAKE_BINARY_DIR}/README.txt" COPYONLY)
|
||||
SET(CPACK_RESOURCE_FILE_README "${CMAKE_BINARY_DIR}/README.txt")
|
||||
ELSE()
|
||||
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
||||
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
|
||||
SET(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README")
|
||||
ENDIF(APPLE)
|
||||
|
||||
SET(CPACK_SOURCE_GENERATOR TGZ)
|
||||
@ -405,13 +383,13 @@ ADD_CUSTOM_TARGET(
|
||||
dist
|
||||
COMMAND git archive --prefix=${ARCHIVE_NAME}/ HEAD
|
||||
| bzip2 > ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
# PkgConfig
|
||||
SET(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
SET(exec_prefix ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
SET(includedir ${CMAKE_INSTALL_PREFIX}/include/vmime)
|
||||
SET(exec_prefix ${VMIME_INSTALL_BINDIR})
|
||||
SET(includedir ${VMIME_INSTALL_INCLUDEDIR}/vmime)
|
||||
SET(libdir ${VMIME_INSTALL_LIBDIR})
|
||||
|
||||
SET(VMIME_PKGCONFIG_LIBS "")
|
||||
@ -534,31 +512,9 @@ ELSE()
|
||||
ENDIF()
|
||||
|
||||
|
||||
INCLUDE(cmake/TargetArch.cmake)
|
||||
TARGET_ARCHITECTURE(CMAKE_TARGET_ARCHITECTURES)
|
||||
|
||||
CHECK_TYPE_SIZE(size_t VMIME_HAVE_SIZE_T)
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Sendmail path
|
||||
|
||||
FOREACH (SENDMAIL_PATH /usr/sbin/sendmail /usr/lib/sendmail /usr/bin/sendmail /bin/sendmail /var/qmail/bin/qmail-inject /bin/cgimail)
|
||||
IF(EXISTS ${SENDMAIL_PATH})
|
||||
MESSAGE(STATUS "Sendmail binary found at ${SENDMAIL_PATH}")
|
||||
SET(VMIME_DEFAULT_SENDMAIL_PATH ${SENDMAIL_PATH})
|
||||
ENDIF()
|
||||
ENDFOREACH(SENDMAIL_PATH)
|
||||
|
||||
SET(
|
||||
VMIME_SENDMAIL_PATH
|
||||
${VMIME_DEFAULT_SENDMAIL_PATH}
|
||||
CACHE
|
||||
STRING
|
||||
"Specifies the path to sendmail binary"
|
||||
)
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Messaging features
|
||||
|
||||
@ -614,8 +570,6 @@ OPTION(
|
||||
##############################################################################
|
||||
# SASL support
|
||||
|
||||
INCLUDE(cmake/FindGSasl.cmake)
|
||||
|
||||
OPTION(
|
||||
VMIME_HAVE_SASL_SUPPORT
|
||||
"Enable SASL support (requires GNU SASL library)"
|
||||
@ -624,6 +578,8 @@ OPTION(
|
||||
|
||||
IF(VMIME_HAVE_SASL_SUPPORT)
|
||||
|
||||
INCLUDE(cmake/FindGSasl.cmake)
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${INCLUDE_DIRECTORIES}
|
||||
${GSASL_INCLUDE_DIR}
|
||||
@ -645,37 +601,33 @@ ENDIF()
|
||||
##############################################################################
|
||||
# SSL/TLS support
|
||||
|
||||
INCLUDE(FindGnuTLS)
|
||||
INCLUDE(FindOpenSSL)
|
||||
|
||||
SET(CMAKE_REQUIRED_LIBRARIES "${GNUTLS_LIBRARY}")
|
||||
CHECK_FUNCTION_EXISTS(gnutls_priority_set_direct VMIME_HAVE_GNUTLS_PRIORITY_FUNCS)
|
||||
|
||||
|
||||
OPTION(
|
||||
VMIME_HAVE_TLS_SUPPORT
|
||||
"SSL/TLS support (requires either GNU TLS or OpenSSL library)"
|
||||
ON
|
||||
)
|
||||
|
||||
SET(
|
||||
VMIME_TLS_SUPPORT_LIB
|
||||
"gnutls"
|
||||
CACHE
|
||||
STRING
|
||||
"Library to use for SSL/TLS conversion"
|
||||
)
|
||||
SET_PROPERTY(
|
||||
CACHE
|
||||
VMIME_TLS_SUPPORT_LIB
|
||||
PROPERTY STRINGS gnutls openssl
|
||||
)
|
||||
|
||||
|
||||
IF(VMIME_HAVE_TLS_SUPPORT)
|
||||
|
||||
SET(
|
||||
VMIME_TLS_SUPPORT_LIB
|
||||
"gnutls"
|
||||
CACHE
|
||||
STRING
|
||||
"Library to use for SSL/TLS conversion"
|
||||
)
|
||||
SET_PROPERTY(
|
||||
CACHE
|
||||
VMIME_TLS_SUPPORT_LIB
|
||||
PROPERTY STRINGS gnutls openssl
|
||||
)
|
||||
|
||||
IF(VMIME_TLS_SUPPORT_LIB STREQUAL "gnutls")
|
||||
|
||||
INCLUDE(FindGnuTLS)
|
||||
SET(CMAKE_REQUIRED_LIBRARIES "${GNUTLS_LIBRARY}")
|
||||
CHECK_FUNCTION_EXISTS(gnutls_priority_set_direct VMIME_HAVE_GNUTLS_PRIORITY_FUNCS)
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${INCLUDE_DIRECTORIES}
|
||||
${GNUTLS_INCLUDE_DIR}
|
||||
@ -701,6 +653,8 @@ IF(VMIME_HAVE_TLS_SUPPORT)
|
||||
|
||||
ELSEIF(VMIME_TLS_SUPPORT_LIB STREQUAL "openssl")
|
||||
|
||||
INCLUDE(FindOpenSSL)
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${INCLUDE_DIRECTORIES}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
@ -729,20 +683,7 @@ ENDIF(VMIME_HAVE_TLS_SUPPORT)
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Charset conversion library
|
||||
|
||||
INCLUDE(cmake/FindIconv.cmake)
|
||||
INCLUDE(cmake/FindICU.cmake)
|
||||
|
||||
FIND_PACKAGE(ICU QUIET)
|
||||
|
||||
IF(ICU_LIBRARIES)
|
||||
SET(VMIME_CHARSETCONV_LIB_DETECTED "icu")
|
||||
ELSEIF(ICONV_FOUND)
|
||||
SET(VMIME_CHARSETCONV_LIB_DETECTED "iconv")
|
||||
ELSEIF(WIN32)
|
||||
SET(VMIME_CHARSETCONV_LIB_DETECTED "win")
|
||||
ENDIF()
|
||||
# Charset conversion library (2/2)
|
||||
|
||||
SET(
|
||||
VMIME_CHARSETCONV_LIB
|
||||
@ -773,6 +714,14 @@ IF(VMIME_CHARSETCONV_LIB STREQUAL "iconv")
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(VMIME_BUILD_STATIC_LIBRARY)
|
||||
TARGET_LINK_LIBRARIES(
|
||||
${VMIME_LIBRARY_NAME}-static
|
||||
${TARGET_LINK_LIBRARIES}
|
||||
${ICONV_LIBRARIES}
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
SET(VMIME_PKGCONFIG_LIBS "${VMIME_PKGCONFIG_LIBS} ${ICONV_LIBRARIES}")
|
||||
SET(VMIME_PKGCONFIG_CFLAGS "${VMIME_PKGCONFIG_CFLAGS} -I${ICONV_INCLUDE_DIR}")
|
||||
|
||||
@ -795,6 +744,14 @@ ELSEIF(VMIME_CHARSETCONV_LIB STREQUAL "icu")
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(VMIME_BUILD_STATIC_LIBRARY)
|
||||
TARGET_LINK_LIBRARIES(
|
||||
${VMIME_LIBRARY_NAME}-static
|
||||
${TARGET_LINK_LIBRARIES}
|
||||
${ICU_LIBRARIES}
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
SET(VMIME_PKGCONFIG_LIBS "${VMIME_PKGCONFIG_LIBS} ${ICU_LIBRARIES}")
|
||||
SET(VMIME_PKGCONFIG_CFLAGS "${VMIME_PKGCONFIG_CFLAGS} -I${ICU_INCLUDE_DIRS}")
|
||||
|
||||
@ -819,89 +776,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
|
||||
|
||||
@ -946,22 +820,22 @@ IF(WIN32)
|
||||
ENDIF()
|
||||
|
||||
# MLang
|
||||
CHECK_INCLUDE_FILES(Mlang.h VMIME_HAVE_MLANG_H)
|
||||
CHECK_LIBRARY_EXISTS("mlang" ConvertINetString "${CMAKE_LIBRARY_PATH}" VMIME_HAVE_MLANG_LIB)
|
||||
# CHECK_INCLUDE_FILES(Mlang.h VMIME_HAVE_MLANG_H)
|
||||
# CHECK_LIBRARY_EXISTS("mlang" ConvertINetString "${CMAKE_LIBRARY_PATH}" VMIME_HAVE_MLANG_LIB)
|
||||
|
||||
IF(VMIME_HAVE_MLANG_H)
|
||||
IF(VMIME_HAVE_MLANG_LIB)
|
||||
SET(VMIME_HAVE_MLANG ON)
|
||||
# IF(VMIME_HAVE_MLANG_H)
|
||||
# IF(VMIME_HAVE_MLANG_LIB)
|
||||
# SET(VMIME_HAVE_MLANG ON)
|
||||
|
||||
IF(VMIME_BUILD_SHARED_LIBRARY)
|
||||
TARGET_LINK_LIBRARIES(
|
||||
${VMIME_LIBRARY_NAME}
|
||||
${TARGET_LINK_LIBRARIES}
|
||||
"mlang"
|
||||
)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
# IF(VMIME_BUILD_SHARED_LIBRARY)
|
||||
# TARGET_LINK_LIBRARIES(
|
||||
# ${VMIME_LIBRARY_NAME}
|
||||
# ${TARGET_LINK_LIBRARIES}
|
||||
# "mlang"
|
||||
# )
|
||||
# ENDIF()
|
||||
# ENDIF()
|
||||
# ENDIF()
|
||||
|
||||
ENDIF()
|
||||
|
||||
@ -975,6 +849,9 @@ CHECK_FUNCTION_EXISTS(getnameinfo VMIME_HAVE_GETNAMEINFO)
|
||||
CHECK_FUNCTION_EXISTS(gettid VMIME_HAVE_GETTID)
|
||||
CHECK_FUNCTION_EXISTS(syscall VMIME_HAVE_SYSCALL)
|
||||
CHECK_SYMBOL_EXISTS(SYS_gettid sys/syscall.h VMIME_HAVE_SYSCALL_GETTID)
|
||||
CHECK_SYMBOL_EXISTS(getthrid unistd.h VMIME_HAVE_GETTHRID)
|
||||
CHECK_SYMBOL_EXISTS(thr_self sys/thr.h VMIME_HAVE_THR_SELF)
|
||||
CHECK_SYMBOL_EXISTS(_lwp_self sys/lwp.h VMIME_HAVE_LWP_SELF)
|
||||
|
||||
CHECK_SYMBOL_EXISTS(SO_KEEPALIVE sys/socket.h VMIME_HAVE_SO_KEEPALIVE)
|
||||
CHECK_SYMBOL_EXISTS(SO_NOSIGPIPE sys/socket.h VMIME_HAVE_SO_NOSIGPIPE)
|
||||
@ -1032,12 +909,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")
|
||||
|
||||
@ -1047,12 +924,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")
|
||||
|
||||
@ -1074,7 +951,7 @@ IF(VMIME_BUILD_DOCUMENTATION)
|
||||
FIND_PACKAGE(Doxygen)
|
||||
|
||||
IF(DOXYGEN_FOUND)
|
||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile @ONLY)
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile @ONLY)
|
||||
|
||||
# Make a target so that documentation can be generated by running "make doc"
|
||||
ADD_CUSTOM_TARGET(
|
||||
@ -1101,26 +978,84 @@ ENDIF()
|
||||
|
||||
# Path to 'sendmail' must be specified if Sendmail protocol is enabled
|
||||
IF(VMIME_HAVE_MESSAGING_PROTO_SENDMAIL)
|
||||
# Sendmail path
|
||||
# only configure this if we are enabling sendmail
|
||||
|
||||
FOREACH (SENDMAIL_PATH /usr/sbin/sendmail /usr/lib/sendmail /usr/bin/sendmail /bin/sendmail /var/qmail/bin/qmail-inject /bin/cgimail)
|
||||
IF(EXISTS ${SENDMAIL_PATH})
|
||||
MESSAGE(STATUS "Sendmail binary found at ${SENDMAIL_PATH}")
|
||||
SET(VMIME_DEFAULT_SENDMAIL_PATH ${SENDMAIL_PATH})
|
||||
ENDIF()
|
||||
ENDFOREACH(SENDMAIL_PATH)
|
||||
|
||||
SET(
|
||||
VMIME_SENDMAIL_PATH
|
||||
${VMIME_DEFAULT_SENDMAIL_PATH}
|
||||
CACHE
|
||||
STRING
|
||||
"Specifies the path to sendmail binary"
|
||||
)
|
||||
|
||||
IF(NOT VMIME_SENDMAIL_PATH OR VMIME_SENDMAIL_PATH STREQUAL "")
|
||||
MESSAGE(FATAL_ERROR "Enabling Sendmail protocol requires that you specify path to 'sendmail' binary.")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Build examples
|
||||
|
||||
IF(VMIME_BUILD_SAMPLES)
|
||||
ADD_SUBDIRECTORY(examples)
|
||||
ENDIF()
|
||||
|
||||
|
||||
# Set our configure file
|
||||
CONFIGURE_FILE(cmake/config.hpp.cmake ${CMAKE_BINARY_DIR}/src/vmime/config.hpp)
|
||||
LIST(APPEND VMIME_LIBRARY_GENERATED_INCLUDE_FILES ${CMAKE_BINARY_DIR}/src/vmime/config.hpp)
|
||||
|
||||
# PkgConfig post-configuration
|
||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/vmime.pc.in ${CMAKE_BINARY_DIR}/vmime.pc @ONLY)
|
||||
INSTALL(FILES ${CMAKE_BINARY_DIR}/vmime.pc DESTINATION "${VMIME_INSTALL_LIBDIR}/pkgconfig" COMPONENT headers)
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/vmime.pc.in ${CMAKE_BINARY_DIR}/vmime.pc @ONLY)
|
||||
|
||||
INCLUDE(CPack)
|
||||
|
||||
# Installation of libraries
|
||||
OPTION(
|
||||
VMIME_INSTALL
|
||||
"Should the vmime library be installed"
|
||||
ON
|
||||
)
|
||||
IF(VMIME_INSTALL)
|
||||
IF(VMIME_BUILD_SHARED_LIBRARY)
|
||||
INSTALL(
|
||||
TARGETS ${VMIME_LIBRARY_NAME}
|
||||
EXPORT ${VMIME_LIBRARY_NAME}-config
|
||||
LIBRARY DESTINATION "${VMIME_INSTALL_LIBDIR}"
|
||||
PUBLIC_HEADER DESTINATION "${VMIME_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT sharedlibs
|
||||
)
|
||||
INSTALL(
|
||||
EXPORT ${VMIME_LIBRARY_NAME}-config
|
||||
DESTINATION "${VMIME_INSTALL_LIBDIR}/cmake/vmime"
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(VMIME_BUILD_STATIC_LIBRARY)
|
||||
INSTALL(
|
||||
TARGETS ${VMIME_LIBRARY_NAME}-static
|
||||
EXPORT ${VMIME_LIBRARY_NAME}-static-config
|
||||
ARCHIVE DESTINATION "${VMIME_INSTALL_LIBDIR}"
|
||||
PUBLIC_HEADER DESTINATION "${VMIME_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT staticlibs
|
||||
)
|
||||
INSTALL(
|
||||
EXPORT ${VMIME_LIBRARY_NAME}-static-config
|
||||
DESTINATION "${VMIME_INSTALL_LIBDIR}/cmake/vmime"
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
# Installation of header files
|
||||
INSTALL_HEADERS_WITH_DIRECTORY(VMIME_LIBRARY_INCLUDE_FILES headers "${CMAKE_CURRENT_SOURCE_DIR}/src/")
|
||||
INSTALL_HEADERS_WITH_DIRECTORY(VMIME_LIBRARY_GENERATED_INCLUDE_FILES headers "${CMAKE_BINARY_DIR}/src")
|
||||
|
||||
INSTALL(FILES ${CMAKE_BINARY_DIR}/vmime.pc DESTINATION "${VMIME_INSTALL_LIBDIR}/pkgconfig" COMPONENT headers)
|
||||
|
||||
MESSAGE("")
|
||||
MESSAGE("VMime will install to the following directories:")
|
||||
MESSAGE(" libraries: ${VMIME_INSTALL_LIBDIR}")
|
||||
MESSAGE(" headers: ${VMIME_INSTALL_INCLUDEDIR}")
|
||||
MESSAGE("")
|
||||
ENDIF(VMIME_INSTALL)
|
||||
|
26
COPYING.OpenSSL
Normal file
26
COPYING.OpenSSL
Normal file
@ -0,0 +1,26 @@
|
||||
OpenSSL License Exception
|
||||
-------------------------
|
||||
|
||||
Copyright (C) 2002-2020, 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 3 (GPL) as published by
|
||||
the Free Software Foundation.
|
||||
The full text of the GPL can be found in the COPYING file.
|
||||
|
||||
In addition, as a special exception, the copyright holders give permission
|
||||
to link the code of portions of this program against the OpenSSL library
|
||||
according to the terms described here:
|
||||
|
||||
You have permission to copy, modify, propagate, and distribute a work
|
||||
formed by combining OpenSSL with VMime, or a work derivative of such a
|
||||
combination, even if such copying, modification, propagation, or
|
||||
distribution would otherwise violate the terms of the GPL. You must
|
||||
comply with the GPL in all respects for all of the code used other than
|
||||
OpenSSL.
|
||||
|
||||
You may include this OpenSSL exception and its grant of permissions when
|
||||
you distribute VMime. Inclusion of this notice with such a distribution
|
||||
constitutes a grant of such permission. If you do not wish to grant these
|
||||
permissions, delete this file.
|
||||
|
94
HACKING
94
HACKING
@ -80,73 +80,91 @@ 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)
|
||||
{
|
||||
case 0:
|
||||
switch (expr) {
|
||||
|
||||
something;
|
||||
break;
|
||||
case 0:
|
||||
|
||||
case 1:
|
||||
something;
|
||||
break;
|
||||
|
||||
something_else;
|
||||
break;
|
||||
case 1:
|
||||
|
||||
case 2:
|
||||
{
|
||||
int var = 42;
|
||||
another_thing;
|
||||
break;
|
||||
}
|
||||
something_else;
|
||||
break;
|
||||
|
||||
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,136 +0,0 @@
|
||||
# https://github.com/petroules/solar-cmake
|
||||
#
|
||||
# Based on the Qt 5 processor detection code, so should be very accurate
|
||||
# https://qt.gitorious.org/qt/qtbase/blobs/master/src/corelib/global/qprocessordetection.h
|
||||
# Currently handles arm (v5, v6, v7), x86 (32/64), ia64, and ppc (32/64)
|
||||
|
||||
# Regarding POWER/PowerPC, just as is noted in the Qt source,
|
||||
# "There are many more known variants/revisions that we do not handle/detect."
|
||||
|
||||
set(archdetect_c_code "
|
||||
#if defined(__arm__) || defined(__TARGET_ARCH_ARM)
|
||||
#if defined(__ARM_ARCH_7__) \\
|
||||
|| defined(__ARM_ARCH_7A__) \\
|
||||
|| defined(__ARM_ARCH_7R__) \\
|
||||
|| defined(__ARM_ARCH_7M__) \\
|
||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7)
|
||||
#error cmake_ARCH armv7
|
||||
#elif defined(__ARM_ARCH_6__) \\
|
||||
|| defined(__ARM_ARCH_6J__) \\
|
||||
|| defined(__ARM_ARCH_6T2__) \\
|
||||
|| defined(__ARM_ARCH_6Z__) \\
|
||||
|| defined(__ARM_ARCH_6K__) \\
|
||||
|| defined(__ARM_ARCH_6ZK__) \\
|
||||
|| defined(__ARM_ARCH_6M__) \\
|
||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6)
|
||||
#error cmake_ARCH armv6
|
||||
#elif defined(__ARM_ARCH_5TEJ__) \\
|
||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5)
|
||||
#error cmake_ARCH armv5
|
||||
#else
|
||||
#error cmake_ARCH arm
|
||||
#endif
|
||||
#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
|
||||
#error cmake_ARCH i386
|
||||
#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
|
||||
#error cmake_ARCH x86_64
|
||||
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
|
||||
#error cmake_ARCH ia64
|
||||
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\
|
||||
|| defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\
|
||||
|| defined(_M_MPPC) || defined(_M_PPC)
|
||||
#if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__)
|
||||
#error cmake_ARCH ppc64
|
||||
#else
|
||||
#error cmake_ARCH ppc
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#error cmake_ARCH unknown
|
||||
")
|
||||
|
||||
# Set ppc_support to TRUE before including this file or ppc and ppc64
|
||||
# will be treated as invalid architectures since they are no longer supported by Apple
|
||||
|
||||
function(target_architecture output_var)
|
||||
if(APPLE AND CMAKE_OSX_ARCHITECTURES)
|
||||
# On OS X we use CMAKE_OSX_ARCHITECTURES *if* it was set
|
||||
# First let's normalize the order of the values
|
||||
|
||||
# Note that it's not possible to compile PowerPC applications if you are using
|
||||
# the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we
|
||||
# disable it by default
|
||||
# See this page for more information:
|
||||
# http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4
|
||||
|
||||
# Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime.
|
||||
# On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise.
|
||||
|
||||
foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES})
|
||||
if("${osx_arch}" STREQUAL "ppc" AND ppc_support)
|
||||
set(osx_arch_ppc TRUE)
|
||||
elseif("${osx_arch}" STREQUAL "i386")
|
||||
set(osx_arch_i386 TRUE)
|
||||
elseif("${osx_arch}" STREQUAL "x86_64")
|
||||
set(osx_arch_x86_64 TRUE)
|
||||
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
|
||||
set(osx_arch_ppc64 TRUE)
|
||||
else()
|
||||
message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Now add all the architectures in our normalized order
|
||||
if(osx_arch_ppc)
|
||||
list(APPEND ARCH ppc)
|
||||
endif()
|
||||
|
||||
if(osx_arch_i386)
|
||||
list(APPEND ARCH i386)
|
||||
endif()
|
||||
|
||||
if(osx_arch_x86_64)
|
||||
list(APPEND ARCH x86_64)
|
||||
endif()
|
||||
|
||||
if(osx_arch_ppc64)
|
||||
list(APPEND ARCH ppc64)
|
||||
endif()
|
||||
else()
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/arch.c" "${archdetect_c_code}")
|
||||
|
||||
enable_language(C)
|
||||
|
||||
# Detect the architecture in a rather creative way...
|
||||
# This compiles a small C program which is a series of ifdefs that selects a
|
||||
# particular #error preprocessor directive whose message string contains the
|
||||
# target architecture. The program will always fail to compile (both because
|
||||
# file is not a valid C program, and obviously because of the presence of the
|
||||
# #error preprocessor directives... but by exploiting the preprocessor in this
|
||||
# way, we can detect the correct target architecture even when cross-compiling,
|
||||
# since the program itself never needs to be run (only the compiler/preprocessor)
|
||||
try_run(
|
||||
run_result_unused
|
||||
compile_result_unused
|
||||
"${CMAKE_BINARY_DIR}"
|
||||
"${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/arch.c"
|
||||
COMPILE_OUTPUT_VARIABLE ARCH
|
||||
CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
|
||||
)
|
||||
|
||||
# Parse the architecture name from the compiler output
|
||||
string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}")
|
||||
|
||||
# Get rid of the value marker leaving just the architecture name
|
||||
string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}")
|
||||
|
||||
# If we are compiling with an unknown architecture this variable should
|
||||
# already be set to "unknown" but in the case that it's empty (i.e. due
|
||||
# to a typo in the code), then set it to unknown
|
||||
if (NOT ARCH)
|
||||
set(ARCH unknown)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(${output_var} "${ARCH}" PARENT_SCOPE)
|
||||
endfunction()
|
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 (CROSS_COMPILING)
|
||||
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 (CROSS_COMPILING)
|
||||
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 (CROSS_COMPILING)
|
||||
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;
|
||||
}
|
@ -16,10 +16,6 @@
|
||||
#define VMIME_VERSION "@VMIME_VERSION@"
|
||||
#define VMIME_API "@VMIME_API_VERSION@"
|
||||
|
||||
// Target OS and architecture
|
||||
#define VMIME_TARGET_ARCH "@CMAKE_TARGET_ARCHITECTURES@"
|
||||
#define VMIME_TARGET_OS "@CMAKE_SYSTEM_NAME@"
|
||||
|
||||
// Set to 1 if debugging should be activated
|
||||
#define VMIME_DEBUG @VMIME_DEBUG@
|
||||
|
||||
@ -80,6 +76,9 @@ typedef unsigned @VMIME_64BIT_TYPE@ vmime_uint64;
|
||||
#cmakedefine01 VMIME_HAVE_GETTID
|
||||
#cmakedefine01 VMIME_HAVE_SYSCALL
|
||||
#cmakedefine01 VMIME_HAVE_SYSCALL_GETTID
|
||||
#cmakedefine01 VMIME_HAVE_GETTHRID
|
||||
#cmakedefine01 VMIME_HAVE_THR_SELF
|
||||
#cmakedefine01 VMIME_HAVE_LWP_SELF
|
||||
#cmakedefine01 VMIME_HAVE_GMTIME_S
|
||||
#cmakedefine01 VMIME_HAVE_GMTIME_R
|
||||
#cmakedefine01 VMIME_HAVE_LOCALTIME_S
|
||||
|
1
contrib/utf8/VERSION
Normal file
1
contrib/utf8/VERSION
Normal file
@ -0,0 +1 @@
|
||||
https://github.com/nemtrif/utfcpp/releases/tag/v4.0.5
|
@ -1,34 +1,46 @@
|
||||
// Copyright 2006 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
|
||||
#include "utf8/checked.h"
|
||||
#include "utf8/unchecked.h"
|
||||
|
||||
#endif // header guard
|
||||
// Copyright 2006 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
|
||||
/*
|
||||
To control the C++ language version used by the library, you can define UTF_CPP_CPLUSPLUS macro
|
||||
and set it to one of the values used by the __cplusplus predefined macro.
|
||||
|
||||
For instance,
|
||||
#define UTF_CPP_CPLUSPLUS 199711L
|
||||
will cause the UTF-8 CPP library to use only types and language features available in the C++ 98 standard.
|
||||
Some library features will be disabled.
|
||||
|
||||
If you leave UTF_CPP_CPLUSPLUS undefined, it will be internally assigned to __cplusplus.
|
||||
*/
|
||||
|
||||
#include "utf8/checked.h"
|
||||
#include "utf8/unchecked.h"
|
||||
|
||||
#endif // header guard
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2006 Nemanja Trifunovic
|
||||
// Copyright 2006-2016 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
@ -39,64 +39,62 @@ namespace utf8
|
||||
|
||||
// Exceptions that may be thrown from the library functions.
|
||||
class invalid_code_point : public exception {
|
||||
uint32_t cp;
|
||||
utfchar32_t cp;
|
||||
public:
|
||||
invalid_code_point(uint32_t cp) : cp(cp) {}
|
||||
virtual const char* what() const throw() { return "Invalid code point"; }
|
||||
uint32_t code_point() const {return cp;}
|
||||
invalid_code_point(utfchar32_t codepoint) : cp(codepoint) {}
|
||||
virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid code point"; }
|
||||
utfchar32_t code_point() const {return cp;}
|
||||
};
|
||||
|
||||
class invalid_utf8 : public exception {
|
||||
uint8_t u8;
|
||||
utfchar8_t u8;
|
||||
public:
|
||||
invalid_utf8 (uint8_t u) : u8(u) {}
|
||||
virtual const char* what() const throw() { return "Invalid UTF-8"; }
|
||||
uint8_t utf8_octet() const {return u8;}
|
||||
invalid_utf8 (utfchar8_t u) : u8(u) {}
|
||||
invalid_utf8 (char c) : u8(static_cast<utfchar8_t>(c)) {}
|
||||
virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid UTF-8"; }
|
||||
utfchar8_t utf8_octet() const {return u8;}
|
||||
};
|
||||
|
||||
class invalid_utf16 : public exception {
|
||||
uint16_t u16;
|
||||
utfchar16_t u16;
|
||||
public:
|
||||
invalid_utf16 (uint16_t u) : u16(u) {}
|
||||
virtual const char* what() const throw() { return "Invalid UTF-16"; }
|
||||
uint16_t utf16_word() const {return u16;}
|
||||
invalid_utf16 (utfchar16_t u) : u16(u) {}
|
||||
virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid UTF-16"; }
|
||||
utfchar16_t utf16_word() const {return u16;}
|
||||
};
|
||||
|
||||
class not_enough_room : public exception {
|
||||
public:
|
||||
virtual const char* what() const throw() { return "Not enough space"; }
|
||||
virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Not enough space"; }
|
||||
};
|
||||
|
||||
/// The library API - functions intended to be called by the users
|
||||
|
||||
template <typename octet_iterator>
|
||||
octet_iterator append(uint32_t cp, octet_iterator result)
|
||||
octet_iterator append(utfchar32_t cp, octet_iterator result)
|
||||
{
|
||||
if (!utf8::internal::is_code_point_valid(cp))
|
||||
throw invalid_code_point(cp);
|
||||
|
||||
if (cp < 0x80) // one octet
|
||||
*(result++) = static_cast<uint8_t>(cp);
|
||||
else if (cp < 0x800) { // two octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else if (cp < 0x10000) { // three octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else { // four octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
return result;
|
||||
return internal::append(cp, result);
|
||||
}
|
||||
|
||||
inline void append(utfchar32_t cp, std::string& s)
|
||||
{
|
||||
append(cp, std::back_inserter(s));
|
||||
}
|
||||
|
||||
template <typename word_iterator>
|
||||
word_iterator append16(utfchar32_t cp, word_iterator result)
|
||||
{
|
||||
if (!utf8::internal::is_code_point_valid(cp))
|
||||
throw invalid_code_point(cp);
|
||||
|
||||
return internal::append16(cp, result);
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename output_iterator>
|
||||
output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
|
||||
output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, utfchar32_t replacement)
|
||||
{
|
||||
while (start != end) {
|
||||
octet_iterator sequence_start = start;
|
||||
@ -107,7 +105,9 @@ namespace utf8
|
||||
*out++ = *it;
|
||||
break;
|
||||
case internal::NOT_ENOUGH_ROOM:
|
||||
throw not_enough_room();
|
||||
out = utf8::append (replacement, out);
|
||||
start = end;
|
||||
break;
|
||||
case internal::INVALID_LEAD:
|
||||
out = utf8::append (replacement, out);
|
||||
++start;
|
||||
@ -129,14 +129,28 @@ namespace utf8
|
||||
template <typename octet_iterator, typename output_iterator>
|
||||
inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
|
||||
{
|
||||
static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
|
||||
static const utfchar32_t replacement_marker = utf8::internal::mask16(0xfffd);
|
||||
return utf8::replace_invalid(start, end, out, replacement_marker);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t next(octet_iterator& it, octet_iterator end)
|
||||
inline std::string replace_invalid(const std::string& s, utfchar32_t replacement)
|
||||
{
|
||||
uint32_t cp = 0;
|
||||
std::string result;
|
||||
replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::string replace_invalid(const std::string& s)
|
||||
{
|
||||
std::string result;
|
||||
replace_invalid(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
utfchar32_t next(octet_iterator& it, octet_iterator end)
|
||||
{
|
||||
utfchar32_t cp = 0;
|
||||
internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
|
||||
switch (err_code) {
|
||||
case internal::UTF8_OK :
|
||||
@ -146,21 +160,31 @@ namespace utf8
|
||||
case internal::INVALID_LEAD :
|
||||
case internal::INCOMPLETE_SEQUENCE :
|
||||
case internal::OVERLONG_SEQUENCE :
|
||||
throw invalid_utf8(*it);
|
||||
throw invalid_utf8(static_cast<utfchar8_t>(*it));
|
||||
case internal::INVALID_CODE_POINT :
|
||||
throw invalid_code_point(cp);
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
template <typename word_iterator>
|
||||
utfchar32_t next16(word_iterator& it, word_iterator end)
|
||||
{
|
||||
utfchar32_t cp = 0;
|
||||
internal::utf_error err_code = utf8::internal::validate_next16(it, end, cp);
|
||||
if (err_code == internal::NOT_ENOUGH_ROOM)
|
||||
throw not_enough_room();
|
||||
return cp;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t peek_next(octet_iterator it, octet_iterator end)
|
||||
utfchar32_t peek_next(octet_iterator it, octet_iterator end)
|
||||
{
|
||||
return utf8::next(it, end);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t prior(octet_iterator& it, octet_iterator start)
|
||||
utfchar32_t prior(octet_iterator& it, octet_iterator start)
|
||||
{
|
||||
// can't do much if it == start
|
||||
if (it == start)
|
||||
@ -174,23 +198,19 @@ namespace utf8
|
||||
return utf8::peek_next(it, end);
|
||||
}
|
||||
|
||||
/// Deprecated in versions that include "prior"
|
||||
template <typename octet_iterator>
|
||||
uint32_t previous(octet_iterator& it, octet_iterator pass_start)
|
||||
{
|
||||
octet_iterator end = it;
|
||||
while (utf8::internal::is_trail(*(--it)))
|
||||
if (it == pass_start)
|
||||
throw invalid_utf8(*it); // error - no lead byte in the sequence
|
||||
octet_iterator temp = it;
|
||||
return utf8::next(temp, end);
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename distance_type>
|
||||
void advance (octet_iterator& it, distance_type n, octet_iterator end)
|
||||
{
|
||||
for (distance_type i = 0; i < n; ++i)
|
||||
utf8::next(it, end);
|
||||
const distance_type zero(0);
|
||||
if (n < zero) {
|
||||
// backward
|
||||
for (distance_type i = n; i < zero; ++i)
|
||||
utf8::prior(it, end);
|
||||
} else {
|
||||
// forward
|
||||
for (distance_type i = zero; i < n; ++i)
|
||||
utf8::next(it, end);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
@ -207,23 +227,23 @@ namespace utf8
|
||||
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
|
||||
{
|
||||
while (start != end) {
|
||||
uint32_t cp = utf8::internal::mask16(*start++);
|
||||
utfchar32_t cp = utf8::internal::mask16(*start++);
|
||||
// Take care of surrogate pairs first
|
||||
if (utf8::internal::is_lead_surrogate(cp)) {
|
||||
if (start != end) {
|
||||
uint32_t trail_surrogate = utf8::internal::mask16(*start++);
|
||||
const utfchar32_t trail_surrogate = utf8::internal::mask16(*start++);
|
||||
if (utf8::internal::is_trail_surrogate(trail_surrogate))
|
||||
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
|
||||
else
|
||||
throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
|
||||
throw invalid_utf16(static_cast<utfchar16_t>(trail_surrogate));
|
||||
}
|
||||
else
|
||||
throw invalid_utf16(static_cast<uint16_t>(cp));
|
||||
throw invalid_utf16(static_cast<utfchar16_t>(cp));
|
||||
|
||||
}
|
||||
// Lone trail surrogate
|
||||
else if (utf8::internal::is_trail_surrogate(cp))
|
||||
throw invalid_utf16(static_cast<uint16_t>(cp));
|
||||
throw invalid_utf16(static_cast<utfchar16_t>(cp));
|
||||
|
||||
result = utf8::append(cp, result);
|
||||
}
|
||||
@ -233,14 +253,14 @@ namespace utf8
|
||||
template <typename u16bit_iterator, typename octet_iterator>
|
||||
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
|
||||
{
|
||||
while (start != end) {
|
||||
uint32_t cp = utf8::next(start, end);
|
||||
while (start < end) {
|
||||
const utfchar32_t cp = utf8::next(start, end);
|
||||
if (cp > 0xffff) { //make a surrogate pair
|
||||
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
|
||||
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
|
||||
*result++ = static_cast<utfchar16_t>((cp >> 10) + internal::LEAD_OFFSET);
|
||||
*result++ = static_cast<utfchar16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
|
||||
}
|
||||
else
|
||||
*result++ = static_cast<uint16_t>(cp);
|
||||
*result++ = static_cast<utfchar16_t>(cp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -257,7 +277,7 @@ namespace utf8
|
||||
template <typename octet_iterator, typename u32bit_iterator>
|
||||
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
|
||||
{
|
||||
while (start != end)
|
||||
while (start < end)
|
||||
(*result++) = utf8::next(start, end);
|
||||
|
||||
return result;
|
||||
@ -265,23 +285,28 @@ namespace utf8
|
||||
|
||||
// The iterator class
|
||||
template <typename octet_iterator>
|
||||
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
|
||||
class iterator {
|
||||
octet_iterator it;
|
||||
octet_iterator range_start;
|
||||
octet_iterator range_end;
|
||||
public:
|
||||
typedef utfchar32_t value_type;
|
||||
typedef utfchar32_t* pointer;
|
||||
typedef utfchar32_t& reference;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
iterator () {}
|
||||
explicit iterator (const octet_iterator& octet_it,
|
||||
const octet_iterator& range_start,
|
||||
const octet_iterator& range_end) :
|
||||
it(octet_it), range_start(range_start), range_end(range_end)
|
||||
const octet_iterator& rangestart,
|
||||
const octet_iterator& rangeend) :
|
||||
it(octet_it), range_start(rangestart), range_end(rangeend)
|
||||
{
|
||||
if (it < range_start || it > range_end)
|
||||
throw std::out_of_range("Invalid utf-8 iterator position");
|
||||
}
|
||||
// the default "big three" are OK
|
||||
octet_iterator base () const { return it; }
|
||||
uint32_t operator * () const
|
||||
utfchar32_t operator * () const
|
||||
{
|
||||
octet_iterator temp = it;
|
||||
return utf8::next(temp, range_end);
|
||||
@ -322,6 +347,13 @@ namespace utf8
|
||||
|
||||
} // namespace utf8
|
||||
|
||||
#if UTF_CPP_CPLUSPLUS >= 202002L // C++ 20 or later
|
||||
#include "cpp20.h"
|
||||
#elif UTF_CPP_CPLUSPLUS >= 201703L // C++ 17 or later
|
||||
#include "cpp17.h"
|
||||
#elif UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later
|
||||
#include "cpp11.h"
|
||||
#endif // C++ 11 or later
|
||||
|
||||
#endif //header guard
|
||||
|
||||
|
||||
|
@ -29,12 +29,42 @@ DEALINGS IN THE SOFTWARE.
|
||||
#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
|
||||
|
||||
#include <iterator>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
// Determine the C++ standard version.
|
||||
// If the user defines UTF_CPP_CPLUSPLUS, use that.
|
||||
// Otherwise, trust the unreliable predefined macro __cplusplus
|
||||
|
||||
#if !defined UTF_CPP_CPLUSPLUS
|
||||
#define UTF_CPP_CPLUSPLUS __cplusplus
|
||||
#endif
|
||||
|
||||
#if UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later
|
||||
#define UTF_CPP_OVERRIDE override
|
||||
#define UTF_CPP_NOEXCEPT noexcept
|
||||
#else // C++ 98/03
|
||||
#define UTF_CPP_OVERRIDE
|
||||
#define UTF_CPP_NOEXCEPT throw()
|
||||
#endif // C++ 11 or later
|
||||
|
||||
|
||||
namespace utf8
|
||||
{
|
||||
typedef vmime_uint8 uint8_t;
|
||||
typedef vmime_uint16 uint16_t;
|
||||
typedef vmime_uint32 uint32_t;
|
||||
// The typedefs for 8-bit, 16-bit and 32-bit code units
|
||||
#if UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later
|
||||
#if UTF_CPP_CPLUSPLUS >= 202002L // C++ 20 or later
|
||||
typedef char8_t utfchar8_t;
|
||||
#else // C++ 11/14/17
|
||||
typedef unsigned char utfchar8_t;
|
||||
#endif
|
||||
typedef char16_t utfchar16_t;
|
||||
typedef char32_t utfchar32_t;
|
||||
#else // C++ 98/03
|
||||
typedef unsigned char utfchar8_t;
|
||||
typedef unsigned short utfchar16_t;
|
||||
typedef unsigned int utfchar32_t;
|
||||
#endif // C++ 11 or later
|
||||
|
||||
// Helper code - not intended to be directly called by the library users. May be changed at any time
|
||||
namespace internal
|
||||
@ -42,61 +72,62 @@ namespace internal
|
||||
// Unicode constants
|
||||
// Leading (high) surrogates: 0xd800 - 0xdbff
|
||||
// Trailing (low) surrogates: 0xdc00 - 0xdfff
|
||||
const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
|
||||
const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
|
||||
const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
|
||||
const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
|
||||
const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10);
|
||||
const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
|
||||
const utfchar16_t LEAD_SURROGATE_MIN = 0xd800u;
|
||||
const utfchar16_t LEAD_SURROGATE_MAX = 0xdbffu;
|
||||
const utfchar16_t TRAIL_SURROGATE_MIN = 0xdc00u;
|
||||
const utfchar16_t TRAIL_SURROGATE_MAX = 0xdfffu;
|
||||
const utfchar16_t LEAD_OFFSET = 0xd7c0u; // LEAD_SURROGATE_MIN - (0x10000 >> 10)
|
||||
const utfchar32_t SURROGATE_OFFSET = 0xfca02400u; // 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN
|
||||
|
||||
// Maximum valid value for a Unicode code point
|
||||
const uint32_t CODE_POINT_MAX = 0x0010ffffu;
|
||||
const utfchar32_t CODE_POINT_MAX = 0x0010ffffu;
|
||||
|
||||
template<typename octet_type>
|
||||
inline uint8_t mask8(octet_type oc)
|
||||
inline utfchar8_t mask8(octet_type oc)
|
||||
{
|
||||
return static_cast<uint8_t>(0xff & oc);
|
||||
return static_cast<utfchar8_t>(0xff & oc);
|
||||
}
|
||||
template<typename u16_type>
|
||||
inline uint16_t mask16(u16_type oc)
|
||||
inline utfchar16_t mask16(u16_type oc)
|
||||
{
|
||||
return static_cast<uint16_t>(0xffff & oc);
|
||||
return static_cast<utfchar16_t>(0xffff & oc);
|
||||
}
|
||||
|
||||
template<typename octet_type>
|
||||
inline bool is_trail(octet_type oc)
|
||||
{
|
||||
return ((utf8::internal::mask8(oc) >> 6) == 0x2);
|
||||
}
|
||||
|
||||
template <typename u16>
|
||||
inline bool is_lead_surrogate(u16 cp)
|
||||
inline bool is_lead_surrogate(utfchar32_t cp)
|
||||
{
|
||||
return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
|
||||
}
|
||||
|
||||
template <typename u16>
|
||||
inline bool is_trail_surrogate(u16 cp)
|
||||
inline bool is_trail_surrogate(utfchar32_t cp)
|
||||
{
|
||||
return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
|
||||
}
|
||||
|
||||
template <typename u16>
|
||||
inline bool is_surrogate(u16 cp)
|
||||
inline bool is_surrogate(utfchar32_t cp)
|
||||
{
|
||||
return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
|
||||
}
|
||||
|
||||
template <typename u32>
|
||||
inline bool is_code_point_valid(u32 cp)
|
||||
inline bool is_code_point_valid(utfchar32_t cp)
|
||||
{
|
||||
return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
inline typename std::iterator_traits<octet_iterator>::difference_type
|
||||
sequence_length(octet_iterator lead_it)
|
||||
inline bool is_in_bmp(utfchar32_t cp)
|
||||
{
|
||||
uint8_t lead = utf8::internal::mask8(*lead_it);
|
||||
return cp < utfchar32_t(0x10000);
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
int sequence_length(octet_iterator lead_it)
|
||||
{
|
||||
const utfchar8_t lead = utf8::internal::mask8(*lead_it);
|
||||
if (lead < 0x80)
|
||||
return 1;
|
||||
else if ((lead >> 5) == 0x6)
|
||||
@ -109,22 +140,20 @@ namespace internal
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename octet_difference_type>
|
||||
inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
|
||||
inline bool is_overlong_sequence(utfchar32_t cp, int length)
|
||||
{
|
||||
if (cp < 0x80) {
|
||||
if (length != 1)
|
||||
if (length != 1)
|
||||
return true;
|
||||
}
|
||||
else if (cp < 0x800) {
|
||||
if (length != 2)
|
||||
if (length != 2)
|
||||
return true;
|
||||
}
|
||||
else if (cp < 0x10000) {
|
||||
if (length != 3)
|
||||
if (length != 3)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -132,7 +161,7 @@ namespace internal
|
||||
|
||||
/// Helper for get_sequence_x
|
||||
template <typename octet_iterator>
|
||||
utf_error increase_safely(octet_iterator& it, octet_iterator end)
|
||||
utf_error increase_safely(octet_iterator& it, const octet_iterator end)
|
||||
{
|
||||
if (++it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
@ -147,7 +176,7 @@ namespace internal
|
||||
|
||||
/// get_sequence_x functions decode utf-8 sequences of the length x
|
||||
template <typename octet_iterator>
|
||||
utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
utf_error get_sequence_1(octet_iterator& it, octet_iterator end, utfchar32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
@ -158,9 +187,9 @@ namespace internal
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
utf_error get_sequence_2(octet_iterator& it, octet_iterator end, utfchar32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
code_point = utf8::internal::mask8(*it);
|
||||
@ -173,11 +202,11 @@ namespace internal
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
utf_error get_sequence_3(octet_iterator& it, octet_iterator end, utfchar32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
|
||||
code_point = utf8::internal::mask8(*it);
|
||||
|
||||
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
|
||||
@ -192,7 +221,7 @@ namespace internal
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
utf_error get_sequence_4(octet_iterator& it, octet_iterator end, utfchar32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
@ -217,16 +246,18 @@ namespace internal
|
||||
#undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
|
||||
|
||||
template <typename octet_iterator>
|
||||
utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
|
||||
utf_error validate_next(octet_iterator& it, octet_iterator end, utfchar32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
|
||||
// Save the original value of it so we can go back in case of failure
|
||||
// Of course, it does not make much sense with i.e. stream iterators
|
||||
octet_iterator original_it = it;
|
||||
|
||||
uint32_t cp = 0;
|
||||
utfchar32_t cp = 0;
|
||||
// Determine the sequence length based on the lead octet
|
||||
typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
|
||||
const octet_difference_type length = utf8::internal::sequence_length(it);
|
||||
const int length = utf8::internal::sequence_length(it);
|
||||
|
||||
// Get trail octets and calculate the code point
|
||||
utf_error err = UTF8_OK;
|
||||
@ -259,7 +290,7 @@ namespace internal
|
||||
else
|
||||
err = OVERLONG_SEQUENCE;
|
||||
}
|
||||
else
|
||||
else
|
||||
err = INVALID_CODE_POINT;
|
||||
}
|
||||
|
||||
@ -270,16 +301,133 @@ namespace internal
|
||||
|
||||
template <typename octet_iterator>
|
||||
inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
|
||||
uint32_t ignored;
|
||||
utfchar32_t ignored;
|
||||
return utf8::internal::validate_next(it, end, ignored);
|
||||
}
|
||||
|
||||
template <typename word_iterator>
|
||||
utf_error validate_next16(word_iterator& it, word_iterator end, utfchar32_t& code_point)
|
||||
{
|
||||
if (it == end)
|
||||
return NOT_ENOUGH_ROOM;
|
||||
// Save the original value of it so we can go back in case of failure
|
||||
// Of course, it does not make much sense with i.e. stream iterators
|
||||
word_iterator original_it = it;
|
||||
|
||||
utf_error err = UTF8_OK;
|
||||
|
||||
const utfchar16_t first_word = *it++;
|
||||
if (!is_surrogate(first_word)) {
|
||||
code_point = first_word;
|
||||
return UTF8_OK;
|
||||
}
|
||||
else {
|
||||
if (it == end)
|
||||
err = NOT_ENOUGH_ROOM;
|
||||
else if (is_lead_surrogate(first_word)) {
|
||||
const utfchar16_t second_word = *it++;
|
||||
if (is_trail_surrogate(second_word)) {
|
||||
code_point = (first_word << 10) + second_word + SURROGATE_OFFSET;
|
||||
return UTF8_OK;
|
||||
} else
|
||||
err = INCOMPLETE_SEQUENCE;
|
||||
|
||||
} else {
|
||||
err = INVALID_LEAD;
|
||||
}
|
||||
}
|
||||
// error branch
|
||||
it = original_it;
|
||||
return err;
|
||||
}
|
||||
|
||||
// Internal implementation of both checked and unchecked append() function
|
||||
// This function will be invoked by the overloads below, as they will know
|
||||
// the octet_type.
|
||||
template <typename octet_iterator, typename octet_type>
|
||||
octet_iterator append(utfchar32_t cp, octet_iterator result) {
|
||||
if (cp < 0x80) // one octet
|
||||
*(result++) = static_cast<octet_type>(cp);
|
||||
else if (cp < 0x800) { // two octets
|
||||
*(result++) = static_cast<octet_type>((cp >> 6) | 0xc0);
|
||||
*(result++) = static_cast<octet_type>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else if (cp < 0x10000) { // three octets
|
||||
*(result++) = static_cast<octet_type>((cp >> 12) | 0xe0);
|
||||
*(result++) = static_cast<octet_type>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<octet_type>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else { // four octets
|
||||
*(result++) = static_cast<octet_type>((cp >> 18) | 0xf0);
|
||||
*(result++) = static_cast<octet_type>(((cp >> 12) & 0x3f)| 0x80);
|
||||
*(result++) = static_cast<octet_type>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<octet_type>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// One of the following overloads will be invoked from the API calls
|
||||
|
||||
// A simple (but dangerous) case: the caller appends byte(s) to a char array
|
||||
inline char* append(utfchar32_t cp, char* result) {
|
||||
return append<char*, char>(cp, result);
|
||||
}
|
||||
|
||||
// Hopefully, most common case: the caller uses back_inserter
|
||||
// i.e. append(cp, std::back_inserter(str));
|
||||
template<typename container_type>
|
||||
std::back_insert_iterator<container_type> append
|
||||
(utfchar32_t cp, std::back_insert_iterator<container_type> result) {
|
||||
return append<std::back_insert_iterator<container_type>,
|
||||
typename container_type::value_type>(cp, result);
|
||||
}
|
||||
|
||||
// The caller uses some other kind of output operator - not covered above
|
||||
// Note that in this case we are not able to determine octet_type
|
||||
// so we assume it's utfchar8_t; that can cause a conversion warning if we are wrong.
|
||||
template <typename octet_iterator>
|
||||
octet_iterator append(utfchar32_t cp, octet_iterator result) {
|
||||
return append<octet_iterator, utfchar8_t>(cp, result);
|
||||
}
|
||||
|
||||
// Internal implementation of both checked and unchecked append16() function
|
||||
// This function will be invoked by the overloads below, as they will know
|
||||
// the word_type.
|
||||
template <typename word_iterator, typename word_type>
|
||||
word_iterator append16(utfchar32_t cp, word_iterator result) {
|
||||
if (is_in_bmp(cp))
|
||||
*(result++) = static_cast<word_type>(cp);
|
||||
else {
|
||||
// Code points from the supplementary planes are encoded via surrogate pairs
|
||||
*(result++) = static_cast<word_type>(LEAD_OFFSET + (cp >> 10));
|
||||
*(result++) = static_cast<word_type>(TRAIL_SURROGATE_MIN + (cp & 0x3FF));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Hopefully, most common case: the caller uses back_inserter
|
||||
// i.e. append16(cp, std::back_inserter(str));
|
||||
template<typename container_type>
|
||||
std::back_insert_iterator<container_type> append16
|
||||
(utfchar32_t cp, std::back_insert_iterator<container_type> result) {
|
||||
return append16<std::back_insert_iterator<container_type>,
|
||||
typename container_type::value_type>(cp, result);
|
||||
}
|
||||
|
||||
// The caller uses some other kind of output operator - not covered above
|
||||
// Note that in this case we are not able to determine word_type
|
||||
// so we assume it's utfchar16_t; that can cause a conversion warning if we are wrong.
|
||||
template <typename word_iterator>
|
||||
word_iterator append16(utfchar32_t cp, word_iterator result) {
|
||||
return append16<word_iterator, utfchar16_t>(cp, result);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// The library API - functions intended to be called by the users
|
||||
|
||||
// Byte order mark
|
||||
const uint8_t bom[] = {0xef, 0xbb, 0xbf};
|
||||
const utfchar8_t bom[] = {0xef, 0xbb, 0xbf};
|
||||
|
||||
template <typename octet_iterator>
|
||||
octet_iterator find_invalid(octet_iterator start, octet_iterator end)
|
||||
@ -293,12 +441,36 @@ namespace internal
|
||||
return result;
|
||||
}
|
||||
|
||||
inline const char* find_invalid(const char* str)
|
||||
{
|
||||
const char* end = str + std::strlen(str);
|
||||
return find_invalid(str, end);
|
||||
}
|
||||
|
||||
inline std::size_t find_invalid(const std::string& s)
|
||||
{
|
||||
std::string::const_iterator invalid = find_invalid(s.begin(), s.end());
|
||||
return (invalid == s.end()) ? std::string::npos : static_cast<std::size_t>(invalid - s.begin());
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
inline bool is_valid(octet_iterator start, octet_iterator end)
|
||||
{
|
||||
return (utf8::find_invalid(start, end) == end);
|
||||
}
|
||||
|
||||
inline bool is_valid(const char* str)
|
||||
{
|
||||
return (*(utf8::find_invalid(str)) == '\0');
|
||||
}
|
||||
|
||||
inline bool is_valid(const std::string& s)
|
||||
{
|
||||
return is_valid(s.begin(), s.end());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename octet_iterator>
|
||||
inline bool starts_with_bom (octet_iterator it, octet_iterator end)
|
||||
{
|
||||
@ -309,16 +481,10 @@ namespace internal
|
||||
);
|
||||
}
|
||||
|
||||
//Deprecated in release 2.3
|
||||
template <typename octet_iterator>
|
||||
inline bool is_bom (octet_iterator it)
|
||||
inline bool starts_with_bom(const std::string& s)
|
||||
{
|
||||
return (
|
||||
(utf8::internal::mask8(*it++)) == bom[0] &&
|
||||
(utf8::internal::mask8(*it++)) == bom[1] &&
|
||||
(utf8::internal::mask8(*it)) == bom[2]
|
||||
);
|
||||
}
|
||||
return starts_with_bom(s.begin(), s.end());
|
||||
}
|
||||
} // namespace utf8
|
||||
|
||||
#endif // header guard
|
||||
|
70
contrib/utf8/utf8/cpp11.h
Normal file
70
contrib/utf8/utf8/cpp11.h
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2018 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_a184c22c_d012_11e8_a8d5_f2801f1b9fd1
|
||||
#define UTF8_FOR_CPP_a184c22c_d012_11e8_a8d5_f2801f1b9fd1
|
||||
|
||||
#include "checked.h"
|
||||
|
||||
namespace utf8
|
||||
{
|
||||
inline void append16(utfchar32_t cp, std::u16string& s)
|
||||
{
|
||||
append16(cp, std::back_inserter(s));
|
||||
}
|
||||
|
||||
inline std::string utf16to8(const std::u16string& s)
|
||||
{
|
||||
std::string result;
|
||||
utf16to8(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u16string utf8to16(const std::string& s)
|
||||
{
|
||||
std::u16string result;
|
||||
utf8to16(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::string utf32to8(const std::u32string& s)
|
||||
{
|
||||
std::string result;
|
||||
utf32to8(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u32string utf8to32(const std::string& s)
|
||||
{
|
||||
std::u32string result;
|
||||
utf8to32(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
} // namespace utf8
|
||||
|
||||
#endif // header guard
|
||||
|
96
contrib/utf8/utf8/cpp17.h
Normal file
96
contrib/utf8/utf8/cpp17.h
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright 2018 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_7e906c01_03a3_4daf_b420_ea7ea952b3c9
|
||||
#define UTF8_FOR_CPP_7e906c01_03a3_4daf_b420_ea7ea952b3c9
|
||||
|
||||
#include "cpp11.h"
|
||||
|
||||
namespace utf8
|
||||
{
|
||||
inline std::string utf16to8(std::u16string_view s)
|
||||
{
|
||||
std::string result;
|
||||
utf16to8(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u16string utf8to16(std::string_view s)
|
||||
{
|
||||
std::u16string result;
|
||||
utf8to16(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::string utf32to8(std::u32string_view s)
|
||||
{
|
||||
std::string result;
|
||||
utf32to8(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u32string utf8to32(std::string_view s)
|
||||
{
|
||||
std::u32string result;
|
||||
utf8to32(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::size_t find_invalid(std::string_view s)
|
||||
{
|
||||
std::string_view::const_iterator invalid = find_invalid(s.begin(), s.end());
|
||||
return (invalid == s.end()) ? std::string_view::npos : static_cast<std::size_t>(invalid - s.begin());
|
||||
}
|
||||
|
||||
inline bool is_valid(std::string_view s)
|
||||
{
|
||||
return is_valid(s.begin(), s.end());
|
||||
}
|
||||
|
||||
inline std::string replace_invalid(std::string_view s, char32_t replacement)
|
||||
{
|
||||
std::string result;
|
||||
replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::string replace_invalid(std::string_view s)
|
||||
{
|
||||
std::string result;
|
||||
replace_invalid(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool starts_with_bom(std::string_view s)
|
||||
{
|
||||
return starts_with_bom(s.begin(), s.end());
|
||||
}
|
||||
|
||||
} // namespace utf8
|
||||
|
||||
#endif // header guard
|
||||
|
124
contrib/utf8/utf8/cpp20.h
Normal file
124
contrib/utf8/utf8/cpp20.h
Normal file
@ -0,0 +1,124 @@
|
||||
// Copyright 2022 Nemanja Trifunovic
|
||||
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTF8_FOR_CPP_207e906c01_03a3_4daf_b420_ea7ea952b3c9
|
||||
#define UTF8_FOR_CPP_207e906c01_03a3_4daf_b420_ea7ea952b3c9
|
||||
|
||||
#include "cpp17.h"
|
||||
|
||||
namespace utf8
|
||||
{
|
||||
inline std::u8string utf16tou8(const std::u16string& s)
|
||||
{
|
||||
std::u8string result;
|
||||
utf16to8(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u8string utf16tou8(std::u16string_view s)
|
||||
{
|
||||
std::u8string result;
|
||||
utf16to8(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u16string utf8to16(const std::u8string& s)
|
||||
{
|
||||
std::u16string result;
|
||||
utf8to16(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u16string utf8to16(const std::u8string_view& s)
|
||||
{
|
||||
std::u16string result;
|
||||
utf8to16(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u8string utf32tou8(const std::u32string& s)
|
||||
{
|
||||
std::u8string result;
|
||||
utf32to8(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u8string utf32tou8(const std::u32string_view& s)
|
||||
{
|
||||
std::u8string result;
|
||||
utf32to8(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u32string utf8to32(const std::u8string& s)
|
||||
{
|
||||
std::u32string result;
|
||||
utf8to32(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u32string utf8to32(const std::u8string_view& s)
|
||||
{
|
||||
std::u32string result;
|
||||
utf8to32(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::size_t find_invalid(const std::u8string& s)
|
||||
{
|
||||
std::u8string::const_iterator invalid = find_invalid(s.begin(), s.end());
|
||||
return (invalid == s.end()) ? std::string_view::npos : static_cast<std::size_t>(invalid - s.begin());
|
||||
}
|
||||
|
||||
inline bool is_valid(const std::u8string& s)
|
||||
{
|
||||
return is_valid(s.begin(), s.end());
|
||||
}
|
||||
|
||||
inline std::u8string replace_invalid(const std::u8string& s, char32_t replacement)
|
||||
{
|
||||
std::u8string result;
|
||||
replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::u8string replace_invalid(const std::u8string& s)
|
||||
{
|
||||
std::u8string result;
|
||||
replace_invalid(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool starts_with_bom(const std::u8string& s)
|
||||
{
|
||||
return starts_with_bom(s.begin(), s.end());
|
||||
}
|
||||
|
||||
} // namespace utf8
|
||||
|
||||
#endif // header guard
|
||||
|
@ -32,37 +32,79 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
namespace utf8
|
||||
{
|
||||
namespace unchecked
|
||||
namespace unchecked
|
||||
{
|
||||
template <typename octet_iterator>
|
||||
octet_iterator append(uint32_t cp, octet_iterator result)
|
||||
octet_iterator append(utfchar32_t cp, octet_iterator result)
|
||||
{
|
||||
if (cp < 0x80) // one octet
|
||||
*(result++) = static_cast<uint8_t>(cp);
|
||||
else if (cp < 0x800) { // two octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else if (cp < 0x10000) { // three octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
}
|
||||
else { // four octets
|
||||
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
|
||||
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
|
||||
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
|
||||
return internal::append(cp, result);
|
||||
}
|
||||
|
||||
template <typename word_iterator>
|
||||
word_iterator append16(utfchar32_t cp, word_iterator result)
|
||||
{
|
||||
return internal::append16(cp, result);
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename output_iterator>
|
||||
output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, utfchar32_t replacement)
|
||||
{
|
||||
while (start != end) {
|
||||
octet_iterator sequence_start = start;
|
||||
internal::utf_error err_code = utf8::internal::validate_next(start, end);
|
||||
switch (err_code) {
|
||||
case internal::UTF8_OK :
|
||||
for (octet_iterator it = sequence_start; it != start; ++it)
|
||||
*out++ = *it;
|
||||
break;
|
||||
case internal::NOT_ENOUGH_ROOM:
|
||||
out = utf8::unchecked::append(replacement, out);
|
||||
start = end;
|
||||
break;
|
||||
case internal::INVALID_LEAD:
|
||||
out = utf8::unchecked::append(replacement, out);
|
||||
++start;
|
||||
break;
|
||||
case internal::INCOMPLETE_SEQUENCE:
|
||||
case internal::OVERLONG_SEQUENCE:
|
||||
case internal::INVALID_CODE_POINT:
|
||||
out = utf8::unchecked::append(replacement, out);
|
||||
++start;
|
||||
// just one replacement mark for the sequence
|
||||
while (start != end && utf8::internal::is_trail(*start))
|
||||
++start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename output_iterator>
|
||||
inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
|
||||
{
|
||||
static const utfchar32_t replacement_marker = utf8::internal::mask16(0xfffd);
|
||||
return utf8::unchecked::replace_invalid(start, end, out, replacement_marker);
|
||||
}
|
||||
|
||||
inline std::string replace_invalid(const std::string& s, utfchar32_t replacement)
|
||||
{
|
||||
std::string result;
|
||||
replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::string replace_invalid(const std::string& s)
|
||||
{
|
||||
std::string result;
|
||||
replace_invalid(s.begin(), s.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t next(octet_iterator& it)
|
||||
utfchar32_t next(octet_iterator& it)
|
||||
{
|
||||
uint32_t cp = utf8::internal::mask8(*it);
|
||||
typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
|
||||
switch (length) {
|
||||
utfchar32_t cp = utf8::internal::mask8(*it);
|
||||
switch (utf8::internal::sequence_length(it)) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
@ -85,40 +127,50 @@ namespace utf8
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
return cp;
|
||||
return cp;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t peek_next(octet_iterator it)
|
||||
utfchar32_t peek_next(octet_iterator it)
|
||||
{
|
||||
return utf8::unchecked::next(it);
|
||||
return utf8::unchecked::next(it);
|
||||
}
|
||||
|
||||
template <typename word_iterator>
|
||||
utfchar32_t next16(word_iterator& it)
|
||||
{
|
||||
utfchar32_t cp = utf8::internal::mask16(*it++);
|
||||
if (utf8::internal::is_lead_surrogate(cp))
|
||||
return (cp << 10) + *it++ + utf8::internal::SURROGATE_OFFSET;
|
||||
return cp;
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
uint32_t prior(octet_iterator& it)
|
||||
utfchar32_t prior(octet_iterator& it)
|
||||
{
|
||||
while (utf8::internal::is_trail(*(--it))) ;
|
||||
octet_iterator temp = it;
|
||||
return utf8::unchecked::next(temp);
|
||||
}
|
||||
|
||||
// Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous)
|
||||
template <typename octet_iterator>
|
||||
inline uint32_t previous(octet_iterator& it)
|
||||
{
|
||||
return utf8::unchecked::prior(it);
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename distance_type>
|
||||
void advance (octet_iterator& it, distance_type n)
|
||||
void advance(octet_iterator& it, distance_type n)
|
||||
{
|
||||
for (distance_type i = 0; i < n; ++i)
|
||||
utf8::unchecked::next(it);
|
||||
const distance_type zero(0);
|
||||
if (n < zero) {
|
||||
// backward
|
||||
for (distance_type i = n; i < zero; ++i)
|
||||
utf8::unchecked::prior(it);
|
||||
} else {
|
||||
// forward
|
||||
for (distance_type i = zero; i < n; ++i)
|
||||
utf8::unchecked::next(it);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename octet_iterator>
|
||||
typename std::iterator_traits<octet_iterator>::difference_type
|
||||
distance (octet_iterator first, octet_iterator last)
|
||||
distance(octet_iterator first, octet_iterator last)
|
||||
{
|
||||
typename std::iterator_traits<octet_iterator>::difference_type dist;
|
||||
for (dist = 0; first < last; ++dist)
|
||||
@ -127,37 +179,39 @@ namespace utf8
|
||||
}
|
||||
|
||||
template <typename u16bit_iterator, typename octet_iterator>
|
||||
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
|
||||
{
|
||||
octet_iterator utf16to8(u16bit_iterator start, u16bit_iterator end, octet_iterator result)
|
||||
{
|
||||
while (start != end) {
|
||||
uint32_t cp = utf8::internal::mask16(*start++);
|
||||
// Take care of surrogate pairs first
|
||||
utfchar32_t cp = utf8::internal::mask16(*start++);
|
||||
// Take care of surrogate pairs first
|
||||
if (utf8::internal::is_lead_surrogate(cp)) {
|
||||
uint32_t trail_surrogate = utf8::internal::mask16(*start++);
|
||||
if (start == end)
|
||||
return result;
|
||||
utfchar32_t trail_surrogate = utf8::internal::mask16(*start++);
|
||||
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
|
||||
}
|
||||
result = utf8::unchecked::append(cp, result);
|
||||
}
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename u16bit_iterator, typename octet_iterator>
|
||||
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
|
||||
u16bit_iterator utf8to16(octet_iterator start, octet_iterator end, u16bit_iterator result)
|
||||
{
|
||||
while (start < end) {
|
||||
uint32_t cp = utf8::unchecked::next(start);
|
||||
utfchar32_t cp = utf8::unchecked::next(start);
|
||||
if (cp > 0xffff) { //make a surrogate pair
|
||||
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
|
||||
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
|
||||
*result++ = static_cast<utfchar16_t>((cp >> 10) + internal::LEAD_OFFSET);
|
||||
*result++ = static_cast<utfchar16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
|
||||
}
|
||||
else
|
||||
*result++ = static_cast<uint16_t>(cp);
|
||||
*result++ = static_cast<utfchar16_t>(cp);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename u32bit_iterator>
|
||||
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
|
||||
octet_iterator utf32to8(u32bit_iterator start, u32bit_iterator end, octet_iterator result)
|
||||
{
|
||||
while (start != end)
|
||||
result = utf8::unchecked::append(*(start++), result);
|
||||
@ -166,7 +220,7 @@ namespace utf8
|
||||
}
|
||||
|
||||
template <typename octet_iterator, typename u32bit_iterator>
|
||||
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
|
||||
u32bit_iterator utf8to32(octet_iterator start, octet_iterator end, u32bit_iterator result)
|
||||
{
|
||||
while (start < end)
|
||||
(*result++) = utf8::unchecked::next(start);
|
||||
@ -176,14 +230,19 @@ namespace utf8
|
||||
|
||||
// The iterator class
|
||||
template <typename octet_iterator>
|
||||
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
|
||||
class iterator {
|
||||
octet_iterator it;
|
||||
public:
|
||||
typedef utfchar32_t value_type;
|
||||
typedef utfchar32_t* pointer;
|
||||
typedef utfchar32_t& reference;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
iterator () {}
|
||||
explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
|
||||
// the default "big three" are OK
|
||||
octet_iterator base () const { return it; }
|
||||
uint32_t operator * () const
|
||||
utfchar32_t operator * () const
|
||||
{
|
||||
octet_iterator temp = it;
|
||||
return utf8::unchecked::next(temp);
|
||||
|
@ -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>();
|
||||
|
||||
@ -166,7 +166,7 @@ In VMime, error handling is exclusively based on exceptions, there is no error
|
||||
codes, or things like that.
|
||||
|
||||
VMime code may throw exceptions in many different situations: an unexpected
|
||||
error occured, an operation is not supported, etc. You should catch them if
|
||||
error occurred, an operation is not supported, etc. You should catch them if
|
||||
you want to report failures to the user. This is also useful when debugging
|
||||
your program.
|
||||
|
||||
@ -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,13 +612,12 @@ 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>
|
||||
(
|
||||
/* attachment data */ data,
|
||||
/* content type */ vmime::mediaType("image/jpeg"),
|
||||
/* description */ vmime::text("Holiday photo"),
|
||||
/* filename */ vmime::word("paris.jpg")
|
||||
);
|
||||
ref <vmime::attachment> att = vmime::make_shared <vmime::defaultAttachment>(
|
||||
/* attachment data */ data,
|
||||
/* content type */ vmime::mediaType("image/jpeg"),
|
||||
/* description */ vmime::text("Holiday photo"),
|
||||
/* filename */ vmime::word("paris.jpg")
|
||||
);
|
||||
\end{lstlisting}
|
||||
|
||||
You will see later that the {\vcode vmime::fileAttachment} class already
|
||||
@ -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
|
||||
|
131
doc/book/msg.tex
131
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,17 +256,17 @@ 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>
|
||||
(
|
||||
/* full path to file */ "/home/vincent/paris.jpg",
|
||||
/* content type */ vmime::mediaType("image/jpeg),
|
||||
/* description */ vmime::text("My holidays in Paris")
|
||||
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")
|
||||
);
|
||||
|
||||
// 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,11 +418,10 @@ 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>
|
||||
(
|
||||
/* full path to file */ "/home/vincent/paris.jpg",
|
||||
/* content type */ vmime::mediaType("image/jpeg),
|
||||
/* description */ vmime::text("My holidays in Paris")
|
||||
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")
|
||||
);
|
||||
|
||||
// Attach it to the message
|
||||
|
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>(
|
||||
"I'm writing this short text to test message construction " \
|
||||
"using the vmime::messageBuilder component."));
|
||||
mb.getTextPart()->setText(
|
||||
vmime::make_shared <vmime::stringContentHandler>(
|
||||
"I'm writing this short text to test message construction " \
|
||||
"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,17 +71,20 @@ int main()
|
||||
mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder"));
|
||||
|
||||
// Message body
|
||||
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."));
|
||||
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."
|
||||
)
|
||||
);
|
||||
|
||||
// Adding an attachment
|
||||
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
|
||||
);
|
||||
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
|
||||
);
|
||||
|
||||
a->getFileInfo().setFilename("example2.cpp");
|
||||
a->getFileInfo().setCreationDate(vmime::datetime("30 Apr 2003 14:30:00 +0200"));
|
||||
@ -101,20 +101,21 @@ int main()
|
||||
std::cout << "==================" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << 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,35 +135,40 @@ 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) << ". "
|
||||
<< part->getType().generate()
|
||||
<< " [" << part->getSize() << " byte(s)]"
|
||||
<< std::endl;
|
||||
std::cout
|
||||
<< (part->getNumber() + 1) << ". "
|
||||
<< part->getType().generate()
|
||||
<< " [" << part->getSize() << " byte(s)]"
|
||||
<< std::endl;
|
||||
|
||||
printStructure(part->getStructure(), level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const vmime::string getFolderPathString(vmime::shared_ptr <vmime::net::folder> f)
|
||||
{
|
||||
static const vmime::string getFolderPathString(vmime::shared_ptr <vmime::net::folder> f) {
|
||||
|
||||
const vmime::string n = f->getName().getBuffer();
|
||||
|
||||
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,8 +223,9 @@ static void printFolders(vmime::shared_ptr <vmime::net::folder> folder, const in
|
||||
|
||||
std::vector <vmime::shared_ptr <vmime::net::folder> > subFolders = folder->getFolders(false);
|
||||
|
||||
for (unsigned int i = 0 ; i < subFolders.size() ; ++i)
|
||||
for (unsigned int i = 0 ; i < subFolders.size() ; ++i) {
|
||||
printFolders(subFolders[i], level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -220,12 +233,13 @@ static void printFolders(vmime::shared_ptr <vmime::net::folder> folder, const in
|
||||
*
|
||||
* @param choices menu choices
|
||||
*/
|
||||
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,23 +335,25 @@ 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
|
||||
@ -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,55 +569,52 @@ static void connectStore()
|
||||
break;
|
||||
|
||||
// Show message envelope
|
||||
case 4:
|
||||
case 4: {
|
||||
|
||||
f->fetchMessage(msg, vmime::net::fetchAttributes::ENVELOPE);
|
||||
vmime::net::fetchAttributes attr(vmime::net::fetchAttributes::ENVELOPE);
|
||||
|
||||
#define ENV_HELPER(x) \
|
||||
try { std::cout << msg->getHeader()->x()->generate() << std::endl; } \
|
||||
catch (vmime::exception) { /* In case the header field does not exist. */ }
|
||||
// If you also want to fetch "Received: " fields:
|
||||
//attr.add("Received");
|
||||
|
||||
ENV_HELPER(From)
|
||||
ENV_HELPER(To)
|
||||
ENV_HELPER(Date)
|
||||
ENV_HELPER(Subject)
|
||||
f->fetchMessage(msg, attr);
|
||||
|
||||
#undef ENV_HELPER
|
||||
std::cout << msg->getHeader()->generate() << std::endl;
|
||||
|
||||
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;
|
||||
@ -622,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);
|
||||
|
||||
@ -640,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();
|
||||
|
||||
@ -659,19 +683,21 @@ 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);
|
||||
@ -687,8 +713,8 @@ static void connectStore()
|
||||
break;
|
||||
}
|
||||
// Add message
|
||||
case 10:
|
||||
{
|
||||
case 10: {
|
||||
|
||||
vmime::messageBuilder mb;
|
||||
|
||||
mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
|
||||
@ -698,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();
|
||||
|
||||
@ -735,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();
|
||||
|
||||
@ -812,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;
|
||||
@ -852,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:
|
||||
|
||||
@ -887,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,20 +3,23 @@
|
||||
#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;
|
||||
@ -24,31 +27,33 @@ class interactiveAuthenticator : public vmime::security::sasl::defaultSASLAuthen
|
||||
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,8 +59,9 @@ 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,28 +82,29 @@ 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())
|
||||
{
|
||||
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;
|
||||
default: type = "(unknown)"; break;
|
||||
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;
|
||||
default: type = "(unknown)"; break;
|
||||
}
|
||||
|
||||
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,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
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
|
||||
);
|
||||
|
||||
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,16 @@ 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(
|
||||
parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition,
|
||||
const bool allowGroup,
|
||||
bool *isLastAddressOfGroup
|
||||
) {
|
||||
|
||||
bool escaped = false;
|
||||
bool quoted = false;
|
||||
bool quotedRFC2047 = false;
|
||||
@ -78,135 +83,174 @@ 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])
|
||||
{
|
||||
case '\\':
|
||||
escaped = true;
|
||||
break;
|
||||
case '"':
|
||||
quoted = !quoted;
|
||||
break;
|
||||
case '<':
|
||||
inRouteAddr = true;
|
||||
break;
|
||||
case '>':
|
||||
inRouteAddr = false;
|
||||
break;
|
||||
|
||||
case '(':
|
||||
} else {
|
||||
|
||||
++commentLevel;
|
||||
break;
|
||||
switch (buffer[pos]) {
|
||||
|
||||
case ')':
|
||||
case '\\':
|
||||
|
||||
if (commentLevel > 0)
|
||||
--commentLevel;
|
||||
escaped = true;
|
||||
break;
|
||||
|
||||
break;
|
||||
case '"':
|
||||
|
||||
case '=':
|
||||
quoted = !quoted;
|
||||
break;
|
||||
|
||||
if (commentLevel == 0 && !quoted && !quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '?')
|
||||
{
|
||||
++pos;
|
||||
quotedRFC2047 = true;
|
||||
}
|
||||
case '<':
|
||||
|
||||
break;
|
||||
inRouteAddr = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
case '>':
|
||||
|
||||
if (commentLevel == 0 && quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '=')
|
||||
{
|
||||
++pos;
|
||||
quotedRFC2047 = false;
|
||||
}
|
||||
inRouteAddr = false;
|
||||
break;
|
||||
|
||||
break;
|
||||
case '(':
|
||||
|
||||
default:
|
||||
{
|
||||
if (commentLevel == 0 && !quoted && !quotedRFC2047 && !inRouteAddr)
|
||||
{
|
||||
switch (buffer[pos])
|
||||
{
|
||||
case ';':
|
||||
++commentLevel;
|
||||
break;
|
||||
|
||||
if (isGroup)
|
||||
{
|
||||
if (pos + 1 < end && buffer[pos + 1] == ',')
|
||||
++pos;
|
||||
}
|
||||
case ')':
|
||||
|
||||
if (isLastAddressOfGroup)
|
||||
*isLastAddressOfGroup = true;
|
||||
|
||||
stop = true;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
|
||||
isGroup = true;
|
||||
break;
|
||||
|
||||
case ',':
|
||||
|
||||
if (!isGroup) stop = true;
|
||||
break;
|
||||
if (commentLevel > 0) {
|
||||
--commentLevel;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '=':
|
||||
|
||||
if (commentLevel == 0 && !quoted && !quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '?') {
|
||||
++pos;
|
||||
quotedRFC2047 = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '?':
|
||||
|
||||
if (commentLevel == 0 && quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '=') {
|
||||
++pos;
|
||||
quotedRFC2047 = false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
if (commentLevel == 0 && !quoted && !quotedRFC2047 && !inRouteAddr) {
|
||||
|
||||
switch (buffer[pos]) {
|
||||
|
||||
case ';':
|
||||
|
||||
if (isGroup) {
|
||||
|
||||
if (pos + 1 < end && buffer[pos + 1] == ',') {
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (isLastAddressOfGroup) {
|
||||
*isLastAddressOfGroup = true;
|
||||
}
|
||||
|
||||
stop = true;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
|
||||
isGroup = true;
|
||||
break;
|
||||
|
||||
case ',':
|
||||
|
||||
if (!isGroup) {
|
||||
stop = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!stop)
|
||||
if (!stop) {
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (newPosition)
|
||||
{
|
||||
if (pos == end)
|
||||
*newPosition = end;
|
||||
else
|
||||
*newPosition = pos + 1; // ',' or ';'
|
||||
size_t newPos;
|
||||
|
||||
if (pos == end) {
|
||||
newPos = end;
|
||||
} else {
|
||||
newPos = pos + 1; // ',' or ';'
|
||||
}
|
||||
|
||||
if (newPosition) {
|
||||
*newPosition = newPos;
|
||||
}
|
||||
|
||||
// Parse extracted address (mailbox or group)
|
||||
if (pos != start)
|
||||
{
|
||||
if (pos != start) {
|
||||
|
||||
shared_ptr <address> parsedAddress;
|
||||
|
||||
if (isGroup)
|
||||
parsedAddress = make_shared <mailboxGroup>();
|
||||
else
|
||||
if (isGroup) {
|
||||
|
||||
if (allowGroup) {
|
||||
|
||||
parsedAddress = make_shared <mailboxGroup>();
|
||||
|
||||
} else { // group not allowed in group, ignore group and continue parsing
|
||||
|
||||
return parseNext(
|
||||
ctx,
|
||||
buffer,
|
||||
newPos,
|
||||
end,
|
||||
newPosition,
|
||||
/* allowGroup */ false,
|
||||
isLastAddressOfGroup
|
||||
);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
parsedAddress = make_shared <mailbox>();
|
||||
}
|
||||
|
||||
parsedAddress->parse(ctx, buffer, start, pos, NULL);
|
||||
parsedAddress->setParsedBounds(start, pos);
|
||||
if (parsedAddress) {
|
||||
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,15 @@ 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(
|
||||
parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition,
|
||||
const bool allowGroup,
|
||||
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(
|
||||
parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition
|
||||
) {
|
||||
|
||||
removeAllAddresses();
|
||||
|
||||
size_t pos = position;
|
||||
|
||||
while (pos < end)
|
||||
{
|
||||
shared_ptr <address> parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, NULL);
|
||||
while (pos < end) {
|
||||
|
||||
if (parsedAddress != NULL)
|
||||
shared_ptr <address> parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, /* allowGroup */ true, 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,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
void parseImpl(
|
||||
parsingContext& ctx,
|
||||
const string& buffer,
|
||||
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;
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
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,40 +81,46 @@ 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,22 +303,25 @@ 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;
|
||||
@ -301,12 +329,11 @@ shared_ptr <bodyPart> attachmentHelper::findBodyPart
|
||||
|
||||
|
||||
// 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,9 +53,9 @@ namespace vmime
|
||||
#ifndef VMIME_BUILDING_DOC
|
||||
|
||||
// Null pointer
|
||||
struct nullPtrType
|
||||
{
|
||||
template<typename T>
|
||||
struct nullPtrType {
|
||||
|
||||
template <typename T>
|
||||
operator shared_ptr <T>() { return shared_ptr <T>(); }
|
||||
};
|
||||
|
||||
@ -78,47 +78,48 @@ 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,35 +220,18 @@ 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
|
||||
{
|
||||
protected:
|
||||
|
||||
noncopyable() { }
|
||||
virtual ~noncopyable() { }
|
||||
|
||||
private:
|
||||
|
||||
noncopyable(const noncopyable&);
|
||||
void operator=(const noncopyable&);
|
||||
};
|
||||
|
||||
} // vmime
|
||||
|
||||
|
||||
|
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.
|
||||
@ -291,17 +306,18 @@ private:
|
||||
|
||||
|
||||
string m_prologText;
|
||||
string m_epilogText;
|
||||
string m_epilogText;
|
||||
string m_boundary;
|
||||
|
||||
shared_ptr <const contentHandler> m_contents;
|
||||
|
||||
bodyPart* m_part;
|
||||
bodyPart* m_part = nullptr;
|
||||
|
||||
std::vector <shared_ptr <bodyPart> > m_parts;
|
||||
|
||||
bool isRootPart() const;
|
||||
|
||||
void initNewPart(shared_ptr <bodyPart> part);
|
||||
void initNewPart(const shared_ptr <bodyPart>& part);
|
||||
|
||||
protected:
|
||||
|
||||
@ -317,24 +333,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);
|
||||
size_t findNextBoundaryPosition(
|
||||
const 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,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
void parseImpl(
|
||||
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;
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
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(
|
||||
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,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
void parseImpl(
|
||||
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;
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
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,55 +24,57 @@
|
||||
#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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,19 +82,19 @@ const word bodyPartAttachment::getName() const
|
||||
}
|
||||
|
||||
|
||||
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,99 @@
|
||||
|
||||
|
||||
|
||||
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));
|
||||
charset::charset(const charset& other)
|
||||
: m_name(other.m_name) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void charset::parseImpl(
|
||||
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
|
||||
{
|
||||
void charset::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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void charset::convert(utility::inputStream& in, utility::outputStream& out,
|
||||
const charset& source, const charset& dest,
|
||||
const charsetConverterOptions& opts)
|
||||
{
|
||||
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 +134,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 +163,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 +252,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,14 +40,14 @@ class encoding; // forward reference
|
||||
|
||||
/** Charset description (basic type).
|
||||
*/
|
||||
class VMIME_EXPORT charset : public component {
|
||||
|
||||
class VMIME_EXPORT charset : public component
|
||||
{
|
||||
public:
|
||||
|
||||
charset();
|
||||
charset(const string& name);
|
||||
charset(const char* name); // to allow creation from vmime::charsets constants
|
||||
charset(const charset& other);
|
||||
|
||||
public:
|
||||
|
||||
@ -99,12 +98,16 @@ public:
|
||||
* byte sequence was found in the input bytes, and the
|
||||
* 'silentlyReplaceInvalidSequences' flag is set to false in
|
||||
* the charsetConverterOptions
|
||||
* @throws exceptions::charset_conv_error if an unexpected error occured
|
||||
* @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.
|
||||
@ -118,12 +121,16 @@ public:
|
||||
* byte sequence was found in the input bytes, and the
|
||||
* 'silentlyReplaceInvalidSequences' flag is set to false in
|
||||
* the charsetConverterOptions
|
||||
* @throws exceptions::charset_conv_error if an unexpected error occured
|
||||
* @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 +154,20 @@ private:
|
||||
protected:
|
||||
|
||||
// Component parsing & assembling
|
||||
void parseImpl
|
||||
(const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
void parseImpl(
|
||||
parsingContext& ctx,
|
||||
const string& buffer,
|
||||
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;
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
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,28 +33,25 @@
|
||||
#include "vmime/utility/filteredStream.hpp"
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
namespace vmime {
|
||||
|
||||
|
||||
namespace utility
|
||||
{
|
||||
namespace utility {
|
||||
|
||||
|
||||
/** A filtered output stream which applies a charset conversion
|
||||
* to input bytes.
|
||||
*
|
||||
* May throw a exceptions::charset_conv_error if an unexpected error
|
||||
* occured when initializing convert, or during charset conversion.
|
||||
* occurred when initializing convert, or during charset conversion.
|
||||
*
|
||||
* May also throw a exceptions::illegal_byte_sequence_for_charset
|
||||
* if an illegal byte sequence was found in the input bytes, and the
|
||||
* '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)
|
||||
@ -109,7 +107,7 @@ public:
|
||||
* byte sequence was found in the input bytes, and the
|
||||
* 'silentlyReplaceInvalidSequences' flag is set to false in
|
||||
* the charsetConverterOptions
|
||||
* @throws exceptions::charset_conv_error if an unexpected error occured
|
||||
* @throws exceptions::charset_conv_error if an unexpected error occurred
|
||||
* during the conversion
|
||||
*/
|
||||
virtual void convert(const string& in, string& out, status* st = NULL) = 0;
|
||||
@ -125,10 +123,14 @@ public:
|
||||
* byte sequence was found in the input bytes, and the
|
||||
* 'silentlyReplaceInvalidSequences' flag is set to false in
|
||||
* the charsetConverterOptions
|
||||
* @throws exceptions::charset_conv_error if an unexpected error occured
|
||||
* @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();
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,132 +1,137 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002-2013 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
|
||||
// published by the Free Software Foundation; either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
// Linking this library statically or dynamically with other modules is making
|
||||
// a combined work based on this library. Thus, the terms and conditions of
|
||||
// the GNU General Public License cover the whole combination.
|
||||
//
|
||||
|
||||
#ifndef VMIME_CHARSETCONVERTER_ICU_HPP_INCLUDED
|
||||
#define VMIME_CHARSETCONVERTER_ICU_HPP_INCLUDED
|
||||
|
||||
|
||||
#include "vmime/config.hpp"
|
||||
|
||||
|
||||
#if VMIME_CHARSETCONV_LIB_IS_ICU
|
||||
|
||||
|
||||
#include "vmime/charsetConverter.hpp"
|
||||
|
||||
|
||||
struct UConverter;
|
||||
|
||||
|
||||
namespace vmime
|
||||
{
|
||||
|
||||
|
||||
/** A generic charset converter which uses ICU library.
|
||||
*/
|
||||
|
||||
class charsetConverter_icu : public charsetConverter
|
||||
{
|
||||
public:
|
||||
|
||||
/** Construct and initialize an ICU charset converter.
|
||||
*
|
||||
* @param source input charset
|
||||
* @param dest output charset
|
||||
* @param opts conversion options
|
||||
*/
|
||||
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());
|
||||
|
||||
private:
|
||||
|
||||
UConverter* m_from;
|
||||
UConverter* m_to;
|
||||
|
||||
charset m_source;
|
||||
charset m_dest;
|
||||
|
||||
charsetConverterOptions m_options;
|
||||
};
|
||||
|
||||
|
||||
namespace utility {
|
||||
|
||||
|
||||
class charsetFilteredOutputStream_icu : public charsetFilteredOutputStream
|
||||
{
|
||||
public:
|
||||
|
||||
/** Construct a new filter for the specified output stream.
|
||||
*
|
||||
* @param source input charset
|
||||
* @param dest output charset
|
||||
* @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();
|
||||
|
||||
|
||||
outputStream& getNextOutputStream();
|
||||
|
||||
void flush();
|
||||
|
||||
protected:
|
||||
|
||||
void writeImpl(const byte_t* const data, const size_t count);
|
||||
|
||||
private:
|
||||
|
||||
UConverter* m_from;
|
||||
UConverter* m_to;
|
||||
|
||||
const charset m_sourceCharset;
|
||||
const charset m_destCharset;
|
||||
|
||||
outputStream& m_stream;
|
||||
|
||||
charsetConverterOptions m_options;
|
||||
};
|
||||
|
||||
|
||||
} // utility
|
||||
|
||||
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_CHARSETCONV_LIB_IS_ICU
|
||||
|
||||
#endif // VMIME_CHARSETCONVERTER_ICU_HPP_INCLUDED
|
||||
//
|
||||
// VMime library (http://www.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
|
||||
// published by the Free Software Foundation; either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
// Linking this library statically or dynamically with other modules is making
|
||||
// a combined work based on this library. Thus, the terms and conditions of
|
||||
// the GNU General Public License cover the whole combination.
|
||||
//
|
||||
|
||||
#ifndef VMIME_CHARSETCONVERTER_ICU_HPP_INCLUDED
|
||||
#define VMIME_CHARSETCONVERTER_ICU_HPP_INCLUDED
|
||||
|
||||
|
||||
#include "vmime/config.hpp"
|
||||
|
||||
|
||||
#if VMIME_CHARSETCONV_LIB_IS_ICU
|
||||
|
||||
|
||||
#include "vmime/charsetConverter.hpp"
|
||||
|
||||
|
||||
struct UConverter;
|
||||
|
||||
|
||||
namespace vmime {
|
||||
|
||||
|
||||
/** A generic charset converter which uses ICU library.
|
||||
*/
|
||||
class charsetConverter_icu : public charsetConverter {
|
||||
|
||||
public:
|
||||
|
||||
/** Construct and initialize an ICU charset converter.
|
||||
*
|
||||
* @param source input charset
|
||||
* @param dest output charset
|
||||
* @param opts conversion options
|
||||
*/
|
||||
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()
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
UConverter* m_from;
|
||||
UConverter* m_to;
|
||||
|
||||
charset m_source;
|
||||
charset m_dest;
|
||||
|
||||
charsetConverterOptions m_options;
|
||||
};
|
||||
|
||||
|
||||
namespace utility {
|
||||
|
||||
|
||||
class charsetFilteredOutputStream_icu : public charsetFilteredOutputStream {
|
||||
|
||||
public:
|
||||
|
||||
/** Construct a new filter for the specified output stream.
|
||||
*
|
||||
* @param source input charset
|
||||
* @param dest output charset
|
||||
* @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();
|
||||
|
||||
|
||||
outputStream& getNextOutputStream();
|
||||
|
||||
void flush();
|
||||
|
||||
protected:
|
||||
|
||||
void writeImpl(const byte_t* const data, const size_t count);
|
||||
|
||||
private:
|
||||
|
||||
UConverter* m_from;
|
||||
UConverter* m_to;
|
||||
|
||||
const charset m_sourceCharset;
|
||||
const charset m_destCharset;
|
||||
|
||||
outputStream& m_stream;
|
||||
|
||||
charsetConverterOptions m_options;
|
||||
};
|
||||
|
||||
|
||||
} // utility
|
||||
|
||||
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_CHARSETCONV_LIB_IS_ICU
|
||||
|
||||
#endif // VMIME_CHARSETCONVERTER_ICU_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
|
||||
@ -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)
|
||||
{
|
||||
const utf8::uint32_t uc = utf8::unchecked::next(ch);
|
||||
while (ch < end) {
|
||||
const 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,64 +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 = in.length() * 2; // 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 = unicodeLen * 6; // 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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,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);
|
||||
}
|
||||
|
||||
@ -187,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(
|
||||
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(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(
|
||||
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(
|
||||
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(
|
||||
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();
|
||||
@ -61,7 +59,7 @@ public:
|
||||
* @param ctx parsing context
|
||||
* @param buffer input buffer
|
||||
*/
|
||||
void parse(const parsingContext& ctx, const string& buffer);
|
||||
void parse(parsingContext& ctx, const string& buffer);
|
||||
|
||||
/** Parse RFC-822/MIME data for this component. If stream is not seekable,
|
||||
* or if length is not specified, entire contents of the stream will
|
||||
@ -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,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
void parse(
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
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,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
void parse(
|
||||
parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
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,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
void parse(
|
||||
const shared_ptr <utility::inputStream>& inputStream,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
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,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
void parse(
|
||||
parsingContext& ctx,
|
||||
const shared_ptr <utility::inputStream>& inputStream,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
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,
|
||||
const size_t curLinePos = 0,
|
||||
size_t* newLinePos = NULL) const;
|
||||
virtual void generate(
|
||||
utility::outputStream& outputStream,
|
||||
const size_t curLinePos = 0,
|
||||
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,
|
||||
utility::outputStream& outputStream,
|
||||
const size_t curLinePos = 0,
|
||||
size_t* newLinePos = NULL) const;
|
||||
virtual void generate(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& outputStream,
|
||||
const size_t curLinePos = 0,
|
||||
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,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
virtual void parseImpl(
|
||||
parsingContext& ctx,
|
||||
const shared_ptr <utility::parserInputStreamAdapter>& parser,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
virtual void parseImpl
|
||||
(const parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
virtual void parseImpl(
|
||||
parsingContext& ctx,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL
|
||||
);
|
||||
|
||||
virtual void generateImpl
|
||||
(const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
size_t* newLinePos = NULL) const = 0;
|
||||
virtual void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 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";
|
||||
@ -59,6 +58,7 @@ namespace mediaTypes
|
||||
const char* const MESSAGE_PARTIAL = "partial";
|
||||
const char* const MESSAGE_EXTERNAL_BODY = "external-body";
|
||||
const char* const MESSAGE_DISPOSITION_NOTIFICATION = "disposition-notification";
|
||||
const char* const MESSAGE_DELIVERY_STATUS = "delivery-status";
|
||||
|
||||
const char* const APPLICATION_OCTET_STREAM = "octet-stream";
|
||||
|
||||
@ -72,8 +72,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 +84,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 +159,8 @@ namespace charsets
|
||||
|
||||
|
||||
// Fields
|
||||
namespace fields
|
||||
{
|
||||
namespace fields {
|
||||
|
||||
const char* const RECEIVED = "Received";
|
||||
const char* const FROM = "From";
|
||||
const char* const SENDER = "Sender";
|
||||
@ -204,34 +204,48 @@ 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";
|
||||
}
|
||||
|
||||
// Constants for DSN (delivery status notification)
|
||||
namespace dsn {
|
||||
|
||||
const char* const NOTIFY = "NOTIFY";
|
||||
const char* const NEVER = "NEVER";
|
||||
const char* const SUCCESS = "SUCCESS";
|
||||
const char* const FAILURE = "FAILURE";
|
||||
const char* const DELAY = "DELAY";
|
||||
const char* const ORCPT = "ORCPT";
|
||||
const char* const RET = "RET";
|
||||
const char* const FULL = "FULL";
|
||||
const char* const HDRS = "HDRS";
|
||||
const char* const ENVID = "ENVID";
|
||||
}
|
||||
|
||||
} // 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
|
||||
@ -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;
|
||||
@ -70,6 +70,7 @@ namespace vmime
|
||||
extern VMIME_EXPORT const char* const MESSAGE_PARTIAL;
|
||||
extern VMIME_EXPORT const char* const MESSAGE_EXTERNAL_BODY;
|
||||
extern VMIME_EXPORT const char* const MESSAGE_DISPOSITION_NOTIFICATION;
|
||||
extern VMIME_EXPORT const char* const MESSAGE_DELIVERY_STATUS;
|
||||
|
||||
extern VMIME_EXPORT const char* const APPLICATION_OCTET_STREAM;
|
||||
|
||||
@ -83,8 +84,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 +96,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 +170,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 +214,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 +225,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 +236,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,10 +247,25 @@ namespace vmime
|
||||
}
|
||||
|
||||
/** Constants for disposition modifiers (RFC-3798). */
|
||||
namespace dispositionModifiers
|
||||
{
|
||||
namespace dispositionModifiers {
|
||||
|
||||
extern VMIME_EXPORT const char* const ERROR;
|
||||
}
|
||||
|
||||
/** Constants for DSN (delivery status notification) */
|
||||
namespace dsn {
|
||||
|
||||
extern VMIME_EXPORT const char* const NOTIFY;
|
||||
extern VMIME_EXPORT const char* const NEVER;
|
||||
extern VMIME_EXPORT const char* const SUCCESS;
|
||||
extern VMIME_EXPORT const char* const FAILURE;
|
||||
extern VMIME_EXPORT const char* const DELAY;
|
||||
extern VMIME_EXPORT const char* const ORCPT;
|
||||
extern VMIME_EXPORT const char* const RET;
|
||||
extern VMIME_EXPORT const char* const FULL;
|
||||
extern VMIME_EXPORT const char* const HDRS;
|
||||
extern VMIME_EXPORT const char* const ENVID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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(
|
||||
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,
|
||||
const string& buffer,
|
||||
const size_t position,
|
||||
const size_t end,
|
||||
size_t* newPosition = NULL);
|
||||
void parseImpl(
|
||||
parsingContext& ctx,
|
||||
const string& buffer,
|
||||
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;
|
||||
void generateImpl(
|
||||
const generationContext& ctx,
|
||||
utility::outputStream& os,
|
||||
const size_t curLinePos = 0,
|
||||
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
|
||||
@ -28,18 +28,16 @@
|
||||
#include <limits>
|
||||
|
||||
#include "vmime/base.hpp"
|
||||
#include "vmime/utility/stringProxy.hpp"
|
||||
#include "vmime/utility/progressListener.hpp"
|
||||
#include "vmime/encoding.hpp"
|
||||
#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 +61,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 +76,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 +89,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;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user