Compare commits

...

206 Commits

Author SHA1 Message Date
52f6184e88 fix: must init raw pointer *bodyPart
All checks were successful
Compilation test / build (push) Successful in 15m13s
2024-12-01 19:26:23 +01:00
fd0b5f7a21 fix: should not use mlang in such a way in mingw
All checks were successful
Compilation test / build (push) Successful in 14m24s
2024-12-01 02:32:41 +01:00
193a9ee85b feat: remember boundary from parsing
All checks were successful
Compilation test / build (push) Successful in 15m19s
2024-11-28 12:00:39 +01:00
Jan Engelhardt
43b262bd8c
gh: add a GitHub workflow for compile+testsuite testing (#313)
This will cause all pushed commits and pull requests to be
fed through a compile and testsuite run.
2024-06-11 21:01:01 +02:00
Jan Engelhardt
beb238b5e7
Fix a test failure in pathTest::testGenerate (#312)
* Fix a test failure in testNewFromString

Fixes an oversight in d296c2d1.

* Fix a test failure in pathTest::testGenerate

Partially revert v0.9.2-183-g9b65b4de.

As per RFC 5322 §3.4.1, an email address must always have a @.
As per RFC 5321 §4.1.2, a path is similar to an email address (always
@), with "" (<>) being the only other special value.

Fixes #294, #301.
2024-06-11 20:49:10 +02:00
Jan Engelhardt
aa60d00496
Fix a test failure in testNewFromString (#311)
Fixes an oversight in d296c2d1.
2024-06-11 20:47:53 +02:00
Jan Engelhardt
0f7014ab57
build: upgrade to C++17 when ICU is used (#310)
ICU 75 requires the use of C++17.

`SET(CMAKE_CXX_STANDARD 17)` has no effect after the first target has been defined
or so, therefore the detection of the conversion library is split and partially
moved upwards.
2024-06-11 20:46:59 +02:00
Jan Engelhardt
fb5b82746a
contrib: update utfcpp to v4.0.5 (#309)
Download a new version from https://github.com/nemtrif/utfcpp/
which explicitly supports C++17.
2024-06-11 20:45:51 +02:00
Jan Engelhardt
5f8fa22602
build: resolve a -Wunused-function compiler warning (#308)
posixSocket.cpp:67:7: warning: ‘char*
{anonymous}::vmime_strerror_r_result(int, char*)’ defined but not
used [-Wunused-function]
   67 | char* vmime_strerror_r_result(int /* res */, char* buf) {

It is to be expected that one of the two r_result functions is going unused,
depending on whichever platform we are currently building on.
2024-06-11 20:44:18 +02:00
Jan Engelhardt
a2636bd4ae
asciiPercent computation: another potential multiplication overflow (#307)
* build: resolve a -Wconversion compiler warning

wordEncoder.cpp:312:91: warning: conversion from
‘std::__cxx11::basic_string<char>::size_type’ {aka ‘long unsigned
int’} to ‘double’ may change value [-Wconversion]
  312 | buffer.length() == 0 ? 1 : static_cast<double>(asciiCount) / buffer.length();
      |                                                              ~~~~~~~~~~~~~^~

* wordEncoder: replace value 100 for asciiPercent

asciiPercent is a ratio, and not counting in units of hundredths
anymore. The maximum value therefore should be 1 not 100.

* vmime: avoid integer multiply wraparound in text::createFromString

The change from commit v0.9.2-194-gb447adbe needs to be applied to
one more function that replicates the same code.

(If the input string is 42949673 characters long or larger, there will
be integer overflow on 32-bit platforms when multiplying by 100.
Switch that one computation to floating point.)
2024-05-21 20:48:08 +02:00
Jan Engelhardt
d296c2d1d5
vmime: prevent loss of a space during text::createFromString (#306)
```
mailbox(text("Test München West", charsets::UTF_8), "a@b.de").generate();
```

produces

```
=?us-ascii?Q?Test_?= =?utf-8?Q?M=C3=BCnchen?= =?us-ascii?Q?West?= <test@example.com>
```

The first space between ``Test`` and ``München`` is encoded as an
underscore along with the first word: ``Test_``. The second space
between ``München`` and ``West`` is encoded with neither of the two
words and thus lost. Decoding the text results in ``Test
MünchenWest`` instead of ``Test München West``.

This is caused by how ``vmime::text::createFromString()`` handles
transitions between 7-bit and 8-bit words: If an 8-bit word follows a
7-bit word, a space is appended to the previous word. The opposite
case of a 7-bit word following an 8-bit word *misses* this behaviour.

When one fixes this problem, a follow-up issue appears:

``text::createFromString("a b\xFFc d")`` tokenizes the input into
``m_words={word("a "), word("b\xFFc ", utf8), word("d")}``. This
"right-side alignment" nature of the whitespace is a problem for
word::generate():

As per RFC 2047, spaces between adjacent encoded words are just
separators but not meant to be displayed. A space between an encoded
word and a regular ASCII text is not just a separator but also meant
to be displayed.

When word::generate() outputs the b-word, it would have to strip one
space, but only when there is a transition from encoded-word to
unencoded word. word::generate() does not know whether d will be
encoded or unencoded.

The idea now is that we could change the tokenization of
``text::createFromString`` such that whitespace is at the *start* of
words rather than at the end. With that, word::generate() need not
know anything about the next word, but rather only the *previous*
one.

Thus, in this patch,

1. The tokenization of ``text::createFromString`` is changed to
   left-align spaces and the function is fixed to account for
   the missing space on transition.
2. ``word::generate`` learns how to steal a space character.
3. Testcases are adjusted to account for the shifted
   position of the space.

Fixes: #283, #284

Co-authored-by: Vincent Richard <vincent@vincent-richard.net>
2024-05-21 15:55:06 +02:00
Jan Engelhardt
c105165c6e
tests: switch a byte sequence in textTest (#305)
Switch out the byte sequence by one that is simiarly random, but one
which happens to decode as valid UTF-8, such that the expected and
actual strings are shown with reasonable characters on a terminal.
2024-05-21 15:48:26 +02:00
Jan Engelhardt
b447adbe37
Fixes/comments for guessBestEncoding (#304)
* tests: add case for getRecommendedEncoding

* vmime: avoid integer multiply wraparound in wordEncoder::guessBestEncoding

If the input string is 42949673 characters long or larger, there will
be integer overflow on 32-bit platforms when multiplying by 100.
Switch that one computation to floating point.

* vmime: update comment in wordEncoder::guessBestEncoding
2024-05-21 15:47:05 +02:00
Jan Engelhardt
97d15b8cd7
vmime: avoid changing SEVEN_BIT when encoding::decideImpl sees U+007F (#303)
* vmime: avoid changing SEVEN_BIT when encoding::decideImpl sees U+007F

Do not switch to QP/B64 when encountering U+007F.
U+007F is part of ASCII just as much as U+0001 is.

---------

Co-authored-by: Vincent Richard <vincent@vincent-richard.net>
2024-05-21 15:45:29 +02:00
Jan Engelhardt
15f3b94580
Resolve compiler warnings (#302)
* build: replace class noncopyable by C++11 deleted function declaration

C++11 is mandatory since commit v0.9.2-48-g8564b2f8, therefore we can
exercise the =delete keyword in class declarations to prohibit
copying.

* build: resolve -Woverloaded-virtual warnings

context.hpp:109:26: warning: "virtual vmime::context&
vmime::context::operator=(const vmime::context&)’ was hidden
[-Woverloaded-virtual=]
  109 |         virtual context& operator=(const context& ctx);
      |                          ^~~~~~~~
generationContext.hpp:153:28: note:   by ‘vmime::generationContext&
vmime::generationContext::operator=(const vmime::generationContext&)’
  153 |         generationContext& operator=(const generationContext& ctx);
      |                            ^~~~~~~~

AFAICS, there is no point in having "virtual" on an assignment operator.
Any derived classes' operator= has different signature anyway.
It is also the only class with a virtual operator=, so that's an indicator
for oddness as well.

* build: resolve -Wdeprecated-declarations warnings

encoding.cpp: In static member function "static const vmime::encoding
vmime::encoding::decideImpl(std::__cxx11::basic_string<char>::const_iterator,
std::__cxx11::basic_string<char>::const_iterator)":

encoding.cpp:161:29: warning: "std::binder2nd<_Operation>
std::bind2nd(const _Operation&, const _Tp&) [with _Operation =
less<unsigned char>; _Tp = int]" is deprecated: use "std::bind" instead
[-Wdeprecated-declarations]
  161 |                 std::bind2nd(std::less<unsigned char>(), 127)
      |                 ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

C++11 is mandatory, so just use a lambda already.
2024-05-21 15:41:50 +02:00
Ján Osuský
d03ad5f0f6
Fix OpenSSL initialization #299 (#300) 2024-03-04 11:48:48 +01:00
Jan Engelhardt
0ce327abee
url: strip leading slash from url-path (#298) 2024-03-04 11:46:03 +01:00
Jan Engelhardt
c6b01fcc32
url: repair off-by-one bug in extractHost (#297)
`hostPart[len]` is pointing to `]`, but we need to check the
char after that.

Fixes: v0.9.2-187-g874a1d8c
2024-03-04 11:45:49 +01:00
Jan Engelhardt
c3c6242ed1
url: add remark to documentation about hardcoded // substring (#293) 2024-01-30 12:41:49 +01:00
Jan Engelhardt
874a1d8c33
url: support IPv6 literals (RFC 2732) (#292) 2024-01-30 12:38:41 +01:00
Vincent Richard
8bed1cc743
Fixed confusing source/bin dirs in makefile. (#291) 2024-01-12 13:36:00 +01:00
vincent-richard
a5623d695f Fixed use of old API (#287). 2024-01-01 18:02:32 +01:00
bmagistro
6fd4de8fb5
Add parsing feedback via parsingContext (#280)
* Add parsing feedback via parsingContext

Changes the parsing context to be modifiable to be able to provide
feedback on the parsing. This allows the user to check if header
recovery was necessary, for example, while parsing the current message.

Signed-off-by: Ben Magistro <koncept1@gmail.com>
Co-authored-by: Vincent Richard <vincent@vincent-richard.net>
2023-12-31 16:10:18 +01:00
bmagistro
9b65b4de6c
Configurable email add domain (#287)
* Allow appending of local hostname to be configured via parsing context

Signed-off-by: Ben Magistro <koncept1@gmail.com>
Co-authored-by: Vincent Richard <vincent@vincent-richard.net>
2023-12-31 16:03:30 +01:00
Jan Engelhardt
acfc0bbf82
Avoid generating illegal Envelope-From with sendmail:// transport (#285)
When the ``sender`` function argument is the empty object, vmime
would still attempt to use it at ``sender.getEmail().generate()``,
but that produces just ``@``. As sendmail is called with ``-f @``,
this shows up in postfix's logs as ``<""@>``.
2023-12-31 15:56:28 +01:00
bmagistro
022303bbc9
Build: static lib dependency for ICU (#281)
* Fix missed path for generated files in #277

* Update cmake to include char conversion dependency on static library
2023-12-31 15:54:48 +01:00
bmagistro
7ada1c974c
Build: fix missed path for generated files in #277 (#278) 2023-12-31 15:35:57 +01:00
Jan Engelhardt
82377e0342
Build: add FreeBSD & libc++ compilation support (#288)
* build: add FreeBSD compilation support

* build: unbreak compilation with clang libc++

unary_function is obsolete with C++11 and removed in C++17.
gnu-gcc-libstdc++ still has the class, but llvm-clang-libc++ does
not, and there is a compile error.

vmime should have just stopped using unary_function with commit
v0.9.2-48-g8564b2f8.

	$ cat x.cpp
	$ clang++ -std=c++17 -stdlib=libc++ -c x.cpp
	In file included from x.cpp:1:
	In file included from /usr/local/include/vmime/net/transport.hpp:34:
	In file included from /usr/local/include/vmime/net/service.hpp:36:
	In file included from /usr/local/include/vmime/net/session.hpp:40:
	In file included from /usr/local/include/vmime/utility/url.hpp:30:
	/usr/local/include/vmime/propertySet.hpp:339:33: error: no template named
	/'unary_function' in namespace 'std'; did you mean '__unary_function'?
		class propFinder : public std::unary_function <shared_ptr <property>, bool> {
					  ~~~~~^~~~~~~~~~~~~~
					       __unary_function
2023-12-31 15:22:36 +01:00
bmagistro
6e11c9c9f8
Make default context thread_local (#286)
* Make default context thread_local

Signed-off-by: Ben Magistro <koncept1@gmail.com>
Co-authored-by: Vincent Richard <vincent@vincent-richard.net>
2023-12-31 15:19:28 +01:00
Jan Engelhardt
1a35bb6d71
Build: add Solaris compilation support (#282) 2023-11-09 20:32:47 +01:00
bmagistro
c6b9ad3c78
Update cmake (#277)
This restructures the cmake a little bit to only find components if they
are actually enabled.  It also rearranges things to better group some
related items.  This change also fixes include directories for the build
target allowing the library to be embedded making the install step
optional.

Signed-off-by: Ben Magistro <koncept1@gmail.com>
2023-08-09 10:59:38 +02:00
Vincent Richard
fc69321d53
Merge pull request #272 from frodegill/bytearray_to_string
Utility function to convert byteArray to HEX string. Useful for printing fingerprint digests etc.
2022-03-26 22:30:00 +01:00
Vincent Richard
56b77ca3b7
Merge pull request #271 from frodegill/digest_sha256
Added support for digest algorithm SHA256
2022-03-26 22:19:47 +01:00
Frode Roxrud Gill
6fd3632912 Added utility function to convert byteArray to HEX string. Useful for printing fingerprint digests etc. 2022-03-13 11:59:02 +01:00
Frode Roxrud Gill
46c09fa8a5
Merge pull request #1 from frodegill/digest_sha256
Added support for digest algorithm SHA256
2022-03-13 11:54:16 +01:00
Frode Roxrud Gill
cd59fabe79 Added support for digest algorithm SHA256 2022-03-13 11:44:27 +01:00
vincent-richard
561746081f Fixed possible recursion crash when parsing mailbox groups. 2022-01-25 10:28:20 +01:00
Vincent Richard
23ab2a6a3c Fixed Cppcheck issues. 2021-11-25 21:57:07 +01:00
Vincent Richard
80ad529d5a #268 Code style fixes + moved specific bits to IMAP namespace 2021-11-25 21:23:50 +01:00
Vincent Richard
c6e3b759bc
Merge pull request #268 from jacadcaps/search
Implemented IMAP SEARCH.
2021-11-25 20:22:50 +01:00
Jacek Piszczek
1a0a22a311 Implemented IMAP SEARCH 2021-10-28 23:17:29 -04:00
Vincent Richard
edcb4b4b1f
Merge pull request #262 from ibanic/master
Prevent accessing empty buffer when using FilteredOutputStream with ICU
2021-05-16 18:43:14 +02:00
ibanic
f5fa6434aa fixed coding style 2021-05-16 09:43:32 +02:00
ibanic
5d78d879bb Prevent accessing empty buffer 2021-05-15 22:32:24 +02:00
vincent-richard
c86e4bcd3a #261 Workaround for bad SEARCH response with AOL IMAP server 2021-05-11 08:31:03 +02:00
vincent-richard
7503cd3747 #200 Fixed installation directory 2021-05-06 21:06:47 +02:00
vincent-richard
c6904bd7cf SMTP/DSN refactoring. 2021-04-03 11:21:50 +02:00
Vincent Richard
a6226e8cbc
Merge pull request #256 from jacadcaps/IMAP.PEEK
IMAP PEEK support.
2021-03-31 21:37:30 +02:00
Vincent Richard
8024c650a2
Merge pull request #258 from jacadcaps/processFetchResponse
Process Message-ID and In-Reply-To in ENVELOPE.
2021-03-31 21:22:13 +02:00
Jacek Piszczek
c0f2380aac Fixed build 2021-03-25 02:17:17 +01:00
vincent-richard
e5186e6710 Fixed parsing of IMAP astring. 2021-03-24 21:04:01 +01:00
Jacek Piszczek
6feb658bfb Added missing includes 2021-03-24 15:57:25 -04:00
Vincent Richard
7d64105dee
Merge pull request #257 from jacadcaps/defaultCertificateVerifier
Improved certificate verification.
2021-03-24 20:52:05 +01:00
Vincent Richard
b2d08d4f71
Merge pull request #255 from jacadcaps/weak_ptr-checks
Weak ptr checks + forced socket disconnections.
2021-03-24 20:41:58 +01:00
Jacek Piszczek
9ec84cf80f Process Message-ID and In-Reply-To in EVELOPE 2021-03-24 14:24:35 -04:00
Jacek Piszczek
db486520f2 Improved certificate verification 2021-03-24 12:55:42 -04:00
Jacek Piszczek
a0d02afc69 IMAP PEEK support 2021-03-24 12:27:47 -04:00
Jacek Piszczek
d7eaba1007 Cosmetics 2021-03-24 11:14:03 -04:00
Jacek Piszczek
68f8eb0d39 Ensure disconnect() method always disconnect the underlying sockets.
Added additional checks after weak pointer locks.
2021-03-24 11:08:40 -04:00
Vincent Richard
115d232483
Merge pull request #253 from jacadcaps/MessageParser
Default missing Content-Type to text/plain.
2021-03-16 21:38:34 +01:00
Vincent Richard
cb5adc3a23
Merge pull request #254 from jacadcaps/MessageParserDate
Workaround a RECEIVED message field missing actual date info.
2021-03-16 21:36:25 +01:00
Jacek Piszczek
025c155919 Workaround a RECEIVED message field missing actual date info. 2021-03-15 20:38:04 -04:00
Jacek Piszczek
408ffb13ea Default missing Content-Type to Text/Plain as per https://tools.ietf.org/html/rfc2045#section-5.2 2021-03-15 20:31:07 -04:00
Vincent Richard
98ec456ed1
Merge pull request #252 from jacadcaps/replyTo
Fixed an ENVELOPE ReplyTo handling regression.
2021-03-15 19:39:33 +01:00
Jacek Piszczek
8416534992 Fixed an ENVELOPE ReplyTo handling regression 2021-03-15 08:18:33 -04:00
Vincent Richard
98e9759da2
Merge pull request #251 from jacadcaps/exception_fixes
Exceptions handling / re-throwing fixes
2021-02-25 20:48:39 +01:00
Jacek Piszczek
39a0cfbcc3 net/tls: Refactored re-throwing exceptions so that the original exception class is retained. With the old code, a socket_exception was re-thrown as vmime::exception.
IMAPFolder.cpp: Fixed a use-after-free in case of an exception in close().
2021-02-24 13:53:39 -05:00
vincent-richard
47c6f35f5a #250 Fixed unquoted mailbox name 2021-02-05 18:28:20 +01:00
Vincent Richard
ea9775c4f1
Merge pull request #249 from mpietruschka/master
You forgot about one line  in "Fixed build with ICU 68.2-1"
2021-01-25 22:55:46 +01:00
Your Name
9116feac76 Fixed build with ICU 68.2-1 2021-01-23 01:35:08 +01:00
Your Name
7f9a0eb148 Fixed build with ICU 68.2-1 2021-01-23 01:03:58 +01:00
Vincent Richard
13ca7fa6e5 Fixed implicit declarations and misc warnings. 2021-01-11 22:34:59 +01:00
Vincent Richard
817358854d Fixed line endings. 2021-01-11 22:06:42 +01:00
Vincent Richard
ec5b8f7cfe #247 Fixed build with ICU 68.2-1 2021-01-11 22:04:52 +01:00
Vincent Richard
3733af5191 Reply-To should be an addressList according to the RFC. 2021-01-11 21:48:34 +01:00
Vincent Richard
2e07dc4c31
Merge pull request #248 from jas4711/jas4711/drop-obsolete-gsasl-symbols
Don't use deprecated gsasl symbols.
2021-01-11 21:18:53 +01:00
Simon Josefsson
c750e899b8
Don't use deprecated gsasl symbols. 2021-01-08 03:25:09 +01:00
Vincent Richard
9e2c286c0b
Merge pull request #246 from jengelh/asciiquote
Avoid force-encoding display names that fit within qcontent
2020-12-12 14:19:58 +01:00
Jan Engelhardt
f4c611b736 Avoid force-encoding display names that fit within qcontent
When the display name contains an At sign, or anything of the sort,
libvmime would forcibly encode this to =?...?=, even if the line
is fine ASCII which only needs quoting.

rspamd takes excessive quoting as a sign of spam and penalizes
such mails by raising the score (rule/match: TO_EXCESS_QP et al.)
2020-12-11 23:10:39 +01:00
vincent-richard
6c4bd0dda9 Check for DSN extension support before using it. 2020-09-04 19:14:33 +02:00
vincent-richard
9205c9d0ab Fixed unit test for DSN support. 2020-09-02 19:57:42 +02:00
vincent-richard
e25751cc0d Fixed missing default argument. 2020-09-02 19:24:11 +02:00
Vincent Richard
84294f6543
Merge pull request #240 from josusky/master
Add basic support for delivery status notifications (DSN).
2020-09-02 19:07:06 +02:00
Jan Osusky
7000792fa0 Fix wording of DSN attributes documentation 2020-08-21 13:30:36 +02:00
0xd34df00d
6eb63399a1 Try obtaining content disposition for all body parts types 2020-08-21 13:22:08 +02:00
0xd34df00d
4edb9ed949 Text body part can also have a name 2020-08-21 13:22:08 +02:00
0xd34df00d
d14038dd66 Refactor out getPartName() 2020-08-21 13:22:08 +02:00
Richard Steele
22ae6a91f5 Fix #223 2020-08-21 13:22:08 +02:00
Jan Osusky
d4cc5cfc9b Editorial changes in DSN attributes 2020-08-21 13:13:55 +02:00
Vincent Richard
4c330bc623
Merge pull request #241 from 0xd34df00d/body_type_parsing
Body type parsing
2020-08-09 11:02:53 +02:00
0xd34df00d
c137bc55af Try obtaining content disposition for all body parts types 2020-08-08 14:46:19 -04:00
0xd34df00d
1806e0be0e Text body part can also have a name 2020-08-08 12:50:53 -04:00
0xd34df00d
83a2669a51 Refactor out getPartName() 2020-08-08 12:44:03 -04:00
Vincent Richard
e02ea9d178
Merge pull request #233 from RichardSteele/fix-openssl-223
Fix #223
2020-07-31 18:02:46 +02:00
Jan Osusky
64ef65e03c Create class for DSN attributes
The three attributes needed to request a Delivery Status Notification are now passed as an "dsnAttributes" object to the send methods.
Fixed code style at some related palces.
2020-07-23 10:42:15 +02:00
Jan Osusky
e30766cf2a Add basic support for delivery status notifications (DSN)
Added possibility to send e-mails with explicit request for delivery status notification and its content.
2020-07-22 08:26:04 +02:00
Vincent Richard
0f99387648
Merge pull request #239 from kisli/laurent-richard-fix-message-flag-set
Fix message flag assignment with FLAG_MODE_SET.
2020-07-17 23:42:13 +02:00
laurent-richard
3052e5b998
Fix message flag assignment with FLAG_MODE_SET 2020-07-16 10:32:10 +02:00
vincent-richard
5c00f7867a #238 Fixed whitespace between encoded words 2020-06-16 19:47:33 +02:00
vincent-richard
9a10a839ec Added test. 2020-06-02 18:13:34 +02:00
vincent-richard
16912a5ed7 Expose Content-Disposition on net message parts. 2020-05-10 10:34:48 +02:00
vincent-richard
fe5492ceb3 Fixed false positives in tests. 2020-04-06 18:20:03 +02:00
vincent-richard
6d90a15bc5 Map '*' to '\*' in non-strict mode. 2020-04-06 18:12:41 +02:00
vincent-richard
f23cc90a6d Added support for pipelined and out-of-order replies. 2020-04-05 11:13:04 +02:00
vincent-richard
2d369b9ac9 INBOX folder special use. 2020-03-26 19:22:23 +01:00
vincent-richard
36cc0c65c8 Misc changes for CPack. 2020-02-14 23:02:58 +01:00
vincent-richard
749a2a0f85 #236 OpenSSL license exception 2020-02-14 22:25:58 +01:00
Vincent Richard
8ac5b7f5fc
Merge pull request #232 from RichardSteele/fix-sni-231
Fix #231: SNI breaks STARTTLS
2019-11-18 21:26:19 +01:00
Richard Steele
893726c3d8 Use peerName instead of peerAddress 2019-11-18 12:22:56 +01:00
Richard Steele
39ece29fed Fix #231 (GnuTLS) 2019-11-18 12:16:10 +01:00
Richard Steele
3c372b08ac Fix #223 2019-11-18 11:54:19 +01:00
Richard Steele
44eb473c9a Fix #231 2019-11-18 11:47:44 +01:00
Vincent Richard
19fb3c2491
Merge pull request #226 from 0xd34df00d/master
Added support for SNI.
2019-10-14 08:51:35 +02:00
0xd34df00d
86b59de8d0 Set SNI name in the gnutls backend as well 2019-10-13 17:21:43 -04:00
Vincent Richard
ab340b561d
Merge pull request #227 from Kopano-dev/boundaryprefix
Boundary marker parsing: WS rules and EQ check
2019-10-07 10:50:30 +02:00
Jan Engelhardt
b06e9e6f86 Skip delimiter lines that are not exactly equal to the boundary
There is crap software out there that generates mails violating the
prefix ban clause from RFC 2046 §5.1 ¶2.

Switch vmime from a prefix match to an equality match, similar to
what Alpine and Thunderbird do too.
2019-10-05 11:37:09 +02:00
Jan Engelhardt
df32418df5 Disregard whitespace between leading boundary hyphens and marker
The way I read the RFC is that whitespace is not allowed before the
boundary marker, only afterwards, so the checks for leading WS are
removed, and the missing check for trailing WS is added.

See RFC 2046 §5.1.1: """The boundary delimiter line is then defined
as a line consisting entirely of two hyphen characters ("-", decimal
value 45) followed by the boundary parameter value from the
Content-Type header field, optional linear whitespace, and a
terminating CRLF."""
2019-10-05 11:31:51 +02:00
Jan Engelhardt
c9119effd7 Reduce indent by 3 levels in findNextBoundary 2019-10-05 11:31:51 +02:00
Jan Engelhardt
6de75f0c95 Modernize RFC reference for boundary line characteristics 2019-10-05 11:31:51 +02:00
0xd34df00d
0fcf45b131 Set SNI in the openssl backend 2019-10-02 21:51:39 -04:00
Vincent Richard
7168f3c4ee
Merge pull request #225 from 0xd34df00d/patch-1
Avoid extern "C" blocks around ICU includes
2019-09-23 21:03:37 +02:00
0xd34df00d
e96aeeb14d
Avoid extern "C" blocks around ICU includes
Looks like it's not necessary, and, moreover, I'm getting this with recent ICU (64.2):
```
/usr/include/unicode/localpointer.h:67:1: error: template with C linkage
   67 | template<typename T>
      | ^~~~~~~~
/var/tmp/portage/dev-libs/vmime-9999/work/vmime-9999/src/vmime/charsetConverter_icu.cpp:37:1: note: ‘extern "C"’ linkage started here
   37 | extern "C" {
      | ^~~~~~~~~~
```

(there's also an issue about that, #218)
2019-09-22 08:26:11 -04:00
Vincent Richard
182e8f5dd8 Simplified IMAP parser objects. 2019-07-20 10:15:41 +02:00
Vincent Richard
523aacb499 Added support for OpenSSL 1.1.0. 2019-07-07 09:56:41 +02:00
Vincent Richard
8f4db13e7f #217 Fixed memory leak 2019-07-02 23:26:29 +02:00
Vincent Richard
e2fc1911f1 Merge branch 'master' of https://github.com/kisli/vmime 2019-04-18 11:29:28 +02:00
Vincent Richard
b59e97d0a7 #213 Add support for invalid empty () in FETCH body structure (non-strict) 2019-04-18 11:28:48 +02:00
Vincent Richard
dad5b4a855
Merge pull request #212 from jengelh/hostname
Unbreak own hostname qualification on POSIX systems
2019-02-07 19:50:33 +01:00
Jan Engelhardt
e1faa92593 Unbreak own hostname qualification on POSIX systems
Partial revert commit v0.9.2-6-g9a3d6880 (issue #160), because
invoking getaddrinfo(NULL, ... AI_CANONNAME) is illegal and never
succeeds.
2019-02-06 23:46:06 +01:00
Vincent Richard
414661858d
Merge pull request #210 from jengelh/twoaddr
Handle parsing of further non-conformant From lines
2019-02-04 21:10:47 +01:00
Jan Engelhardt
d1190b496f Improve address parser for malformed mailbox specifications
Spammers use "Name <addr> <addr>" to trick some parsers.
My expectations as to what the outcome should be is presented
in the updated mailboxTest.cpp.

The DFA in mailbox::parseImpl is hereby redone so as to pick the
rightmost address-looking portion as the address, rather than
something in between. While doing so, it will also no longer mangle
the name part anymore (it does this by keeping a "as_if_name"
variable around until the end).
2019-01-25 08:11:07 +01:00
Jan Engelhardt
cc18aa39c1 tests: add more malformation tests to mailboxTest 2019-01-24 13:17:52 +01:00
Vincent Richard
0368adade1 #206 Initialize and delete pointers 2018-10-17 20:26:44 +02:00
Vincent Richard
df135b5a8b Removed 'stringProxy' since COW std::string is no longer valid in C++11. 2018-09-15 07:41:26 +02:00
Vincent Richard
0c81108cc8
Merge pull request #183 from josusky/master
Fix of compilation warning reported by GCC 4.9.3.
2018-09-07 21:02:26 +02:00
Vincent Richard
71968d978d
Merge branch 'master' into master 2018-09-07 20:32:51 +02:00
Vincent Richard
ea0d24809d Useless mutex does not make nl_langinfo() thread-safe. 2018-09-06 20:09:54 +02:00
Vincent Richard
cfd4492915 More tests. 2018-09-06 00:22:34 +02:00
Vincent Richard
7e29cf01fa Fixed bug in implementation of isStringEqualNoCase(). 2018-09-06 00:16:48 +02:00
Vincent Richard
258f943ded Moved implementation. 2018-09-06 00:13:24 +02:00
Vincent Richard
3bd864efc2 Fixed possible memory leak. 2018-09-06 00:05:13 +02:00
Vincent Richard
b55bdc9c0b Code style and clarity. 2018-09-05 23:54:48 +02:00
Vincent Richard
71a0fa4b26
Merge pull request #198 from xguerin/master
Import multiple certificates withing a single stream
2018-09-05 23:35:50 +02:00
Vincent Richard
5cd1f2990a
Merge pull request #201 from 0xd34df00d/master
Added net::message::getName() + the IMAP implementation
2018-08-31 18:59:36 +02:00
Vincent Richard
d4c386beda Removed useless 'constCast's. 2018-08-18 19:51:21 +02:00
Vincent Richard
f173b0a535 Avoid copy by passing shared_ptr<> with const reference. 2018-08-18 16:08:25 +02:00
Vincent Richard
997616c629 Fixed delete array. 2018-08-18 13:52:20 +02:00
Vincent Richard
81e73c0f56 Fixed compilation errors with OpenSSL 1.1.0. 2018-08-17 21:29:02 +02:00
Vincent Richard
1e56a3617d Force classic locale when formatting IMAP UIDs. 2018-08-17 21:22:11 +02:00
Vincent Richard
5eae3b1bd6 Fixed warnings with GCC 7. 2018-08-17 21:10:48 +02:00
Vincent Richard
f9a4099837 Added section about tracing. 2018-08-17 20:30:21 +02:00
0xd34df00d
52042b2b5b Added net::message::getName() + the IMAP implementation. 2018-07-04 16:03:49 -04:00
Xavier Guérin
df8051d8db Import multiple certificates withing a single stream 2018-05-30 22:17:15 -04:00
Xavier Guérin
6ad4c1a0d5 Fix X509Certificate::getIssuerString signature 2018-05-30 20:20:56 -04:00
Vincent Richard
a9b822140b #196 Allow overriding CMAKE_CXX_FLAGS 2018-04-24 20:31:26 +02:00
Vincent Richard
8495ce1116 #194 Fixed documentation 2018-04-04 20:10:28 +02:00
Vincent Richard
8564b2f8b0 #193 Dropped support for boot::shared_ptr<>, enabled C++11 support in CMake 2018-04-01 11:29:07 +02:00
Vincent Richard
ed825ba255
Merge pull request #181 from rusdevops/patch-2
Update CMakeLists.txt
2018-03-12 20:42:03 +01:00
Vincent Richard
f04190bafa #191 X509Certificate::import() now auto-detects format 2018-03-12 20:37:12 +01:00
Vincent Richard
abba40e97d Added unit test related to PR #192. 2018-03-12 20:33:27 +01:00
Vincent Richard
754e556aeb
Merge pull request #192 from bosim/address-parsing
Handle parsing of a@b.c <e@f.g>
2018-03-12 20:31:03 +01:00
Bo Simonsen
b73d765f51 Handle parsing of a@b.c <e@f.g>
The behavior of current VMIME implementation will result in address a@b.c
with an empty name. That is because the parsing is stopped whenever a
wihtespace and a at-character is seen. We should continue the parsing to
deduce the real address (e@f.g in the example).
2018-02-19 13:08:09 +01:00
Vincent Richard
680057bacd
Merge pull request #184 from josusky/smtp-auth
Add SMTPS with AUTH PLAIN without SASL.
2017-12-20 08:46:28 +01:00
Vincent Richard
d7a1b5817e Issue #186: SMTPUTF8 is not an argument to RCPT + UTF8 in recipient address must switch the whole message to SMTPUTF8. 2017-12-14 22:11:58 +01:00
Vincent Richard
1592cccb61 Fixed #186: use SMTPUTF8 only when needed. 2017-12-14 21:39:29 +01:00
Jan Osusky
dff676572a Add SMTPS with AUTH PLAIN without SASL
GNU SASL is a nice library but comes with its own prerequisites and dependencies.
As IMAP and POP3 are able to work without SASL it seems to me logical to add some authentication support to SMTP too. As these days most of the communication is encrypted it is common to use simple mechanism like AUTH PLAIN, so I have added it.
2017-11-03 18:30:43 +01:00
Jan Osusky
6cfe2c5f6c Add SMTPS with AUTH PLAIN without SASL
GNU SASL is a nice library but comes with its own prerequisites and dependencies.
As IMAP and POP3 are able to work without SASL it seems to me logical to add some authentication support to SMTP too. As these days most of the communication is encrypted it is common to use simple mechanism like AUTH PLAIN, so I have added it.
2017-10-20 16:06:14 +02:00
Jan Osusky
9e97519186 Fix of compilation warning reported by GCC 4.9.3
'class vmime::net::messageSetEnumerator' has virtual functions and accessible non-virtual destructor
2017-10-20 15:44:39 +02:00
Vincent Richard
eb5d9db693 Merge pull request #182 from miachm/master
Remove unnecessary public in vmime::encoding
2017-10-18 08:58:52 +02:00
Miguel Chacon
e83937ba42 Remove unnecesary public in vmime::enconding 2017-10-17 21:11:03 +02:00
rusdevops
51af739f8e Update CMakeLists.txt 2017-10-12 08:06:53 -07:00
rusdevops
b848dec86a Update CMakeLists.txt 2017-10-12 07:53:24 -07:00
Vincent Richard
79e96398cd Merge pull request #180 from rusdevops/patch-1
Update CMakeLists.txt
2017-10-09 20:15:07 +02:00
rusdevops
a965f64262 Update CMakeLists.txt 2017-10-04 11:52:54 +03:00
Vincent Richard
e14fd4f2c9 Issue #179: fixed input/output buffer size. 2017-09-06 20:59:10 +02:00
Vincent Richard
a370654a32 Merge pull request #178 from Aulddays/master
Fixed send performance issue
2017-08-18 21:12:45 +02:00
Aulddays
c6cf359ffc Fixed send performance issue 2017-08-18 17:15:36 +08:00
Vincent Richard
243efb267f Fixed #177: thread id on OpenBSD. 2017-08-09 20:39:54 +02:00
Vincent Richard
f61efd2f36 Clear OpenSSL error queue before calling a SSL_*() function, then SSL_get_error(). 2017-07-14 07:16:41 +02:00
Vincent Richard
5ea19601d5 Fixed #176: fixed missing definition of AF_UNSPEC and SOCK_STREAM on OpenBSD systems. 2017-07-14 06:32:58 +02:00
Vincent Richard
3d3ed7b260 Issue #175: use CMake macros for installation dir. 2017-06-19 22:08:45 +02:00
Vincent Richard
50b312f98a Issue #173: recognize non-standard '8bits' encoding. 2017-06-19 21:24:10 +02:00
Vincent Richard
ea66541338 Issue #138: fixed non-portable HOST_NAME_MAX. 2017-05-08 21:53:26 +02:00
Vincent Richard
8d3ea37b55 Issue #138: more reliable detection of strerror_r() variant. 2017-05-08 21:46:00 +02:00
Vincent Richard
d2b3f98ba1 Fixed #171: cross-compiling detection. 2017-05-04 21:38:50 +02:00
Vincent Richard
8146d80e0c Removed unused VMIME_TARGET_* defines. 2017-04-26 19:07:24 +02:00
Vincent Richard
1806073524 Merge pull request #169 from 0xd34df00d/master
Remove target architecture detection.
2017-04-26 19:06:26 +02:00
0xd34df00d
1862f165c2 Remove target architecture detection. 2017-04-08 20:02:34 -04:00
Vincent Richard
8e6db1c7a6 Merge branch 'master' of https://github.com/kisli/vmime 2017-03-29 21:28:45 +02:00
Vincent Richard
604b713562 Issue #168: multiple sequences of 'LF..' not replaced correctly. 2017-03-28 22:31:04 +02:00
Vincent Richard
1bc9f457be Merge pull request #165 from bmagistro/master
Ensure user defined parsingContext is passed forward on calls to parse.
2017-03-13 20:18:04 +01:00
Vincent Richard
041854731c Issue #167: don't build samples by default. 2017-03-13 18:45:26 +01:00
Vincent Richard
428c49b69f Issue #166: fixed include paths. 2017-03-13 18:44:52 +01:00
bmagistro
522ec147a3 fix deleted character 2017-03-09 15:40:50 -05:00
bmagistro
975f555f22 attempt 2, fix whitespace differences 2017-03-09 14:20:43 -05:00
bmagistro
e6f2ed341a attempt 2, fix whitespace differences 2017-03-09 14:07:15 -05:00
bmagistro
8fb7b007f9 use original headerField.cpp to avoid whitespace differences 2017-02-27 11:12:12 -05:00
bmagistro
68fd4e1e42 add option to control parser invalid line behavior 2017-02-27 11:04:33 -05:00
bmagistro
05a65a3bfa ensure user defined parsingContext is passed forward on calls to parse 2017-02-25 09:17:49 -05:00
Vincent Richard
3cfcdca2ff Added example on how to fetch additional header fields. 2017-02-10 21:53:33 +01:00
Vincent Richard
9a3d6880e8 Fixed issue #160: invalid characters in hostname. 2017-02-10 21:20:22 +01:00
Vincent Richard
e973619d7e Issue #163: default encoder (fallback). 2017-02-08 21:27:10 +01:00
Vincent Richard
ec5f4370b6 Fixed #159: parsing error on invalid FETCH BODYSTRUCTURE response. 2017-01-18 21:10:10 +01:00
Vincent Richard
f29edeb887 Fixed possible bad memory access. 2017-01-17 21:22:44 +01:00
Vincent Richard
08b8ce3dc7 Emulate extraction of header+body for a specific part (IMAP). 2017-01-12 23:00:04 +01:00
Vincent Richard
8a63b02764 Fixed issue #157. 2017-01-11 20:20:05 +01:00
575 changed files with 31712 additions and 26016 deletions

25
.github/workflows/build.yml vendored Normal file
View 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

View File

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

@ -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.

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

View File

@ -1 +0,0 @@
build

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

@ -0,0 +1 @@
https://github.com/nemtrif/utfcpp/releases/tag/v4.0.5

View File

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

View File

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

View File

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

View File

@ -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);

View File

@ -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}

View File

@ -25,8 +25,6 @@ want SASL\footnote{Simple Authentication and Security Layer} support ;
\item either the \href{http://www.openssl.org}{OpenSSL library} or the
\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}
% ============================================================================

View File

@ -55,7 +55,7 @@ General Public License\footnote{See Appendix \ref{appendix_license} and
\url{http://www.gnu.org/copyleft/gpl.html}} (GPL) version 3:
\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

View File

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

View File

@ -300,10 +300,10 @@ The following example shows how to use a custom authenticator to request
the user to enter her/his credentials:
\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...}"").

View File

@ -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>();

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

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

View File

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

View File

@ -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>();
}
};

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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
);
};

View File

@ -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()));
}
}

View File

@ -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;
};

View File

@ -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;
};

View File

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

View File

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

View File

@ -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();

View File

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

View File

@ -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;
};

View File

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

View File

@ -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;
};

View File

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

View File

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

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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) {
}

View File

@ -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
);
};

View File

@ -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("?") {
}

View File

@ -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();

View File

@ -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);

View File

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

View File

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

View File

@ -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;
}

View File

@ -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:

View File

@ -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;
}

View File

@ -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:

View File

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

View File

@ -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:

View File

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

View File

@ -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;
}
}

View File

@ -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> >();
}

View File

@ -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;
};

View File

@ -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));
}

View File

@ -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:

View File

@ -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() {
}

View File

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

View File

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

View File

@ -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:

View File

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