aboutsummaryrefslogtreecommitdiff
path: root/gnu/packages/purescript.scm
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/packages/purescript.scm')
0 files changed, 0 insertions, 0 deletions
.2%;'/> -rw-r--r--vmime-master/COPYING674
-rw-r--r--vmime-master/COPYING.OpenSSL26
-rw-r--r--vmime-master/Doxyfile.in1043
-rw-r--r--vmime-master/HACKING360
-rw-r--r--vmime-master/NEWS0
-rw-r--r--vmime-master/README30
-rw-r--r--vmime-master/README.autotools13
-rwxr-xr-xvmime-master/build_for_losedows.sh23
-rw-r--r--vmime-master/cmake/FindCppUnit.cmake34
-rw-r--r--vmime-master/cmake/FindGSasl.cmake51
-rw-r--r--vmime-master/cmake/FindICU.cmake314
-rw-r--r--vmime-master/cmake/FindIconv.cmake61
-rw-r--r--vmime-master/cmake/Utils.cmake13
-rw-r--r--vmime-master/cmake/config.hpp.cmake97
-rw-r--r--vmime-master/config_header/config.hpp97
-rw-r--r--vmime-master/contrib/punycode/punycode.c264
-rw-r--r--vmime-master/contrib/punycode/punycode.h84
-rw-r--r--vmime-master/contrib/utf8/utf8.h34
-rw-r--r--vmime-master/contrib/utf8/utf8/checked.h327
-rw-r--r--vmime-master/contrib/utf8/utf8/core.h326
-rw-r--r--vmime-master/contrib/utf8/utf8/unchecked.h228
-rw-r--r--vmime-master/doc/book/.gitignore17
-rw-r--r--vmime-master/doc/book/basics.tex823
-rw-r--r--vmime-master/doc/book/book.tex118
-rw-r--r--vmime-master/doc/book/building.tex175
-rw-r--r--vmime-master/doc/book/images/address-mailbox-mailboxgroup.svg355
-rw-r--r--vmime-master/doc/book/images/message-body-header.svg716
-rw-r--r--vmime-master/doc/book/images/messaging-services.svg617
-rw-r--r--vmime-master/doc/book/intro.tex90
-rw-r--r--vmime-master/doc/book/msg.tex430
-rw-r--r--vmime-master/doc/book/net.tex1203
-rw-r--r--vmime-master/doc/book/start.tex111
-rw-r--r--vmime-master/examples/CMakeLists.txt38
-rw-r--r--vmime-master/examples/example1.cpp107
-rw-r--r--vmime-master/examples/example2.cpp121
-rw-r--r--vmime-master/examples/example3.cpp153
-rw-r--r--vmime-master/examples/example4.cpp108
-rw-r--r--vmime-master/examples/example5.cpp85
-rw-r--r--vmime-master/examples/example6.cpp938
-rw-r--r--vmime-master/examples/example6_authenticator.hpp112
-rw-r--r--vmime-master/examples/example6_certificateVerifier.hpp64
-rw-r--r--vmime-master/examples/example6_timeoutHandler.hpp60
-rw-r--r--vmime-master/examples/example6_tracer.hpp59
-rw-r--r--vmime-master/examples/example7.cpp118
-rw-r--r--vmime-master/examples/viewer/CMakeLists.txt31
-rw-r--r--vmime-master/examples/viewer/viewer.cpp294
-rw-r--r--vmime-master/mingw_cross_toolchain.cmake14
-rw-r--r--vmime-master/src/vmime/address.cpp236
-rw-r--r--vmime-master/src/vmime/address.hpp89
-rw-r--r--vmime-master/src/vmime/addressList.cpp328
-rw-r--r--vmime-master/src/vmime/addressList.hpp198
-rw-r--r--vmime-master/src/vmime/attachment.hpp116
-rw-r--r--vmime-master/src/vmime/attachmentHelper.cpp339
-rw-r--r--vmime-master/src/vmime/attachmentHelper.hpp137
-rw-r--r--vmime-master/src/vmime/base.cpp158
-rw-r--r--vmime-master/src/vmime/base.hpp258
-rw-r--r--vmime-master/src/vmime/body.cpp1111
-rw-r--r--vmime-master/src/vmime/body.hpp365
-rw-r--r--vmime-master/src/vmime/bodyPart.cpp198
-rw-r--r--vmime-master/src/vmime/bodyPart.hpp155
-rw-r--r--vmime-master/src/vmime/bodyPartAttachment.cpp147
-rw-r--r--vmime-master/src/vmime/bodyPartAttachment.hpp76
-rw-r--r--vmime-master/src/vmime/charset.cpp268
-rw-r--r--vmime-master/src/vmime/charset.hpp176
-rw-r--r--vmime-master/src/vmime/charsetConverter.cpp53
-rw-r--r--vmime-master/src/vmime/charsetConverter.hpp162
-rw-r--r--vmime-master/src/vmime/charsetConverterOptions.cpp37
-rw-r--r--vmime-master/src/vmime/charsetConverterOptions.hpp59
-rw-r--r--vmime-master/src/vmime/charsetConverter_iconv.cpp537
-rw-r--r--vmime-master/src/vmime/charsetConverter_iconv.hpp145
-rw-r--r--vmime-master/src/vmime/charsetConverter_icu.cpp572
-rw-r--r--vmime-master/src/vmime/charsetConverter_icu.hpp137
-rw-r--r--vmime-master/src/vmime/charsetConverter_idna.cpp208
-rw-r--r--vmime-master/src/vmime/charsetConverter_idna.hpp74
-rw-r--r--vmime-master/src/vmime/charsetConverter_win.cpp227
-rw-r--r--vmime-master/src/vmime/charsetConverter_win.hpp91
-rw-r--r--vmime-master/src/vmime/component.cpp275
-rw-r--r--vmime-master/src/vmime/component.hpp265
-rw-r--r--vmime-master/src/vmime/constants.cpp251
-rw-r--r--vmime-master/src/vmime/constants.hpp272
-rw-r--r--vmime-master/src/vmime/contentDisposition.cpp144
-rw-r--r--vmime-master/src/vmime/contentDisposition.hpp99
-rw-r--r--vmime-master/src/vmime/contentDispositionField.cpp162
-rw-r--r--vmime-master/src/vmime/contentDispositionField.hpp146
-rw-r--r--vmime-master/src/vmime/contentHandler.cpp39
-rw-r--r--vmime-master/src/vmime/contentHandler.hpp147
-rw-r--r--vmime-master/src/vmime/contentTypeField.cpp114
-rw-r--r--vmime-master/src/vmime/contentTypeField.hpp113
-rw-r--r--vmime-master/src/vmime/context.cpp86
-rw-r--r--vmime-master/src/vmime/context.hpp120
-rw-r--r--vmime-master/src/vmime/dateTime.cpp925
-rw-r--r--vmime-master/src/vmime/dateTime.hpp275
-rw-r--r--vmime-master/src/vmime/defaultAttachment.cpp164
-rw-r--r--vmime-master/src/vmime/defaultAttachment.hpp99
-rw-r--r--vmime-master/src/vmime/disposition.cpp351
-rw-r--r--vmime-master/src/vmime/disposition.hpp163
-rw-r--r--vmime-master/src/vmime/emailAddress.cpp708
-rw-r--r--vmime-master/src/vmime/emailAddress.hpp135
-rw-r--r--vmime-master/src/vmime/emptyContentHandler.cpp126
-rw-r--r--vmime-master/src/vmime/emptyContentHandler.hpp80
-rw-r--r--vmime-master/src/vmime/encoding.cpp331
-rw-r--r--vmime-master/src/vmime/encoding.hpp180
-rw-r--r--vmime-master/src/vmime/exception.cpp735
-rw-r--r--vmime-master/src/vmime/exception.hpp865
-rw-r--r--vmime-master/src/vmime/export.hpp36
-rw-r--r--vmime-master/src/vmime/fileAttachment.cpp253
-rw-r--r--vmime-master/src/vmime/fileAttachment.hpp226
-rw-r--r--vmime-master/src/vmime/fileContentHandler.cpp94
-rw-r--r--vmime-master/src/vmime/fileContentHandler.hpp102
-rw-r--r--vmime-master/src/vmime/generatedMessageAttachment.cpp108
-rw-r--r--vmime-master/src/vmime/generatedMessageAttachment.hpp77
-rw-r--r--vmime-master/src/vmime/generationContext.cpp139
-rw-r--r--vmime-master/src/vmime/generationContext.hpp171
-rw-r--r--vmime-master/src/vmime/header.cpp417
-rw-r--r--vmime-master/src/vmime/header.hpp362
-rw-r--r--vmime-master/src/vmime/headerField.cpp374
-rw-r--r--vmime-master/src/vmime/headerField.hpp191
-rw-r--r--vmime-master/src/vmime/headerFieldFactory.cpp158
-rw-r--r--vmime-master/src/vmime/headerFieldFactory.hpp159
-rw-r--r--vmime-master/src/vmime/headerFieldValue.cpp43
-rw-r--r--vmime-master/src/vmime/headerFieldValue.hpp49
-rw-r--r--vmime-master/src/vmime/htmlTextPart.cpp568
-rw-r--r--vmime-master/src/vmime/htmlTextPart.hpp268
-rw-r--r--vmime-master/src/vmime/mailbox.cpp476
-rw-r--r--vmime-master/src/vmime/mailbox.hpp123
-rw-r--r--vmime-master/src/vmime/mailboxField.cpp96
-rw-r--r--vmime-master/src/vmime/mailboxField.hpp69
-rw-r--r--vmime-master/src/vmime/mailboxGroup.cpp406
-rw-r--r--vmime-master/src/vmime/mailboxGroup.hpp206
-rw-r--r--vmime-master/src/vmime/mailboxList.cpp252
-rw-r--r--vmime-master/src/vmime/mailboxList.hpp184
-rw-r--r--vmime-master/src/vmime/mdn/MDNHelper.cpp362
-rw-r--r--vmime-master/src/vmime/mdn/MDNHelper.hpp142
-rw-r--r--vmime-master/src/vmime/mdn/MDNInfos.cpp38
-rw-r--r--vmime-master/src/vmime/mdn/MDNInfos.hpp57
-rw-r--r--vmime-master/src/vmime/mdn/receivedMDNInfos.cpp140
-rw-r--r--vmime-master/src/vmime/mdn/receivedMDNInfos.hpp93
-rw-r--r--vmime-master/src/vmime/mdn/sendableMDNInfos.cpp72
-rw-r--r--vmime-master/src/vmime/mdn/sendableMDNInfos.hpp72
-rw-r--r--vmime-master/src/vmime/mediaType.cpp207
-rw-r--r--vmime-master/src/vmime/mediaType.hpp119
-rw-r--r--vmime-master/src/vmime/message.cpp49
-rw-r--r--vmime-master/src/vmime/message.hpp60
-rw-r--r--vmime-master/src/vmime/messageAttachment.hpp52
-rw-r--r--vmime-master/src/vmime/messageBuilder.cpp333
-rw-r--r--vmime-master/src/vmime/messageBuilder.hpp221
-rw-r--r--vmime-master/src/vmime/messageId.cpp329
-rw-r--r--vmime-master/src/vmime/messageId.hpp144
-rw-r--r--vmime-master/src/vmime/messageIdSequence.cpp277
-rw-r--r--vmime-master/src/vmime/messageIdSequence.hpp175
-rw-r--r--vmime-master/src/vmime/messageParser.cpp328
-rw-r--r--vmime-master/src/vmime/messageParser.hpp164
-rw-r--r--vmime-master/src/vmime/misc/importanceHelper.cpp163
-rw-r--r--vmime-master/src/vmime/misc/importanceHelper.hpp103
-rw-r--r--vmime-master/src/vmime/net/builtinServices.inl76
-rw-r--r--vmime-master/src/vmime/net/connectionInfos.hpp68
-rw-r--r--vmime-master/src/vmime/net/defaultConnectionInfos.cpp60
-rw-r--r--vmime-master/src/vmime/net/defaultConnectionInfos.hpp66
-rw-r--r--vmime-master/src/vmime/net/defaultTimeoutHandler.cpp78
-rw-r--r--vmime-master/src/vmime/net/defaultTimeoutHandler.hpp80
-rw-r--r--vmime-master/src/vmime/net/dsnAttributes.cpp71
-rw-r--r--vmime-master/src/vmime/net/dsnAttributes.hpp114
-rw-r--r--vmime-master/src/vmime/net/events.cpp180
-rw-r--r--vmime-master/src/vmime/net/events.hpp276
-rw-r--r--vmime-master/src/vmime/net/fetchAttributes.cpp98
-rw-r--r--vmime-master/src/vmime/net/fetchAttributes.hpp140
-rw-r--r--vmime-master/src/vmime/net/folder.cpp134
-rw-r--r--vmime-master/src/vmime/net/folder.hpp440
-rw-r--r--vmime-master/src/vmime/net/folderAttributes.cpp122
-rw-r--r--vmime-master/src/vmime/net/folderAttributes.hpp177
-rw-r--r--vmime-master/src/vmime/net/folderStatus.hpp73
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPCommand.cpp437
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPCommand.hpp124
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPConnection.cpp886
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPConnection.hpp172
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPFolder.cpp1622
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPFolder.hpp230
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPFolderStatus.cpp292
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPFolderStatus.hpp123
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPMessage.cpp760
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPMessage.hpp200
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPMessagePart.cpp225
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPMessagePart.hpp108
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp227
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp95
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPMessageStructure.cpp94
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPMessageStructure.hpp75
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPParser.hpp4986
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPSStore.cpp82
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPSStore.hpp70
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPServiceInfos.cpp135
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPServiceInfos.hpp89
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPStore.cpp287
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPStore.hpp124
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPTag.cpp148
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPTag.hpp85
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPUtils.cpp854
-rw-r--r--vmime-master/src/vmime/net/imap/IMAPUtils.hpp144
-rw-r--r--vmime-master/src/vmime/net/imap/imap.hpp35
-rw-r--r--vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.cpp569
-rw-r--r--vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.hpp127
-rw-r--r--vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.cpp337
-rw-r--r--vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.hpp115
-rw-r--r--vmime-master/src/vmime/net/maildir/maildir.hpp34
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirFolder.cpp1365
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirFolder.hpp211
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirFolderStatus.cpp88
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirFolderStatus.hpp75
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirFormat.cpp104
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirFormat.hpp192
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirMessage.cpp410
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirMessage.hpp137
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirMessagePart.cpp178
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirMessagePart.hpp106
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirMessageStructure.cpp104
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirMessageStructure.hpp82
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirServiceInfos.cpp76
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirServiceInfos.hpp69
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirStore.cpp294
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirStore.hpp123
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirUtils.cpp288
-rw-r--r--vmime-master/src/vmime/net/maildir/maildirUtils.hpp160
-rw-r--r--vmime-master/src/vmime/net/message.cpp155
-rw-r--r--vmime-master/src/vmime/net/message.hpp369
-rw-r--r--vmime-master/src/vmime/net/messageSet.cpp430
-rw-r--r--vmime-master/src/vmime/net/messageSet.hpp358
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Command.cpp267
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Command.hpp123
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Connection.cpp737
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Connection.hpp132
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Folder.cpp822
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Folder.hpp179
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3FolderStatus.cpp88
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3FolderStatus.hpp75
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Message.cpp283
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Message.hpp124
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Response.cpp504
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Response.hpp194
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3SStore.cpp82
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3SStore.hpp74
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3ServiceInfos.cpp142
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3ServiceInfos.hpp91
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Store.cpp262
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Store.hpp120
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Utils.cpp135
-rw-r--r--vmime-master/src/vmime/net/pop3/POP3Utils.hpp92
-rw-r--r--vmime-master/src/vmime/net/pop3/pop3.hpp35
-rw-r--r--vmime-master/src/vmime/net/securedConnectionInfos.hpp55
-rw-r--r--vmime-master/src/vmime/net/sendmail/sendmail.hpp31
-rw-r--r--vmime-master/src/vmime/net/sendmail/sendmailServiceInfos.cpp77
-rw-r--r--vmime-master/src/vmime/net/sendmail/sendmailServiceInfos.hpp69
-rw-r--r--vmime-master/src/vmime/net/sendmail/sendmailTransport.cpp244
-rw-r--r--vmime-master/src/vmime/net/sendmail/sendmailTransport.hpp112
-rw-r--r--vmime-master/src/vmime/net/service.cpp170
-rw-r--r--vmime-master/src/vmime/net/service.hpp239
-rw-r--r--vmime-master/src/vmime/net/serviceFactory.cpp157
-rw-r--r--vmime-master/src/vmime/net/serviceFactory.hpp168
-rw-r--r--vmime-master/src/vmime/net/serviceInfos.cpp198
-rw-r--r--vmime-master/src/vmime/net/serviceInfos.hpp263
-rw-r--r--vmime-master/src/vmime/net/serviceRegistration.inl105
-rw-r--r--vmime-master/src/vmime/net/session.cpp188
-rw-r--r--vmime-master/src/vmime/net/session.hpp206
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp180
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp94
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPCommand.cpp258
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPCommand.hpp125
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPCommandSet.cpp160
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPCommandSet.hpp106
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPConnection.cpp714
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPConnection.hpp136
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPExceptions.cpp212
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPExceptions.hpp159
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPResponse.cpp366
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPResponse.hpp200
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPSTransport.cpp82
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPSTransport.hpp74
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPServiceInfos.cpp144
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPServiceInfos.hpp93
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPTransport.cpp502
-rw-r--r--vmime-master/src/vmime/net/smtp/SMTPTransport.hpp144
-rw-r--r--vmime-master/src/vmime/net/smtp/smtp.hpp33
-rw-r--r--vmime-master/src/vmime/net/socket.hpp223
-rw-r--r--vmime-master/src/vmime/net/store.cpp57
-rw-r--r--vmime-master/src/vmime/net/store.hpp115
-rw-r--r--vmime-master/src/vmime/net/timeoutHandler.hpp89
-rw-r--r--vmime-master/src/vmime/net/tls/TLSProperties.cpp44
-rw-r--r--vmime-master/src/vmime/net/tls/TLSProperties.hpp105
-rw-r--r--vmime-master/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp77
-rw-r--r--vmime-master/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp88
-rw-r--r--vmime-master/src/vmime/net/tls/TLSSession.cpp48
-rw-r--r--vmime-master/src/vmime/net/tls/TLSSession.hpp96
-rw-r--r--vmime-master/src/vmime/net/tls/TLSSocket.cpp44
-rw-r--r--vmime-master/src/vmime/net/tls/TLSSocket.hpp88
-rw-r--r--vmime-master/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp113
-rw-r--r--vmime-master/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp68
-rw-r--r--vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp313
-rw-r--r--vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp95
-rw-r--r--vmime-master/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp548
-rw-r--r--vmime-master/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp129
-rw-r--r--vmime-master/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp169
-rw-r--r--vmime-master/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp90
-rw-r--r--vmime-master/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp112
-rw-r--r--vmime-master/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp68
-rw-r--r--vmime-master/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp147
-rw-r--r--vmime-master/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp109
-rw-r--r--vmime-master/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp761
-rw-r--r--vmime-master/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp142
-rw-r--r--vmime-master/src/vmime/net/tracer.cpp74
-rw-r--r--vmime-master/src/vmime/net/tracer.hpp110
-rw-r--r--vmime-master/src/vmime/net/transport.cpp265
-rw-r--r--vmime-master/src/vmime/net/transport.hpp152
-rw-r--r--vmime-master/src/vmime/object.cpp52
-rw-r--r--vmime-master/src/vmime/object.hpp52
-rw-r--r--vmime-master/src/vmime/parameter.cpp665
-rw-r--r--vmime-master/src/vmime/parameter.hpp176
-rw-r--r--vmime-master/src/vmime/parameterizedHeaderField.cpp634
-rw-r--r--vmime-master/src/vmime/parameterizedHeaderField.hpp222
-rw-r--r--vmime-master/src/vmime/parsedMessageAttachment.cpp114
-rw-r--r--vmime-master/src/vmime/parsedMessageAttachment.hpp76
-rw-r--r--vmime-master/src/vmime/parserHelpers.hpp140
-rw-r--r--vmime-master/src/vmime/parsingContext.cpp64
-rw-r--r--vmime-master/src/vmime/parsingContext.hpp82
-rw-r--r--vmime-master/src/vmime/path.cpp206
-rw-r--r--vmime-master/src/vmime/path.hpp106
-rw-r--r--vmime-master/src/vmime/plainTextPart.cpp121
-rw-r--r--vmime-master/src/vmime/plainTextPart.hpp74
-rw-r--r--vmime-master/src/vmime/platform.cpp77
-rw-r--r--vmime-master/src/vmime/platform.hpp158
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixChildProcess.cpp410
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixChildProcess.hpp92
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixCriticalSection.cpp67
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixCriticalSection.hpp69
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixFile.cpp715
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixFile.hpp224
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixHandler.cpp292
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixHandler.hpp103
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixSocket.cpp969
-rw-r--r--vmime-master/src/vmime/platforms/posix/posixSocket.hpp118
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsCodepages.hpp197
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsCriticalSection.cpp67
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsCriticalSection.hpp68
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsFile.cpp712
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsFile.hpp225
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsHandler.cpp315
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsHandler.hpp101
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsSocket.cpp547
-rw-r--r--vmime-master/src/vmime/platforms/windows/windowsSocket.hpp117
-rw-r--r--vmime-master/src/vmime/propertySet.cpp399
-rw-r--r--vmime-master/src/vmime/propertySet.hpp461
-rw-r--r--vmime-master/src/vmime/relay.cpp363
-rw-r--r--vmime-master/src/vmime/relay.hpp108
-rw-r--r--vmime-master/src/vmime/security/authenticator.hpp136
-rw-r--r--vmime-master/src/vmime/security/cert/X509Certificate.cpp72
-rw-r--r--vmime-master/src/vmime/security/cert/X509Certificate.hpp197
-rw-r--r--vmime-master/src/vmime/security/cert/certificate.hpp84
-rw-r--r--vmime-master/src/vmime/security/cert/certificateChain.cpp53
-rw-r--r--vmime-master/src/vmime/security/cert/certificateChain.hpp79
-rw-r--r--vmime-master/src/vmime/security/cert/certificateException.cpp84
-rw-r--r--vmime-master/src/vmime/security/cert/certificateException.hpp95
-rw-r--r--vmime-master/src/vmime/security/cert/certificateExpiredException.cpp55
-rw-r--r--vmime-master/src/vmime/security/cert/certificateExpiredException.hpp65
-rw-r--r--vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.cpp55
-rw-r--r--vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.hpp65
-rw-r--r--vmime-master/src/vmime/security/cert/certificateNotTrustedException.cpp55
-rw-r--r--vmime-master/src/vmime/security/cert/certificateNotTrustedException.hpp65
-rw-r--r--vmime-master/src/vmime/security/cert/certificateNotYetValidException.cpp55
-rw-r--r--vmime-master/src/vmime/security/cert/certificateNotYetValidException.hpp65
-rw-r--r--vmime-master/src/vmime/security/cert/certificateVerifier.hpp76
-rw-r--r--vmime-master/src/vmime/security/cert/defaultCertificateVerifier.cpp191
-rw-r--r--vmime-master/src/vmime/security/cert/defaultCertificateVerifier.hpp98
-rw-r--r--vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp395
-rw-r--r--vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp96
-rw-r--r--vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp655
-rw-r--r--vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp119
-rw-r--r--vmime-master/src/vmime/security/cert/serverIdentityException.cpp55
-rw-r--r--vmime-master/src/vmime/security/cert/serverIdentityException.hpp65
-rw-r--r--vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.cpp61
-rw-r--r--vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.hpp72
-rw-r--r--vmime-master/src/vmime/security/defaultAuthenticator.cpp130
-rw-r--r--vmime-master/src/vmime/security/defaultAuthenticator.hpp73
-rw-r--r--vmime-master/src/vmime/security/digest/md5/md5MessageDigest.cpp349
-rw-r--r--vmime-master/src/vmime/security/digest/md5/md5MessageDigest.hpp85
-rw-r--r--vmime-master/src/vmime/security/digest/messageDigest.cpp56
-rw-r--r--vmime-master/src/vmime/security/digest/messageDigest.hpp142
-rw-r--r--vmime-master/src/vmime/security/digest/messageDigestFactory.cpp81
-rw-r--r--vmime-master/src/vmime/security/digest/messageDigestFactory.hpp110
-rw-r--r--vmime-master/src/vmime/security/digest/sha1/sha1MessageDigest.cpp276
-rw-r--r--vmime-master/src/vmime/security/digest/sha1/sha1MessageDigest.hpp79
-rw-r--r--vmime-master/src/vmime/security/sasl/SASLAuthenticator.hpp96
-rw-r--r--vmime-master/src/vmime/security/sasl/SASLContext.cpp221
-rw-r--r--vmime-master/src/vmime/security/sasl/SASLContext.hpp136
-rw-r--r--vmime-master/src/vmime/security/sasl/SASLMechanism.hpp153
-rw-r--r--vmime-master/src/vmime/security/sasl/SASLMechanismFactory.cpp149
-rw-r--r--vmime-master/src/vmime/security/sasl/SASLMechanismFactory.hpp155
-rw-r--r--vmime-master/src/vmime/security/sasl/SASLSession.cpp221
-rw-r--r--vmime-master/src/vmime/security/sasl/SASLSession.hpp180
-rw-r--r--vmime-master/src/vmime/security/sasl/SASLSocket.cpp273
-rw-r--r--vmime-master/src/vmime/security/sasl/SASLSocket.hpp108
-rw-r--r--vmime-master/src/vmime/security/sasl/XOAuth2SASLAuthenticator.cpp99
-rw-r--r--vmime-master/src/vmime/security/sasl/XOAuth2SASLAuthenticator.hpp77
-rw-r--r--vmime-master/src/vmime/security/sasl/XOAuth2SASLMechanism.cpp155
-rw-r--r--vmime-master/src/vmime/security/sasl/XOAuth2SASLMechanism.hpp102
-rw-r--r--vmime-master/src/vmime/security/sasl/builtinSASLMechanism.cpp221
-rw-r--r--vmime-master/src/vmime/security/sasl/builtinSASLMechanism.hpp105
-rw-r--r--vmime-master/src/vmime/security/sasl/defaultSASLAuthenticator.cpp159
-rw-r--r--vmime-master/src/vmime/security/sasl/defaultSASLAuthenticator.hpp91
-rw-r--r--vmime-master/src/vmime/streamContentHandler.cpp257
-rw-r--r--vmime-master/src/vmime/streamContentHandler.hpp126
-rw-r--r--vmime-master/src/vmime/stringContentHandler.cpp228
-rw-r--r--vmime-master/src/vmime/stringContentHandler.hpp107
-rw-r--r--vmime-master/src/vmime/text.cpp536
-rw-r--r--vmime-master/src/vmime/text.hpp291
-rw-r--r--vmime-master/src/vmime/textPart.hpp117
-rw-r--r--vmime-master/src/vmime/textPartFactory.cpp68
-rw-r--r--vmime-master/src/vmime/textPartFactory.hpp77
-rw-r--r--vmime-master/src/vmime/types.hpp87
-rw-r--r--vmime-master/src/vmime/utility/childProcess.hpp103
-rw-r--r--vmime-master/src/vmime/utility/datetimeUtils.cpp317
-rw-r--r--vmime-master/src/vmime/utility/datetimeUtils.hpp98
-rw-r--r--vmime-master/src/vmime/utility/encoder/b64Encoder.cpp350
-rw-r--r--vmime-master/src/vmime/utility/encoder/b64Encoder.hpp73
-rw-r--r--vmime-master/src/vmime/utility/encoder/binaryEncoder.cpp39
-rw-r--r--vmime-master/src/vmime/utility/encoder/binaryEncoder.hpp51
-rw-r--r--vmime-master/src/vmime/utility/encoder/eightBitEncoder.cpp39
-rw-r--r--vmime-master/src/vmime/utility/encoder/eightBitEncoder.hpp51
-rw-r--r--vmime-master/src/vmime/utility/encoder/encoder.cpp76
-rw-r--r--vmime-master/src/vmime/utility/encoder/encoder.hpp135
-rw-r--r--vmime-master/src/vmime/utility/encoder/encoderFactory.cpp149
-rw-r--r--vmime-master/src/vmime/utility/encoder/encoderFactory.hpp164
-rw-r--r--vmime-master/src/vmime/utility/encoder/noopEncoder.cpp94
-rw-r--r--vmime-master/src/vmime/utility/encoder/noopEncoder.hpp66
-rw-r--r--vmime-master/src/vmime/utility/encoder/qpEncoder.cpp568
-rw-r--r--vmime-master/src/vmime/utility/encoder/qpEncoder.hpp77
-rw-r--r--vmime-master/src/vmime/utility/encoder/sevenBitEncoder.cpp39
-rw-r--r--vmime-master/src/vmime/utility/encoder/sevenBitEncoder.hpp51
-rw-r--r--vmime-master/src/vmime/utility/encoder/uuEncoder.cpp358
-rw-r--r--vmime-master/src/vmime/utility/encoder/uuEncoder.hpp68
-rw-r--r--vmime-master/src/vmime/utility/file.hpp264
-rw-r--r--vmime-master/src/vmime/utility/filteredStream.cpp402
-rw-r--r--vmime-master/src/vmime/utility/filteredStream.hpp405
-rw-r--r--vmime-master/src/vmime/utility/inputStream.cpp33
-rw-r--r--vmime-master/src/vmime/utility/inputStream.hpp75
-rw-r--r--vmime-master/src/vmime/utility/inputStreamAdapter.cpp84
-rw-r--r--vmime-master/src/vmime/utility/inputStreamAdapter.hpp65
-rw-r--r--vmime-master/src/vmime/utility/inputStreamByteBufferAdapter.cpp104
-rw-r--r--vmime-master/src/vmime/utility/inputStreamByteBufferAdapter.hpp63
-rw-r--r--vmime-master/src/vmime/utility/inputStreamPointerAdapter.cpp48
-rw-r--r--vmime-master/src/vmime/utility/inputStreamPointerAdapter.hpp61
-rw-r--r--vmime-master/src/vmime/utility/inputStreamSocketAdapter.cpp79
-rw-r--r--vmime-master/src/vmime/utility/inputStreamSocketAdapter.hpp75
-rw-r--r--vmime-master/src/vmime/utility/inputStreamStringAdapter.cpp119
-rw-r--r--vmime-master/src/vmime/utility/inputStreamStringAdapter.hpp66
-rw-r--r--vmime-master/src/vmime/utility/outputStream.cpp44
-rw-r--r--vmime-master/src/vmime/utility/outputStream.hpp133
-rw-r--r--vmime-master/src/vmime/utility/outputStreamAdapter.cpp52
-rw-r--r--vmime-master/src/vmime/utility/outputStreamAdapter.hpp63
-rw-r--r--vmime-master/src/vmime/utility/outputStreamByteArrayAdapter.cpp50
-rw-r--r--vmime-master/src/vmime/utility/outputStreamByteArrayAdapter.hpp59
-rw-r--r--vmime-master/src/vmime/utility/outputStreamSocketAdapter.cpp65
-rw-r--r--vmime-master/src/vmime/utility/outputStreamSocketAdapter.hpp76
-rw-r--r--vmime-master/src/vmime/utility/outputStreamStringAdapter.cpp52
-rw-r--r--vmime-master/src/vmime/utility/outputStreamStringAdapter.hpp59
-rw-r--r--vmime-master/src/vmime/utility/parserInputStreamAdapter.cpp175
-rw-r--r--vmime-master/src/vmime/utility/parserInputStreamAdapter.hpp172
-rw-r--r--vmime-master/src/vmime/utility/path.cpp324
-rw-r--r--vmime-master/src/vmime/utility/path.hpp189
-rw-r--r--vmime-master/src/vmime/utility/progressListener.cpp78
-rw-r--r--vmime-master/src/vmime/utility/progressListener.hpp99
-rw-r--r--vmime-master/src/vmime/utility/random.cpp90
-rw-r--r--vmime-master/src/vmime/utility/random.hpp78
-rw-r--r--vmime-master/src/vmime/utility/seekableInputStream.hpp62
-rw-r--r--vmime-master/src/vmime/utility/seekableInputStreamRegionAdapter.cpp111
-rw-r--r--vmime-master/src/vmime/utility/seekableInputStreamRegionAdapter.hpp73
-rw-r--r--vmime-master/src/vmime/utility/stream.cpp39
-rw-r--r--vmime-master/src/vmime/utility/stream.hpp60
-rw-r--r--vmime-master/src/vmime/utility/streamUtils.cpp130
-rw-r--r--vmime-master/src/vmime/utility/streamUtils.hpp83
-rw-r--r--vmime-master/src/vmime/utility/stringUtils.cpp337
-rw-r--r--vmime-master/src/vmime/utility/stringUtils.hpp271
-rw-r--r--vmime-master/src/vmime/utility/sync/autoLock.hpp65
-rw-r--r--vmime-master/src/vmime/utility/sync/criticalSection.cpp44
-rw-r--r--vmime-master/src/vmime/utility/sync/criticalSection.hpp64
-rw-r--r--vmime-master/src/vmime/utility/url.cpp431
-rw-r--r--vmime-master/src/vmime/utility/url.hpp213
-rw-r--r--vmime-master/src/vmime/utility/urlUtils.cpp133
-rw-r--r--vmime-master/src/vmime/utility/urlUtils.hpp57
-rw-r--r--vmime-master/src/vmime/vmime.hpp160
-rw-r--r--vmime-master/src/vmime/word.cpp939
-rw-r--r--vmime-master/src/vmime/word.hpp272
-rw-r--r--vmime-master/src/vmime/wordEncoder.cpp320
-rw-r--r--vmime-master/src/vmime/wordEncoder.hpp118
-rwxr-xr-xvmime-master/test-outsourced-build.sh12
-rw-r--r--vmime-master/tests/misc/importanceHelperTest.cpp191
-rw-r--r--vmime-master/tests/net/folderAttributesTest.cpp137
-rw-r--r--vmime-master/tests/net/imap/IMAPCommandTest.cpp495
-rw-r--r--vmime-master/tests/net/imap/IMAPParserTest.cpp374
-rw-r--r--vmime-master/tests/net/imap/IMAPTagTest.cpp90
-rw-r--r--vmime-master/tests/net/imap/IMAPUtilsTest.cpp283
-rw-r--r--vmime-master/tests/net/maildir/maildirStoreTest.cpp584
-rw-r--r--vmime-master/tests/net/maildir/maildirUtilsTest.cpp54
-rw-r--r--vmime-master/tests/net/messageSetTest.cpp229
-rw-r--r--vmime-master/tests/net/pop3/POP3CommandTest.cpp241
-rw-r--r--vmime-master/tests/net/pop3/POP3ResponseTest.cpp244
-rw-r--r--vmime-master/tests/net/pop3/POP3StoreTest.cpp67
-rw-r--r--vmime-master/tests/net/pop3/POP3TestUtils.hpp69
-rw-r--r--vmime-master/tests/net/pop3/POP3UtilsTest.cpp88
-rw-r--r--vmime-master/tests/net/smtp/SMTPCommandSetTest.cpp181
-rw-r--r--vmime-master/tests/net/smtp/SMTPCommandTest.cpp252
-rw-r--r--vmime-master/tests/net/smtp/SMTPResponseTest.cpp238
-rw-r--r--vmime-master/tests/net/smtp/SMTPTransportTest.cpp324
-rw-r--r--vmime-master/tests/net/smtp/SMTPTransportTestUtils.hpp792
-rw-r--r--vmime-master/tests/parser/attachmentHelperTest.cpp335
-rw-r--r--vmime-master/tests/parser/bodyPartTest.cpp414
-rw-r--r--vmime-master/tests/parser/bodyTest.cpp79
-rw-r--r--vmime-master/tests/parser/charsetFilteredOutputStreamTest.cpp213
-rw-r--r--vmime-master/tests/parser/charsetTest.cpp252
-rw-r--r--vmime-master/tests/parser/charsetTestSuites.hpp102
-rw-r--r--vmime-master/tests/parser/datetimeTest.cpp123
-rw-r--r--vmime-master/tests/parser/dispositionTest.cpp150
-rw-r--r--vmime-master/tests/parser/emailAddressTest.cpp281
-rw-r--r--vmime-master/tests/parser/emptyContentHandlerTest.cpp99
-rw-r--r--vmime-master/tests/parser/fileContentHandlerTest.cpp134
-rw-r--r--vmime-master/tests/parser/headerFieldTest.cpp112
-rw-r--r--vmime-master/tests/parser/headerTest.cpp375
-rw-r--r--vmime-master/tests/parser/htmlTextPartTest.cpp241
-rw-r--r--vmime-master/tests/parser/mailboxGroupTest.cpp107
-rw-r--r--vmime-master/tests/parser/mailboxListTest.cpp47
-rw-r--r--vmime-master/tests/parser/mailboxTest.cpp187
-rw-r--r--vmime-master/tests/parser/mediaTypeTest.cpp100
-rw-r--r--vmime-master/tests/parser/messageIdSequenceTest.cpp78
-rw-r--r--vmime-master/tests/parser/messageIdTest.cpp77
-rw-r--r--vmime-master/tests/parser/messageTest.cpp64
-rw-r--r--vmime-master/tests/parser/parameterTest.cpp722
-rw-r--r--vmime-master/tests/parser/pathTest.cpp102
-rw-r--r--vmime-master/tests/parser/streamContentHandlerTest.cpp194
-rw-r--r--vmime-master/tests/parser/stringContentHandlerTest.cpp165
-rw-r--r--vmime-master/tests/parser/textTest.cpp918
-rw-r--r--vmime-master/tests/parser/wordEncoderTest.cpp174
-rw-r--r--vmime-master/tests/security/digest/md5Test.cpp228
-rw-r--r--vmime-master/tests/security/digest/sha1Test.cpp119
-rw-r--r--vmime-master/tests/testRunner.cpp305
-rw-r--r--vmime-master/tests/testUtils.cpp404
-rw-r--r--vmime-master/tests/testUtils.hpp407
-rw-r--r--vmime-master/tests/utility/datetimeUtilsTest.cpp157
-rw-r--r--vmime-master/tests/utility/encoder/b64EncoderTest.cpp168
-rw-r--r--vmime-master/tests/utility/encoder/encoderFactoryTest.cpp63
-rw-r--r--vmime-master/tests/utility/encoder/encoderTestUtils.hpp82
-rw-r--r--vmime-master/tests/utility/encoder/qpEncoderTest.cpp275
-rw-r--r--vmime-master/tests/utility/filteredStreamTest.cpp341
-rw-r--r--vmime-master/tests/utility/outputStreamByteArrayAdapterTest.cpp82
-rw-r--r--vmime-master/tests/utility/outputStreamSocketAdapterTest.cpp87
-rw-r--r--vmime-master/tests/utility/outputStreamStringAdapterTest.cpp84
-rw-r--r--vmime-master/tests/utility/parserInputStreamAdapterTest.cpp51
-rw-r--r--vmime-master/tests/utility/pathTest.cpp356
-rw-r--r--vmime-master/tests/utility/seekableInputStreamRegionAdapterTest.cpp176
-rw-r--r--vmime-master/tests/utility/stringUtilsTest.cpp214
-rw-r--r--vmime-master/tests/utility/urlTest.cpp312
-rw-r--r--vmime-master/vmime.pc.in13
562 files changed, 116586 insertions, 0 deletions
diff --git a/vmime-master/.gitignore b/vmime-master/.gitignore
new file mode 100644
index 0000000..2262aac
--- /dev/null
+++ b/vmime-master/.gitignore
@@ -0,0 +1,41 @@
+*.o
+*.sw?
+*.a
+*.dSYM
+*.vim
+
+# Doxygen-generated
+doc/html/*
+
+# CMake-generated / Build files
+CMakeFiles/
+CMakeCache.txt
+/_CPack_Packages/
+cmake_install.cmake
+/CPackConfig.cmake
+/CPackSourceConfig.cmake
+/Doxyfile
+/Makefile
+/install_manifest*
+/libvmime.a
+/vmime.pc
+/src/vmime/config.hpp
+/src/vmime/export-static.hpp
+/src/vmime/export-shared.hpp
+/COPYING.txt
+build/
+Makefile
+export-shared.hpp
+export-static.hpp
+
+# Outsourced build test
+/_build/
+/_install/
+
+# CTest-generated files
+/CTestTestfile.cmake
+/Testing/
+
+# Mac
+._DS_Store
+
diff --git a/vmime-master/.travis.yml b/vmime-master/.travis.yml
new file mode 100644
index 0000000..eb3ada8
--- /dev/null
+++ b/vmime-master/.travis.yml
@@ -0,0 +1,37 @@
+# Travis-CI build file for VMime
+# See http://travis-ci.org for details
+
+language: cpp
+
+compiler:
+ - gcc
+ - clang
+
+# Settings
+env:
+ # -- default configuration (iconv + GnuTLS)
+ - CTEST_OUTPUT_ON_FAILURE=1 OPTIONS="-DVMIME_SENDMAIL_PATH=/path/to/sendmail -DCMAKE_BUILD_TYPE=Debug -DVMIME_BUILD_TESTS=ON -DVMIME_BUILD_SAMPLES=ON"
+ # -- ICU
+ - CTEST_OUTPUT_ON_FAILURE=1 OPTIONS="-DVMIME_SENDMAIL_PATH=/path/to/sendmail -DCMAKE_BUILD_TYPE=Debug -DVMIME_BUILD_TESTS=ON -DVMIME_BUILD_SAMPLES=ON -DVMIME_CHARSETCONV_LIB_IS_ICONV=OFF -DVMIME_CHARSETCONV_LIB_IS_ICU=ON"
+ # -- OpenSSL
+ - CTEST_OUTPUT_ON_FAILURE=1 OPTIONS="-DVMIME_SENDMAIL_PATH=/path/to/sendmail -DCMAKE_BUILD_TYPE=Debug -DVMIME_BUILD_TESTS=ON -DVMIME_BUILD_SAMPLES=ON -DVMIME_TLS_SUPPORT_LIB_IS_GNUTLS=OFF -DVMIME_TLS_SUPPORT_LIB_IS_OPENSSL=ON"
+
+# Make sure some required tools/libraries are installed
+install:
+ - sudo apt-get update >/dev/null
+ - sudo apt-get -q install cmake libcppunit-dev valgrind
+ - sudo apt-get -q install libgsasl7-dev libgnutls-dev libssl-dev libicu-dev libboost-dev
+ # -- for the samples
+ - sudo apt-get -q install libgtk-3-dev
+
+# Run the build script
+script:
+ - mkdir _build
+ - cd _build
+ - cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS
+ - cmake .. -L
+ - cat ./src/vmime/config.hpp
+ - cat ./src/vmime/export-shared.hpp
+ - cat ./src/vmime/export-static.hpp
+ - cmake --build . --target install
+ - ctest
diff --git a/vmime-master/AUTHORS b/vmime-master/AUTHORS
new file mode 100644
index 0000000..1ddeb3d
--- /dev/null
+++ b/vmime-master/AUTHORS
@@ -0,0 +1,38 @@
+
+VMIME AUTHOR
+============
+
+Vincent Richard <vincent@vmime.org>
+Project owner and creator. VMime was created in 1998, and publicly released
+under the GNU GPL license in 2003.
+
+
+VMIME CONTRIBUTORS
+==================
+
+VMime is Open Source software, you are free and welcome to contribute!
+
+If you have a patch and you want it to be included into official VMime
+release, you have to release your patch into the public domain or assign
+the copyright to "VMime authors". You will then be credited in this
+AUTHORS file.
+
+ - Stefan Uhrig <stefanuhrig@gmx.net>
+ - Rafael Fernandez <prf@adinet.com.uy>
+ - Xin Li <lixin3@staff.sina.com.cn>
+ - Benjamin Biron <benbiron@gmail.com>
+ - Bertrand Benoit <projettwk@users.sourceforge.net>
+ - Tim Teulings <rael@edge.ping.de>
+ - Georg Sauthoff <gsauthof@techfak.uni-bielefeld.de>
+ - Pierre Thierry <nowhere.man@levallois.eu.org> (patches for STL algorithms)
+ - Zarafa <http://developer.zarafa.com/VmimePatches>
+ - Bartek Szurgot <vempirelord@wp.pl, http://baszerr.org>
+ - Achim Brandt <http://sourceforge.net/users/a-brandt/>
+ - Mehmet Bozkurt <mehmet.bozkurt78@gmail.com> (OpenSSL support, ICU support)
+ - Anthony Dervish <antmd@mac.com>
+
+Please apologize if I have forgotten someone here. ;) Send me an email
+to <vincent@vmime.org> if you want your name to be listed.
+
+See Changelogs for full list.
+
diff --git a/vmime-master/CMakeLists.txt b/vmime-master/CMakeLists.txt
new file mode 100644
index 0000000..6206e6f
--- /dev/null
+++ b/vmime-master/CMakeLists.txt
@@ -0,0 +1,1038 @@
+#
+# CMake configuration file for VMime
+#
+# Usage:
+#
+# . 'cmake -LH' to list build settings variable
+#
+# . 'cmake -G <generator>' to generate makefiles for a build system
+# eg. cmake -G "Unix Makefiles"
+#
+# For more information, please visit:
+# http://www.cmake.org
+#
+
+CMAKE_MINIMUM_REQUIRED(VERSION 3.1 FATAL_ERROR)
+
+INCLUDE(cmake/Utils.cmake)
+
+INCLUDE(CheckIncludeFiles)
+INCLUDE(CheckIncludeFileCXX)
+INCLUDE(CheckFunctionExists)
+INCLUDE(CheckSymbolExists)
+INCLUDE(CheckTypeSize)
+INCLUDE(CheckLibraryExists)
+INCLUDE(CheckCXXSourceCompiles)
+INCLUDE(GNUInstallDirs)
+
+
+# CMake configuration
+SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY build/bin)
+SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY build/lib)
+SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY build/lib)
+
+SET(CMAKE_VERBOSE_MAKEFILE ON)
+
+
+# Package version number
+SET(VMIME_VERSION_MAJOR 0)
+SET(VMIME_VERSION_MINOR 9)
+SET(VMIME_VERSION_MICRO 2)
+
+# API version number (libtool)
+#
+# Increment this number only immediately before a public release.
+# This is independent from package version number.
+#
+# See: http://semver.org/
+#
+# . Implementation changed (eg. bug/security fix): REVISION++
+# . Interfaces added/removed/changed: CURRENT++, REVISION=0
+# . Interfaces added (upward-compatible changes): AGE++
+# . Interfaces removed: AGE=0
+SET(VMIME_API_VERSION_CURRENT 1)
+SET(VMIME_API_VERSION_REVISION 0)
+SET(VMIME_API_VERSION_AGE 0)
+
+
+SET(VMIME_VERSION ${VMIME_VERSION_MAJOR}.${VMIME_VERSION_MINOR}.${VMIME_VERSION_MICRO})
+SET(VMIME_API_VERSION ${VMIME_API_VERSION_CURRENT}.${VMIME_API_VERSION_REVISION}.${VMIME_API_VERSION_AGE})
+
+
+##############################################################################
+# VMime Library
+
+# Project
+PROJECT(
+ vmime
+ LANGUAGES CXX C
+ VERSION ${VMIME_VERSION}
+)
+
+# 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)
+
+# Source files
+FILE(
+ GLOB_RECURSE
+ VMIME_LIBRARY_SRC_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/vmime/*.cpp
+)
+
+FILE(
+ GLOB_RECURSE
+ VMIME_LIBRARY_INCLUDE_FILES
+ ${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_BINARY_DIR}/src/vmime # for "config.hpp"
+)
+
+INCLUDE(GenerateExportHeader)
+ADD_COMPILER_EXPORT_FLAGS()
+
+# Shared library
+OPTION(
+ VMIME_BUILD_SHARED_LIBRARY
+ "Build shared library"
+ ON
+)
+
+IF(VMIME_BUILD_SHARED_LIBRARY)
+
+ ADD_LIBRARY(
+ ${VMIME_LIBRARY_NAME}
+ SHARED
+ ${VMIME_LIBRARY_SRC_FILES}
+ ${VMIME_LIBRARY_INCLUDE_FILES}
+ )
+
+ TARGET_INCLUDE_DIRECTORIES(${VMIME_LIBRARY_NAME} PUBLIC
+ $<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
+ )
+
+ LIST(APPEND VMIME_LIBRARY_GENERATED_INCLUDE_FILES "${CMAKE_BINARY_DIR}/src/vmime/export-shared.hpp")
+
+ SET_TARGET_PROPERTIES(
+ ${VMIME_LIBRARY_NAME}
+ PROPERTIES
+ VERSION "${VMIME_API_VERSION}"
+ SOVERSION "${VMIME_API_VERSION_CURRENT}"
+ COMPILE_FLAGS -DVMIME_SHARED
+ )
+
+ENDIF()
+
+# Static library
+#
+# Note: cannot have two targets with the same name so the static version has
+# '-static' appended and then the name of the output file is set separately.
+OPTION(
+ VMIME_BUILD_STATIC_LIBRARY
+ "Build static library"
+ ON
+)
+
+IF(VMIME_BUILD_STATIC_LIBRARY)
+
+ ADD_LIBRARY(
+ ${VMIME_LIBRARY_NAME}-static
+ STATIC
+ ${VMIME_LIBRARY_SRC_FILES}
+ ${VMIME_LIBRARY_INCLUDE_FILES}
+ )
+
+ TARGET_INCLUDE_DIRECTORIES(${VMIME_LIBRARY_NAME}-static PUBLIC
+ $<INSTALL_INTERFACE:include>
+ )
+
+ GENERATE_EXPORT_HEADER(
+ ${VMIME_LIBRARY_NAME}-static
+ BASE_NAME VMIME
+ 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
+ )
+
+ LIST(APPEND VMIME_LIBRARY_GENERATED_INCLUDE_FILES "${CMAKE_BINARY_DIR}/src/vmime/export-static.hpp")
+
+ SET_TARGET_PROPERTIES(
+ ${VMIME_LIBRARY_NAME}-static
+ PROPERTIES
+ OUTPUT_NAME ${VMIME_LIBRARY_NAME}
+ COMPILE_FLAGS -DVMIME_STATIC
+ )
+
+ENDIF()
+
+# Ensure at least one type of library (either shared or static) is build
+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")
+
+# Installation of libraries
+IF(VMIME_BUILD_SHARED_LIBRARY)
+ INSTALL(
+ TARGETS ${VMIME_LIBRARY_NAME}
+ EXPORT ${VMIME_LIBRARY_NAME}-config
+ LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" COMPONENT sharedlibs
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" COMPONENT sharedlibs
+ )
+ENDIF()
+
+IF(VMIME_BUILD_STATIC_LIBRARY)
+ INSTALL(
+ TARGETS ${VMIME_LIBRARY_NAME}-static
+ EXPORT ${VMIME_LIBRARY_NAME}-config
+ LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" COMPONENT staticlibs
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" COMPONENT staticlibs
+ )
+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 ${VMIME_LIBRARY_INCLUDE_FILES}
+# DESTINATION include
+# COMPONENT headers
+#)
+
+install(EXPORT ${VMIME_LIBRARY_NAME}-config DESTINATION cmake)
+
+
+##############################################################################
+# Tests
+
+OPTION(
+ VMIME_BUILD_TESTS
+ "Build unit tests (this will create a 'run-tests' binary)"
+ OFF
+)
+
+IF(VMIME_BUILD_TESTS)
+
+ ENABLE_TESTING()
+
+ INCLUDE(cmake/FindCppUnit.cmake)
+ INCLUDE_DIRECTORIES(${CPPUNIT_INCLUDE_DIR})
+
+ FILE(
+ GLOB_RECURSE
+ VMIME_TESTS_SRC_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/tests/*Test.cpp
+ )
+
+ ADD_LIBRARY(
+ test-runner
+ ${CMAKE_CURRENT_SOURCE_DIR}/tests/testRunner.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/testUtils.cpp
+ )
+
+ # Build one file for each test
+ FOREACH(VMIME_TEST_SRC_FILE ${VMIME_TESTS_SRC_FILES})
+
+ # "/path/to/vmime/tests/module/testFile.cpp" --> "module_testFile"
+ GET_FILENAME_COMPONENT(VMIME_TEST_SRC_PATH "${VMIME_TEST_SRC_FILE}" 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}")
+ STRING(REPLACE "_tests_" "" VMIME_TEST_NAME "${VMIME_TEST_NAME}")
+
+ ADD_EXECUTABLE(
+ ${VMIME_TEST_NAME}
+ ${VMIME_TEST_SRC_FILE}
+ )
+
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_TEST_NAME}
+ ${VMIME_LIBRARY_NAME}
+ ${CPPUNIT_LIBRARY} test-runner
+ )
+
+ ADD_DEPENDENCIES(
+ ${VMIME_TEST_NAME}
+ ${VMIME_LIBRARY_NAME}
+ )
+
+ ADD_TEST(
+ ${VMIME_TEST_NAME}
+ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${VMIME_TEST_NAME}
+ )
+
+ ENDFOREACH()
+
+ # Build one file for all tests
+ ADD_EXECUTABLE(
+ "run-tests"
+ ${VMIME_TESTS_SRC_FILES}
+ )
+
+ TARGET_LINK_LIBRARIES(
+ "run-tests"
+ ${VMIME_LIBRARY_NAME}
+ ${CPPUNIT_LIBRARY} test-runner
+ )
+
+ ADD_DEPENDENCIES(
+ "run-tests"
+ ${VMIME_LIBRARY_NAME}
+ )
+
+ENDIF()
+
+
+##############################################################################
+# Examples
+
+OPTION(
+ VMIME_BUILD_SAMPLES
+ "Build samples (in 'examples' directory)"
+ OFF
+)
+
+
+##############################################################################
+# 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
+IF(APPLE)
+ # CPack/PackageManager won't allow file without recognized extension
+ # to be used as license file.
+ 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_CURRENT_SOURCE_DIR}/COPYING")
+ SET(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README")
+ENDIF(APPLE)
+
+SET(CPACK_SOURCE_GENERATOR TGZ)
+SET(CPACK_SOURCE_IGNORE_FILES "\\\\.git;~$;build/")
+SET(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION})
+
+# Set components
+SET(CPACK_COMPONENTS_ALL sharedlibs staticlibs headers)
+
+SET(CPACK_COMPONENT_SHAREDLIBS_DISPLAY_NAME "Shared libraries")
+SET(CPACK_COMPONENT_SHAREDLIBS_DESCRIPTION
+ "Shared library for general use.")
+
+SET(CPACK_COMPONENT_STATICLIBS_DISPLAY_NAME "Static libraries")
+SET(CPACK_COMPONENT_STATICLIBS_DESCRIPTION
+ "Static library, good if you want to embed VMime in your application.")
+
+SET(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ Headers")
+SET(CPACK_COMPONENT_HEADERS_DESCRIPTION
+ "C/C++ header files.")
+
+SET(CPACK_COMPONENT_SHAREDLIBS_GROUP "Development")
+SET(CPACK_COMPONENT_STATICLIBS_GROUP "Development")
+SET(CPACK_COMPONENT_HEADERS_GROUP "Development")
+SET(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION "")
+
+# Make a target "dist" to generate tarball
+SET(ARCHIVE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION})
+
+ADD_CUSTOM_TARGET(
+ dist
+ COMMAND git archive --prefix=${ARCHIVE_NAME}/ HEAD
+ | bzip2 > ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+# PkgConfig
+SET(prefix ${CMAKE_INSTALL_PREFIX})
+SET(exec_prefix ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR})
+SET(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vmime)
+SET(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
+
+SET(VMIME_PKGCONFIG_LIBS "")
+SET(VMIME_PKGCONFIG_CFLAGS "")
+SET(VMIME_PKGCONFIG_REQUIRES "")
+
+
+##############################################################################
+# Build type
+
+IF(NOT CMAKE_BUILD_TYPE)
+ SET(
+ CMAKE_BUILD_TYPE
+ "Debug"
+ CACHE STRING
+ "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
+ FORCE
+ )
+ENDIF(NOT CMAKE_BUILD_TYPE)
+
+# Set a default build type for single-configuration
+# CMake generators if no build type is set.
+IF(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
+ SET(CMAKE_BUILD_TYPE Debug)
+ENDIF()
+
+# Debug build
+MESSAGE("-- Build type: ${CMAKE_BUILD_TYPE}")
+IF(${CMAKE_BUILD_TYPE} STREQUAL Debug)
+ ADD_DEFINITIONS(-DDEBUG)
+ENDIF(${CMAKE_BUILD_TYPE} STREQUAL Debug)
+
+
+IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
+ SET(VMIME_DEBUG 1)
+ELSE()
+ SET(VMIME_DEBUG 0)
+ENDIF()
+
+
+##############################################################################
+# Test endianness and basic type sizes
+
+INCLUDE(TestBigEndian)
+TEST_BIG_ENDIAN(BIGENDIAN)
+
+IF(BIGENDIAN EQUAL 0)
+ set(VMIME_BYTE_ORDER_BIG_ENDIAN 0)
+ set(VMIME_BYTE_ORDER_LITTLE_ENDIAN 1)
+ELSE(BIGENDIAN EQUAL 0)
+ SET(VMIME_BYTE_ORDER_BIG_ENDIAN 1)
+ SET(VMIME_BYTE_ORDER_LITTLE_ENDIAN 0)
+ENDIF(BIGENDIAN EQUAL 0)
+
+
+CHECK_INCLUDE_FILE_CXX(cstdint VMIME_HAVE_CSTDINT)
+
+CHECK_TYPE_SIZE("char" SIZEOF_CHAR)
+CHECK_TYPE_SIZE("short" SIZEOF_SHORT)
+CHECK_TYPE_SIZE("int" SIZEOF_INT)
+CHECK_TYPE_SIZE("long" SIZEOF_LONG)
+CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
+CHECK_TYPE_SIZE("__int64" SIZEOF___INT64)
+
+SET(CMAKE_EXTRA_INCLUDE_FILES cstdint)
+CHECK_TYPE_SIZE("int64_t" SIZEOF_INT64_T)
+SET(CMAKE_EXTRA_INCLUDE_FILES)
+
+
+IF(SIZEOF_CHAR EQUAL 1)
+ SET(VMIME_8BIT_TYPE "char")
+ELSE()
+ MESSAGE(FATAL_ERROR "Cannot determine 8-bit type")
+ENDIF()
+
+IF(SIZEOF_INT EQUAL 2)
+ SET(VMIME_16BIT_TYPE "int")
+ELSE()
+ IF(SIZEOF_SHORT EQUAL 2)
+ SET(VMIME_16BIT_TYPE "short")
+ ELSE()
+ MESSAGE(FATAL_ERROR "Cannot determine 16-bit type")
+ ENDIF()
+ENDIF()
+
+IF(SIZEOF_INT EQUAL 4)
+ SET(VMIME_32BIT_TYPE "int")
+ELSE()
+ IF(SIZEOF_LONG EQUAL 4)
+ SET(VMIME_32BIT_TYPE "long")
+ ELSE()
+ IF(SIZEOF_LONG_LONG EQUAL 4)
+ SET(VMIME_32BIT_TYPE "long long")
+ ELSE()
+ MESSAGE(FATAL_ERROR "Cannot determine 32-bit type")
+ ENDIF()
+ ENDIF()
+ENDIF()
+
+IF(SIZEOF_INT EQUAL 8)
+ SET(VMIME_64BIT_TYPE "int")
+ELSE()
+ IF(SIZEOF_LONG EQUAL 8)
+ SET(VMIME_64BIT_TYPE "long")
+ ELSE()
+ IF(SIZEOF_LONG_LONG EQUAL 8)
+ SET(VMIME_64BIT_TYPE "long long")
+ ELSE()
+ IF(SIZEOF_INT64_T EQUAL 8)
+ SET(VMIME_64BIT_TYPE "int64_t")
+ ELSE()
+ IF(SIZEOF___INT64 EQUAL 8)
+ SET(VMIME_64BIT_TYPE "__int64")
+ ELSE()
+ MESSAGE(FATAL_ERROR "Cannot determine 64-bit type")
+ ENDIF()
+ ENDIF()
+ ENDIF()
+ ENDIF()
+ENDIF()
+
+
+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
+
+# Module
+OPTION(
+ VMIME_HAVE_MESSAGING_FEATURES
+ "Enable messaging features (connection to IMAP, POP3, SMTP...)"
+ ON
+)
+
+# Protocols
+OPTION(
+ VMIME_HAVE_MESSAGING_PROTO_POP3
+ "Enable POP3 protocol"
+ ON
+)
+
+OPTION(
+ VMIME_HAVE_MESSAGING_PROTO_SMTP
+ "Enable SMTP protocol"
+ ON
+)
+
+OPTION(
+ VMIME_HAVE_MESSAGING_PROTO_IMAP
+ "Enable IMAP protocol"
+ ON
+)
+
+OPTION(
+ VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+ "Enable Maildir protocol"
+ ON
+)
+
+OPTION(
+ VMIME_HAVE_MESSAGING_PROTO_SENDMAIL
+ "Enable Sendmail protocol"
+ ON
+)
+
+
+##############################################################################
+# File-system features
+
+OPTION(
+ VMIME_HAVE_FILESYSTEM_FEATURES
+ "Enable file-system features (required for file attachments and Maildir)"
+ ON
+)
+
+
+##############################################################################
+# SASL support
+
+INCLUDE(cmake/FindGSasl.cmake)
+
+OPTION(
+ VMIME_HAVE_SASL_SUPPORT
+ "Enable SASL support (requires GNU SASL library)"
+ ON
+)
+
+IF(VMIME_HAVE_SASL_SUPPORT)
+
+ INCLUDE_DIRECTORIES(
+ ${INCLUDE_DIRECTORIES}
+ ${GSASL_INCLUDE_DIR}
+ )
+
+ IF(VMIME_BUILD_SHARED_LIBRARY)
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_LIBRARY_NAME}
+ ${TARGET_LINK_LIBRARIES}
+ ${GSASL_LIBRARIES}
+ )
+ ENDIF()
+
+ SET(VMIME_PKGCONFIG_REQUIRES "${VMIME_PKGCONFIG_REQUIRES} libgsasl")
+
+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)
+
+ IF(VMIME_TLS_SUPPORT_LIB STREQUAL "gnutls")
+
+ INCLUDE_DIRECTORIES(
+ ${INCLUDE_DIRECTORIES}
+ ${GNUTLS_INCLUDE_DIR}
+ )
+
+ LINK_DIRECTORIES(
+ ${LINK_DIRECTORIES}
+ ${GNUTLS_LIBRARY_DIRS}
+ )
+
+ IF(VMIME_BUILD_SHARED_LIBRARY)
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_LIBRARY_NAME}
+ ${TARGET_LINK_LIBRARIES}
+ ${GNUTLS_LIBRARY}
+ )
+ ENDIF()
+
+ SET(VMIME_PKGCONFIG_REQUIRES "${VMIME_PKGCONFIG_REQUIRES} gnutls")
+
+ SET(VMIME_TLS_SUPPORT_LIB_IS_GNUTLS "ON")
+ SET(VMIME_TLS_SUPPORT_LIB_IS_OPENSSL "OFF")
+
+ ELSEIF(VMIME_TLS_SUPPORT_LIB STREQUAL "openssl")
+
+ INCLUDE_DIRECTORIES(
+ ${INCLUDE_DIRECTORIES}
+ ${OPENSSL_INCLUDE_DIR}
+ )
+
+ IF(VMIME_BUILD_SHARED_LIBRARY)
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_LIBRARY_NAME}
+ ${TARGET_LINK_LIBRARIES}
+ ${OPENSSL_LIBRARIES}
+ )
+ ENDIF()
+
+ SET(VMIME_PKGCONFIG_REQUIRES "${VMIME_PKGCONFIG_REQUIRES} openssl")
+
+ SET(VMIME_TLS_SUPPORT_LIB_IS_GNUTLS "OFF")
+ SET(VMIME_TLS_SUPPORT_LIB_IS_OPENSSL "ON")
+
+ ELSE()
+
+ MESSAGE(FATAL_ERROR "TLS support is enabled, but no TLS/SSL library was selected/found")
+
+ ENDIF()
+
+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()
+
+SET(
+ VMIME_CHARSETCONV_LIB
+ "${VMIME_CHARSETCONV_LIB_DETECTED}"
+ CACHE
+ STRING
+ "Library to use for charset conversion"
+)
+SET_PROPERTY(
+ CACHE
+ VMIME_CHARSETCONV_LIB
+ PROPERTY STRINGS win iconv icu
+)
+
+
+IF(VMIME_CHARSETCONV_LIB STREQUAL "iconv")
+
+ INCLUDE_DIRECTORIES(
+ ${INCLUDE_DIRECTORIES}
+ ${ICONV_INCLUDE_DIR}
+ )
+
+ IF(VMIME_BUILD_SHARED_LIBRARY)
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_LIBRARY_NAME}
+ ${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}")
+
+ SET(VMIME_CHARSETCONV_LIB_IS_ICONV "ON")
+ SET(VMIME_CHARSETCONV_LIB_IS_ICU "OFF")
+ SET(VMIME_CHARSETCONV_LIB_IS_WIN "OFF")
+
+ELSEIF(VMIME_CHARSETCONV_LIB STREQUAL "icu")
+
+ INCLUDE_DIRECTORIES(
+ ${INCLUDE_DIRECTORIES}
+ ${ICU_INCLUDE_DIRS}
+ )
+
+ IF(VMIME_BUILD_SHARED_LIBRARY)
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_LIBRARY_NAME}
+ ${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}")
+
+ SET(VMIME_CHARSETCONV_LIB_IS_ICONV "OFF")
+ SET(VMIME_CHARSETCONV_LIB_IS_ICU "ON")
+ SET(VMIME_CHARSETCONV_LIB_IS_WIN "OFF")
+
+ELSEIF(VMIME_CHARSETCONV_LIB STREQUAL "win")
+
+ MESSAGE(WARNING "*** ICU or iconv library should always be preferred"
+ " over MultiByteToWideChar/WideCharToMultiByte on Windows, as"
+ " error handling is very poor, and there is no streaming support.")
+
+ SET(VMIME_CHARSETCONV_LIB_IS_ICONV "OFF")
+ SET(VMIME_CHARSETCONV_LIB_IS_ICU "OFF")
+ SET(VMIME_CHARSETCONV_LIB_IS_WIN "ON")
+
+ELSE()
+
+ MESSAGE(FATAL_ERROR "No charset conversion library was selected/found")
+
+ENDIF()
+
+
+##############################################################################
+# Platform
+
+SET(VMIME_PLATFORM_IS_POSIX OFF)
+SET(VMIME_PLATFORM_IS_WINDOWS OFF)
+
+IF(WIN32)
+ SET(VMIME_PLATFORM_IS_WINDOWS ON)
+ELSE()
+ SET(VMIME_PLATFORM_IS_POSIX ON)
+ENDIF()
+
+
+##############################################################################
+# Platform-specific checks
+
+CHECK_FUNCTION_EXISTS(gmtime_s VMIME_HAVE_GMTIME_S)
+CHECK_FUNCTION_EXISTS(gmtime_r VMIME_HAVE_GMTIME_R)
+CHECK_FUNCTION_EXISTS(localtime_s VMIME_HAVE_LOCALTIME_S)
+CHECK_FUNCTION_EXISTS(localtime_r VMIME_HAVE_LOCALTIME_R)
+CHECK_FUNCTION_EXISTS(strcpy_s VMIME_HAVE_STRCPY_S)
+
+
+##############################################################################
+# Windows-specific checks
+
+IF(WIN32)
+
+ # Winsock
+ CHECK_LIBRARY_EXISTS("ws2_32" getch "${CMAKE_LIBRARY_PATH}" VMIME_HAVE_LIBWS2_32)
+
+ IF(VMIME_HAVE_LIBWS2_32)
+ IF(VMIME_BUILD_SHARED_LIBRARY)
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_LIBRARY_NAME}
+ ${TARGET_LINK_LIBRARIES}
+ "ws2_32"
+ )
+ ELSE()
+ SET(VMIME_PKGCONFIG_LIBS "${VMIME_PKGCONFIG_LIBS} -lws2_32")
+ ENDIF()
+ ENDIF()
+
+ # MLang
+ 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_BUILD_SHARED_LIBRARY)
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_LIBRARY_NAME}
+ ${TARGET_LINK_LIBRARIES}
+ "mlang"
+ )
+ ENDIF()
+ ENDIF()
+ ENDIF()
+
+ENDIF()
+
+
+##############################################################################
+# POSIX-specific checks
+
+CHECK_FUNCTION_EXISTS(getaddrinfo VMIME_HAVE_GETADDRINFO)
+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(SO_KEEPALIVE sys/socket.h VMIME_HAVE_SO_KEEPALIVE)
+CHECK_SYMBOL_EXISTS(SO_NOSIGPIPE sys/socket.h VMIME_HAVE_SO_NOSIGPIPE)
+
+CHECK_SYMBOL_EXISTS(MSG_NOSIGNAL sys/socket.h VMIME_HAVE_MSG_NOSIGNAL)
+
+CHECK_SYMBOL_EXISTS(strerror_r string.h VMIME_HAVE_STRERROR_R)
+
+FIND_PACKAGE(Threads)
+
+IF(VMIME_BUILD_SHARED_LIBRARY)
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_LIBRARY_NAME}
+ ${TARGET_LINK_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
+ )
+ENDIF()
+
+FIND_LIBRARY(PTHREAD_LIB pthread)
+
+IF(PTHREAD_LIB)
+ SET(VMIME_HAVE_PTHREAD 1)
+
+ IF(VMIME_BUILD_SHARED_LIBRARY)
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_LIBRARY_NAME}
+ ${TARGET_LINK_LIBRARIES}
+ ${PTHREAD_LIB}
+ )
+ ENDIF()
+ELSE(PTHREAD_LIB)
+ SET(VMIME_HAVE_PTHREAD 0)
+ENDIF(PTHREAD_LIB)
+
+# getaddrinfo_a() - GNU libc
+LIST(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
+LIST(APPEND CMAKE_REQUIRED_LIBRARIES anl)
+CHECK_SYMBOL_EXISTS(getaddrinfo_a netdb.h VMIME_HAVE_GETADDRINFO_A)
+
+IF(VMIME_HAVE_GETADDRINFO_A)
+ IF(VMIME_BUILD_SHARED_LIBRARY)
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_LIBRARY_NAME}
+ ${TARGET_LINK_LIBRARIES}
+ anl
+ )
+ ENDIF()
+ENDIF()
+
+
+##############################################################################
+# Additional compiler flags
+
+IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+
+ SET(
+ CMAKE_CXX_FLAGS
+ "-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 ${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")
+
+ELSE()
+
+ IF(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
+
+ SET(
+ CMAKE_CXX_FLAGS
+ "-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 ${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")
+
+ ENDIF()
+
+ENDIF()
+
+
+##############################################################################
+# Documentation
+
+OPTION(
+ VMIME_BUILD_DOCUMENTATION
+ "Build documentation"
+ ON
+)
+
+IF(VMIME_BUILD_DOCUMENTATION)
+ FIND_PACKAGE(Doxygen)
+
+ IF(DOXYGEN_FOUND)
+ 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(
+ doc
+ ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+ COMMENT "Generating API documentation with Doxygen" VERBATIM
+ )
+ ENDIF(DOXYGEN_FOUND)
+ENDIF(VMIME_BUILD_DOCUMENTATION)
+
+##############################################################################
+# Sanity checks
+
+# Maildir protocol is available only if file-system features are enabled
+IF(VMIME_HAVE_MESSAGING_FEATURES AND VMIME_HAVE_MESSAGING_PROTO_MAILDIR AND NOT VMIME_HAVE_FILESYSTEM_FEATURES)
+ MESSAGE(FATAL_ERROR "Maildir protocol requires file-system support (VMIME_HAVE_FILESYSTEM_FEATURES must be set to ON).")
+ENDIF()
+
+# Sendmail protocol is available only if file-system features are enabled
+IF(VMIME_HAVE_MESSAGING_FEATURES AND VMIME_HAVE_MESSAGING_PROTO_SENDMAIL AND NOT VMIME_HAVE_FILESYSTEM_FEATURES)
+ MESSAGE(FATAL_ERROR "Sendmail protocol requires file-system support (VMIME_HAVE_FILESYSTEM_FEATURES must be set to ON).")
+ENDIF()
+
+# Path to 'sendmail' must be specified if Sendmail protocol is enabled
+IF(VMIME_HAVE_MESSAGING_PROTO_SENDMAIL)
+ 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)
+
+# PkgConfig post-configuration
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/vmime.pc.in ${CMAKE_BINARY_DIR}/vmime.pc @ONLY)
+INSTALL(FILES ${CMAKE_BINARY_DIR}/vmime.pc DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig" COMPONENT headers)
+
+INCLUDE(CPack)
+
+IF(WIN32)
+ target_link_libraries(vmime crypt32)
+ENDIF()
diff --git a/vmime-master/COPYING b/vmime-master/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/vmime-master/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/vmime-master/COPYING.OpenSSL b/vmime-master/COPYING.OpenSSL
new file mode 100644
index 0000000..bf205f5
--- /dev/null
+++ b/vmime-master/COPYING.OpenSSL
@@ -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.
+
diff --git a/vmime-master/Doxyfile.in b/vmime-master/Doxyfile.in
new file mode 100644
index 0000000..3b491c3
--- /dev/null
+++ b/vmime-master/Doxyfile.in
@@ -0,0 +1,1043 @@
+#
+# Doxygen settings for VMime
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+#
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = VMime
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/doc/
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en
+# (Japanese with english messages), Korean, Norwegian, Polish, Portuguese,
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these class will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+#HIDE_IN_BODY_DOCS = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = NO
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH =
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower case letters. If set to YES upper case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are adviced to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explict @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+INHERIT_DOCS = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = NO
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consist of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+#WARN_IF_DOC_ERROR = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = @CMAKE_CURRENT_SOURCE_DIR@/src/ @CMAKE_CURRENT_SOURCE_DIR@/vmime/
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS = */config.hpp */IMAPTag* */IMAPParser* */IMAPUtils* */IMAPConnection* */md5* */smartPtr* */authHelper* */maildirUtils*
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER = NO
+# YES --> sources visibles
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 1
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output dir.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non empty doxygen will try to run
+# the html help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the Html help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+,
+# or Internet explorer 4.0+). Note that for large projects the tree generation
+# can take a very long time. In such cases it is better to disable this feature.
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 300
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimised for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assigments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_XML = NO
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+#GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+#PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+#PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+#PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED = VMIME_BUILDING_DOC VMIME_HAVE_SASL_SUPPORT VMIME_HAVE_TLS_SUPPORT VMIME_HAVE_FILESYSTEM_FEATURES VMIME_HAVE_MESSAGING_FEATURES VMIME_HAVE_MESSAGING_PROTO_POP3 VMIME_HAVE_MESSAGING_PROTO_SMTP VMIME_HAVE_MESSAGING_PROTO_IMAP VMIME_HAVE_MESSAGING_PROTO_MAILDIR VMIME_HAVE_MESSAGING_PROTO_SENDMAIL
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse the
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yield more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermedate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
+
+# The CGI_NAME tag should be the name of the CGI script that
+# starts the search engine (doxysearch) with the correct parameters.
+# A script with this name will be generated by doxygen.
+
+#CGI_NAME = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the
+# cgi binaries are located. See the documentation of your http daemon for
+# details.
+
+#CGI_URL =
+
+# The DOC_URL tag should be the absolute URL to the directory where the
+# documentation is located. If left blank the absolute path to the
+# documentation, with file:// prepended to it, will be used.
+
+#DOC_URL =
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the
+# documentation is located. If left blank the directory on the local machine
+# will be used.
+
+#DOC_ABSPATH =
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
+# is installed.
+
+#BIN_ABSPATH = /usr/local/bin/
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
+# documentation generated for other projects. This allows doxysearch to search
+# the documentation for these projects as well.
+
+#EXT_DOC_PATHS =
+
diff --git a/vmime-master/HACKING b/vmime-master/HACKING
new file mode 100644
index 0000000..a1cf21c
--- /dev/null
+++ b/vmime-master/HACKING
@@ -0,0 +1,360 @@
+This file contains coding guidelines for VMime. You should follow them
+if you want to contribute to VMime. The rules below are not guidelines
+or recommendations, but strict rules.
+
+
+1. General rules
+ 1.1. Language
+ 1.2. Unit tests
+ 1.3. Version Control
+ 1.4. Warnings
+2. Style, indentation and braces
+ 2.1. Indentation
+ 2.2. Brace position
+ 2.3. "switch" statement
+ 2.4. Single instruction
+ 2.5. Line length
+ 2.6. Spaces and parentheses
+ 2.7. End-of-line character
+ 2.8. Short functions
+ 2.9. Limit Variable Scope
+3. Naming conventions
+ 3.1. Classes
+ 3.2. Variables/parameters/member variables
+ 3.3. Member variables
+ 3.4. Files
+ 3.5. Namespaces
+ 3.6. Constants
+4. Comments
+5. Miscellaneous
+
+
+
+1. General rules
+================
+
+1.1. Language
+-------------
+
+The project language is English. All comments, variable names, class names,
+commit messages and so on, must be in English.
+
+
+1.2. Unit tests
+---------------
+
+Unit tests are very important. For each new class you write, you should also
+write a unit test for it. If you write a new method, add a new test case in
+the unit test of the class.
+
+When you fix a bug, also add a new test case to ensure the bug will not
+happen anymore.
+
+
+1.3. Version Control
+--------------------
+
+Each commit MUST be done with a message ('-m' flag) that briefly describes what
+changes have been done.
+
+DO NOT use commit messages like -m "Updated"!
+
+
+1.4. Warnings
+-------------
+
+The code should compile WITHOUT ANY WARNING, even those for unused parameters!
+
+
+
+2. Style, indentation and braces
+================================
+
+2.1. Indentation
+----------------
+
+Use TABS (ASCII character #9) and _not_ SPACES. This allow everyone to set tab
+width to its preferred settings (eg. 4 or 8 spaces).
+
+
+2.2. Brace position
+-------------------
+
+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) {
+
+ do_something();
+ do_another_thing();
+
+ } 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:
+
+ something;
+ break;
+
+ case 1:
+
+ something_else;
+ break;
+
+ case 2: {
+
+ int var = 42;
+ another_thing;
+ break;
+ }
+ }
+
+
+2.4. Single instruction
+-----------------------
+
+Don't omit braces around simple single-statement body:
+
+ if (...) {
+ something;
+ }
+
+and not:
+
+ if (...)
+ something;
+
+
+2.5. Line length
+----------------
+
+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
+for ease of cut and paste.
+
+
+2.6. Spaces and parentheses
+---------------------------
+
+Put spaces around operators: =, >, <, !=, +, -, /, *, ^, %, ||, &&, &, |:
+
+ x = (a * (b + (c - d)))
+
+Do not put spaces around parentheses.
+
+ if ((a == b) || (c == d))
+
+Do not put spaces around "->":
+
+ object->method()
+
+Do not put spaces inside brackets:
+
+ x = array[index] and _NOT_: x = array[ index ]
+
+Do not use space between a function name and parenthesis. No extra spaces
+between parameters and arguments, just after commas:
+
+ method(arg1, arg2, ...)
+
+Do use a single space before flow control statements:
+
+ while (x == y) and _NOT_: while(x==y)
+
+
+2.7. End-of-line character
+--------------------------
+
+Configure your editor to use "\n" (UNIX convention) for end-of-line sequence,
+and not "\r\n" (Windows), nor "\n\r", nor any other combination.
+
+
+2.8. Short functions
+--------------------
+
+To the extent that it is feasible, functions should be kept small and focused.
+It is, however, recognized that long functions are sometimes appropriate, so no
+hard limit is placed on method length. If a function exceeds 40 lines or so,
+think about whether it can be broken up without harming the structure of the
+program.
+
+
+2.9. Limit Variable Scope
+-------------------------
+
+The scope of local variables should be kept to a minimum. By doing so, you
+increase the readability and maintainability of your code and reduce the
+likelihood of error. Each variable should be declared in the innermost block
+that encloses all uses of the variable.
+
+Local variables should be declared at the point they are first used. Nearly
+every local variable declaration should contain an initializer. If you don't
+yet have enough information to initialize a variable sensibly, you should
+postpone the declaration until you do.
+
+
+
+3. Naming conventions
+=====================
+
+3.1. Classes
+------------
+
+Classes names are in lower-case. However, each word should start with an
+upper-case letter.
+
+Examples: "object", "exampleClass", "anotherExampleClass"...
+
+
+3.2. Variables/parameters/member variables
+------------------------------------------
+
+Variable names should be enough explicit so that someone reading the code can
+instantly understand what the variable contains and is used for.
+
+Variables names are in lower-case.
+
+DO NOT use Hungarian notation.
+
+Examples: "address", "recipientMailbox", ...
+
+Avoid variable names with less than 5 characters, except for loop indices and
+iterators.
+
+NOTE: variable names like "it", "jt" and so on are commonly used when iterating
+over STL containers.
+
+
+3.3. Member variables
+---------------------
+
+Use a prefix for class members: "m_" for normal class members, and "sm_" for
+static members, if they are not public.
+
+Examples: "m_mailboxList", "sm_instance"...
+
+
+3.4. Files
+----------
+
+Use ".hpp" for header files, and ".cpp" for implementation files. ".inc" should
+be used for implementation files not directly compiled, but included from
+other implementation files.
+
+Files have to be named exactly like the class they define. For example, class
+"mailboxList" should be declared in "mailboxList.hpp" and implemented in
+"mailboxList.cpp".
+
+Both header and implementation files must be placed in 'src/vmime/' directory.
+
+
+3.5. Namespaces
+---------------
+
+Namespaces are named exactly like variables.
+
+
+3.6. Constants
+--------------
+
+Constants are ALL_CAPS_WITH_UNDERSCORES.
+
+
+
+4. Comments
+===========
+
+The // (two slashes) style of comment tags should be used in most situations.
+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 {
+
+ private:
+
+ int m_member1; // first member
+ int m_secondMember; // second member
+ };
+
+Note about special comment blocks: Doxygen is used to generate documentation
+from annotated C++ sources, so be sure to use available markings to annotate
+the purpose of the functions/classes and the meaning of the parameters.
+
+
+5. Miscellaneous
+================
+
+* No code should be put in header files, only declarations (except for
+ templates and inline functions).
+
+* Try to avoid public member variables. Write accessors instead (get/set).
+
+* Do NOT use 'using namespace' (and especially not in header files). All
+ namespaces should be explicitely named.
+
+* Use the 'get' and 'set' prefix for accessors:
+
+ Variable: m_foo
+ Get method: getFoo()
+ Set method: setFoo()
+
+* No more than one class per file (except for inner classes).
+
+* Put the #include for the class's header file first in the implementation
+ file.
+
+* Put the copyright header at the top of each file.
+
+* Write "unique inclusion #ifdef's" for header files:
+
+ #ifndef N1_N2_FILENAME_HPP_INCLUDED
+ #define N1_N2_FILENAME_HPP_INCLUDED
+
+ // ...
+
+ #endif // N1_N2_FILENAME_HPP_INCLUDED
+
+ where N1 is the top-level namespace, N2 the sub-namespace, and so on.
+ For example, class "vmime::utility::stringUtils" uses the following
+ #ifdef name: VMIME_UTILITY_STRINGUTILS_HPP_INCLUDED.
+
diff --git a/vmime-master/NEWS b/vmime-master/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vmime-master/NEWS
diff --git a/vmime-master/README b/vmime-master/README
new file mode 100644
index 0000000..7db9175
--- /dev/null
+++ b/vmime-master/README
@@ -0,0 +1,30 @@
+
+VMime is a powerful C++ class library for working with RFC-822 and MIME messages
+and Internet messaging services like IMAP, POP or SMTP.
+
+With VMime you can parse, generate and modify messages, and also connect to store
+and transport services to receive or send messages over the Internet. The library
+offers all the features to build a complete mail client.
+
+Key Features
+------------
+
+* it is free software! GNU GPL license (Commercial licenses available!)
+* fully RFC-compliant implementation
+* object-oriented and modular design
+* very easy-to-use (intuitive design)
+* well documented code
+* very high reliability
+* maximum portability
+
+Features Overview
+-----------------
+
+* RFC-2822 and multipart messages
+* aggregate documents and embedded objects
+* 8-bit MIME and encoded word extensions
+* full support for attachments
+* POP3, IMAP, SMTP, maildir and sendmail
+* SSL/TLS security layer and X.509 certificates (using GNU TLS)
+* SASL authentication (using GNU SASL)
+
diff --git a/vmime-master/README.autotools b/vmime-master/README.autotools
new file mode 100644
index 0000000..a67c1c8
--- /dev/null
+++ b/vmime-master/README.autotools
@@ -0,0 +1,13 @@
+Where are the ./configure script and the Makefile's?
+
+Configure and Make scripts are not included in the git source tree. They are
+automatically generated by the CMake script.
+
+Just use the following instruction to generate everything needed for the
+traditional "make" and "make install" build process.
+
+ cmake -G "Unix Makefiles"
+
+Please note that "configure" script is not needed anymore, as platform
+checks are now done by CMake.
+
diff --git a/vmime-master/build_for_losedows.sh b/vmime-master/build_for_losedows.sh
new file mode 100755
index 0000000..55b242f
--- /dev/null
+++ b/vmime-master/build_for_losedows.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+rm -rf build/
+mkdir build/
+
+# perhaps we'll also disable VMIME_HAVE_FILESYSTEM_FEATURES ?
+## perhaps we should change CMAKE_BUILD_TYPE to Release or MinSizeRel.
+cmake \
+ -D GNU_HOST=i686-w64-mingw32 \
+ -D CMAKE_TOOLCHAIN_FILE=./mingw_cross_toolchain.cmake \
+ -D OPENSSL_ROOT_DIR=../openssl-1.1.0h/ \
+ -D VMIME_TLS_SUPPORT_LIB=openssl \
+ -D VMIME_HAVE_SASL_SUPPORT=OFF \
+ -D VMIME_BUILD_DOCUMENTATION=OFF \
+ -D VMIME_HAVE_MESSAGING_PROTO_SENDMAIL=OFF \
+ -D VMIME_HAVE_MESSAGING_PROTO_MAILDIR=OFF \
+ -D CMAKE_BUILD_TYPE=MinSizeRel. \
+ -B build/ ./
+
+cd build/ && make vmime-static
+cd ../
+cp build/build/lib/libvmime.a .
+cp build/src/vmime/config.hpp src/vmime/
diff --git a/vmime-master/cmake/FindCppUnit.cmake b/vmime-master/cmake/FindCppUnit.cmake
new file mode 100644
index 0000000..d74a4f3
--- /dev/null
+++ b/vmime-master/cmake/FindCppUnit.cmake
@@ -0,0 +1,34 @@
+#
+# http://root.cern.ch/viewvc/trunk/cint/reflex/cmake/modules/FindCppUnit.cmake
+#
+# - Find CppUnit
+# This module finds an installed CppUnit package.
+#
+# It sets the following variables:
+# CPPUNIT_FOUND - Set to false, or undefined, if CppUnit isn't found.
+# CPPUNIT_INCLUDE_DIR - The CppUnit include directory.
+# CPPUNIT_LIBRARY - The CppUnit library to link against.
+
+FIND_PATH(CPPUNIT_INCLUDE_DIR cppunit/Test.h)
+FIND_LIBRARY(CPPUNIT_LIBRARY NAMES cppunit)
+
+IF (CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY)
+ SET(CPPUNIT_FOUND TRUE)
+ENDIF (CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY)
+
+IF (CPPUNIT_FOUND)
+
+ # show which CppUnit was found only if not quiet
+ IF (NOT CppUnit_FIND_QUIETLY)
+ MESSAGE(STATUS "Found CppUnit: ${CPPUNIT_LIBRARY}")
+ ENDIF (NOT CppUnit_FIND_QUIETLY)
+
+ELSE (CPPUNIT_FOUND)
+
+ # fatal error if CppUnit is required but not found
+ IF (CppUnit_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR "Could not find CppUnit")
+ ENDIF (CppUnit_FIND_REQUIRED)
+
+ENDIF (CPPUNIT_FOUND)
+
diff --git a/vmime-master/cmake/FindGSasl.cmake b/vmime-master/cmake/FindGSasl.cmake
new file mode 100644
index 0000000..31890a2
--- /dev/null
+++ b/vmime-master/cmake/FindGSasl.cmake
@@ -0,0 +1,51 @@
+# - Try to find the GNU sasl library (gsasl)
+#
+# Once done this will define
+#
+# GNUTLS_FOUND - System has gnutls
+# GNUTLS_INCLUDE_DIR - The gnutls include directory
+# GNUTLS_LIBRARIES - The libraries needed to use gnutls
+# GNUTLS_DEFINITIONS - Compiler switches required for using gnutls
+
+# Adapted from FindGnuTLS.cmake, which is:
+# Copyright 2009, Brad Hards, <bradh@kde.org>
+#
+# Changes are Copyright 2009, Michele Caini, <skypjack@gmail.com>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+IF (GSASL_INCLUDE_DIR AND GSASL_LIBRARIES)
+ # in cache already
+ SET(GSasl_FIND_QUIETLY TRUE)
+ENDIF (GSASL_INCLUDE_DIR AND GSASL_LIBRARIES)
+
+IF (NOT WIN32)
+ # use pkg-config to get the directories and then use these values
+ # in the FIND_PATH() and FIND_LIBRARY() calls
+ find_package(PkgConfig)
+ pkg_check_modules(PC_GSASL libgsasl)
+ SET(GSASL_DEFINITIONS ${PC_GSASL_CFLAGS_OTHER})
+ENDIF (NOT WIN32)
+
+FIND_PATH(GSASL_INCLUDE_DIR gsasl.h
+ HINTS
+ ${PC_GSASL_INCLUDEDIR}
+ ${PC_GSASL_INCLUDE_DIRS}
+ PATH_SUFFIXES gsasl
+ )
+
+FIND_LIBRARY(GSASL_LIBRARIES NAMES gsasl libgsasl
+ HINTS
+ ${PC_GSASL_LIBDIR}
+ ${PC_GSASL_LIBRARY_DIRS}
+ )
+
+INCLUDE(FindPackageHandleStandardArgs)
+
+# handle the QUIETLY and REQUIRED arguments and set GSASL_FOUND to TRUE if
+# all listed variables are TRUE
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GSASL DEFAULT_MSG GSASL_LIBRARIES GSASL_INCLUDE_DIR)
+
+MARK_AS_ADVANCED(GSASL_INCLUDE_DIR GSASL_LIBRARIES)
diff --git a/vmime-master/cmake/FindICU.cmake b/vmime-master/cmake/FindICU.cmake
new file mode 100644
index 0000000..786f157
--- /dev/null
+++ b/vmime-master/cmake/FindICU.cmake
@@ -0,0 +1,314 @@
+# This module can find the International Components for Unicode (ICU) Library
+#
+# Requirements:
+# - CMake >= 2.8.3 (for new version of find_package_handle_standard_args)
+#
+# The following variables will be defined for your use:
+# - ICU_FOUND : were all of your specified components found (include dependencies)?
+# - ICU_INCLUDE_DIRS : ICU include directory
+# - ICU_LIBRARIES : ICU libraries
+# - ICU_VERSION : complete version of ICU (x.y.z)
+# - ICU_MAJOR_VERSION : major version of ICU
+# - ICU_MINOR_VERSION : minor version of ICU
+# - ICU_PATCH_VERSION : patch version of ICU
+# - ICU_<COMPONENT>_FOUND : were <COMPONENT> found? (FALSE for non specified component if it is not a dependency)
+#
+# For windows or non standard installation, define ICU_ROOT variable to point to the root installation of ICU. Two ways:
+# - run cmake with -DICU_ROOT=<PATH>
+# - define an environment variable with the same name before running cmake
+# With cmake-gui, before pressing "Configure":
+# 1) Press "Add Entry" button
+# 2) Add a new entry defined as:
+# - Name: ICU_ROOT
+# - Type: choose PATH in the selection list
+# - Press "..." button and select the root installation of ICU
+#
+# Example Usage:
+#
+# 1. Copy this file in the root of your project source directory
+# 2. Then, tell CMake to search this non-standard module in your project directory by adding to your CMakeLists.txt:
+# set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
+# 3. Finally call find_package() once, here are some examples to pick from
+#
+# Require ICU 4.4 or later
+# find_package(ICU 4.4 REQUIRED)
+#
+# if(ICU_FOUND)
+# include_directories(${ICU_INCLUDE_DIRS})
+# add_executable(myapp myapp.c)
+# target_link_libraries(myapp ${ICU_LIBRARIES})
+# endif(ICU_FOUND)
+
+#=============================================================================
+# Copyright (c) 2011-2012, julp
+# https://github.com/julp/FindICU.cmake
+#
+# Distributed under the OSI-approved BSD License
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#=============================================================================
+
+find_package(PkgConfig QUIET)
+
+########## Private ##########
+set(ICU_PUBLIC_VAR_NS "ICU") # Prefix for all ICU relative public variables
+set(ICU_PRIVATE_VAR_NS "_${ICU_PUBLIC_VAR_NS}") # Prefix for all ICU relative internal variables
+set(PC_ICU_PRIVATE_VAR_NS "_PC${ICU_PRIVATE_VAR_NS}") # Prefix for all pkg-config relative internal variables
+
+function(icudebug _VARNAME)
+ if(${ICU_PUBLIC_VAR_NS}_DEBUG)
+ if(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+ message("${ICU_PUBLIC_VAR_NS}_${_VARNAME} = ${${ICU_PUBLIC_VAR_NS}_${_VARNAME}}")
+ else(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+ message("${ICU_PUBLIC_VAR_NS}_${_VARNAME} = <UNDEFINED>")
+ endif(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+ endif(${ICU_PUBLIC_VAR_NS}_DEBUG)
+endfunction(icudebug)
+
+set(${ICU_PRIVATE_VAR_NS}_ROOT "")
+if(DEFINED ENV{ICU_ROOT})
+ set(${ICU_PRIVATE_VAR_NS}_ROOT "$ENV{ICU_ROOT}")
+endif(DEFINED ENV{ICU_ROOT})
+if (DEFINED ICU_ROOT)
+ set(${ICU_PRIVATE_VAR_NS}_ROOT "${ICU_ROOT}")
+endif(DEFINED ICU_ROOT)
+
+set(${ICU_PRIVATE_VAR_NS}_BIN_SUFFIXES )
+set(${ICU_PRIVATE_VAR_NS}_LIB_SUFFIXES )
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_BIN_SUFFIXES "bin64")
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_LIB_SUFFIXES "lib64")
+endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
+list(APPEND ${ICU_PRIVATE_VAR_NS}_BIN_SUFFIXES "bin")
+list(APPEND ${ICU_PRIVATE_VAR_NS}_LIB_SUFFIXES "lib")
+
+set(${ICU_PRIVATE_VAR_NS}_COMPONENTS )
+# <icu component name> <library name 1> ... <library name N>
+macro(icu_declare_component _NAME)
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_COMPONENTS ${_NAME})
+ set("${ICU_PRIVATE_VAR_NS}_COMPONENTS_${_NAME}" ${ARGN})
+endmacro(icu_declare_component)
+
+icu_declare_component(data icudata)
+icu_declare_component(uc icuuc) # Common and Data libraries
+icu_declare_component(i18n icui18n icuin) # Internationalization library
+icu_declare_component(io icuio ustdio) # Stream and I/O Library
+icu_declare_component(le icule) # Layout library
+icu_declare_component(lx iculx) # Paragraph Layout library
+
+########## Public ##########
+set(${ICU_PUBLIC_VAR_NS}_FOUND TRUE)
+set(${ICU_PUBLIC_VAR_NS}_LIBRARIES )
+set(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS )
+set(${ICU_PUBLIC_VAR_NS}_C_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CXX_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CPP_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_C_SHARED_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CXX_SHARED_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CPP_SHARED_FLAGS "")
+foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PRIVATE_VAR_NS}_COMPONENTS})
+ string(TOUPPER "${${ICU_PRIVATE_VAR_NS}_COMPONENT}" ${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT)
+ set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE) # may be done in the icu_declare_component macro
+endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+
+# Check components
+if(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS) # uc required at least
+ set(${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS uc)
+else(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+ list(APPEND ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS uc)
+ list(REMOVE_DUPLICATES ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+ foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+ if(NOT DEFINED ${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+ message(FATAL_ERROR "Unknown ICU component: ${${ICU_PRIVATE_VAR_NS}_COMPONENT}")
+ endif(NOT DEFINED ${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+ endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+endif(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+
+# Includes
+find_path(
+ ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS
+ NAMES unicode/utypes.h utypes.h
+ HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT}
+ PATH_SUFFIXES "include"
+ DOC "Include directories for ICU"
+)
+
+if(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+ ########## <part to keep synced with tests/version/CMakeLists.txt> ##########
+ if(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uvernum.h") # ICU >= 4
+ file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uvernum.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+ elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uversion.h") # ICU [2;4[
+ file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uversion.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+ elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/utypes.h") # ICU [1.4;2[
+ file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/utypes.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+ elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/utypes.h") # ICU 1.3
+ file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/utypes.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+ else()
+ message(FATAL_ERROR "ICU version header not found")
+ endif()
+
+ if(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *ICU_VERSION *\"([0-9]+)\".*") # ICU 1.3
+ # [1.3;1.4[ as #define ICU_VERSION "3" (no patch version, ie all 1.3.X versions will be detected as 1.3.0)
+ set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "1")
+ set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_1}")
+ set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "0")
+ elseif(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *U_ICU_VERSION_MAJOR_NUM *([0-9]+).*")
+ set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
+ #
+ # Since version 4.9.1, ICU release version numbering was totaly changed, see:
+ # - http://site.icu-project.org/download/49
+ # - http://userguide.icu-project.org/design#TOC-Version-Numbers-in-ICU
+ #
+ if(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION LESS 49)
+ string(REGEX REPLACE ".*# *define *U_ICU_VERSION_MINOR_NUM *([0-9]+).*" "\\1" ${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS}")
+ string(REGEX REPLACE ".*# *define *U_ICU_VERSION_PATCHLEVEL_NUM *([0-9]+).*" "\\1" ${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "${${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS}")
+ else(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION LESS 49)
+ string(REGEX MATCH [0-9]$ ${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION}")
+ string(REGEX REPLACE [0-9]$ "" ${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION}")
+ string(REGEX REPLACE ".*# *define *U_ICU_VERSION_MINOR_NUM *([0-9]+).*" "\\1" ${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "${${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS}")
+ endif(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION LESS 49)
+ elseif(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *U_ICU_VERSION *\"(([0-9]+)(\\.[0-9]+)*)\".*") # ICU [1.4;1.8[
+ # [1.4;1.8[ as #define U_ICU_VERSION "1.4.1.2" but it seems that some 1.4.1(?:\.\d)? have releasing error and appears as 1.4.0
+ set(${ICU_PRIVATE_VAR_NS}_FULL_VERSION "${CMAKE_MATCH_1}") # copy CMAKE_MATCH_1, no longer valid on the following if
+ if(${ICU_PRIVATE_VAR_NS}_FULL_VERSION MATCHES "^([0-9]+)\\.([0-9]+)$")
+ set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
+ set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_2}")
+ set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "0")
+ elseif(${ICU_PRIVATE_VAR_NS}_FULL_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)")
+ set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
+ set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_2}")
+ set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "${CMAKE_MATCH_3}")
+ endif()
+ else()
+ message(FATAL_ERROR "failed to detect ICU version")
+ endif()
+ set(${ICU_PUBLIC_VAR_NS}_VERSION "${${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION}.${${ICU_PUBLIC_VAR_NS}_MINOR_VERSION}.${${ICU_PUBLIC_VAR_NS}_PATCH_VERSION}")
+ ########## </part to keep synced with tests/version/CMakeLists.txt> ##########
+
+ # Check dependencies (implies pkg-config)
+ if(PKG_CONFIG_FOUND)
+ set(${ICU_PRIVATE_VAR_NS}_COMPONENTS_DUP ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+ foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PRIVATE_VAR_NS}_COMPONENTS_DUP})
+ pkg_check_modules(PC_ICU_PRIVATE_VAR_NS "icu-${${ICU_PRIVATE_VAR_NS}_COMPONENT}" QUIET)
+
+ if(${PC_ICU_PRIVATE_VAR_NS}_FOUND)
+ foreach(${PC_ICU_PRIVATE_VAR_NS}_LIBRARY ${PC_ICU_LIBRARIES})
+ string(REGEX REPLACE "^icu" "" ${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY ${${PC_ICU_PRIVATE_VAR_NS}_LIBRARY})
+ list(APPEND ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS ${${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY})
+ endforeach(${PC_ICU_PRIVATE_VAR_NS}_LIBRARY)
+ endif(${PC_ICU_PRIVATE_VAR_NS}_FOUND)
+ endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+ list(REMOVE_DUPLICATES ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+ endif(PKG_CONFIG_FOUND)
+
+ # Check libraries
+ foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+ set(${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES )
+ set(${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES )
+ foreach(${ICU_PRIVATE_VAR_NS}_BASE_NAME ${${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT}})
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}")
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}d")
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}${ICU_MAJOR_VERSION}${ICU_MINOR_VERSION}")
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}${ICU_MAJOR_VERSION}${ICU_MINOR_VERSION}d")
+ endforeach(${ICU_PRIVATE_VAR_NS}_BASE_NAME)
+
+ find_library(
+ ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}
+ NAMES ${${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES}
+ HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT}
+ PATH_SUFFIXES ${_ICU_LIB_SUFFIXES}
+ DOC "Release libraries for ICU"
+ )
+ find_library(
+ ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}
+ NAMES ${${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES}
+ HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT}
+ PATH_SUFFIXES ${_ICU_LIB_SUFFIXES}
+ DOC "Debug libraries for ICU"
+ )
+
+ string(TOUPPER "${${ICU_PRIVATE_VAR_NS}_COMPONENT}" ${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT)
+ if(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # both not found
+ set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE)
+ set("${ICU_PUBLIC_VAR_NS}_FOUND" FALSE)
+ else(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # one or both found
+ set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" TRUE)
+ if(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # release not found => we are in debug
+ set(${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT} "${${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}")
+ elseif(NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # debug not found => we are in release
+ set(${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT} "${${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}")
+ else() # both found
+ set(
+ ${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT}
+ optimized ${${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}
+ debug ${${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}
+ )
+ endif()
+ list(APPEND ${ICU_PUBLIC_VAR_NS}_LIBRARIES ${${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT}})
+ endif(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+ endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+
+ # Try to find out compiler flags
+ find_program(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT} icu-config)
+ if(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_C_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cxxflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CXX_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cppflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CPP_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_C_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cxxflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CXX_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cppflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CPP_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ endif(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE)
+
+ # Check find_package arguments
+ include(FindPackageHandleStandardArgs)
+ if(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+ find_package_handle_standard_args(
+ ${ICU_PUBLIC_VAR_NS}
+ REQUIRED_VARS ${ICU_PUBLIC_VAR_NS}_LIBRARIES ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS
+ VERSION_VAR ${ICU_PUBLIC_VAR_NS}_VERSION
+ )
+ else(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+ find_package_handle_standard_args(${ICU_PUBLIC_VAR_NS} "ICU not found" ${ICU_PUBLIC_VAR_NS}_LIBRARIES ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+ endif(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+else(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+ if(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+ message(FATAL_ERROR "Could not find ICU include directory")
+ endif(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+endif(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+
+mark_as_advanced(
+ ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS
+ ${ICU_PUBLIC_VAR_NS}_LIBRARIES
+)
+
+# IN (args)
+icudebug("FIND_COMPONENTS")
+icudebug("FIND_REQUIRED")
+icudebug("FIND_QUIETLY")
+icudebug("FIND_VERSION")
+# OUT
+# Found
+icudebug("FOUND")
+icudebug("UC_FOUND")
+icudebug("I18N_FOUND")
+icudebug("IO_FOUND")
+icudebug("LE_FOUND")
+icudebug("LX_FOUND")
+icudebug("DATA_FOUND")
+# Flags
+icudebug("C_FLAGS")
+icudebug("CPP_FLAGS")
+icudebug("CXX_FLAGS")
+icudebug("C_SHARED_FLAGS")
+icudebug("CPP_SHARED_FLAGS")
+icudebug("CXX_SHARED_FLAGS")
+# Linking
+icudebug("INCLUDE_DIRS")
+icudebug("LIBRARIES")
+# Version
+icudebug("MAJOR_VERSION")
+icudebug("MINOR_VERSION")
+icudebug("PATCH_VERSION")
+icudebug("VERSION")
diff --git a/vmime-master/cmake/FindIconv.cmake b/vmime-master/cmake/FindIconv.cmake
new file mode 100644
index 0000000..6233657
--- /dev/null
+++ b/vmime-master/cmake/FindIconv.cmake
@@ -0,0 +1,61 @@
+# - Try to find Iconv
+# Once done this will define
+#
+# ICONV_FOUND - system has Iconv
+# ICONV_INCLUDE_DIR - the Iconv include directory
+# ICONV_LIBRARIES - Link these to use Iconv
+# ICONV_SECOND_ARGUMENT_IS_CONST - the second argument for iconv() is const
+#
+include(CheckCXXSourceCompiles)
+
+IF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
+ # Already in cache, be silent
+ SET(ICONV_FIND_QUIETLY TRUE)
+ENDIF (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
+
+FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
+
+IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c HINTS "/opt/local/lib")
+ELSE()
+ FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c)
+ENDIF()
+
+IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
+ SET(ICONV_FOUND TRUE)
+ENDIF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
+
+set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
+set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARIES})
+IF(ICONV_FOUND)
+ check_cxx_source_compiles("
+ #include <iconv.h>
+ int main(){
+ iconv_t conv = 0;
+ const char* in = 0;
+ size_t ilen = 0;
+ char* out = 0;
+ size_t olen = 0;
+ iconv(conv, &in, &ilen, &out, &olen);
+ return 0;
+ }
+" ICONV_SECOND_ARGUMENT_IS_CONST )
+ENDIF(ICONV_FOUND)
+set(CMAKE_REQUIRED_INCLUDES)
+set(CMAKE_REQUIRED_LIBRARIES)
+
+IF(ICONV_FOUND)
+ IF(NOT ICONV_FIND_QUIETLY)
+ MESSAGE(STATUS "Found Iconv: ${ICONV_LIBRARIES}")
+ ENDIF(NOT ICONV_FIND_QUIETLY)
+ELSE(ICONV_FOUND)
+ IF(Iconv_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR "Could not find Iconv")
+ ENDIF(Iconv_FIND_REQUIRED)
+ENDIF(ICONV_FOUND)
+
+MARK_AS_ADVANCED(
+ ICONV_INCLUDE_DIR
+ ICONV_LIBRARIES
+ ICONV_SECOND_ARGUMENT_IS_CONST
+)
diff --git a/vmime-master/cmake/Utils.cmake b/vmime-master/cmake/Utils.cmake
new file mode 100644
index 0000000..fd8928e
--- /dev/null
+++ b/vmime-master/cmake/Utils.cmake
@@ -0,0 +1,13 @@
+
+# Installing headers and preserving the directory structure
+# Found here: http://www.semipol.de/archives/251
+MACRO(INSTALL_HEADERS_WITH_DIRECTORY HEADER_LIST COMPONENT_NAME REMOVE_PREFIX)
+
+ FOREACH(HEADER ${${HEADER_LIST}})
+ STRING(REGEX MATCH "(.*)[/\\]" DIR ${HEADER})
+ STRING(REPLACE "${REMOVE_PREFIX}" "" DIR ${DIR})
+ INSTALL(FILES ${HEADER} DESTINATION include/${DIR} COMPONENT ${COMPONENT_NAME})
+ ENDFOREACH(HEADER)
+
+ENDMACRO(INSTALL_HEADERS_WITH_DIRECTORY)
+
diff --git a/vmime-master/cmake/config.hpp.cmake b/vmime-master/cmake/config.hpp.cmake
new file mode 100644
index 0000000..c5e9fde
--- /dev/null
+++ b/vmime-master/cmake/config.hpp.cmake
@@ -0,0 +1,97 @@
+//
+// This file was automatically generated by CMake.
+//
+
+#ifndef VMIME_CONFIG_HPP_INCLUDED
+#define VMIME_CONFIG_HPP_INCLUDED
+
+
+#include "vmime/export.hpp"
+
+
+// Name of package
+#define VMIME_PACKAGE "@PROJECT_NAME@"
+
+// Version number of package
+#define VMIME_VERSION "@VMIME_VERSION@"
+#define VMIME_API "@VMIME_API_VERSION@"
+
+// Set to 1 if debugging should be activated
+#define VMIME_DEBUG @VMIME_DEBUG@
+
+// Byte order (set one or the other, but not both!)
+#define VMIME_BYTE_ORDER_BIG_ENDIAN @VMIME_BYTE_ORDER_BIG_ENDIAN@
+#define VMIME_BYTE_ORDER_LITTLE_ENDIAN @VMIME_BYTE_ORDER_LITTLE_ENDIAN@
+
+// Generic types
+#cmakedefine01 VMIME_HAVE_CSTDINT
+#if VMIME_HAVE_CSTDINT
+# include <cstdint>
+#endif
+
+// -- 8-bit
+typedef signed @VMIME_8BIT_TYPE@ vmime_int8;
+typedef unsigned @VMIME_8BIT_TYPE@ vmime_uint8;
+// -- 16-bit
+typedef signed @VMIME_16BIT_TYPE@ vmime_int16;
+typedef unsigned @VMIME_16BIT_TYPE@ vmime_uint16;
+// -- 32-bit
+typedef signed @VMIME_32BIT_TYPE@ vmime_int32;
+typedef unsigned @VMIME_32BIT_TYPE@ vmime_uint32;
+// -- 64-bit
+typedef signed @VMIME_64BIT_TYPE@ vmime_int64;
+typedef unsigned @VMIME_64BIT_TYPE@ vmime_uint64;
+
+#cmakedefine01 VMIME_HAVE_SIZE_T
+
+// Charset conversion support
+#cmakedefine01 VMIME_CHARSETCONV_LIB_IS_ICONV
+#cmakedefine01 VMIME_CHARSETCONV_LIB_IS_ICU
+#cmakedefine01 VMIME_CHARSETCONV_LIB_IS_WIN
+
+// Options
+// -- File-system support
+#cmakedefine01 VMIME_HAVE_FILESYSTEM_FEATURES
+// -- SASL support
+#cmakedefine01 VMIME_HAVE_SASL_SUPPORT
+// -- TLS/SSL support
+#cmakedefine01 VMIME_HAVE_TLS_SUPPORT
+#cmakedefine01 VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+#cmakedefine01 VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+#define VMIME_HAVE_GNUTLS_PRIORITY_FUNCS @VMIME_HAVE_GNUTLS_PRIORITY_FUNCS@
+// -- Messaging support
+#cmakedefine01 VMIME_HAVE_MESSAGING_FEATURES
+// -- Messaging protocols
+#cmakedefine01 VMIME_HAVE_MESSAGING_PROTO_POP3
+#cmakedefine01 VMIME_HAVE_MESSAGING_PROTO_SMTP
+#cmakedefine01 VMIME_HAVE_MESSAGING_PROTO_IMAP
+#cmakedefine01 VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+#cmakedefine01 VMIME_HAVE_MESSAGING_PROTO_SENDMAIL
+// -- Platform-specific code
+#cmakedefine01 VMIME_PLATFORM_IS_POSIX
+#cmakedefine01 VMIME_PLATFORM_IS_WINDOWS
+#cmakedefine01 VMIME_HAVE_PTHREAD
+#cmakedefine01 VMIME_HAVE_GETADDRINFO
+#cmakedefine01 VMIME_HAVE_GETADDRINFO_A
+#cmakedefine01 VMIME_HAVE_GETTID
+#cmakedefine01 VMIME_HAVE_SYSCALL
+#cmakedefine01 VMIME_HAVE_SYSCALL_GETTID
+#cmakedefine01 VMIME_HAVE_GETTHRID
+#cmakedefine01 VMIME_HAVE_GMTIME_S
+#cmakedefine01 VMIME_HAVE_GMTIME_R
+#cmakedefine01 VMIME_HAVE_LOCALTIME_S
+#cmakedefine01 VMIME_HAVE_LOCALTIME_R
+#cmakedefine01 VMIME_HAVE_STRERROR_R
+#cmakedefine01 VMIME_HAVE_MLANG
+#cmakedefine01 VMIME_HAVE_SO_KEEPALIVE
+#cmakedefine01 VMIME_HAVE_SO_NOSIGPIPE
+#cmakedefine01 VMIME_HAVE_MSG_NOSIGNAL
+#cmakedefine01 VMIME_SHARED_PTR_USE_CXX
+#cmakedefine01 VMIME_SHARED_PTR_USE_BOOST
+
+
+#define VMIME_SENDMAIL_PATH "@VMIME_SENDMAIL_PATH@"
+
+
+#endif // VMIME_CONFIG_HPP_INCLUDED
+
diff --git a/vmime-master/config_header/config.hpp b/vmime-master/config_header/config.hpp
new file mode 100644
index 0000000..026b839
--- /dev/null
+++ b/vmime-master/config_header/config.hpp
@@ -0,0 +1,97 @@
+//
+// This file was automatically generated by CMake.
+//
+
+#ifndef VMIME_CONFIG_HPP_INCLUDED
+#define VMIME_CONFIG_HPP_INCLUDED
+
+
+#include "vmime/export.hpp"
+
+
+// Name of package
+#define VMIME_PACKAGE "vmime"
+
+// Version number of package
+#define VMIME_VERSION "0.9.2"
+#define VMIME_API "1.0.0"
+
+// Set to 1 if debugging should be activated
+#define VMIME_DEBUG 1
+
+// Byte order (set one or the other, but not both!)
+#define VMIME_BYTE_ORDER_BIG_ENDIAN 0
+#define VMIME_BYTE_ORDER_LITTLE_ENDIAN 1
+
+// Generic types
+#define VMIME_HAVE_CSTDINT 1
+#if VMIME_HAVE_CSTDINT
+# include <cstdint>
+#endif
+
+// -- 8-bit
+typedef signed char vmime_int8;
+typedef unsigned char vmime_uint8;
+// -- 16-bit
+typedef signed short vmime_int16;
+typedef unsigned short vmime_uint16;
+// -- 32-bit
+typedef signed int vmime_int32;
+typedef unsigned int vmime_uint32;
+// -- 64-bit
+typedef signed long long vmime_int64;
+typedef unsigned long long vmime_uint64;
+
+#define VMIME_HAVE_SIZE_T 1
+
+// Charset conversion support
+#define VMIME_CHARSETCONV_LIB_IS_ICONV 0
+#define VMIME_CHARSETCONV_LIB_IS_ICU 0
+#define VMIME_CHARSETCONV_LIB_IS_WIN 1
+
+// Options
+// -- File-system support
+#define VMIME_HAVE_FILESYSTEM_FEATURES 1
+// -- SASL support
+#define VMIME_HAVE_SASL_SUPPORT 0
+// -- TLS/SSL support
+#define VMIME_HAVE_TLS_SUPPORT 1
+#define VMIME_TLS_SUPPORT_LIB_IS_GNUTLS 0
+#define VMIME_TLS_SUPPORT_LIB_IS_OPENSSL 1
+#define VMIME_HAVE_GNUTLS_PRIORITY_FUNCS
+// -- Messaging support
+#define VMIME_HAVE_MESSAGING_FEATURES 1
+// -- Messaging protocols
+#define VMIME_HAVE_MESSAGING_PROTO_POP3 1
+#define VMIME_HAVE_MESSAGING_PROTO_SMTP 1
+#define VMIME_HAVE_MESSAGING_PROTO_IMAP 1
+#define VMIME_HAVE_MESSAGING_PROTO_MAILDIR 0
+#define VMIME_HAVE_MESSAGING_PROTO_SENDMAIL 0
+// -- Platform-specific code
+#define VMIME_PLATFORM_IS_POSIX 0
+#define VMIME_PLATFORM_IS_WINDOWS 1
+#define VMIME_HAVE_PTHREAD 0
+#define VMIME_HAVE_GETADDRINFO 0
+#define VMIME_HAVE_GETADDRINFO_A 0
+#define VMIME_HAVE_GETTID 0
+#define VMIME_HAVE_SYSCALL 0
+#define VMIME_HAVE_SYSCALL_GETTID 0
+#define VMIME_HAVE_GETTHRID 0
+#define VMIME_HAVE_GMTIME_S 0
+#define VMIME_HAVE_GMTIME_R 0
+#define VMIME_HAVE_LOCALTIME_S 0
+#define VMIME_HAVE_LOCALTIME_R 0
+#define VMIME_HAVE_STRERROR_R 0
+#define VMIME_HAVE_MLANG 0
+#define VMIME_HAVE_SO_KEEPALIVE 0
+#define VMIME_HAVE_SO_NOSIGPIPE 0
+#define VMIME_HAVE_MSG_NOSIGNAL 0
+#define VMIME_SHARED_PTR_USE_CXX 0
+#define VMIME_SHARED_PTR_USE_BOOST 0
+
+
+#define VMIME_SENDMAIL_PATH "/usr/lib/sendmail"
+
+
+#endif // VMIME_CONFIG_HPP_INCLUDED
+
diff --git a/vmime-master/contrib/punycode/punycode.c b/vmime-master/contrib/punycode/punycode.c
new file mode 100644
index 0000000..f669aa0
--- /dev/null
+++ b/vmime-master/contrib/punycode/punycode.c
@@ -0,0 +1,264 @@
+/*
+punycode.c from RFC 3492
+http://www.nicemice.net/idn/
+Adam M. Costello
+http://www.nicemice.net/amc/
+
+This is ANSI C code (C89) implementing Punycode (RFC 3492).
+
+*/
+
+#include <string.h>
+
+/*** Bootstring parameters for Punycode ***/
+
+enum { base = 36, tmin = 1, tmax = 26, skew = 38, damp = 700,
+ initial_bias = 72, initial_n = 0x80, delimiter = 0x2D };
+
+/* basic(cp) tests whether cp is a basic code point: */
+#define basic(cp) ((punycode_uint)(cp) < 0x80)
+
+/* delim(cp) tests whether cp is a delimiter: */
+#define delim(cp) ((cp) == delimiter)
+
+/* decode_digit(cp) returns the numeric value of a basic code */
+/* point (for use in representing integers) in the range 0 to */
+/* base-1, or base if cp is does not represent a value. */
+
+static punycode_uint decode_digit(punycode_uint cp)
+{
+ return cp - 48 < 10 ? cp - 22 : cp - 65 < 26 ? cp - 65 :
+ cp - 97 < 26 ? cp - 97 : (punycode_uint) base;
+}
+
+/* encode_digit(d,flag) returns the basic code point whose value */
+/* (when used for representing integers) is d, which needs to be in */
+/* the range 0 to base-1. The lowercase form is used unless flag is */
+/* nonzero, in which case the uppercase form is used. The behavior */
+/* is undefined if flag is nonzero and digit d has no uppercase form. */
+
+static char encode_digit(punycode_uint d, int flag)
+{
+ return char(d + 22 + 75 * (d < 26) - ((flag != 0) << 5));
+ /* 0..25 map to ASCII a..z or A..Z */
+ /* 26..35 map to ASCII 0..9 */
+}
+
+/* flagged(bcp) tests whether a basic code point is flagged */
+/* (uppercase). The behavior is undefined if bcp is not a */
+/* basic code point. */
+
+#define flagged(bcp) ((punycode_uint)(bcp) - 65 < 26)
+
+/* encode_basic(bcp,flag) forces a basic code point to lowercase */
+/* if flag is zero, uppercase if flag is nonzero, and returns */
+/* the resulting code point. The code point is unchanged if it */
+/* is caseless. The behavior is undefined if bcp is not a basic */
+/* code point. */
+
+static char encode_basic(punycode_uint bcp, int flag)
+{
+ bcp -= (bcp - 97 < 26) << 5;
+ return char(bcp + ((!flag && (bcp - 65 < 26)) << 5));
+}
+
+/*** Platform-specific constants ***/
+
+/* maxint is the maximum value of a punycode_uint variable: */
+static const punycode_uint maxint = -1U;
+/* Because maxint is unsigned, -1 becomes the maximum value. */
+
+/*** Bias adaptation function ***/
+
+static punycode_uint adapt(
+ punycode_uint delta, punycode_uint numpoints, int firsttime )
+{
+ punycode_uint k;
+
+ delta = firsttime ? delta / damp : delta >> 1;
+ /* delta >> 1 is a faster way of doing delta / 2 */
+ delta += delta / numpoints;
+
+ for (k = 0; delta > ((base - tmin) * tmax) / 2; k += base) {
+ delta /= base - tmin;
+ }
+
+ return k + (base - tmin + 1) * delta / (delta + skew);
+}
+
+/*** Main encode function ***/
+
+enum punycode_status punycode_encode(
+ punycode_uint input_length,
+ const punycode_uint input[],
+ const unsigned char case_flags[],
+ punycode_uint *output_length,
+ char output[] )
+{
+ punycode_uint n, delta, h, b, out, max_out, bias, j, m, q, k, t;
+
+ /* Initialize the state: */
+
+ n = initial_n;
+ delta = out = 0;
+ max_out = *output_length;
+ bias = initial_bias;
+
+ /* Handle the basic code points: */
+
+ for (j = 0; j < input_length; ++j) {
+ if (basic(input[j])) {
+ if (max_out - out < 2) return punycode_big_output;
+ output[out++] = char(
+ case_flags ? encode_basic(input[j], case_flags[j]) : input[j]
+ );
+ }
+ /* else if (input[j] < n) return punycode_bad_input; */
+ /* (not needed for Punycode with unsigned code points) */
+ }
+
+ h = b = out;
+
+ /* h is the number of code points that have been handled, b is the */
+ /* number of basic code points, and out is the number of characters */
+ /* that have been output. */
+
+ if (b > 0) output[out++] = delimiter;
+
+ /* Main encoding loop: */
+
+ while (h < input_length) {
+ /* All non-basic code points < n have been */
+ /* handled already. Find the next larger one: */
+
+ for (m = maxint, j = 0; j < input_length; ++j) {
+ /* if (basic(input[j])) continue; */
+ /* (not needed for Punycode) */
+ if (input[j] >= n && input[j] < m) m = input[j];
+ }
+
+ /* Increase delta enough to advance the decoder's */
+ /* <n,i> state to <m,0>, but guard against overflow: */
+
+ if (m - n > (maxint - delta) / (h + 1)) return punycode_overflow;
+ delta += (m - n) * (h + 1);
+ n = m;
+
+ for (j = 0; j < input_length; ++j) {
+ /* Punycode does not need to check whether input[j] is basic: */
+ if (input[j] < n /* || basic(input[j]) */ ) {
+ if (++delta == 0) return punycode_overflow;
+ }
+
+ if (input[j] == n) {
+ /* Represent delta as a generalized variable-length integer: */
+
+ for (q = delta, k = base; ; k += base) {
+ if (out >= max_out) return punycode_big_output;
+ t = k <= bias /* + tmin */ ? (punycode_uint) tmin : /* +tmin not needed */
+ k >= (punycode_uint) bias + (punycode_uint) tmax ? (punycode_uint) tmax : k - (punycode_uint) bias;
+ if (q < t) break;
+ output[out++] = encode_digit(t + (q - t) % (base - t), 0);
+ q = (q - t) / (base - t);
+ }
+
+ output[out++] = encode_digit(q, case_flags && case_flags[j]);
+ bias = adapt(delta, h + 1, h == b);
+ delta = 0;
+ ++h;
+ }
+ }
+
+ ++delta, ++n;
+ }
+
+ *output_length = out;
+ return punycode_success;
+}
+
+/*** Main decode function ***/
+
+enum punycode_status punycode_decode(
+ punycode_uint input_length,
+ const char input[],
+ punycode_uint *output_length,
+ punycode_uint output[],
+ unsigned char case_flags[] )
+{
+ punycode_uint n, out, i, max_out, bias,
+ b, j, in, oldi, w, k, digit, t;
+
+ /* Initialize the state: */
+
+ n = initial_n;
+ out = i = 0;
+ max_out = *output_length;
+ bias = initial_bias;
+
+ /* Handle the basic code points: Let b be the number of input code */
+ /* points before the last delimiter, or 0 if there is none, then */
+ /* copy the first b code points to the output. */
+
+ for (b = j = 0; j < input_length; ++j) if (delim(input[j])) b = j;
+ if (b > max_out) return punycode_big_output;
+
+ for (j = 0; j < b; ++j) {
+ if (case_flags) case_flags[out] = flagged(input[j]);
+ if (!basic(input[j])) return punycode_bad_input;
+ output[out++] = input[j];
+ }
+
+ /* Main decoding loop: Start just after the last delimiter if any */
+ /* basic code points were copied; start at the beginning otherwise. */
+
+ for (in = b > 0 ? b + 1 : 0; in < input_length; ++out) {
+
+ /* in is the index of the next character to be consumed, and */
+ /* out is the number of code points in the output array. */
+
+ /* Decode a generalized variable-length integer into delta, */
+ /* which gets added to i. The overflow checking is easier */
+ /* if we increase i as we go, then subtract off its starting */
+ /* value at the end to obtain delta. */
+
+ for (oldi = i, w = 1, k = base; ; k += base) {
+ if (in >= input_length) return punycode_bad_input;
+ digit = decode_digit(input[in++]);
+ if (digit >= base) return punycode_bad_input;
+ if (digit > (maxint - i) / w) return punycode_overflow;
+ i += digit * w;
+ t = k <= (punycode_uint) bias /* + tmin */ ? (punycode_uint) tmin : /* +tmin not needed */
+ k >= (punycode_uint) bias + (punycode_uint) tmax ? (punycode_uint) tmax : k - (punycode_uint) bias;
+ if (digit < t) break;
+ if (w > maxint / (base - t)) return punycode_overflow;
+ w *= (base - t);
+ }
+
+ bias = adapt(i - oldi, out + 1, oldi == 0);
+
+ /* i was supposed to wrap around from out+1 to 0, */
+ /* incrementing n each time, so we'll fix that now: */
+
+ if (i / (out + 1) > maxint - n) return punycode_overflow;
+ n += i / (out + 1);
+ i %= (out + 1);
+
+ /* Insert n at position i of the output: */
+
+ /* not needed for Punycode: */
+ /* if (decode_digit(n) <= base) return punycode_invalid_input; */
+ if (out >= max_out) return punycode_big_output;
+
+ if (case_flags) {
+ memmove(case_flags + i + 1, case_flags + i, out - i);
+ /* Case of last character determines uppercase flag: */
+ case_flags[i] = flagged(input[in - 1]);
+ }
+
+ memmove(output + i + 1, output + i, (out - i) * sizeof *output);
+ output[i++] = n;
+ }
+
+ *output_length = out;
+ return punycode_success;
+}
diff --git a/vmime-master/contrib/punycode/punycode.h b/vmime-master/contrib/punycode/punycode.h
new file mode 100644
index 0000000..fb02ee9
--- /dev/null
+++ b/vmime-master/contrib/punycode/punycode.h
@@ -0,0 +1,84 @@
+/*
+punycode.h from RFC 3492
+http://www.nicemice.net/idn/
+Adam M. Costello
+http://www.nicemice.net/amc/
+
+This is ANSI C code (C89) implementing Punycode (RFC 3492).
+
+*/
+
+#include <limits.h>
+
+enum punycode_status {
+ punycode_success,
+ punycode_bad_input, /* Input is invalid. */
+ punycode_big_output, /* Output would exceed the space provided. */
+ punycode_overflow /* Input needs wider integers to process. */
+};
+
+#if UINT_MAX >= (1 << 26) - 1
+typedef unsigned int punycode_uint;
+#else
+typedef unsigned long punycode_uint;
+#endif
+
+enum punycode_status punycode_encode(
+ punycode_uint input_length,
+ const punycode_uint input[],
+ const unsigned char case_flags[],
+ punycode_uint *output_length,
+ char output[] );
+
+ /* punycode_encode() converts Unicode to Punycode. The input */
+ /* is represented as an array of Unicode code points (not code */
+ /* units; surrogate pairs are not allowed), and the output */
+ /* will be represented as an array of ASCII code points. The */
+ /* output string is *not* null-terminated; it will contain */
+ /* zeros if and only if the input contains zeros. (Of course */
+ /* the caller can leave room for a terminator and add one if */
+ /* needed.) The input_length is the number of code points in */
+ /* the input. The output_length is an in/out argument: the */
+ /* caller passes in the maximum number of code points that it */
+ /* can receive, and on successful return it will contain the */
+ /* number of code points actually output. The case_flags array */
+ /* holds input_length boolean values, where nonzero suggests that */
+ /* the corresponding Unicode character be forced to uppercase */
+ /* after being decoded (if possible), and zero suggests that */
+ /* it be forced to lowercase (if possible). ASCII code points */
+ /* are encoded literally, except that ASCII letters are forced */
+ /* to uppercase or lowercase according to the corresponding */
+ /* uppercase flags. If case_flags is a null pointer then ASCII */
+ /* letters are left as they are, and other code points are */
+ /* treated as if their uppercase flags were zero. The return */
+ /* value can be any of the punycode_status values defined above */
+ /* except punycode_bad_input; if not punycode_success, then */
+ /* output_size and output might contain garbage. */
+
+enum punycode_status punycode_decode(
+ punycode_uint input_length,
+ const char input[],
+ punycode_uint *output_length,
+ punycode_uint output[],
+ unsigned char case_flags[] );
+
+ /* punycode_decode() converts Punycode to Unicode. The input is */
+ /* represented as an array of ASCII code points, and the output */
+ /* will be represented as an array of Unicode code points. The */
+ /* input_length is the number of code points in the input. The */
+ /* output_length is an in/out argument: the caller passes in */
+ /* the maximum number of code points that it can receive, and */
+ /* on successful return it will contain the actual number of */
+ /* code points output. The case_flags array needs room for at */
+ /* least output_length values, or it can be a null pointer if the */
+ /* case information is not needed. A nonzero flag suggests that */
+ /* the corresponding Unicode character be forced to uppercase */
+ /* by the caller (if possible), while zero suggests that it be */
+ /* forced to lowercase (if possible). ASCII code points are */
+ /* output already in the proper case, but their flags will be set */
+ /* appropriately so that applying the flags would be harmless. */
+ /* The return value can be any of the punycode_status values */
+ /* defined above; if not punycode_success, then output_length, */
+ /* output, and case_flags might contain garbage. On success, the */
+ /* decoder will never need to write an output_length greater than */
+ /* input_length, because of how the encoding is defined. */
diff --git a/vmime-master/contrib/utf8/utf8.h b/vmime-master/contrib/utf8/utf8.h
new file mode 100644
index 0000000..4e44514
--- /dev/null
+++ b/vmime-master/contrib/utf8/utf8.h
@@ -0,0 +1,34 @@
+// 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
diff --git a/vmime-master/contrib/utf8/utf8/checked.h b/vmime-master/contrib/utf8/utf8/checked.h
new file mode 100644
index 0000000..1331155
--- /dev/null
+++ b/vmime-master/contrib/utf8/utf8/checked.h
@@ -0,0 +1,327 @@
+// 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_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+#include <stdexcept>
+
+namespace utf8
+{
+ // Base for the exceptions that may be thrown from the library
+ class exception : public ::std::exception {
+ };
+
+ // Exceptions that may be thrown from the library functions.
+ class invalid_code_point : public exception {
+ uint32_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;}
+ };
+
+ class invalid_utf8 : public exception {
+ uint8_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;}
+ };
+
+ class invalid_utf16 : public exception {
+ uint16_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;}
+ };
+
+ class not_enough_room : public exception {
+ public:
+ virtual const char* what() const throw() { 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)
+ {
+ 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;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_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:
+ throw not_enough_room();
+ case internal::INVALID_LEAD:
+ out = utf8::append (replacement, out);
+ ++start;
+ break;
+ case internal::INCOMPLETE_SEQUENCE:
+ case internal::OVERLONG_SEQUENCE:
+ case internal::INVALID_CODE_POINT:
+ out = utf8::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 uint32_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)
+ {
+ uint32_t cp = 0;
+ internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ break;
+ case internal::NOT_ENOUGH_ROOM :
+ throw not_enough_room();
+ case internal::INVALID_LEAD :
+ case internal::INCOMPLETE_SEQUENCE :
+ case internal::OVERLONG_SEQUENCE :
+ throw invalid_utf8(*it);
+ case internal::INVALID_CODE_POINT :
+ throw invalid_code_point(cp);
+ }
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_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)
+ {
+ // can't do much if it == start
+ if (it == start)
+ throw not_enough_room();
+
+ octet_iterator end = it;
+ // Go back until we hit either a lead octet or start
+ while (utf8::internal::is_trail(*(--it)))
+ if (it == start)
+ throw invalid_utf8(*it); // error - no lead byte in the sequence
+ 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);
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::next(first, last);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ 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
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ if (start != end) {
+ uint32_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));
+ }
+ else
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ }
+ // Lone trail surrogate
+ else if (utf8::internal::is_trail_surrogate(cp))
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ result = utf8::append(cp, result);
+ }
+ return result;
+ }
+
+ 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);
+ 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);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start != end)
+ (*result++) = utf8::next(start, end);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
+ octet_iterator it;
+ octet_iterator range_start;
+ octet_iterator range_end;
+ public:
+ 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)
+ {
+ 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
+ {
+ octet_iterator temp = it;
+ return utf8::next(temp, range_end);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ if (range_start != rhs.range_start || range_end != rhs.range_end)
+ throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ utf8::next(it, range_end);
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ utf8::next(it, range_end);
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::prior(it, range_start);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::prior(it, range_start);
+ return temp;
+ }
+ }; // class iterator
+
+} // namespace utf8
+
+#endif //header guard
+
+
diff --git a/vmime-master/contrib/utf8/utf8/core.h b/vmime-master/contrib/utf8/utf8/core.h
new file mode 100644
index 0000000..f858c4a
--- /dev/null
+++ b/vmime-master/contrib/utf8/utf8/core.h
@@ -0,0 +1,326 @@
+// 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_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include <iterator>
+
+namespace utf8
+{
+ typedef vmime_uint8 uint8_t;
+ typedef vmime_uint16 uint16_t;
+ typedef vmime_uint32 uint32_t;
+
+// Helper code - not intended to be directly called by the library users. May be changed at any time
+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;
+
+ // Maximum valid value for a Unicode code point
+ const uint32_t CODE_POINT_MAX = 0x0010ffffu;
+
+ template<typename octet_type>
+ inline uint8_t mask8(octet_type oc)
+ {
+ return static_cast<uint8_t>(0xff & oc);
+ }
+ template<typename u16_type>
+ inline uint16_t mask16(u16_type oc)
+ {
+ return static_cast<uint16_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)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_trail_surrogate(u16 cp)
+ {
+ return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u32>
+ inline bool is_code_point_valid(u32 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)
+ {
+ uint8_t lead = utf8::internal::mask8(*lead_it);
+ if (lead < 0x80)
+ return 1;
+ else if ((lead >> 5) == 0x6)
+ return 2;
+ else if ((lead >> 4) == 0xe)
+ return 3;
+ else if ((lead >> 3) == 0x1e)
+ return 4;
+ else
+ return 0;
+ }
+
+ template <typename octet_difference_type>
+ inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
+ {
+ if (cp < 0x80) {
+ if (length != 1)
+ return true;
+ }
+ else if (cp < 0x800) {
+ if (length != 2)
+ return true;
+ }
+ else if (cp < 0x10000) {
+ if (length != 3)
+ return true;
+ }
+
+ return false;
+ }
+
+ enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
+
+ /// Helper for get_sequence_x
+ template <typename octet_iterator>
+ utf_error increase_safely(octet_iterator& it, octet_iterator end)
+ {
+ if (++it == end)
+ return NOT_ENOUGH_ROOM;
+
+ if (!utf8::internal::is_trail(*it))
+ return INCOMPLETE_SEQUENCE;
+
+ return UTF8_OK;
+ }
+
+ #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
+
+ /// 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)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_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)
+
+ code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_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)
+
+ code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_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)
+
+ code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ #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)
+ {
+ // 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;
+ // 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);
+
+ // Get trail octets and calculate the code point
+ utf_error err = UTF8_OK;
+ switch (length) {
+ case 0:
+ return INVALID_LEAD;
+ case 1:
+ err = utf8::internal::get_sequence_1(it, end, cp);
+ break;
+ case 2:
+ err = utf8::internal::get_sequence_2(it, end, cp);
+ break;
+ case 3:
+ err = utf8::internal::get_sequence_3(it, end, cp);
+ break;
+ case 4:
+ err = utf8::internal::get_sequence_4(it, end, cp);
+ break;
+ }
+
+ if (err == UTF8_OK) {
+ // Decoding succeeded. Now, security checks...
+ if (utf8::internal::is_code_point_valid(cp)) {
+ if (!utf8::internal::is_overlong_sequence(cp, length)){
+ // Passed! Return here.
+ code_point = cp;
+ ++it;
+ return UTF8_OK;
+ }
+ else
+ err = OVERLONG_SEQUENCE;
+ }
+ else
+ err = INVALID_CODE_POINT;
+ }
+
+ // Failure branch - restore the original value of the iterator
+ it = original_it;
+ return err;
+ }
+
+ template <typename octet_iterator>
+ inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
+ uint32_t ignored;
+ return utf8::internal::validate_next(it, end, ignored);
+ }
+
+} // namespace internal
+
+ /// The library API - functions intended to be called by the users
+
+ // Byte order mark
+ const uint8_t bom[] = {0xef, 0xbb, 0xbf};
+
+ template <typename octet_iterator>
+ octet_iterator find_invalid(octet_iterator start, octet_iterator end)
+ {
+ octet_iterator result = start;
+ while (result != end) {
+ utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
+ if (err_code != internal::UTF8_OK)
+ return result;
+ }
+ return result;
+ }
+
+ template <typename octet_iterator>
+ inline bool is_valid(octet_iterator start, octet_iterator end)
+ {
+ return (utf8::find_invalid(start, end) == end);
+ }
+
+ template <typename octet_iterator>
+ inline bool starts_with_bom (octet_iterator it, octet_iterator end)
+ {
+ return (
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
+ ((it != end) && (utf8::internal::mask8(*it)) == bom[2])
+ );
+ }
+
+ //Deprecated in release 2.3
+ template <typename octet_iterator>
+ inline bool is_bom (octet_iterator it)
+ {
+ return (
+ (utf8::internal::mask8(*it++)) == bom[0] &&
+ (utf8::internal::mask8(*it++)) == bom[1] &&
+ (utf8::internal::mask8(*it)) == bom[2]
+ );
+ }
+} // namespace utf8
+
+#endif // header guard
+
+
diff --git a/vmime-master/contrib/utf8/utf8/unchecked.h b/vmime-master/contrib/utf8/utf8/unchecked.h
new file mode 100644
index 0000000..cb24271
--- /dev/null
+++ b/vmime-master/contrib/utf8/utf8/unchecked.h
@@ -0,0 +1,228 @@
+// 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_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+
+namespace utf8
+{
+ namespace unchecked
+ {
+ template <typename octet_iterator>
+ octet_iterator append(uint32_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 result;
+ }
+
+ template <typename octet_iterator>
+ uint32_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) {
+ case 1:
+ break;
+ case 2:
+ it++;
+ cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
+ break;
+ case 3:
+ ++it;
+ cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ case 4:
+ ++it;
+ cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+ ++it;
+ cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ }
+ ++it;
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it)
+ {
+ return utf8::unchecked::next(it);
+ }
+
+ template <typename octet_iterator>
+ uint32_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)
+ {
+ for (distance_type i = 0; 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)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::unchecked::next(first);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ 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
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ }
+ result = utf8::unchecked::append(cp, result);
+ }
+ return result;
+ }
+
+ 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::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);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::unchecked::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start < end)
+ (*result++) = utf8::unchecked::next(start);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
+ octet_iterator it;
+ public:
+ 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
+ {
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::unchecked::prior(it);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::unchecked::prior(it);
+ return temp;
+ }
+ }; // class iterator
+
+ } // namespace utf8::unchecked
+} // namespace utf8
+
+
+#endif // header guard
+
diff --git a/vmime-master/doc/book/.gitignore b/vmime-master/doc/book/.gitignore
new file mode 100644
index 0000000..5bb5584
--- /dev/null
+++ b/vmime-master/doc/book/.gitignore
@@ -0,0 +1,17 @@
+# PDFLatex
+*.log
+*.aux
+*.toc
+*.out
+*.pdf
+*.lo[flt]
+
+# Hevea
+*.haux
+*.htoc
+book.image.tex
+book.html
+
+images/Makefile2
+images/*.png
+
diff --git a/vmime-master/doc/book/basics.tex b/vmime-master/doc/book/basics.tex
new file mode 100644
index 0000000..94633ef
--- /dev/null
+++ b/vmime-master/doc/book/basics.tex
@@ -0,0 +1,823 @@
+\chapter{Basics}
+
+% ============================================================================
+\section{Reference counting}
+
+\subsection{Introduction} % --------------------------------------------------
+
+Since version 0.7.2cvs, VMime use smart pointers to simplify memory
+management. Smart pointers rely on
+RAII\footnote{Ressource Allocation is Initialisation} so that we do not need
+to bother with deleting an object (freeing memory) when it is not used
+anymore.
+
+There are two possibilities for owning a reference to an object. We can own a
+strong reference to an object: as long as we keep this reference, the object
+is not destroyed. Or we can own a weak reference to the object: the object can
+be destroyed if nobody owns a strong reference to it, in which case the weak
+reference becomes invalid.
+
+An object is destroyed as soon as the last strong reference to it is released.
+At the same tine, all weak references (if any) are automatically set to point
+to \vnull.
+
+In VMime, these two types of references are known as {\vcode vmime::shared\_ptr}
+and {\vcode vmime::weak\_ptr}, respectively.
+
+\vnote{since November 2013, we switched from an old, intrusive implementation
+of smart pointers to a more standard one: either Boost {\vcode shared\_ptr<>}
+implementation or standard C++ one if we are compiling in C++11. Here are the
+changes:
+
+{\vcode vmime::ref <>} is replaced with {\vcode vmime::shared\_ptr <>}
+
+{\vcode vmime::weak\_ref <>} is replaced with {\vcode vmime::weak\_ptr <>}
+
+{\vcode vmime::create <>} is replaced with {\vcode vmime::make\_shared <>}
+}
+
+\subsection{Instanciating reference-counted objects} % -----------------------
+
+In VMime, all objects that support reference counting inherit from the
+{\vcode vmime::object} class, which is responsible for
+incrementing/decrementing the counter and managing the object's life cycle.
+If you want to create a smart pointer to a new object instance, you should
+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 {
+
+public:
+
+ myObject(const vmime::string& name)
+ : m_name(name) {
+
+ }
+
+ void sayHello() {
+
+ std::cout << "Hello " << m_name << std::endl;
+ }
+
+private:
+
+ vmime::string m_name;
+};
+
+int main() {
+
+ vmime::shared_ptr <myObject> obj =
+ vmime::make_shared <myObject>("world");
+
+ obj->sayHello();
+
+ return 0;
+
+} // Here, 'obj' gets automatically destroyed
+\end{lstlisting}
+
+\subsection{Using smart pointers} % ------------------------------------------
+
+Smart pointers are copiable, assignable and comparable. You can use them like
+you would use normal ("raw") C++ pointers (eg. you can write
+\lstinline{!ptr, ptr != NULL, ptr->method(), *ptr}...).
+
+Type safety is also guaranteed, and you can type cast smart pointers using
+the {\vcode static\_cast()}, {\vcode dynamic\_cast()} and {\vcode const\_cast()}
+equivalents on {\vcode vmime::shared\_ptr} and {\vcode vmime::weak\_ptr} objects:
+
+\begin{lstlisting}[caption={Casting smart pointers}]
+class myBase : public vmime::object { }
+class myObject : public myBase { }
+
+vmime::shared_ptr <myObject> obj = vmime::make_shared <myObject>();
+
+// Implicit downcast
+vmime::shared_ptr <myBase> base = obj;
+
+// Explicit upcast
+vmime::shared_ptr <myObject> obj2 = vmime::dynamicCast <myObject>(base);
+\end{lstlisting}
+
+Weak references are used to resolve reference cycles (an object which refers
+directly or indirectly to itself). The following example illustrates a
+typical problem of reference counting:
+
+\begin{lstlisting}
+class parent : public vmime::object {
+
+public:
+
+ void createChild(vmime::shared_ptr <child> c) {
+
+ m_child = c;
+ }
+
+private:
+
+ vmime::shared_ptr <child> m_child;
+};
+
+class child : public vmime::object {
+
+public:
+
+ child(vmime::shared_ptr <parent> p)
+ : m_parent(p) {
+
+ }
+
+private:
+
+ vmime::shared_ptr <parent> m_parent;
+};
+
+int main() {
+
+ vmime::shared_ptr <parent> p = vmime::make_shared <parent>();
+ vmime::shared_ptr <child> c = vmime::make_shared <child>();
+
+ p->setChild(c);
+}
+\end{lstlisting}
+
+In this example, neither {\vcode p} nor {\vcode c} will be deleted when
+exiting {\vcode main()}. That's because {\vcode p} indirectly points to itself
+{\em via} {\vcode c}, and {\em vice versa}. The solution is to use a weak
+reference to the parent:
+
+\begin{lstlisting}
+vmime::weak_ptr <parent> m_parent;
+\end{lstlisting}
+
+The decision to make the parent or the child a weak reference is purely
+semantic, and it depends on the context and the relationships between the
+objects. Note that when the parent is deleted, the {\vcode m\_parent} member
+of the child points to \vnull.
+
+More information about reference counting can be found on
+Wikipedia\footnote{http://en.wikipedia.org/wiki/Reference\_counting}.
+
+% ============================================================================
+\section{Error handling}
+
+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 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.
+
+VMime exceptions support chaining: an exception can be encapsulated into
+another exception to hide implementation details. The function
+{\vcode exception::other()} returns the next exception in the chain,
+or \vnull.
+
+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) {
+
+ os << "* vmime::exceptions::" << e.name() << std::endl;
+ os << " what = " << e.what() << std::endl;
+
+ // Recursively print all encapsuled exceptions
+ if (e.other() != NULL) {
+ os << *e.other();
+ }
+
+ return os;
+}
+
+...
+
+try {
+
+ // ...some call to VMime...
+
+} catch (vmime::exception& e) {
+
+ std::cerr << e; // VMime exception
+
+} catch (std::exception& e) {
+
+ std::cerr << e.what(); // standard exception
+}
+\end{lstlisting}
+
+Read the source of {\vexample example6} if yo want to see a more complete
+example of using VMime exceptions (such as getting more detailed information
+by using specialized classes of {\vcode vmime::exception}).
+
+
+% ============================================================================
+\section{Basic objects}
+
+\subsection{The {\vcode component} class} % ----------------------------------
+
+In VMime, all the components of a message inherit from the same class
+{\vcode component}. This includes the message itself (classes {\vcode message}
+and {\vcode bodyPart}), the header, the header fields and the value of each
+header field, the body and all the parts in the message.
+
+The class component provide a common interface for parsing or generating all
+these components (methods {\vcode parse()} and {\vcode generate()}). It also
+provides additional functions to get some information about the parsing
+process or the structure (methods {\vcode getParsedOffset()},
+{\vcode getParsedLength()} and {\vcode getChildComponents()}).
+
+VMime also provides a set of classes corresponding to the basic types found
+in a message; for example a mailbox, a mailbox list, date/time information,
+media type, etc. They all inherit from {\vcode component} too.
+
+\subsection{Date and time} % -------------------------------------------------
+
+Date and time are used in several places in VMime, particularly in header
+fields (Date, Received, ...). VMime fully supports RFC-2822's date and time
+specification. The object {\vcode vmime::datetime} is used to manipulate date
+and time information, and to parse/generate it from/to RFC-2822 format.
+
+The following code snippet show various manners of using the
+{\vcode vmime::datetime} object:
+
+\begin{lstlisting}[caption={Using {\vcode vmime::datetime} object}]
+// Creating from string in RFC-2822 format
+vmime::datetime d1("Sat, 08 Oct 2005 14:07:52 +0200");
+
+// Creating from components
+vmime::datetime d2(
+ /* date */ 2005, vmime::datetime::OCTOBER, 8,
+ /* time */ 14, 7, 52,
+ /* zone */ vmime::datetime::GMT2
+);
+
+// Getting day of week
+const int dow = d2.getWeekDay(); // 'dow' should be datetime::SATURDAY
+\end{lstlisting}
+
+\subsection{Media type} % ----------------------------------------------------
+
+In MIME, the nature of the data contained in parts is identified using a
+media type. A general type (eg. \emph{image}) and a sub-type (eg. \emph{jpeg})
+are put together to form a media type (eg. \emph{image/jpeg}). This is also
+called the MIME type.
+
+There are a lot of media types officially registered, and vendor-specific
+types are possible (they start with ``x-'', eg.
+\emph{application/x-zip-compressed}).
+
+In VMime, the object {\vcode vmime::mediaType} represents a media type. There
+are also some constants for top-level types and sub-types in the
+{\vcode vmime::mediaTypes} namespace. For example, you can instanciate a new
+media type with:
+
+\begin{lstlisting}
+vmime::mediaType theType(
+ /* top-level type */ vmime::mediaTypes::IMAGE,
+ /* sub-type */ vmime::mediaTypes::IMAGE_JPEG
+);
+
+// theType.getType() is "image"
+// theType.getSubType() is "jpeg"
+// theType.generate() returns "image/jpeg"
+\end{lstlisting}
+
+For more information about media types, see
+RFC-2046\footnote{http://www.faqs.org/rfcs/rfc2046.html}.
+
+\subsection{Mailbox and mailbox groups} % ------------------------------------
+
+VMime provides several objects for working with mailboxes and addresses.
+
+The {\vcode vmime::address} class is an abstract type for representing an
+address: it can be either a mailbox (type {\vcode vmime::mailbox}) or a
+mailbox group (type {\vcode vmime::mailboxGroup}). A mailbox is composed of
+an email address (mandatory) and possibly a name. A mailbox group is simply
+a named list of mailboxes (see Figure \ref{uml_addr_mbox_mboxgroup}).
+
+\begin{lstlisting}[caption={Using mailboxes and mailbox groups}]
+vmime::shared_ptr <vmime::mailbox> mbox1 = vmime::make_shared <vmime::mailbox>
+ (/* name */ vmime::text("John Doe"), /* email */ "john.doe@acme.com");
+vmime::shared_ptr <vmime::mailbox> mbox2 = vmime::make_shared <vmime::mailbox>
+ (/* no name, email only */ "bill@acme.com");
+
+vmime::shared_ptr <vmime::mailboxGroup> grp = vmime::make_shared <vmime::mailboxGroup>();
+grp->appendMailbox(mbox1);
+grp->appendMailbox(mbox2);
+\end{lstlisting}
+
+\begin{figure}[ht!]
+ \center\includegraphics[width=0.7\textwidth]
+ {images/address-mailbox-mailboxgroup.png}\endcenter
+ \caption{Diagram for address-related classes}
+ \label{uml_addr_mbox_mboxgroup}
+\end{figure}
+
+
+% ============================================================================
+\section{Message, body parts and header}
+
+\subsection{Introduction to MIME messages} % ---------------------------------
+
+A MIME message is a recursive structure in which each part can contains one
+or more parts (or \emph{entities}). Each part is composed of a header and
+a body (actual contents). Figure \ref{uml_msg_body_header} shows how this
+model is implemented in VMime, and all classes that take part in it.
+
+\begin{figure}
+ \center\includegraphics[width=1.0\textwidth]
+ {images/message-body-header.png}\endcenter
+ \caption{Overall structure of MIME messages}
+ \label{uml_msg_body_header}
+\end{figure}
+
+
+\subsection{Header and header fields} % --------------------------------------
+
+\subsubsection{Standard header fields} % .....................................
+
+Header fields carry information about a message (or a part) and its contents.
+Each header field has a name and a value. All types that can be used as a
+field value inherit from the {\vcode headerFieldValue} class.
+
+You cannot instanciate header fields directly using their constructor.
+Instead, you should use the {\vcode headerFieldFactory} object. This ensures
+the right field type and value type is used for the specified field name.
+For more information about how to use header fields and the factory, see
+section \ref{msg-building-simple-message}.
+
+Some standard fields are officially registered and have their value type
+specified in a RFC. Table \ref{standard-fields} lists all the fields
+registered by default in VMime and the value type they contains.
+
+By default, all unregistered fields have a value of type {\vcode text}.
+
+\begin{table}[!ht]
+\begin{center}
+\noindent\begin{tabularx}{0.85\textwidth}{|X|X|}
+\hline
+ {\bf Field Name} &
+ {\bf Value Type} \\
+\hline
+\hline
+From & mailbox \\
+To & addressList \\
+Cc & addressList \\
+Bcc & addressList \\
+Sender & mailbox \\
+Date & datetime \\
+Received & relay \\
+Subject & text \\
+Reply-To & mailbox \\
+Delivered-To & mailbox \\
+Organization & text \\
+Return-Path & path \\
+Mime-Version & text \\
+Content-Type & mediaType \\
+Content-Transfer-Encoding & encoding \\
+Content-Description & text \\
+Content-Disposition & contentDisposition \\
+Content-Id & messageId \\
+Content-Location & text \\
+Message-Id & messageId \\
+In-Reply-To & messageIdSequence \\
+References & messageIdSequence \\
+Original-Message-Id & messageId \\
+Disposition & disposition \\
+Disposition-Notification-To & mailboxList \\
+\hline
+\end{tabularx}
+\end{center}
+\label{standard-fields}
+\caption{Standard fields and their types}
+\end{table}
+
+
+\subsubsection{Parameterized fields} % .......................................
+
+In addition to a value, some header fields can contain one or more
+\emph{name=value} couples which are called \emph{parameters}. For example,
+this is used in the \emph{Content-Type} field to give more information about
+the content:
+
+\begin{verbatim}
+ Content-Type: text/plain; charset="utf-8"
+\end{verbatim}
+
+Fields that support parameters inherit from the
+{\vcode parameterizedHeaderField} class which provides methods to deal with
+these parameters: {\vcode appendParameter()}, {\vcode getParameterAt()}...
+
+A parameter is identified by a name (eg. \emph{charset}) and associated to
+a value of type {\vcode vmime::text}. Parameters provide helper functions to
+convert automatically from basic types to text, and \emph{vice versa}. The
+following example illustrates it:
+
+\begin{lstlisting}[caption={Getting and setting parameter value in fields}]
+vmime::shared_ptr <vmime::parameterizedField> field =
+ header->findField <vmime::parameterizedField>("X-Field-That-Contains-Parameters");
+
+// Use setValue() to convert from a basic type to 'text'
+vmime::shared_ptr <vmime::parameter> prm = field->getParameter("my-date-param");
+prm->setValue(vmime::datetime::now());
+
+// Use getValueAs() to convert from 'text' to a basic type
+prm = field->getParameter("my-charset-param");
+const vmime::charset ch = prm->getValueAs <vmime::charset>();
+\end{lstlisting}
+
+Some fields provide easy access to their standard parameters (see
+Table \ref{standard-prm-fields}). This avoids finding the parameter and
+\emph{dynamic-casting} its value to the right type. The following code
+illustrates how to use it:
+
+\begin{lstlisting}
+vmime::shared_ptr <vmime::contentTypeField> field =
+ header->getField <vmime::contentTypeField>(vmime::fields::CONTENT_TYPE);
+
+// 1. First solution: the "hard" way
+vmime::shared_ptr <vmime::parameter> prm = field->findParameter("charset");
+const charset ch1 = prm->getValueAs <vmime::charset>();
+
+// 2. Second solution: the simple way
+const charset ch2 = field->getCharset();
+\end{lstlisting}
+
+\vnote{In both cases, an exception {\vcode no\_such\_parameter} can be
+thrown if the parameter does not exist, so be sure to catch it.}
+
+\begin{table}[ht!]
+\begin{center}
+\noindent\begin{tabularx}{0.85\textwidth}{|l|l|X|}
+\hline
+ {\bf Field Name} &
+ {\bf Field Type} &
+ {\bf Parameters} \\
+\hline
+\hline
+Content-Type & contentTypeField & boundary, charset, report-type \\
+\hline
+Content-Disposition & contentDispositionField & creation-date,
+modification-date, read-date, filename, size \\
+\hline
+\end{tabularx}
+\end{center}
+\label{standard-prm-fields}
+\caption{Standard parameterized fields}
+\end{table}
+
+
+
+% ============================================================================
+\section{Streams}
+
+\subsection{Streams and stream adapters} % -----------------------------------
+
+Streams permit reading or writing data whatever the underlying system is:
+a file on a hard disk, a socket connected to a remote service...
+
+There are two types of streams: input streams (from which you can read data)
+and output streams (in which you can write data). Some adapters are provided
+for compatibility and convenience, for example:
+
+\begin{itemize}
+\item {\vcode inputStreamAdapter} and {\vcode outputStreamAdapter}: allow
+to use standard C++ iostreams with VMime;
+\item {\vcode inputStreamStringAdapter} and
+{\vcode outputStreamStringAdapter}: use a {\vcode vmime::string} object to
+read/write data.
+\end{itemize}
+
+The following example shows two ways of writing the current date to the
+standard output, using stream adapters:
+
+\begin{lstlisting}[caption={Using stream adapters}]
+// Get current date and time
+const vmime::datetime date = vmime::datetime::now();
+
+// 1. Using outputStreamAdapter
+vmime::utility::outputStreamAdapter out(std::cout);
+
+std::cout << "Current date is: ";
+date.generate(out);
+std::cout << std::endl;
+
+// 2. Using outputStreamStringAdapter
+vmime::string dateStr;
+vmime::utility::outputStreamStringAdapter outStr(dateStr);
+
+date.generate(outStr);
+
+std::cout << "Current date is: " << dateStr << std::endl;
+\end{lstlisting}
+
+
+\subsection{Stream filters} % ------------------------------------------------
+
+Input and output streams can be filtered to perform inline conversions (for
+example, there is a filter to convert ``{\textbackslash}r{\textbackslash}n''
+sequences to ``{\textbackslash}n''). They inherit from
+{\vcode vmime::utility::filteredInputStream} or
+{\vcode vmime::utility::filteredOutputStream} and are used like adapters (some
+filters also accept parameters; read the documentation).
+
+The most useful filter in VMime (and probably the only one you will need) is
+the {\vcode charsetFilteredOutputStream}, which performs inline conversion
+of charsets. See \ref{section_charsets} to know how to use it.
+
+\vnote{After you have finished to use a filtered output stream, it is
+important to call {\vcode flush()} on it to flush the internal buffer.
+If {\vcode flush()} is not called, not all data may be written to the
+underlying stream.}
+
+
+% ============================================================================
+\section{Content handlers}
+
+\subsection{Introduction} % --------------------------------------------------
+
+Content handlers are an abstraction for data sources. They are currently used
+when some data need to be stored for later use (eg. body part contents,
+attachment data, ...). Data can be stored encoded or unencoded (for more
+information about encodings, see \ref{section_encodings}).
+
+\subsection{Extracting data from content handlers} % -------------------------
+
+You can extract data in a content handler using the {\vcode extract()} method
+(which automatically decodes data if encoded) or {\vcode extractRaw()} (which
+extracts data without perfoming any decoding).
+
+The following example shows how to extract the body text from a message, and
+writing it to the standard output with charset conversion:
+
+\begin{lstlisting}[caption={Using content handlers to extract body text from
+a message}]
+// Suppose we already have a message
+vmime::shared_ptr <vmime::message> msg;
+
+// Obtains a reference to the body contents
+vmime::shared_ptr <vmime::body> body = msg->getBody();
+vmime::shared_ptr <vmime::contentHandler> cts = body->getContents();
+
+vmime::utility::outputStreamAdapter out(std::cout);
+cts->extract(out);
+\end{lstlisting}
+
+\vnote{The body contents is extracted ``as is''. No charset conversion is
+performed. See \ref{section_charsets} to know more about conversion between
+charsets.}
+
+
+\subsection{Creating content handlers} % -------------------------------------
+
+When you are building a message, you may need to instanciate content handlers
+if you want to set the contents of a body part. The following code snippet
+shows how to set the body text of a part from a string:
+
+\begin{lstlisting}[caption={Setting the contents of a body part}]
+vmime::shared_ptr <vmime::bodyPart> part; // suppose we have a body part
+
+// Create a new content handler from a string
+vmime::shared_ptr <vmime::contentHandler> cth =
+ vmime::make_shared <vmime::stringContentHandler>("Put body contents here");
+
+// Set the contents
+part->getBody()->setContents(cth);
+\end{lstlisting}
+
+Content handlers are also used when creating attachments. The following
+example illustrates how to create an attachment from a file:
+
+\begin{lstlisting}[caption={Creating an attachment from a file}]
+// Create a stream from a file
+std::ifstream* fileStream = new std::ifstream();
+
+fileStream->open("/home/vincent/paris.jpg", std::ios::binary);
+
+if (!*fileStream) {
+ // handle error
+}
+
+vmime::shared_ptr <utility::stream> dataStream =
+ vmime::make_shared <vmime::utility::inputStreamPointerAdapter>(fileStream);
+
+ // NOTE: 'fileStream' will be automatically deleted
+ // when 'dataStream' is deleted
+
+// Create a new content handler
+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")
+);
+\end{lstlisting}
+
+You will see later that the {\vcode vmime::fileAttachment} class already
+encapsulates all the mechanics to create an attachment from a file.
+
+
+% ============================================================================
+\section{Character sets, charsets and conversions\label{section_charsets}}
+
+Quoting from RFC-2278: \emph{`` The term 'charset' is used to refer to a
+method of converting a sequence of octets into a sequence of characters.''}
+
+With the {\vcode vmime::charset} object, VMime supports conversion between
+charsets using the {\em iconv} library, which is available on almost all
+existing platforms. See {\vcode vmime::charset} and
+{\vcode vmime::charsetConverter} in the class documentation to know more
+about charset conversion.
+
+The following example shows how to convert data in one charset to another
+charset. The data is extracted from the body of a message and converted
+to UTF-8 charset:
+
+\begin{lstlisting}[caption={Extracting and converting body contents to a
+specified charset}]
+vmime::shared_ptr <vmime::message> msg; // we have a message
+
+// Obtain the content handler first
+vmime::shared_ptr <vmime::body> body = msg->getBody();
+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(),
+ /* dest charset */ vmime::charset("utf-8"),
+ /* dest stream */ out
+);
+
+cth->extract(fout);
+
+fout.flush(); // Very important!
+\end{lstlisting}
+
+
+% ============================================================================
+\section{Non-ASCII text in header fields}
+
+MIME standard defines methods\footnote{See RFC-2047: Message Header Extensions
+for Non-ASCII Text} for dealing with data which is not 7-bit only (ie. the
+ASCII character set), in particular in header fields. For example, the field
+``Subject:'' use this data type.
+
+VMime is fully compatible with RFC-2047 and provides two objects for
+manipulating 8-bit data: {\vcode vmime::text} and {\vcode vmime::word}. A word
+represents textual information encoded in a specified charset. A text is
+composed of one or more words.
+
+RFC-2047 describes the process of encoding 8-bit data into a 7-bit form;
+basically, it relies on Base64 and Quoted-Printable encoding. Hopefully, all
+the encoding/decoding process is done internally by VMime, so creating text
+objects is fairly simple:
+
+\begin{lstlisting}[caption={Creating \vcode{vmime::text} objects}]
+vmime::string inText = "Linux dans un téléphone mobile";
+vmime::charset inCharset = "utf-8";
+
+vmime::text outText;
+outText.createFromString(inText, inCharset);
+
+// 'outText' now contains 3 words:
+// . <us-ascii> "Linux dans un "
+// . <utf-8> "téléphone "
+// . <us-ascii> "mobile"
+
+vmime::shared_ptr <vmime::header> header = myMessage->getHeader();
+header->Subject()->setValue(outText);
+\end{lstlisting}
+
+In general, you will not need to decode RFC-2047-encoded data as the process
+is totally transparent in VMime. If you really have to, you can use the
+{\vcode vmime::text::decodeAndUnfold()} static method to create a text object
+from encoded data.
+
+For example, say you have the following encoded data:
+
+\begin{verbatim}
+ Linux dans un =?UTF-8?B?dMOpbMOpcGhvbmUgbW9iaWxl?=
+\end{verbatim}
+
+You can simply decode it using the following code:
+
+\begin{lstlisting}[caption={Decoding RFC-2047-encoded data}]
+vmime::string inData =
+ "Linux dans un =?UTF-8?B?dMOpbMOpcGhvbmUgbW9iaWxl?=";
+
+vmime::text outText;
+vmime::text::decodeAndUnfold(inData, &outText);
+\end{lstlisting}
+
+{\vcode vmime::text} also provides a function to convert all the words to
+another charset in a single call. The following example shows how to convert
+text stored in the Subject field of a message:
+
+\begin{lstlisting}[caption={Converting data in a {\vcode vmime::text} to a
+specified charset}]
+vmime::shared_ptr <vmime::message> msg; // we have a message
+
+vmime::text subject = msg->getHeader()->Subject()->getValue();
+
+const vmime::string subjectText =
+ subject.getConvertedText(vmime::charset("utf-8"));
+
+// 'subjectText' now contains the subject in UTF-8 encoding
+\end{lstlisting}
+
+
+% ============================================================================
+\section{Encodings\label{section_encodings}}
+
+\subsection{Introduction} % --------------------------------------------------
+
+The MIME standard defines a certain number of encodings to allow data
+to be safely transmitted from one peer to another. VMime provides
+data encoding and decoding using the {\vcode vmime::utility::encoder::encoder} object.
+
+You should not need to use encoders directly, as all encoding/decoding
+process is handled internally by the library, but it is good to know
+they exist and how they work.
+
+\subsection{Using encoders} % ------------------------------------------------
+
+You can create an instance of an encoder using the 'vmime::utility::encoder::encoderFactory'
+object, giving the encoding name ({\it base64}, {\it quoted-printable}, ...).
+The following example creates an instance of the Base64 encoder to encode
+some data:
+
+\begin{lstlisting}[caption={A simple example of using an encoder}]
+vmime::shared_ptr <vmime::utility::encoder::encoder> enc =
+ vmime::utility::encoder::encoderFactory::getInstance()->create("base64");
+
+vmime::string inString("Some data to encode");
+vmime::utility::inputStreamStringAdapter in(inString);
+
+vmime::string outString;
+vmime::utility::outputStreamStringAdapter out(outString);
+
+enc->encode(in, out);
+
+std::cout << "Encoded data is:" << outString << std::endl;
+\end{lstlisting}
+
+\subsection{Enumerating available encoders} % --------------------------------
+
+The behaviour of the encoders can be configured using properties. However,
+not all encoders support properties. The following example\footnote{This is
+an excerpt from {\vexample example6}} enumerates available encoders and the
+supported properties for each of them:
+
+\begin{lstlisting}[caption={Enumerating encoders and their properties}]
+vmime::shared_ptr <vmime::utility::encoder::encoderFactory> ef =
+ vmime::utility::encoder::encoderFactory::getInstance();
+
+std::cout << "Available encoders:" << std::endl;
+
+for (int i = 0 ; i < ef->getEncoderCount() ; ++i) {
+
+ // Output encoder name
+ vmime::shared_ptr <const vmime::utility::encoder::encoderFactory::registeredEncoder>
+ enc = ef->getEncoderAt(i);
+
+ std::cout << " * " << enc->getName() << std::endl;
+
+ // Create an instance of the encoder to get its properties
+ vmime::shared_ptr <vmime::utility::encoder::encoder> e = enc->create();
+
+ std::vector <vmime::string> props = e->getAvailableProperties();
+ std::vector <vmime::string>::const_iterator it;
+
+ for (it = props.begin() ; it != props.end() ; ++it) {
+ std::cout << " - " << *it << std::endl;
+ }
+\end{lstlisting}
+
+
+% ============================================================================
+\section{Progress listeners}
+
+Progress listeners are used with objects that can notify you about the state
+of progress when they are performing an operation.
+
+The {\vcode vmime::utility::progressListener} interface is rather simple:
+
+\begin{lstlisting}
+void start(const int predictedTotal);
+void progress(const int current, const int currentTotal);
+void stop(const int total);
+\end{lstlisting}
+
+{\vcode start()} and {\vcode stop()} are called at the beginning and the end
+of the operation, respectively. {\vcode progress()} is called each time the
+status of progress changes (eg. a chunk of data has been processed). There is
+no unit specified for the values passed in argument. It depends on the
+notifier: it can be bytes, percent, number of messages...
diff --git a/vmime-master/doc/book/book.tex b/vmime-master/doc/book/book.tex
new file mode 100644
index 0000000..4db213a
--- /dev/null
+++ b/vmime-master/doc/book/book.tex
@@ -0,0 +1,118 @@
+\documentclass[11pt]{report}
+
+\title{{\Huge VMime Book} \\ \ \\ A Developer's Guide To VMime}
+\author{Vincent Richard \\ vincent@vmime.org}
+
+\usepackage{graphicx}
+\usepackage{tabularx}
+\usepackage{array}
+\usepackage{listings}
+\usepackage[usenames]{color}
+\usepackage{ucs}
+\usepackage[utf8x]{inputenc}
+\usepackage[vcentering,dvips]{geometry}
+%\usepackage{type1cm} % scalable Computer Modern fonts
+\usepackage{courier} % use Adobe Courier instead of Computer Modern Typewriter
+\usepackage{fancyheadings}
+\usepackage{hyperref}
+\usepackage{verbatim}
+\usepackage{footmisc}
+
+
+\setcounter{secnumdepth}{10}
+\setcounter{tocdepth}{10}
+
+\def\vcode{\tt}
+\def\vnull{{\tt NULL}}
+\newcommand{\vnote}[1]{{\sc note:} #1}
+\def\vexample{\tt\sc}
+\newcommand{\verti}[1]{\rotatebox{90}{#1\ }} % vertical text
+\def\vdot{$\bullet$}
+
+\sloppy % Disable "overfull \hbox..." warnings
+
+\newcommand{\Chapter}[1]{\chapter{#1} \setcounter{figure}{1}}
+
+% 'listings' configuration
+\definecolor{listingFrame}{rgb}{0.9,0.9,0.9}
+\lstset{language=C++,showstringspaces=false}
+\lstset{keywordstyle=\bf,commentstyle=\it}
+\lstset{captionpos=b,extendedchars=true,inputencoding=latin1}
+\lstset{fontadjust=true,basewidth={0.5em,0.4em},columns=fixed,flexiblecolumns=false}
+\lstset{frame=leftline,framerule=0.1cm,framesep=0.3cm,rulecolor=\color{listingFrame}}
+\lstset{abovecaptionskip=0.5cm,xleftmargin=1.1cm,aboveskip=0.5cm,belowskip=0.2cm}
+
+% 'hyperref' configuration
+\hypersetup{
+ backref=true,pagebackref=true,hyperindex=rue,colorlinks=true,
+ breaklinks=true,urlcolor=blue,linkcolor=black,bookmarks=true,bookmarksopen=true
+}
+
+% HTML output configuration
+%HEVEA\renewcommand{\includegraphics}[2][]{\imgsrc{#2}}
+%HEVEA\renewcommand{\verti}[1]{#1}
+%HEVEA\def\vdot{\bullet}
+%HEVEA\newcommand{\linespread}{}
+%HEVEA\newcommand{\clubpenalty}{}
+%HEVEA\newcommand{\widowpenalty}{}
+%HEVEA\newcommand{\geometry}{}
+
+
+% Page layout
+\geometry{papersize={210mm,297mm},total={160mm,230mm}}
+
+% Text layout
+\setlength{\skip\footins}{1cm} % margin between text and footnotes
+\clubpenalty=1000
+\addtolength{\parskip}{+0.3cm}
+\linespread{1.05}
+\widowpenalty=1000
+
+
+\begin{document}
+
+% Title page
+\maketitle
+\newpage
+
+% Table of contents
+\tableofcontents
+\newpage
+
+% Chapters
+\include{intro}
+\include{building}
+\include{start}
+\include{basics}
+\include{msg}
+\include{net}
+
+\thispagestyle{empty}
+\ \newpage
+
+
+%HEVEA\begin{comment}
+
+% List of listings
+\lstlistoflistings
+\addcontentsline{toc}{chapter}{Listings}
+
+% List of figures
+\listoffigures
+\addcontentsline{toc}{chapter}{List of figures}
+
+% List of table
+\listoftables
+\addcontentsline{toc}{chapter}{List of tables}
+
+%HEVEA\end{comment}
+
+
+% Appendixes
+\appendix
+
+\chapter{The GNU General Public License\label{appendix_license}}
+\verbatiminput{../../COPYING}
+
+\end{document}
+
diff --git a/vmime-master/doc/book/building.tex b/vmime-master/doc/book/building.tex
new file mode 100644
index 0000000..9feeedc
--- /dev/null
+++ b/vmime-master/doc/book/building.tex
@@ -0,0 +1,175 @@
+\label{chapter_building}
+\chapter{Building and Installing VMime}
+
+% ============================================================================
+\section{Introduction}
+
+If no pre-build packages of VMime is available for your system, or if for some
+reason you want to compile it yourself from scratch, this section will guide
+you through the process.
+
+% ============================================================================
+\section{What you need}
+
+To build VMime from the sources, you will need the following:
+
+\begin{itemize}
+\item a working C++ compiler with good STL implementation and also a good
+support for templates (for example, \href{http://gcc.gnu.org/}{GNU GCC}) ;
+\item \href{http://www.cmake.org/}{CMake} build system ;
+\item either \href{http://www.icu-project.org}{ICU library} or an usable
+{\vcode iconv()} implementation (see
+\href{http://www.gnu.org/software/libiconv/}{libiconv of GNU Project}) ;
+\item the \href{http://www.gnu.org/software/gsasl/}{GNU SASL Library} if you
+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 ;
+\end{itemize}
+
+% ============================================================================
+\section{Obtaining source files}
+
+You can download a package containing the source files of the latest release
+of the VMime library from the \href{http://www.vmime.org/}{VMime web site}.
+
+You can also obtain the current development version from the Git repository,
+which is currently hosted at GitHub. It can be checked out through anonymous
+access with the following instruction:
+
+\begin{verbatim}
+ git clone git://github.com/kisli/vmime
+\end{verbatim}
+
+% ============================================================================
+\section{Compiling and installing}
+
+VMime relies on CMake for building. CMake is an open source, cross-platform
+build system. It will generate all build scripts required to compile VMime on
+your platform.
+
+First, extract the tarball or checkout the VMime source code into a directory
+somewhere on your system, let's call it {\vcode /path/to/vmime-source}. Then,
+create a build directory, which will contain all intermediate build files and
+the final libraries, let's call it {\vcode /path/to/vmime-build}.
+
+From the build directory, run {\vcode cmake} with the {\vcode -G} argument
+corresponding to your platform/choice. For example, if you are on a
+Unix-compatible platform (like GNU/Linux or MacOS) and want to use the
+{\vcode make} utility for building, type:
+
+\begin{verbatim}
+ $ cd /path/to/vmime-build
+ $ cmake -G "Unix Makefiles" /path/to/vmime-source
+\end{verbatim}
+
+CMake will perform some tests on your system to check for libs installed
+and some platform-specific includes, and create all files needed for
+compiling the project. Additionally, a {\vcode src/vmime/config.hpp} file
+with the parameters detected for your system will be created.
+
+Next, you can start the compilation process:
+
+\begin{verbatim}
+ $ cmake --build .
+\end{verbatim}
+
+Please wait a few minutes while the compilation runs (you should have some
+time to have a coffee right now!). If you get errors during the compilation,
+be sure your system meet the requirements given at the beginning of the
+chapter. You can also try to get a newer version (from the Git repository, for
+example) or to get some help on VMime user forums.
+
+If everything compiled successfully, you can install the library and
+the development files on your system:
+
+\begin{verbatim}
+ # make install
+\end{verbatim}
+
+\vnote{you must do that with superuser rights (root) if you chose to install
+the library into the default location (ie: /usr/lib and /usr/include).}
+
+Now, you are done! You can jump to the next chapter to know how to use VMime
+in your program...
+
+
+% ============================================================================
+\section{\label{custom-build}Customizing build}
+
+You should not modify the {\vcode config.hpp} file directly. Instead, you
+should run {\vcode cmake} again, and specify your build options on the command
+line. For example, to force using OpenSSL library instead of GnuTLS for TLS
+support, type:
+
+\begin{verbatim}
+ $ cmake -G "Unix Makefiles" -DVMIME_TLS_SUPPORT_LIB=openssl
+\end{verbatim}
+
+If you want to enable or disable some features in VMime, you can obtain some
+help by typing {\vcode cmake -L}. The defaults should be OK though. For a
+complate list of build options, you can also refer to section
+\ref{build-options}, page \pageref{build-options}. For more information about
+using CMake, go to \href{http://www.cmake.org/}{the CMake web site}.
+
+\vnote{Delete the {\vcode CMakeCache.txt} file if you changed configuration
+or if something changed on your system, as CMake may cache some values to
+speed things up.}
+
+You can also use another build backend, like
+Ninja\footnote{\url{https://ninja-build.org/}}, if you have it on your system:
+
+\begin{verbatim}
+ $ cd /path/to/vmime-build
+ $ cmake -G Ninja /path/to/vmime-source
+ $ ninja
+ # ninja install
+\end{verbatim}
+
+To install VMime in a directory different from the default directory
+({\vcode /usr} on GNU/Linux systems), set the
+{\vcode CMAKE\_INSTALL\_PREFIX} option:
+
+\begin{verbatim}
+ $ cmake -DCMAKE_INSTALL_PREFIX=/opt/ ...
+\end{verbatim}
+
+
+% ============================================================================
+\section{\label{build-options}Build options}
+
+Some options can be given to CMake to control the build:
+
+\begin{table}[!ht]
+\noindent\begin{tabularx}{1.0\textwidth}{|l|X|}
+\hline
+ {\bf Option name} &
+ {\bf Description} \\
+\hline
+\hline
+VMIME\_BUILD\_SHARED\_LIBRARY &
+Set to ON to build a shared version (.so) of the library (default is ON). \\
+\hline
+VMIME\_BUILD\_STATIC\_LIBRARY &
+Set to ON to build a static version (.a) of the library (default is ON). \\
+\hline
+VMIME\_BUILD\_TESTS &
+Set to ON to build unit tests (default is OFF). \\
+\hline
+VMIME\_TLS\_SUPPORT\_LIB &
+Set to either "openssl" or "gnutls" to force using either OpenSSL or GNU TLS
+for SSL/TLS support (default depends on which libraries are available on
+your system). \\
+\hline
+VMIME\_CHARSETCONV\_LIB &
+Set to either "iconv", "icu" or "win" (Windows only) to force using iconv, ICU
+or Windows built-in API for converting between charsets (default value depends
+on which libraries are available on your system). \\
+\hline
+CMAKE\_BUILD\_TYPE &
+Set the build type: either "Release" or "Debug". In Debug build, optimizations
+are disabled and debugging information are enabled. \\
+\hline
+\end{tabularx}
+\caption{CMake build options}
+\end{table}
diff --git a/vmime-master/doc/book/images/address-mailbox-mailboxgroup.svg b/vmime-master/doc/book/images/address-mailbox-mailboxgroup.svg
new file mode 100644
index 0000000..a7752d4
--- /dev/null
+++ b/vmime-master/doc/book/images/address-mailbox-mailboxgroup.svg
@@ -0,0 +1,355 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="453.27998pt"
+ height="307.89001pt"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.42.2"
+ sodipodi:docbase="/home/vincent/projects/vmime/doc/book/images"
+ sodipodi:docname="address-mailbox-mailboxgroup.svg"
+ inkscape:export-xdpi="73.779999"
+ inkscape:export-ydpi="73.779999">
+ <defs
+ id="defs3">
+ <marker
+ inkscape:stockid="Torso"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Torso"
+ style="overflow:visible">
+ <g
+ id="g2045"
+ transform="scale(0.7)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path1128"
+ d="M -4.7792281,-3.2395420 C -2.4288541,-2.8736027 0.52103922,-1.3019943 0.25792722,0.38794346 C -0.0051877922,2.0778819 -2.2126741,2.6176539 -4.5630471,2.2517169 C -6.9134221,1.8857769 -8.5210350,0.75201414 -8.2579220,-0.93792336 C -7.9948090,-2.6278615 -7.1296041,-3.6054813 -4.7792281,-3.2395420 z "
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;marker-start:none;marker-mid:none;marker-end:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path1909"
+ d="M 4.4598789,0.088665736 C -2.5564571,-4.3783320 5.2248769,-3.9061806 -0.84829578,-8.7197331"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-end:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path1910"
+ d="M 4.9298719,0.057520736 C -1.3872731,1.7494689 1.8027579,5.4782079 -4.9448731,7.5462725"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" />
+ <rect
+ transform="matrix(0.527536,-0.849533,0.887668,0.460484,0.000000,0.000000)"
+ y="-1.7408575"
+ x="-10.391706"
+ height="2.7608147"
+ width="2.6366582"
+ id="rect2035"
+ style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" />
+ <rect
+ transform="matrix(0.671205,-0.741272,0.790802,0.612072,0.000000,0.000000)"
+ y="-7.9629307"
+ x="4.9587269"
+ height="2.8614161"
+ width="2.7327356"
+ id="rect2036"
+ style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" />
+ <path
+ transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,25.96648,19.71619)"
+ d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z"
+ sodipodi:ry="0.60731727"
+ sodipodi:rx="0.60731727"
+ sodipodi:cy="-28.685045"
+ sodipodi:cx="16.172634"
+ id="path2037"
+ style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,26.82450,16.99126)"
+ d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z"
+ sodipodi:ry="0.60731727"
+ sodipodi:rx="0.60731727"
+ sodipodi:cy="-28.685045"
+ sodipodi:cx="16.172634"
+ id="path2038"
+ style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none"
+ sodipodi:type="arc" />
+ </g>
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path5324"
+ d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="1.0000000"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.0000000"
+ inkscape:cx="248.49444"
+ inkscape:cy="298.91345"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1150"
+ inkscape:window-height="986"
+ inkscape:window-x="0"
+ inkscape:window-y="30"
+ fill="#ff0000"
+ inkscape:showpageshadow="true"
+ showguides="true"
+ showgrid="false"
+ inkscape:grid-bbox="false"
+ inkscape:grid-points="false" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/SourceCode" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <path
+ id="path5442"
+ d="M 303.65293,104.37647 L 303.65293,173.68448"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path5440"
+ d="M 462.39333,172.39335 L 462.39333,240.10630"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path5438"
+ d="M 139.24323,172.39335 L 139.24323,240.10630"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
+ d="M 257.32713,293.92642 L 392.05898,293.92642"
+ id="path2543" />
+ <rect
+ style="fill:#e0f5cc;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect1291"
+ width="132.69368"
+ height="105.95705"
+ x="237.85556"
+ y="13.003311" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="245.51651"
+ y="55.887268"
+ id="text1293"
+ sodipodi:linespacing="125.00000%"><tspan
+ sodipodi:role="line"
+ id="tspan2242"
+ x="245.51651"
+ y="55.887268">isEmpty() : bool</tspan><tspan
+ sodipodi:role="line"
+ id="tspan2244"
+ x="245.51651"
+ y="70.887268">isGroup() : bool</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="279.65814"
+ y="29.038483"
+ id="text2347"
+ sodipodi:linespacing="125.00000%"><tspan
+ sodipodi:role="line"
+ id="tspan2222"
+ x="279.65814"
+ y="29.038483">address</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
+ d="M 238.27499,37.373470 L 370.37704,37.373470"
+ id="path2351" />
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2433"
+ width="242.87289"
+ height="157.12062"
+ x="17.947495"
+ y="215.62213" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="24.265694"
+ y="258.30316"
+ id="text2435"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan2315"
+ x="24.265694"
+ y="258.30316">getName() : string</tspan><tspan
+ sodipodi:role="line"
+ id="tspan2317"
+ x="24.265694"
+ y="273.30316">setName(n : string) : void</tspan><tspan
+ sodipodi:role="line"
+ id="tspan2319"
+ x="24.265694"
+ y="288.30316">appendMailbox(m : ref &lt;mailbox&gt;)</tspan><tspan
+ sodipodi:role="line"
+ id="tspan2321"
+ x="24.265694"
+ y="303.30316">getMailboxCount() : int</tspan><tspan
+ sodipodi:role="line"
+ id="tspan2323"
+ x="24.265694"
+ y="318.30316">getMailboxAt(i : int) : ref &lt;mailbox&gt;</tspan><tspan
+ sodipodi:role="line"
+ id="tspan2325"
+ x="24.265694"
+ y="333.30316">...</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="91.950951"
+ y="231.45441"
+ id="text2439"
+ sodipodi:linespacing="125.00000%"><tspan
+ sodipodi:role="line"
+ id="tspan2246"
+ x="91.950951"
+ y="231.45441">mailboxGroup</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
+ d="M 19.330207,239.78939 L 260.20091,239.78939"
+ id="path2443" />
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2447"
+ width="174.79645"
+ height="124.30678"
+ x="373.27942"
+ y="215.33472" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="380.74768"
+ y="258.15143"
+ id="text2449"
+ sodipodi:linespacing="125.00000%"><tspan
+ sodipodi:role="line"
+ id="tspan2286"
+ x="380.74768"
+ y="258.15143">getName() : text</tspan><tspan
+ sodipodi:role="line"
+ id="tspan2288"
+ x="380.74768"
+ y="273.15143">setName(n : text) : void</tspan><tspan
+ sodipodi:role="line"
+ id="tspan2290"
+ x="380.74768"
+ y="288.15143">getEmail() : string</tspan><tspan
+ sodipodi:role="line"
+ id="tspan2292"
+ x="380.74768"
+ y="303.15143">setEmail(e : string) : void</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="434.7478"
+ y="231.30267"
+ id="text2453"
+ sodipodi:linespacing="125.00000%"><tspan
+ sodipodi:role="line"
+ id="tspan2276"
+ x="434.74780"
+ y="231.30267">mailbox</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 373.64397,239.63760 L 547.69600,239.63760"
+ id="path2457" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500457;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2541"
+ width="15.541327"
+ height="15.541327"
+ x="-23.443876"
+ y="392.33624"
+ transform="matrix(0.707107,-0.707107,0.707107,0.707107,0.000000,0.000000)" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="344.41357"
+ y="289.23822"
+ id="text2545"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan5160"
+ sodipodi:role="line"
+ y="289.23822"
+ x="344.41357">0..n</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="293.07501"
+ y="312.23822"
+ id="text2549"
+ sodipodi:linespacing="125.00000%"><tspan
+ sodipodi:role="line"
+ id="tspan2294"
+ x="293.07501"
+ y="312.23822">mailboxes</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="289.07501"
+ y="289.23822"
+ id="text2553"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan5158"
+ sodipodi:role="line"
+ y="289.23822"
+ x="289.07501">0</tspan></text>
+ <path
+ id="path2575"
+ d="M 290.22642,134.62157 L 318.11534,134.62157 L 303.70606,120.21230 L 290.22642,134.62157 z "
+ style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ </g>
+ <path
+ id="path5436"
+ d="M 139.78693,173.17443 L 461.72537,173.17443"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;stroke-dasharray:none" />
+</svg>
diff --git a/vmime-master/doc/book/images/message-body-header.svg b/vmime-master/doc/book/images/message-body-header.svg
new file mode 100644
index 0000000..29923fa
--- /dev/null
+++ b/vmime-master/doc/book/images/message-body-header.svg
@@ -0,0 +1,716 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="707.28000pt"
+ height="612.89000pt"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.42.2"
+ sodipodi:docbase="/home/vincent/projects/vmime/doc/book/images"
+ sodipodi:docname="message-body-header.svg"
+ inkscape:export-xdpi="73.779999"
+ inkscape:export-ydpi="73.779999">
+ <defs
+ id="defs3">
+ <marker
+ inkscape:stockid="Torso"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Torso"
+ style="overflow:visible">
+ <g
+ id="g2045"
+ transform="scale(0.7)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path1128"
+ d="M -4.7792281,-3.2395420 C -2.4288541,-2.8736027 0.52103922,-1.3019943 0.25792722,0.38794346 C -0.0051877922,2.0778819 -2.2126741,2.6176539 -4.5630471,2.2517169 C -6.9134221,1.8857769 -8.5210350,0.75201414 -8.2579220,-0.93792336 C -7.9948090,-2.6278615 -7.1296041,-3.6054813 -4.7792281,-3.2395420 z "
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;marker-start:none;marker-mid:none;marker-end:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path1909"
+ d="M 4.4598789,0.088665736 C -2.5564571,-4.3783320 5.2248769,-3.9061806 -0.84829578,-8.7197331"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-end:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path1910"
+ d="M 4.9298719,0.057520736 C -1.3872731,1.7494689 1.8027579,5.4782079 -4.9448731,7.5462725"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" />
+ <rect
+ transform="matrix(0.527536,-0.849533,0.887668,0.460484,0.000000,0.000000)"
+ y="-1.7408575"
+ x="-10.391706"
+ height="2.7608147"
+ width="2.6366582"
+ id="rect2035"
+ style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" />
+ <rect
+ transform="matrix(0.671205,-0.741272,0.790802,0.612072,0.000000,0.000000)"
+ y="-7.9629307"
+ x="4.9587269"
+ height="2.8614161"
+ width="2.7327356"
+ id="rect2036"
+ style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" />
+ <path
+ transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,25.96648,19.71619)"
+ d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z"
+ sodipodi:ry="0.60731727"
+ sodipodi:rx="0.60731727"
+ sodipodi:cy="-28.685045"
+ sodipodi:cx="16.172634"
+ id="path2037"
+ style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,26.82450,16.99126)"
+ d="M 16.779951 -28.685045 A 0.60731727 0.60731727 0 1 0 15.565317,-28.685045 A 0.60731727 0.60731727 0 1 0 16.779951 -28.685045 z"
+ sodipodi:ry="0.60731727"
+ sodipodi:rx="0.60731727"
+ sodipodi:cy="-28.685045"
+ sodipodi:cx="16.172634"
+ id="path2038"
+ style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none"
+ sodipodi:type="arc" />
+ </g>
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path5324"
+ d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.00000000"
+ inkscape:cx="394.46478"
+ inkscape:cy="380.70648"
+ inkscape:document-units="px"
+ inkscape:current-layer="svg2"
+ inkscape:window-width="1150"
+ inkscape:window-height="986"
+ inkscape:window-x="0"
+ inkscape:window-y="30" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/SourceCode" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <path
+ id="path2407"
+ d="M 253.02743,136.68448 L 253.02743,67.376470"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path5442"
+ d="M 635.99153,281.37647 L 635.99153,350.68448"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path5440"
+ d="M 783.39333,349.39335 L 783.39333,417.10630"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path5438"
+ d="M 446.06998,349.39335 L 446.06998,417.10630"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 16.987518,219.56412 L 153.50367,219.56412"
+ id="path2375" />
+ <path
+ id="path2345"
+ d="M 508.29892,263.82217 L 105.85472,471.31117"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path2347"
+ d="M 502.39025,252.30315 L 515.17042,277.09145 L 521.37461,257.68108 L 502.39025,252.30315 z "
+ style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <g
+ transform="matrix(1.828236e-17,1.000000,-1.000000,1.828236e-17,533.0981,623.6004)"
+ id="g2321">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M -100.36367,371.67294 L 26.017722,371.67294"
+ id="path2323" />
+ <g
+ id="g2325"
+ transform="translate(-113.9177,-82.19766)">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 140.20049,454.12696 L 129.75724,443.68372"
+ id="path2327" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 139.84823,453.80527 L 129.66343,463.99007"
+ id="path2329" />
+ </g>
+ </g>
+ <path
+ id="path2241"
+ d="M 507.60723,180.01568 L 350.16119,180.01568"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <rect
+ style="fill:#dcf5e6;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect1291"
+ width="236.14607"
+ height="157.54773"
+ x="522.13733"
+ y="126.86942" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="529.52441"
+ y="169.54865"
+ id="text1293"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan5228"
+ sodipodi:role="line"
+ y="169.54865"
+ x="529.52441">parse(buf : string) : void</tspan><tspan
+ id="tspan5230"
+ sodipodi:role="line"
+ y="183.94865"
+ x="529.52441">generate(out : outputStream) : void</tspan><tspan
+ id="tspan5232"
+ sodipodi:role="line"
+ y="198.34865"
+ x="529.52441" /><tspan
+ id="tspan5234"
+ sodipodi:role="line"
+ y="212.74865"
+ x="529.52441">clone() : ref &lt;component&gt;</tspan><tspan
+ id="tspan5236"
+ sodipodi:role="line"
+ y="227.14865"
+ x="529.52441">copyFrom(src : component) : void</tspan><tspan
+ id="tspan5238"
+ sodipodi:role="line"
+ y="241.54865"
+ x="529.52441">getChildComponents() : vector</tspan><tspan
+ id="tspan5240"
+ sodipodi:role="line"
+ y="255.94865"
+ x="529.52441">getParsedOffset() : int</tspan><tspan
+ id="tspan5242"
+ sodipodi:role="line"
+ y="270.34865"
+ x="529.52441">getParsedLength() : int</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="609.02057"
+ y="142.69992"
+ id="text2347"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan5172"
+ sodipodi:role="line"
+ y="142.69992"
+ x="609.02057">component</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 522.50261,151.03487 L 758.16522,151.03487"
+ id="path2351" />
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2353"
+ width="218.71376"
+ height="151.16983"
+ x="145.51056"
+ y="133.04831" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="154.6483"
+ y="175.75391"
+ id="text2355"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan2349"
+ sodipodi:role="line"
+ y="175.75391"
+ x="154.64830">getBody() : ref &lt;body&gt;</tspan><tspan
+ id="tspan2351"
+ sodipodi:role="line"
+ y="190.15391"
+ x="154.64830">getHeader() : ref &lt;header&gt;</tspan><tspan
+ id="tspan2353"
+ sodipodi:role="line"
+ y="204.55391"
+ x="154.64830">getParentPart() : ref &lt;bodyPart&gt;</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="222.66418"
+ y="148.90518"
+ id="text2375"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan5272"
+ sodipodi:role="line"
+ y="148.90518"
+ x="222.66418">bodyPart</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 145.87565,157.24013 L 363.84409,157.24013"
+ id="path2379" />
+ <g
+ transform="matrix(1.828236e-17,1.000000,-1.000000,1.828236e-17,548.9327,384.9312)"
+ id="g2247">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M -100.36367,371.67294 L 26.017722,371.67294"
+ id="path2387" />
+ <g
+ id="g2395"
+ transform="translate(-113.9177,-82.19766)">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 140.20049,454.12696 L 129.75724,443.68372"
+ id="path2389" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 139.84823,453.80527 L 129.66343,463.99007"
+ id="path2393" />
+ </g>
+ </g>
+ <text
+ sodipodi:linespacing="100.00000%"
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="138.11696"
+ y="382.06345"
+ id="text2403"><tspan
+ id="tspan2273"
+ sodipodi:role="line"
+ y="382.06345"
+ x="138.11696">body</tspan></text>
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2433"
+ width="276.37778"
+ height="157.12062"
+ x="304.96820"
+ y="412.46472" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="313.24988"
+ y="455.14575"
+ id="text2435"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan5256"
+ sodipodi:role="line"
+ y="455.14575"
+ x="313.24988">hasField(name : string) : bool</tspan><tspan
+ id="tspan5258"
+ sodipodi:role="line"
+ y="469.54575"
+ x="313.24988">findField(name : string) : ref &lt;headerField&gt;</tspan><tspan
+ id="tspan5260"
+ sodipodi:role="line"
+ y="483.94575"
+ x="313.24988">findAllFields(name : string) : vector</tspan><tspan
+ id="tspan5262"
+ sodipodi:role="line"
+ y="498.34575"
+ x="313.24988">getField(name : string) : ref &lt;headerField&gt;</tspan><tspan
+ id="tspan5264"
+ sodipodi:role="line"
+ y="512.74575"
+ x="313.24988">appendField(f : ref &lt;headerField&gt;) : void</tspan><tspan
+ id="tspan5266"
+ sodipodi:role="line"
+ y="527.14575"
+ x="313.24988">...</tspan><tspan
+ id="tspan5268"
+ sodipodi:role="line"
+ y="541.54576"
+ x="313.24988">getFieldAt(pos : int) : ref &lt;headerField&gt;</tspan><tspan
+ id="tspan5270"
+ sodipodi:role="line"
+ y="555.94576"
+ x="313.24988">getFieldCount() : int</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="412.95099"
+ y="428.297"
+ id="text2439"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan5154"
+ sodipodi:role="line"
+ y="428.29700"
+ x="412.95099">header</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 306.34976,436.63194 L 580.95005,436.63194"
+ id="path2443" />
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2447"
+ width="174.79645"
+ height="124.30678"
+ x="694.27942"
+ y="412.17731" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="701.74768"
+ y="454.99402"
+ id="text2449"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan5176"
+ sodipodi:role="line"
+ y="454.99402"
+ x="701.74768">getName() : string</tspan><tspan
+ id="tspan5178"
+ sodipodi:role="line"
+ y="469.39402"
+ x="701.74768">getValue() : component</tspan><tspan
+ id="tspan5180"
+ sodipodi:role="line"
+ y="483.79402"
+ x="701.74768">setValue(val : component)</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="738.73987"
+ y="428.14526"
+ id="text2453"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan5152"
+ sodipodi:role="line"
+ y="428.14526"
+ x="738.73987">headerField</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 694.64397,436.48015 L 868.69600,436.48015"
+ id="path2457" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500381;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2541"
+ width="15.541226"
+ height="15.541226"
+ x="65.401291"
+ y="759.55469"
+ transform="matrix(0.707107,-0.707107,0.707107,0.707107,0.000000,0.000000)" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 605.07226,490.76897 L 694.31385,490.76897"
+ id="path2543" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="661.23236"
+ y="486.08081"
+ id="text2545"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan5160"
+ sodipodi:role="line"
+ y="486.08081"
+ x="661.23236">0..n</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="626.90173"
+ y="509.08081"
+ id="text2549"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan5156"
+ sodipodi:role="line"
+ y="509.08081"
+ x="626.90173">fields</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="611.56311"
+ y="486.08081"
+ id="text2553"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan5158"
+ sodipodi:role="line"
+ y="486.08081"
+ x="611.56311">0</tspan></text>
+ <path
+ id="path2575"
+ d="M 622.56502,300.28297 L 650.45394,300.28297 L 636.04466,285.87370 L 622.56502,300.28297 z "
+ style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2225"
+ width="171.85686"
+ height="151.16983"
+ x="74.698677"
+ y="412.04831" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="82.183701"
+ y="454.75391"
+ id="text2227"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan2377"
+ sodipodi:role="line"
+ y="454.75391"
+ x="82.183701">getContents() : ref &lt;ch&gt;</tspan><tspan
+ id="tspan2379"
+ sodipodi:role="line"
+ y="469.15391"
+ x="82.183701">getCharset() : charset</tspan><tspan
+ id="tspan2381"
+ sodipodi:role="line"
+ y="483.55391"
+ x="82.183701">getEncoding() : encoding</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="141.69556"
+ y="427.90518"
+ id="text2231"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan2237"
+ sodipodi:role="line"
+ y="427.90518"
+ x="141.69556">body</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 75.063282,436.24013 L 246.17599,436.24013"
+ id="path2235" />
+ <path
+ id="path2239"
+ d="M 506.13949,167.78737 L 506.13949,195.67630 L 520.54876,181.26702 L 506.13949,167.78737 z "
+ style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <g
+ transform="matrix(1.828236e-17,1.000000,-1.000000,1.828236e-17,548.9327,384.9312)"
+ id="g2253">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M -100.36367,371.67294 L 26.017722,371.67294"
+ id="path2255" />
+ <g
+ id="g2257"
+ transform="translate(-113.9177,-82.19766)">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 140.20049,454.12696 L 129.75724,443.68372"
+ id="path2259" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 139.84823,453.80527 L 129.66343,463.99007"
+ id="path2261" />
+ </g>
+ </g>
+ <g
+ transform="matrix(1.828236e-17,1.000000,-1.000000,1.828236e-17,704.8357,384.9312)"
+ id="g2263">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M -100.36367,371.67294 L 26.017722,371.67294"
+ id="path2265" />
+ <g
+ id="g2267"
+ transform="translate(-113.9177,-82.19766)">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 140.20049,454.12696 L 129.75724,443.68372"
+ id="path2269" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 139.84823,453.80527 L 129.66343,463.99007"
+ id="path2271" />
+ </g>
+ </g>
+ <text
+ sodipodi:linespacing="100.00000%"
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="342.21133"
+ y="384.8981"
+ id="text2275"><tspan
+ id="tspan2279"
+ sodipodi:role="line"
+ y="384.89810"
+ x="342.21133">header</tspan></text>
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2283"
+ width="223.48137"
+ height="99.596283"
+ x="46.366730"
+ y="650.83508" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="53.664009"
+ y="693.75391"
+ id="text2285"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan2337"
+ sodipodi:role="line"
+ y="693.75391"
+ x="53.664009">extract(out : outputStream) : void</tspan><tspan
+ id="tspan2339"
+ sodipodi:role="line"
+ y="708.15391"
+ x="53.664009">getLength() : int</tspan><tspan
+ id="tspan2341"
+ sodipodi:role="line"
+ y="722.55391"
+ x="53.664009">getEncoding() : encoding</tspan><tspan
+ id="tspan2343"
+ sodipodi:role="line"
+ y="736.95391"
+ x="53.664009">isEmpty() : bool</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="107.50659"
+ y="666.90515"
+ id="text2289"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan2295"
+ sodipodi:role="line"
+ y="666.90515"
+ x="107.50659">contentHandler</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 46.694654,675.24013 L 269.50523,675.24013"
+ id="path2293" />
+ <text
+ sodipodi:linespacing="100.00000%"
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="96.439804"
+ y="606.38623"
+ id="text2313"><tspan
+ id="tspan2331"
+ sodipodi:role="line"
+ y="606.38623"
+ x="96.439804">contents</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2343873;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 16.600928,494.52517 L 54.665082,494.52517"
+ id="path2357" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="114.21628"
+ y="211.67206"
+ id="text2359"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan2361"
+ sodipodi:role="line"
+ y="211.67206"
+ x="114.21628">0..n</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="15.201084"
+ y="211.39832"
+ id="text2363"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan2371"
+ sodipodi:role="line"
+ y="211.39832"
+ x="15.201084">sub-parts</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="37.547035"
+ y="486.67206"
+ id="text2367"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan2369"
+ sodipodi:role="line"
+ y="486.67206"
+ x="37.547035">0</tspan></text>
+ <rect
+ style="fill:#ffffff;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500843;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2355"
+ width="15.541844"
+ height="15.541844"
+ x="-313.66727"
+ y="385.82047"
+ transform="matrix(0.707107,-0.707107,0.707107,0.707107,0.000000,0.000000)" />
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2383"
+ width="171.85686"
+ height="67.987976"
+ x="169.86403"
+ y="15.308525" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="228.35699"
+ y="31.574478"
+ id="text2393"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan2399"
+ sodipodi:role="line"
+ y="31.574478"
+ x="228.35699">message</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 170.22863,39.909422 L 341.34134,39.909422"
+ id="path2397" />
+ <path
+ id="path2405"
+ d="M 266.45394,117.77798 L 238.56502,117.77798 L 252.97430,132.18725 L 266.45394,117.77798 z "
+ style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ </g>
+ <path
+ id="path5436"
+ d="M 446.81292,350.17443 L 782.69938,350.17443"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2515085;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path2373"
+ d="M 16.806908,219.05029 L 16.806908,493.94805"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2522694;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+</svg>
diff --git a/vmime-master/doc/book/images/messaging-services.svg b/vmime-master/doc/book/images/messaging-services.svg
new file mode 100644
index 0000000..fe4f8c8
--- /dev/null
+++ b/vmime-master/doc/book/images/messaging-services.svg
@@ -0,0 +1,617 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="629.28000pt"
+ height="615.89000pt"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.48.0 r9654"
+ sodipodi:docname="messaging-services.svg"
+ inkscape:export-filename="/home/vincent/www/vmime/documentation/images/design-messaging.png"
+ inkscape:export-xdpi="74.639999"
+ inkscape:export-ydpi="74.639999"
+ version="1.1">
+ <defs
+ id="defs3">
+ <marker
+ inkscape:stockid="Torso"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Torso"
+ style="overflow:visible">
+ <g
+ id="g2045"
+ transform="scale(0.7)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path1128"
+ d="M -4.7792281,-3.2395420 C -2.4288541,-2.8736027 0.52103922,-1.3019943 0.25792722,0.38794346 C -0.0051877922,2.0778819 -2.2126741,2.6176539 -4.5630471,2.2517169 C -6.9134221,1.8857769 -8.5210350,0.75201414 -8.2579220,-0.93792336 C -7.9948090,-2.6278615 -7.1296041,-3.6054813 -4.7792281,-3.2395420 z "
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;marker-start:none;marker-mid:none;marker-end:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path1909"
+ d="M 4.4598789,0.088665736 C -2.5564571,-4.3783320 5.2248769,-3.9061806 -0.84829578,-8.7197331"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-end:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path1910"
+ d="M 4.9298719,0.057520736 C -1.3872731,1.7494689 1.8027579,5.4782079 -4.9448731,7.5462725"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none" />
+ <rect
+ transform="matrix(0.527536,-0.849533,0.887668,0.460484,0.000000,0.000000)"
+ y="-1.7408575"
+ x="-10.391706"
+ height="2.7608147"
+ width="2.6366582"
+ id="rect2035"
+ style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" />
+ <rect
+ transform="matrix(0.671205,-0.741272,0.790802,0.612072,0.000000,0.000000)"
+ y="-7.9629307"
+ x="4.9587269"
+ height="2.8614161"
+ width="2.7327356"
+ id="rect2036"
+ style="fill-rule:evenodd;stroke-width:1.0000000pt;marker-end:none" />
+ <path
+ transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,25.96648,19.71619)"
+ d="m 16.779951,-28.685045 c 0,0.335412 -0.271905,0.607317 -0.607317,0.607317 -0.335412,0 -0.607317,-0.271905 -0.607317,-0.607317 0,-0.335412 0.271905,-0.607318 0.607317,-0.607318 0.335412,0 0.607317,0.271906 0.607317,0.607318 z"
+ sodipodi:ry="0.60731727"
+ sodipodi:rx="0.60731727"
+ sodipodi:cy="-28.685045"
+ sodipodi:cx="16.172634"
+ id="path2037"
+ style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(6.793608e-17,-1.109517,1.109517,6.793608e-17,26.82450,16.99126)"
+ d="m 16.779951,-28.685045 c 0,0.335412 -0.271905,0.607317 -0.607317,0.607317 -0.335412,0 -0.607317,-0.271905 -0.607317,-0.607317 0,-0.335412 0.271905,-0.607318 0.607317,-0.607318 0.335412,0 0.607317,0.271906 0.607317,0.607318 z"
+ sodipodi:ry="0.60731727"
+ sodipodi:rx="0.60731727"
+ sodipodi:cy="-28.685045"
+ sodipodi:cx="16.172634"
+ id="path2038"
+ style="fill:#ff0000;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;marker-start:none;marker-end:none"
+ sodipodi:type="arc" />
+ </g>
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path5324"
+ d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.75785828"
+ inkscape:cx="365.32198"
+ inkscape:cy="407.27112"
+ inkscape:document-units="px"
+ inkscape:current-layer="svg2"
+ inkscape:window-width="1150"
+ inkscape:window-height="986"
+ inkscape:window-x="69"
+ inkscape:window-y="33"
+ showgrid="false"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <path
+ id="path5442"
+ d="M 495.30781,321.26414 L 495.30781,390.57215"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path5440"
+ d="M 662.55216,389.28102 L 662.55216,456.99397"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path5438"
+ d="M 325.22881,389.28102 L 325.22881,456.99397"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <g
+ transform="matrix(0.866025,0.499999,-0.499999,0.866025,111.0615,336.6054)"
+ id="g3452">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:5.0000000 5.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ d="M 278.87323,198.08204 L 405.25462,198.08204"
+ id="path3454" />
+ <g
+ transform="matrix(-1.000000,-1.845854e-17,1.845854e-17,-1.000000,684.3929,415.9391)"
+ style="stroke-width:1.2500000;stroke-miterlimit:4.0000000"
+ id="g3456">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 278.87321,217.60074 L 289.31646,228.04398"
+ id="path3458" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 279.22547,217.92243 L 289.41027,207.73763"
+ id="path3460" />
+ </g>
+ </g>
+ <g
+ transform="matrix(-0.499998,0.866024,-0.866024,-0.499998,528.2205,319.3107)"
+ id="g3396">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:5.0000000 5.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ d="M 278.87323,198.08204 L 405.25462,198.08204"
+ id="path3398" />
+ <g
+ transform="matrix(-1.000000,-1.845854e-17,1.845854e-17,-1.000000,684.3929,415.9391)"
+ style="stroke-width:1.2500000;stroke-miterlimit:4.0000000"
+ id="g3400">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 278.87321,217.60074 L 289.31646,228.04398"
+ id="path3402" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 279.22547,217.92243 L 289.41027,207.73763"
+ id="path3404" />
+ </g>
+ </g>
+ <g
+ transform="matrix(0.500000,0.866024,-0.866024,0.500000,431.6077,-252.3913)"
+ id="g3200">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:5.0000000 5.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ d="M 278.87323,198.08204 L 405.25462,198.08204"
+ id="path3202" />
+ <g
+ transform="matrix(-1.000000,-1.845854e-17,1.845854e-17,-1.000000,684.3929,415.9391)"
+ style="stroke-width:1.2500000;stroke-miterlimit:4.0000000"
+ id="g3204">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 278.87321,217.60074 L 289.31646,228.04398"
+ id="path3206" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 279.22547,217.92243 L 289.41027,207.73763"
+ id="path3208" />
+ </g>
+ </g>
+ <g
+ transform="matrix(0.499999,-0.866025,0.866025,0.499999,-54.36140,359.0658)"
+ id="g3168">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:5.0000000 5.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ d="M 278.87323,198.08204 L 405.25462,198.08204"
+ id="path3156" />
+ <g
+ transform="matrix(-1.000000,-1.845854e-17,1.845854e-17,-1.000000,684.3929,415.9391)"
+ style="stroke-width:1.2500000;stroke-miterlimit:4.0000000"
+ id="g3158">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 278.87321,217.60074 L 289.31646,228.04398"
+ id="path3160" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 279.22547,217.92243 L 289.41027,207.73763"
+ id="path3162" />
+ </g>
+ </g>
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect1291"
+ width="144.63049"
+ height="123.75754"
+ x="423.21133"
+ y="200.65219" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="430.8407"
+ y="243.43631"
+ id="text1293"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan3116"
+ sodipodi:role="line"
+ y="243.43631"
+ x="430.84070">connect() : void</tspan><tspan
+ id="tspan3118"
+ sodipodi:role="line"
+ y="257.83631"
+ x="430.84070">disconnect() : void</tspan><tspan
+ id="tspan3120"
+ sodipodi:role="line"
+ y="272.23631"
+ x="430.84070">isConnected() : bool</tspan><tspan
+ id="tspan3122"
+ sodipodi:role="line"
+ y="286.63631"
+ x="430.84070">noop() : void</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="473.4863"
+ y="216.58759"
+ id="text2347"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan2932"
+ sodipodi:role="line"
+ y="216.58759"
+ x="473.48630">service</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 423.62452,224.92254 L 567.67587,224.92254"
+ id="path2351" />
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2353"
+ width="254.50919"
+ height="106.53888"
+ x="40.771675"
+ y="200.75146" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="49.807129"
+ y="243.64157"
+ id="text2355"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan3148"
+ sodipodi:role="line"
+ y="243.64157"
+ x="49.807129">getTransport(url : url) : ref &lt;transport&gt;</tspan><tspan
+ id="tspan3150"
+ sodipodi:role="line"
+ y="258.04157"
+ x="49.807129">getStore(url : url) : ref &lt;store&gt;</tspan><tspan
+ id="tspan3152"
+ sodipodi:role="line"
+ y="272.44157"
+ x="49.807129">getProperties() : propertySet</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="143.33478"
+ y="216.79285"
+ id="text2375"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan3124"
+ sodipodi:role="line"
+ y="216.79285"
+ x="143.33478">session</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 41.137120,225.12780 L 294.90028,225.12780"
+ id="path2379" />
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2433"
+ width="219.00885"
+ height="100.80741"
+ x="215.20381"
+ y="429.00940" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="223.58997"
+ y="472.3562"
+ id="text2435"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan3110"
+ sodipodi:role="line"
+ y="472.35620"
+ x="223.58997">getDefaultFolder() : ref &lt;folder&gt;</tspan><tspan
+ id="tspan3112"
+ sodipodi:role="line"
+ y="486.75620"
+ x="223.58997">getRootFolder() : ref &lt;folder&gt;</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="309.11777"
+ y="445.50742"
+ id="text2439"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan2936"
+ sodipodi:role="line"
+ y="445.50742"
+ x="309.11777">store</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 216.61640,453.84241 L 433.36337,453.84241"
+ id="path2443" />
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect2447"
+ width="219.00674"
+ height="101.04262"
+ x="553.75336"
+ y="428.77499" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="561.0639"
+ y="472.20447"
+ id="text2449"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan3114"
+ sodipodi:role="line"
+ y="472.20447"
+ x="561.06390">send(msg : ref &lt;message&gt;) : void</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="632.07196"
+ y="445.35568"
+ id="text2453"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan2934"
+ sodipodi:role="line"
+ y="445.35568"
+ x="632.07196">transport</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 554.08593,453.69062 L 771.88660,453.69062"
+ id="path2457" />
+ <path
+ id="path2575"
+ d="M 481.88130,340.17064 L 509.77022,340.17064 L 495.36094,325.76137 L 481.88130,340.17064 z "
+ style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <g
+ transform="translate(17.15883,45.55696)"
+ id="g3136">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 405.51967,217.85706 L 279.13828,217.85706"
+ id="path2265" />
+ <g
+ style="stroke-width:1.2500000;stroke-miterlimit:4.0000000"
+ id="g3132">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 278.87321,217.60074 L 289.31646,228.04398"
+ id="path2269" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 279.22547,217.92243 L 289.41027,207.73763"
+ id="path2271" />
+ </g>
+ </g>
+ <text
+ sodipodi:linespacing="100.00000%"
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="335.37018"
+ y="257.45505"
+ id="text2275"><tspan
+ id="tspan3146"
+ sodipodi:role="line"
+ y="257.45505"
+ x="335.37018">session</tspan></text>
+ <text
+ transform="matrix(0.500000,0.866025,-0.866025,0.500000,0.000000,0.000000)"
+ sodipodi:linespacing="100.00000%"
+ xml:space="preserve"
+ style="font-size:11.999973px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="313.42676"
+ y="-318.0412"
+ id="text3174"><tspan
+ id="tspan3178"
+ sodipodi:role="line"
+ y="-318.04120"
+ x="313.42676">&lt;instanciates&gt;</tspan></text>
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect3180"
+ width="253.81813"
+ height="96.037521"
+ x="234.02649"
+ y="9.0948601" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="241.24963"
+ y="52.019093"
+ id="text3182"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan3218"
+ sodipodi:role="line"
+ y="52.019093"
+ x="241.24963">create(protocol : string) : ref &lt;service&gt;</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="312.24161"
+ y="25.170307"
+ id="text3192"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan3198"
+ sodipodi:role="line"
+ y="25.170307"
+ x="312.24161">serviceFactory</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 234.44127,33.505080 L 487.67742,33.505080"
+ id="path3196" />
+ <text
+ transform="matrix(0.500000,-0.866025,0.866025,0.500000,0.000000,0.000000)"
+ sodipodi:linespacing="100.00000%"
+ xml:space="preserve"
+ style="font-size:11.999965px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="-19.006903"
+ y="316.46106"
+ id="text3210"><tspan
+ id="tspan3214"
+ sodipodi:role="line"
+ y="316.46106"
+ x="-19.006903">&lt;uses&gt;</tspan></text>
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect3362"
+ width="244.86130"
+ height="116.61144"
+ x="14.277589"
+ y="572.10736" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="22.589966"
+ y="615.3562"
+ id="text3364"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan3386"
+ sodipodi:role="line"
+ y="615.35620"
+ x="22.589966">getName() : string</tspan><tspan
+ id="tspan3388"
+ sodipodi:role="line"
+ y="629.75620"
+ x="22.589966">open() : void</tspan><tspan
+ id="tspan3390"
+ sodipodi:role="line"
+ y="644.15620"
+ x="22.589966">close() : void</tspan><tspan
+ id="tspan3392"
+ sodipodi:role="line"
+ y="658.55620"
+ x="22.589966">getMessages(int from, int to) : vector</tspan><tspan
+ id="tspan3394"
+ sodipodi:role="line"
+ y="672.95620"
+ x="22.589966">...</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="119.45631"
+ y="588.50739"
+ id="text3370"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan3376"
+ sodipodi:role="line"
+ y="588.50739"
+ x="119.45631">folder</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2449049;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 15.691587,596.84241 L 258.28817,596.84241"
+ id="path3374" />
+ <text
+ transform="matrix(0.500000,-0.866025,0.866025,0.500000,0.000000,0.000000)"
+ sodipodi:linespacing="100.00000%"
+ xml:space="preserve"
+ style="font-size:11.999992px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="-398.12543"
+ y="406.40524"
+ id="text3406"><tspan
+ id="tspan3408"
+ sodipodi:role="line"
+ y="406.40524"
+ x="-398.12543">&lt;instanciates&gt;</tspan></text>
+ <rect
+ style="fill:#f5f5c8;fill-opacity:1.0000000;stroke:#000000;stroke-width:1.2500000;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="rect3410"
+ width="244.86130"
+ height="140.35690"
+ x="365.27762"
+ y="617.23462" />
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="373.59"
+ y="660.3562"
+ id="text3412"
+ sodipodi:linespacing="120.00000%"><tspan
+ id="tspan3440"
+ sodipodi:role="line"
+ y="660.35620"
+ x="373.59000">getNumber() : int</tspan><tspan
+ id="tspan3442"
+ sodipodi:role="line"
+ y="674.75620"
+ x="373.59000">getFlags() : int</tspan><tspan
+ id="tspan3444"
+ sodipodi:role="line"
+ y="689.15620"
+ x="373.59000">getHeader() : int</tspan><tspan
+ id="tspan3446"
+ sodipodi:role="line"
+ y="703.55620"
+ x="373.59000">getStructure() : structure</tspan><tspan
+ id="tspan3448"
+ sodipodi:role="line"
+ y="717.95620"
+ x="373.59000">extract(out : outputStream) : void</tspan><tspan
+ id="tspan3450"
+ sodipodi:role="line"
+ y="732.35620"
+ x="373.59000">...</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.000000px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="459.11771"
+ y="633.50739"
+ id="text3424"
+ sodipodi:linespacing="100.00000%"><tspan
+ id="tspan3430"
+ sodipodi:role="line"
+ y="633.50739"
+ x="459.11771">message</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2449049;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 366.69159,641.84241 L 609.28817,641.84241"
+ id="path3428" />
+ <text
+ transform="matrix(0.866025,0.500000,-0.500000,0.866025,0.000000,0.000000)"
+ sodipodi:linespacing="100.00000%"
+ xml:space="preserve"
+ style="font-size:11.999992px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+ x="558.315"
+ y="419.37476"
+ id="text3462"><tspan
+ id="tspan3464"
+ sodipodi:role="line"
+ y="419.37476"
+ x="558.31500">&lt;instanciates&gt;</tspan></text>
+ </g>
+ <path
+ id="path5436"
+ d="M 325.97175,390.06210 L 661.85821,390.06210"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2515085;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <rect
+ y="170.36218"
+ x="668.00000"
+ height="76.000000"
+ width="134.00000"
+ id="rect3360"
+ style="stroke-opacity:1.0000000;stroke-dashoffset:0.0000000;stroke-miterlimit:4.0000000;stroke-linejoin:miter;stroke-linecap:round;stroke-width:1.2500000;stroke:none;fill-rule:nonzero;fill-opacity:1.0000000;fill:none" />
+</svg>
diff --git a/vmime-master/doc/book/intro.tex b/vmime-master/doc/book/intro.tex
new file mode 100644
index 0000000..fe7bcf5
--- /dev/null
+++ b/vmime-master/doc/book/intro.tex
@@ -0,0 +1,90 @@
+\chapter{Introduction}
+
+% ============================================================================
+\section{Overview}
+
+VMime is a powerful C++ class library for working with MIME messages and
+Internet messaging services like IMAP, POP or SMTP.
+
+With VMime you can parse, generate and modify messages, and also connect to
+store and transport services to receive or send messages over the Internet.
+The library offers all the features to build a complete mail client.
+
+The main objectives of this library are:
+
+\begin{itemize}
+\item fully RFC-compliant implementation;
+\item object-oriented and modular design;
+\item very easy-to-use (intuitive design);
+\item well documented code;
+\item very high reliability;
+\item maximum portability.
+\end{itemize}
+
+
+% ============================================================================
+\section{Features}
+
+\noindent MIME features:
+
+\begin{itemize}
+\item Full support for RFC-2822 and multipart messages (RFC-1521)
+\item Aggregate documents (MHTML) and embedded objects (RFC-2557)
+\item Message Disposition Notification (RFC-3798)
+\item 8-bit MIME (RFC-2047)
+\item Encoded word extensions (RFC-2231)
+\item Attachments
+\end{itemize}
+
+\noindent Network features:
+
+\begin{itemize}
+\item Support for IMAP, POP3 and maildir stores
+\item Support for SMTP and sendmail transport methods
+\item Extraction of whole message or specific parts
+\item TLS/SSL security layer
+\item SASL authentication
+\end{itemize}
+
+
+% ============================================================================
+\section{Copyright and license}
+
+VMime library is Free Software and is licensed under the terms of the GNU
+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 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
+ published by the Free Software Foundation; either version 3 of
+ the License, or (at your option) any later version.
+
+ VMime 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.
+
+ 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.
+\end{verbatim}
+
+\newpage
+\noindent This document is released under the terms of the
+GNU Free Documentation
+License\footnote{See \url{http://www.gnu.org/copyleft/fdl.html}} (FDL):
+
+\begin{verbatim}
+ Copyright (C) 2004 Vincent Richard
+
+ Permission is granted to copy, distribute and/or modify
+ this document under the terms of the GNU Free Documentation
+ License, Version 1.2 or any later version published by the
+ Free Software Foundation; with no Invariant Sections, no
+ Front-Cover Texts, and no Back-Cover Texts.
+\end{verbatim}
+
diff --git a/vmime-master/doc/book/msg.tex b/vmime-master/doc/book/msg.tex
new file mode 100644
index 0000000..ce9d8a8
--- /dev/null
+++ b/vmime-master/doc/book/msg.tex
@@ -0,0 +1,430 @@
+\chapter{Parsing and Building Messages}
+
+% ============================================================================
+\section{Parsing messages}
+
+\subsection{Introduction} % --------------------------------------------------
+
+Parsing is the process of creating a structured representation (for example,
+a hierarchy of C++ objects) of a message from its ``textual'' representation
+(the raw data that is actually sent on the Internet).
+
+For example, say you have the following email in a file called "hello.eml":
+
+\begin{verbatim}
+Date: Thu, Oct 13 2005 15:22:46 +0200
+From: Vincent <vincent@vmime.org>
+To: you@vmime.org
+Subject: Hello from VMime!
+
+A simple message to test VMime
+\end{verbatim}
+
+The following code snippet shows how you can easily obtain a
+{\vcode vmime::message} object from data in this file:
+
+\begin{lstlisting}[caption={Parsing a message from a file}]
+// Read data from file
+std::ifstream file;
+file.open("hello.eml", std::ios::in | std::ios::binary);
+
+vmime::utility::inputStreamAdapter is(file);
+
+vmime::string data;
+vmime::utility::outputStreamStringAdapter os(data);
+
+vmime::utility::bufferedStreamCopy(is, os);
+
+// Actually parse the message
+vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>();
+msg->parse(data);
+
+vmime::shared_ptr <vmime::header> hdr = msg->getHeader();
+vmime::shared_ptr <vmime::body> bdy = msg->getBody();
+
+// Now, you can extract some of its components
+vmime::charset ch(vmime::charsets::UTF_8);
+
+std::cout
+ << "The subject of the message is: "
+ << hdr->Subject()->getValue <vmime::text>()->getConvertedText(ch)
+ << std::endl
+ << "It was sent by: "
+ << hdr->From()->getValue <vmime::mailbox>()->getName().getConvertedText(ch)
+ << " (email: " << hdr->From()->getValue <vmime::mailbox>()->getEmail() << ")"
+ << std::endl;
+\end{lstlisting}
+
+The output of this program is:
+
+\begin{verbatim}
+The subject of the message is: Hello from VMime!
+It was sent by: Vincent (email: vincent@vmime.org)
+\end{verbatim}
+
+
+\subsection{Using the {\vcode vmime::messageParser} object} % ----------------
+
+The {\vcode vmime::messageParser} object allows to parse messages in a more
+simple manner. You can obtain all the text parts and attachments as well as
+basic fields (expeditor, recipients, subject...), without dealing with
+MIME message structure.
+
+\begin{lstlisting}[caption={Using {\vcode vmime::messageParser} to parse
+more complex messages}]
+// Read data from file
+std::ifstream file;
+file.open("hello.eml", std::ios::in | std::ios::binary);
+
+vmime::utility::inputStreamAdapter is(file);
+
+vmime::string data;
+vmime::utility::outputStreamStringAdapter os(data);
+
+vmime::utility::bufferedStreamCopy(is, os);
+
+// Actually parse the message
+vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>();
+msg->parse(data);
+
+// Here start the differences with the previous example
+vmime::messageParser mp(msg);
+
+// Output information about attachments
+std::cout << "Message has " << mp.getAttachmentCount()
+ << " attachment(s)" << std::endl;
+
+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;
+}
+
+// Output information about text parts
+std::cout << "Message has " << mp.getTextPartCount()
+ << " text part(s)" << std::endl;
+
+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) {
+
+ vmime::shared_ptr <const vmime::htmlTextPart> htp =
+ vmime::dynamicCast <const vmime::htmlTextPart>(tp);
+
+ // HTML text is in tp->getText()
+ // Plain text is in tp->getPlainText()
+
+ // Enumerate embedded objects
+ 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 {
+
+ // Text is in tp->getText()
+ }
+}
+\end{lstlisting}
+
+
+% ============================================================================
+\section{Building messages}
+
+\subsection{A simple message\label{msg-building-simple-message}} % -----------
+
+Of course, you can build a MIME message from scratch by creating the various
+objects that compose it (parts, fields, etc.). The following is an example of
+how to achieve it:
+
+\begin{lstlisting}[caption={Building a simple message from scratch}]
+vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>();
+
+vmime::shared_ptr <vmime::header> hdr = msg->getHeader();
+vmime::shared_ptr <vmime::body> bdy = msg->getBody();
+
+vmime::shared_ptr <vmime::headerFieldFactory> hfFactory =
+ vmime::headerFieldFactory::getInstance();
+
+// Append a 'Date:' field
+vmime::shared_ptr <vmime::headerField> dateField =
+ hfFactory->create(vmime::fields::DATE);
+
+dateField->setValue(vmime::datetime::now());
+hdr->appendField(dateField);
+
+// Append a 'Subject:' field
+vmime::shared_ptr <vmime::headerField> subjectField =
+ hfFactory->create(vmime::fields::SUBJECT);
+
+subjectField->setValue(vmime::text("Message subject"));
+hdr->appendField(subjectField);
+
+// Append a 'From:' field
+vmime::shared_ptr <vmime::headerField> fromField =
+ hfFactory->create(vmime::fields::FROM);
+
+fromField->setValue(vmime::make_shared <vmime::mailbox>("me@vmime.org"));
+hdr->appendField(fromField);
+
+// Append a 'To:' field
+vmime::shared_ptr <vmime::headerField> toField =
+ hfFactory->create(vmime::fields::TO);
+
+vmime::shared_ptr <vmime::mailboxList> recipients =
+ vmime::make_shared <vmime::mailboxList>();
+
+recipients->appendMailbox
+ (vmime::make_shared <vmime::mailbox>("you@vmime.org"));
+
+toField->setValue(recipients);
+hdr->appendField(toField);
+
+// Set the body contents
+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);
+msg->generate(out);
+\end{lstlisting}
+
+As you can see, this is a little fastidious. Hopefully, VMime also offers a
+more simple way for creating messages. The {\vcode vmime::messageBuilder}
+object can create basic messages that you can then customize.
+
+The following code can be used to build exactly the same message as in the
+previous example, using the {\vcode vmime::messageBuilder} object:
+
+\begin{lstlisting}[caption={Building a simple message
+using {\vcode vmime::messageBuilder}}]
+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.getTextPart()->setCharset(vmime::charsets::ISO8859_15);
+ 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();
+
+ // Output raw message data to standard output
+ vmime::utility::outputStreamAdapter out(std::cout);
+ msg->generate(out);
+
+// VMime exception
+} catch (vmime::exception& e) {
+
+ std::cerr << "vmime::exception: " << e.what() << std::endl;
+
+// Standard exception
+} catch (std::exception& e) {
+
+ std::cerr << "std::exception: " << e.what() << std::endl;
+}
+\end{lstlisting}
+
+
+\subsection{Adding an attachment} % ------------------------------------------
+
+Dealing with attachments is quite simple. Add the following code to the
+previous example to attach a file to the message:
+
+\begin{lstlisting}[caption={Building a message with an attachment using
+{\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")
+ );
+
+// 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")
+);
+
+// Add this attachment to the message
+mb.appendAttachment(att);
+\end{lstlisting}
+
+
+\subsection{HTML messages and embedded objects} % ----------------------------
+
+VMime also supports aggregate messages, which permits to build MIME messages
+containing HTML text and embedded objects (such as images). For more information
+about aggregate messages, please read RFC-2557 (\emph{MIME Encapsulation of
+Aggregate Documents, such as HTML}).
+
+Creating such messages is quite easy, using the {\vcode vmime::messageBuilder}
+object. The following code constructs a message containing text in both plain
+and HTML format, and a JPEG image:
+
+\begin{lstlisting}[caption={Building an HTML message with an embedded image
+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")
+);
+
+// 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
+ )
+);
+
+// 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.
+vmime::shared_ptr <vmime::htmlTextPart> textPart =
+ vmime::dynamicCast <vmime::htmlTextPart>(mb.getTextPart());
+
+// -- Add the JPEG image (the returned identifier is used to identify the
+// -- embedded object in the HTML text, the famous "CID", or "Content-Id").
+// -- Note: you can also read data from a file; see the next example.
+const vmime::string id = textPart->addObject("<...image data...>",
+ vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG));
+
+// -- 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->setPlainText(
+ vmime::make_shared <vmime::stringContentHandler>(
+ "This is the plain text."
+ )
+);
+\end{lstlisting}
+
+This will create a message having the following structure:
+
+\begin{verbatim}
+multipart/alternative
+ text/plain
+ multipart/related
+ text/html
+ image/jpeg
+\end{verbatim}
+
+You can easily tell VMime to read the embedded object data from a file. The
+following code opens the file \emph{/path/to/image.jpg}, connects it to an
+input stream, then add an embedded object:
+
+\begin{lstlisting}
+vmime::utility::fileSystemFactory* fs =
+ vmime::platform::getHandler()->getFileSystemFactory();
+
+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()
+ );
+
+const vmime::string cid = textPart.addObject(
+ imageCts,
+ vmime::mediaType(
+ vmime::mediaTypes::IMAGE,
+ vmime::mediaTypes::IMAGE_JPEG
+ )
+);
+\end{lstlisting}
+
+
+% ============================================================================
+\section{Working with attachments: the attachment helper}
+
+The {\vcode attachmentHelper} object allows listing all attachments in a
+message, as well as adding new attachments, without using the
+{\vcode messageParser} and {\vcode messageBuilders} objects. It can work
+directly on messages and body parts.
+
+To use it, you do not need any knowledge about how attachment parts should
+be organized in a MIME message.
+
+The following code snippet tests if a body part is an attachment, and if so,
+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)) {
+
+ // The body part contains an attachment, get it
+ vmime::shared_ptr <const vmime::attachment> attach =
+ attachmentHelper::getBodyPartAttachment(part);
+
+ // Extract attachment data to standard output
+ vmime::utility::outputStreamAdapter out(std::cout);
+ attach->getData()->extract(out);
+}
+\end{lstlisting}
+
+You can also easily extract all attachments from a message:
+
+\begin{lstlisting}[caption={Extracting all attachments from a message}]
+vmime::shared_ptr <vmime::message> msg; // suppose we have a message
+
+const std::vector <ref <const attachment> > atts =
+ attachmentHelper::findAttachmentsInMessage(msg);
+\end{lstlisting}
+
+Finally, the {\vcode attachmentHelper} object can be used to add an
+attachment to an existing message, whatever it contains (text parts,
+attachments, ...). The algorithm can modify the structure of the
+message if needed (eg. add a \emph{multipart/mixed} part if no one
+exists in the message). Simply call the {\vcode addAttachment}
+function:
+
+\begin{lstlisting}[caption={Adding an attachment to an existing message}]
+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")
+ );
+
+// Attach it to the message
+vmime::attachmentHelper::addAttachment(msg, att);
+\end{lstlisting}
+
diff --git a/vmime-master/doc/book/net.tex b/vmime-master/doc/book/net.tex
new file mode 100644
index 0000000..3fab903
--- /dev/null
+++ b/vmime-master/doc/book/net.tex
@@ -0,0 +1,1203 @@
+\chapter{Working with Messaging Services}
+
+% ============================================================================
+\section{Introduction}
+
+In addition to parsing and building MIME messages, VMime also offers a lot of
+features to work with messaging services. This includes connecting to remote
+messaging stores (like IMAP or POP3), local stores (maildir) and transport
+services (send messages over SMTP or local sendmail), through an unified
+interface (see Figure \ref{uml_messaging_module}). That means that you can
+use independently IMAP of POP3 without having to change any line of code.
+
+Source code of {\vexample Example6} covers all features presented in this
+chapter, so it is important you take some time to read it.
+
+\begin{figure}
+ \center\includegraphics[width=0.9\textwidth]
+ {images/messaging-services.png}\endcenter
+ \caption{Overall structure of the messaging module}
+ \label{uml_messaging_module}
+\end{figure}
+
+The interface is composed of five classes:
+
+\begin{itemize}
+\item {\vcode vmime::net::service}: this is the base interface for a
+messaging service. It can be either a store service or a transport
+service.
+
+\item {\vcode vmime::net::serviceFactory}: create instances of a service.
+This is used internally by the session object (see below).
+
+\item {\vcode vmime::net::store}: interface for a store service. A store
+service offers access to a set of folders containing messages. This is
+used for IMAP, POP3 and maildir.
+
+\item {\vcode vmime::net::transport}: interface for a transport service.
+A transport service is capable of sending messages. This is used for
+SMTP and sendmail.
+
+\item {\vcode vmime::net::session}: a session object is used to store the
+parameters used by a service (eg. connection parameters). Each service
+instance is associated with only one session. The session object is capable
+of creating instances of services.
+\end{itemize}
+
+The following classes are specific to store services:
+
+\begin{itemize}
+\item {\vcode vmime::net::folder}: a folder can either contain other folders
+or messages, or both.
+
+\item {\vcode vmime::net::message}: this is the interface for dealing with
+messages. For a given message, you can have access to its flags, its MIME
+structure and you can also extract the whole message data or given parts (if
+supported by the underlying protocol).
+\end{itemize}
+
+
+% ============================================================================
+\section{Working with sessions}
+
+\subsection{Setting properties} % --------------------------------------------
+
+Sessions are used to store configuration parameters for services. They
+contains a set of typed properties that can modify the behaviour of the
+services. Before using a messaging service, you must create and
+initialize a session object:
+
+\begin{lstlisting}
+vmime::shared_ptr <vmime::net::session> theSession = vmime::net::session::create();
+\end{lstlisting}
+
+Session properties include:
+
+\begin{itemize}
+\item connection parameters: host and port to connect to;
+\item authentication parameters: user credentials required to use the
+service (if any);
+\item protocol-specific parameters: enable or disable extensions (eg. APOP
+support in POP3).
+\end{itemize}
+
+Properties are stored using a dotted notation, to specify the service type,
+the protocol name, the category and the name of the property:
+
+\begin{verbatim}
+ {service_type}.{protocol}.category.name
+\end{verbatim}
+
+An example of property is \emph{store.pop3.options.apop} (used to enable or
+disable the use of APOP authentication). The \emph{store.pop3} part is called
+the \emph{prefix}. This allow specifying different values for the same
+property depending on the protocol used.
+
+The session properties are stored in a {\vcode vmime::propertySet} object.
+To set the value of a property, you can use either:
+
+\begin{lstlisting}
+theSession->getProperties().setProperty("property-name", value);
+\end{lstlisting}
+
+or:
+
+\begin{lstlisting}
+theSession->getProperties()["property-name"] = value;
+\end{lstlisting}
+
+
+\subsection{Available properties} % ------------------------------------------
+
+Following is a list of available properties and the protocols they apply to,
+as the time of writing this documentation\footnote{You can get an up-to-date
+list of the properties by running \vexample{Example7}}. For better clarity,
+the prefixes do not appear in this table.
+
+\begin{table}[!ht]
+\noindent\begin{tabularx}{1.0\textwidth}{|l|c|X|c|c|c|c|c|c|c|c|}
+\hline
+ {\bf Property name} &
+ {\bf Type} &
+ {\bf Description} &
+ \verti{\bf POP3} &
+ \verti{\bf POP3S} &
+ \verti{\bf IMAP} &
+ \verti{\bf IMAPS} &
+ \verti{\bf SMTP} &
+ \verti{\bf SMTPS} &
+ \verti{\bf maildir} &
+ \verti{\bf sendmail} \\
+\hline
+\hline
+options.sasl & bool & Set to {\vcode true} to use SASL authentication, if
+available. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\
+\hline
+options.sasl.fallback & bool & Fail if SASL authentication failed (do not
+try other authentication mechanisms). & \vdot & \vdot & \vdot & \vdot &
+\vdot & \vdot & & \\
+\hline
+auth.username\footnote{You should use authenticators
+instead.\label{fn_auth_username}} & string & Set the username of the account
+to connect to. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\
+\hline
+auth.password\footref{fn_auth_username} & string & Set the password of the
+account. & \vdot & \vdot & \vdot & \vdot & \vdot & \vdot & & \\
+\hline
+connection.tls & bool & Set to {\vcode true} to start a secured connection
+using STARTTLS extension, if available. & \vdot & & \vdot & & \vdot & & & \\
+\hline
+connection.tls.required & bool & Fail if a secured connection cannot be
+started. & \vdot & & \vdot & & \vdot & & & \\
+\hline
+server.address & string & Server host name or IP address. &\vdot & \vdot &
+\vdot & \vdot & \vdot & \vdot & & \\
+\hline
+server.port & int & Server port. & \vdot & \vdot & \vdot & \vdot &
+\vdot & \vdot & & \\
+\hline
+server.rootpath & string & Root directory for mail repository (eg.
+\emph{/home/vincent/Mail}). & & & & & & & \vdot & \\
+\hline
+\end{tabularx}
+\caption{Properties common to all protocols}
+\end{table}
+
+\newpage
+These are the protocol-specific options:
+
+\begin{table}[!ht]
+\noindent\begin{tabularx}{1.0\textwidth}{|l|c|X|}
+\hline
+ {\bf Property name} &
+ {\bf Type} &
+ {\bf Description} \\
+% POP3/POP3S
+\hline
+\multicolumn{3}{|c|}{POP3, POP3S} \\
+\hline
+store.pop3.options.apop & bool & Enable or disable authentication with
+APOP (if SASL is enabled, this occurs after all SASL mechanisms have been
+tried). \\
+\hline
+store.pop3.options.apop.fallback & bool & If set to {\vcode true} and
+APOP fails, the authentication process fails (ie. unsecure plain text
+authentication is not used). \\
+\hline
+% SMTP
+\multicolumn{3}{|c|}{SMTP, SMTPS} \\
+\hline
+transport.smtp.options.need-authentication & bool & Set to \emph{true} if
+the server requires to authenticate before sending messages. \\
+\hline
+transport.smtp.options.pipelining & bool & Set to {\vcode false} to disable
+command pipelining, if the server supports it (default is {\vcode true}). \\
+\hline
+transport.smtp.options.chunking & bool & Set to {\vcode false} to disable
+CHUNKING extension, if the server supports it (default is {\vcode true}). \\
+\hline
+% sendmail
+\multicolumn{3}{|c|}{sendmail} \\
+\hline
+transport.sendmail.binpath & string & The path to the \emph{sendmail}
+executable on your system. The default is the one found by the configuration
+script when VMime was built. \\
+\hline
+\end{tabularx}
+\caption{Protocol-specific options}
+\end{table}
+
+
+\subsection{Instanciating services} % ----------------------------------------
+
+You can create a service either by specifying its protocol name, or by
+specifying the URL of the service. Creation by name is deprecated so
+this chapter only presents the latter option.
+
+The URL scheme for connecting to services is:
+
+\begin{verbatim}
+ protocol://[username[:password]@]host[:port]/[root-path]
+\end{verbatim}
+
+\vnote{For local services (ie. \emph{sendmail} and \emph{maildir}), the host
+part is not used, but it must not be empty (you can use "localhost").}
+
+The following table shows an example URL for each service:
+
+\noindent\begin{tabularx}{1.0\textwidth}{|c|X|}
+\hline
+ {\bf Service} &
+ {\bf Connection URL} \\
+\hline
+imap, imaps & {\tt imap://imap.example.com},
+{\tt imaps://vincent:pass@example.com} \\
+\hline
+pop3, pop3s & {\tt pop3://pop3.example.com} \\
+\hline
+smtp, smtps & {\tt smtp://smtp.example.com} \\
+\hline
+maildir & {\tt maildir://localhost/home/vincent/Mail} (host not used) \\
+\hline
+sendmail & {\tt sendmail://localhost} (host not used, always localhost) \\
+\hline
+\end{tabularx}
+
+\newpage
+
+When you have the connection URL, instanciating the service is quite simple.
+Depending on the type of service, you will use either {\vcode getStore()} or
+{\vcode getTransport()}. For example, for store services, use:
+
+\begin{lstlisting}
+vmime::utility:url url("imap://user:pass@imap.example.com");
+vmime::shared_ptr <vmime::net::store> st = sess->getStore(url);
+\end{lstlisting}
+
+and for transport services:
+
+\begin{lstlisting}
+vmime::utility:url url("smtp://smtp.example.com");
+vmime::shared_ptr <vmime::net::transport> tr = sess->getTransport(url);
+\end{lstlisting}
+
+
+% ============================================================================
+\section{User credentials and authenticators}
+
+Some services need some user credentials (eg. username and password) to open
+a session. In VMime, user credentials can be specified in the session
+properties or by using a custom authenticator (callback).
+
+\begin{lstlisting}[caption={Setting user credentials using session
+properties}]
+vmime::shared_ptr <vmime::net::session> sess; // Suppose we have a session
+
+sess->getProperties()["store.imap.auth.username"] = "vincent";
+sess->getProperties()["store.imap.auth.password"] = "my-password";
+\end{lstlisting}
+
+Although not recommended, you can also specify username and password
+directly in the connection URL,
+ie: \emph{imap://username:password@imap.example.com/}. This works only for
+services requiring an username and a password as user credentials, and no
+other information.
+
+Sometimes, it may not be very convenient to set username/password in the
+session properties, or not possible (eg. extended SASL mechanisms) . That's
+why VMime offers an alternate way of getting user credentials: the
+{\vcode authenticator} object. Basically, an authenticator is an object that
+can return user credentials on-demand (like a callback).
+
+Currently, there are two types of authenticator in VMime: a basic
+authenticator (class {\vcode vmime::security::authenticator}) and, if SASL
+support is enabled, a SASL authenticator
+(class {\vcode vmime::security::sasl::SASLAuthenticator}). Usually, you
+should use the default implementations, or at least make your own
+implementation inherit from them.
+
+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 {
+
+ std::cout << "Enter your username: " << std::endl;
+
+ vmime::string res;
+ std::getline(std::cin, res);
+
+ return res;
+ }
+
+ const string getPassword() const {
+
+ std::cout << "Enter your password: " << std::endl;
+
+ vmime::string res;
+ std::getline(std::cin, res);
+
+ return res;
+ }
+};
+\end{lstlisting}
+
+This is how to use it:
+
+\begin{lstlisting}
+// First, create a session
+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>()
+);
+\end{lstlisting}
+
+\vnote{An authenticator object should be used with one and only one service
+at a time. This is required because the authentication process may need to
+retrieve the service name (SASL).}
+
+Of course, this example is quite simplified. For example, if several
+authentication mechanisms are tried, the user may be requested to enter the
+same information multiple times. See {\vexample Example6} for a more complex
+implementation of an authenticator, with caching support.
+
+If you want to use SASL (ie. if \emph{options.sasl} is set to \emph{true}),
+your authenticator must inherit from
+{\vcode vmime::security::sasl::SASLAuthenticator} or
+{\vcode vmime::security::sasl::defaultSASLAuthenticator}, even if you do not
+use the SASL-specific methods {\vcode getAcceptableMechanisms()} and
+{\vcode setSASLMechanism()}. Have a look at {\vexample Example6} to see an
+implementation of an SASL authenticator.
+
+\begin{lstlisting}[caption={A simple SASL authenticator}]
+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,
+ 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.
+ //
+ // If you do not want to bother with this, you can simply return
+ // the default list, which is ordered by security strength.
+ return defaultSASLAuthenticator::
+ getAcceptableMechanisms(available, suggested);
+ }
+
+ void setSASLMechanism(const vmime::shared_ptr <mechanism>& mech) {
+
+ // This is called when the authentication process is going to
+ // try the specified mechanism.
+ //
+ // The mechanism name is in mech->getName()
+
+ defaultSASLAuthenticator::setSASLMechanism(mech);
+ }
+
+ // ...implement getUsername() and getPassword()...
+};
+\end{lstlisting}
+
+
+% ============================================================================
+\section{Using transport service}
+
+You have two possibilities for giving message data to the service when you
+want to send a message:
+
+\begin{itemize}
+\item either you have a reference to a message (type {\vcode vmime::message})
+and you can simply call {\vcode send(msg)};
+\item or you only have raw message data (as a string, for example), and you
+have to call the second overload of {\vcode send()}, which takes additional
+parameters (corresponding to message envelope);
+\end{itemize}
+
+The following example illustrates the use of a transport service to send a
+message using the second method:
+
+\begin{lstlisting}[caption={Using a transport service}]
+const vmime::string msgData =
+ "From: me@example.org \r\n"
+ "To: you@example.org \r\n"
+ "Date: Sun, Oct 30 2005 17:06:42 +0200 \r\n"
+ "Subject: Test \r\n"
+ "\r\n"
+ "Message body";
+
+// Create a new session
+vmime::utility::url url("smtp://example.com");
+
+vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create();
+
+// Create an instance of the transport service
+vmime::shared_ptr <vmime::net::transport> tr = sess->getTransport(url);
+
+// Connect it
+tr->connect();
+
+// Send the message
+vmime::utility::inputStreamStringAdapter is(msgData);
+
+vmime::mailbox from("me@example.org");
+vmime::mailboxList to;
+to.appendMailbox(vmime::make_shared <vmime::mailbox>("you@example.org"));
+
+tr->send(
+ /* expeditor */ from,
+ /* recipient(s) */ to,
+ /* data */ is,
+ /* total length */ msgData.length()
+);
+
+// We have finished using the service
+tr->disconnect();
+\end{lstlisting}
+
+\vnote{Exceptions can be thrown at any time when using a service. For better
+clarity, exceptions are not caught here, but be sure to catch them in your own
+application to provide error feedback to the user.}
+
+If you use SMTP, you can enable authentication by setting some properties
+on the session object ({\vcode service::setProperty()} is a shortcut for
+setting properties on the session with the correct prefix):
+
+\begin{lstlisting}
+tr->setProperty("options.need-authentication", true);
+tr->setProperty("auth.username", "user");
+tr->setProperty("auth.password", "password");
+\end{lstlisting}
+
+
+% ============================================================================
+\section{Using store service}
+
+\subsection{Connecting to a store} % -----------------------------------------
+
+The first basic step for using a store service is to connect to it. The
+following example shows how to initialize a session and instanciate the
+store service:
+
+\begin{lstlisting}[caption={Connecting to a store service}]
+// Create a new session
+vmime::utility::url url("imap://vincent:password@imap:example.org");
+
+vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create();
+
+// Create an instance of the transport service
+vmime::shared_ptr <vmime::net::store> store = sess->getStore(url);
+
+// Connect it
+store->connect();
+\end{lstlisting}
+
+\vnote{{\vexample Example6} contains a more complete example for connecting
+to a store service, with support for a custom authenticator.}
+
+\subsection{Opening a folder} % ----------------------------------------------
+
+You can open a folder using two different access modes: either in
+\emph{read-only} mode (where you can only read message flags and contents), or
+in \emph{read-write} mode (where you can read messages, but also delete them
+or add new ones). When you have a reference to a folder, simply call the
+{\vcode open()} method with the desired access mode:
+
+\begin{lstlisting}
+folder->open(vmime::net::folder::MODE_READ_WRITE);
+\end{lstlisting}
+
+\vnote{Not all stores support the \emph{read-write} mode. By default, if the
+\emph{read-write} mode is not available, the folder silently fall backs on
+the \emph{read-only} mode, unless the \emph{failIfModeIsNotAvailable} argument
+to {\vcode open()} is set to true.}
+
+Call {\vcode getDefaultFolder()} on the store to obtain a reference to the
+default folder, which is usually the INBOX folder (where messages arrive when
+they are received).
+
+You can also open a specific folder by specifying its path. The following
+example will open a folder named \emph{bar}, which is a child of \emph{foo}
+in the root folder:
+
+\begin{lstlisting}[caption={Opening a folder from its path}]
+vmime::net::folder::path path;
+path /= vmime::net::folder::path::component("foo");
+path /= vmime::net::folder::path::component("bar");
+
+vmime::shared_ptr <vmime::net::folder> fld = store->getFolder(path);
+fld->open(vmime::net::folder::MODE_READ_WRITE);
+\end{lstlisting}
+
+\vnote{You can specify a path as a string as there is no way to get the
+separator used to delimitate path components. Always use {\vcode operator/=}
+or {\vcode appendComponent}.}
+
+\vnote{Path components are of type {\vcode vmime::word}, which means that
+VMime supports folder names with extended characters, not only 7-bit
+US-ASCII. However, be careful that this may not be supported by the
+underlying store protocol (IMAP supports it, because it uses internally a
+modified UTF-7 encoding).}
+
+\subsection{Fetching messages} % ---------------------------------------------
+
+You can fetch some information about a message without having to download the
+whole message. Moreover, folders support fetching for multiple messages in
+a single request, for better performance. The following items are currently
+available for fetching:
+
+\begin{itemize}
+\item {\bf envelope}: sender, recipients, date and subject;
+\item {\bf structure}: MIME structure of the message;
+\item {\bf content-info}: content-type of the root part;
+\item {\bf flags}: message flags;
+\item {\bf size}: message size;
+\item {\bf header}: retrieve all the header fields of a message;
+\item {\bf uid}: unique identifier of a message;
+\item {\bf importance}: fetch header fields suitable for use with
+{\vcode misc::importanceHelper}.
+\end{itemize}
+
+\vnote{Not all services support all fetchable items. Call
+{\vcode getFetchCapabilities()} on a folder to know which information can be
+fetched by a service.}
+
+The following code shows how to list all the messages in a folder, and
+retrieve basic information to show them to the user:
+
+\begin{lstlisting}[caption={Fetching information about multiple messages}]
+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,
+ vmime::net::fetchAttributes::FLAGS |
+ vmime::net::fetchAttributes::ENVELOPE
+);
+
+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) {
+ std::cout << " - is read" << std::endl;
+ }
+ if (flags & vmime::net::message::FLAG_DELETED) {
+ std::cout << " - is deleted" << std::endl;
+ }
+
+ vmime::shared_ptr <const vmime::header> hdr = msg->getHeader();
+
+ std::cout << " - sent on " << hdr->Date()->generate() << std::endl;
+ std::cout << " - sent by " << hdr->From()->generate() << std::endl;
+}
+\end{lstlisting}
+
+IMAP supports fetching specific header fields of a message. Here is how to use
+the {\vcode fetchAttributes} object to do it:
+
+\begin{lstlisting}[caption={Using fetchAttributes object to fetch specific header fields of a message}]
+
+// Fetch message flags and the "Received" and "X-Mailer" header fields
+vmime::net::fetchAttributes fetchAttribs;
+fetchAttribs.add(vmime::net::fetchAttributes::FLAGS);
+fetchAttribs.add("Received");
+fetchAttribs.add("X-Mailer");
+
+folder->fetchMessages(allMessages, fetchAttribs);
+\end{lstlisting}
+
+
+\subsection{Extracting messages and parts}
+
+To extract the whole contents of a message (including headers), use the
+{\vcode extract()} method on a {\vcode vmime::net::message} object. The
+following example extracts the first message in the default folder:
+
+\begin{lstlisting}[caption={Extracting messages}]
+// Get a reference to the folder and to its first message
+vmime::shared_ptr <vmime::net::folder> folder = store->getDefaultFolder();
+vmime::shared_ptr <vmime::net::message> msg = folder->getMessage(1);
+
+// Write the message contents to the standard output
+vmime::utility::outputStreamAdapter out(std::cout);
+msg->extract(out);
+\end{lstlisting}
+
+Some protocols (like IMAP) also support the extraction of specific MIME parts
+of a message without downloading the whole message. This can save bandwidth
+and time. The method {\vcode extractPart()} is used in this case:
+
+\begin{lstlisting}[caption={Extracting a specific MIME part of a message}]
+// Fetching structure is required before extracting a part
+folder->fetchMessage(msg, vmime::net::fetchAttributes::STRUCTURE);
+
+// Now, we can extract the part
+msg->extractPart(msg->getStructure()->getPartAt(0)->getPartAt(1));
+\end{lstlisting}
+
+Suppose we have a message with the following structure:
+
+\begin{verbatim}
+ multipart/mixed
+ text/html
+ image/jpeg [*]
+\end{verbatim}
+
+The previous example will extract the header and body of the \emph{image/jpeg}
+part.
+
+\subsection{Deleting messages} % ---------------------------------------------
+
+The following example will delete the second and the third message from the
+store.
+
+\begin{lstlisting}[caption={Deleting messages}]
+vmime::shared_ptr <vmime::net::folder> folder = store->getDefaultFolder();
+
+folder->deleteMessages(vmime::net::messageSet::byNumber(/* from */ 2, /* to */ 3));
+
+// This is equivalent
+std::vector <int> nums;
+nums.push_back(2);
+nums.push_back(3);
+folder->deleteMessages(vmime::net::messageSet::byNumber(nums));
+
+// This is also equivalent (but will require 2 roundtrips to server)
+folder->deleteMessages(vmime::net::messageSet::byNumber(2));
+folder->deleteMessages(vmime::net::messageSet::byNumber(2)); // renumbered, 3 becomes 2
+\end{lstlisting}
+
+\subsection{Events} % --------------------------------------------------------
+
+As a result of executing some operation (or from time to time, even if no
+operation has been performed), a store service can send events to notify you
+that something has changed (eg. the number of messages in a folder). These
+events may allow you to update the user interface associated to a message
+store.
+
+Currently, there are three types of event:
+
+\begin{itemize}
+\item {\bf message change}: sent when the number of messages in a folder
+has changed (ie. some messages have been added or removed);
+\item {\bf message count change}: sent when one or more message(s) have
+changed (eg. flags or deleted status);
+\item {\bf folder change}: sent when a folder has been created, renamed or
+deleted.
+\end{itemize}
+
+You can register a listener for each event type by using the corresponding
+methods on a {\vcode folder} object: {\vcode addMessageChangedListener()},
+{\vcode addMessageCountListener()} or {\vcode addFolderListener()}. For more
+information, please read the class documentation for
+{\vcode vmime::net::events} namespace.
+
+
+% ============================================================================
+\section{Handling timeouts}
+
+Unexpected errors can occur while messaging services are performing
+operations and waiting a response from the server (eg. server stops
+responding, network link falls down). As all operations as synchronous,
+they can be ``blocked'' a long time before returning (in fact, they loop
+until they either receive a response from the server, or the underlying
+socket system returns an error).
+
+VMime provides a mechanism to control the duration of operations. This
+mechanism allows the program to cancel an operation that is currently
+running.
+
+An interface called {\vcode timeoutHandler} is provided:
+
+\begin{lstlisting}
+class timeoutHandler : public object {
+
+ /** Called to test if the time limit has been reached.
+ *
+ * @return true if the timeout delay is elapsed
+ */
+ virtual const bool isTimeOut() = 0;
+
+ /** Called to reset the timeout counter.
+ */
+ virtual void resetTimeOut() = 0;
+
+ /** Called when the time limit has been reached (when
+ * isTimeOut() returned true).
+ *
+ * @return true to continue (and reset the timeout)
+ * or false to cancel the current operation
+ */
+ virtual const bool handleTimeOut() = 0;
+};
+\end{lstlisting}
+
+While the operation runs, the service calls {\vcode isTimeout()} at variable
+intervals. If the {\vcode isTimeout()} function returns {\vcode true},
+then {\vcode handleTimeout()} is called. If the {\vcode handleTimeout()}
+function returns {\vcode false}, the operation is cancelled and
+an {\vcode operation\_timed\_out} exception is thrown. Else, if
+{\vcode handleTimeout()} returns true, the operation continues and the
+timeout counter is reset.
+The function {\vcode resetTimeout()} is called each time data has
+been received from the server to reset the timeout delay.
+
+When using a service, a default timeout handler is set: if an operation
+is blocked for more than 30 seconds (ie. network link is down and no data
+was received since 30 seconds), an {\vcode operation\_timed\_out} exception
+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 {
+
+public:
+
+ myTimeoutHandler() {
+
+ m_startTime = time(NULL);
+ }
+
+ const bool isTimeOut() {
+
+ return time(NULL) >= m_startTime + 30; // 30 seconds timeout
+ }
+
+ void resetTimeOut() {
+
+ m_startTime = time(NULL);
+ }
+
+ const bool handleTimeOut() {
+
+ std::cout << "Operation timed out." << std::endl;
+ << "Press [Y] to continue, or [N] to "
+ << "cancel the operation." << std::endl;
+
+ std::string response;
+ std::cin >> response;
+
+ return response == "y" || response == "Y";
+ }
+
+private:
+
+ time_t m_startTime;
+};
+\end{lstlisting}
+
+To make the service use your timeout handler, you need to write a factory
+class, to allow the service to create instances of the handler class. This
+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 {
+
+public:
+
+ ref <timeoutHandler> create() {
+
+ return vmime::make_shared <myTimeoutHandler>();
+ }
+};
+\end{lstlisting}
+
+Then, call the {\vcode setTimeoutHandlerFactory()} method on the service object
+to set the timeout handler factory to use during the session:
+
+\begin{lstlisting}
+theService->setTimeoutHandlerFactory(vmime::make_shared <myTimeoutHandlerFactory>());
+\end{lstlisting}
+
+
+% ============================================================================
+\newpage
+\section{Secured connection using TLS/SSL}
+
+\subsection{Introduction} % --------------------------------------------------
+
+If you have enabled TLS support in VMime, you can configure messaging services
+so that they use a secured connection.
+
+Quoting from RFC-2246 - the TLS 1.0 protocol specification: \emph{`` The TLS
+protocol provides communications privacy over the Internet. The protocol
+allows client/server applications to communicate in a way that is designed
+to prevent eavesdropping, tampering, or message forgery.''}
+
+TLS has the following advantages:
+
+\begin{itemize}
+\item authentication: server identity can be verified;
+\item privacy: transmission of data between client and server cannot be read
+by someone in the middle of the connection;
+\item integrity: original data which is transferred between a client and a
+server can not be modified by an attacker without being detected.
+\end{itemize}
+
+\vnote{What is the difference between SSL and TLS? SSL is a protocol designed
+by Netscape. TLS is a standard protocol, and is partly based on version 3 of
+the SSL protocol. The two protocols are not interoperable, but TLS does
+support a mechanism to back down to SSL 3.}
+
+VMime offers two possibilities for using a secured connection:
+
+\begin{itemize}
+\item you can connect to a server listening on a special port (eg. IMAPS
+instead of IMAP): this is the classical use of SSL, but is now deprecated;
+\item connect to a server listening on the default port, and then begin a
+secured connection: this is STARTTLS.
+\end{itemize}
+
+
+\subsection{Setting up a secured connection} % -------------------------------
+
+\subsubsection{Connecting to a ``secured'' port} % ...........................
+
+To use the classical SSL/TLS way, simply use the ``S'' version of the protocol
+to connect to the server (eg. \emph{imaps} instead of \emph{imap}). This is
+currently available for SMTP, POP3 and IMAP.
+
+\begin{lstlisting}
+vmime::shared_ptr <vmime::net::store> store =
+ theSession->getStore(vmime::utility::url("imaps://example.org"));
+\end{lstlisting}
+
+\subsubsection{Using STARTTLS} % .............................................
+
+To make the service start a secured session using the STARTTLS method, simply
+set the \emph{connection.tls} property:
+
+\begin{lstlisting}
+theService->setProperty("connection.tls", true);
+\end{lstlisting}
+
+\vnote{If, for some reason, a secured connection cannot be started, the
+default behaviour is to fallback on a normal connection. To make
+{\vcode connect()} fail if STARTTLS fails, set the
+\emph{connection.tls.required} to \emph{true}.}
+
+\subsection{Certificate verification} % --------------------------------------
+
+\subsubsection{How it works} % ...............................................
+
+If you tried the previous examples, a
+{\vcode certificateException} might have been thrown.
+This is because the default certificate verifier in VMime did not manage to
+verify the certificate, and so could not trust it.
+
+Basically, when you connect to a server using TLS, the server responds with
+a list of certificates, called a certificate chain (usually, certificates are
+of type X.509\footnote{And VMime currently supports only X.509 certificates}).
+The certificate chain is ordered so that the first certificate is the subject
+certificate, the second is the subject's issuer one, the third is the issuer's
+issuer, and so on.
+
+To decide whether the server can be trusted or not, you have to verify that
+\emph{each} certificate is valid (ie. is trusted). For more information
+about X.509 and certificate verification, see related articles on Wikipedia
+\footnote{See \url{http://wikipedia.org/wiki/Public\_key\_certificate}}.
+
+\subsubsection{Using the default certificate verifier} % .....................
+
+The default certificate verifier maintains a list of root (CAs) and user
+certificates that are trusted. By default, the list is empty. So, you have
+to initialize it before using the verifier.
+
+The algorithm\footnote{See
+\url{http://wikipedia.org/wiki/Certification\_path\_validation\_algorithm}}
+used is quite simple:
+
+\begin{enumerate}
+\item for every certificate in the chain, verify that the certificate has been
+issued by the next certificate in the chain;
+\item for every certificate in the chain, verify that the certificate is valid
+at the current time;
+\item ensure that the first certificate's subject name matches the hostname
+of the server;
+\item decide whether the subject's certificate can be trusted:
+ \begin{itemize}
+ \item first, verify that the the last certificate in the chain was
+ issued by a third-party that we trust (root CAs);
+ \item if the issuer certificate cannot be verified against root CAs,
+ compare the subject's certificate against the trusted certificates
+ (the certificates the user has decided to trust).
+ \end{itemize}
+\end{enumerate}
+
+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) {
+
+ std::ifstream certFile;
+ certFile.open(path.c_str(), std::ios::in | std::ios::binary);
+
+ if (!certFile) {
+ // ...handle error...
+ }
+
+ vmime::utility::inputStreamAdapter is(certFile);
+ vmime::shared_ptr <vmime::security::cert::X509Certificate> cert;
+
+ cert = vmime::security::cert::X509Certificate::import(is);
+
+ return cert;
+}
+\end{lstlisting}
+
+Then, we can use the {\vcode loadX509CertificateFromFile} function to load
+certificates and initialize the certificate verifier:
+
+\begin{lstlisting}[caption={Using the default certificate verifier}]
+vmime::shared_ptr <vmime::security::cert::defaultCertificateVerifier> vrf =
+ vmime::make_shared <vmime::security::cert::defaultCertificateVerifier>();
+
+// Load root CAs (such as Verisign or Thawte)
+std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > rootCAs;
+
+rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca1.cer");
+rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca2.cer");
+rootCAs.push_back(loadX509CertificateFromFile("/path/to/root-ca3.cer");
+
+vrf->setX509RootCAs(rootCAs);
+
+// Then, load certificates that the user explicitely chose to trust
+std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > trusted;
+
+trusted.push_back(loadX509CertificateFromFile("/path/to/trusted-site1.cer");
+trusted.push_back(loadX509CertificateFromFile("/path/to/trusted-site2.cer");
+
+vrf->setX509TrustedCerts(trusted);
+\end{lstlisting}
+
+
+\subsubsection{Writing your own certificate verifier} % ......................
+
+If you need to do more complex verifications on certificates, you will have to
+write your own verifier. Your verifier should inherit from the
+{\vcode vmime::security::cert::certificateVerifier} class and implement the
+method {\vcode verify()}. Then, if the specified certificate chain is trusted,
+simply return from the function, or else throw a
+{\vcode certificateException}.
+
+The following example shows how to implement an interactive certificate
+verifier which relies on the user's decision, and nothing else (you SHOULD NOT
+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 {
+
+public:
+
+ void verify(const vmime::shared_ptr <certificateChain>& certs) {
+
+ // Obtain the subject's certificate
+ vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0);
+
+ std::cout << std::endl;
+ std::cout << "Server sent a '" << cert->getType() << "'"
+ << " certificate." << std::endl;
+ std::cout << "Do you want to accept this certificate? (Y/n) ";
+ std::cout.flush();
+
+ std::string answer;
+ std::getline(std::cin, answer);
+
+ 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();
+ }
+};
+\end{lstlisting}
+
+\vnote{In production code, it may be a good idea to remember user's decisions
+about which certificates to trust and which not. See {\vexample Example6} for
+a basic cache implementation.}
+
+Finally, to make the service use your own certificate verifier, simply write:
+
+\begin{lstlisting}
+theService->setCertificateVerifier(vmime::make_shared <myCertVerifier>());
+\end{lstlisting}
+
+\subsection{SSL/TLS Properties} % --------------------------------------------
+
+If you want to customize behavior or set some options on TLS/SSL connection,
+you may use the TLSProperties object, and pass it to the service session. The
+TLS/SSL options must be set {\em before} creating any service with the session
+(ie. before calling either {\vcode getStore()} or {\vcode getTransport()} on
+the session), or they will not be used.
+
+The following example shows how to set the cipher suite preferences for TLS:
+
+\begin{lstlisting}[caption={Setting TLS cipher suite preferences}]
+vmime::shared_ptr <vmime::net::session> sess = /* ... */;
+
+vmime::shared_ptr <vmime::net::tls::TLSProperties> tlsProps =
+ vmime::make_shared <vmime::net::tls::TLSProperties>();
+
+// for OpenSSL
+tlsProps->setCipherString("HIGH:!ADH:@STRENGTH");
+
+// for GNU TLS
+tlsProps->setCipherString("NORMAL:%SSL3_RECORD_VERSION");
+
+sess->setTLSProperties(tlsProps);
+\end{lstlisting}
+
+Please note that the cipher suite string format and meaning depend on the
+underlying TLS library (either OpenSSL or GNU TLS):
+
+\begin{itemize}
+\item for GNU TLS, read this: \newline
+\url{http://gnutls.org/manual/html\_node/Priority-Strings.html}
+
+\item for OpenSSL, read this: \newline
+\url{http://www.openssl.org/docs/apps/ciphers.html#CIPHER\_STRINGS}
+\end{itemize}
+
+You may also set cipher suite preferences using predefined constants that
+map to generic security modes:
+
+\begin{lstlisting}[caption={Setting TLS cipher suite preferences using predefined modes}]
+sess->setCipherSuite(vmime::net::tls::TLSProperties::CIPHERSUITE_HIGH);
+\end{lstlisting}
+
+The following constants are available:
+
+\noindent\begin{tabularx}{1.0\textwidth}{|l|X|}
+\hline
+ {\bf Constant} &
+ {\bf Meaning} \\
+\hline
+ CIPHERSUITE\_HIGH &
+ High encryption cipher suites ($>$ 128 bits) \\
+\hline
+ CIPHERSUITE\_MEDIUM &
+ Medium encryption cipher suites ($>=$ 128 bits) \\
+\hline
+ CIPHERSUITE\_LOW &
+ Low encryption cipher suites ($>=$ 64 bits) \\
+\hline
+ CIPHERSUITE\_DEFAULT &
+ Default cipher suite (actual cipher suites used depends
+ on the underlying SSL/TLS library) \\
+\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...}"").
diff --git a/vmime-master/doc/book/start.tex b/vmime-master/doc/book/start.tex
new file mode 100644
index 0000000..f169330
--- /dev/null
+++ b/vmime-master/doc/book/start.tex
@@ -0,0 +1,111 @@
+\chapter{Getting Started}
+
+% ============================================================================
+\section{Using VMime in your programs}
+
+First, make sure you have successfully compiled and installed VMime using the
+instructions described in Chapter \ref{chapter_building}. To use VMime in your
+program, you simply have to include VMime headers:
+
+\begin{lstlisting}
+#include <vmime/vmime.hpp>
+\end{lstlisting}
+
+\vnote{for versions older than 0.6.1, include $<$vmime/vmime$>$.}
+
+As of version 0.6.1, VMime uses {\vcode pkg-config} to simplify compiling and
+linking with VMime. The {\vcode pkg-config} utility is used to detect the
+appropriate compiler and linker flags needed for a library.
+
+You can simply build your program with:
+
+\begin{verbatim}
+ $ g++ `pkg-config --cflags --libs vmime` -static -o myprog myprog.cpp
+\end{verbatim}
+
+to use the static version, or with:
+
+\begin{verbatim}
+ $ g++ `pkg-config --cflags vmime` -o myprog myprog.cpp `pkg-config --libs vmime`
+\end{verbatim}
+
+to use the shared version.
+
+\vnote{it is highly recommended that you link your program against the shared
+version of the library.}
+
+All VMime classes and global functions are defined in the namespace
+{\vcode vmime}, so prefix explicitely all your declarations which use VMime
+with {\vcode vmime::}, or import the {\vcode vmime} namespace into the global
+namespace with the C++ keywork {\vcode using} (not recommended, though).
+
+
+% ============================================================================
+\section{If you can not (or do not want to) use {\vcode pkg-config}}
+
+{\bf Linking with the shared library (.so):} compile your program with the
+{\vcode -lvmime} flag. You can use the -L path flag if the library file is
+not in a standard path (ie. not in /usr/lib or /usr/local/lib).
+
+\vnote{if you want to link your program with the shared version of VMime
+library, make sure the library has been compiled using CMake build system
+({\vcode make}, then {\vcode make install}). When you compile with SCons,
+only the static library is built and installed.}
+
+{\bf Linking with the static library (.a):} follow the same procedure as for
+shared linking and append the flag -static to force static linking. Although
+static linking is possible, you are encouraged to use the shared (dynamic)
+version of the library.
+
+
+% ============================================================================
+\section{Platform-dependent code}
+
+While the most part of VMime code is pure ANSI C++, there are some features
+that are platform-specific: file management (opening/reading/writing files),
+network code (socket, DNS resolution) and time management. All the
+non-portable stuff is done by a bridge object called a platform handler (see
+{\vcode vmime::platform}).
+
+If your platform is POSIX-compatible (eg. GNU/Linux, *BSD) or is Windows,
+then you are lucky: VMime has built-in support for these platforms. If not,
+don't worry, the sources of the built-in platform handlers are very well
+documented, so writing you own should not be very difficult.
+
+If your VMime version is $<=$ 0.9.1, you should tell VMime which platform
+handler you want to use at the beginning of your program (before using
+\emph{any} VMime object, or calling \emph{any} VMime global function).
+
+So, if your platform is POSIX, your program should look like this:
+
+\begin{lstlisting}[caption={Initializing VMime and the platform handler}]
+#include <vmime/vmime.hpp>
+#include <vmime/platforms/posix/posixHandler.hpp>
+
+int main() {
+
+ vmime::platform::
+ setHandler <vmime::platforms::posix::posixHandler>();
+
+ // Now, you can use VMime
+ // ...do what you want, it's your program...
+}
+\end{lstlisting}
+
+For using VMime on Windows, include
+{\vcode vmime/platforms/windows/windowsHandler.hpp} and use the following line
+to initialize the platform handler:
+
+\begin{lstlisting}
+vmime::platform::
+ setHandler <vmime::platforms::windows::windowsHandler>();
+\end{lstlisting}
+
+\vnote{since version 0.9.2, this is not needed any more: the platform
+handler is installed automatically using the platform detected during the
+build configuration.}
+
+\vnote{since version 0.8.1, {\vcode vmime::platformDependant} was renamed
+to {\vcode vmime::platform}. The old name has been kept for compatibility
+but it is recommended that you update your code, if needed.}
+
diff --git a/vmime-master/examples/CMakeLists.txt b/vmime-master/examples/CMakeLists.txt
new file mode 100644
index 0000000..9e6998f
--- /dev/null
+++ b/vmime-master/examples/CMakeLists.txt
@@ -0,0 +1,38 @@
+
+IF(VMIME_BUILD_SAMPLES)
+
+ ADD_SUBDIRECTORY(viewer)
+
+ FILE(
+ GLOB
+ VMIME_SAMPLES_SRC_FILES
+ ${CMAKE_SOURCE_DIR}/examples/*.cpp
+ )
+
+ # Build one file for each sample
+ FOREACH(VMIME_SAMPLE_SRC_FILE ${VMIME_SAMPLES_SRC_FILES})
+
+ GET_FILENAME_COMPONENT(VMIME_SAMPLE_NAME "${VMIME_SAMPLE_SRC_FILE}" NAME_WE)
+
+ ADD_EXECUTABLE(
+ ${VMIME_SAMPLE_NAME}
+ ${VMIME_SAMPLE_SRC_FILE}
+ )
+
+ TARGET_LINK_LIBRARIES(
+ ${VMIME_SAMPLE_NAME}
+ ${VMIME_LIBRARY_NAME}
+ )
+
+ ADD_DEPENDENCIES(
+ ${VMIME_SAMPLE_NAME}
+ ${VMIME_LIBRARY_NAME}
+ )
+
+ ENDFOREACH()
+
+ELSE()
+
+ MESSAGE(FATAL_ERROR "Examples are not to be built (set VMIME_BUILD_SAMPLES to YES.")
+
+ENDIF()
diff --git a/vmime-master/examples/example1.cpp b/vmime-master/examples/example1.cpp
new file mode 100644
index 0000000..c698fa7
--- /dev/null
+++ b/vmime-master/examples/example1.cpp
@@ -0,0 +1,107 @@
+//
+// 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.
+//
+
+//
+// EXAMPLE DESCRIPTION:
+// ====================
+// This sample program demonstrate the use of the messageBuilder component
+// to build a simple message.
+//
+// For more information, please visit:
+// http://www.vmime.org/
+//
+
+#include <iostream>
+#include <locale>
+#include <clocale>
+
+#include "vmime/vmime.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+
+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 {
+ std::locale::global(std::locale(""));
+ } catch (std::exception &) {
+ std::setlocale(LC_ALL, "");
+ }
+
+ try {
+
+ vmime::messageBuilder mb;
+
+ // Fill in the basic fields
+ mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
+
+ vmime::addressList to;
+ to.appendAddress(vmime::make_shared <vmime::mailbox>("you@elsewhere.com"));
+
+ mb.setRecipients(to);
+
+ vmime::addressList bcc;
+ bcc.appendAddress(vmime::make_shared <vmime::mailbox>("you-bcc@nowhere.com"));
+
+ mb.setBlindCopyRecipients(bcc);
+
+ 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."
+ )
+ );
+
+ // Construction
+ vmime::shared_ptr <vmime::message> msg = mb.construct();
+
+ // Raw text generation
+ std::cout << "Generated message:" << std::endl;
+ std::cout << "==================" << std::endl;
+
+ vmime::utility::outputStreamAdapter out(std::cout);
+ msg->generate(out);
+
+ // VMime exception
+ } catch (vmime::exception& e) {
+
+ std::cout << "vmime::exception: " << e.what() << std::endl;
+ throw;
+
+ // Standard exception
+ } catch (std::exception& e) {
+
+ std::cout << "std::exception: " << e.what() << std::endl;
+ throw;
+ }
+
+ std::cout << std::endl;
+
+ return 0;
+}
diff --git a/vmime-master/examples/example2.cpp b/vmime-master/examples/example2.cpp
new file mode 100644
index 0000000..da01d75
--- /dev/null
+++ b/vmime-master/examples/example2.cpp
@@ -0,0 +1,121 @@
+//
+// 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.
+//
+
+//
+// EXAMPLE DESCRIPTION:
+// ====================
+// This sample program demonstrate the use of the messageBuilder component
+// to build a simple message with an attachment.
+//
+// For more information, please visit:
+// http://www.vmime.org/
+//
+
+#include <iostream>
+#include <locale>
+#include <clocale>
+
+#include "vmime/vmime.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+
+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 {
+ std::locale::global(std::locale(""));
+ } catch (std::exception &) {
+ std::setlocale(LC_ALL, "");
+ }
+
+ try {
+
+ vmime::messageBuilder mb;
+
+ // Fill in the basic fields
+ mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
+
+ vmime::addressList to;
+ to.appendAddress(vmime::make_shared <vmime::mailbox>("you@elsewhere.com"));
+
+ mb.setRecipients(to);
+
+ vmime::addressList bcc;
+ bcc.appendAddress(vmime::make_shared <vmime::mailbox>("you-bcc@nowhere.com"));
+
+ mb.setBlindCopyRecipients(bcc);
+
+ 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."
+ )
+ );
+
+ // 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
+ );
+
+ a->getFileInfo().setFilename("example2.cpp");
+ a->getFileInfo().setCreationDate(vmime::datetime("30 Apr 2003 14:30:00 +0200"));
+
+ mb.attach(a);
+
+ // Construction
+ vmime::shared_ptr <vmime::message> msg = mb.construct();
+
+ // Raw text generation
+ vmime::string dataToSend = msg->generate();
+
+ std::cout << "Generated message:" << std::endl;
+ std::cout << "==================" << std::endl;
+ std::cout << std::endl;
+ std::cout << dataToSend << std::endl;
+
+ // VMime exception
+ } catch (vmime::exception& e) {
+
+ std::cout << "vmime::exception: " << e.what() << std::endl;
+ throw;
+
+ // Standard exception
+ } catch (std::exception& e) {
+
+ std::cout << "std::exception: " << e.what() << std::endl;
+ throw;
+ }
+
+ std::cout << std::endl;
+
+ return 0;
+}
diff --git a/vmime-master/examples/example3.cpp b/vmime-master/examples/example3.cpp
new file mode 100644
index 0000000..b452225
--- /dev/null
+++ b/vmime-master/examples/example3.cpp
@@ -0,0 +1,153 @@
+//
+// 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.
+//
+
+//
+// EXAMPLE DESCRIPTION:
+// ====================
+// This sample program demonstrate the use of the messageBuilder component
+// to build a complex message (HTML content, plain text and embedded image).
+//
+// For more information, please visit:
+// http://www.vmime.org/
+//
+
+#include <iostream>
+#include <locale>
+#include <clocale>
+
+#include "vmime/vmime.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+
+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 {
+ std::locale::global(std::locale(""));
+ } catch (std::exception &) {
+ std::setlocale(LC_ALL, "");
+ }
+
+ try {
+
+ vmime::messageBuilder mb;
+
+ // Fill in the basic fields
+ mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
+
+ vmime::addressList to;
+ to.appendAddress(vmime::make_shared <vmime::mailbox>("you@elsewhere.com"));
+
+ mb.setRecipients(to);
+
+ vmime::addressList bcc;
+ bcc.appendAddress(vmime::make_shared <vmime::mailbox>("you-bcc@nowhere.com"));
+
+ mb.setBlindCopyRecipients(bcc);
+
+ 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
+ )
+ );
+
+ // 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());
+
+ // -- embed an image (the returned "CID" (content identifier) is used to reference
+ // -- the image into HTML content).
+ vmime::shared_ptr <vmime::utility::fileSystemFactory> fs =
+ vmime::platform::getHandler()->getFileSystemFactory();
+
+ vmime::shared_ptr <vmime::utility::file> imageFile =
+ fs->create(fs->stringToPath("/path/to/image.jpg"));
+
+ vmime::shared_ptr <vmime::utility::fileReader> fileReader =
+ imageFile->getFileReader();
+
+ vmime::shared_ptr <vmime::contentHandler> imageCts =
+ 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
+ )
+ );
+
+ // -- 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)."
+ )
+ );
+
+ // Construction
+ vmime::shared_ptr <vmime::message> msg = mb.construct();
+
+ // Raw text generation
+ vmime::string dataToSend = msg->generate();
+
+ std::cout << "Generated message:" << std::endl;
+ std::cout << "==================" << std::endl;
+ std::cout << std::endl;
+ std::cout << dataToSend << std::endl;
+
+ // VMime exception
+ } catch (vmime::exception& e) {
+
+ std::cout << "vmime::exception: " << e.what() << std::endl;
+ throw;
+
+ // Standard exception
+ } catch (std::exception& e) {
+
+ std::cout << "std::exception: " << e.what() << std::endl;
+ throw;
+ }
+
+ std::cout << std::endl;
+
+ return 0;
+}
diff --git a/vmime-master/examples/example4.cpp b/vmime-master/examples/example4.cpp
new file mode 100644
index 0000000..4d50c2e
--- /dev/null
+++ b/vmime-master/examples/example4.cpp
@@ -0,0 +1,108 @@
+//
+// 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.
+//
+
+//
+// EXAMPLE DESCRIPTION:
+// ====================
+// This sample program demonstrate the use of the messageParser component
+// to enumerate the text parts in a message.
+//
+// For more information, please visit:
+// http://www.vmime.org/
+//
+
+#include <iostream>
+#include <locale>
+#include <clocale>
+
+#include "vmime/vmime.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+
+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 {
+ std::locale::global(std::locale(""));
+ } catch (std::exception &) {
+ std::setlocale(LC_ALL, "");
+ }
+
+ try {
+
+ vmime::messageParser mp("<...MIME message content...>");
+
+ // Enumerate text parts
+ 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) {
+
+ 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) {
+
+ 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 {
+
+ const vmime::textPart& tp = dynamic_cast<const vmime::textPart&>(part);
+
+ // Text is in "tp.getText()"
+ }
+ }
+
+ // VMime exception
+ } catch (vmime::exception& e) {
+
+ std::cout << "vmime::exception: " << e.what() << std::endl;
+ throw;
+
+ // Standard exception
+ } catch (std::exception& e) {
+
+ std::cout << "std::exception: " << e.what() << std::endl;
+ throw;
+ }
+
+ std::cout << std::endl;
+
+ return 0;
+}
diff --git a/vmime-master/examples/example5.cpp b/vmime-master/examples/example5.cpp
new file mode 100644
index 0000000..24d5cbf
--- /dev/null
+++ b/vmime-master/examples/example5.cpp
@@ -0,0 +1,85 @@
+//
+// 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.
+//
+
+//
+// EXAMPLE DESCRIPTION:
+// ====================
+// This sample program demonstrate the use of the messageParser component
+// to enumerate the attachments in a message.
+//
+// For more information, please visit:
+// http://www.vmime.org/
+//
+
+#include <iostream>
+#include <locale>
+#include <clocale>
+
+#include "vmime/vmime.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+
+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 {
+ std::locale::global(std::locale(""));
+ } catch (std::exception &) {
+ std::setlocale(LC_ALL, "");
+ }
+
+ try {
+
+ vmime::messageParser mp("<...MIME message content...>");
+
+ // Enumerate attachments
+ for (size_t i = 0 ; i < mp.getAttachmentCount() ; ++i) {
+
+ const vmime::attachment& att = *mp.getAttachmentAt(i);
+
+ // Media type (content type) is in "att.getType()"
+ // Name is in "att.getName()"
+ // Description is in "att.getDescription()"
+ // Data is in "att.getData()"
+ }
+
+ // VMime exception
+ } catch (vmime::exception& e) {
+
+ std::cout << "vmime::exception: " << e.what() << std::endl;
+ throw;
+
+ // Standard exception
+ } catch (std::exception& e) {
+
+ std::cout << "std::exception: " << e.what() << std::endl;
+ throw;
+ }
+
+ std::cout << std::endl;
+
+ return 0;
+}
diff --git a/vmime-master/examples/example6.cpp b/vmime-master/examples/example6.cpp
new file mode 100644
index 0000000..add24b3
--- /dev/null
+++ b/vmime-master/examples/example6.cpp
@@ -0,0 +1,938 @@
+//
+// 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.
+//
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <map>
+#include <locale>
+#include <clocale>
+
+#include "vmime/vmime.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+#include "example6_tracer.hpp"
+#include "example6_authenticator.hpp"
+#include "example6_certificateVerifier.hpp"
+#include "example6_timeoutHandler.hpp"
+
+
+// Global session object
+static vmime::shared_ptr <vmime::net::session> g_session = vmime::net::session::create();
+
+
+/** Returns the messaging protocols supported by VMime.
+ *
+ * @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) {
+
+ 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) {
+
+ const vmime::net::serviceFactory::registeredService& serv = *sf->getServiceAt(i);
+
+ if (serv.getType() == type) {
+
+ if (count != 0) {
+ res << ", ";
+ }
+
+ res << serv.getName();
+ ++count;
+ }
+ }
+
+ return res.str();
+}
+
+
+// Exception helper
+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)) {
+
+ const vmime::exceptions::command_error& cee =
+ dynamic_cast <const vmime::exceptions::command_error&>(e);
+
+ os << " command = " << cee.command() << std::endl;
+ os << " response = " << cee.response() << std::endl;
+ }
+
+ 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)) {
+
+ 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)) {
+
+ 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)) {
+
+ const vmime::exceptions::filesystem_exception& fse =
+ dynamic_cast <const vmime::exceptions::filesystem_exception&>(e);
+
+ os << " path = " << vmime::platform::getHandler()->
+ getFileSystemFactory()->pathToString(fse.path()) << std::endl;
+ }
+
+ if (e.other()) {
+ os << *e.other();
+ }
+
+ return os;
+}
+
+
+/** Print the MIME structure of a message on the standard output.
+ *
+ * @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) {
+
+ vmime::shared_ptr <const vmime::net::messagePart> part = s->getPartAt(i);
+
+ for (int j = 0 ; j < level * 2 ; ++j) {
+ std::cout << " ";
+ }
+
+ 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) {
+
+ const vmime::string n = f->getName().getBuffer();
+
+ if (n.empty()) { // root folder
+
+ return "/";
+
+ } else {
+
+ vmime::shared_ptr <vmime::net::folder> p = f->getParent();
+ return getFolderPathString(p) + n + "/";
+ }
+}
+
+
+/** Print folders and sub-folders on the standard output.
+ *
+ * @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) {
+ std::cout << " ";
+ }
+
+ const vmime::net::folderAttributes attr = folder->getAttributes();
+ std::ostringstream attrStr;
+
+ if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_ALL) {
+ attrStr << " \\use:All";
+ } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_ARCHIVE) {
+ attrStr << " \\use:Archive";
+ } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_DRAFTS) {
+ attrStr << " \\use:Drafts";
+ } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_FLAGGED) {
+ attrStr << " \\use:Flagged";
+ } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_JUNK) {
+ attrStr << " \\use:Junk";
+ } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_SENT) {
+ attrStr << " \\use:Sent";
+ } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_TRASH) {
+ attrStr << " \\use:Trash";
+ } else if (attr.getSpecialUse() == vmime::net::folderAttributes::SPECIALUSE_IMPORTANT) {
+ attrStr << " \\use:Important";
+ }
+
+ if (attr.getFlags() & vmime::net::folderAttributes::FLAG_HAS_CHILDREN) {
+ attrStr << " \\flag:HasChildren";
+ }
+ if (attr.getFlags() & vmime::net::folderAttributes::FLAG_NO_OPEN) {
+ attrStr << " \\flag:NoOpen";
+ }
+
+ for (size_t i = 0, n = attr.getUserFlags().size() ; i < n ; ++i) {
+ attrStr << " \\" << attr.getUserFlags()[i];
+ }
+
+ std::cout << getFolderPathString(folder);
+ std::cout << " " << attrStr.str();
+ std::cout << std::endl;
+
+ std::vector <vmime::shared_ptr <vmime::net::folder> > subFolders = folder->getFolders(false);
+
+ for (unsigned int i = 0 ; i < subFolders.size() ; ++i) {
+ printFolders(subFolders[i], level + 1);
+ }
+}
+
+
+/** Print a menu on the standard output.
+ *
+ * @param choices menu choices
+ */
+static unsigned int printMenu(const std::vector <std::string>& choices) {
+
+ std::cout << std::endl;
+
+ 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() << "] ";
+ std::cout.flush();
+
+ std::string line;
+ std::getline(std::cin, line);
+
+ std::istringstream iss(line);
+
+ unsigned int choice = 0;
+ iss >> choice;
+
+ std::cout << std::endl;
+
+ if (choice < 1 || choice > choices.size()) {
+ return 0;
+ } else {
+ return choice;
+ }
+}
+
+
+/** Send a message interactively.
+ */
+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;
+ std::cout << "(eg. smtp://myserver.com, sendmail://localhost)" << std::endl;
+ std::cout << "> ";
+ std::cout.flush();
+
+ vmime::string urlString;
+ std::getline(std::cin, urlString);
+
+ vmime::utility::url url(urlString);
+
+ vmime::shared_ptr <vmime::net::transport> tr;
+
+ if (url.getUsername().empty() || url.getPassword().empty()) {
+ tr = g_session->getTransport(url, vmime::make_shared <interactiveAuthenticator>());
+ } else {
+ tr = g_session->getTransport(url);
+ }
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+ // Enable TLS support if available
+ tr->setProperty("connection.tls", true);
+
+ // Set the time out handler
+ tr->setTimeoutHandlerFactory(vmime::make_shared <timeoutHandlerFactory>());
+
+ // Set the object responsible for verifying certificates, in the
+ // case a secured connection is used (TLS/SSL)
+ 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()) {
+ tr->setProperty("options.need-authentication", true);
+ }
+
+ // Trace communication between client and server
+ vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>();
+ tr->setTracerFactory(vmime::make_shared <myTracerFactory>(traceStream));
+
+ // Information about the mail
+ std::cout << "Enter email of the expeditor (eg. me@somewhere.com): ";
+ std::cout.flush();
+
+ vmime::string fromString;
+ std::getline(std::cin, fromString);
+
+ vmime::mailbox from(fromString);
+ vmime::mailboxList to;
+
+ for (bool cont = true ; cont ; ) {
+
+ std::cout << "Enter email of the recipient (empty to stop): ";
+ std::cout.flush();
+
+ vmime::string toString;
+ std::getline(std::cin, toString);
+
+ cont = (toString.size() != 0);
+
+ 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 ; ) {
+
+ std::string line;
+ std::getline(std::cin, line);
+
+ if (line == ".") {
+ cont = false;
+ } else {
+ data << line << "\r\n";
+ }
+ }
+
+ // Connect to server
+ tr->connect();
+
+ // Send the message
+ vmime::string msgData = data.str();
+ vmime::utility::inputStreamStringAdapter vis(msgData);
+
+ tr->send(from, to, vis, msgData.length());
+
+ // Note: you could also write this:
+ // vmime::message msg;
+ // ...
+ // tr->send(&msg);
+
+ // Display connection log
+ std::cout << std::endl;
+ std::cout << "Connection Trace:" << std::endl;
+ std::cout << "=================" << std::endl;
+ std::cout << traceStream->str();
+
+ tr->disconnect();
+
+ } catch (vmime::exception& e) {
+
+ std::cerr << std::endl;
+ std::cerr << e << std::endl;
+ throw;
+
+ } catch (std::exception& e) {
+
+ std::cerr << std::endl;
+ std::cerr << "std::exception: " << e.what() << std::endl;
+ throw;
+ }
+}
+
+
+/** Connect to a message store interactively.
+ */
+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;
+ std::cout << "(eg. pop3://user:pass@myserver.com, imap://myserver.com:123)" << std::endl;
+ std::cout << "> ";
+ std::cout.flush();
+
+ vmime::string urlString;
+ std::getline(std::cin, urlString);
+
+ vmime::utility::url url(urlString);
+
+ // If no authenticator is given in argument to getStore(), a default one
+ // is used. Its behaviour is to get the user credentials from the
+ // session properties "auth.username" and "auth.password".
+ vmime::shared_ptr <vmime::net::store> st;
+
+ if (url.getUsername().empty() || url.getPassword().empty()) {
+ st = g_session->getStore(url, vmime::make_shared <interactiveAuthenticator>());
+ } else {
+ st = g_session->getStore(url);
+ }
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+ // Enable TLS support if available
+ st->setProperty("connection.tls", true);
+
+ // Set the time out handler
+ st->setTimeoutHandlerFactory(vmime::make_shared <timeoutHandlerFactory>());
+
+ // Set the object responsible for verifying certificates, in the
+ // case a secured connection is used (TLS/SSL)
+ st->setCertificateVerifier(
+ vmime::make_shared <interactiveCertificateVerifier>()
+ );
+
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ // Trace communication between client and server
+ vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>();
+ st->setTracerFactory(vmime::make_shared <myTracerFactory>(traceStream));
+
+ // Connect to the mail store
+ st->connect();
+
+ // Display some information about the connection
+ vmime::shared_ptr <vmime::net::connectionInfos> ci = st->getConnectionInfos();
+
+ std::cout << std::endl;
+ std::cout << "Connected to '" << ci->getHost() << "' (port " << ci->getPort() << ")" << std::endl;
+ std::cout << "Connection is " << (st->isSecuredConnection() ? "" : "NOT ") << "secured." << std::endl;
+
+ // Open the default folder in this store
+ vmime::shared_ptr <vmime::net::folder> f = st->getDefaultFolder();
+// vmime::shared_ptr <vmime::net::folder> f = st->getFolder(vmime::utility::path("a"));
+
+ f->open(vmime::net::folder::MODE_READ_WRITE);
+
+ vmime::size_t count = f->getMessageCount();
+
+ std::cout << std::endl;
+ std::cout << count << " message(s) in your inbox" << std::endl;
+
+ for (bool cont = true ; cont ; ) {
+
+ typedef std::map <vmime::size_t, vmime::shared_ptr <vmime::net::message> > MessageList;
+ MessageList msgList;
+
+ try {
+
+ std::vector <std::string> choices;
+
+ choices.push_back("Show message flags");
+ choices.push_back("Show message structure");
+ choices.push_back("Show message header");
+ choices.push_back("Show message envelope");
+ choices.push_back("Extract whole message");
+ choices.push_back("Extract attachments");
+ choices.push_back("Status");
+ choices.push_back("List folders");
+ choices.push_back("Change folder");
+ choices.push_back("Add message (to the current folder)");
+ choices.push_back("Copy message (into the current folder)");
+ choices.push_back("Display trace output");
+ choices.push_back("Return to main menu");
+
+ const int choice = printMenu(choices);
+
+ // Request message number
+ vmime::shared_ptr <vmime::net::message> msg;
+
+ if (choice == 1 || choice == 2 || choice == 3 || choice == 4 ||
+ choice == 5 || choice == 6 || choice == 11) {
+
+ std::cout << "Enter message number: ";
+ std::cout.flush();
+
+ std::string line;
+ std::getline(std::cin, line);
+
+ std::istringstream iss(line);
+
+ vmime::size_t num = 0;
+ iss >> num;
+
+ if (num < 1 || num > f->getMessageCount()) {
+
+ std::cerr << "Invalid message number." << std::endl;
+ continue;
+ }
+
+ MessageList::iterator it = msgList.find(num);
+
+ if (it != msgList.end()) {
+
+ msg = (*it).second;
+
+ } else {
+
+ msg = f->getMessage(num);
+ msgList.insert(MessageList::value_type(num, msg));
+ }
+
+ std::cout << std::endl;
+ }
+
+ switch (choice) {
+
+ // Show message flags
+ case 1:
+
+ f->fetchMessage(msg, vmime::net::fetchAttributes::FLAGS);
+
+ if (msg->getFlags() & vmime::net::message::FLAG_SEEN) {
+ std::cout << "FLAG_SEEN" << std::endl;
+ }
+ if (msg->getFlags() & vmime::net::message::FLAG_RECENT) {
+ std::cout << "FLAG_RECENT" << std::endl;
+ }
+ if (msg->getFlags() & vmime::net::message::FLAG_REPLIED) {
+ std::cout << "FLAG_REPLIED" << std::endl;
+ }
+ if (msg->getFlags() & vmime::net::message::FLAG_DELETED) {
+ std::cout << "FLAG_DELETED" << std::endl;
+ }
+ if (msg->getFlags() & vmime::net::message::FLAG_MARKED) {
+ std::cout << "FLAG_MARKED" << std::endl;
+ }
+ if (msg->getFlags() & vmime::net::message::FLAG_PASSED) {
+ std::cout << "FLAG_PASSED" << std::endl;
+ }
+
+ break;
+
+ // Show message structure
+ case 2:
+
+ f->fetchMessage(msg, vmime::net::fetchAttributes::STRUCTURE);
+ printStructure(msg->getStructure());
+ break;
+
+ // Show message header
+ case 3:
+
+ f->fetchMessage(msg, vmime::net::fetchAttributes::FULL_HEADER);
+ std::cout << msg->getHeader()->generate() << std::endl;
+ break;
+
+ // Show message envelope
+ case 4: {
+
+ vmime::net::fetchAttributes attr(vmime::net::fetchAttributes::ENVELOPE);
+
+ // If you also want to fetch "Received: " fields:
+ //attr.add("Received");
+
+ f->fetchMessage(msg, attr);
+
+ std::cout << msg->getHeader()->generate() << std::endl;
+
+ break;
+ }
+ // Extract whole message
+ case 5: {
+
+ vmime::utility::outputStreamAdapter out(std::cout);
+ msg->extract(out);
+
+ break;
+ }
+ // Extract attachments
+ 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) {
+
+ 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) {
+
+ vmime::shared_ptr <const vmime::attachment> att = *it;
+
+ // Get attachment size
+ vmime::size_t size = 0;
+
+ if (att->getData()->isEncoded()) {
+ size = att->getData()->getEncoding().getEncoder()->getDecodedSize(att->getData()->getLength());
+ } else {
+ size = att->getData()->getLength();
+ }
+
+ std::cout << "Found attachment '" << att->getName().getBuffer() << "'"
+ << ", size is " << size << " bytes:" << std::endl;
+
+ // Get attachment data
+ std::cout << std::endl;
+ std::cout << "========== BEGIN CONTENT ==========" << std::endl;
+
+ vmime::utility::outputStreamAdapter osa(std::cout);
+ att->getData()->extract(osa);
+
+ std::cout << std::endl;
+ std::cout << "========== END CONTENT ==========" << std::endl;
+
+ // Or write it to a file
+ /*
+ vmime::shared_ptr <vmime::utility::fileSystemFactory> fsf
+ = vmime::platform::getHandler()->getFileSystemFactory();
+
+ vmime::shared_ptr <vmime::utility::file> file
+ = fsf->create(vmime::utility::path::fromString
+ ("/path/to/attachment-file", "/", vmime::charsets::UTF_8));
+ // -or- ("C:\\Temp\\attachment-file", "\\", vmime::charsets::UTF_8));
+
+ file->createFile();
+
+ vmime::shared_ptr <vmime::utility::outputStream> output =
+ file->getFileWriter()->getOutputStream();
+
+ att->getData()->extract(*output.get());
+ */
+ }
+
+ } else {
+
+ std::cout << "No attachments found." << std::endl;
+ }
+
+ break;
+ }
+ // Status
+ case 7: {
+
+ vmime::size_t count, unseen;
+ f->status(count, unseen);
+
+ std::cout << "Status: count=" << count << ", unseen=" << unseen << std::endl;
+ break;
+ }
+ // List folders
+ case 8: {
+
+ vmime::shared_ptr <vmime::net::folder> root = st->getRootFolder();
+
+ printFolders(root);
+ break;
+ }
+ // Change folder
+ case 9: {
+
+ std::cout << "Enter folder path (eg. /root/subfolder):" << std::endl;
+ std::cout.flush();
+
+ std::string path;
+ std::getline(std::cin, path);
+
+ vmime::shared_ptr <vmime::net::folder> newFolder = st->getRootFolder();
+
+ 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()) {
+ newFolder = newFolder->getFolder(vmime::utility::path::component(x));
+ }
+
+ if (p == std::string::npos) {
+ break;
+ }
+ }
+
+ newFolder->open(vmime::net::folder::MODE_READ_WRITE);
+
+ count = newFolder->getMessageCount();
+
+ std::cout << std::endl;
+ std::cout << count << " message(s) in this folder" << std::endl;
+
+ f->close(true); // 'true' to expunge deleted messages
+ f = newFolder;
+
+ break;
+ }
+ // Add message
+ case 10: {
+
+ vmime::messageBuilder mb;
+
+ mb.setExpeditor(vmime::mailbox("me@somewhere.com"));
+
+ vmime::addressList to;
+ to.appendAddress(vmime::make_shared <vmime::mailbox>("you@elsewhere.com"));
+ 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."
+ )
+ );
+
+ vmime::shared_ptr <vmime::message> msg = mb.construct();
+
+ vmime::net::messageSet set = f->addMessage(msg);
+
+ if (set.isEmpty()) {
+
+ std::cout << "Message has successfully been added, "
+ << "but its UID/number is not known." << std::endl;
+
+ } else {
+
+ const vmime::net::messageRange& range = set.getRangeAt(0);
+
+ 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 {
+
+ const vmime::size_t number =
+ dynamic_cast <const vmime::net::numberMessageRange&>(range).getFirst();
+
+ std::cout << "Message has successfully been added, "
+ << "its number is '" << number << "'." << std::endl;
+ }
+ }
+
+ break;
+ }
+ // Copy message
+ case 11: {
+
+ vmime::net::messageSet set = f->copyMessages(f->getFullPath(),
+ vmime::net::messageSet::byNumber(msg->getNumber()));
+
+ if (set.isEmpty()) {
+
+ std::cout << "Message has successfully been copied, "
+ << "but its UID/number is not known." << std::endl;
+
+ } else {
+
+ const vmime::net::messageRange& range = set.getRangeAt(0);
+
+ 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 {
+
+ const vmime::size_t number =
+ dynamic_cast <const vmime::net::numberMessageRange&>(range).getFirst();
+
+ std::cout << "Message has successfully been copied, "
+ << "its number is '" << number << "'." << std::endl;
+ }
+ }
+
+ break;
+ }
+ // Display trace output
+ case 12:
+
+ std::cout << std::endl;
+ std::cout << "Connection Trace:" << std::endl;
+ std::cout << "=================" << std::endl;
+ std::cout << traceStream->str();
+ break;
+
+ // Main menu
+ case 13:
+
+ f->close(true); // 'true' to expunge deleted messages
+ cont = false;
+ break;
+ }
+
+/*
+ // Append message
+ std::istringstream iss(
+ "From: me@localhost\r\n"
+ "To: you@localhost\r\n"
+ "Subject: Message Text\r\n"
+ "\r\n"
+ "This is a test message...\r\n"
+ "Bye bye!\r\n"
+ );
+
+ f->addMessage(iss, iss.str().size());
+
+ // Folder renaming
+ {
+ vmime::shared_ptr <vmime::net::folder> f = st->getFolder(vmime::net::folder::path("c"));
+ f->rename(vmime::net::folder::path("c2"));
+
+ vmime::shared_ptr <vmime::net::folder> g = st->getFolder(vmime::net::folder::path("c2"));
+ g->rename(vmime::net::folder::path("c"));
+ }
+
+ // Message copy: copy all messages from 'f' to 'g'
+ {
+ vmime::shared_ptr <vmime::net::folder> g = st->getFolder(vmime::net::folder::path("TEMP"));
+
+ if (!g->exists()) {
+ g->create(vmime::net::folder::TYPE_CONTAINS_MESSAGES);
+ }
+
+ f->copyMessages(g->getFullPath());
+ }
+*/
+
+ } catch (vmime::exception& e) {
+
+ std::cerr << std::endl;
+ std::cerr << e << std::endl;
+
+ } catch (std::exception& e) {
+
+ std::cerr << std::endl;
+ std::cerr << "std::exception: " << e.what() << std::endl;
+ }
+
+ } // for(cont)
+
+ st->disconnect();
+
+ } catch (vmime::exception& e) {
+
+ std::cerr << std::endl;
+ std::cerr << e << std::endl;
+ throw;
+
+ } catch (std::exception& e) {
+
+ std::cerr << std::endl;
+ std::cerr << "std::exception: " << e.what() << std::endl;
+ throw;
+ }
+}
+
+
+/* Show the main menu.
+ *
+ * @return true to quit the program, false to continue
+ */
+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)) {
+
+ // Connect to store
+ case 1:
+
+ connectStore();
+ return false;
+
+ // Send a message
+ case 2:
+
+ sendMessage();
+ return false;
+
+ // Quit
+ case 3:
+
+ return true;
+
+ // Other choice
+ default:
+
+ return false;
+ }
+}
+
+
+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 {
+ std::locale::global(std::locale(""));
+ } catch (std::exception &) {
+ std::setlocale(LC_ALL, "");
+ }
+
+ for (bool quit = false ; !quit ; ) {
+
+ // Loop on main menu
+ quit = menu();
+ }
+
+ return 0;
+}
diff --git a/vmime-master/examples/example6_authenticator.hpp b/vmime-master/examples/example6_authenticator.hpp
new file mode 100644
index 0000000..56f0239
--- /dev/null
+++ b/vmime-master/examples/example6_authenticator.hpp
@@ -0,0 +1,112 @@
+
+
+#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,
+ 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) {
+
+ std::cout << " " << available[i]->getName();
+
+ if (suggested && available[i]->getName() == suggested->getName()) {
+ std::cout << "(suggested)";
+ }
+ }
+
+ std::cout << std::endl << std::endl;
+
+ return defaultSASLAuthenticator::getAcceptableMechanisms(available, suggested);
+ }
+
+ 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()) {
+ m_username = getUserInput("Username");
+ }
+
+ return m_username;
+ }
+
+ 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) {
+
+ std::cout << prompt << ": ";
+ std::cout.flush();
+
+ vmime::string res;
+ std::getline(std::cin, res);
+
+ return res;
+ }
+
+private:
+
+ mutable vmime::string m_username;
+ mutable vmime::string m_password;
+};
+
+#else // !VMIME_HAVE_SASL_SUPPORT
+
+// Simple authentication handler
+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()) {
+ m_password = getUserInput("Password");
+ }
+
+ return m_password;
+ }
+
+ static const vmime::string getUserInput(const std::string& prompt) {
+
+ std::cout << prompt << ": ";
+ std::cout.flush();
+
+ vmime::string res;
+ std::getline(std::cin, res);
+
+ return res;
+ }
+
+private:
+
+ mutable vmime::string m_username;
+ mutable vmime::string m_password;
+};
+
+#endif // VMIME_HAVE_SASL_SUPPORT
diff --git a/vmime-master/examples/example6_certificateVerifier.hpp b/vmime-master/examples/example6_certificateVerifier.hpp
new file mode 100644
index 0000000..3d8bf82
--- /dev/null
+++ b/vmime-master/examples/example6_certificateVerifier.hpp
@@ -0,0 +1,64 @@
+
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+// Certificate verifier (TLS/SSL)
+class interactiveCertificateVerifier : public vmime::security::cert::defaultCertificateVerifier {
+
+public:
+
+ 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&) {
+
+ // Obtain subject's certificate
+ vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0);
+
+ std::cout << std::endl;
+ std::cout << "Server sent a '" << cert->getType() << "'" << " certificate." << std::endl;
+ std::cout << "Do you want to accept this certificate? (Y/n) ";
+ std::cout.flush();
+
+ std::string answer;
+ std::getline(std::cin, answer);
+
+ if (answer.length() != 0 &&
+ (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)
+ );
+
+ setX509TrustedCerts(m_trustedCerts);
+ defaultCertificateVerifier::verify(chain, hostname);
+ }
+
+ return;
+ }
+
+ throw vmime::security::cert::certificateException("User did not accept the certificate.");
+ }
+ }
+
+private:
+
+ static std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > m_trustedCerts;
+};
+
+
+std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> >
+ interactiveCertificateVerifier::m_trustedCerts;
+
+#endif // VMIME_HAVE_TLS_SUPPORT
diff --git a/vmime-master/examples/example6_timeoutHandler.hpp b/vmime-master/examples/example6_timeoutHandler.hpp
new file mode 100644
index 0000000..7999084
--- /dev/null
+++ b/vmime-master/examples/example6_timeoutHandler.hpp
@@ -0,0 +1,60 @@
+#include <ctime>
+
+
+/** Time out handler.
+ * Used to stop the current operation after too much time, or if the user
+ * requested cancellation.
+ */
+class timeoutHandler : public vmime::net::timeoutHandler {
+
+public:
+
+ timeoutHandler()
+ : m_start(time(NULL)) {
+
+ }
+
+ 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
+ // operation
+
+ // 10 seconds timeout
+ return (time(NULL) - m_start) >= 10; // seconds
+ }
+
+ 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() {
+
+ // 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.
+
+ // If you return false here, the operation will be actually cancelled.
+ // If true, the time out is reset and the operation continues.
+ return false;
+ }
+
+private:
+
+ time_t m_start;
+};
+
+
+class timeoutHandlerFactory : public vmime::net::timeoutHandlerFactory {
+
+public:
+
+ vmime::shared_ptr <vmime::net::timeoutHandler> create() {
+
+ return vmime::make_shared <timeoutHandler>();
+ }
+};
diff --git a/vmime-master/examples/example6_tracer.hpp b/vmime-master/examples/example6_tracer.hpp
new file mode 100644
index 0000000..27090cf
--- /dev/null
+++ b/vmime-master/examples/example6_tracer.hpp
@@ -0,0 +1,59 @@
+
+/** Tracer used to demonstrate logging communication between client and server.
+ */
+class myTracer : public vmime::net::tracer {
+
+public:
+
+ 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) {
+
+ *m_stream << "[" << m_service->getProtocolName() << ":" << m_connectionId
+ << "] C: " << line << std::endl;
+ }
+
+ void traceReceive(const vmime::string& line) {
+
+ *m_stream << "[" << m_service->getProtocolName() << ":" << m_connectionId
+ << "] S: " << line << std::endl;
+ }
+
+private:
+
+ vmime::shared_ptr <std::ostringstream> m_stream;
+ vmime::shared_ptr <vmime::net::service> m_service;
+ const int m_connectionId;
+};
+
+
+class myTracerFactory : public vmime::net::tracerFactory {
+
+public:
+
+ myTracerFactory(const vmime::shared_ptr <std::ostringstream>& stream)
+ : m_stream(stream) {
+
+ }
+
+ 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);
+ }
+
+private:
+
+ vmime::shared_ptr <std::ostringstream> m_stream;
+};
diff --git a/vmime-master/examples/example7.cpp b/vmime-master/examples/example7.cpp
new file mode 100644
index 0000000..db96dbd
--- /dev/null
+++ b/vmime-master/examples/example7.cpp
@@ -0,0 +1,118 @@
+//
+// 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.
+//
+
+//
+// EXAMPLE DESCRIPTION:
+// ====================
+// This sample program demonstrates how to enumerate encoders and
+// messaging services in VMime.
+//
+// For more information, please visit:
+// http://www.vmime.org/
+//
+
+#include <iostream>
+#include <locale>
+#include <clocale>
+
+#include "vmime/vmime.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+
+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) {
+
+ vmime::shared_ptr <const vmime::utility::encoder::encoderFactory::registeredEncoder>
+ enc = ef->getEncoderAt(i);
+
+ std::cout << " * " << enc->getName() << std::endl;
+
+ vmime::shared_ptr <vmime::utility::encoder::encoder> e =
+ vmime::utility::encoder::encoderFactory::getInstance()->create(enc->getName());
+
+ std::vector <vmime::string> props = e->getAvailableProperties();
+
+ for (std::vector <vmime::string>::const_iterator it = props.begin() ; it != props.end() ; ++it) {
+ std::cout << " - " << *it << std::endl;
+ }
+ }
+
+ std::cout << std::endl;
+
+ // Enumerate messaging services and their properties
+ vmime::shared_ptr <vmime::net::serviceFactory> sf =
+ vmime::net::serviceFactory::getInstance();
+
+ std::cout << "Available messaging services:" << std::endl;
+
+ for (size_t i = 0 ; i < sf->getServiceCount() ; ++i) {
+
+ const vmime::net::serviceFactory::registeredService& serv = *sf->getServiceAt(i);
+
+ std::cout << " * " << serv.getName() << std::endl;
+
+ std::vector <vmime::net::serviceInfos::property> props =
+ serv.getInfos().getAvailableProperties();
+
+ for (std::vector <vmime::net::serviceInfos::property>::const_iterator it = props.begin() ;
+ 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;
+ }
+
+ vmime::string flags;
+
+ if (p.getFlags() & vmime::net::serviceInfos::property::FLAG_REQUIRED) {
+ flags += " FLAG_REQUIRED";
+ }
+ 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;
+ std::cout << ", defaultValue=" << p.getDefaultValue() << ")" << std::endl;
+ }
+ }
+
+ std::cout << std::endl;
+
+ return 0;
+}
diff --git a/vmime-master/examples/viewer/CMakeLists.txt b/vmime-master/examples/viewer/CMakeLists.txt
new file mode 100644
index 0000000..c8d9316
--- /dev/null
+++ b/vmime-master/examples/viewer/CMakeLists.txt
@@ -0,0 +1,31 @@
+
+IF(VMIME_BUILD_SAMPLES)
+
+ FIND_PACKAGE(PkgConfig REQUIRED)
+ PKG_CHECK_MODULES(GTK3 REQUIRED gtk+-3.0)
+
+ INCLUDE_DIRECTORIES(${GTK3_INCLUDE_DIRS})
+ LINK_DIRECTORIES(${GTK3_LIBRARY_DIRS})
+ ADD_DEFINITIONS(${GTK3_CFLAGS_OTHER})
+
+ ADD_EXECUTABLE(
+ viewer
+ viewer.cpp
+ )
+
+ TARGET_LINK_LIBRARIES(
+ viewer
+ ${VMIME_LIBRARY_NAME}
+ ${GTK3_LIBRARIES}
+ )
+
+ ADD_DEPENDENCIES(
+ viewer
+ ${VMIME_LIBRARY_NAME}
+ )
+
+ELSE()
+
+ MESSAGE(FATAL_ERROR "Examples are not to be built (set VMIME_BUILD_SAMPLES to YES.")
+
+ENDIF()
diff --git a/vmime-master/examples/viewer/viewer.cpp b/vmime-master/examples/viewer/viewer.cpp
new file mode 100644
index 0000000..a03120a
--- /dev/null
+++ b/vmime-master/examples/viewer/viewer.cpp
@@ -0,0 +1,294 @@
+//
+// 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.
+//
+
+//
+// EXAMPLE DESCRIPTION:
+// ====================
+// A simple MIME viewer to show all the components of a message.
+// The user interface is written using GTK+ 2.6.
+//
+// For more information, please visit:
+// http://www.vmime.org/
+//
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <typeinfo>
+
+#include <gtk/gtk.h>
+
+#include "vmime/vmime.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+
+
+GtkWidget* window = NULL;
+GtkWidget* treeView = NULL;
+GtkWidget* textArea = NULL;
+
+GtkTreeStore* treeModel = NULL;
+
+vmime::shared_ptr <vmime::message> currentMessage;
+
+
+
+void insertRowInModel(
+ GtkTreeStore* model,
+ vmime::shared_ptr <vmime::component> comp,
+ GtkTreeIter* parent = NULL
+) {
+
+ GtkTreeIter iter;
+
+ gtk_tree_store_append(model, &iter, parent);
+ gtk_tree_store_set(model, &iter, 0, typeid(*comp).name(), 1, comp.get(), -1);
+
+ const std::vector <vmime::shared_ptr <vmime::component> > children = comp->getChildComponents();
+
+ for (int i = 0 ; i < children.size() ; ++i) {
+ insertRowInModel(model, children[i], &iter);
+ }
+}
+
+
+void updateTreeView() {
+
+ GtkTreeStore* model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeView)));
+
+ g_object_ref(model);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(treeView), NULL);
+
+ gtk_tree_store_clear(model);
+
+ insertRowInModel(model, currentMessage);
+
+ gtk_tree_view_set_model(GTK_TREE_VIEW(treeView), GTK_TREE_MODEL(model));
+ g_object_unref(model);
+}
+
+
+static void treeViewSelChanged(GtkTreeView* treeView, gpointer userData) {
+
+ GtkTreePath* path = NULL;
+ GtkTreeViewColumn* col = NULL;
+
+ gtk_tree_view_get_cursor(treeView, &path, &col);
+
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(treeModel), &iter, path);
+
+ vmime::component* comp = NULL;
+ gtk_tree_model_get(GTK_TREE_MODEL(treeModel), &iter, 1, &comp, -1);
+
+ GtkTextBuffer* textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textArea));
+ GtkTextIter start, end;
+
+ gtk_text_buffer_get_iter_at_offset(textBuffer, &start, comp->getParsedOffset());
+ gtk_text_buffer_get_iter_at_offset(textBuffer, &end, comp->getParsedOffset() + comp->getParsedLength());
+
+ gtk_text_buffer_select_range(textBuffer, &start, &end);
+
+ gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(textArea), &start, 0.0, FALSE, 0.0, 0.0);
+
+ gtk_tree_path_free(path);
+}
+
+
+static void destroy(GtkWidget* widget, gpointer data) {
+
+ gtk_main_quit();
+}
+
+
+void openFile(const std::string& filename) {
+
+ std::ifstream file;
+ file.open(filename.c_str(), std::ios::in | std::ios::binary);
+
+ if (!file) {
+ std::cerr << "Can't open file '" << filename << "'." << std::endl;
+ return;
+ }
+
+ vmime::string data;
+ char buffer[16384];
+
+ do {
+ file.read(buffer, sizeof(buffer));
+ data += vmime::string(buffer, file.gcount());
+ } while (file.gcount());
+
+ vmime::shared_ptr <vmime::message> msg = vmime::make_shared <vmime::message>();
+ msg->parse(data);
+
+ currentMessage = msg;
+
+ char* convData = g_convert_with_fallback(data.c_str(), data.length(),
+ "UTF-8", "ISO-8859-1", "?", NULL, NULL, NULL);
+
+ if (!convData) {
+
+ gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textArea)),
+ "GLib UTF-8 conversion error.", -1);
+
+ } else {
+
+ gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(textArea)),
+ convData, strlen(convData));
+
+ g_free(convData);
+ }
+
+ updateTreeView();
+}
+
+
+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) {
+
+ char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg));
+
+ openFile(filename);
+
+ g_free(filename);
+ }
+
+ gtk_widget_destroy(dlg);
+}
+
+
+
+// UI definitions
+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) }
+};
+
+static const char* uiDefinition =
+ "<ui>" \
+ " <menubar name=\"MainMenuBar\">" \
+ " <menu action=\"FileMenu\">" \
+ " <menuitem action=\"FileOpen\"/>" \
+ " <menuitem action=\"FileExit\"/>" \
+ " </menu>" \
+ " </menubar>" \
+ "</ui>";
+
+
+int main(int argc, char* argv[]) {
+
+ // VMime initialization
+ vmime::platform::setHandler<vmime::platforms::posix::posixHandler>();
+
+ // GTK+ initialization
+ gtk_init(&argc, &argv);
+
+ // Create a new window
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_default_size(GTK_WINDOW(window), 800, 550);
+ gtk_window_set_title(GTK_WINDOW(window), "VMime Viewer Example");
+
+ g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);
+
+ GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(window), vbox);
+
+ // Menubar
+ GtkActionGroup* actionGroup = gtk_action_group_new ("Actions");
+ gtk_action_group_add_actions(actionGroup, uiActions, G_N_ELEMENTS(uiActions), NULL);
+
+ GtkUIManager* uiManager = gtk_ui_manager_new();
+ gtk_ui_manager_insert_action_group(uiManager, actionGroup, 1);
+ gtk_ui_manager_add_ui_from_string(uiManager, uiDefinition, -1, NULL);
+
+ GtkWidget* menuBar = gtk_ui_manager_get_widget(uiManager, "/MainMenuBar");
+
+ gtk_box_pack_start(GTK_BOX(vbox), menuBar, FALSE, FALSE, 0);
+
+ // Horizontal Pane
+ GtkWidget* hpane = gtk_hpaned_new();
+ gtk_box_pack_start(GTK_BOX(vbox), hpane, TRUE, TRUE, 0);
+
+ // Tree View
+ treeModel = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
+
+ treeView = gtk_tree_view_new();
+
+ g_signal_connect(G_OBJECT(treeView), "cursor-changed", G_CALLBACK(treeViewSelChanged), NULL);
+
+ GtkWidget* scroll = gtk_scrolled_window_new(NULL, NULL);
+
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(scroll), treeView);
+
+ gtk_paned_add1(GTK_PANED(hpane), scroll);
+
+ GtkTreeViewColumn* col = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(col, "Component Name");
+ gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), col);
+
+ GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
+
+ gtk_tree_view_column_pack_start(col, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(col, renderer, "text", 0);
+
+ gtk_tree_view_set_model(GTK_TREE_VIEW(treeView), GTK_TREE_MODEL(treeModel));
+ g_object_unref(treeModel);
+
+ gtk_widget_set_size_request(treeView, 200, 100);
+
+ // Text Area
+ textArea = gtk_text_view_new();
+
+ gtk_text_view_set_editable(GTK_TEXT_VIEW(textArea), FALSE);
+
+ scroll = gtk_scrolled_window_new(NULL, NULL);
+
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(scroll), textArea);
+
+ gtk_paned_add2(GTK_PANED(hpane), scroll);
+
+ // Show main window
+ gtk_widget_show_all(window);
+
+ // GTK main loop
+ gtk_main();
+
+ return 0;
+}
diff --git a/vmime-master/mingw_cross_toolchain.cmake b/vmime-master/mingw_cross_toolchain.cmake
new file mode 100644
index 0000000..d8727f1
--- /dev/null
+++ b/vmime-master/mingw_cross_toolchain.cmake
@@ -0,0 +1,14 @@
+SET(CMAKE_SYSTEM_NAME Windows)
+SET(CMAKE_CROSSCOMPILING TRUE)
+
+IF("${GNU_HOST}" STREQUAL "")
+ SET(GNU_HOST i686-w64-mingw32)
+ENDIF()
+
+# specify the cross compiler
+SET(CMAKE_C_COMPILER_TARGET ${GNU_HOST})
+SET(CMAKE_C_COMPILER ${GNU_HOST}-gcc)
+SET(CMAKE_CXX_COMPILER_TARGET ${GNU_HOST})
+SET(CMAKE_CXX_COMPILER ${GNU_HOST}-g++)
+SET(CMAKE_RC_COMPILER_TARGET ${GNU_HOST})
+SET(CMAKE_RC_COMPILER ${GNU_HOST}-windres)
diff --git a/vmime-master/src/vmime/address.cpp b/vmime-master/src/vmime/address.cpp
new file mode 100644
index 0000000..3bc434f
--- /dev/null
+++ b/vmime-master/src/vmime/address.cpp
@@ -0,0 +1,236 @@
+//
+// 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.
+//
+
+#include "vmime/address.hpp"
+
+#include "vmime/mailbox.hpp"
+#include "vmime/mailboxGroup.hpp"
+
+#include "vmime/parserHelpers.hpp"
+
+
+namespace vmime {
+
+
+address::address() {
+
+}
+
+
+/*
+
+ RFC #2822:
+ 3.4. ADDRESS SPECIFICATION
+
+ Addresses occur in several message header fields to indicate senders
+ and recipients of messages. An address may either be an individual
+ mailbox, or a group of mailboxes.
+
+address = mailbox / group
+
+mailbox = name-addr / addr-spec
+
+name-addr = [display-name] angle-addr
+
+angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
+
+group = display-name ":" [mailbox-list / CFWS] ";"
+ [CFWS]
+
+display-name = phrase
+
+mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list
+
+address-list = (address *("," address)) / obs-addr-list
+
+*/
+
+shared_ptr <address> address::parseNext(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition,
+ bool *isLastAddressOfGroup
+) {
+
+ bool escaped = false;
+ bool quoted = false;
+ bool quotedRFC2047 = false;
+ bool inRouteAddr = false;
+ bool isGroup = false;
+ bool stop = false;
+ int commentLevel = 0;
+
+ if (isLastAddressOfGroup) {
+ *isLastAddressOfGroup = false;
+ }
+
+ size_t pos = position;
+
+ while (pos < end && parserHelpers::isSpace(buffer[pos])) {
+ ++pos;
+ }
+
+ const size_t start = pos;
+
+ while (!stop && pos < end) {
+
+ if (escaped) {
+
+ escaped = false;
+
+ } else {
+
+ switch (buffer[pos]) {
+
+ case '\\':
+
+ escaped = true;
+ break;
+
+ case '"':
+
+ quoted = !quoted;
+ break;
+
+ case '<':
+
+ inRouteAddr = true;
+ break;
+
+ case '>':
+
+ inRouteAddr = false;
+ break;
+
+ case '(':
+
+ ++commentLevel;
+ break;
+
+ case ')':
+
+ if (commentLevel > 0) {
+ --commentLevel;
+ }
+
+ 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) {
+ ++pos;
+ }
+ }
+
+ if (newPosition) {
+
+ if (pos == end) {
+ *newPosition = end;
+ } else {
+ *newPosition = pos + 1; // ',' or ';'
+ }
+ }
+
+ // Parse extracted address (mailbox or group)
+ if (pos != start) {
+
+ shared_ptr <address> parsedAddress;
+
+ if (isGroup) {
+ parsedAddress = make_shared <mailboxGroup>();
+ } else {
+ parsedAddress = make_shared <mailbox>();
+ }
+
+ parsedAddress->parse(ctx, buffer, start, pos, NULL);
+ parsedAddress->setParsedBounds(start, pos);
+
+ return parsedAddress;
+ }
+
+ return null;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/address.hpp b/vmime-master/src/vmime/address.hpp
new file mode 100644
index 0000000..f83f238
--- /dev/null
+++ b/vmime-master/src/vmime/address.hpp
@@ -0,0 +1,89 @@
+//
+// 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_ADDRESS_HPP_INCLUDED
+#define VMIME_ADDRESS_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/headerFieldValue.hpp"
+
+
+namespace vmime {
+
+
+/** Abstract class representing a mailbox or a group of mailboxes.
+ *
+ * This class define a common behaviour for the mailbox
+ * and mailboxGroup classes.
+ */
+class VMIME_EXPORT address : public headerFieldValue {
+
+protected:
+
+ address();
+
+public:
+
+ /** Check whether this address is empty (no mailboxes specified
+ * if this is a mailboxGroup -or- no email specified if this is
+ * a mailbox).
+ *
+ * @return true if this address is empty
+ */
+ virtual bool isEmpty() const = 0;
+
+ /** Test whether this is object is a mailboxGroup.
+ *
+ * @return true if this is a mailboxGroup, false otherwise
+ */
+ virtual bool isGroup() const = 0;
+
+ virtual shared_ptr <component> clone() const = 0;
+
+ /** Parse an address from an input buffer.
+ *
+ * @param ctx parsing context
+ * @param buffer input buffer
+ * @param position position in the input buffer
+ * @param end end position in the input buffer
+ * @param newPosition will receive the new position in the input buffer
+ * @param isLastAddressOfGroup will be set to true if this is the last address
+ * 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
+ );
+};
+
+
+} // vmime
+
+
+#endif // VMIME_ADDRESS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/addressList.cpp b/vmime-master/src/vmime/addressList.cpp
new file mode 100644
index 0000000..03c9e8f
--- /dev/null
+++ b/vmime-master/src/vmime/addressList.cpp
@@ -0,0 +1,328 @@
+//
+// 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.
+//
+
+#include "vmime/addressList.hpp"
+#include "vmime/parserHelpers.hpp"
+#include "vmime/exception.hpp"
+#include "vmime/mailboxList.hpp"
+#include "vmime/mailboxGroup.hpp"
+
+
+namespace vmime {
+
+
+addressList::addressList() {
+
+}
+
+
+addressList::addressList(const addressList& addrList)
+ : headerFieldValue() {
+
+ copyFrom(addrList);
+}
+
+
+addressList::~addressList() {
+
+ removeAllAddresses();
+}
+
+
+void addressList::parseImpl(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ removeAllAddresses();
+
+ size_t pos = position;
+
+ while (pos < end) {
+
+ shared_ptr <address> parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, NULL);
+
+ if (parsedAddress) {
+ m_list.push_back(parsedAddress);
+ }
+ }
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+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() ; ; ) {
+
+ (*i)->generate(ctx, os, pos, &pos);
+
+ if (++i == m_list.end()) {
+ break;
+ }
+
+ os << ", ";
+ pos += 2;
+ }
+ }
+
+ if (newLinePos) {
+ *newLinePos = pos;
+ }
+}
+
+
+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) {
+
+ m_list.push_back(vmime::clone(*it));
+ }
+}
+
+
+addressList& addressList::operator=(const addressList& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+addressList& addressList::operator=(const mailboxList& other) {
+
+ removeAllAddresses();
+
+ for (size_t i = 0 ; i < other.getMailboxCount() ; ++i) {
+ m_list.push_back(dynamicCast <address>(other.getMailboxAt(i)->clone()));
+ }
+
+ return *this;
+}
+
+
+shared_ptr <component> addressList::clone() const {
+
+ return make_shared <addressList>(*this);
+}
+
+
+void addressList::appendAddress(const shared_ptr <address> &addr) {
+
+ m_list.push_back(addr);
+}
+
+
+void addressList::insertAddressBefore(const shared_ptr <address>& beforeAddress, const shared_ptr <address>& addr) {
+
+ const std::vector <shared_ptr <address> >::iterator it = std::find(
+ m_list.begin(), m_list.end(), beforeAddress
+ );
+
+ if (it == m_list.end()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ m_list.insert(it, addr);
+}
+
+
+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(
+ const shared_ptr <address>& afterAddress,
+ const shared_ptr <address>& addr
+) {
+
+ 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, 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(const shared_ptr <address>& addr) {
+
+ const std::vector <shared_ptr <address> >::iterator it = std::find(
+ m_list.begin(), m_list.end(), addr
+ );
+
+ if (it == m_list.end()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ m_list.erase(it);
+}
+
+
+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;
+
+ m_list.erase(it);
+}
+
+
+void addressList::removeAllAddresses() {
+
+ m_list.clear();
+}
+
+
+size_t addressList::getAddressCount() const {
+
+ return m_list.size();
+}
+
+
+bool addressList::isEmpty() const {
+
+ return m_list.empty();
+}
+
+
+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 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) {
+
+ list.push_back(*it);
+ }
+
+ return list;
+}
+
+
+const std::vector <shared_ptr <address> > addressList::getAddressList() {
+
+ return m_list;
+}
+
+
+const std::vector <shared_ptr <component> > addressList::getChildComponents() {
+
+ std::vector <shared_ptr <component> > list;
+
+ copy_vector(m_list, list);
+
+ return list;
+}
+
+
+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) {
+
+ shared_ptr <const address> addr = *it;
+
+ 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) {
+
+ res->appendMailbox(vmime::clone(*jt));
+ }
+
+ } else {
+
+ res->appendMailbox(dynamicCast <mailbox>(addr->clone()));
+ }
+ }
+
+ return res;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/addressList.hpp b/vmime-master/src/vmime/addressList.hpp
new file mode 100644
index 0000000..69cbd74
--- /dev/null
+++ b/vmime-master/src/vmime/addressList.hpp
@@ -0,0 +1,198 @@
+//
+// 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_ADDRESSLIST_HPP_INCLUDED
+#define VMIME_ADDRESSLIST_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/headerFieldValue.hpp"
+
+#include "vmime/address.hpp"
+
+
+namespace vmime {
+
+
+class mailboxList;
+
+
+/** A list of addresses.
+ */
+class VMIME_EXPORT addressList : public headerFieldValue {
+
+public:
+
+ addressList();
+ addressList(const addressList& addrList);
+
+ ~addressList();
+
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ addressList& operator=(const addressList& other);
+ addressList& operator=(const mailboxList& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+
+ /** Add a address at the end of the list.
+ *
+ * @param addr address to append
+ */
+ void appendAddress(const shared_ptr <address>& addr);
+
+ /** Insert a new address before the specified address.
+ *
+ * @param beforeAddress address before which the new address will be inserted
+ * @param addr address to insert
+ * @throw std::out_of_range if the address is not in the list
+ */
+ void insertAddressBefore(
+ const shared_ptr <address>& beforeAddress,
+ const shared_ptr <address>& addr
+ );
+
+ /** Insert a new address before the specified position.
+ *
+ * @param pos position at which to insert the new address (0 to insert at
+ * the beginning of the list)
+ * @param addr address to insert
+ * @throw std::out_of_range if the position is out of range
+ */
+ void insertAddressBefore(const size_t pos, const shared_ptr <address>& addr);
+
+ /** Insert a new address after the specified address.
+ *
+ * @param afterAddress address after which the new address will be inserted
+ * @param addr address to insert
+ * @throw std::out_of_range if the address is not in the list
+ */
+ void insertAddressAfter(
+ const shared_ptr <address>& afterAddress,
+ const shared_ptr <address>& addr
+ );
+
+ /** Insert a new address after the specified position.
+ *
+ * @param pos position of the address before the new address
+ * @param addr address to insert
+ * @throw std::out_of_range if the position is out of range
+ */
+ 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(const shared_ptr <address>& addr);
+
+ /** Remove the address at the specified position.
+ *
+ * @param pos position of the address to remove
+ * @throw std::out_of_range if the position is out of range
+ */
+ void removeAddress(const size_t pos);
+
+ /** Remove all addresses from the list.
+ */
+ void removeAllAddresses();
+
+ /** Return the number of addresses in the list.
+ *
+ * @return number of addresses
+ */
+ size_t getAddressCount() const;
+
+ /** Tests whether the list of addresses is empty.
+ *
+ * @return true if there is no address, false otherwise
+ */
+ bool isEmpty() const;
+
+ /** Return the address at the specified position.
+ *
+ * @param pos position
+ * @return address at position 'pos'
+ * @throw std::out_of_range if the position is out of range
+ */
+ shared_ptr <address> getAddressAt(const size_t pos);
+
+ /** Return the address at the specified position.
+ *
+ * @param pos position
+ * @return address at position 'pos'
+ * @throw std::out_of_range if the position is out of range
+ */
+ const shared_ptr <const address> getAddressAt(const size_t pos) const;
+
+ /** Return the address list.
+ *
+ * @return list of addresses
+ */
+ const std::vector <shared_ptr <const address> > getAddressList() const;
+
+ /** Return the address list.
+ *
+ * @return list of addresses
+ */
+ const std::vector <shared_ptr <address> > getAddressList();
+
+ /** Return a list of mailboxes.
+ * If some addresses are actually groups, mailboxes are recursively
+ * extracted from these groups.
+ *
+ * @return list of mailboxes
+ */
+ shared_ptr <mailboxList> toMailboxList() const;
+
+private:
+
+ std::vector <shared_ptr <address> > m_list;
+
+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 generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_ADDRESSLIST_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/attachment.hpp b/vmime-master/src/vmime/attachment.hpp
new file mode 100644
index 0000000..be20e33
--- /dev/null
+++ b/vmime-master/src/vmime/attachment.hpp
@@ -0,0 +1,116 @@
+//
+// 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_ATTACHMENT_HPP_INCLUDED
+#define VMIME_ATTACHMENT_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+
+#include "vmime/bodyPart.hpp"
+#include "vmime/mediaType.hpp"
+#include "vmime/text.hpp"
+#include "vmime/contentHandler.hpp"
+#include "vmime/encoding.hpp"
+
+
+namespace vmime {
+
+
+/** Base class for all types of attachment.
+ */
+class VMIME_EXPORT attachment : public object {
+
+ friend class messageBuilder;
+ friend class messageParser;
+ friend class attachmentHelper;
+
+protected:
+
+ attachment() { }
+
+public:
+
+ virtual ~attachment() { }
+
+ /** Return the media type of this attachment.
+ *
+ * @return content type of the attachment
+ */
+ virtual const mediaType getType() const = 0;
+
+ /** Return the description of this attachment.
+ *
+ * @return attachment description, or an empty text
+ * if no description is available
+ */
+ virtual const text getDescription() const = 0;
+
+ /** Return the (file) name of this attachment.
+ *
+ * @return attachment name, or an empty word if no
+ * name is available
+ */
+ virtual const word getName() const = 0;
+
+ /** Return the data contained in this attachment.
+ *
+ * @return attachment data
+ */
+ virtual const shared_ptr <const contentHandler> getData() const = 0;
+
+ /** Return the encoding used for this attachment.
+ *
+ * @return attachment data encoding
+ */
+ virtual const encoding getEncoding() const = 0;
+
+ /** Return the part in which the attachment has been found.
+ * This can be a vmime::bodyPart or a vmime::net::part object.
+ *
+ * @return attachment part or NULL if the attachment is not
+ * attached to a part
+ */
+ virtual shared_ptr <const object> getPart() const = 0;
+
+ /** Return the header of the attachment part.
+ *
+ * @return attachment part header or NULL if the attachment
+ * is not attached to a part
+ */
+ virtual shared_ptr <const header> getHeader() const = 0;
+
+protected:
+
+ /** Generate the attachment in the specified body part.
+ *
+ * @param parent body part in which to generate the attachment
+ */
+ virtual void generateIn(const shared_ptr <bodyPart>& parent) const = 0;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_ATTACHMENT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/attachmentHelper.cpp b/vmime-master/src/vmime/attachmentHelper.cpp
new file mode 100644
index 0000000..8605122
--- /dev/null
+++ b/vmime-master/src/vmime/attachmentHelper.cpp
@@ -0,0 +1,339 @@
+//
+// 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.
+//
+
+#include "vmime/attachmentHelper.hpp"
+
+#include "vmime/bodyPartAttachment.hpp"
+#include "vmime/parsedMessageAttachment.hpp"
+#include "vmime/generatedMessageAttachment.hpp"
+
+#include "vmime/disposition.hpp"
+#include "vmime/emptyContentHandler.hpp"
+
+#include <iterator>
+
+
+namespace vmime {
+
+
+// static
+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) {
+
+ const contentDisposition disp = *cdf->getValue <contentDisposition>();
+
+ if (disp.getName() != contentDispositionTypes::INLINE) {
+ return true;
+ }
+
+ 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)) {
+
+ // If this is the root part, it might not be an attachment
+ if (!part->getParentPart()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ // Assume "attachment" if type is not "text/..." or "multipart/...".
+ mediaType type;
+ bool hasContentTypeName = false;
+
+ shared_ptr <const contentTypeField> ctf =
+ part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
+
+ if (ctf) {
+
+ type = *ctf->getValue <mediaType>();
+
+ if (ctf->hasParameter("name")) {
+ hasContentTypeName = true;
+ }
+
+ } 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()) {
+ return false;
+ }
+
+ // No "Content-type" field: assume "application/octet-stream".
+ type = mediaType(
+ mediaTypes::APPLICATION,
+ mediaTypes::APPLICATION_OCTET_STREAM
+ );
+ }
+
+ if (type.getType() != mediaTypes::TEXT &&
+ 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) {
+ return true;
+ }
+
+ 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)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+
+// static
+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) {
+
+ type = *ctf->getValue <mediaType>();
+
+ } else {
+
+ // No "Content-type" field: assume "application/octet-stream".
+ type = mediaType(
+ mediaTypes::APPLICATION,
+ mediaTypes::APPLICATION_OCTET_STREAM
+ );
+ }
+
+ if (type.getType() == mediaTypes::MESSAGE &&
+ type.getSubType() == mediaTypes::MESSAGE_RFC822) {
+
+ return make_shared <generatedMessageAttachment>(part);
+
+ } else {
+
+ return make_shared <bodyPartAttachment>(part);
+ }
+}
+
+
+// static
+const std::vector <shared_ptr <const attachment> >
+ 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(
+ const shared_ptr <const bodyPart>& part,
+ const unsigned int options
+ ) {
+
+ std::vector <shared_ptr <const attachment> > atts;
+
+ // Test this part
+ if (isBodyPartAnAttachment(part, options)) {
+
+ atts.push_back(getBodyPartAttachment(part, options));
+
+ // Find in sub-parts
+ } else {
+
+ shared_ptr <const body> bdy = part->getBody();
+
+ for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) {
+
+ std::vector <shared_ptr <const attachment> > partAtts =
+ findAttachmentsInBodyPart(bdy->getPartAt(i), options);
+
+ std::copy(partAtts.begin(), partAtts.end(), std::back_inserter(atts));
+ }
+ }
+
+ return atts;
+}
+
+
+// static
+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
+ );
+
+ shared_ptr <bodyPart> part = findBodyPart(msg, mpMixed);
+
+ 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_TRANSFER_ENCODING)) {
+
+ container->getHeader()->ContentTransferEncoding()->setValue(
+ msg->getHeader()->ContentTransferEncoding()->getValue()
+ );
+ }
+
+ // Move parts from the root part to this new part
+ const std::vector <shared_ptr <bodyPart> > partList =
+ msg->getBody()->getPartList();
+
+ msg->getBody()->removeAllParts();
+
+ for (unsigned int i = 0 ; i < partList.size() ; ++i) {
+ container->getBody()->appendPart(partList[i]);
+ }
+
+ msg->getBody()->appendPart(container);
+
+ } 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_TRANSFER_ENCODING)) {
+
+ child->getHeader()->ContentTransferEncoding()->setValue(
+ msg->getHeader()->ContentTransferEncoding()->getValue()
+ );
+ }
+
+ child->getBody()->setContents(msg->getBody()->getContents());
+ msg->getBody()->setContents(make_shared <emptyContentHandler>());
+
+ msg->getBody()->appendPart(child);
+ }
+
+ // Set the root part to 'multipart/mixed'
+ msg->getHeader()->ContentType()->setValue(mpMixed);
+
+ msg->getHeader()->removeAllFields(vmime::fields::CONTENT_DISPOSITION);
+ msg->getHeader()->removeAllFields(vmime::fields::CONTENT_TRANSFER_ENCODING);
+
+ part = msg;
+ }
+
+ // Generate the attachment part
+ att->generateIn(part);
+}
+
+
+// static
+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);
+
+ if (found) {
+ return found;
+ }
+ }
+
+ return null;
+}
+
+
+// static
+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
diff --git a/vmime-master/src/vmime/attachmentHelper.hpp b/vmime-master/src/vmime/attachmentHelper.hpp
new file mode 100644
index 0000000..f28819f
--- /dev/null
+++ b/vmime-master/src/vmime/attachmentHelper.hpp
@@ -0,0 +1,137 @@
+//
+// 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_ATTACHMENTHELPER_HPP_INCLUDED
+#define VMIME_ATTACHMENTHELPER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+#include "vmime/attachment.hpp"
+#include "vmime/message.hpp"
+
+
+namespace vmime {
+
+
+/** Retrieve attachment information from message parts.
+ */
+class VMIME_EXPORT attachmentHelper {
+
+public:
+
+ /** Options for use with the following functions:
+ * findAttachmentsInMessage,
+ * getBodyPartAttachment,
+ * and isBodyPartAnAttachment.
+ */
+ 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. */
+ };
+
+ /** Test whether a body part is an attachment.
+ *
+ * @param part message part to test
+ * @param options search options (see FindOptions)
+ * @return true if the part is an attachment, false otherwise
+ */
+ 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
+ * information (ie. is not an attachment), NULL is returned.
+ *
+ * @param part message part in which to search
+ * @param options search options (see FindOptions)
+ * @return attachment found in the part, or NULL
+ */
+ 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.
+ * This is simply a recursive call to getBodyPartAttachment().
+ *
+ * @param part part in which to search
+ * @param options search options (see FindOptions)
+ * @return a list of attachments found
+ */
+ static const std::vector <shared_ptr <const attachment> >
+ 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().
+ *
+ * @param msg message in which to search
+ * @param options search options (see FindOptions)
+ * @return a list of attachments found
+ */
+ static const std::vector <shared_ptr <const attachment> >
+ 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(
+ 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(
+ const shared_ptr <message>& msg,
+ const shared_ptr <message>& amsg
+ );
+
+protected:
+
+ static shared_ptr <bodyPart> findBodyPart(
+ const shared_ptr <bodyPart>& part,
+ const mediaType& type
+ );
+};
+
+
+} // vmime
+
+
+#endif // VMIME_ATTACHMENTHELPER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/base.cpp b/vmime-master/src/vmime/base.cpp
new file mode 100644
index 0000000..395d7b3
--- /dev/null
+++ b/vmime-master/src/vmime/base.cpp
@@ -0,0 +1,158 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+#include "vmime/charset.hpp"
+#include "vmime/base.hpp"
+
+#include "vmime/utility/encoder/encoder.hpp"
+#include "vmime/utility/encoder/b64Encoder.hpp"
+#include "vmime/utility/encoder/qpEncoder.hpp"
+
+#include "vmime/text.hpp"
+
+#include "vmime/parserHelpers.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+// For initializing
+#include "vmime/utility/encoder/encoderFactory.hpp"
+#include "vmime/headerFieldFactory.hpp"
+#include "vmime/textPartFactory.hpp"
+#include "vmime/generationContext.hpp"
+#include "vmime/parsingContext.hpp"
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ #include "vmime/net/serviceFactory.hpp"
+#endif
+
+
+namespace vmime {
+
+
+/** "Null" (empty) string.
+ */
+const string NULL_STRING;
+
+/** "Null" (empty) text.
+ */
+const text NULL_TEXT;
+
+/** "Null" (empty) word.
+ */
+const word NULL_WORD("", vmime::charset(vmime::charsets::US_ASCII));
+
+
+/** Return the library name (eg: "libvmime").
+ *
+ * @return library name
+ */
+const string libname() { return (VMIME_PACKAGE); }
+
+/** Return the library version (eg: "0.5.2").
+ *
+ * @return library version
+ */
+const string libversion() { return (VMIME_VERSION " (" __DATE__ " " __TIME__ ")"); }
+
+/** Return the library API version (eg: "6:1:6").
+ *
+ * @return library API version
+ */
+const string libapi() { return (VMIME_API); }
+
+
+// New line sequence to be used when folding header fields.
+const string NEW_LINE_SEQUENCE = "\r\n ";
+const size_t NEW_LINE_SEQUENCE_LENGTH = 1; // space
+
+/** The CR-LF sequence.
+ */
+const string CRLF = "\r\n";
+
+
+/** The current MIME version supported by VMime.
+ */
+const string SUPPORTED_MIME_VERSION = "1.0";
+
+
+#ifndef VMIME_BUILDING_DOC
+
+/** Null shared pointer.
+ */
+nullPtrType null;
+
+#endif // VMIME_BUILDING_DOC
+
+
+// Line length limits
+namespace lineLengthLimits {
+
+ const size_t infinite = std::numeric_limits <size_t>::max();
+}
+
+
+const size_t npos = std::numeric_limits <size_t>::max();
+
+
+
+#ifndef VMIME_BUILDING_DOC
+
+//
+// V-Mime Initializer
+// ====================
+//
+// Force instanciation of singletons. This is to prevent problems that might
+// happen in multithreaded applications...
+//
+// WARNING: we put the initializer at the end of this compilation unit. This
+// ensures this object is initialized _after_ all other global variables in
+// the same compilation unit (in particular "lineLengthLimits::infinite",
+// which is used by the generate() function (called from "textPartFactory"
+// constructor, for example).
+//
+
+struct initializer {
+
+ initializer() {
+
+ parsingContext::getDefaultContext();
+ generationContext::getDefaultContext();
+
+ utility::encoder::encoderFactory::getInstance();
+ headerFieldFactory::getInstance();
+ textPartFactory::getInstance();
+
+ #if VMIME_HAVE_MESSAGING_FEATURES
+ net::serviceFactory::getInstance();
+ #endif
+ }
+};
+
+initializer theInitializer;
+
+#endif // VMIME_BUILDING_DOC
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/base.hpp b/vmime-master/src/vmime/base.hpp
new file mode 100644
index 0000000..7782477
--- /dev/null
+++ b/vmime-master/src/vmime/base.hpp
@@ -0,0 +1,258 @@
+//
+// 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_BASE_HPP_INCLUDED
+#define VMIME_BASE_HPP_INCLUDED
+
+
+#include <string>
+#include <vector>
+#include <map>
+#include <sstream>
+#include <cctype>
+#include <locale>
+
+#include "vmime/config.hpp"
+#include "vmime/types.hpp"
+#include "vmime/constants.hpp"
+
+
+namespace vmime {
+
+ class text;
+ class word;
+ class charset;
+
+
+ // "Null" strings
+ extern VMIME_EXPORT const string NULL_STRING;
+
+ extern VMIME_EXPORT const text NULL_TEXT;
+ extern VMIME_EXPORT const word NULL_WORD;
+
+#ifndef VMIME_BUILDING_DOC
+
+ // Null pointer
+ struct nullPtrType {
+
+ template <typename T>
+ operator shared_ptr <T>() { return shared_ptr <T>(); }
+ };
+
+ extern nullPtrType VMIME_EXPORT null;
+
+#endif // VMIME_BUILDING_DOC
+
+
+ //
+ // Library name and version
+ //
+
+ const string VMIME_EXPORT libname();
+ const string VMIME_EXPORT libversion();
+ const string VMIME_EXPORT libapi();
+
+
+ //
+ // Helpful functions used for array -> iterator conversion
+ //
+
+ template <typename T, size_t N>
+ 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;
+ }
+
+ template <typename T, size_t N>
+ inline T* begin(T (&array)[N]) {
+
+ return array;
+ }
+
+ template <typename T, size_t 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;
+ }
+
+
+ // Copy one vector to another, with type conversion
+
+ template <class T1, class T2>
+ 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) {
+ v2[i] = v1[i];
+ }
+ }
+
+
+ /*
+
+ RFC#2822
+ 2.1.1. Line Length Limits
+
+ There are two limits that this standard places on the number of
+ characters in a line. Each line of characters MUST be no more than
+ 998 characters, and SHOULD be no more than 78 characters, excluding
+ the CRLF.
+
+ The 998 character limit is due to limitations in many implementations
+ which send, receive, or store Internet Message Format messages that
+ simply cannot handle more than 998 characters on a line. Receiving
+ implementations would do well to handle an arbitrarily large number
+ of characters in a line for robustness sake. However, there are so
+ many implementations which (in compliance with the transport
+ requirements of [RFC2821]) do not accept messages containing more
+ than 1000 character including the CR and LF per line, it is important
+ for implementations not to create such messages.
+
+ The more conservative 78 character recommendation is to accommodate
+ the many implementations of user interfaces that display these
+ messages which may truncate, or disastrously wrap, the display of
+ more than 78 characters per line, in spite of the fact that such
+ implementations are non-conformant to the intent of this specification
+ (and that of [RFC2821] if they actually cause information to be lost).
+ Again, even though this limitation is put on messages, it is encumbant
+ upon implementations which display messages to handle an arbitrarily
+ large number of characters in a line (certainly at least up to the 998
+ character limit) for the sake of robustness.
+ */
+
+ namespace lineLengthLimits {
+
+ extern VMIME_EXPORT const size_t infinite;
+
+ enum {
+ max = 998,
+ convenient = 78
+ };
+ }
+
+
+ // New line sequence to be used when folding header fields.
+ extern VMIME_EXPORT const string NEW_LINE_SEQUENCE;
+ extern VMIME_EXPORT const size_t NEW_LINE_SEQUENCE_LENGTH;
+
+
+ // CR-LF sequence
+ extern VMIME_EXPORT const string CRLF;
+
+
+ // Mime version
+ extern VMIME_EXPORT const string SUPPORTED_MIME_VERSION;
+
+ /** Utility classes. */
+ namespace utility { }
+
+
+ /** Constant value with the greatest possible value for an element
+ * of type size_t. The meaning is "infinite" or "until the end".
+ */
+ extern VMIME_EXPORT const size_t npos;
+
+
+ /** Clone helper (using a shared_ptr).
+ * This is an alias for dynamic_pointer_cast <T>(obj->clone()).
+ */
+ template <class T>
+ shared_ptr <T> clone(const shared_ptr <T>& obj) {
+
+ return dynamic_pointer_cast <T>(obj->clone());
+ }
+
+ /** Clone helper (using a const shared_ptr).
+ * This is an alias for dynamic_pointer_cast <T>(obj->clone()).
+ */
+ template <class T>
+ shared_ptr <T> clone(const shared_ptr <const T>& obj) {
+
+ return dynamic_pointer_cast <T>(obj->clone());
+ }
+
+ /** Clone helper (using a const reference).
+ * This is an alias for dynamic_pointer_cast <T>(obj.clone()).
+ */
+ template <class T>
+ shared_ptr <T> clone(const T& obj) {
+
+ return dynamic_pointer_cast <T>(obj.clone());
+ }
+
+ /** Downcast helper.
+ * Usage: vmime::dynamicCast <DerivedType>(obj), where 'obj' is of
+ * type Type, and DerivedType is derived from Type.
+ */
+ template <class X, class Y>
+ 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) {
+
+ 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
+
+
+#include "vmime/utility/stream.hpp"
+
+
+#endif // VMIME_BASE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/body.cpp b/vmime-master/src/vmime/body.cpp
new file mode 100644
index 0000000..a3875b9
--- /dev/null
+++ b/vmime-master/src/vmime/body.cpp
@@ -0,0 +1,1111 @@
+//
+// 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.
+//
+
+#include "vmime/bodyPart.hpp"
+#include "vmime/body.hpp"
+
+#include "vmime/contentTypeField.hpp"
+#include "vmime/text.hpp"
+
+#include "vmime/utility/random.hpp"
+
+#include "vmime/utility/seekableInputStreamRegionAdapter.hpp"
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+#include "vmime/parserHelpers.hpp"
+
+#include "vmime/emptyContentHandler.hpp"
+#include "vmime/stringContentHandler.hpp"
+#include "vmime/streamContentHandler.hpp"
+
+
+namespace vmime {
+
+
+body::body()
+ : m_contents(make_shared <emptyContentHandler>()) {
+
+}
+
+
+body::~body() {
+
+}
+
+
+/*
+ * boundaryStart: will become the index for "\r\n--marker"
+ * boundaryEnd: will become the index after "marker", i.e. index for potential trailing "--", "\r\n", etc.
+ * return value: index for "marker"
+ */
+// static
+size_t body::findNextBoundaryPosition(
+ const shared_ptr <utility::parserInputStreamAdapter>& parser,
+ const string& boundary,
+ const size_t position,
+ const size_t end,
+ size_t* boundaryStart,
+ size_t* boundaryEnd
+) {
+
+ size_t pos = position;
+
+ for (; pos != npos && pos < end; ++pos) {
+
+ pos = parser->findNext(boundary, pos);
+
+ if (pos == npos) {
+ break; // not found
+ }
+
+ if (pos == 0) {
+ // Boundary is a prefix of another, continue the search (same for the other "continue"s)
+ continue;
+ }
+
+ // Ensure the bytes before boundary are "[LF]--": boundary should be
+ // at the beginning of a line, and should start with "--"
+ if (pos < 3) {
+ continue;
+ }
+ parser->seek(pos - 3);
+ if (!parser->matchBytes("\n--", 3)) {
+ continue;
+ }
+
+ parser->seek(pos + boundary.length());
+
+ const byte_t next = parser->peekByte();
+
+ // Boundary should be followed by a new line or a dash
+ if (!isspace(next) && next != '-') {
+ continue;
+ }
+
+ // Get rid of the "[CR]" just before "[LF]--", if any
+ size_t backwards = 0;
+ if (pos >= 4) {
+ parser->seek(pos - 4);
+ if (parser->peekByte() == '\r') {
+ ++backwards;
+ }
+ }
+
+ *boundaryStart = pos - backwards - 3;
+ *boundaryEnd = pos + boundary.length();
+
+ return pos;
+ }
+
+ return pos;
+}
+
+
+void body::parseImpl(
+ const parsingContext& ctx,
+ const shared_ptr <utility::parserInputStreamAdapter>& parser,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ removeAllParts();
+
+ m_prologText.clear();
+ m_epilogText.clear();
+
+ if (end == position) {
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+
+ return;
+ }
+
+ // Check whether the body is a MIME-multipart.
+ // If it is, also get (or try to guess) the boundary separator.
+ bool isMultipart = false;
+ string boundary;
+
+ shared_ptr <const contentTypeField> ctf =
+ m_part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
+
+ if (ctf) {
+
+ const mediaType type = *ctf->getValue <mediaType>();
+
+ if (type.getType() == mediaTypes::MULTIPART) {
+
+ isMultipart = true;
+
+ if (ctf->hasBoundary()) {
+
+ boundary = ctf->getBoundary();
+
+ } else {
+
+ // No "boundary" parameter specified: we can try to
+ // guess it by scanning the body contents...
+ size_t pos = position;
+
+ parser->seek(pos);
+
+ if (pos + 2 < end && parser->matchBytes("--", 2)) {
+
+ pos += 2;
+
+ } else {
+
+ pos = parser->findNext("\n--", position);
+
+ if ((pos != npos) && (pos + 3 < end)) {
+ pos += 3; // skip \n--
+ }
+ }
+
+ if ((pos != npos) && (pos < end)) {
+
+ parser->seek(pos);
+
+ // Read some bytes after boundary separator
+ byte_t buffer[256];
+ const size_t bufferLen =
+ parser->read(buffer, std::min(end - pos, sizeof(buffer) / sizeof(buffer[0])));
+
+ buffer[sizeof(buffer) / sizeof(buffer[0]) - 1] = '\0';
+
+ // Skip transport padding bytes (SPACE or HTAB), if any
+ size_t boundarySkip = 0;
+
+ while (boundarySkip < bufferLen && parserHelpers::isSpace(buffer[boundarySkip])) {
+ ++boundarySkip;
+ }
+
+ // Extract boundary from buffer (stop at first CR or LF).
+ // We have to stop after a reasonnably long boundary length (100)
+ // not to take the whole body contents for a boundary...
+ byte_t boundaryBytes[100];
+ size_t boundaryLen = 0;
+
+ for (byte_t c = buffer[boundarySkip] ;
+ boundaryLen < bufferLen && boundaryLen < 100 && !(c == '\r' || c == '\n') ;
+ ++boundaryLen, c = buffer[boundarySkip + boundaryLen]) {
+
+ boundaryBytes[boundaryLen] = c;
+ }
+
+ if (boundaryLen >= 1 && boundaryLen < 100) {
+
+ // RFC #1521, Page 31:
+ // "...the boundary parameter, which consists of 1 to 70
+ // characters from a set of characters known to be very
+ // robust through email gateways, and NOT ending with
+ // white space..."
+ while (boundaryLen != 0 &&
+ parserHelpers::isSpace(boundaryBytes[boundaryLen - 1])) {
+
+ boundaryLen--;
+ }
+
+ if (boundaryLen >= 1) {
+ boundary = string(boundaryBytes, boundaryBytes + boundaryLen);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // This is a multi-part body
+ if (isMultipart && !boundary.empty()) {
+
+ size_t partStart = position;
+ size_t pos = position;
+
+ bool lastPart = false;
+
+ // Find the first boundary
+ size_t boundaryStart, boundaryEnd;
+ pos = findNextBoundaryPosition(parser, boundary, pos, end, &boundaryStart, &boundaryEnd);
+
+ for (int index = 0 ; !lastPart && (pos != npos) && (pos < end) ; ++index) {
+
+ size_t partEnd = boundaryStart;
+
+ // Check whether it is the last part (boundary terminated by "--")
+ parser->seek(boundaryEnd);
+
+ if (boundaryEnd + 1 < end && parser->matchBytes("--", 2)) {
+
+ lastPart = true;
+ boundaryEnd += 2;
+ }
+
+ // RFC 2046 §5.1.1 page 22: """If a boundary delimiter
+ // line appears to end with white space, the white
+ // space must be presumed to have been added by a
+ // gateway, and must be deleted."""
+ parser->seek(boundaryEnd);
+ boundaryEnd += parser->skipIf(parserHelpers::isSpaceOrTab, end);
+
+ // End of boundary line
+ if (boundaryEnd + 1 < end && parser->matchBytes("\r\n", 2)) {
+ boundaryEnd += 2;
+ } else if (boundaryEnd < end && parser->peekByte() == '\n') {
+ ++boundaryEnd;
+ } else if (boundaryEnd == end) {
+ } else {
+ /*
+ * RFC 2046 §5.1.1 page 19: """[...] optional
+ * linear whitespace, and a terminating
+ * CRLF.""" — junk handling is left
+ * unspecified, so we might as well skip it to
+ * facilitate broken mails.
+ */
+ boundaryEnd += parser->skipIf([](char_t c) { return c != '\n'; }, end);
+ pos = findNextBoundaryPosition(parser, boundary, boundaryEnd, end, &boundaryStart, &boundaryEnd);
+ --index;
+ continue;
+ }
+
+ if (index == 0) {
+
+ if (partEnd > partStart) {
+
+ vmime::text text;
+ text.parse(ctx, parser, partStart, partEnd);
+
+ m_prologText = text.getWholeBuffer();
+
+ } else {
+
+ m_prologText = "";
+ }
+
+ } else { // index > 0
+
+ shared_ptr <bodyPart> part = m_part->createChildPart();
+
+ // End before start may happen on empty bodyparts (directly
+ // successive boundaries without even a line-break)
+ if (partEnd < partStart) {
+ std::swap(partStart, partEnd);
+ }
+
+ part->parse(ctx, parser, partStart, partEnd, NULL);
+
+ m_parts.push_back(part);
+ }
+
+ partStart = boundaryEnd;
+
+ // Find the next boundary
+ pos = findNextBoundaryPosition(
+ parser, boundary, boundaryEnd, end, &boundaryStart, &boundaryEnd
+ );
+ }
+
+ m_contents = make_shared <emptyContentHandler>();
+
+ // Last part was not found: recover from missing boundary
+ if (!lastPart && pos == npos) {
+
+ shared_ptr <bodyPart> part = m_part->createChildPart();
+
+ try {
+ part->parse(ctx, parser, partStart, end);
+ } catch (std::exception&) {
+ throw;
+ }
+
+ m_parts.push_back(part);
+
+ // Treat remaining text as epilog
+ } else if (partStart < end) {
+
+ vmime::text text;
+ text.parse(ctx, parser, partStart, end);
+
+ m_epilogText = text.getWholeBuffer();
+ }
+
+ // Treat the contents as 'simple' data
+ } else {
+
+ encoding enc;
+
+ shared_ptr <const headerField> cef =
+ m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING);
+
+ if (cef) {
+
+ enc = *cef->getValue <encoding>();
+
+ } else {
+
+ // Defaults to "7bit" (RFC-1521)
+ enc = vmime::encoding(encodingTypes::SEVEN_BIT);
+ }
+
+ // Extract the (encoded) contents
+ const size_t length = end - position;
+
+ shared_ptr <utility::inputStream> contentStream =
+ make_shared <utility::seekableInputStreamRegionAdapter>(
+ parser->getUnderlyingStream(), position, length
+ );
+
+ m_contents = make_shared <streamContentHandler>(contentStream, length, enc);
+ }
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+text body::getActualPrologText(const generationContext& ctx) const {
+
+ const string& prologText =
+ m_prologText.empty()
+ ? (isRootPart()
+ ? ctx.getPrologText()
+ : NULL_STRING
+ )
+ : m_prologText;
+
+ if (prologText.empty()) {
+ return text();
+ } else {
+ return text(prologText, vmime::charset("us-ascii"));
+ }
+}
+
+
+text body::getActualEpilogText(const generationContext& ctx) const {
+
+ const string& epilogText =
+ m_epilogText.empty()
+ ? (isRootPart()
+ ? ctx.getEpilogText()
+ : NULL_STRING
+ )
+ : m_epilogText;
+
+ if (epilogText.empty()) {
+ return text();
+ } else {
+ return text(epilogText, vmime::charset("us-ascii"));
+ }
+}
+
+
+void body::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t /* curLinePos */,
+ size_t* newLinePos
+) const {
+
+ // MIME-Multipart
+ if (getPartCount() != 0) {
+
+ string boundary;
+
+ if (!m_part) {
+
+ boundary = generateRandomBoundaryString();
+
+ } else {
+
+ // Use current boundary string, if specified. If no "Content-Type" field is
+ // present, or the boundary is not specified, generate a random one
+ shared_ptr <contentTypeField> ctf =
+ m_part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
+
+ if (ctf) {
+
+ if (ctf->hasBoundary()) {
+
+ boundary = ctf->getBoundary();
+
+ } else {
+
+ // No boundary string specified
+ boundary = generateRandomBoundaryString();
+ }
+
+ } else {
+
+ // No Content-Type (and no boundary string specified)
+ boundary = generateRandomBoundaryString();
+ }
+ }
+
+ const text prologText = getActualPrologText(ctx);
+ const text epilogText = getActualEpilogText(ctx);
+
+ if (!prologText.isEmpty()) {
+
+ prologText.encodeAndFold(
+ ctx, os, 0, NULL,
+ text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE
+ );
+
+ os << CRLF;
+ }
+
+ os << "--" << boundary;
+
+ for (size_t p = 0 ; p < getPartCount() ; ++p) {
+
+ os << CRLF;
+
+ getPartAt(p)->generate(ctx, os, 0);
+
+ os << CRLF << "--" << boundary;
+ }
+
+ os << "--" << CRLF;
+
+ if (!epilogText.isEmpty()) {
+
+ epilogText.encodeAndFold(
+ ctx, os, 0, NULL,
+ text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE
+ );
+
+ os << CRLF;
+ }
+
+ if (newLinePos) {
+ *newLinePos = 0;
+ }
+
+ // Simple body
+ } else {
+
+ // Generate the contents
+ shared_ptr <contentHandler> contents = m_contents->clone();
+ contents->setContentTypeHint(getContentType());
+
+ contents->generate(os, getEncoding(), ctx.getMaxLineLength());
+ }
+}
+
+
+size_t body::getGeneratedSize(const generationContext& ctx) {
+
+ // MIME-Multipart
+ if (getPartCount() != 0) {
+
+ size_t size = 0;
+
+ // Size of parts and boundaries
+ for (size_t p = 0 ; p < getPartCount() ; ++p) {
+ size += 100; // boundary, CRLF...
+ size += getPartAt(p)->getGeneratedSize(ctx);
+ }
+
+ // Size of prolog/epilog text
+ const text prologText = getActualPrologText(ctx);
+
+ if (!prologText.isEmpty()) {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter osa(oss);
+
+ prologText.encodeAndFold(
+ ctx, osa, 0, NULL,
+ text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE
+ );
+
+ size += oss.str().size();
+ }
+
+ const text epilogText = getActualEpilogText(ctx);
+
+ if (!epilogText.isEmpty()) {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter osa(oss);
+
+ epilogText.encodeAndFold(
+ ctx, osa, 0, NULL,
+ text::FORCE_NO_ENCODING | text::NO_NEW_LINE_SEQUENCE
+ );
+
+ size += oss.str().size();
+ }
+
+ return size;
+
+ // Simple body
+ } else {
+
+ if (getEncoding() == m_contents->getEncoding()) {
+
+ // No re-encoding has to be performed
+ return m_contents->getLength();
+
+ } else {
+
+ shared_ptr <utility::encoder::encoder> srcEncoder = m_contents->getEncoding().getEncoder();
+ shared_ptr <utility::encoder::encoder> dstEncoder = getEncoding().getEncoder();
+
+ return dstEncoder->getEncodedSize(srcEncoder->getDecodedSize(m_contents->getLength()));
+ }
+ }
+}
+
+
+/*
+ RFC #1521, Page 32:
+ 7.2.1. Multipart: The common syntax
+
+ "...Encapsulation boundaries must not appear within the
+ encapsulations, and must be no longer than 70 characters..."
+
+
+ boundary := 0*69<bchars> bcharsnospace
+
+ bchars := bcharsnospace / " "
+
+ bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / "+" /"_"
+ / "," / "-" / "." / "/" / ":" / "=" / "?"
+*/
+
+const string body::generateRandomBoundaryString() {
+
+ // 64 characters that can be _safely_ used in a boundary string
+ static const char bchars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-+";
+
+ /*
+ RFC #1521, Page 19:
+
+ Since the hyphen character ("-") is represented as itself in the
+ Quoted-Printable encoding, care must be taken, when encapsulating a
+ quoted-printable encoded body in a multipart entity, to ensure that
+ the encapsulation boundary does not appear anywhere in the encoded
+ body. (A good strategy is to choose a boundary that includes a
+ character sequence such as "=_" which can never appear in a quoted-
+ printable body. See the definition of multipart messages later in
+ this document.)
+ */
+
+ char boundary[2 + 48 + 1] = { 0 };
+
+ boundary[0] = '=';
+ boundary[1] = '_';
+
+ // Generate a string of random characters
+ unsigned int r = utility::random::getTime();
+ unsigned int m = static_cast <unsigned int>(sizeof(unsigned int));
+
+ for (size_t i = 2 ; i < (sizeof(boundary) / sizeof(boundary[0]) - 1) ; ++i) {
+
+ boundary[i] = bchars[r & 63];
+ r >>= 6;
+
+ if (--m == 0) {
+ r = utility::random::getNext();
+ m = static_cast <unsigned int>(sizeof(unsigned int));
+ }
+ }
+
+ return string(boundary);
+}
+
+
+bool body::isValidBoundary(const string& boundary) {
+
+ static const string validChars("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'()+_,-./:=?");
+
+ const string::const_iterator end = boundary.end();
+ bool valid = false;
+
+ if (boundary.length() > 0 && boundary.length() < 70) {
+
+ const char last = *(end - 1);
+
+ if (!(last == ' ' || last == '\t' || last == '\n')) {
+
+ valid = true;
+
+ for (string::const_iterator i = boundary.begin() ; valid && i != end ; ++i) {
+ valid = (validChars.find_first_of(*i) != string::npos);
+ }
+ }
+ }
+
+ return valid;
+}
+
+
+//
+// Quick-access functions
+//
+
+
+void body::setContentType(const mediaType& type, const charset& chset) {
+
+ shared_ptr <contentTypeField> ctf =
+ dynamicCast <contentTypeField>(m_part->getHeader()->ContentType());
+
+ ctf->setValue(type);
+ ctf->setCharset(chset);
+}
+
+
+void body::setContentType(const mediaType& type) {
+
+ m_part->getHeader()->ContentType()->setValue(type);
+}
+
+
+const mediaType body::getContentType() const {
+
+ shared_ptr <const contentTypeField> ctf =
+ m_part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
+
+ if (ctf) {
+
+ return *ctf->getValue <mediaType>();
+
+ } else {
+
+ // Defaults to "text/plain" (RFC-1521)
+ return mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN);
+ }
+}
+
+
+void body::setCharset(const charset& chset) {
+
+ shared_ptr <contentTypeField> ctf =
+ m_part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
+
+ // If a Content-Type field exists, set charset
+ if (ctf) {
+
+ ctf->setCharset(chset);
+
+ // Else, create a new Content-Type field of default type "text/plain"
+ // and set charset on it
+ } else {
+
+ setContentType(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN), chset);
+ }
+}
+
+
+const charset body::getCharset() const {
+
+ const shared_ptr <const contentTypeField> ctf =
+ m_part->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
+
+ if (ctf) {
+
+ if (ctf->hasCharset()) {
+
+ return ctf->getCharset();
+
+ } else {
+
+ // Defaults to "us-ascii" (RFC-1521)
+ return vmime::charset(charsets::US_ASCII);
+ }
+
+ } else {
+
+ // Defaults to "us-ascii" (RFC-1521)
+ return vmime::charset(charsets::US_ASCII);
+ }
+}
+
+
+void body::setEncoding(const encoding& enc) {
+
+ m_part->getHeader()->ContentTransferEncoding()->setValue(enc);
+}
+
+
+const encoding body::getEncoding() const {
+
+ shared_ptr <const headerField> cef =
+ m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING);
+
+ if (cef) {
+
+ return *cef->getValue <encoding>();
+
+ } else {
+
+ if (m_contents->isEncoded()) {
+ return m_contents->getEncoding();
+ }
+ }
+
+ // Defaults to "7bit" (RFC-1521)
+ return vmime::encoding(encodingTypes::SEVEN_BIT);
+}
+
+
+void body::setParentPart(bodyPart* parent) {
+
+ m_part = parent;
+
+ for (std::vector <shared_ptr <bodyPart> >::iterator it = m_parts.begin() ;
+ it != m_parts.end() ; ++it) {
+
+ shared_ptr <bodyPart> childPart = *it;
+ parent->importChildPart(childPart);
+ }
+}
+
+
+bool body::isRootPart() const {
+
+ return !m_part || !m_part->getParentPart();
+}
+
+
+shared_ptr <component> body::clone() const {
+
+ shared_ptr <body> bdy = make_shared <body>();
+
+ bdy->copyFrom(*this);
+
+ return bdy;
+}
+
+
+void body::copyFrom(const component& other) {
+
+ const body& bdy = dynamic_cast <const body&>(other);
+
+ m_prologText = bdy.m_prologText;
+ m_epilogText = bdy.m_epilogText;
+
+ m_contents = bdy.m_contents;
+
+ removeAllParts();
+
+ for (size_t p = 0 ; p < bdy.getPartCount() ; ++p) {
+
+ shared_ptr <bodyPart> part = m_part->createChildPart();
+
+ part->copyFrom(*bdy.getPartAt(p));
+
+ m_parts.push_back(part);
+ }
+}
+
+
+body& body::operator=(const body& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+const string& body::getPrologText() const {
+
+ return m_prologText;
+}
+
+
+void body::setPrologText(const string& prologText) {
+
+ m_prologText = prologText;
+}
+
+
+const string& body::getEpilogText() const {
+
+ return m_epilogText;
+}
+
+
+void body::setEpilogText(const string& epilogText) {
+
+ m_epilogText = epilogText;
+}
+
+
+const shared_ptr <const contentHandler> body::getContents() const {
+
+ return m_contents;
+}
+
+
+void body::setContents(const shared_ptr <const contentHandler>& contents) {
+
+ m_contents = contents;
+}
+
+
+void body::setContents(
+ const shared_ptr <const contentHandler>& contents,
+ const mediaType& type
+) {
+
+ m_contents = contents;
+
+ setContentType(type);
+}
+
+
+void body::setContents(
+ const shared_ptr <const contentHandler>& contents,
+ const mediaType& type,
+ const charset& chset
+) {
+
+ m_contents = contents;
+
+ setContentType(type, chset);
+}
+
+
+void body::setContents(
+ const shared_ptr <const contentHandler>& contents,
+ const mediaType& type,
+ const charset& chset,
+ const encoding& enc
+) {
+
+ m_contents = contents;
+
+ setContentType(type, chset);
+ setEncoding(enc);
+}
+
+
+void body::initNewPart(const shared_ptr <bodyPart>& part) {
+
+ // A part can be in only one body at the same time: if part is
+ // already attached to a parent part, remove it from the current
+ // parent part
+ if (part->getParentPart()) {
+ part->getParentPart()->getBody()->removePart(part);
+ }
+
+ if (m_part) {
+
+ m_part->importChildPart(part);
+
+ shared_ptr <header> hdr = m_part->getHeader();
+
+ // Check whether we have a boundary string
+ shared_ptr <contentTypeField> ctf =
+ hdr->findField <contentTypeField>(fields::CONTENT_TYPE);
+
+ if (ctf) {
+
+ if (ctf->hasBoundary()) {
+
+ const string boundary = ctf->getBoundary();
+
+ if (boundary.empty() || !isValidBoundary(boundary)) {
+ ctf->setBoundary(generateRandomBoundaryString());
+ }
+
+ } else {
+
+ // No "boundary" parameter: generate a random one.
+ ctf->setBoundary(generateRandomBoundaryString());
+ }
+
+ if (ctf->getValue <mediaType>()->getType() != mediaTypes::MULTIPART) {
+
+ // Warning: multi-part body but the Content-Type is
+ // not specified as "multipart/..."
+ }
+
+ } else {
+
+ // No "Content-Type" field: create a new one and generate
+ // a random boundary string.
+ ctf = hdr->getField <contentTypeField>(fields::CONTENT_TYPE);
+
+ ctf->setValue(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED));
+ ctf->setBoundary(generateRandomBoundaryString());
+ }
+ }
+}
+
+
+void body::appendPart(const shared_ptr <bodyPart>& part) {
+
+ initNewPart(part);
+
+ m_parts.push_back(part);
+}
+
+
+void body::insertPartBefore(
+ const shared_ptr <bodyPart>& beforePart,
+ const shared_ptr <bodyPart>& part
+) {
+
+ initNewPart(part);
+
+ const std::vector <shared_ptr <bodyPart> >::iterator it = std::find(
+ m_parts.begin(), m_parts.end(), beforePart
+ );
+
+ if (it == m_parts.end()) {
+ throw exceptions::no_such_part();
+ }
+
+ m_parts.insert(it, part);
+}
+
+
+void body::insertPartBefore(
+ const size_t pos,
+ const shared_ptr <bodyPart>& part
+) {
+
+ initNewPart(part);
+
+ m_parts.insert(m_parts.begin() + pos, part);
+}
+
+
+void body::insertPartAfter(
+ const shared_ptr <bodyPart>& afterPart,
+ const shared_ptr <bodyPart>& part
+) {
+
+ initNewPart(part);
+
+ const std::vector <shared_ptr <bodyPart> >::iterator it = std::find(
+ m_parts.begin(), m_parts.end(), afterPart
+ );
+
+ if (it == m_parts.end()) {
+ throw exceptions::no_such_part();
+ }
+
+ m_parts.insert(it + 1, part);
+}
+
+
+void body::insertPartAfter(const size_t pos, const shared_ptr <bodyPart>& part) {
+
+ initNewPart(part);
+
+ m_parts.insert(m_parts.begin() + pos + 1, part);
+}
+
+
+void body::removePart(const shared_ptr <bodyPart>& part) {
+
+ const std::vector <shared_ptr <bodyPart> >::iterator it = std::find(
+ m_parts.begin(), m_parts.end(), part
+ );
+
+ if (it == m_parts.end()) {
+ throw exceptions::no_such_part();
+ }
+
+ m_parts.erase(it);
+}
+
+
+void body::removePart(const size_t pos) {
+
+ m_parts.erase(m_parts.begin() + pos);
+}
+
+
+void body::removeAllParts() {
+
+ m_parts.clear();
+}
+
+
+size_t body::getPartCount() const {
+
+ return m_parts.size();
+}
+
+
+bool body::isEmpty() const {
+
+ return m_parts.size() == 0;
+}
+
+
+shared_ptr <bodyPart> body::getPartAt(const size_t pos) {
+
+ return m_parts[pos];
+}
+
+
+const shared_ptr <const bodyPart> body::getPartAt(const size_t pos) const {
+
+ return m_parts[pos];
+}
+
+
+const std::vector <shared_ptr <const bodyPart> > body::getPartList() const {
+
+ std::vector <shared_ptr <const bodyPart> > list;
+
+ list.reserve(m_parts.size());
+
+ for (std::vector <shared_ptr <bodyPart> >::const_iterator it = m_parts.begin() ;
+ it != m_parts.end() ; ++it) {
+
+ list.push_back(*it);
+ }
+
+ return list;
+}
+
+
+const std::vector <shared_ptr <bodyPart> > body::getPartList() {
+
+ return m_parts;
+}
+
+
+const std::vector <shared_ptr <component> > body::getChildComponents() {
+
+ std::vector <shared_ptr <component> > list;
+
+ copy_vector(m_parts, list);
+
+ return list;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/body.hpp b/vmime-master/src/vmime/body.hpp
new file mode 100644
index 0000000..7ece000
--- /dev/null
+++ b/vmime-master/src/vmime/body.hpp
@@ -0,0 +1,365 @@
+//
+// 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_BODY_HPP_INCLUDED
+#define VMIME_BODY_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/component.hpp"
+
+#include "vmime/header.hpp"
+
+#include "vmime/mediaType.hpp"
+#include "vmime/charset.hpp"
+#include "vmime/encoding.hpp"
+
+#include "vmime/contentHandler.hpp"
+
+
+namespace vmime {
+
+
+class bodyPart;
+
+
+/** Body section of a MIME part.
+ */
+class VMIME_EXPORT body : public component {
+
+ friend class bodyPart;
+
+public:
+
+ body();
+ ~body();
+
+ /** Add a part at the end of the list.
+ *
+ * @param part part to append
+ */
+ void appendPart(const shared_ptr <bodyPart>& part);
+
+ /** Insert a new part before the specified part.
+ *
+ * @param beforePart part before which the new part will be inserted
+ * @param part part to insert
+ * @throw exceptions::no_such_part if the part is not in the list
+ */
+ void insertPartBefore(
+ const shared_ptr <bodyPart>& beforePart,
+ const shared_ptr <bodyPart>& part
+ );
+
+ /** Insert a new part before the specified position.
+ *
+ * @param pos position at which to insert the new part (0 to insert at
+ * the beginning of the list)
+ * @param part part to insert
+ */
+ void insertPartBefore(const size_t pos, const shared_ptr <bodyPart>& part);
+
+ /** Insert a new part after the specified part.
+ *
+ * @param afterPart part after which the new part will be inserted
+ * @param part part to insert
+ * @throw exceptions::no_such_part if the part is not in the list
+ */
+ 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, 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(const shared_ptr <bodyPart>& part);
+
+ /** Remove the part at the specified position.
+ *
+ * @param pos position of the part to remove
+ */
+ void removePart(const size_t pos);
+
+ /** Remove all parts from the list.
+ */
+ void removeAllParts();
+
+ /** Return the number of parts in the list.
+ *
+ * @return number of parts
+ */
+ size_t getPartCount() const;
+
+ /** Tests whether the list of parts is empty.
+ *
+ * @return true if there is no part, false otherwise
+ */
+ bool isEmpty() const;
+
+ /** Return the part at the specified position.
+ *
+ * @param pos position
+ * @return part at position 'pos'
+ */
+ shared_ptr <bodyPart> getPartAt(const size_t pos);
+
+ /** Return the part at the specified position.
+ *
+ * @param pos position
+ * @return part at position 'pos'
+ */
+ const shared_ptr <const bodyPart> getPartAt(const size_t pos) const;
+
+ /** Return the part list.
+ *
+ * @return list of parts
+ */
+ const std::vector <shared_ptr <const bodyPart> > getPartList() const;
+
+ /** Return the part list.
+ *
+ * @return list of parts
+ */
+ const std::vector <shared_ptr <bodyPart> > getPartList();
+
+ /** Return the prolog text.
+ *
+ * @return prolog text
+ */
+ const string& getPrologText() const;
+
+ /** Set the prolog text.
+ *
+ * @param prologText new prolog text
+ */
+ void setPrologText(const string& prologText);
+
+ /** Return the epilog text.
+ *
+ * @return epilog text
+ */
+ const string& getEpilogText() const;
+
+ /** Set the epilog text.
+ *
+ * @param epilogText new epilog text
+ */
+ void setEpilogText(const string& epilogText);
+
+ /** Return a read-only reference to body contents.
+ *
+ * @return read-only body contents
+ */
+ const shared_ptr <const contentHandler> getContents() const;
+
+ /** Set the body contents.
+ *
+ * @param contents new body 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(
+ const shared_ptr <const contentHandler>& contents,
+ const mediaType& type
+ );
+
+ /** Set the body contents, type and charset.
+ *
+ * @param contents new body contents
+ * @param type type of contents
+ * @param chset charset of contents
+ */
+ void setContents(
+ const shared_ptr <const contentHandler>& contents,
+ const mediaType& type,
+ const charset& chset
+ );
+
+ /** Set the body contents, type, charset and encoding.
+ *
+ * @param contents new body contents
+ * @param type type of contents
+ * @param chset charset of contents
+ * @param enc contents encoding
+ */
+ 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.
+ *
+ * @param type MIME media type of contents
+ * @param chset charset of contents
+ */
+ void setContentType(const mediaType& type, const charset& chset);
+
+ /** Set the MIME type of contents.
+ *
+ * @param type MIME media type of contents
+ */
+ void setContentType(const mediaType& type);
+
+ /** Return the media type of the data contained in the body contents.
+ * This is a shortcut for getHeader()->ContentType()->getValue()
+ * on the parent part.
+ *
+ * @return media type of body contents
+ */
+ const mediaType getContentType() const;
+
+ /** Set the charset of contents.
+ * If the type is not set, it will be set to default "text/plain" type.
+ *
+ * @param chset charset of contents
+ */
+ void setCharset(const charset& chset);
+
+ /** Return the charset of the data contained in the body contents.
+ * This is a shortcut for getHeader()->ContentType()->getCharset()
+ * on the parent part.
+ *
+ * @return charset of body contents
+ */
+ const charset getCharset() const;
+
+ /** Set the output encoding of contents.
+ * Contents will be encoded (or re-encoded) when this node is being generated.
+ *
+ * @param enc encoding of contents
+ */
+ void setEncoding(const encoding& enc);
+
+ /** Return the encoding used to encode the body contents.
+ * This is a shortcut for getHeader()->ContentTransferEncoding()->getValue()
+ * on the parent part.
+ *
+ * @return encoding of body contents
+ */
+ const encoding getEncoding() const;
+
+ /** Generate a new random boundary string.
+ *
+ * @return randomly generated boundary string
+ */
+ static const string generateRandomBoundaryString();
+
+ /** Test a boundary string for validity (as defined in RFC #1521, page 19).
+ *
+ * @param boundary boundary string to test
+ * @return true if the boundary string is valid, false otherwise
+ */
+ static bool isValidBoundary(const string& boundary);
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ body& operator=(const body& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+ size_t getGeneratedSize(const generationContext& ctx);
+
+private:
+
+ text getActualPrologText(const generationContext& ctx) const;
+ text getActualEpilogText(const generationContext& ctx) const;
+
+ void setParentPart(bodyPart* parent);
+
+
+ string m_prologText;
+ string m_epilogText;
+
+ shared_ptr <const contentHandler> m_contents;
+
+ bodyPart* m_part;
+
+ std::vector <shared_ptr <bodyPart> > m_parts;
+
+ bool isRootPart() const;
+
+ void initNewPart(const shared_ptr <bodyPart>& part);
+
+protected:
+
+ /** Finds the next boundary position in the parsing buffer.
+ *
+ * @param parser parser object
+ * @param boundary boundary string (without "--" nor CR/LF)
+ * @param position start position
+ * @param end end position
+ * @param boundaryStart will hold the start position of the boundary (including any
+ * CR/LF and "--" before the boundary)
+ * @param boundaryEnd will hold the end position of the boundary (position just
+ * before the CRLF or "--" which follows)
+ * @return the position of the boundary string, or npos if not found
+ */
+ 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,
+ 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;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_BODY_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/bodyPart.cpp b/vmime-master/src/vmime/bodyPart.cpp
new file mode 100644
index 0000000..ff81994
--- /dev/null
+++ b/vmime-master/src/vmime/bodyPart.cpp
@@ -0,0 +1,198 @@
+//
+// 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.
+//
+
+#include "vmime/bodyPart.hpp"
+
+
+namespace vmime {
+
+
+bodyPart::bodyPart()
+ : m_header(make_shared <header>()),
+ m_body(make_shared <body>()),
+ m_parent() {
+
+ m_body->setParentPart(this);
+}
+
+
+void bodyPart::parseImpl(
+ const parsingContext& ctx,
+ const shared_ptr <utility::parserInputStreamAdapter>& parser,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ // Parse the headers
+ size_t pos = position;
+ m_header->parse(ctx, parser, pos, end, &pos);
+
+ // Parse the body contents
+ m_body->parse(ctx, parser, pos, end, NULL);
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+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) {
+ *newLinePos = 0;
+ }
+}
+
+
+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 <bodyPart> p = make_shared <bodyPart>();
+
+ p->m_parent = NULL;
+
+ p->m_header->copyFrom(*m_header);
+ p->m_body->copyFrom(*m_body);
+
+ return p;
+}
+
+
+void bodyPart::copyFrom(const component& other) {
+
+ const bodyPart& bp = dynamic_cast <const bodyPart&>(other);
+
+ m_header->copyFrom(*(bp.m_header));
+ m_body->copyFrom(*(bp.m_body));
+}
+
+
+bodyPart& bodyPart::operator=(const bodyPart& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+const shared_ptr <const header> bodyPart::getHeader() const {
+
+ return m_header;
+}
+
+
+shared_ptr <header> bodyPart::getHeader() {
+
+ return m_header;
+}
+
+
+void bodyPart::setHeader(const shared_ptr <header>& h) {
+
+ m_header = h;
+}
+
+
+const shared_ptr <const body> bodyPart::getBody() const {
+
+ return m_body;
+}
+
+
+shared_ptr <body> bodyPart::getBody() {
+
+ return m_body;
+}
+
+
+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) {
+ oldPart->setBody(make_shared <body>());
+ }
+}
+
+
+bodyPart* bodyPart::getParentPart() {
+
+ return m_parent;
+}
+
+
+const bodyPart* bodyPart::getParentPart() const {
+
+ return m_parent;
+}
+
+
+shared_ptr <bodyPart> bodyPart::createChildPart() {
+
+ shared_ptr <bodyPart> part = make_shared <bodyPart>();
+ part->m_parent = this;
+
+ return part;
+}
+
+
+void bodyPart::importChildPart(const shared_ptr <bodyPart>& part) {
+
+ part->m_parent = this;
+}
+
+
+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;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/bodyPart.hpp b/vmime-master/src/vmime/bodyPart.hpp
new file mode 100644
index 0000000..f63b367
--- /dev/null
+++ b/vmime-master/src/vmime/bodyPart.hpp
@@ -0,0 +1,155 @@
+//
+// 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_BODYPART_HPP_INCLUDED
+#define VMIME_BODYPART_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/component.hpp"
+
+#include "vmime/header.hpp"
+#include "vmime/body.hpp"
+
+
+namespace vmime {
+
+
+/** A MIME part.
+ */
+class VMIME_EXPORT bodyPart : public component {
+
+ friend class body;
+
+public:
+
+ bodyPart();
+
+ /** Return the header section of this part.
+ *
+ * @return header section
+ */
+ const shared_ptr <const header> getHeader() const;
+
+ /** Return the header section of this part.
+ *
+ * @return header section
+ */
+ shared_ptr <header> getHeader();
+
+ /** Replaces the header section of this part.
+ *
+ * @param header the new header of this part
+ */
+ void setHeader(const shared_ptr <header>& header);
+
+ /** Return the body section of this part.
+ *
+ * @return body section
+ */
+ const shared_ptr <const body> getBody() const;
+
+ /** Return the body section of this part.
+ *
+ * @return body section
+ */
+ shared_ptr <body> getBody();
+
+ /** Replaces the body section of this part.
+ *
+ * @param body new body section
+ */
+ void setBody(const shared_ptr <body>& body);
+
+ /** Return the parent part of this part.
+ *
+ * @return parent part or NULL if not known
+ */
+ bodyPart* getParentPart();
+
+ /** Return the parent part of this part (const version).
+ *
+ * @return parent part or NULL if not known
+ */
+ const bodyPart* getParentPart() const;
+
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ bodyPart& operator=(const bodyPart& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+ size_t getGeneratedSize(const generationContext& ctx);
+
+private:
+
+ shared_ptr <header> m_header;
+ mutable shared_ptr <body> m_body;
+
+ // We can't use a weak_ptr<> here as the parent part may
+ // have been allocated on the stack
+ bodyPart* m_parent;
+
+protected:
+
+ /** Creates and returns a new part and set this part as its
+ * parent. The newly created sub-part should then be added
+ * to this part by calling getBody()->appendPart(). Called
+ * by the body class.
+ *
+ * @return child part
+ */
+ shared_ptr <bodyPart> createChildPart();
+
+ /** Detach the specified part from its current parent part (if
+ * any) and attach it to this part by setting this part as its
+ * new parent. The sub-part should then be added to this part
+ * by calling getBody()->appendPart(). Called by body class.
+ *
+ * @param part child part to attach
+ */
+ void importChildPart(const shared_ptr <bodyPart>& part);
+
+ // Component parsing & assembling
+ void parseImpl(
+ const parsingContext& ctx,
+ const shared_ptr <utility::parserInputStreamAdapter>& parser,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition = NULL
+ );
+
+ void generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_BODYPART_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/bodyPartAttachment.cpp b/vmime-master/src/vmime/bodyPartAttachment.cpp
new file mode 100644
index 0000000..01b306e
--- /dev/null
+++ b/vmime-master/src/vmime/bodyPartAttachment.cpp
@@ -0,0 +1,147 @@
+//
+// 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.
+//
+
+#include "vmime/bodyPartAttachment.hpp"
+
+
+namespace vmime {
+
+
+bodyPartAttachment::bodyPartAttachment(const shared_ptr <const bodyPart>& part)
+ : m_part(part) {
+
+}
+
+
+const mediaType bodyPartAttachment::getType() const {
+
+ shared_ptr <const contentTypeField> ctf = getContentType();
+
+ if (ctf) {
+
+ return *ctf->getValue <mediaType>();
+
+ } else {
+
+ // No "Content-type" field: assume "application/octet-stream".
+ return mediaType(
+ mediaTypes::APPLICATION,
+ mediaTypes::APPLICATION_OCTET_STREAM
+ );
+ }
+}
+
+
+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()) {
+
+ name = cdf->getFilename();
+
+ // Try the 'name' parameter of 'Content-Type' field
+ } else {
+
+ shared_ptr <const contentTypeField> ctf = getContentType();
+
+ if (ctf) {
+
+ shared_ptr <const parameter> prm = ctf->findParameter("name");
+
+ if (prm) {
+ name = prm->getValue();
+ }
+ }
+ }
+
+ return name;
+}
+
+
+const text bodyPartAttachment::getDescription() const {
+
+ text description;
+
+ shared_ptr <const headerField> cd =
+ getHeader()->findField(fields::CONTENT_DESCRIPTION);
+
+ if (cd) {
+
+ description = *cd->getValue <text>();
+
+ } else {
+
+ // No description available.
+ }
+
+ return description;
+}
+
+
+const encoding bodyPartAttachment::getEncoding() const {
+
+ return m_part->getBody()->getEncoding();
+}
+
+
+const shared_ptr <const contentHandler> bodyPartAttachment::getData() const {
+
+ return m_part->getBody()->getContents();
+}
+
+
+shared_ptr <const object> bodyPartAttachment::getPart() const {
+
+ return m_part;
+}
+
+
+shared_ptr <const header> bodyPartAttachment::getHeader() const {
+
+ return m_part->getHeader();
+}
+
+
+shared_ptr <const contentDispositionField> bodyPartAttachment::getContentDisposition() const {
+
+ return getHeader()->findField <contentDispositionField>(fields::CONTENT_DISPOSITION);
+}
+
+
+shared_ptr <const contentTypeField> bodyPartAttachment::getContentType() const {
+
+ return getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
+}
+
+
+void bodyPartAttachment::generateIn(const shared_ptr <bodyPart>& /* parent */) const {
+
+ // Not used
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/bodyPartAttachment.hpp b/vmime-master/src/vmime/bodyPartAttachment.hpp
new file mode 100644
index 0000000..974e2f8
--- /dev/null
+++ b/vmime-master/src/vmime/bodyPartAttachment.hpp
@@ -0,0 +1,76 @@
+//
+// 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_BODYPARTATTACHMENT_HPP_INCLUDED
+#define VMIME_BODYPARTATTACHMENT_HPP_INCLUDED
+
+
+#ifndef VMIME_BUILDING_DOC // implementation detail
+
+
+#include "vmime/attachment.hpp"
+
+#include "vmime/contentDispositionField.hpp"
+#include "vmime/contentTypeField.hpp"
+
+
+namespace vmime {
+
+
+/** An attachment related to a local body part.
+ */
+class VMIME_EXPORT bodyPartAttachment : public attachment {
+
+public:
+
+ bodyPartAttachment(const shared_ptr <const bodyPart>& part);
+
+ const mediaType getType() const;
+ const word getName() const;
+ const text getDescription() const;
+ const encoding getEncoding() const;
+
+ const shared_ptr <const contentHandler> getData() const;
+
+ shared_ptr <const object> getPart() const;
+ shared_ptr <const header> getHeader() const;
+
+private:
+
+ void generateIn(const shared_ptr <bodyPart>& parent) const;
+
+ shared_ptr <const contentDispositionField> getContentDisposition() const;
+ shared_ptr <const contentTypeField> getContentType() const;
+
+
+ shared_ptr <const bodyPart> m_part;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_BUILDING_DOC
+
+
+#endif // VMIME_BODYPARTATTACHMENT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/charset.cpp b/vmime-master/src/vmime/charset.cpp
new file mode 100644
index 0000000..8828c56
--- /dev/null
+++ b/vmime-master/src/vmime/charset.cpp
@@ -0,0 +1,268 @@
+//
+// 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.
+//
+
+#include "vmime/charset.hpp"
+#include "vmime/exception.hpp"
+#include "vmime/platform.hpp"
+#include "vmime/encoding.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include "vmime/charsetConverter.hpp"
+
+
+
+namespace vmime {
+
+
+charset::charset()
+ : m_name(charsets::US_ASCII) {
+
+}
+
+
+charset::charset(const string& 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")) {
+ m_name = "utf-7";
+ }
+}
+
+
+charset::charset(const char* 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)
+ );
+
+ // 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")) {
+ m_name = "utf-7";
+ }
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void charset::generateImpl(
+ const generationContext& /* ctx */,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ os << m_name;
+
+ if (newLinePos) {
+ *newLinePos = curLinePos + m_name.length();
+ }
+}
+
+
+void charset::convert(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ const charset& source,
+ const charset& dest,
+ const charsetConverterOptions& opts
+) {
+
+ 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) {
+ out = in;
+ return;
+ }
+
+ shared_ptr <charsetConverter> conv = charsetConverter::create(source, dest, opts);
+ conv->convert(in, out);
+}
+
+
+bool charset::isValidText(const string& text, string::size_type* firstInvalidByte) const {
+
+ charsetConverterOptions opts;
+ opts.silentlyReplaceInvalidSequences = false;
+
+ charsetConverter::status st;
+
+ 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) {
+
+ // An illegal byte sequence was found in the input buffer
+ if (firstInvalidByte) {
+
+ if (st.inputBytesRead < text.length())
+ *firstInvalidByte = st.inputBytesRead;
+ else
+ *firstInvalidByte = text.length();
+ }
+
+ return false;
+ }
+
+ if (firstInvalidByte) {
+ *firstInvalidByte = text.length();
+ }
+
+ return true;
+}
+
+
+const charset charset::getLocalCharset() {
+
+ return platform::getHandler()->getLocalCharset();
+}
+
+
+charset& charset::operator=(const charset& other) {
+
+ copyFrom(other);
+ 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 !(*this == value);
+}
+
+
+shared_ptr <component> charset::clone() const {
+
+ return make_shared <charset>(m_name);
+}
+
+
+const string& charset::getName() const {
+
+ return m_name;
+}
+
+
+void charset::copyFrom(const component& other) {
+
+ m_name = dynamic_cast <const charset&>(other).m_name;
+}
+
+
+const std::vector <shared_ptr <component> > charset::getChildComponents() {
+
+ return std::vector <shared_ptr <component> >();
+}
+
+
+
+// Explicitly force encoding for some charsets
+struct CharsetEncodingEntry {
+
+ CharsetEncodingEntry(const string& charset_, const string& encoding_)
+ : charset(charset_), encoding(encoding_) {
+
+ }
+
+ const string charset;
+ const string encoding;
+};
+
+
+CharsetEncodingEntry g_charsetEncodingMap[] = {
+
+ // Use QP encoding for ISO-8859-x charsets
+ CharsetEncodingEntry("iso-8859", encodingTypes::QUOTED_PRINTABLE),
+ CharsetEncodingEntry("iso8859", encodingTypes::QUOTED_PRINTABLE),
+
+ // RFC-1468 states:
+ // " ISO-2022-JP may also be used in MIME Part 2 headers. The "B"
+ // encoding should be used with ISO-2022-JP text. "
+ // Use Base64 encoding for all ISO-2022 charsets.
+ CharsetEncodingEntry("iso-2022", encodingTypes::BASE64),
+ CharsetEncodingEntry("iso2022", encodingTypes::BASE64),
+
+ // Last entry is not used
+ CharsetEncodingEntry("", "")
+};
+
+
+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) {
+ enc = g_charsetEncodingMap[i].encoding;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/charset.hpp b/vmime-master/src/vmime/charset.hpp
new file mode 100644
index 0000000..61f9bd6
--- /dev/null
+++ b/vmime-master/src/vmime/charset.hpp
@@ -0,0 +1,176 @@
+//
+// 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_CHARSET_HPP_INCLUDED
+#define VMIME_CHARSET_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/utility/inputStream.hpp"
+#include "vmime/utility/outputStream.hpp"
+#include "vmime/charsetConverterOptions.hpp"
+#include "vmime/component.hpp"
+
+
+namespace vmime {
+
+
+class encoding; // forward reference
+
+
+/** Charset description (basic type).
+ */
+class VMIME_EXPORT charset : public component {
+
+public:
+
+ charset();
+ charset(const string& name);
+ charset(const char* name); // to allow creation from vmime::charsets constants
+
+public:
+
+ /** Return the ISO name of the charset.
+ *
+ * @return charset name
+ */
+ const string& getName() const;
+
+ charset& operator=(const charset& other);
+
+ bool operator==(const charset& value) const;
+ bool operator!=(const charset& value) const;
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+ /** Gets the recommended encoding for this charset.
+ * Note: there may be no recommended encoding.
+ *
+ * @param enc output parameter that will hold recommended encoding
+ * @return true if an encoding is recommended (the encoding is stored
+ * in the enc parameter), false otherwise (in this case, the enc
+ * parameter is not modified)
+ */
+ bool getRecommendedEncoding(encoding& enc) const;
+
+ /** Returns the default charset used on the system.
+ *
+ * This function simply calls <code>platformHandler::getLocalCharset()</code>
+ * and is provided for convenience.
+ *
+ * @return system default charset
+ */
+ static const charset getLocalCharset();
+
+ /** Convert a string buffer from one charset to another
+ * charset (in-memory conversion)
+ *
+ * \deprecated Use the new convert() method, which takes
+ * an outputStream parameter.
+ *
+ * @param in input buffer
+ * @param out output buffer
+ * @param source input charset
+ * @param dest output charset
+ * @param opts conversion options
+ * @throws 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
+ * @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()
+ );
+
+ /** Convert the contents of an input stream in a specified charset
+ * to another charset and write the result to an output stream.
+ *
+ * @param in input stream to read data from
+ * @param out output stream to write the converted data
+ * @param source input charset
+ * @param dest output charset
+ * @param opts conversion options
+ * @throws 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
+ * @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()
+ );
+
+ /** Checks whether the specified text is valid in this charset.
+ *
+ * @param text input text
+ * @param firstInvalidByte if the function returns false, will contain
+ * the index of the first invalid byte in the string. Can be NULL if
+ * not used.
+ * @return true if the text is perfectly valid in this charset,
+ * or false otherwise (eg. it contains illegal sequences)
+ */
+ bool isValidText(const string& text, string::size_type* firstInvalidByte) const;
+
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+
+private:
+
+ string m_name;
+
+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 generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_CHARSET_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/charsetConverter.cpp b/vmime-master/src/vmime/charsetConverter.cpp
new file mode 100644
index 0000000..96bc3b8
--- /dev/null
+++ b/vmime-master/src/vmime/charsetConverter.cpp
@@ -0,0 +1,53 @@
+//
+// 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.
+//
+
+#include "vmime/charsetConverter.hpp"
+
+#include "vmime/charsetConverter_idna.hpp"
+
+
+namespace vmime {
+
+
+// static
+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 {
+ return createGenericConverter(source, dest, opts);
+ }
+}
+
+
+charsetConverter::status::status()
+ : inputBytesRead(0), outputBytesWritten(0) {
+
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/charsetConverter.hpp b/vmime-master/src/vmime/charsetConverter.hpp
new file mode 100644
index 0000000..2cde4b5
--- /dev/null
+++ b/vmime-master/src/vmime/charsetConverter.hpp
@@ -0,0 +1,162 @@
+//
+// 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_HPP_INCLUDED
+#define VMIME_CHARSETCONVERTER_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/component.hpp"
+
+#include "vmime/charset.hpp"
+#include "vmime/charsetConverterOptions.hpp"
+#include "vmime/utility/filteredStream.hpp"
+
+
+namespace vmime {
+
+
+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
+ * 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 {
+
+};
+
+
+} // utility
+
+
+/** Convert between charsets.
+ */
+class VMIME_EXPORT charsetConverter : public object {
+
+public:
+
+ /** Holds information about a conversion.
+ */
+ struct status {
+
+ status();
+
+
+ /** Number of bytes read from input buffer and successfully converted.
+ */
+ size_t inputBytesRead;
+
+ /** Number of bytes written to output buffer.
+ */
+ size_t outputBytesWritten;
+ };
+
+
+ /** Construct and initialize an iconv charset converter.
+ *
+ * @param source input charset
+ * @param dest output charset
+ * @param opts conversion options
+ */
+ 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)
+ *
+ * \deprecated Use the new convert() method, which takes
+ * an outputStream parameter.
+ *
+ * @param in input buffer
+ * @param out output buffer
+ * @param st will receive some extra infos when conversion is finished
+ * or stopped by an error (can be NULL)
+ * @throws 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
+ * @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;
+
+ /** Convert the contents of an input stream in a specified charset
+ * to another charset and write the result to an output stream.
+ *
+ * @param in input stream to read data from
+ * @param out output stream to write the converted data
+ * @param st will receive some extra infos when conversion is finished
+ * or stopped by an error (can be NULL)
+ * @throws 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
+ * @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;
+
+ /** Returns a filtered output stream which applies a charset
+ * conversion to input bytes. Please note that it may not be
+ * supported by the converter.
+ *
+ * @param os stream into which filtered data will be written
+ * @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;
+
+private:
+
+ static shared_ptr <charsetConverter> createGenericConverter(
+ const charset& source,
+ const charset& dest,
+ const charsetConverterOptions& opts
+ );
+};
+
+
+} // vmime
+
+
+#endif // VMIME_CHARSETCONVERTER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/charsetConverterOptions.cpp b/vmime-master/src/vmime/charsetConverterOptions.cpp
new file mode 100644
index 0000000..a18a928
--- /dev/null
+++ b/vmime-master/src/vmime/charsetConverterOptions.cpp
@@ -0,0 +1,37 @@
+//
+// 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.
+//
+
+#include "vmime/charsetConverterOptions.hpp"
+
+
+namespace vmime {
+
+
+charsetConverterOptions::charsetConverterOptions()
+ : silentlyReplaceInvalidSequences(true),
+ invalidSequence("?") {
+
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/charsetConverterOptions.hpp b/vmime-master/src/vmime/charsetConverterOptions.hpp
new file mode 100644
index 0000000..567e004
--- /dev/null
+++ b/vmime-master/src/vmime/charsetConverterOptions.hpp
@@ -0,0 +1,59 @@
+//
+// 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_CHARSETCONVERTEROPTIONS_HPP_INCLUDED
+#define VMIME_CHARSETCONVERTEROPTIONS_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+
+
+namespace vmime {
+
+
+/** Options for charset conversion.
+ */
+class VMIME_EXPORT charsetConverterOptions : public object {
+
+public:
+
+ charsetConverterOptions();
+
+
+ /** If true, invalid sequences will be silently replaced with
+ * a string when possible (see 'invalidSequence').
+ * Default is true.
+ */
+ bool silentlyReplaceInvalidSequences;
+
+ /** Replace invalid sequences with this string.
+ * Default is '?'.
+ */
+ string invalidSequence;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_CHARSETCONVERTEROPTIONS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/charsetConverter_iconv.cpp b/vmime-master/src/vmime/charsetConverter_iconv.cpp
new file mode 100644
index 0000000..5c4cc17
--- /dev/null
+++ b/vmime-master/src/vmime/charsetConverter_iconv.cpp
@@ -0,0 +1,537 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_CHARSETCONV_LIB_IS_ICONV
+
+
+#include "vmime/charsetConverter_iconv.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+#include "vmime/utility/outputStreamStringAdapter.hpp"
+
+
+extern "C" {
+
+#ifndef VMIME_BUILDING_DOC
+
+ #include <iconv.h>
+ #include <errno.h>
+
+ // HACK: prototypes may differ depending on the compiler and/or system (the
+ // second parameter may or may not be 'const'). This relies on the compiler
+ // for choosing the right type.
+
+ class ICONV_IN_TYPE {
+
+ public:
+
+ ICONV_IN_TYPE(const char** ptr) : m_ptr(ptr) { }
+
+ ICONV_IN_TYPE(const vmime::byte_t** ptr)
+ : m_ptr(reinterpret_cast <const char**>(ptr)) { }
+
+ operator const char**() { return m_ptr; }
+ operator char**() { return const_cast <char**>(m_ptr); }
+
+ private:
+
+ const char** m_ptr;
+ };
+
+ class ICONV_OUT_TYPE {
+
+ public:
+
+ ICONV_OUT_TYPE(char** ptr) : m_ptr(ptr) { }
+
+ ICONV_OUT_TYPE(vmime::byte_t** ptr)
+ : m_ptr(reinterpret_cast <char**>(ptr)) { }
+
+ operator char**() { return m_ptr; }
+
+ private:
+
+ char** m_ptr;
+ };
+
+#endif // VMIME_BUILDING_DOC
+}
+
+
+
+// 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()
+) {
+
+ const char* invalidCharIn = opts.invalidSequence.c_str();
+ vmime::size_t invalidCharInLen = opts.invalidSequence.length();
+
+ vmime::byte_t invalidCharOutBuffer[16];
+ vmime::byte_t* invalidCharOutPtr = invalidCharOutBuffer;
+ vmime::size_t invalidCharOutLen = 16;
+
+ if (iconv(cd, ICONV_IN_TYPE(&invalidCharIn), &invalidCharInLen,
+ ICONV_OUT_TYPE(&invalidCharOutPtr), &invalidCharOutLen) != static_cast <size_t>(-1)) {
+
+ out.write(invalidCharOutBuffer, 16 - invalidCharOutLen);
+ }
+}
+
+
+
+namespace vmime {
+
+
+// static
+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) {
+
+ // 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)) {
+
+ iconv_t* p = new iconv_t;
+ *p= cd;
+
+ m_desc = p;
+ }
+}
+
+
+charsetConverter_iconv::~charsetConverter_iconv() {
+
+ if (m_desc) {
+
+ // Close iconv handle
+ iconv_close(*static_cast <iconv_t*>(m_desc));
+
+ delete static_cast <iconv_t*>(m_desc);
+ m_desc = NULL;
+ }
+}
+
+
+void charsetConverter_iconv::convert(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ status* st
+) {
+
+ 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);
+
+ byte_t inBuffer[32768];
+ byte_t outBuffer[32768];
+ size_t inPos = 0;
+
+ bool prevIsInvalid = false;
+ bool breakAfterNext = false;
+
+ 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);
+
+ const byte_t* inPtr = breakAfterNext ? NULL : inBuffer;
+ size_t *ptrLength = breakAfterNext ? NULL : &inLength;
+ byte_t* outPtr = outBuffer;
+
+ // Convert input bytes
+ if (iconv(cd, ICONV_IN_TYPE(&inPtr), ptrLength,
+ 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) {
+
+ // Write successfully converted bytes
+ out.write(outBuffer, sizeof(outBuffer) - outLength);
+
+ 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
+ outputInvalidChar(out, cd, m_options);
+
+ // 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 {
+
+ // Write successfully converted bytes
+ out.write(outBuffer, sizeof(outBuffer) - outLength);
+
+ // Leave unconverted bytes in the input buffer
+ std::copy(const_cast <byte_t*>(inPtr), inBuffer + sizeof(inBuffer), inBuffer);
+ inPos = inLength;
+
+ if (errno != E2BIG) {
+ prevIsInvalid = true;
+ }
+ }
+
+ } else {
+
+ // Write successfully converted bytes
+ out.write(outBuffer, sizeof(outBuffer) - outLength);
+
+ if (st && inPtr) {
+ st->inputBytesRead += (inPtr - inBuffer);
+ st->outputBytesWritten += (outPtr - outBuffer);
+ }
+
+ inPos = 0;
+ prevIsInvalid = false;
+ }
+
+ if (breakAfterNext) {
+ break;
+ }
+
+ // Check for end of data, loop again to flush stateful data from iconv
+ if (in.eof() && inPos == 0) {
+ breakAfterNext = true;
+ }
+ }
+}
+
+
+void charsetConverter_iconv::convert(const string& in, string& out, status* st) {
+
+ if (st) {
+ new (st) status();
+ }
+
+ out.clear();
+
+ utility::inputStreamStringAdapter is(in);
+ utility::outputStreamStringAdapter os(out);
+
+ convert(is, os, st);
+
+ os.flush();
+}
+
+
+shared_ptr <utility::charsetFilteredOutputStream>
+ charsetConverter_iconv::getFilteredOutputStream(
+ utility::outputStream& os,
+ const charsetConverterOptions& opts
+ ) {
+
+ return make_shared <utility::charsetFilteredOutputStream_iconv>(m_source, m_dest, &os, opts);
+}
+
+
+
+// charsetFilteredOutputStream_iconv
+
+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) {
+
+ // 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)) {
+
+ iconv_t* p = new iconv_t;
+ *p= cd;
+
+ m_desc = p;
+ }
+}
+
+
+charsetFilteredOutputStream_iconv::~charsetFilteredOutputStream_iconv() {
+
+ if (m_desc) {
+
+ // Close iconv handle
+ iconv_close(*static_cast <iconv_t*>(m_desc));
+
+ delete static_cast <iconv_t*>(m_desc);
+ m_desc = NULL;
+ }
+}
+
+
+outputStream& charsetFilteredOutputStream_iconv::getNextOutputStream() {
+
+ return m_stream;
+}
+
+
+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);
+
+ const byte_t* curData = data;
+ size_t curDataLen = count;
+
+ // 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) {
+
+ // 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) {
+ throw exceptions::illegal_byte_sequence_for_charset();
+ }
+
+ outputInvalidChar(m_stream, cd);
+
+ std::copy(
+ m_unconvBuffer + 1,
+ m_unconvBuffer + m_unconvCount, m_unconvBuffer
+ );
+
+ m_unconvCount--;
+ }
+
+ // Get more data
+ const size_t remaining =
+ std::min(curDataLen, sizeof(m_unconvBuffer) - m_unconvCount);
+
+ std::copy(curData, curData + remaining, m_unconvBuffer + m_unconvCount);
+
+ m_unconvCount += remaining;
+ curDataLen -= remaining;
+ curData += remaining;
+
+ if (remaining == 0)
+ return; // no more data
+
+ // Try a conversion
+ const byte_t* inPtr = m_unconvBuffer;
+ size_t inLength = m_unconvCount;
+ byte_t* outPtr = m_outputBuffer;
+ size_t outLength = sizeof(m_outputBuffer);
+
+ const size_t inLength0 = inLength;
+
+ if (iconv(cd, ICONV_IN_TYPE(&inPtr), &inLength,
+ 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
+ );
+
+ m_unconvCount -= inputConverted;
+
+ continue;
+ }
+
+ // Write successfully converted bytes
+ m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
+
+ // Empty the unconverted buffer
+ m_unconvCount = 0;
+ }
+
+ if (curDataLen == 0) {
+ return; // no more data
+ }
+
+ // Now, convert the current data buffer
+ const byte_t* inPtr = curData;
+ size_t inLength = std::min(curDataLen, sizeof(m_outputBuffer) / MAX_CHARACTER_WIDTH);
+ byte_t* outPtr = m_outputBuffer;
+ size_t outLength = sizeof(m_outputBuffer);
+
+ const size_t inLength0 = inLength;
+
+ if (iconv(cd, ICONV_IN_TYPE(&inPtr), &inLength,
+ ICONV_OUT_TYPE(&outPtr), &outLength) == static_cast <size_t>(-1)) {
+
+ // Write successfully converted bytes
+ m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
+
+ const size_t inputConverted = inLength0 - inLength;
+
+ curData += inputConverted;
+ curDataLen -= inputConverted;
+
+ // Put one byte byte into the unconverted buffer so
+ // that the next iteration fill it
+ if (curDataLen != 0) {
+
+ m_unconvCount = 1;
+ m_unconvBuffer[0] = *curData;
+
+ curData++;
+ curDataLen--;
+ }
+
+ } else {
+
+ // Write successfully converted bytes
+ m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
+
+ curData += inLength0;
+ curDataLen -= inLength0;
+ }
+ }
+}
+
+
+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) {
+
+ // Try a conversion
+ const byte_t* inPtr = m_unconvBuffer + offset;
+ size_t inLength = m_unconvCount;
+ byte_t* outPtr = m_outputBuffer;
+ size_t outLength = sizeof(m_outputBuffer);
+
+ const size_t inLength0 = inLength;
+
+ 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) {
+ throw exceptions::illegal_byte_sequence_for_charset();
+ }
+
+ outputInvalidChar(m_stream, cd);
+
+ offset++;
+ m_unconvCount--;
+
+ } else {
+
+ // Write successfully converted bytes
+ m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
+
+ offset += inputConverted;
+ m_unconvCount -= inputConverted;
+ }
+
+ } else {
+
+ // Write successfully converted bytes
+ m_stream.write(m_outputBuffer, sizeof(m_outputBuffer) - outLength);
+
+ m_unconvCount = 0;
+ }
+ }
+
+ m_stream.flush();
+}
+
+
+} // utility
+
+
+} // vmime
+
+
+#endif // VMIME_CHARSETCONV_LIB_IS_ICONV
diff --git a/vmime-master/src/vmime/charsetConverter_iconv.hpp b/vmime-master/src/vmime/charsetConverter_iconv.hpp
new file mode 100644
index 0000000..c64813c
--- /dev/null
+++ b/vmime-master/src/vmime/charsetConverter_iconv.hpp
@@ -0,0 +1,145 @@
+//
+// 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_ICONV_HPP_INCLUDED
+#define VMIME_CHARSETCONVERTER_ICONV_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_CHARSETCONV_LIB_IS_ICONV
+
+
+#include "vmime/charsetConverter.hpp"
+
+
+namespace vmime {
+
+
+/** A generic charset converter which uses iconv library.
+ */
+class charsetConverter_iconv : public charsetConverter {
+
+public:
+
+ /** Construct and initialize an iconv charset converter.
+ *
+ * @param source input charset
+ * @param dest output charset
+ * @param opts conversion options
+ */
+ 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()
+ );
+
+private:
+
+ void* m_desc;
+
+ charset m_source;
+ charset m_dest;
+
+ charsetConverterOptions m_options;
+};
+
+
+namespace utility {
+
+
+class charsetFilteredOutputStream_iconv : 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_iconv(
+ const charset& source,
+ const charset& dest, outputStream* os,
+ const charsetConverterOptions& opts = charsetConverterOptions()
+ );
+
+ ~charsetFilteredOutputStream_iconv();
+
+
+ outputStream& getNextOutputStream();
+
+ void flush();
+
+protected:
+
+ void writeImpl(const byte_t* const data, const size_t count);
+
+private:
+
+ // Maximum character width in any charset
+ enum { MAX_CHARACTER_WIDTH = 128 };
+
+
+ void* m_desc;
+
+ const charset m_sourceCharset;
+ const charset m_destCharset;
+
+ outputStream& m_stream;
+
+ // Buffer in which unconverted bytes are left until they can
+ // be converted (when more data arrives). The length should be
+ // large enough to contain any character in any charset.
+ byte_t m_unconvBuffer[MAX_CHARACTER_WIDTH];
+ size_t m_unconvCount;
+
+ // Buffer used for conversion. Avoids declaring it in write().
+ // Should be at least MAX_CHARACTER_WIDTH * MAX_CHARACTER_WIDTH.
+ byte_t m_outputBuffer[32768];
+
+ charsetConverterOptions m_options;
+};
+
+
+} // utility
+
+
+} // vmime
+
+
+#endif // VMIME_CHARSETCONV_LIB_IS_ICONV
+
+#endif // VMIME_CHARSETCONVERTER_ICONV_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/charsetConverter_icu.cpp b/vmime-master/src/vmime/charsetConverter_icu.cpp
new file mode 100644
index 0000000..55195b7
--- /dev/null
+++ b/vmime-master/src/vmime/charsetConverter_icu.cpp
@@ -0,0 +1,572 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_CHARSETCONV_LIB_IS_ICU
+
+
+#include "vmime/charsetConverter_icu.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+#include "vmime/utility/outputStreamStringAdapter.hpp"
+
+
+#ifndef VMIME_BUILDING_DOC
+
+ #include <unicode/ucnv.h>
+ #include <unicode/ucnv_err.h>
+
+#endif // VMIME_BUILDING_DOC
+
+
+#include <unicode/unistr.h>
+
+
+namespace vmime {
+
+
+// static
+shared_ptr <charsetConverter> charsetConverter::createGenericConverter(
+ const charset& source,
+ const charset& dest,
+ const charsetConverterOptions& opts
+) {
+
+ return make_shared <charsetConverter_icu>(source, dest, opts);
+}
+
+
+charsetConverter_icu::charsetConverter_icu(
+ const charset& source,
+ const charset& dest,
+ const charsetConverterOptions& opts
+)
+ : m_from(NULL),
+ m_to(NULL),
+ m_source(source),
+ m_dest(dest),
+ m_options(opts) {
+
+ UErrorCode err = U_ZERO_ERROR;
+ m_from = ucnv_open(source.getName().c_str(), &err);
+
+ if (!U_SUCCESS(err)) {
+
+ throw exceptions::charset_conv_error(
+ "Cannot initialize ICU converter for source charset '" + source.getName()
+ + "' (error code: " + u_errorName(err) + "."
+ );
+ }
+
+ m_to = ucnv_open(dest.getName().c_str(), &err);
+
+ if (!U_SUCCESS(err)) {
+
+ throw exceptions::charset_conv_error(
+ "Cannot initialize ICU converter for destination charset '" + dest.getName()
+ + "' (error code: " + u_errorName(err) + "."
+ );
+ }
+}
+
+
+charsetConverter_icu::~charsetConverter_icu() {
+
+ if (m_from) ucnv_close(m_from);
+ if (m_to) ucnv_close(m_to);
+}
+
+
+void charsetConverter_icu::convert(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ status* st
+) {
+
+ UErrorCode err = U_ZERO_ERROR;
+
+ ucnv_reset(m_from);
+ ucnv_reset(m_to);
+
+ if (st) {
+ new (st) status();
+ }
+
+ // From buffers
+ byte_t cpInBuffer[16]; // stream data put here
+ const size_t outSize = ucnv_getMinCharSize(m_from) * sizeof(cpInBuffer) * sizeof(UChar);
+ std::vector <UChar> uOutBuffer(outSize); // Unicode chars end up here
+
+ // To buffers
+ // converted (char) data end up here
+ const size_t cpOutBufferSz = ucnv_getMaxCharSize(m_to) * outSize;
+ std::vector <char> cpOutBuffer(cpOutBufferSz);
+
+ // Tell ICU what to do when encountering an illegal byte sequence
+ if (m_options.silentlyReplaceInvalidSequences) {
+
+ // Set replacement chars for when converting from Unicode to codepage
+ icu::UnicodeString substString(m_options.invalidSequence.c_str());
+ ucnv_setSubstString(m_to, substString.getTerminatedBuffer(), -1, &err);
+
+ if (U_FAILURE(err)) {
+ throw exceptions::charset_conv_error("[ICU] Error when setting substitution string.");
+ }
+
+ } else {
+
+ // Tell ICU top stop (and return an error) on illegal byte sequences
+ ucnv_setToUCallBack(
+ m_from, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err
+ );
+
+ if (U_FAILURE(err)) {
+ throw exceptions::charset_conv_error("[ICU] Error when setting ToU callback.");
+ }
+
+ ucnv_setFromUCallBack(
+ m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err
+ );
+
+ if (U_FAILURE(err)) {
+ throw exceptions::charset_conv_error("[ICU] Error when setting FromU callback.");
+ }
+ }
+
+ // Input data available
+ while (!in.eof()) {
+
+ // Read input data into buffer
+ size_t inLength = in.read(cpInBuffer, sizeof(cpInBuffer));
+
+ // Beginning of read data
+ const char* source = reinterpret_cast <const char*>(&cpInBuffer[0]);
+ const char* sourceLimit = source + inLength; // end + 1
+
+ UBool flush = in.eof(); // is this last run?
+
+ UErrorCode toErr;
+
+ // Loop until all source has been processed
+ do {
+
+ // Set up target pointers
+ UChar* target = &uOutBuffer[0];
+ UChar* targetLimit = &target[0] + outSize;
+
+ toErr = U_ZERO_ERROR;
+
+ ucnv_toUnicode(
+ m_from, &target, targetLimit,
+ &source, sourceLimit, NULL, flush, &toErr
+ );
+
+ if (st) {
+ st->inputBytesRead += (source - reinterpret_cast <const char*>(&cpInBuffer[0]));
+ }
+
+ if (toErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(toErr)) {
+
+ if (toErr == U_INVALID_CHAR_FOUND ||
+ toErr == U_TRUNCATED_CHAR_FOUND ||
+ toErr == U_ILLEGAL_CHAR_FOUND) {
+
+ // Error will be thrown later (*)
+
+ } else {
+
+ throw exceptions::charset_conv_error(
+ "[ICU] Error converting to Unicode from " + m_source.getName()
+ );
+ }
+ }
+
+ // The Unicode source is the buffer just written and the limit
+ // is where the previous conversion stopped (target is moved in the conversion)
+ const UChar* uSource = &uOutBuffer[0];
+ UChar* uSourceLimit = &target[0];
+ UErrorCode fromErr;
+
+ // Loop until converted chars are fully written
+ do {
+
+ char* cpTarget = &cpOutBuffer[0];
+ const char* cpTargetLimit = &cpOutBuffer[0] + cpOutBufferSz;
+
+ fromErr = U_ZERO_ERROR;
+
+ // Write converted bytes (Unicode) to destination codepage
+ ucnv_fromUnicode(
+ m_to, &cpTarget, cpTargetLimit,
+ &uSource, uSourceLimit, NULL, flush, &fromErr
+ );
+
+ if (st) {
+
+ // Decrement input bytes count by the number of input bytes in error
+ char errBytes[16];
+ int8_t errBytesLen = sizeof(errBytes);
+ UErrorCode errBytesErr = U_ZERO_ERROR;
+
+ ucnv_getInvalidChars(m_from, errBytes, &errBytesLen, &errBytesErr);
+
+ st->inputBytesRead -= errBytesLen;
+ st->outputBytesWritten += cpTarget - &cpOutBuffer[0];
+ }
+
+ // (*) If an error occurred while converting from input charset, throw it now
+ if (toErr == U_INVALID_CHAR_FOUND ||
+ toErr == U_TRUNCATED_CHAR_FOUND ||
+ toErr == U_ILLEGAL_CHAR_FOUND) {
+
+ throw exceptions::illegal_byte_sequence_for_charset();
+ }
+
+ if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) {
+
+ if (fromErr == U_INVALID_CHAR_FOUND ||
+ fromErr == U_TRUNCATED_CHAR_FOUND ||
+ fromErr == U_ILLEGAL_CHAR_FOUND) {
+
+ throw exceptions::illegal_byte_sequence_for_charset();
+
+ } else {
+
+ throw exceptions::charset_conv_error(
+ "[ICU] Error converting from Unicode to " + m_dest.getName()
+ );
+ }
+ }
+
+ // Write to destination stream
+ out.write(&cpOutBuffer[0], (cpTarget - &cpOutBuffer[0]));
+
+ } while (fromErr == U_BUFFER_OVERFLOW_ERROR);
+
+ } while (toErr == U_BUFFER_OVERFLOW_ERROR);
+ }
+}
+
+
+void charsetConverter_icu::convert(const string& in, string& out, status* st) {
+
+ if (st) {
+ new (st) status();
+ }
+
+ out.clear();
+
+ utility::inputStreamStringAdapter is(in);
+ utility::outputStreamStringAdapter os(out);
+
+ convert(is, os, st);
+
+ os.flush();
+}
+
+
+shared_ptr <utility::charsetFilteredOutputStream>
+ charsetConverter_icu::getFilteredOutputStream(
+ utility::outputStream& os,
+ const charsetConverterOptions& opts
+ ) {
+
+ return make_shared <utility::charsetFilteredOutputStream_icu>(m_source, m_dest, &os, opts);
+}
+
+
+
+// charsetFilteredOutputStream_icu
+
+namespace utility {
+
+
+charsetFilteredOutputStream_icu::charsetFilteredOutputStream_icu(
+ const charset& source,
+ const charset& dest,
+ outputStream* os,
+ const charsetConverterOptions& opts
+)
+ : m_from(NULL),
+ m_to(NULL),
+ m_sourceCharset(source),
+ m_destCharset(dest),
+ m_stream(*os),
+ m_options(opts) {
+
+ UErrorCode err = U_ZERO_ERROR;
+ m_from = ucnv_open(source.getName().c_str(), &err);
+
+ if (!U_SUCCESS(err)) {
+
+ throw exceptions::charset_conv_error(
+ "Cannot initialize ICU converter for source charset '" + source.getName()
+ + "' (error code: " + u_errorName(err) + "."
+ );
+ }
+
+ m_to = ucnv_open(dest.getName().c_str(), &err);
+
+ if (!U_SUCCESS(err)) {
+
+ throw exceptions::charset_conv_error(
+ "Cannot initialize ICU converter for destination charset '" + dest.getName()
+ + "' (error code: " + u_errorName(err) + "."
+ );
+ }
+
+ // Tell ICU what to do when encountering an illegal byte sequence
+ if (m_options.silentlyReplaceInvalidSequences) {
+
+ // Set replacement chars for when converting from Unicode to codepage
+ icu::UnicodeString substString(m_options.invalidSequence.c_str());
+ ucnv_setSubstString(m_to, substString.getTerminatedBuffer(), -1, &err);
+
+ if (U_FAILURE(err)) {
+ throw exceptions::charset_conv_error("[ICU] Error when setting substitution string.");
+ }
+
+ } else {
+
+ // Tell ICU top stop (and return an error) on illegal byte sequences
+ ucnv_setToUCallBack(
+ m_to, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err
+ );
+
+ if (U_FAILURE(err)) {
+ throw exceptions::charset_conv_error("[ICU] Error when setting ToU callback.");
+ }
+
+ ucnv_setFromUCallBack(
+ m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err
+ );
+
+ if (U_FAILURE(err)) {
+ throw exceptions::charset_conv_error("[ICU] Error when setting FromU callback.");
+ }
+ }
+}
+
+
+charsetFilteredOutputStream_icu::~charsetFilteredOutputStream_icu() {
+
+ if (m_from) ucnv_close(m_from);
+ if (m_to) ucnv_close(m_to);
+}
+
+
+outputStream& charsetFilteredOutputStream_icu::getNextOutputStream() {
+
+ return m_stream;
+}
+
+
+void charsetFilteredOutputStream_icu::writeImpl(
+ const byte_t* const data,
+ const size_t count
+) {
+
+ if (!m_from || !m_to) {
+ throw exceptions::charset_conv_error("Cannot initialize converters.");
+ }
+
+ // Allocate buffer for Unicode chars
+ const size_t uniSize = ucnv_getMinCharSize(m_from) * count * sizeof(UChar);
+ std::vector <UChar> uniBuffer(uniSize);
+
+ // Conversion loop
+ UErrorCode toErr = U_ZERO_ERROR;
+
+ const char* uniSource = reinterpret_cast <const char*>(data);
+ const char* uniSourceLimit = uniSource + count;
+
+ do {
+
+ // Convert from source charset to Unicode
+ UChar* uniTarget = &uniBuffer[0];
+ UChar* uniTargetLimit = &uniBuffer[0] + uniSize;
+
+ toErr = U_ZERO_ERROR;
+
+ ucnv_toUnicode(
+ m_from, &uniTarget, uniTargetLimit,
+ &uniSource, uniSourceLimit, NULL, /* flush */ FALSE, &toErr
+ );
+
+ if (U_FAILURE(toErr) && toErr != U_BUFFER_OVERFLOW_ERROR) {
+
+ if (toErr == U_INVALID_CHAR_FOUND ||
+ toErr == U_TRUNCATED_CHAR_FOUND ||
+ toErr == U_ILLEGAL_CHAR_FOUND) {
+
+ throw exceptions::illegal_byte_sequence_for_charset();
+
+ } else {
+
+ throw exceptions::charset_conv_error(
+ "[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'."
+ );
+ }
+ }
+
+ const size_t uniLength = uniTarget - &uniBuffer[0];
+
+ // Allocate buffer for destination charset
+ const size_t cpSize = ucnv_getMinCharSize(m_to) * uniLength;
+ std::vector <char> cpBuffer(cpSize);
+
+ // Convert from Unicode to destination charset
+ UErrorCode fromErr = U_ZERO_ERROR;
+
+ const UChar* cpSource = &uniBuffer[0];
+ const UChar* cpSourceLimit = &uniBuffer[0] + uniLength;
+
+ do {
+
+ char* cpTarget = &cpBuffer[0];
+ char* cpTargetLimit = &cpBuffer[0] + cpSize;
+
+ fromErr = U_ZERO_ERROR;
+
+ ucnv_fromUnicode(
+ m_to, &cpTarget, cpTargetLimit,
+ &cpSource, cpSourceLimit, NULL, /* flush */ FALSE, &fromErr
+ );
+
+ if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) {
+
+ if (fromErr == U_INVALID_CHAR_FOUND ||
+ fromErr == U_TRUNCATED_CHAR_FOUND ||
+ fromErr == U_ILLEGAL_CHAR_FOUND) {
+
+ throw exceptions::illegal_byte_sequence_for_charset();
+
+ } else {
+
+ throw exceptions::charset_conv_error(
+ "[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'."
+ );
+ }
+ }
+
+ const size_t cpLength = cpTarget - &cpBuffer[0];
+
+ // Write successfully converted bytes
+ m_stream.write(&cpBuffer[0], cpLength);
+
+ } while (fromErr == U_BUFFER_OVERFLOW_ERROR);
+
+ } while (toErr == U_BUFFER_OVERFLOW_ERROR);
+}
+
+
+void charsetFilteredOutputStream_icu::flush() {
+
+ if (!m_from || !m_to) {
+ throw exceptions::charset_conv_error("Cannot initialize converters.");
+ }
+
+ // Allocate buffer for Unicode chars
+ const size_t uniSize = ucnv_getMinCharSize(m_from) * 1024 * sizeof(UChar);
+ std::vector <UChar> uniBuffer(uniSize);
+
+ // Conversion loop (with flushing)
+ UErrorCode toErr = U_ZERO_ERROR;
+
+ const char* uniSource = 0;
+ const char* uniSourceLimit = 0;
+
+ do {
+
+ // Convert from source charset to Unicode
+ UChar* uniTarget = &uniBuffer[0];
+ UChar* uniTargetLimit = &uniBuffer[0] + uniSize;
+
+ toErr = U_ZERO_ERROR;
+
+ ucnv_toUnicode(
+ m_from, &uniTarget, uniTargetLimit,
+ &uniSource, uniSourceLimit, NULL, /* flush */ TRUE, &toErr
+ );
+
+ if (U_FAILURE(toErr) && toErr != U_BUFFER_OVERFLOW_ERROR) {
+
+ throw exceptions::charset_conv_error(
+ "[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'."
+ );
+ }
+
+ const size_t uniLength = uniTarget - &uniBuffer[0];
+
+ // Allocate buffer for destination charset
+ const size_t cpSize = ucnv_getMinCharSize(m_to) * uniLength;
+ std::vector <char> cpBuffer(cpSize);
+
+ // Convert from Unicode to destination charset
+ UErrorCode fromErr = U_ZERO_ERROR;
+
+ const UChar* cpSource = &uniBuffer[0];
+ const UChar* cpSourceLimit = &uniBuffer[0] + uniLength;
+
+ do {
+
+ char* cpTarget = &cpBuffer[0];
+ char* cpTargetLimit = &cpBuffer[0] + cpSize;
+
+ fromErr = U_ZERO_ERROR;
+
+ ucnv_fromUnicode(
+ m_to, &cpTarget, cpTargetLimit,
+ &cpSource, cpSourceLimit, NULL, /* flush */ TRUE, &fromErr
+ );
+
+ if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) {
+
+ throw exceptions::charset_conv_error(
+ "[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'."
+ );
+ }
+
+ const size_t cpLength = cpTarget - &cpBuffer[0];
+
+ // Write successfully converted bytes
+ m_stream.write(&cpBuffer[0], cpLength);
+
+ } while (fromErr == U_BUFFER_OVERFLOW_ERROR);
+
+ } while (toErr == U_BUFFER_OVERFLOW_ERROR);
+
+ m_stream.flush();
+}
+
+
+} // utility
+
+
+} // vmime
+
+
+#endif // VMIME_CHARSETCONV_LIB_IS_ICU
diff --git a/vmime-master/src/vmime/charsetConverter_icu.hpp b/vmime-master/src/vmime/charsetConverter_icu.hpp
new file mode 100644
index 0000000..cf5eb6b
--- /dev/null
+++ b/vmime-master/src/vmime/charsetConverter_icu.hpp
@@ -0,0 +1,137 @@
+//
+// 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
diff --git a/vmime-master/src/vmime/charsetConverter_idna.cpp b/vmime-master/src/vmime/charsetConverter_idna.cpp
new file mode 100644
index 0000000..eb8764f
--- /dev/null
+++ b/vmime-master/src/vmime/charsetConverter_idna.cpp
@@ -0,0 +1,208 @@
+//
+// 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.
+//
+
+#include "vmime/charsetConverter_idna.hpp"
+
+#include "vmime/exception.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+#include "vmime/utility/streamUtils.hpp"
+#include "vmime/utility/outputStreamStringAdapter.hpp"
+
+
+extern "C" {
+
+#include "contrib/punycode/punycode.h"
+#include "contrib/punycode/punycode.c"
+
+}
+
+#include "contrib/utf8/utf8.h"
+
+
+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() {
+
+}
+
+
+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
+ string inStr;
+ vmime::utility::outputStreamStringAdapter os(inStr);
+ vmime::utility::bufferedStreamCopy(in, os);
+
+ string outStr;
+ convert(inStr, outStr, st);
+
+ out << outStr;
+}
+
+
+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) {
+ st->inputBytesRead = in.length();
+ st->outputBytesWritten = in.length();
+ }
+
+ // No need to encode as Punycode
+ out = in;
+ return;
+ }
+
+ string inUTF8;
+ charset::convert(in, inUTF8, m_source, vmime::charsets::UTF_8);
+
+ const char* ch = inUTF8.c_str();
+ const char* end = inUTF8.c_str() + inUTF8.length();
+
+ std::vector <punycode_uint> unichars;
+ unichars.reserve(inUTF8.length());
+
+ while (ch < end) {
+ const utf8::uint32_t uc = utf8::unchecked::next(ch);
+ unichars.push_back(uc);
+ }
+
+ 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]
+ );
+
+ if (status == punycode_success) {
+
+ out = string("xn--") + string(output.begin(), output.begin() + outputLen);
+
+ if (st) {
+ st->outputBytesWritten = out.length();
+ }
+
+ } else {
+
+ // TODO
+ }
+
+ } else if (m_source == "idna") {
+
+ if (in.length() < 5 || in.substr(0, 4) != "xn--") {
+
+ if (st) {
+ st->inputBytesRead = in.length();
+ st->outputBytesWritten = in.length();
+ }
+
+ // Not an IDNA string
+ out = in;
+ return;
+ }
+
+ punycode_uint inputLen = static_cast <punycode_uint>(in.length() - 4);
+
+ 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
+ );
+
+ if (st) {
+ st->inputBytesRead = in.length();
+ }
+
+ 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) {
+
+ p = utf8::unchecked::append(*it, p);
+ }
+
+ string outUTF8(&outUTF8Bytes[0], p);
+ charset::convert(outUTF8, out, vmime::charsets::UTF_8, m_dest);
+
+ if (st) {
+ st->outputBytesWritten = out.length();
+ }
+
+ } else {
+
+ // TODO
+ }
+ }
+}
+
+
+shared_ptr <utility::charsetFilteredOutputStream>
+ charsetConverter_idna::getFilteredOutputStream(
+ utility::outputStream& /* os */,
+ const charsetConverterOptions& /* opts */
+ ) {
+
+ // Not supported
+ return null;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/charsetConverter_idna.hpp b/vmime-master/src/vmime/charsetConverter_idna.hpp
new file mode 100644
index 0000000..aaf547d
--- /dev/null
+++ b/vmime-master/src/vmime/charsetConverter_idna.hpp
@@ -0,0 +1,74 @@
+//
+// 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_IDNA_HPP_INCLUDED
+#define VMIME_CHARSETCONVERTER_IDNA_HPP_INCLUDED
+
+
+#include "vmime/charsetConverter.hpp"
+
+
+namespace vmime {
+
+
+/** A charset converter which can convert to and from Punycode (for IDNA).
+ */
+class charsetConverter_idna : public charsetConverter {
+
+public:
+
+ /** Construct and initialize an IDNA charset converter.
+ *
+ * @param source input charset
+ * @param dest output charset
+ * @param opts conversion options
+ */
+ 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()
+ );
+
+private:
+
+ charset m_source;
+ charset m_dest;
+
+ charsetConverterOptions m_options;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_CHARSETCONVERTER_IDNA_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/charsetConverter_win.cpp b/vmime-master/src/vmime/charsetConverter_win.cpp
new file mode 100644
index 0000000..eab1829
--- /dev/null
+++ b/vmime-master/src/vmime/charsetConverter_win.cpp
@@ -0,0 +1,227 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_CHARSETCONV_LIB_IS_WIN
+
+
+#include "vmime/charsetConverter_win.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/utility/stringUtils.hpp"
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+#include "vmime/utility/outputStreamStringAdapter.hpp"
+
+#include <string.h>
+#include <stdlib.h>
+
+
+#if (_WIN32 || _WIN64 || WIN32 || WIN64)
+ #include <windows.h>
+ #include "vmime/platforms/windows/windowsCodepages.hpp"
+#else
+ #error Please use VMIME_CHARSETCONV_LIB_IS_WIN only on Windows!
+#endif
+
+
+#define CP_UNICODE 1200
+
+
+namespace vmime {
+
+
+// static
+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) {
+
+}
+
+
+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()) {
+ const size_t len = in.read(buffer, sizeof(buffer));
+ utility::stringUtils::appendBytesToString(inStr, buffer, len);
+ }
+
+ convert(inStr, outStr, st);
+
+ out.write(outStr.data(), outStr.length());
+}
+
+
+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());
+
+ // Convert from source charset to Unicode
+ std::vector <char> unicodeBuffer;
+ const WCHAR* unicodePtr = NULL;
+ size_t unicodeLen = 0;
+
+ if (sourceCodePage == CP_UNICODE) {
+
+ unicodePtr = reinterpret_cast <const WCHAR*>(in.c_str());
+ unicodeLen = in.length() / 2;
+
+ } else {
+
+ const size_t bufferSize = MultiByteToWideChar(
+ sourceCodePage, 0, in.c_str(), static_cast <int>(in.length()), NULL, 0
+ ) * sizeof(WCHAR); // in wide characters
+
+ unicodeBuffer.resize(bufferSize);
+
+ DWORD flags = 0;
+
+ 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)
+ );
+
+ 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()
+ );
+ }
+ }
+ }
+
+ // Convert from Unicode to destination charset
+ if (destCodePage == CP_UNICODE) {
+
+ out.assign(reinterpret_cast <const char*>(unicodePtr), unicodeLen * 2);
+
+ } else {
+
+ const size_t bufferSize = WideCharToMultiByte(
+ destCodePage, 0, unicodePtr, static_cast <int>(unicodeLen),
+ NULL, 0, 0, NULL
+ ); // in multibyte characters
+
+ 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
+ );
+
+ 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()
+ );
+ }
+ }
+
+ out.assign(&buffer[0], len);
+ }
+}
+
+
+// static
+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')) {
+
+ return atoi(name + 2);
+ }
+
+ return vmime::platforms::windows::windowsCodepages::getByName(name); // throws
+}
+
+
+shared_ptr <utility::charsetFilteredOutputStream>
+ charsetConverter_win::getFilteredOutputStream(
+ utility::outputStream& /* os */,
+ const charsetConverterOptions& /* opts */
+ ) {
+
+ // TODO: implement me!
+ return null;
+}
+
+
+} // vmime
+
+
+#endif // VMIME_CHARSETCONV_LIB_IS_WIN
diff --git a/vmime-master/src/vmime/charsetConverter_win.hpp b/vmime-master/src/vmime/charsetConverter_win.hpp
new file mode 100644
index 0000000..d20970b
--- /dev/null
+++ b/vmime-master/src/vmime/charsetConverter_win.hpp
@@ -0,0 +1,91 @@
+//
+// 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_WIN_HPP_INCLUDED
+#define VMIME_CHARSETCONVERTER_WIN_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_CHARSETCONV_LIB_IS_WIN
+
+
+#include "vmime/charsetConverter.hpp"
+
+
+namespace vmime {
+
+
+/** A generic charset converter which uses Windows MultiByteToWideChar
+ * and WideCharToMultiByte API functions.
+ *
+ * ICU or iconv library should always be preferred over this one, even
+ * on Windows platform, as MultiByteToWideChar() and WideCharToMultiByte()
+ * functions cannot be used easily with streams (no context). Moreover,
+ * error handling is very poor, in particular when an invalid sequence
+ * is found...
+ *
+ * Also, "status" is not supported by this converter for the same reason.
+ */
+class charsetConverter_win : public charsetConverter {
+
+public:
+
+ /** Construct and initialize a Windows charset converter.
+ *
+ * @param source input charset
+ * @param dest output charset
+ * @param opts conversion options
+ */
+ 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
+ );
+
+private:
+
+ static int getCodePage(const char* name);
+
+ charset m_source;
+ charset m_dest;
+
+ charsetConverterOptions m_options;
+};
+
+
+} // namespace
+
+
+#endif // VMIME_CHARSETCONV_LIB_IS_WIN
+
+#endif // VMIME_CHARSETCONVERTER_WIN_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/component.cpp b/vmime-master/src/vmime/component.cpp
new file mode 100644
index 0000000..7adf8f7
--- /dev/null
+++ b/vmime-master/src/vmime/component.cpp
@@ -0,0 +1,275 @@
+//
+// 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.
+//
+
+#include "vmime/component.hpp"
+#include "vmime/base.hpp"
+
+#include "vmime/utility/streamUtils.hpp"
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+#include <sstream>
+
+
+namespace vmime {
+
+
+component::component()
+ : m_parsedOffset(0), m_parsedLength(0) {
+
+}
+
+
+component::~component() {
+
+}
+
+
+void component::parse(
+ const shared_ptr <utility::inputStream>& inputStream,
+ const size_t length
+) {
+
+ parse(inputStream, 0, length, NULL);
+}
+
+
+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,
+ 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 || end == 0) {
+
+ // Read the whole stream into a buffer
+ std::ostringstream oss;
+ utility::outputStreamAdapter ossAdapter(oss);
+
+ utility::bufferedStreamCopyRange(*inputStream, ossAdapter, position, end - position);
+
+ const string buffer = oss.str();
+ parseImpl(ctx, buffer, 0, buffer.length(), NULL);
+
+ } else {
+
+ shared_ptr <utility::parserInputStreamAdapter> parser =
+ make_shared <utility::parserInputStreamAdapter>(seekableStream);
+
+ parseImpl(ctx, parser, position, end, newPosition);
+ }
+}
+
+
+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) {
+
+ 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
+) {
+
+ 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
+) {
+
+ m_parsedOffset = m_parsedLength = 0;
+
+ parseImpl(ctx, buffer, position, end, newPosition);
+}
+
+
+void component::offsetParsedBounds(const size_t offset) {
+
+ // Offset parsed bounds of this component
+ 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) {
+ children[i]->offsetParsedBounds(offset);
+ }
+}
+
+
+void component::parseImpl(
+ const parsingContext& ctx,
+ const shared_ptr <utility::parserInputStreamAdapter>& parser,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ // This is the default implementation for parsing from an input stream:
+ // actually, we extract the substring and use the "parse from string" implementation
+ const string buffer = parser->extract(position, end);
+ parseImpl(ctx, buffer, 0, buffer.length(), newPosition);
+
+ // Recursivey offset parsed bounds on children
+ if (position != 0) {
+ offsetParsedBounds(position);
+ }
+
+ if (newPosition) {
+ *newPosition += position;
+ }
+}
+
+
+void component::parseImpl(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition) {
+
+ // This is the default implementation for parsing from a string:
+ // actually, we encapsulate the string buffer in an input stream, then use
+ // the "parse from input stream" implementation
+ shared_ptr <utility::seekableInputStream> stream =
+ make_shared <utility::inputStreamStringAdapter>(buffer);
+
+ shared_ptr <utility::parserInputStreamAdapter> parser =
+ make_shared <utility::parserInputStreamAdapter>(stream);
+
+ parseImpl(ctx, parser, position, end, newPosition);
+}
+
+
+const string component::generate(
+ const size_t maxLineLength,
+ const size_t curLinePos
+) const {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter adapter(oss);
+
+ generationContext ctx(generationContext::getDefaultContext());
+ ctx.setMaxLineLength(maxLineLength);
+
+ generateImpl(ctx, adapter, curLinePos, NULL);
+
+ 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(
+ 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::getParsedLength() const {
+
+ return m_parsedLength;
+}
+
+
+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) {
+
+ 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) {
+
+ totalSize += (*it)->getGeneratedSize(ctx);
+ }
+
+ return totalSize;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/component.hpp b/vmime-master/src/vmime/component.hpp
new file mode 100644
index 0000000..91164c3
--- /dev/null
+++ b/vmime-master/src/vmime/component.hpp
@@ -0,0 +1,265 @@
+//
+// 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_COMPONENT_HPP_INCLUDED
+#define VMIME_COMPONENT_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/utility/inputStream.hpp"
+#include "vmime/utility/seekableInputStream.hpp"
+#include "vmime/utility/parserInputStreamAdapter.hpp"
+#include "vmime/utility/outputStream.hpp"
+#include "vmime/generationContext.hpp"
+#include "vmime/parsingContext.hpp"
+
+
+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 {
+
+public:
+
+ component();
+ virtual ~component();
+
+ /** Parse RFC-822/MIME data for this component, using the default
+ * parsing context.
+ *
+ * @param buffer input buffer
+ */
+ void parse(const string& buffer);
+
+ /** Parse RFC-822/MIME data for this component.
+ *
+ * @param ctx parsing context
+ * @param buffer input buffer
+ */
+ void parse(const 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
+ * be loaded into memory before parsing.
+ *
+ * @param inputStream stream from which to read data
+ * @param length data length, in bytes (0 = unknown/not specified)
+ */
+ 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.
+ *
+ * @param buffer input buffer
+ * @param position current position in the input buffer
+ * @param end end position in the input buffer
+ * @param newPosition will receive the new position in the input buffer
+ */
+ 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.
+ *
+ * @param ctx parsing context
+ * @param buffer input buffer
+ * @param position current position in the input buffer
+ * @param end end position in the input buffer
+ * @param newPosition will receive the new position in the input buffer
+ */
+ void parse(
+ const 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
+ * be loaded into memory before parsing. The default parsing context
+ * will be used.
+ *
+ * @param inputStream stream from which to read data
+ * @param position current position in the input stream
+ * @param end end position in the input stream
+ * @param newPosition will receive the new position in the input stream
+ */
+ 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
+ * be loaded into memory before parsing.
+ *
+ * @param ctx parsing context
+ * @param inputStream stream from which to read data
+ * @param position current position in the input stream
+ * @param end end position in the input stream
+ * @param newPosition will receive the new position in the input stream
+ */
+ void parse(
+ const 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.
+ *
+ * \deprecated Use the new generate() method, which takes an outputStream parameter.
+ *
+ * @param maxLineLength maximum line length for output
+ * @param curLinePos length of the current line in the output buffer
+ * @return generated data
+ */
+ virtual const string generate(
+ const size_t maxLineLength = lineLengthLimits::infinite,
+ const size_t curLinePos = 0
+ ) const;
+
+ /** Generate RFC-2822/MIME data for this component, using the default generation context.
+ *
+ * @param outputStream output stream
+ * @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;
+
+ /** Generate RFC-2822/MIME data for this component, using the default generation context.
+ *
+ * @param ctx generation context
+ * @param outputStream output stream
+ * @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;
+
+ /** Clone this component.
+ *
+ * @return a copy of this component
+ */
+ virtual shared_ptr <component> clone() const = 0;
+
+ /** Replace data in this component by data in other component.
+ * Both components must be of the same type.
+ *
+ * @throw std::bad_cast_exception if the components are not
+ * of the same (dynamic) type
+ * @param other other component to copy data from
+ */
+ virtual void copyFrom(const component& other) = 0;
+
+ /** Return the start position of this component in the
+ * parsed message contents. Use for debugging only.
+ *
+ * @return start position in parsed buffer
+ * or 0 if this component has not been parsed
+ */
+ size_t getParsedOffset() const;
+
+ /** Return the length of this component in the
+ * parsed message contents. Use for debugging only.
+ *
+ * @return length of the component in parsed buffer
+ * or 0 if this component has not been parsed
+ */
+ size_t getParsedLength() const;
+
+ /** Return the list of children of this component.
+ *
+ * @return list of child components
+ */
+ virtual const std::vector <shared_ptr <component> > getChildComponents() = 0;
+
+ /** Get the number of bytes that will be used by this component when
+ * it is generated. This may be a heuristically-derived estimate,
+ * but such an estimated size should always be larger than the actual
+ * generated size.
+ *
+ * @param ctx generation context
+ * @return component size when generated
+ */
+ virtual size_t getGeneratedSize(const generationContext& ctx);
+
+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,
+ 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 generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const = 0;
+
+private:
+
+ void offsetParsedBounds(const size_t offset);
+
+ size_t m_parsedOffset;
+ size_t m_parsedLength;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_COMPONENT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/constants.cpp b/vmime-master/src/vmime/constants.cpp
new file mode 100644
index 0000000..445c012
--- /dev/null
+++ b/vmime-master/src/vmime/constants.cpp
@@ -0,0 +1,251 @@
+//
+// 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.
+//
+
+#include "vmime/constants.hpp"
+
+
+namespace vmime {
+
+
+// Media Types
+namespace mediaTypes {
+
+ // Types
+ const char* const TEXT = "text";
+ const char* const MULTIPART = "multipart";
+ const char* const MESSAGE = "message";
+ const char* const APPLICATION = "application";
+ const char* const IMAGE = "image";
+ const char* const AUDIO = "audio";
+ const char* const VIDEO = "video";
+
+ // Sub-types
+ const char* const TEXT_PLAIN = "plain";
+ const char* const TEXT_HTML = "html";
+ const char* const TEXT_RICHTEXT = "richtext";
+ const char* const TEXT_ENRICHED = "enriched";
+ const char* const TEXT_RFC822_HEADERS = "rfc822-headers"; // RFC-1892
+ const char* const TEXT_DIRECTORY = "directory"; // RFC-2426
+
+ const char* const MULTIPART_MIXED = "mixed";
+ const char* const MULTIPART_RELATED = "related";
+ const char* const MULTIPART_ALTERNATIVE = "alternative";
+ const char* const MULTIPART_PARALLEL = "parallel";
+ const char* const MULTIPART_DIGEST = "digest";
+ const char* const MULTIPART_REPORT = "report"; // RFC-1892
+
+ const char* const MESSAGE_RFC822 = "rfc822";
+ 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";
+
+ const char* const IMAGE_JPEG = "jpeg";
+ const char* const IMAGE_GIF = "gif";
+
+ const char* const AUDIO_BASIC = "basic";
+
+ const char* const VIDEO_MPEG = "mpeg";
+}
+
+
+// Encoding types
+namespace encodingTypes {
+
+ const char* const SEVEN_BIT = "7bit";
+ const char* const EIGHT_BIT = "8bit";
+ const char* const BASE64 = "base64";
+ const char* const QUOTED_PRINTABLE = "quoted-printable";
+ const char* const BINARY = "binary";
+ const char* const UUENCODE = "uuencode";
+}
+
+
+// Content disposition types
+namespace contentDispositionTypes {
+
+ const char* const INLINE = "inline";
+ const char* const ATTACHMENT = "attachment";
+}
+
+
+// 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";
+ const char* const ISO8859_4 = "iso-8859-4";
+ const char* const ISO8859_5 = "iso-8859-5";
+ const char* const ISO8859_6 = "iso-8859-6";
+ const char* const ISO8859_7 = "iso-8859-7";
+ const char* const ISO8859_8 = "iso-8859-8";
+ const char* const ISO8859_9 = "iso-8859-9";
+ const char* const ISO8859_10 = "iso-8859-10";
+ const char* const ISO8859_13 = "iso-8859-13";
+ const char* const ISO8859_14 = "iso-8859-14";
+ const char* const ISO8859_15 = "iso-8859-15";
+ const char* const ISO8859_16 = "iso-8859-16";
+
+ const char* const CP_437 = "cp437";
+ const char* const CP_737 = "cp737";
+ const char* const CP_775 = "cp775";
+ const char* const CP_850 = "cp850";
+ const char* const CP_852 = "cp852";
+ const char* const CP_853 = "cp853";
+ const char* const CP_855 = "cp855";
+ const char* const CP_857 = "cp857";
+ const char* const CP_858 = "cp858";
+ const char* const CP_860 = "cp860";
+ const char* const CP_861 = "cp861";
+ const char* const CP_862 = "cp862";
+ const char* const CP_863 = "cp863";
+ const char* const CP_864 = "cp864";
+ const char* const CP_865 = "cp865";
+ const char* const CP_866 = "cp866";
+ const char* const CP_869 = "cp869";
+ const char* const CP_874 = "cp874";
+ const char* const CP_1125 = "cp1125";
+ const char* const CP_1250 = "cp1250";
+ const char* const CP_1251 = "cp1251";
+ const char* const CP_1252 = "cp1252";
+ const char* const CP_1253 = "cp1253";
+ const char* const CP_1254 = "cp1254";
+ const char* const CP_1255 = "cp1255";
+ const char* const CP_1256 = "cp1256";
+ const char* const CP_1257 = "cp1257";
+
+ const char* const US_ASCII = "us-ascii";
+
+ const char* const UTF_7 = "utf-7";
+ const char* const UTF_8 = "utf-8";
+ const char* const UTF_16 = "utf-16";
+ const char* const UTF_32 = "utf-32";
+
+ const char* const WINDOWS_1250 = "windows-1250";
+ const char* const WINDOWS_1251 = "windows-1251";
+ const char* const WINDOWS_1252 = "windows-1252";
+ const char* const WINDOWS_1253 = "windows-1253";
+ const char* const WINDOWS_1254 = "windows-1254";
+ const char* const WINDOWS_1255 = "windows-1255";
+ const char* const WINDOWS_1256 = "windows-1256";
+ const char* const WINDOWS_1257 = "windows-1257";
+ const char* const WINDOWS_1258 = "windows-1258";
+
+ const char* const IDNA = "idna";
+}
+
+
+// Fields
+namespace fields {
+
+ const char* const RECEIVED = "Received";
+ const char* const FROM = "From";
+ const char* const SENDER = "Sender";
+ const char* const REPLY_TO = "Reply-To";
+ const char* const TO = "To";
+ const char* const CC = "Cc";
+ const char* const BCC = "Bcc";
+ const char* const DATE = "Date";
+ const char* const SUBJECT = "Subject";
+ const char* const ORGANIZATION = "Organization";
+ const char* const USER_AGENT = "User-Agent";
+ const char* const DELIVERED_TO = "Delivered-To";
+ const char* const RETURN_PATH = "Return-Path";
+ const char* const MIME_VERSION = "Mime-Version";
+ const char* const MESSAGE_ID = "Message-Id";
+ const char* const CONTENT_TYPE = "Content-Type";
+ const char* const CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
+ const char* const CONTENT_DESCRIPTION = "Content-Description";
+ const char* const CONTENT_DISPOSITION = "Content-Disposition";
+ const char* const CONTENT_ID = "Content-Id";
+ const char* const CONTENT_LOCATION = "Content-Location";
+ const char* const IN_REPLY_TO = "In-Reply-To";
+ const char* const REFERENCES = "References";
+
+ const char* const X_MAILER = "X-Mailer";
+ const char* const X_PRIORITY = "X-Priority";
+
+ // RFC-3798: Message Disposition
+ const char* const ORIGINAL_MESSAGE_ID = "Original-Message-ID";
+ const char* const DISPOSITION_NOTIFICATION_TO = "Disposition-Notification-To";
+ const char* const DISPOSITION_NOTIFICATION_OPTIONS = "Disposition-Notification-Options";
+ const char* const DISPOSITION = "Disposition";
+ const char* const FAILURE = "Failure";
+ const char* const ERROR = "Error";
+ const char* const WARNING = "Warning";
+ const char* const ORIGINAL_RECIPIENT = "Original-Recipient";
+ const char* const FINAL_RECIPIENT = "Final-Recipient";
+ const char* const REPORTING_UA = "Reporting-UA";
+ const char* const MDN_GATEWAY = "MDN-Gateway";
+}
+
+
+// Constants for disposition action modes (RFC-3978).
+namespace dispositionActionModes {
+
+ const char* const MANUAL = "manual";
+ const char* const AUTOMATIC = "automatic";
+}
+
+
+// Constants for disposition sending modes (RFC-3798).
+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 {
+
+ const char* const DISPLAYED = "displayed";
+ const char* const DELETED = "deleted";
+}
+
+
+// Constants for disposition modifiers (RFC-3798).
+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
diff --git a/vmime-master/src/vmime/constants.hpp b/vmime-master/src/vmime/constants.hpp
new file mode 100644
index 0000000..9d25383
--- /dev/null
+++ b/vmime-master/src/vmime/constants.hpp
@@ -0,0 +1,272 @@
+//
+// 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
+// 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_CONSTANTS_HPP_INCLUDED
+#define VMIME_CONSTANTS_HPP_INCLUDED
+
+
+#include <string>
+
+#include "vmime/types.hpp"
+
+
+// Remove Windows defines of ERROR and WARNING
+#ifdef _WIN32
+ #undef ERROR
+ #undef WARNING
+#endif
+
+
+namespace vmime {
+
+ /** Constants for media types. */
+ namespace mediaTypes {
+
+ // Types
+ extern VMIME_EXPORT const char* const TEXT;
+ extern VMIME_EXPORT const char* const MULTIPART;
+ extern VMIME_EXPORT const char* const MESSAGE;
+ extern VMIME_EXPORT const char* const APPLICATION;
+ extern VMIME_EXPORT const char* const IMAGE;
+ extern VMIME_EXPORT const char* const AUDIO;
+ extern VMIME_EXPORT const char* const VIDEO;
+
+ // Sub-types
+ extern VMIME_EXPORT const char* const TEXT_PLAIN;
+ extern VMIME_EXPORT const char* const TEXT_HTML;
+ extern VMIME_EXPORT const char* const TEXT_RICHTEXT;
+ extern VMIME_EXPORT const char* const TEXT_ENRICHED;
+ extern VMIME_EXPORT const char* const TEXT_RFC822_HEADERS; // RFC-1892
+ extern VMIME_EXPORT const char* const TEXT_DIRECTORY; // RFC-2426
+
+ extern VMIME_EXPORT const char* const MULTIPART_MIXED;
+ extern VMIME_EXPORT const char* const MULTIPART_RELATED;
+ extern VMIME_EXPORT const char* const MULTIPART_ALTERNATIVE;
+ extern VMIME_EXPORT const char* const MULTIPART_PARALLEL;
+ extern VMIME_EXPORT const char* const MULTIPART_DIGEST;
+ extern VMIME_EXPORT const char* const MULTIPART_REPORT; // RFC-1892
+
+ extern VMIME_EXPORT const char* const MESSAGE_RFC822;
+ 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;
+
+ extern VMIME_EXPORT const char* const IMAGE_JPEG;
+ extern VMIME_EXPORT const char* const IMAGE_GIF;
+
+ extern VMIME_EXPORT const char* const AUDIO_BASIC;
+
+ extern VMIME_EXPORT const char* const VIDEO_MPEG;
+ }
+
+
+ /** Constants for encoding types. */
+ 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;
+ extern VMIME_EXPORT const char* const QUOTED_PRINTABLE;
+ extern VMIME_EXPORT const char* const BINARY;
+ extern VMIME_EXPORT const char* const UUENCODE;
+ }
+
+
+ /** Constants for content disposition types (RFC-2183). */
+ namespace contentDispositionTypes {
+
+ extern VMIME_EXPORT const char* const INLINE;
+ extern VMIME_EXPORT const char* const ATTACHMENT;
+ }
+
+
+ /** Constants for 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;
+ extern VMIME_EXPORT const char* const ISO8859_4;
+ extern VMIME_EXPORT const char* const ISO8859_5;
+ extern VMIME_EXPORT const char* const ISO8859_6;
+ extern VMIME_EXPORT const char* const ISO8859_7;
+ extern VMIME_EXPORT const char* const ISO8859_8;
+ extern VMIME_EXPORT const char* const ISO8859_9;
+ extern VMIME_EXPORT const char* const ISO8859_10;
+ extern VMIME_EXPORT const char* const ISO8859_13;
+ extern VMIME_EXPORT const char* const ISO8859_14;
+ extern VMIME_EXPORT const char* const ISO8859_15;
+ extern VMIME_EXPORT const char* const ISO8859_16;
+
+ extern VMIME_EXPORT const char* const CP_437;
+ extern VMIME_EXPORT const char* const CP_737;
+ extern VMIME_EXPORT const char* const CP_775;
+ extern VMIME_EXPORT const char* const CP_850;
+ extern VMIME_EXPORT const char* const CP_852;
+ extern VMIME_EXPORT const char* const CP_853;
+ extern VMIME_EXPORT const char* const CP_855;
+ extern VMIME_EXPORT const char* const CP_857;
+ extern VMIME_EXPORT const char* const CP_858;
+ extern VMIME_EXPORT const char* const CP_860;
+ extern VMIME_EXPORT const char* const CP_861;
+ extern VMIME_EXPORT const char* const CP_862;
+ extern VMIME_EXPORT const char* const CP_863;
+ extern VMIME_EXPORT const char* const CP_864;
+ extern VMIME_EXPORT const char* const CP_865;
+ extern VMIME_EXPORT const char* const CP_866;
+ extern VMIME_EXPORT const char* const CP_869;
+ extern VMIME_EXPORT const char* const CP_874;
+ extern VMIME_EXPORT const char* const CP_1125;
+ extern VMIME_EXPORT const char* const CP_1250;
+ extern VMIME_EXPORT const char* const CP_1251;
+ extern VMIME_EXPORT const char* const CP_1252;
+ extern VMIME_EXPORT const char* const CP_1253;
+ extern VMIME_EXPORT const char* const CP_1254;
+ extern VMIME_EXPORT const char* const CP_1255;
+ extern VMIME_EXPORT const char* const CP_1256;
+ extern VMIME_EXPORT const char* const CP_1257;
+
+ extern VMIME_EXPORT const char* const US_ASCII;
+
+ extern VMIME_EXPORT const char* const UTF_7;
+ extern VMIME_EXPORT const char* const UTF_8;
+ extern VMIME_EXPORT const char* const UTF_16;
+ extern VMIME_EXPORT const char* const UTF_32;
+
+ extern VMIME_EXPORT const char* const WINDOWS_1250;
+ extern VMIME_EXPORT const char* const WINDOWS_1251;
+ extern VMIME_EXPORT const char* const WINDOWS_1252;
+ extern VMIME_EXPORT const char* const WINDOWS_1253;
+ extern VMIME_EXPORT const char* const WINDOWS_1254;
+ extern VMIME_EXPORT const char* const WINDOWS_1255;
+ extern VMIME_EXPORT const char* const WINDOWS_1256;
+ extern VMIME_EXPORT const char* const WINDOWS_1257;
+ extern VMIME_EXPORT const char* const WINDOWS_1258;
+
+ extern VMIME_EXPORT const char* const IDNA;
+ }
+
+ /** Constants for standard field names. */
+ namespace fields {
+
+ extern VMIME_EXPORT const char* const RECEIVED;
+ extern VMIME_EXPORT const char* const FROM;
+ extern VMIME_EXPORT const char* const SENDER;
+ extern VMIME_EXPORT const char* const REPLY_TO;
+ extern VMIME_EXPORT const char* const TO;
+ extern VMIME_EXPORT const char* const CC;
+ extern VMIME_EXPORT const char* const BCC;
+ extern VMIME_EXPORT const char* const DATE;
+ extern VMIME_EXPORT const char* const SUBJECT;
+ extern VMIME_EXPORT const char* const ORGANIZATION;
+ extern VMIME_EXPORT const char* const USER_AGENT;
+ extern VMIME_EXPORT const char* const DELIVERED_TO;
+ extern VMIME_EXPORT const char* const RETURN_PATH;
+ extern VMIME_EXPORT const char* const MIME_VERSION;
+ extern VMIME_EXPORT const char* const MESSAGE_ID;
+ extern VMIME_EXPORT const char* const CONTENT_TYPE;
+ extern VMIME_EXPORT const char* const CONTENT_TRANSFER_ENCODING;
+ extern VMIME_EXPORT const char* const CONTENT_DESCRIPTION;
+ extern VMIME_EXPORT const char* const CONTENT_DISPOSITION;
+ extern VMIME_EXPORT const char* const CONTENT_ID;
+ extern VMIME_EXPORT const char* const CONTENT_LOCATION;
+ extern VMIME_EXPORT const char* const IN_REPLY_TO;
+ extern VMIME_EXPORT const char* const REFERENCES;
+
+ extern VMIME_EXPORT const char* const X_MAILER;
+ extern VMIME_EXPORT const char* const X_PRIORITY;
+
+ // RFC-3798: Message Disposition Notification
+ extern VMIME_EXPORT const char* const ORIGINAL_MESSAGE_ID;
+ extern VMIME_EXPORT const char* const DISPOSITION_NOTIFICATION_TO;
+ extern VMIME_EXPORT const char* const DISPOSITION_NOTIFICATION_OPTIONS;
+ extern VMIME_EXPORT const char* const DISPOSITION;
+ extern VMIME_EXPORT const char* const FAILURE;
+ extern VMIME_EXPORT const char* const ERROR;
+ extern VMIME_EXPORT const char* const WARNING;
+ extern VMIME_EXPORT const char* const ORIGINAL_RECIPIENT;
+ extern VMIME_EXPORT const char* const FINAL_RECIPIENT;
+ extern VMIME_EXPORT const char* const REPORTING_UA;
+ extern VMIME_EXPORT const char* const MDN_GATEWAY;
+ }
+
+ /** Constants for disposition action modes (RFC-3978). */
+ namespace dispositionActionModes {
+
+ /** User implicitely displayed or deleted the message (filter or
+ * any other automatic action). */
+ extern VMIME_EXPORT const char* const AUTOMATIC;
+
+ /** User explicitely displayed or deleted the message (manual action). */
+ extern VMIME_EXPORT const char* const MANUAL;
+ }
+
+ /** Constants for disposition sending modes (RFC-3798). */
+ 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;
+
+ /** User explicitly gave permission for this particular MDN to be sent. */
+ extern VMIME_EXPORT const char* const SENT_MANUALLY;
+ }
+
+ /** Constants for disposition types (RFC-3798). */
+ namespace dispositionTypes {
+
+ /** Message has been displayed to the user. */
+ extern VMIME_EXPORT const char* const DISPLAYED;
+ /** Message has been deleted without being displayed. */
+ extern VMIME_EXPORT const char* const DELETED;
+ /** Message has been denied. */
+ extern VMIME_EXPORT const char* const DENIED;
+ }
+
+ /** Constants for disposition modifiers (RFC-3798). */
+ 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;
+ }
+}
+
+
+#endif // VMIME_CONSTANTS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/contentDisposition.cpp b/vmime-master/src/vmime/contentDisposition.cpp
new file mode 100644
index 0000000..1602273
--- /dev/null
+++ b/vmime-master/src/vmime/contentDisposition.cpp
@@ -0,0 +1,144 @@
+//
+// 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.
+//
+
+#include "vmime/contentDisposition.hpp"
+#include "vmime/utility/stringUtils.hpp"
+
+
+namespace vmime {
+
+
+contentDisposition::contentDisposition()
+ : m_name(contentDispositionTypes::INLINE) {
+
+}
+
+
+contentDisposition::contentDisposition(const string& name)
+ : m_name(utility::stringUtils::toLower(name)) {
+
+}
+
+
+contentDisposition::contentDisposition(const contentDisposition& type)
+ : 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)
+ )
+ );
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void contentDisposition::generateImpl(
+ const generationContext& /* ctx */,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ os << m_name;
+
+ if (newLinePos) {
+ *newLinePos = curLinePos + m_name.length();
+ }
+}
+
+
+contentDisposition& contentDisposition::operator=(const string& name) {
+
+ m_name = utility::stringUtils::toLower(name);
+ 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 !(*this == value);
+}
+
+
+shared_ptr <component> contentDisposition::clone() const {
+
+ return make_shared <contentDisposition>(*this);
+}
+
+
+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) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+const string& contentDisposition::getName() const {
+
+ return m_name;
+}
+
+
+void contentDisposition::setName(const string& name) {
+
+ m_name = name;
+}
+
+
+const std::vector <shared_ptr <component> > contentDisposition::getChildComponents() {
+
+ return std::vector <shared_ptr <component> >();
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/contentDisposition.hpp b/vmime-master/src/vmime/contentDisposition.hpp
new file mode 100644
index 0000000..636c0fb
--- /dev/null
+++ b/vmime-master/src/vmime/contentDisposition.hpp
@@ -0,0 +1,99 @@
+//
+// 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_CONTENTDISPOSITION_HPP_INCLUDED
+#define VMIME_CONTENTDISPOSITION_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/headerFieldValue.hpp"
+
+
+namespace vmime {
+
+
+/** Content disposition (basic type).
+ */
+class VMIME_EXPORT contentDisposition : public headerFieldValue {
+
+public:
+
+ contentDisposition();
+ contentDisposition(const string& name);
+ contentDisposition(const contentDisposition& disp);
+
+
+ /** Return the content disposition type.
+ * See the constants in vmime::dispositionTypes.
+ *
+ * @return name of the disposition type (eg. "inline")
+ */
+ const string& getName() const;
+
+ /** Set the content disposition type.
+ * See the constants in vmime::dispositionTypes.
+ *
+ * @param name name of the disposition type
+ */
+ void setName(const string& name);
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ contentDisposition& operator=(const contentDisposition& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+
+ contentDisposition& operator=(const string& name);
+
+ bool operator==(const contentDisposition& value) const;
+ bool operator!=(const contentDisposition& value) const;
+
+private:
+
+ string m_name;
+
+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 generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_CONTENTDISPOSITION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/contentDispositionField.cpp b/vmime-master/src/vmime/contentDispositionField.cpp
new file mode 100644
index 0000000..7e50680
--- /dev/null
+++ b/vmime-master/src/vmime/contentDispositionField.cpp
@@ -0,0 +1,162 @@
+//
+// 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.
+//
+
+#include "vmime/contentDispositionField.hpp"
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+
+
+contentDispositionField::contentDispositionField() {
+
+}
+
+
+contentDispositionField::contentDispositionField(contentDispositionField&)
+ : parameterizedHeaderField() {
+
+}
+
+
+bool contentDispositionField::hasCreationDate() const {
+
+ return hasParameter("creation-date");
+}
+
+
+const datetime contentDispositionField::getCreationDate() const {
+
+ shared_ptr <parameter> param = findParameter("creation-date");
+
+ if (param) {
+ return param->getValueAs <datetime>();
+ } else {
+ return datetime::now();
+ }
+}
+
+
+void contentDispositionField::setCreationDate(const datetime& creationDate) {
+
+ getParameter("creation-date")->setValue(creationDate);
+}
+
+
+bool contentDispositionField::hasModificationDate() const {
+
+ return hasParameter("modification-date");
+}
+
+
+const datetime contentDispositionField::getModificationDate() const {
+
+ shared_ptr <parameter> param = findParameter("modification-date");
+
+ if (param) {
+ return param->getValueAs <datetime>();
+ } else {
+ return datetime::now();
+ }
+}
+
+
+void contentDispositionField::setModificationDate(const datetime& modificationDate) {
+
+ getParameter("modification-date")->setValue(modificationDate);
+}
+
+
+bool contentDispositionField::hasReadDate() const {
+
+ return hasParameter("read-date");
+}
+
+
+const datetime contentDispositionField::getReadDate() const {
+
+ shared_ptr <parameter> param = findParameter("read-date");
+
+ if (param) {
+ return param->getValueAs <datetime>();
+ } else {
+ return datetime::now();
+ }
+}
+
+
+void contentDispositionField::setReadDate(const datetime& readDate) {
+
+ getParameter("read-date")->setValue(readDate);
+}
+
+
+bool contentDispositionField::hasFilename() const {
+
+ return hasParameter("filename");
+}
+
+
+const word contentDispositionField::getFilename() const {
+
+ shared_ptr <parameter> param = findParameter("filename");
+
+ if (param) {
+ return param->getValue();
+ } else {
+ return word();
+ }
+}
+
+
+void contentDispositionField::setFilename(const word& filename) {
+
+ getParameter("filename")->setValue(filename);
+}
+
+
+bool contentDispositionField::hasSize() const {
+
+ return hasParameter("size");
+}
+
+
+const string contentDispositionField::getSize() const {
+
+ shared_ptr <parameter> param = findParameter("size");
+
+ if (param) {
+ return param->getValue().getBuffer();
+ } else {
+ return "";
+ }
+}
+
+
+void contentDispositionField::setSize(const string& size) {
+
+ getParameter("size")->setValue(word(size, vmime::charsets::US_ASCII));
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/contentDispositionField.hpp b/vmime-master/src/vmime/contentDispositionField.hpp
new file mode 100644
index 0000000..89eb907
--- /dev/null
+++ b/vmime-master/src/vmime/contentDispositionField.hpp
@@ -0,0 +1,146 @@
+//
+// 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_CONTENTDISPOSITIONFIELD_HPP_INCLUDED
+#define VMIME_CONTENTDISPOSITIONFIELD_HPP_INCLUDED
+
+
+#include "vmime/parameterizedHeaderField.hpp"
+
+#include "vmime/contentDisposition.hpp"
+#include "vmime/dateTime.hpp"
+#include "vmime/word.hpp"
+
+
+namespace vmime {
+
+
+/** Describes presentation information, as per RFC-2183.
+ */
+class VMIME_EXPORT contentDispositionField : public parameterizedHeaderField {
+
+ friend class headerFieldFactory;
+
+protected:
+
+ contentDispositionField();
+ contentDispositionField(contentDispositionField&);
+
+public:
+
+ /** Test whether the "creation-date" parameter is set.
+ *
+ * @return true if the "creation-date" parameter is set, or false otherwise
+ */
+ bool hasCreationDate() const;
+
+ /** Return the value of the "creation-date" parameter.
+ *
+ * @return value of the "creation-date" parameter
+ */
+ const datetime getCreationDate() const;
+
+ /** Set the value of the "creation-date" parameter.
+ *
+ * @param creationDate new value for the "creation-date" parameter
+ */
+ void setCreationDate(const datetime& creationDate);
+
+ /** Test whether the "modification-date" parameter is set.
+ *
+ * @return true if the "modification-date" parameter is set, or false otherwise
+ */
+ bool hasModificationDate() const;
+
+ /** Return the value of the "modification-date" parameter.
+ *
+ * @return value of the "modification-date" parameter
+ */
+ const datetime getModificationDate() const;
+
+ /** Set the value of the "modification-date" parameter.
+ *
+ * @param modificationDate new value for the "modification-date" parameter
+ */
+ void setModificationDate(const datetime& modificationDate);
+
+ /** Test whether the "read-date" parameter is set.
+ *
+ * @return true if the "read-date" parameter is set, or false otherwise
+ */
+ bool hasReadDate() const;
+
+ /** Return the value of the "read-date" parameter.
+ *
+ * @return value of the "read-date" parameter
+ */
+ const datetime getReadDate() const;
+
+ /** Set the value of the "read-date" parameter.
+ *
+ * @param readDate new value for the "read-date" parameter
+ */
+ void setReadDate(const datetime& readDate);
+
+ /** Test whether the "filename" parameter is set.
+ *
+ * @return true if the "filename" parameter is set, or false otherwise
+ */
+ bool hasFilename() const;
+
+ /** Return the value of the "filename" parameter.
+ *
+ * @return value of the "filename" parameter
+ */
+ const word getFilename() const;
+
+ /** Set the value of the "filename" parameter.
+ *
+ * @param filename new value for the "filename" parameter
+ */
+ void setFilename(const word& filename);
+
+ /** Test whether the "size" parameter is set.
+ *
+ * @return true if the "size" parameter is set, or false otherwise
+ */
+ bool hasSize() const;
+
+ /** Return the value of the "size" parameter.
+ *
+ * @return value of the "size" parameter
+ */
+ const string getSize() const;
+
+ /** Set the value of the "size" parameter.
+ *
+ * @param size new value for the "size" parameter
+ */
+ void setSize(const string& size);
+};
+
+
+} // vmime
+
+
+#endif // VMIME_CONTENTDISPOSITIONFIELD_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/contentHandler.cpp b/vmime-master/src/vmime/contentHandler.cpp
new file mode 100644
index 0000000..0a0e6ad
--- /dev/null
+++ b/vmime-master/src/vmime/contentHandler.cpp
@@ -0,0 +1,39 @@
+//
+// 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.
+//
+
+#include "vmime/contentHandler.hpp"
+
+
+namespace vmime {
+
+
+// No encoding = "binary" encoding
+const encoding contentHandler::NO_ENCODING(encodingTypes::BINARY);
+
+
+contentHandler::~contentHandler() {
+
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/contentHandler.hpp b/vmime-master/src/vmime/contentHandler.hpp
new file mode 100644
index 0000000..2d344ee
--- /dev/null
+++ b/vmime-master/src/vmime/contentHandler.hpp
@@ -0,0 +1,147 @@
+//
+// 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_CONTENTHANDLER_HPP_INCLUDED
+#define VMIME_CONTENTHANDLER_HPP_INCLUDED
+
+
+#include <limits>
+
+#include "vmime/base.hpp"
+#include "vmime/utility/progressListener.hpp"
+#include "vmime/encoding.hpp"
+#include "vmime/mediaType.hpp"
+
+
+namespace vmime {
+
+
+class VMIME_EXPORT contentHandler : public object {
+
+public:
+
+ /** Used to specify that enclosed data is not encoded. */
+ static const vmime::encoding NO_ENCODING;
+
+
+ virtual ~contentHandler();
+
+ /** Return a copy of this object.
+ *
+ * @return copy of this object
+ */
+ virtual shared_ptr <contentHandler> clone() const = 0;
+
+ /** Output the contents into the specified stream. Data will be
+ * encoded before being written into the stream. This is used internally
+ * by the body object to generate the message, you may not need to use
+ * this (see contentHandler::extract() if you want to get the contents).
+ *
+ * @param os output stream
+ * @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;
+
+ /** Extract the contents into the specified stream. If needed, data
+ * will be decoded before being written into the stream.
+ *
+ * @throw exceptions::no_encoder_available if the encoding is
+ * not supported
+ * @param os output stream
+ * @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;
+
+ /** Extract the contents into the specified stream, without
+ * decoding it. It may be useful in case the encoding is not
+ * supported and you want to extract raw data.
+ *
+ * @param os output stream
+ * @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;
+
+ /** Returns the actual length of data. WARNING: this can return 0 if no
+ * length was specified when setting data of this object, or if the
+ * length is not known).
+ *
+ * @return length of data
+ */
+ virtual size_t getLength() const = 0;
+
+ /** Returns 'true' if data managed by this object is encoded.
+ *
+ * @return true if data is encoded, false otherwise
+ */
+ virtual bool isEncoded() const = 0;
+
+ /** Returns the encoding used for data (or "binary" if not encoded).
+ *
+ * @return encoding used for data
+ */
+ virtual const vmime::encoding& getEncoding() const = 0;
+
+ /** Returns 'true' if there is no data set.
+ *
+ * @return true if no data is managed by this object, false otherwise
+ */
+ virtual bool isEmpty() const = 0;
+
+ /** Indicates whether the extract() method can be called multiple times.
+ *
+ * @return true if the data can be extracted multiple times, or false
+ * if not (ie. streamed data from socket)
+ */
+ virtual bool isBuffered() const = 0;
+
+ /** Gives a hint about the kind of data managed by this object.
+ *
+ * @param type content media type
+ */
+ virtual void setContentTypeHint(const mediaType& type) = 0;
+
+ /** Returns a hint about the kind of data managed by this object.
+ *
+ * @return type content media type
+ */
+ virtual const mediaType getContentTypeHint() const = 0;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_CONTENTHANDLER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/contentTypeField.cpp b/vmime-master/src/vmime/contentTypeField.cpp
new file mode 100644
index 0000000..ec4971d
--- /dev/null
+++ b/vmime-master/src/vmime/contentTypeField.cpp
@@ -0,0 +1,114 @@
+//
+// 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.
+//
+
+#include "vmime/contentTypeField.hpp"
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+
+
+contentTypeField::contentTypeField() {
+
+}
+
+
+contentTypeField::contentTypeField(contentTypeField&)
+ : parameterizedHeaderField() {
+
+}
+
+
+bool contentTypeField::hasBoundary() const {
+
+ return hasParameter("boundary");
+}
+
+
+const string contentTypeField::getBoundary() const {
+
+ shared_ptr <parameter> param = findParameter("boundary");
+
+ if (param) {
+ return param->getValue().getBuffer();
+ } else {
+ return "";
+ }
+}
+
+
+void contentTypeField::setBoundary(const string& boundary) {
+
+ getParameter("boundary")->setValue(word(boundary, vmime::charsets::US_ASCII));
+}
+
+
+bool contentTypeField::hasCharset() const {
+
+ return hasParameter("charset");
+}
+
+
+const charset contentTypeField::getCharset() const {
+
+ shared_ptr <parameter> param = findParameter("charset");
+
+ if (param) {
+ return param->getValueAs <charset>();
+ } else {
+ return charset();
+ }
+}
+
+
+void contentTypeField::setCharset(const charset& ch) {
+
+ getParameter("charset")->setValue(ch);
+}
+
+
+bool contentTypeField::hasReportType() const {
+
+ return hasParameter("report-type");
+}
+
+
+const string contentTypeField::getReportType() const {
+
+ shared_ptr <parameter> param = findParameter("report-type");
+
+ if (param) {
+ return param->getValue().getBuffer();
+ } else {
+ return "";
+ }
+}
+
+
+void contentTypeField::setReportType(const string& reportType) {
+
+ getParameter("report-type")->setValue(word(reportType, vmime::charsets::US_ASCII));
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/contentTypeField.hpp b/vmime-master/src/vmime/contentTypeField.hpp
new file mode 100644
index 0000000..a63e7da
--- /dev/null
+++ b/vmime-master/src/vmime/contentTypeField.hpp
@@ -0,0 +1,113 @@
+//
+// 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_CONTENTTYPEFIELD_HPP_INCLUDED
+#define VMIME_CONTENTTYPEFIELD_HPP_INCLUDED
+
+
+#include "vmime/parameterizedHeaderField.hpp"
+
+#include "vmime/mediaType.hpp"
+#include "vmime/charset.hpp"
+
+
+namespace vmime {
+
+
+class VMIME_EXPORT contentTypeField : public parameterizedHeaderField {
+
+ friend class headerFieldFactory;
+
+protected:
+
+ contentTypeField();
+ contentTypeField(contentTypeField&);
+
+public:
+
+ /** Test whether the "boundary" parameter is set.
+ *
+ * @return true if the "boundary" parameter is set, or false otherwise
+ */
+ bool hasBoundary() const;
+
+ /** Return the value of the "boundary" parameter. Boundary is a
+ * random string used to separate body parts.
+ *
+ * @return value of the "boundary" parameter
+ */
+ const string getBoundary() const;
+
+ /** Set the value of the "boundary" parameter. Boundary is a
+ * random string used to separate body parts. Normally, the
+ * boundary is generated automatically by VMime, you should
+ * not need to call this.
+ *
+ * @param boundary new value for the "boundary" parameter
+ */
+ void setBoundary(const string& boundary);
+
+ /** Test whether the "charset" parameter is set.
+ *
+ * @return true if the "charset" parameter is set, or false otherwise
+ */
+ bool hasCharset() const;
+
+ /** Return the value of the "charset" parameter. It specifies the
+ * charset used in the body part contents.
+ *
+ * @return value of the "charset" parameter
+ */
+ const charset getCharset() const;
+
+ /** Set the value of the "charset" parameter. It specifies the
+ * charset used in the body part contents.
+ *
+ * @param ch new value for the "charset" parameter
+ */
+ void setCharset(const charset& ch);
+
+ /** Test whether the "report-type" parameter is set.
+ *
+ * @return true if the "report-type" parameter is set, or false otherwise
+ */
+ bool hasReportType() const;
+
+ /** Return the value of the "report-type" parameter (RFC-1892).
+ *
+ * @return value of the "report-type" parameter
+ */
+ const string getReportType() const;
+
+ /** Set the value of the "report-type" parameter (RFC-1892).
+ *
+ * @param reportType new value for the "report-type" parameter
+ */
+ void setReportType(const string& reportType);
+};
+
+
+} // vmime
+
+
+#endif // VMIME_CONTENTTYPEFIELD_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/context.cpp b/vmime-master/src/vmime/context.cpp
new file mode 100644
index 0000000..3fc4941
--- /dev/null
+++ b/vmime-master/src/vmime/context.cpp
@@ -0,0 +1,86 @@
+//
+// 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.
+//
+
+#include "vmime/context.hpp"
+
+
+namespace vmime {
+
+
+context::context()
+ : m_internationalizedEmail(false) {
+
+}
+
+
+context::context(const context& ctx)
+ : object(),
+ m_internationalizedEmail(ctx.m_internationalizedEmail) {
+
+}
+
+
+context::~context() {
+
+}
+
+
+bool context::getInternationalizedEmailSupport() const {
+
+ return m_internationalizedEmail;
+}
+
+
+void context::setInternationalizedEmailSupport(const bool support) {
+
+ m_internationalizedEmail = support;
+}
+
+
+const charsetConverterOptions& context::getCharsetConversionOptions() const {
+
+ return m_charsetConvOptions;
+}
+
+
+void context::setCharsetConversionOptions(const charsetConverterOptions& opts) {
+
+ m_charsetConvOptions = opts;
+}
+
+
+context& context::operator=(const context& ctx) {
+
+ copyFrom(ctx);
+ return *this;
+}
+
+
+void context::copyFrom(const context& ctx) {
+
+ m_internationalizedEmail = ctx.m_internationalizedEmail;
+ m_charsetConvOptions = ctx.m_charsetConvOptions;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/context.hpp b/vmime-master/src/vmime/context.hpp
new file mode 100644
index 0000000..1d00950
--- /dev/null
+++ b/vmime-master/src/vmime/context.hpp
@@ -0,0 +1,120 @@
+//
+// 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_CONTEXT_HPP_INCLUDED
+#define VMIME_CONTEXT_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/charsetConverterOptions.hpp"
+
+
+namespace vmime {
+
+
+/** Holds configuration parameters used either for parsing or generating messages.
+ */
+class VMIME_EXPORT context : public object {
+
+public:
+
+ virtual ~context();
+
+ /** Returns whether support for Internationalized Email Headers (RFC-6532)
+ * is enabled.
+ *
+ * @return true if RFC-6532 support is enabled, false otherwise
+ */
+ bool getInternationalizedEmailSupport() const;
+
+ /** Enables or disables support for Internationalized Email Headers (RFC-6532).
+ * This is disabled by default, and should be used only with servers
+ * which support it (eg. SMTP servers with SMTPUTF8 extension).
+ *
+ * @param support true if RFC-6532 support is enabled, false otherwise
+ */
+ void setInternationalizedEmailSupport(const bool support);
+
+ /** Returns options used currently for charset conversions by the parser and/or
+ * the generator. See charsetConverterOptions class for more information.
+ *
+ * @return current charset conversion options
+ */
+ const charsetConverterOptions& getCharsetConversionOptions() const;
+
+ /** Sets the options used currently for charset conversions by the parser and/or
+ * the generator. See charsetConverterOptions class for more information.
+ *
+ * @param opts new charset conversion options
+ */
+ void setCharsetConversionOptions(const charsetConverterOptions& opts);
+
+ /** Switches between contexts temporarily.
+ */
+ template <typename CTX_CLASS>
+ class switcher {
+
+ public:
+
+ /** Switches to the specified context.
+ * Default context will temporarily use the data of the specified
+ * new context during the lifetime of this object.
+ *
+ * @param newCtx new context
+ */
+ switcher(CTX_CLASS& newCtx)
+ : m_oldCtxData(CTX_CLASS::getDefaultContext()), m_newCtx(&newCtx) {
+
+ CTX_CLASS::getDefaultContext().copyFrom(newCtx);
+ }
+
+ /** Restores back saved context.
+ */
+ ~switcher() {
+
+ CTX_CLASS::getDefaultContext().copyFrom(m_oldCtxData);
+ }
+
+ private:
+
+ CTX_CLASS m_oldCtxData;
+ CTX_CLASS* m_newCtx;
+ };
+
+protected:
+
+ context();
+ context(const context& ctx);
+
+ virtual context& operator=(const context& ctx);
+ void copyFrom(const context& ctx);
+
+ bool m_internationalizedEmail;
+ charsetConverterOptions m_charsetConvOptions;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_CONTEXT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/dateTime.cpp b/vmime-master/src/vmime/dateTime.cpp
new file mode 100644
index 0000000..fd44303
--- /dev/null
+++ b/vmime-master/src/vmime/dateTime.cpp
@@ -0,0 +1,925 @@
+//
+// 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.
+//
+
+#include <iomanip>
+
+#include "vmime/config.hpp"
+#include "vmime/dateTime.hpp"
+#include "vmime/platform.hpp"
+#include "vmime/parserHelpers.hpp"
+
+#include "vmime/utility/datetimeUtils.hpp"
+
+
+namespace vmime {
+
+/*
+
+ RFC #822:
+ 5. DATE AND TIME SPECIFICATION
+
+date-time = [ day "," ] date time ; dd mm yy
+ ; hh:mm:ss zzz
+day = "Mon" / "Tue" / "Wed" / "Thu" /
+ "Fri" / "Sat" / "Sun"
+
+date = 1*2DIGIT month 2DIGIT ; day month year
+ ; e.g. 20 Jun 82
+month = "Jan" / "Feb" / "Mar" / "Apr" /
+ "May" / "Jun" / "Jul" / "Aug" /
+ "Sep" / "Oct" / "Nov" / "Dec"
+
+time = hour zone ; ANSI and Military
+
+hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] ; 00:00:00 - 23:59:59
+
+zone = "UT" / "GMT" ; Universal Time
+ ; North American : UT
+ / "EST" / "EDT" ; Eastern: - 5/ - 4
+ / "CST" / "CDT" ; Central: - 6/ - 5
+ / "MST" / "MDT" ; Mountain: - 7/ - 6
+ / "PST" / "PDT" ; Pacific: - 8/ - 7
+ / 1ALPHA ; Military: Z = UT;
+ ; A:-1; (J not used)
+ ; M:-12; N:+1; Y:+12
+ / ( ("+" / "-") 4DIGIT ) ; Local differential
+ ; hours+min. (HHMM)
+*/
+
+
+void datetime::parseImpl(
+ const parsingContext& /* ctx */,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ const char* const pend = buffer.data() + end;
+ const char* p = buffer.data() + position;
+
+ // Parse the date and time value
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ if (p < pend) {
+
+ if (parserHelpers::isAlpha(*p)) {
+
+ // Ignore week day
+ while (p < pend && parserHelpers::isAlpha(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ if (p < pend && *p == ',') ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+
+ bool dayParsed = false;
+
+ if (parserHelpers::isAlpha(*p)) {
+
+ // Ill-formed date/time, this may be the month,
+ // so we skip day parsing (will be done later)
+
+ } else {
+
+ while (p < pend && !parserHelpers::isDigit(*p)) ++p;
+
+ if (p < pend && parserHelpers::isDigit(*p)) {
+
+ // Month day
+ int day = 0;
+
+ do {
+ day = day * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ m_day = (day >= 1 && day <= 31) ? day : 1;
+
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ } else {
+
+ m_day = 1;
+
+ // Skip everything to the next field
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+
+ dayParsed = true;
+ }
+
+ if (p < pend && parserHelpers::isAlpha(*p)) {
+
+ // Month
+ char_t month[4] = { 0 };
+ int monthLength = 0;
+
+ do {
+ month[monthLength++] = *p;
+ ++p;
+ } while (monthLength < 3 && p < pend && parserHelpers::isAlpha(*p));
+
+ while (p < pend && parserHelpers::isAlpha(*p)) ++p;
+
+ switch (month[0]) {
+
+ case 'a':
+ case 'A': {
+
+ if (month[1] == 'u' || month[1] == 'U')
+ m_month = AUGUST;
+ else
+ m_month = APRIL; // by default
+
+ break;
+ }
+ case 'd':
+ case 'D': {
+
+ m_month = DECEMBER;
+ break;
+ }
+ case 'f':
+ case 'F': {
+
+ m_month = FEBRUARY;
+ break;
+ }
+ case 'j':
+ case 'J': {
+
+ if (month[1] == 'u' || month[1] == 'U') {
+
+ if (month[2] == 'l' || month[2] == 'L') {
+ m_month = JULY;
+ } else { // if (month[2] == 'n' || month[2] == 'N')
+ m_month = JUNE;
+ }
+
+ } else {
+
+ m_month = JANUARY; // by default
+ }
+
+ break;
+ }
+ case 'm':
+ case 'M': {
+
+ if ((month[1] == 'a' || month[1] == 'A') &&
+ (month[2] == 'y' || month[2] == 'Y')) {
+
+ m_month = MAY;
+
+ } else {
+
+ m_month = MARCH; // by default
+ }
+
+ break;
+ }
+ case 'n':
+ case 'N': {
+
+ m_month = NOVEMBER;
+ break;
+ }
+ case 'o':
+ case 'O': {
+
+ m_month = OCTOBER;
+ break;
+ }
+ case 's':
+ case 'S': {
+
+ m_month = SEPTEMBER;
+ break;
+ }
+ default: {
+
+ m_month = JANUARY; // by default
+ break;
+ }
+ }
+
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ } else {
+
+ m_month = JANUARY;
+
+ if (parserHelpers::isDigit(*p)) {
+
+ // Here, we expected a month, but it maybe
+ // a ill-formed date, so try to parse a year
+ // (we don't skip anything).
+
+ } else {
+
+ // Skip everything to the next field
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+ }
+
+ if (!dayParsed && p < pend && parserHelpers::isDigit(*p)) {
+
+ // Month day
+ int day = 0;
+
+ do {
+ day = day * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ m_day = (day >= 1 && day <= 31) ? day : 1;
+
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+
+ if (p < pend && parserHelpers::isDigit(*p)) {
+
+ // Check for ill-formed date/time and try to recover
+ if (p + 2 < pend && *(p + 2) == ':') {
+
+ // Skip year (default to current), and advance
+ // to time parsing
+ m_year = now().getYear();
+
+ } else {
+
+ // Year
+ int year = 0;
+
+ do {
+ year = year * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ if (year < 70) m_year = year + 2000;
+ else if (year < 1000) m_year = year + 1900;
+ else m_year = year;
+
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+
+ } else {
+
+ m_year = 1970;
+
+ // Skip everything to the next field
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+
+ if (p < pend && parserHelpers::isDigit(*p)) {
+
+ // Hour
+ int hour = 0;
+
+ do {
+ hour = hour * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ m_hour = (hour >= 0 && hour <= 23) ? hour : 0;
+
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ if (p < pend && *p == ':') {
+
+ ++p;
+
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ if (p < pend && parserHelpers::isDigit(*p)) {
+
+ // Minute
+ int minute = 0;
+
+ do {
+ minute = minute * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ m_minute = (minute >= 0 && minute <= 59) ? minute : 0;
+
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ if (p < pend && *p == ':') {
+
+ ++p;
+
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ if (p < pend && parserHelpers::isDigit(*p)) {
+
+ // Second
+ int second = 0;
+
+ do {
+ second = second * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ m_second = (second >= 0 && second <= 59) ? second : 0;
+
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ } else {
+
+ m_second = 0;
+ }
+
+ } else {
+
+ m_second = 0;
+ }
+
+ } else {
+
+ m_minute = 0;
+ }
+
+ } else {
+
+ m_minute = 0;
+ }
+
+ } else {
+
+ m_hour = 0;
+
+ // Skip everything to the next field
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+
+ if (p + 1 < pend && (*p == '+' || *p == '-') && parserHelpers::isDigit(*(p + 1))) {
+
+ const char_t sign = *p;
+ ++p;
+
+ // Zone offset (in hour/minutes)
+ int offset = 0;
+
+ do {
+ offset = offset * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ const int hourOff = offset / 100;
+ const int minOff = offset % 100;
+
+ if (sign == '+') {
+ m_zone = hourOff * 60 + minOff;
+ } else {
+ m_zone = -(hourOff * 60 + minOff);
+ }
+
+ } else if (p < pend && isalpha(*p)) {
+
+ bool done = false;
+
+ // Zone offset (Time zone name)
+ char_t zone[4] = { 0 };
+ int zoneLength = 0;
+
+ do {
+ zone[zoneLength++] = *p;
+ ++p;
+ } while (zoneLength < 3 && p < pend);
+
+ switch (zone[0])
+ {
+ case 'c':
+ case 'C':
+ {
+ if (zoneLength >= 2)
+ {
+ if (zone[1] == 's' || zone[1] == 'S')
+ m_zone = CST;
+ else
+ m_zone = CDT;
+
+ done = true;
+ }
+
+ break;
+ }
+ case 'e':
+ case 'E':
+ {
+ if (zoneLength >= 2) {
+
+ if (zone[1] == 's' || zone[1] == 'S') {
+ m_zone = EST;
+ } else {
+ m_zone = EDT;
+ }
+
+ done = true;
+ }
+
+ break;
+ }
+ case 'm':
+ case 'M': {
+
+ if (zoneLength >= 2) {
+
+ if (zone[1] == 's' || zone[1] == 'S') {
+ m_zone = MST;
+ } else {
+ m_zone = MDT;
+ }
+
+ done = true;
+ }
+
+ break;
+ }
+ case 'p':
+ case 'P': {
+
+ if (zoneLength >= 2) {
+
+ if (zone[1] == 's' || zone[1] == 'S') {
+ m_zone = PST;
+ } else {
+ m_zone = PDT;
+ }
+
+ done = true;
+ }
+
+ break;
+ }
+ case 'g':
+ case 'G':
+ case 'u':
+ case 'U': {
+
+ if (zoneLength >= 2) {
+
+ m_zone = GMT; // = UTC
+ done = true;
+ }
+
+ break;
+ }
+
+ }
+
+ if (!done) {
+
+ const char_t z = zone[0];
+
+ // Military time zone
+ if (z != 'j' && z != 'J') {
+
+ typedef std::map <char_t, int> Map;
+ static const Map::value_type offsetMapInit[] = {
+
+ Map::value_type('a', -60),
+ Map::value_type('b', -120),
+ Map::value_type('c', -180),
+ Map::value_type('d', -240),
+ Map::value_type('e', -300),
+ Map::value_type('f', -360),
+ Map::value_type('g', -420),
+ Map::value_type('h', -480),
+ Map::value_type('i', -540),
+ Map::value_type('k', -600),
+ Map::value_type('l', -660),
+ Map::value_type('m', -720),
+
+ Map::value_type('n', 60),
+ Map::value_type('o', 120),
+ Map::value_type('p', 180),
+ Map::value_type('q', 240),
+ Map::value_type('r', 300),
+ Map::value_type('s', 360),
+ Map::value_type('t', 420),
+ Map::value_type('u', 480),
+ Map::value_type('v', 540),
+ Map::value_type('w', 600),
+ Map::value_type('x', 660),
+ Map::value_type('y', 720),
+
+ Map::value_type('z', 0),
+ };
+
+ static const Map offsetMap(
+ ::vmime::begin(offsetMapInit),
+ ::vmime::end(offsetMapInit)
+ );
+
+ Map::const_iterator pos =
+ offsetMap.find(parserHelpers::toLower(z));
+
+ if (pos != offsetMap.end()) {
+ m_zone = (*pos).second;
+ } else {
+ m_zone = GMT;
+ }
+
+ } else {
+
+ m_zone = GMT;
+ }
+ }
+
+ } else {
+
+ m_zone = 0;
+ }
+
+ } else {
+
+ m_year = 1970;
+ m_month = JANUARY;
+ m_day = 1;
+
+ m_hour = 0;
+ m_minute = 0;
+ m_second = 0;
+
+ m_zone = 0;
+ }
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void datetime::generateImpl(
+ const generationContext& /* ctx */,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ static const char* dayNames[] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+ };
+ static const char* monthNames[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+
+ const int z = ((m_zone < 0) ? -m_zone : m_zone);
+ const int zh = z / 60;
+ const int zm = z % 60;
+
+ std::ostringstream oss;
+ oss.imbue(std::locale::classic());
+
+ oss << dayNames[getWeekDay()] << ", "
+ << m_day << " " << monthNames[m_month - 1] << " " << m_year
+ << " " << std::setfill('0') << std::setw(2) << m_hour << ":"
+ << std::setfill('0') << std::setw(2) << m_minute << ":"
+ << std::setfill('0') << std::setw(2) << m_second
+ << " " << ((m_zone < 0) ? '-' : '+') << std::setfill('0') << std::setw(2) << zh
+ << std::setfill('0') << std::setw(2) << zm;
+
+ const string& str = oss.str();
+ os << str;
+
+ if (newLinePos) {
+ *newLinePos = curLinePos + str.length();
+ }
+}
+
+
+datetime::datetime()
+ : m_year(1970), m_month(1), m_day(1),
+ m_hour(0), m_minute(0), m_second(0), m_zone(0) {
+
+}
+
+
+datetime::datetime(const int year, const int month, const int day)
+ : m_year(year), m_month(month), m_day(day),
+ m_hour(0), m_minute(0), m_second(0), m_zone(0) {
+
+}
+
+
+datetime::datetime(
+ const int year,
+ const int month,
+ const int day,
+ const int hour,
+ const int minute,
+ const int second,
+ const int zone
+)
+ : m_year(year),
+ m_month(month),
+ m_day(day),
+ m_hour(hour),
+ m_minute(minute),
+ m_second(second),
+ m_zone(zone) {
+
+}
+
+
+datetime::datetime(const datetime& d)
+ : headerFieldValue(),
+ m_year(d.m_year),
+ m_month(d.m_month),
+ m_day(d.m_day),
+ m_hour(d.m_hour),
+ m_minute(d.m_minute),
+ m_second(d.m_second),
+ m_zone(d.m_zone) {
+
+}
+
+
+datetime::datetime(const time_t t, const int zone) {
+
+#if VMIME_HAVE_LOCALTIME_S
+
+ struct tm tms;
+
+ if (!gmtime_s(&tms, &t)) {
+ localtime_s(&tms, &t);
+ }
+
+#elif VMIME_HAVE_LOCALTIME_R
+ struct tm tms;
+
+ if (!gmtime_r(&t, &tms)) {
+ localtime_r(&t, &tms);
+ }
+
+#else
+
+ struct tm* gtm = gmtime(&t);
+ struct tm* ltm = localtime(&t);
+
+ struct tm tms;
+
+ if (gtm) {
+ tms = *gtm;
+ } else if (ltm) {
+ tms = *ltm;
+ }
+
+#endif
+
+ m_year = tms.tm_year + 1900;
+ m_month = tms.tm_mon + 1;
+ m_day = tms.tm_mday;
+ m_hour = tms.tm_hour;
+ m_minute = tms.tm_min;
+ m_second = tms.tm_sec;
+ m_zone = zone;
+}
+
+
+datetime::datetime(const string& date) {
+
+ parse(date);
+}
+
+
+datetime::~datetime() {
+
+}
+
+
+void datetime::copyFrom(const component& other) {
+
+ const datetime& d = dynamic_cast <const datetime&>(other);
+
+ m_year = d.m_year;
+ m_month = d.m_month;
+ m_day = d.m_day;
+ m_hour = d.m_hour;
+ m_minute = d.m_minute;
+ m_second = d.m_second;
+ m_zone = d.m_zone;
+}
+
+
+datetime& datetime::operator=(const datetime& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+datetime& datetime::operator=(const string& s) {
+
+ parse(s);
+ return *this;
+}
+
+
+void datetime::getTime(int& hour, int& minute, int& second, int& zone) const {
+
+ hour = m_hour;
+ minute = m_minute;
+ second = m_second;
+ zone = m_zone;
+}
+
+
+void datetime::getTime(int& hour, int& minute, int& second) const {
+
+ hour = m_hour;
+ minute = m_minute;
+ second = m_second;
+}
+
+
+void datetime::getDate(int& year, int& month, int& day) const {
+
+ year = m_year;
+ month = m_month;
+ day = m_day;
+}
+
+
+void datetime::setTime(
+ const int hour,
+ const int minute,
+ const int second,
+ const int zone
+) {
+
+ m_hour = hour;
+ m_minute = minute;
+ m_second = second;
+ m_zone = zone;
+}
+
+
+void datetime::setDate(
+ const int year,
+ const int month,
+ const int day
+) {
+
+ m_year = year;
+ m_month = month;
+ m_day = day;
+}
+
+
+const datetime datetime::now() {
+
+ return platform::getHandler()->getCurrentLocalTime();
+}
+
+
+shared_ptr <component> datetime::clone() const {
+
+ return make_shared <datetime>(*this);
+}
+
+
+const std::vector <shared_ptr <component> > datetime::getChildComponents() {
+
+ return std::vector <shared_ptr <component> >();
+}
+
+
+int datetime::getYear() const { return m_year; }
+int datetime::getMonth() const { return m_month; }
+int datetime::getDay() const { return m_day; }
+int datetime::getHour() const { return m_hour; }
+int datetime::getMinute() const { return m_minute; }
+int datetime::getSecond() const { return m_second; }
+int datetime::getZone() const { return m_zone; }
+int datetime::getWeekDay() const { return utility::datetimeUtils::getDayOfWeek(m_year, m_month, m_day); }
+int datetime::getWeek() const { return utility::datetimeUtils::getWeekOfYear(m_year, m_month, m_day); }
+
+void datetime::setYear(const int year) { m_year = year; }
+void datetime::setMonth(const int month) { m_month = std::min(std::max(month, 1), 12); }
+void datetime::setDay(const int day) { m_day = day; }
+void datetime::setHour(const int hour) { m_hour = hour; }
+void datetime::setMinute(const int minute) { m_minute = minute; }
+void datetime::setSecond(const int second) { m_second = second; }
+void datetime::setZone(const int zone) { m_zone = zone; }
+
+
+bool datetime::operator==(const datetime& other) const {
+
+ const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this);
+ const datetime ut2 = utility::datetimeUtils::toUniversalTime(other);
+
+ return ut1.m_year == ut2.m_year &&
+ ut1.m_month == ut2.m_month &&
+ ut1.m_day == ut2.m_day &&
+ ut1.m_hour == ut2.m_hour &&
+ ut1.m_minute == ut2.m_minute &&
+ ut1.m_second == ut2.m_second;
+}
+
+
+bool datetime::operator!=(const datetime& other) const {
+
+ const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this);
+ const datetime ut2 = utility::datetimeUtils::toUniversalTime(other);
+
+ return ut1.m_year != ut2.m_year ||
+ ut1.m_month != ut2.m_month ||
+ ut1.m_day != ut2.m_day ||
+ ut1.m_hour != ut2.m_hour ||
+ ut1.m_minute != ut2.m_minute ||
+ ut1.m_second != ut2.m_second;
+}
+
+
+bool datetime::operator<(const datetime& other) const {
+
+ const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this);
+ const datetime ut2 = utility::datetimeUtils::toUniversalTime(other);
+
+ return (ut1.m_year < ut2.m_year) ||
+ ((ut1.m_year == ut2.m_year) && ((ut1.m_month < ut2.m_month) ||
+ ((ut1.m_month == ut2.m_month) && ((ut1.m_day < ut2.m_day) ||
+ ((ut1.m_day == ut2.m_day) && ((ut1.m_hour < ut2.m_hour) ||
+ ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute < ut2.m_minute) ||
+ ((ut1.m_minute == ut2.m_minute) && ((ut1.m_second < ut2.m_second)))))))))));
+}
+
+
+bool datetime::operator<=(const datetime& other) const {
+
+ const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this);
+ const datetime ut2 = utility::datetimeUtils::toUniversalTime(other);
+
+ return (ut1.m_year < ut2.m_year) ||
+ ((ut1.m_year == ut2.m_year) && ((ut1.m_month < ut2.m_month) ||
+ ((ut1.m_month == ut2.m_month) && ((ut1.m_day < ut2.m_day) ||
+ ((ut1.m_day == ut2.m_day) && ((ut1.m_hour < ut2.m_hour) ||
+ ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute < ut2.m_minute) ||
+ ((ut1.m_minute == ut2.m_minute) && ((ut1.m_second <= ut2.m_second)))))))))));
+}
+
+
+bool datetime::operator>(const datetime& other) const {
+
+ const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this);
+ const datetime ut2 = utility::datetimeUtils::toUniversalTime(other);
+
+ return (ut1.m_year > ut2.m_year) ||
+ ((ut1.m_year == ut2.m_year) && ((ut1.m_month > ut2.m_month) ||
+ ((ut1.m_month == ut2.m_month) && ((ut1.m_day > ut2.m_day) ||
+ ((ut1.m_day == ut2.m_day) && ((ut1.m_hour > ut2.m_hour) ||
+ ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute > ut2.m_minute) ||
+ ((ut1.m_minute == ut2.m_minute) && (ut1.m_second > ut2.m_second))))))))));
+}
+
+
+bool datetime::operator>=(const datetime& other) const {
+
+ const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this);
+ const datetime ut2 = utility::datetimeUtils::toUniversalTime(other);
+
+ return (ut1.m_year > ut2.m_year) ||
+ ((ut1.m_year == ut2.m_year) && ((ut1.m_month > ut2.m_month) ||
+ ((ut1.m_month == ut2.m_month) && ((ut1.m_day > ut2.m_day) ||
+ ((ut1.m_day == ut2.m_day) && ((ut1.m_hour > ut2.m_hour) ||
+ ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute > ut2.m_minute) ||
+ ((ut1.m_minute == ut2.m_minute) && (ut1.m_second >= ut2.m_second))))))))));
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/dateTime.hpp b/vmime-master/src/vmime/dateTime.hpp
new file mode 100644
index 0000000..64e8dad
--- /dev/null
+++ b/vmime-master/src/vmime/dateTime.hpp
@@ -0,0 +1,275 @@
+//
+// 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_DATETIME_HPP_INCLUDED
+#define VMIME_DATETIME_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/headerFieldValue.hpp"
+
+#include <ctime>
+
+
+namespace vmime {
+
+
+/** Date and time (basic type).
+ */
+class VMIME_EXPORT datetime : public headerFieldValue {
+
+public:
+
+ // Constructors
+ datetime();
+ datetime(
+ const int year,
+ const int month,
+ const int day
+ );
+ datetime(
+ const int year,
+ const int month,
+ const int day,
+ const int hour,
+ const int minute,
+ const int second,
+ const int zone = GMT
+ );
+ datetime(const datetime& d);
+ datetime(const string& date);
+ datetime(const time_t t, const int zone = GMT);
+
+ // Destructor
+ ~datetime();
+
+ // Some time zones (in minutes)
+ enum TimeZones {
+
+ GMT_12 = -720, // GMT-12h
+ GMT_11 = -660, // GMT-11h
+ GMT_10 = -600, // GMT-10h
+ GMT_9 = -540, // GMT-9h
+ GMT_8 = -480, // GMT-8h
+ GMT_7 = -420, // GMT-7h
+ GMT_6 = -360, // GMT-6h
+ GMT_5 = -300, // GMT-5h
+ GMT_4 = -240, // GMT-4h
+ GMT_3 = -180, // GMT-3h
+ GMT_2 = -120, // GMT-2h
+ GMT_1 = -60, // GMT-1h
+ GMT = 0, // GMT
+ GMT1 = 60, // GMT+1h
+ GMT2 = 120, // GMT+2h
+ GMT3 = 180, // GMT+3h
+ GMT4 = 240, // GMT+4h
+ GMT5 = 300, // GMT+5h
+ GMT6 = 360, // GMT+6h
+ GMT7 = 420, // GMT+7h
+ GMT8 = 480, // GMT+8h
+ GMT9 = 540, // GMT+9h
+ GMT10 = 600, // GMT+10h
+ GMT11 = 660, // GMT+11h
+ GMT12 = 720, // GMT+12h
+
+ UT = GMT, // Universal Time
+
+ EST = GMT_5, // Eastern
+ EDT = GMT_4,
+ CST = GMT_6, // Central
+ CDT = GMT_5,
+ MST = GMT_7, // Mountain
+ MDT = GMT_6,
+ PST = GMT_8, // Pacific
+ PDT = GMT_7,
+
+ // Military time zones
+ A = GMT_1,
+ B = GMT_2,
+ C = GMT_3,
+ D = GMT_4,
+ E = GMT_5,
+ F = GMT_6,
+ G = GMT_7,
+ H = GMT_8,
+ I = GMT_9, // J not used
+ K = GMT_10,
+ L = GMT_11,
+ M = GMT_12,
+
+ N = GMT1,
+ O = GMT2,
+ P = GMT3,
+ Q = GMT4,
+ R = GMT5,
+ S = GMT6,
+ T = GMT7,
+ U = GMT8,
+ V = GMT9,
+ W = GMT10,
+ X = GMT11,
+ Y = GMT12,
+
+ Z = GMT
+ };
+
+ // Months list
+ enum Months {
+
+ // Long
+ JANUARY = 1,
+ FEBRUARY = 2,
+ MARCH = 3,
+ APRIL = 4,
+ MAY = 5,
+ JUNE = 6,
+ JULY = 7,
+ AUGUST = 8,
+ SEPTEMBER = 9,
+ OCTOBER = 10,
+ NOVEMBER = 11,
+ DECEMBER = 12,
+
+ // Short
+ JAN = 1,
+ FEB = 2,
+ MAR = 3,
+ APR = 4,
+ JUN = 6,
+ JUL = 7,
+ AUG = 8,
+ SEP = 9,
+ OCT = 10,
+ NOV = 11,
+ DEC = 12
+ };
+
+ // Days of week list
+ enum DaysOfWeek {
+
+ // Long
+ SUNDAY = 0,
+ MONDAY = 1,
+ TUESDAY = 2,
+ WEDNESDAY = 3,
+ THURSDAY = 4,
+ FRIDAY = 5,
+ SATURDAY = 6,
+
+ // Short
+ SUN = 0,
+ MON = 1,
+ TUE = 2,
+ WED = 3,
+ THU = 4,
+ FRI = 5,
+ SAT = 6
+ };
+
+private:
+
+ // Date components
+ int m_year;
+ int m_month;
+ int m_day;
+
+ // Time components
+ int m_hour;
+ int m_minute;
+ int m_second;
+ int m_zone;
+
+public:
+
+ // Get
+ int getYear() const;
+ int getMonth() const;
+ int getDay() const;
+ int getHour() const;
+ int getMinute() const;
+ int getSecond() const;
+ int getZone() const;
+ int getWeekDay() const;
+ int getWeek() const;
+
+ void getTime(int& hour, int& minute, int& second, int& zone) const;
+ void getTime(int& hour, int& minute, int& second) const;
+ void getDate(int& year, int& month, int& day) const;
+
+ // Set
+ void setYear(const int year);
+ void setMonth(const int month);
+ void setDay(const int day);
+ void setHour(const int hour);
+ void setMinute(const int minute);
+ void setSecond(const int second);
+ void setZone(const int zone);
+
+ void setTime(const int hour = 0, const int minute = 0, const int second = 0, const int zone = GMT);
+ void setDate(const int year, const int month, const int day);
+
+ // Assignment
+ datetime& operator=(const datetime& other);
+ datetime& operator=(const string& s);
+
+ void copyFrom(const component& other);
+
+ shared_ptr <component> clone() const;
+
+ // Comparison
+ bool operator==(const datetime& other) const;
+ bool operator!=(const datetime& other) const;
+ bool operator<(const datetime& other) const;
+ bool operator<=(const datetime& other) const;
+ bool operator>(const datetime& other) const;
+ bool operator>=(const datetime& other) const;
+
+ // Current date and time
+ static const datetime now();
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+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 generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_DATETIME_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/defaultAttachment.cpp b/vmime-master/src/vmime/defaultAttachment.cpp
new file mode 100644
index 0000000..36eaa3c
--- /dev/null
+++ b/vmime-master/src/vmime/defaultAttachment.cpp
@@ -0,0 +1,164 @@
+//
+// 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.
+//
+
+#include "vmime/defaultAttachment.hpp"
+
+#include "vmime/contentDisposition.hpp"
+#include "vmime/contentDispositionField.hpp"
+#include "vmime/encoding.hpp"
+
+
+namespace vmime {
+
+
+defaultAttachment::defaultAttachment() {
+
+}
+
+
+defaultAttachment::defaultAttachment(
+ const shared_ptr <const contentHandler>& data,
+ const encoding& enc,
+ const mediaType& type,
+ const text& desc,
+ const word& name
+)
+ : m_type(type),
+ m_desc(desc),
+ m_data(data),
+ m_encoding(enc),
+ m_name(name) {
+
+}
+
+
+defaultAttachment::defaultAttachment(
+ const shared_ptr <const contentHandler>& data,
+ const mediaType& type,
+ const text& desc,
+ const word& name
+)
+ : m_type(type),
+ m_desc(desc),
+ m_data(data),
+ m_encoding(encoding::decide(data)),
+ m_name(name) {
+
+}
+
+
+defaultAttachment::defaultAttachment(const defaultAttachment& attach)
+ : attachment(),
+ m_type(attach.m_type),
+ m_desc(attach.m_desc),
+ m_data(vmime::clone(attach.m_data)),
+ m_encoding(attach.m_encoding),
+ m_name(attach.m_name) {
+
+}
+
+
+defaultAttachment::~defaultAttachment() {
+
+}
+
+
+defaultAttachment& defaultAttachment::operator=(const defaultAttachment& attach) {
+
+ m_type = attach.m_type;
+ m_desc = attach.m_desc;
+ m_name = attach.m_name;
+ m_data = vmime::clone(attach.m_data);
+ m_encoding = attach.m_encoding;
+
+ return *this;
+}
+
+
+void defaultAttachment::generateIn(const shared_ptr <bodyPart>& parent) const {
+
+ // Create and append a new part for this attachment
+ shared_ptr <bodyPart> part = make_shared <bodyPart>();
+ parent->getBody()->appendPart(part);
+
+ generatePart(part);
+}
+
+
+void defaultAttachment::generatePart(const shared_ptr <bodyPart>& part) const {
+
+ // Set header fields
+ part->getHeader()->ContentType()->setValue(m_type);
+ if (!m_desc.isEmpty()) part->getHeader()->ContentDescription()->setValue(m_desc);
+ part->getHeader()->ContentTransferEncoding()->setValue(m_encoding);
+ part->getHeader()->ContentDisposition()->setValue(contentDisposition(contentDispositionTypes::ATTACHMENT));
+ dynamicCast <contentDispositionField>(part->getHeader()->ContentDisposition())->setFilename(m_name);
+
+ // Set contents
+ part->getBody()->setContents(m_data);
+}
+
+
+const mediaType defaultAttachment::getType() const {
+
+ return m_type;
+}
+
+
+const text defaultAttachment::getDescription() const {
+
+ return m_desc;
+}
+
+
+const word defaultAttachment::getName() const {
+
+ return m_name;
+}
+
+
+const shared_ptr <const contentHandler> defaultAttachment::getData() const {
+
+ return m_data;
+}
+
+
+const encoding defaultAttachment::getEncoding() const {
+
+ return m_encoding;
+}
+
+
+shared_ptr <const object> defaultAttachment::getPart() const {
+
+ return null;
+}
+
+
+shared_ptr <const header> defaultAttachment::getHeader() const {
+
+ return null;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/defaultAttachment.hpp b/vmime-master/src/vmime/defaultAttachment.hpp
new file mode 100644
index 0000000..ce1c603
--- /dev/null
+++ b/vmime-master/src/vmime/defaultAttachment.hpp
@@ -0,0 +1,99 @@
+//
+// 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_DEFAULTATTACHMENT_HPP_INCLUDED
+#define VMIME_DEFAULTATTACHMENT_HPP_INCLUDED
+
+
+#include "vmime/attachment.hpp"
+#include "vmime/encoding.hpp"
+
+
+namespace vmime {
+
+
+/** Default implementation for attachments.
+ */
+class VMIME_EXPORT defaultAttachment : public attachment {
+
+protected:
+
+ // For use in derived classes.
+ defaultAttachment();
+
+public:
+
+ defaultAttachment(
+ const shared_ptr <const contentHandler>& data,
+ const encoding& enc,
+ const mediaType& type,
+ const text& desc = NULL_TEXT,
+ const word& name = NULL_WORD
+ );
+
+ defaultAttachment(
+ const shared_ptr <const contentHandler>& data,
+ const mediaType& type,
+ const text& desc = NULL_TEXT,
+ const word& name = NULL_WORD
+ );
+
+ defaultAttachment(const defaultAttachment& attach);
+
+ ~defaultAttachment();
+
+ defaultAttachment& operator=(const defaultAttachment& attach);
+
+ const mediaType getType() const;
+ const text getDescription() const;
+ const word getName() const;
+ const shared_ptr <const contentHandler> getData() const;
+ const encoding getEncoding() const;
+
+ shared_ptr <const object> getPart() const;
+
+ shared_ptr <const header> getHeader() const;
+
+protected:
+
+ mediaType m_type; /**< Media type (eg. "application/octet-stream") */
+ text m_desc; /**< Description (eg. "The image you requested") */
+ shared_ptr <const contentHandler> m_data; /**< Attachment data (eg. the file contents) */
+ encoding m_encoding; /**< Encoding */
+ word m_name; /**< Name/filename (eg. "sunset.jpg") */
+
+private:
+
+ // No need to override "generateIn", use "generatePart" instead (see below).
+ void generateIn(const shared_ptr <bodyPart>& parent) const;
+
+protected:
+
+ virtual void generatePart(const shared_ptr <bodyPart>& part) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_DEFAULTATTACHMENT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/disposition.cpp b/vmime-master/src/vmime/disposition.cpp
new file mode 100644
index 0000000..6e10cb9
--- /dev/null
+++ b/vmime-master/src/vmime/disposition.cpp
@@ -0,0 +1,351 @@
+//
+// 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.
+//
+
+#include "vmime/disposition.hpp"
+
+#include "vmime/parserHelpers.hpp"
+#include "vmime/utility/stringUtils.hpp"
+
+
+namespace vmime {
+
+
+disposition::disposition() {
+
+}
+
+
+disposition::disposition(
+ const string& actionMode,
+ const string& sendingMode,
+ const string& type,
+ const string& modifier
+)
+ : m_actionMode(actionMode),
+ m_sendingMode(sendingMode),
+ m_type(type) {
+
+ m_modifiers.push_back(modifier);
+}
+
+
+shared_ptr <component> disposition::clone() const {
+
+ shared_ptr <disposition> disp = make_shared <disposition>();
+
+ disp->m_actionMode = m_actionMode;
+ disp->m_sendingMode = m_sendingMode;
+ disp->m_type = m_type;
+ disp->m_modifiers.resize(m_modifiers.size());
+
+ std::copy(m_modifiers.begin(), m_modifiers.end(), disp->m_modifiers.begin());
+
+ return disp;
+}
+
+
+void disposition::copyFrom(const component& other) {
+
+ const disposition& disp = dynamic_cast <const disposition&>(other);
+
+ m_actionMode = disp.m_actionMode;
+ m_sendingMode = disp.m_sendingMode;
+ m_type = disp.m_type;
+ m_modifiers.resize(disp.m_modifiers.size());
+
+ std::copy(disp.m_modifiers.begin(), disp.m_modifiers.end(), m_modifiers.begin());
+}
+
+
+disposition& disposition::operator=(const disposition& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+const std::vector <shared_ptr <component> > disposition::getChildComponents() {
+
+ return std::vector <shared_ptr <component> >();
+}
+
+
+void disposition::setActionMode(const string& mode) {
+
+ m_actionMode = mode;
+}
+
+
+const string& disposition::getActionMode() const {
+
+ return m_actionMode;
+}
+
+
+void disposition::setSendingMode(const string& mode) {
+
+ m_sendingMode = mode;
+}
+
+
+const string& disposition::getSendingMode() const {
+
+ return m_sendingMode;
+}
+
+
+void disposition::setType(const string& type) {
+
+ m_type = type;
+}
+
+
+const string& disposition::getType() const {
+
+ return m_type;
+}
+
+
+void disposition::addModifier(const string& modifier) {
+
+ if (!hasModifier(modifier)) {
+ m_modifiers.push_back(utility::stringUtils::toLower(modifier));
+ }
+}
+
+
+void disposition::removeModifier(const string& modifier) {
+
+ const string modifierLC = utility::stringUtils::toLower(modifier);
+
+ for (std::vector <string>::iterator it = m_modifiers.begin() ;
+ it != m_modifiers.end() ; ++it) {
+
+ if (*it == modifierLC) {
+ m_modifiers.erase(it);
+ break;
+ }
+ }
+}
+
+
+void disposition::removeAllModifiers() {
+
+ m_modifiers.clear();
+}
+
+
+bool disposition::hasModifier(const string& modifier) const {
+
+ const string modifierLC = utility::stringUtils::toLower(modifier);
+
+ for (std::vector <string>::const_iterator it = m_modifiers.begin() ;
+ it != m_modifiers.end() ; ++it) {
+
+ if (*it == modifierLC) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+const std::vector <string> disposition::getModifierList() const {
+
+ return m_modifiers;
+}
+
+
+void disposition::parseImpl(
+ const parsingContext& /* ctx */,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ // disposition-mode ";" disposition-type
+ // [ "/" disposition-modifier *( "," disposition-modifier ) ]
+ //
+ // disposition-mode = action-mode "/" sending-mode
+
+ size_t pos = position;
+
+ while (pos < end && parserHelpers::isSpace(buffer[pos])) {
+ ++pos;
+ }
+
+ // -- disposition-mode
+ const size_t modeStart = pos;
+ size_t modeEnd = pos;
+
+ while (pos < end && buffer[pos] != ';') {
+ ++modeEnd;
+ ++pos;
+ }
+
+ while (modeEnd > modeStart && parserHelpers::isSpace(buffer[modeEnd - 1])) {
+ --modeEnd;
+ }
+
+ const string mode = string(buffer.begin() + modeStart, buffer.begin() + modeEnd);
+ const size_t slash = mode.find('/');
+
+ if (slash != string::npos) {
+
+ m_actionMode = string(mode.begin(), mode.begin() + slash);
+ m_sendingMode = string(mode.begin() + slash + 1, mode.end());
+
+ } else {
+
+ m_actionMode = mode;
+ m_sendingMode.clear();
+ }
+
+ if (pos < end) {
+ // Skip ';'
+ ++pos;
+ }
+
+ while (pos < end && parserHelpers::isSpace(buffer[pos])) {
+ ++pos;
+ }
+
+ // -- disposition-type
+ const size_t typeStart = pos;
+ size_t typeEnd = pos;
+
+ while (pos < end && buffer[pos] != '/') {
+ ++typeEnd;
+ ++pos;
+ }
+
+ while (typeEnd > typeStart && parserHelpers::isSpace(buffer[typeEnd - 1])) {
+ --typeEnd;
+ }
+
+ m_type = string(buffer.begin() + typeStart, buffer.begin() + typeEnd);
+
+ m_modifiers.clear();
+
+ if (pos < end) { // modifiers follow
+
+ // Skip '/'
+ ++pos;
+
+ while (pos < end) {
+
+ while (pos < end && parserHelpers::isSpace(buffer[pos])) {
+ ++pos;
+ }
+
+ const size_t modifierStart = pos;
+ size_t modifierEnd = pos;
+
+ while (pos < end && buffer[pos] != ',') {
+ ++modifierEnd;
+ ++pos;
+ }
+
+ while (modifierEnd > modifierStart && parserHelpers::isSpace(buffer[modifierEnd - 1])) {
+ --modifierEnd;
+ }
+
+ if (modifierEnd > modifierStart) {
+
+ m_modifiers.push_back(
+ string(
+ buffer.begin() + modifierStart,
+ buffer.begin() + modifierEnd
+ )
+ );
+ }
+
+ // Skip ','
+ if (pos < end) {
+ ++pos;
+ }
+ }
+ }
+
+ if (newPosition) {
+ *newPosition = pos;
+ }
+}
+
+
+void disposition::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ size_t pos = curLinePos;
+
+ const string actionMode = (m_actionMode.empty() ? "automatic-action" : m_actionMode);
+ const string sendingMode = (m_sendingMode.empty() ? "MDN-sent-automatically" : m_sendingMode);
+
+ os << actionMode << "/" << sendingMode << ";";
+ pos += actionMode.length() + 1 + sendingMode.length() + 1;
+
+ if (pos > ctx.getMaxLineLength()) {
+ os << NEW_LINE_SEQUENCE;
+ pos = NEW_LINE_SEQUENCE_LENGTH;
+ }
+
+ const string type = (m_type.empty() ? "displayed" : m_type);
+
+ os << type;
+ pos += type.length();
+
+ if (m_modifiers.size() >= 1) {
+
+ for (std::vector <string>::size_type i = 0, n = 0 ; i < m_modifiers.size() ; ++i) {
+
+ const string mod = utility::stringUtils::trim(m_modifiers[i]);
+
+ if (!mod.empty()) {
+
+ if (n == 0) {
+ os << "/";
+ } else {
+ os << ",";
+ }
+
+ os << mod;
+ pos += 1 + mod.length();
+
+ ++n;
+ }
+ }
+ }
+
+ if (newLinePos) {
+ *newLinePos = pos;
+ }
+}
+
+
+}
diff --git a/vmime-master/src/vmime/disposition.hpp b/vmime-master/src/vmime/disposition.hpp
new file mode 100644
index 0000000..d4b023b
--- /dev/null
+++ b/vmime-master/src/vmime/disposition.hpp
@@ -0,0 +1,163 @@
+//
+// 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_DISPOSITION_HPP_INCLUDED
+#define VMIME_DISPOSITION_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/headerFieldValue.hpp"
+
+#include <vector>
+
+
+namespace vmime {
+
+
+/** Disposition - from RFC-3798 (basic type).
+ */
+class VMIME_EXPORT disposition : public headerFieldValue {
+
+public:
+
+ disposition();
+ disposition(
+ const string& actionMode,
+ const string& sendingMode,
+ const string& type,
+ const string& modifier
+ );
+
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ disposition& operator=(const disposition& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+
+ /** Set the disposition action mode.
+ * See the constants in vmime::dispositionActionModes.
+ *
+ * @param mode disposition action mode
+ */
+ void setActionMode(const string& mode);
+
+ /** Return the disposition action mode.
+ * See the constants in vmime::dispositionActionModes.
+ *
+ * @return disposition action mode
+ */
+ const string& getActionMode() const;
+
+ /** Set the disposition sending mode.
+ * See the constants in vmime::dispositionSendingModes.
+ *
+ * @param mode disposition sending mode
+ */
+ void setSendingMode(const string& mode);
+
+ /** Return the disposition sending mode.
+ * See the constants in vmime::dispositionSendingModes.
+ *
+ * @return disposition sending mode
+ */
+ const string& getSendingMode() const;
+
+ /** Set the disposition type.
+ * See the constants in vmime::dispositionTypes.
+ *
+ * @param type disposition type
+ */
+ void setType(const string& type);
+
+ /** Return the disposition type.
+ * See the constants in vmime::dispositionTypes.
+ *
+ * @return disposition type
+ */
+ const string& getType() const;
+
+ /** Add a disposition modifier if it does not exist.
+ * See the constants in vmime::dispositionModifiers.
+ *
+ * @param modifier modifier to add
+ */
+ void addModifier(const string& modifier);
+
+ /** Remove the specified disposition modifier.
+ * See the constants in vmime::dispositionModifiers.
+ *
+ * @param modifier modifier to remove
+ */
+ void removeModifier(const string& modifier);
+
+ /** Remove all disposition modifiers.
+ */
+ void removeAllModifiers();
+
+ /** Test whether a disposition modifier is set.
+ *
+ * @param modifier modifier to test
+ * @return true if the specified modifier is set, false otherwise
+ */
+ bool hasModifier(const string& modifier) const;
+
+ /** Return the list of modifiers.
+ *
+ * @return list of modifiers
+ */
+ const std::vector <string> getModifierList() const;
+
+private:
+
+ string m_actionMode;
+ string m_sendingMode;
+ string m_type;
+
+ std::vector <string> m_modifiers;
+
+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 generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_DISPOSITION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/emailAddress.cpp b/vmime-master/src/vmime/emailAddress.cpp
new file mode 100644
index 0000000..1be678a
--- /dev/null
+++ b/vmime-master/src/vmime/emailAddress.cpp
@@ -0,0 +1,708 @@
+//
+// 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.
+//
+
+#include "vmime/emailAddress.hpp"
+
+#include "vmime/platform.hpp"
+
+#include "vmime/parserHelpers.hpp"
+#include "vmime/utility/outputStreamAdapter.hpp"
+#include "vmime/utility/outputStreamStringAdapter.hpp"
+#include "vmime/utility/stringUtils.hpp"
+
+
+namespace vmime {
+
+
+/** Decode an IDNA-encoded domain name ("xn--5rtw95l.xn--wgv71a")
+ * to a fully decoded domain name in UTF-8 ("黒川.日本").
+ *
+ * @param idnaDomain domain name encoded with IDNA
+ * @return decoded domain name in UTF-8
+ */
+static const string domainNameFromIDNA(const string& idnaDomain) {
+
+ std::ostringstream domainName;
+ size_t p = 0;
+
+ for (size_t n = idnaDomain.find('.', p) ;
+ (n = idnaDomain.find('.', p)) != string::npos ; p = n + 1) {
+
+ const string encodedPart(idnaDomain.begin() + p, idnaDomain.begin() + n);
+
+ if (encodedPart.length() > 4 &&
+ encodedPart[0] == 'x' && encodedPart[1] == 'n' &&
+ encodedPart[2] == '-' && encodedPart[3] == '-') {
+
+ string decodedPart;
+ charset::convert(
+ encodedPart, decodedPart,
+ vmime::charsets::IDNA, vmime::charsets::UTF_8
+ );
+
+ domainName << decodedPart << '.';
+
+ } else {
+
+ domainName << encodedPart << '.'; // not encoded
+ }
+ }
+
+ if (p < idnaDomain.length()) {
+
+ const string encodedPart(idnaDomain.begin() + p, idnaDomain.end());
+
+ if (encodedPart.length() > 4 &&
+ encodedPart[0] == 'x' && encodedPart[1] == 'n' &&
+ encodedPart[2] == '-' && encodedPart[3] == '-') {
+
+ string decodedPart;
+ charset::convert(
+ encodedPart, decodedPart,
+ vmime::charsets::IDNA, vmime::charsets::UTF_8
+ );
+
+ domainName << decodedPart;
+
+ } else {
+
+ domainName << encodedPart; // not encoded
+ }
+ }
+
+ return domainName.str();
+}
+
+
+/** Encode an UTF-8 domain name ("黒川.日本") to an IDNA-encoded
+ * domain name ("xn--5rtw95l.xn--wgv71a").
+ *
+ * @param domainName domain name in UTF-8
+ * @return domain name encoded with IDNA
+ */
+static const string domainNameToIDNA(const string& domainName) {
+
+ std::ostringstream idnaDomain;
+ size_t p = 0;
+
+ for (size_t n = domainName.find('.', p) ;
+ (n = domainName.find('.', p)) != string::npos ; p = n + 1) {
+
+ string idnaPart;
+ charset::convert(
+ string(domainName.begin() + p, domainName.begin() + n), idnaPart,
+ vmime::charsets::UTF_8, vmime::charsets::IDNA
+ );
+
+ idnaDomain << idnaPart << '.';
+ }
+
+ if (p < domainName.length()) {
+
+ string idnaPart;
+ charset::convert(
+ string(domainName.begin() + p, domainName.end()), idnaPart,
+ vmime::charsets::UTF_8, vmime::charsets::IDNA
+ );
+
+ idnaDomain << idnaPart;
+ }
+
+ return idnaDomain.str();
+}
+
+
+
+
+emailAddress::emailAddress() {
+
+}
+
+
+emailAddress::emailAddress(const emailAddress& eml)
+ : component(),
+ m_localName(eml.m_localName),
+ m_domainName(eml.m_domainName) {
+
+}
+
+
+emailAddress::emailAddress(const string& email) {
+
+ parse(email);
+}
+
+
+emailAddress::emailAddress(const char* email) {
+
+ parse(email);
+}
+
+
+emailAddress::emailAddress(const string& localName, const string& domainName)
+ : component(),
+ m_localName(word(localName, vmime::charsets::UTF_8)),
+ m_domainName(word(domainName, vmime::charsets::UTF_8)) {
+
+}
+
+
+emailAddress::emailAddress(const word& localName, const word& domainName)
+ : component(),
+ m_localName(localName),
+ m_domainName(domainName) {
+
+}
+
+
+void emailAddress::parseImpl(
+ const parsingContext& /* ctx */,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ const char* const pend = buffer.data() + end;
+ const char* const pstart = buffer.data() + position;
+ const char* p = pstart;
+
+ enum ParserStates {
+ State_Before,
+ State_LocalPartStart,
+ State_LocalPartMiddle,
+ State_LocalPartComment,
+ State_LocalPartQuoted,
+ State_LocalPartRFC2047Start,
+ State_LocalPartRFC2047Middle,
+ State_LocalPartRFC2047MiddleQM,
+ State_LocalPartRFC2047End,
+ State_DomainPartStart,
+ State_DomainPartMiddle,
+ State_DomainPartComment,
+ State_End,
+ State_Error
+ } state = State_Before;
+
+ std::ostringstream localPart;
+ std::ostringstream domainPart;
+
+ bool escapeNext = false; // for quoting
+ bool prevIsDot = false;
+ bool atFound = false;
+ bool stop = false;
+ int commentLevel = 0;
+ bool localPartIsRFC2047 = false;
+
+ while (p < pend && !stop) {
+
+ const char c = *p;
+
+ if ((localPart.str().length() + domainPart.str().length()) >= 256) {
+ state = State_Error;
+ break;
+ }
+
+ switch (state) {
+
+ case State_Before:
+
+ if (parserHelpers::isSpace(c)) {
+ ++p;
+ } else {
+ state = State_LocalPartStart;
+ }
+
+ break;
+
+ case State_LocalPartStart:
+
+ if (c == '"') {
+
+ state = State_LocalPartQuoted;
+ ++p;
+
+ } else if (c == '=') {
+
+ state = State_LocalPartRFC2047Start;
+ ++p;
+
+ } else if (c == '(') {
+
+ state = State_LocalPartComment;
+ ++commentLevel;
+ ++p;
+
+ } else {
+
+ state = State_LocalPartMiddle;
+ localPart << c;
+ ++p;
+ }
+
+ break;
+
+ case State_LocalPartComment:
+
+ if (escapeNext) {
+
+ escapeNext = false;
+ ++p;
+
+ } else if (c == '\\') {
+
+ escapeNext = true;
+ ++p;
+
+ } else if (c == '(') {
+
+ ++commentLevel;
+ ++p;
+
+ } else if (c == ')') {
+
+ if (--commentLevel == 0) {
+ // End of comment
+ state = State_LocalPartMiddle;
+ }
+
+ ++p;
+
+ } else {
+
+ // Comment continues
+ ++p;
+ }
+
+ break;
+
+ case State_LocalPartQuoted:
+
+ if (escapeNext) {
+
+ escapeNext = false;
+
+ if (c == '"' || c == '\\') {
+
+ localPart << c;
+ ++p;
+
+ } else {
+
+ // This char cannot be escaped
+ state = State_Error;
+ }
+
+ } else if (c == '"') {
+
+ // End of quoted string
+ state = State_LocalPartMiddle;
+ ++p;
+
+ } else if (c == '\\') {
+
+ escapeNext = true;
+ ++p;
+
+ } else {
+
+ localPart << c;
+ ++p;
+ }
+
+ break;
+
+ case State_LocalPartRFC2047Start:
+
+ if (c == '?') {
+
+ state = State_LocalPartRFC2047Middle;
+ localPart << "=?";
+ localPartIsRFC2047 = true;
+ ++p;
+
+ } else {
+
+ state = State_LocalPartMiddle;
+ localPart << '=';
+ localPart << c;
+ ++p;
+ }
+
+ break;
+
+ case State_LocalPartMiddle:
+
+ if (c == '.') {
+
+ prevIsDot = true;
+ localPart << c;
+ ++p;
+
+ } else if (c == '"' && prevIsDot) {
+
+ prevIsDot = false;
+ state = State_LocalPartQuoted;
+ ++p;
+
+ } else if (c == '(') {
+
+ // By allowing comments anywhere in the local part,
+ // we are more permissive than RFC-2822
+ state = State_LocalPartComment;
+ ++commentLevel;
+ ++p;
+
+ } else if (c == '@') {
+
+ atFound = true;
+ state = State_DomainPartStart;
+ ++p;
+
+ } else if (parserHelpers::isSpace(c)) {
+
+ // Allow not specifying domain part
+ state = State_End;
+
+ } else {
+
+ prevIsDot = false;
+ localPart << c;
+ ++p;
+ }
+
+ break;
+
+ case State_LocalPartRFC2047Middle:
+
+ if (c == '?') {
+
+ state = State_LocalPartRFC2047MiddleQM;
+ ++p;
+
+ } else {
+
+ localPart << c;
+ ++p;
+ }
+
+ break;
+
+ case State_LocalPartRFC2047MiddleQM:
+
+ if (c == '=') {
+
+ // End of RFC-2047 encoded word
+ state = State_LocalPartRFC2047End;
+ localPart << "?=";
+ ++p;
+
+ } else {
+
+ state = State_LocalPartRFC2047Middle;
+ localPart << '?';
+ localPart << c;
+ ++p;
+ }
+
+ break;
+
+ case State_LocalPartRFC2047End:
+
+ if (c == '@') {
+
+ atFound = true;
+ state = State_DomainPartStart;
+ ++p;
+
+ } else {
+
+ state = State_End;
+ }
+
+ break;
+
+ case State_DomainPartStart:
+
+ if (c == '(') {
+
+ state = State_DomainPartComment;
+ ++commentLevel;
+ ++p;
+
+ } else {
+
+ state = State_DomainPartMiddle;
+ domainPart << c;
+ ++p;
+ }
+
+ break;
+
+ case State_DomainPartMiddle:
+
+ if (parserHelpers::isSpace(c)) {
+
+ state = State_End;
+
+ } else if (c == '(') {
+
+ // By allowing comments anywhere in the domain part,
+ // we are more permissive than RFC-2822
+ state = State_DomainPartComment;
+ ++commentLevel;
+ ++p;
+
+ } else {
+
+ domainPart << c;
+ ++p;
+ }
+
+ break;
+
+ case State_DomainPartComment:
+
+ if (escapeNext) {
+
+ escapeNext = false;
+ ++p;
+
+ } else if (c == '\\') {
+
+ escapeNext = true;
+ ++p;
+
+ } else if (c == '(') {
+
+ ++commentLevel;
+ ++p;
+
+ } else if (c == ')') {
+
+ if (--commentLevel == 0) {
+
+ // End of comment
+ state = State_DomainPartMiddle;
+ }
+
+ ++p;
+
+ } else {
+
+ // Comment continues
+ ++p;
+ }
+
+ break;
+
+ case State_End:
+ case State_Error:
+
+ stop = true;
+ break;
+ }
+ }
+
+ if (p == pend && state != State_Error) {
+
+ if (state == State_DomainPartMiddle) {
+ state = State_End;
+ } else if (state == State_LocalPartMiddle) {
+ state = State_End; // allow not specifying domain part
+ }
+ }
+
+ if (state != State_End) {
+
+ m_localName = word("invalid", vmime::charsets::UTF_8);
+ m_domainName = word("invalid", vmime::charsets::UTF_8);
+
+ } else {
+
+ // If the domain part is missing, use local host name
+ if (domainPart.str().empty() && !atFound) {
+ domainPart << platform::getHandler()->getHostName();
+ }
+
+ if (localPartIsRFC2047) {
+ m_localName.parse(localPart.str());
+ } else {
+ m_localName = word(localPart.str(), vmime::charsets::UTF_8);
+ }
+
+ m_domainName = word(domainNameFromIDNA(domainPart.str()), vmime::charsets::UTF_8);
+ }
+
+ setParsedBounds(position, p - pend);
+
+ if (newPosition) {
+ *newPosition = p - pend;
+ }
+}
+
+
+void emailAddress::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ string localPart, domainPart;
+
+ if (ctx.getInternationalizedEmailSupport() &&
+ (!utility::stringUtils::is7bit(m_localName.getBuffer()) ||
+ !utility::stringUtils::is7bit(m_domainName.getBuffer()))) {
+
+ // Local part
+ string localPartUTF8(m_localName.getConvertedText(vmime::charsets::UTF_8));
+ word localPartWord(localPartUTF8, vmime::charsets::UTF_8);
+
+ vmime::utility::outputStreamStringAdapter os(localPart);
+ localPartWord.generate(ctx, os, 0, NULL, text::FORCE_NO_ENCODING | text::QUOTE_IF_NEEDED, NULL);
+
+ // Domain part
+ domainPart = m_domainName.getConvertedText(vmime::charsets::UTF_8);
+
+ } else {
+
+ // Local part
+ vmime::utility::outputStreamStringAdapter os(localPart);
+ m_localName.generate(ctx, os, 0, NULL, text::QUOTE_IF_NEEDED, NULL);
+
+ // Domain part as IDNA
+ domainPart = domainNameToIDNA(m_domainName.getConvertedText(vmime::charsets::UTF_8));
+ }
+
+ os << localPart
+ << "@"
+ << domainPart;
+
+ if (newLinePos) {
+
+ *newLinePos = curLinePos
+ + localPart.length()
+ + 1 // @
+ + domainPart.length();
+ }
+}
+
+
+bool emailAddress::operator==(const class emailAddress& eml) const {
+
+ return m_localName == eml.m_localName &&
+ m_domainName == eml.m_domainName;
+}
+
+
+bool emailAddress::operator!=(const class emailAddress& eml) const {
+
+ return !(*this == eml);
+}
+
+
+void emailAddress::copyFrom(const component& other) {
+
+ const emailAddress& source = dynamic_cast <const emailAddress&>(other);
+
+ m_localName = source.m_localName;
+ m_domainName = source.m_domainName;
+}
+
+
+emailAddress& emailAddress::operator=(const emailAddress& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+shared_ptr <component>emailAddress::clone() const {
+
+ return make_shared <emailAddress>(*this);
+}
+
+
+const word& emailAddress::getLocalName() const {
+
+ return m_localName;
+}
+
+
+void emailAddress::setLocalName(const word& localName) {
+
+ m_localName = localName;
+}
+
+
+const word& emailAddress::getDomainName() const {
+
+ return m_domainName;
+}
+
+
+void emailAddress::setDomainName(const word& domainName) {
+
+ m_domainName = domainName;
+}
+
+
+const std::vector <shared_ptr <component> > emailAddress::getChildComponents() {
+
+ return std::vector <shared_ptr <component> >();
+}
+
+
+bool emailAddress::isEmpty() const {
+
+ return m_localName.isEmpty();
+}
+
+
+const string emailAddress::toString() const {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter adapter(oss);
+
+ generationContext ctx(generationContext::getDefaultContext());
+ ctx.setMaxLineLength(lineLengthLimits::infinite);
+
+ generateImpl(ctx, adapter, 0, NULL);
+
+ return oss.str();
+}
+
+
+const text emailAddress::toText() const {
+
+ text txt;
+ txt.appendWord(make_shared <vmime::word>(m_localName));
+ txt.appendWord(make_shared <vmime::word>("@", vmime::charsets::US_ASCII));
+ txt.appendWord(make_shared <vmime::word>(m_domainName));
+
+ return txt;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/emailAddress.hpp b/vmime-master/src/vmime/emailAddress.hpp
new file mode 100644
index 0000000..7824996
--- /dev/null
+++ b/vmime-master/src/vmime/emailAddress.hpp
@@ -0,0 +1,135 @@
+//
+// 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_EMAILADDRESS_HPP_INCLUDED
+#define VMIME_EMAILADDRESS_HPP_INCLUDED
+
+
+#include "vmime/component.hpp"
+#include "vmime/text.hpp"
+
+
+namespace vmime {
+
+
+/** An email address: local name and domain name (basic type).
+ */
+class VMIME_EXPORT emailAddress : public component {
+
+public:
+
+ emailAddress();
+ emailAddress(const emailAddress& eml);
+ emailAddress(const string& email);
+ emailAddress(const char* email);
+ emailAddress(const string& localName, const string& domainName);
+ emailAddress(const word& localName, const word& domainName);
+
+ /** Return the local name of the address.
+ *
+ * @return local name of the address
+ */
+ const word& getLocalName() const;
+
+ /** Set the local name of the address.
+ *
+ * @param localName local name of the address
+ */
+ void setLocalName(const word& localName);
+
+ /** Return the domain name of the address.
+ *
+ * @return domain name of the address
+ */
+ const word& getDomainName() const;
+
+ /** Set the domain name of the address.
+ *
+ * @param domainName domain name of the address
+ */
+ void setDomainName(const word& domainName);
+
+ /** Returns whether this email address is empty.
+ * Address is considered as empty if the local part is not specified.
+ *
+ * @return true if the address is empty, false otherwise
+ */
+ bool isEmpty() const;
+
+ /** Returns the email address as a string, by joining components.
+ * (ie. the local name, followed by a @ then the domain name.)
+ *
+ * @return email address as a string
+ */
+ const string toString() const;
+
+ /** Returns the email address as multibyte text, by joining components.
+ * (ie. the local name, followed by a @ then the domain name.)
+ *
+ * @return email address as multibyte text
+ */
+ const text toText() const;
+
+ // Comparison
+ bool operator==(const class emailAddress& eml) const;
+ bool operator!=(const class emailAddress& eml) const;
+
+ // Assignment
+ void copyFrom(const component& other);
+ shared_ptr <component> clone() const;
+ emailAddress& operator=(const emailAddress& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+protected:
+
+ word m_localName;
+ word m_domainName;
+
+public:
+
+ using component::parse;
+ using component::generate;
+
+ // Component parsing & assembling
+ void parseImpl(
+ const 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;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_EMAILADDRESS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/emptyContentHandler.cpp b/vmime-master/src/vmime/emptyContentHandler.cpp
new file mode 100644
index 0000000..3cf7965
--- /dev/null
+++ b/vmime-master/src/vmime/emptyContentHandler.cpp
@@ -0,0 +1,126 @@
+//
+// 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.
+//
+
+#include "vmime/emptyContentHandler.hpp"
+
+
+namespace vmime {
+
+
+emptyContentHandler::emptyContentHandler() {
+
+}
+
+
+shared_ptr <contentHandler> emptyContentHandler::clone() const {
+
+ return make_shared <emptyContentHandler>();
+}
+
+
+void emptyContentHandler::generate(
+ utility::outputStream& /* os */,
+ const vmime::encoding& /* enc */,
+ const size_t /* maxLineLength */
+) const {
+
+ // Nothing to do.
+}
+
+
+void emptyContentHandler::extract(
+ utility::outputStream& /* os */,
+ utility::progressListener* progress) const
+{
+ if (progress) {
+ progress->start(0);
+ }
+
+ // Nothing to do.
+
+ if (progress) {
+ progress->stop(0);
+ }
+}
+
+
+void emptyContentHandler::extractRaw(
+ utility::outputStream& /* os */,
+ utility::progressListener* progress
+) const {
+
+ if (progress) {
+ progress->start(0);
+ }
+
+ // Nothing to do.
+
+ if (progress) {
+ progress->stop(0);
+ }
+}
+
+
+size_t emptyContentHandler::getLength() const {
+
+ return 0;
+}
+
+
+bool emptyContentHandler::isEmpty() const {
+
+ return true;
+}
+
+
+bool emptyContentHandler::isEncoded() const {
+
+ return false;
+}
+
+
+const vmime::encoding& emptyContentHandler::getEncoding() const {
+
+ return NO_ENCODING;
+}
+
+
+bool emptyContentHandler::isBuffered() const {
+
+ return true;
+}
+
+
+void emptyContentHandler::setContentTypeHint(const mediaType& type) {
+
+ m_contentType = type;
+}
+
+
+const mediaType emptyContentHandler::getContentTypeHint() const {
+
+ return m_contentType;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/emptyContentHandler.hpp b/vmime-master/src/vmime/emptyContentHandler.hpp
new file mode 100644
index 0000000..b7e0897
--- /dev/null
+++ b/vmime-master/src/vmime/emptyContentHandler.hpp
@@ -0,0 +1,80 @@
+//
+// 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_EMPTYCONTENTHANDLER_HPP_INCLUDED
+#define VMIME_EMPTYCONTENTHANDLER_HPP_INCLUDED
+
+
+#include "vmime/contentHandler.hpp"
+
+
+namespace vmime {
+
+
+class VMIME_EXPORT emptyContentHandler : public contentHandler {
+
+public:
+
+ emptyContentHandler();
+
+ shared_ptr <contentHandler> clone() const;
+
+ void generate(
+ utility::outputStream& os,
+ const vmime::encoding& enc,
+ const size_t maxLineLength = lineLengthLimits::infinite
+ ) const;
+
+ void extract(
+ utility::outputStream& os,
+ utility::progressListener* progress = NULL
+ ) const;
+
+ void extractRaw(
+ utility::outputStream& os,
+ utility::progressListener* progress = NULL
+ ) const;
+
+ size_t getLength() const;
+
+ bool isEncoded() const;
+
+ const vmime::encoding& getEncoding() const;
+
+ bool isEmpty() const;
+
+ bool isBuffered() const;
+
+ void setContentTypeHint(const mediaType& type);
+ const mediaType getContentTypeHint() const;
+
+private:
+
+ mediaType m_contentType;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_EMPTYCONTENTHANDLER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/encoding.cpp b/vmime-master/src/vmime/encoding.cpp
new file mode 100644
index 0000000..23814a6
--- /dev/null
+++ b/vmime-master/src/vmime/encoding.cpp
@@ -0,0 +1,331 @@
+//
+// 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.
+//
+
+#include "vmime/encoding.hpp"
+#include "vmime/contentHandler.hpp"
+
+#include "vmime/utility/outputStreamStringAdapter.hpp"
+#include "vmime/utility/encoder/encoderFactory.hpp"
+
+#include <algorithm>
+
+
+namespace vmime {
+
+
+encoding::encoding()
+ : m_name(encodingTypes::SEVEN_BIT),
+ m_usage(USAGE_UNKNOWN) {
+
+}
+
+
+encoding::encoding(const string& name)
+ : m_name(utility::stringUtils::toLower(name)),
+ m_usage(USAGE_UNKNOWN) {
+
+}
+
+
+encoding::encoding(const string& name, const EncodingUsage usage)
+ : m_name(utility::stringUtils::toLower(name)),
+ m_usage(usage) {
+
+}
+
+
+encoding::encoding(const encoding& enc)
+ : headerFieldValue(),
+ m_name(enc.m_name),
+ m_usage(enc.m_usage) {
+}
+
+
+void encoding::parseImpl(
+ const parsingContext& /* ctx */,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ m_usage = USAGE_UNKNOWN;
+
+ m_name = utility::stringUtils::toLower(
+ utility::stringUtils::trim(
+ utility::stringUtils::unquote(
+ utility::stringUtils::trim(
+ string(buffer.begin() + position, buffer.begin() + end)
+ )
+ )
+ )
+ );
+
+ if (m_name.empty()) {
+ m_name = encodingTypes::SEVEN_BIT; // assume default "7-bit"
+ }
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void encoding::generateImpl(
+ const generationContext& /* ctx */,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ os << m_name;
+
+ if (newLinePos) {
+ *newLinePos = curLinePos + m_name.length();
+ }
+}
+
+
+shared_ptr <utility::encoder::encoder> encoding::getEncoder() const {
+
+ shared_ptr <utility::encoder::encoder> encoder =
+ utility::encoder::encoderFactory::getInstance()->create(generate());
+
+ // FIXME: this should not be here (move me into QP encoder instead?)
+ if (m_usage == USAGE_TEXT && m_name == encodingTypes::QUOTED_PRINTABLE) {
+ encoder->getProperties()["text"] = true;
+ }
+
+ return encoder;
+}
+
+
+encoding& encoding::operator=(const encoding& other) {
+
+ copyFrom(other);
+ return (*this);
+}
+
+
+encoding& encoding::operator=(const string& name) {
+
+ m_name = utility::stringUtils::toLower(name);
+ m_usage = USAGE_UNKNOWN;
+
+ return *this;
+}
+
+
+bool encoding::operator==(const encoding& value) const {
+
+ return utility::stringUtils::toLower(m_name) == value.m_name;
+}
+
+
+bool encoding::operator!=(const encoding& value) const {
+
+ return !(*this == value);
+}
+
+
+const encoding encoding::decideImpl(
+ const string::const_iterator begin,
+ const string::const_iterator end
+) {
+
+ const string::difference_type length = end - begin;
+ const string::difference_type count = std::count_if(
+ begin, end,
+ std::bind2nd(std::less<unsigned char>(), 127)
+ );
+
+ // All is in 7-bit US-ASCII --> 7-bit (or Quoted-Printable...)
+ if (length == count) {
+
+ // Now, we check if there is any line with more than
+ // "lineLengthLimits::convenient" characters (7-bit requires that)
+ string::const_iterator p = begin;
+
+ const size_t maxLen = lineLengthLimits::convenient;
+ size_t len = 0;
+
+ for ( ; p != end && len <= maxLen ; ) {
+
+ if (*p == '\n') {
+
+ len = 0;
+ ++p;
+
+ // May or may not need to be encoded, we don't take
+ // any risk (avoid problems with SMTP)
+ if (p != end && *p == '.') {
+ len = maxLen + 1;
+ }
+
+ } else {
+
+ ++len;
+ ++p;
+ }
+ }
+
+ if (len > maxLen) {
+ return encoding(encodingTypes::QUOTED_PRINTABLE);
+ } else {
+ return encoding(encodingTypes::SEVEN_BIT);
+ }
+
+ // Less than 20% non US-ASCII --> Quoted-Printable
+ } else if ((length - count) <= length / 5) {
+
+ return encoding(encodingTypes::QUOTED_PRINTABLE);
+
+ // Otherwise --> Base64
+ } else {
+
+ return encoding(encodingTypes::BASE64);
+ }
+}
+
+
+bool encoding::shouldReencode() const {
+
+ if (m_name == encodingTypes::BASE64 ||
+ m_name == encodingTypes::QUOTED_PRINTABLE ||
+ m_name == encodingTypes::UUENCODE) {
+
+ return false;
+ }
+
+ return true;
+}
+
+
+const encoding encoding::decide(
+ const shared_ptr <const contentHandler>& data,
+ const EncodingUsage usage
+) {
+
+ // Do not re-encode data if it is already encoded
+ if (data->isEncoded() && !data->getEncoding().shouldReencode()) {
+ return data->getEncoding();
+ }
+
+ encoding enc;
+
+ if (usage == USAGE_TEXT && data->isBuffered() &&
+ data->getLength() > 0 && data->getLength() < 32768) {
+
+ // Extract data into temporary buffer
+ string buffer;
+ utility::outputStreamStringAdapter os(buffer);
+
+ data->extract(os);
+ os.flush();
+
+ enc = decideImpl(buffer.begin(), buffer.end());
+
+ } else {
+
+ enc = encoding(encodingTypes::BASE64);
+ }
+
+ enc.setUsage(usage);
+
+ return enc;
+}
+
+
+const encoding encoding::decide(
+ const shared_ptr <const contentHandler>& data,
+ const charset& chset,
+ const EncodingUsage usage
+) {
+
+ // Do not re-encode data if it is already encoded
+ if (data->isEncoded() && !data->getEncoding().shouldReencode()) {
+ return data->getEncoding();
+ }
+
+ if (usage == USAGE_TEXT) {
+
+ encoding recEncoding;
+
+ if (chset.getRecommendedEncoding(recEncoding)) {
+
+ recEncoding.setUsage(usage);
+ return recEncoding;
+ }
+ }
+
+ return decide(data, usage);
+}
+
+
+shared_ptr <component> encoding::clone() const {
+
+ return make_shared <encoding>(*this);
+}
+
+
+void encoding::copyFrom(const component& other) {
+
+ const encoding& e = dynamic_cast <const encoding&>(other);
+
+ m_name = e.m_name;
+}
+
+
+const string& encoding::getName() const {
+
+ return m_name;
+}
+
+
+void encoding::setName(const string& name) {
+
+ m_name = name;
+}
+
+
+encoding::EncodingUsage encoding::getUsage() const {
+
+ return m_usage;
+}
+
+
+void encoding::setUsage(const EncodingUsage usage) {
+
+ m_usage = usage;
+}
+
+
+const std::vector <shared_ptr <component> > encoding::getChildComponents() {
+
+ return std::vector <shared_ptr <component> >();
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/encoding.hpp b/vmime-master/src/vmime/encoding.hpp
new file mode 100644
index 0000000..2ff17ef
--- /dev/null
+++ b/vmime-master/src/vmime/encoding.hpp
@@ -0,0 +1,180 @@
+//
+// 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_ENCODING_HPP_INCLUDED
+#define VMIME_ENCODING_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/headerFieldValue.hpp"
+
+#include "vmime/utility/encoder/encoder.hpp"
+
+
+namespace vmime {
+
+
+class contentHandler;
+
+
+/** Content encoding (basic type).
+ */
+class VMIME_EXPORT encoding : public headerFieldValue {
+
+public:
+
+ enum EncodingUsage {
+
+ USAGE_UNKNOWN,
+ USAGE_TEXT, /**< Use for body text. */
+ USAGE_BINARY_DATA /**< Use for attachment, image... */
+ };
+
+
+ encoding();
+ explicit encoding(const string& name);
+ encoding(const string& name, const EncodingUsage usage);
+ encoding(const encoding& enc);
+
+ /** Return the name of the encoding.
+ * See the constants in vmime::encodingTypes.
+ *
+ * @return name of the encoding (eg. "quoted-printable")
+ */
+ const string& getName() const;
+
+ /** Set the name of the encoding.
+ * See the constants in vmime::encodingTypes.
+ *
+ * @param name name of the encoding
+ */
+ void setName(const string& name);
+
+ /** Return the type of contents this encoding is used for.
+ * See the EncodingUsage enum.
+ */
+ EncodingUsage getUsage() const;
+
+ /** Set the type of contents this encoding is used for.
+ * See the EncodingUsage enum.
+ *
+ * @param usage type of contents
+ */
+ void setUsage(const EncodingUsage usage);
+
+
+ encoding& operator=(const encoding& other);
+ encoding& operator=(const string& name);
+
+ bool operator==(const encoding& value) const;
+ bool operator!=(const encoding& value) const;
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+ /** Decide which encoding to use based on the specified data.
+ *
+ * @param data data used to determine encoding
+ * @param usage context of use of data
+ * @return suitable encoding for specified data
+ */
+ static const encoding decide(
+ const shared_ptr <const contentHandler>& data,
+ const EncodingUsage usage = USAGE_BINARY_DATA
+ );
+
+ /** Decide which encoding to use based on the specified data and charset.
+ *
+ * @param data data used to determine encoding
+ * @param chset charset of data
+ * @param usage context of use of data
+ * @return suitable encoding for specified data and charset
+ */
+ static const encoding decide(
+ const shared_ptr <const contentHandler>& data,
+ const charset& chset,
+ const EncodingUsage usage = USAGE_BINARY_DATA
+ );
+
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+
+ /** Use encoderFactory to obtain an encoder/decoder object
+ * for the current encoding type.
+ *
+ * @throw exceptions::no_encoder_available if no encoder
+ * is registered for the encoding
+ * @return a new encoder object for the encoding type
+ */
+ shared_ptr <utility::encoder::encoder> getEncoder() const;
+
+private:
+
+ string m_name;
+ EncodingUsage m_usage;
+
+ /** Determine whether data encoded using this encoding should
+ * be re-encoded if needed.
+ *
+ * @return true if data should be re-encoded, false otherwise
+ */
+ bool shouldReencode() const;
+
+ /** Decide which encoding to use based on the specified data.
+ *
+ * Please note: this will read the whole buffer, so it should be used only
+ * for small amount of data (eg. text), and not large binary attachments.
+ *
+ * @param begin start iterator in buffer
+ * @param end end iterator in buffer
+ * @return suitable encoding for specified data
+ */
+ static const encoding decideImpl(
+ const string::const_iterator begin,
+ const string::const_iterator end
+ );
+
+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 generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_ENCODING_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/exception.cpp b/vmime-master/src/vmime/exception.cpp
new file mode 100644
index 0000000..fb9dea9
--- /dev/null
+++ b/vmime-master/src/vmime/exception.cpp
@@ -0,0 +1,735 @@
+//
+// 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.
+//
+
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+
+
+//
+// exception
+//
+
+const exception exception::NO_EXCEPTION;
+
+
+exception::exception()
+ : std::runtime_error(""), m_other(NULL) {
+
+}
+
+
+exception::exception(const string& what, const exception& other)
+ : std::runtime_error(what), m_other(&other != &NO_EXCEPTION ? other.clone() : NULL) {
+
+}
+
+
+exception::exception(const exception& e)
+ : std::runtime_error(e.what()), m_other(e.m_other == NULL ? NULL : e.m_other->clone()) {
+
+}
+
+
+exception::~exception() throw() {
+
+ delete m_other;
+}
+
+
+void exception::chainException(const exception& other) {
+
+ exception* e = other.clone();
+
+ delete m_other;
+ m_other = e;
+}
+
+
+const exception* exception::other() const throw() {
+
+ return m_other;
+}
+
+
+const char* exception::name() const throw() {
+
+ return "exception";
+}
+
+
+exception* exception::clone() const {
+
+ return new exception(*this);
+}
+
+
+
+namespace exceptions {
+
+
+//
+// bad_field_value_type
+//
+
+bad_field_value_type::~bad_field_value_type() throw() {}
+bad_field_value_type::bad_field_value_type(const string& fieldName, const exception& other)
+ : exception("Bad value type for field '" + fieldName + "'.", other) {}
+
+exception* bad_field_value_type::clone() const { return new bad_field_value_type(*this); }
+const char* bad_field_value_type::name() const throw() { return "bad_field_value_type"; }
+
+
+
+//
+// charset_conv_error
+//
+
+charset_conv_error::~charset_conv_error() throw() {}
+charset_conv_error::charset_conv_error(const string& what, const exception& other)
+ : exception(what.empty() ? "Charset conversion error." : what, other) {}
+
+exception* charset_conv_error::clone() const { return new charset_conv_error(*this); }
+const char* charset_conv_error::name() const throw() { return "charset_conv_error"; }
+
+
+
+//
+// illegal_byte_sequence_for_charset
+//
+
+illegal_byte_sequence_for_charset::~illegal_byte_sequence_for_charset() throw() {}
+illegal_byte_sequence_for_charset::illegal_byte_sequence_for_charset(const string& what, const exception& other)
+ : exception(what.empty() ? "Found illegal byte sequence for this charset." : what, other) {}
+
+exception* illegal_byte_sequence_for_charset::clone() const { return new illegal_byte_sequence_for_charset(*this); }
+const char* illegal_byte_sequence_for_charset::name() const throw() { return "illegal_byte_sequence_for_charset"; }
+
+
+
+//
+// no_encoder_available
+//
+
+no_encoder_available::~no_encoder_available() throw() {}
+no_encoder_available::no_encoder_available(const string& name, const exception& other)
+ : exception("No encoder available: '" + name + "'.", other) {}
+
+exception* no_encoder_available::clone() const { return new no_encoder_available(*this); }
+const char* no_encoder_available::name() const throw() { return "no_encoder_available"; }
+
+
+//
+// no_digest_algorithm_available
+//
+
+no_digest_algorithm_available::~no_digest_algorithm_available() throw() {}
+no_digest_algorithm_available::no_digest_algorithm_available(const string& name, const exception& other)
+ : exception("No algorithm available: '" + name + "'.", other) {}
+
+exception* no_digest_algorithm_available::clone() const { return new no_digest_algorithm_available(*this); }
+const char* no_digest_algorithm_available::name() const throw() { return "no_digest_algorithm_available"; }
+
+
+//
+// no_such_field
+//
+
+no_such_field::~no_such_field() throw() {}
+no_such_field::no_such_field(const exception& other)
+ : exception("Field not found.", other) {}
+
+exception* no_such_field::clone() const { return new no_such_field(*this); }
+const char* no_such_field::name() const throw() { return "no_such_field"; }
+
+
+//
+// no_such_part
+//
+
+no_such_part::~no_such_part() throw() {}
+no_such_part::no_such_part(const exception& other)
+ : exception("Part not found.", other) {}
+
+exception* no_such_part::clone() const { return new no_such_part(*this); }
+const char* no_such_part::name() const throw() { return "no_such_part"; }
+
+
+//
+// no_such_message_id
+//
+
+no_such_message_id::~no_such_message_id() throw() {}
+no_such_message_id::no_such_message_id(const exception& other)
+ : exception("Message-Id not found.", other) {}
+
+exception* no_such_message_id::clone() const { return new no_such_message_id(*this); }
+const char* no_such_message_id::name() const throw() { return "no_such_message_id"; }
+
+
+//
+// open_file_error
+//
+
+open_file_error::~open_file_error() throw() {}
+open_file_error::open_file_error(const exception& other)
+ : exception("Error opening file.", other) {}
+
+exception* open_file_error::clone() const { return new open_file_error(*this); }
+const char* open_file_error::name() const throw() { return "open_file_error"; }
+
+
+//
+// no_factory_available
+//
+
+no_factory_available::~no_factory_available() throw() {}
+no_factory_available::no_factory_available(const exception& other)
+ : exception("No factory available.", other) {}
+
+exception* no_factory_available::clone() const { return new no_factory_available(*this); }
+const char* no_factory_available::name() const throw() { return "no_factory_available"; }
+
+
+//
+// no_platform_handler
+//
+
+no_platform_handler::~no_platform_handler() throw() {}
+no_platform_handler::no_platform_handler(const exception& other)
+ : exception("No platform handler installed.", other) {}
+
+exception* no_platform_handler::clone() const { return new no_platform_handler(*this); }
+const char* no_platform_handler::name() const throw() { return "no_platform_handler"; }
+
+
+//
+// no_expeditor
+//
+
+no_expeditor::~no_expeditor() throw() {}
+no_expeditor::no_expeditor(const exception& other)
+ : exception("No expeditor specified.", other) {}
+
+exception* no_expeditor::clone() const { return new no_expeditor(*this); }
+const char* no_expeditor::name() const throw() { return "no_expeditor"; }
+
+
+//
+// no_recipient
+//
+
+no_recipient::~no_recipient() throw() {}
+no_recipient::no_recipient(const exception& other)
+ : exception("No recipient specified.", other) {}
+
+exception* no_recipient::clone() const { return new no_recipient(*this); }
+const char* no_recipient::name() const throw() { return "no_recipient"; }
+
+
+//
+// no_such_property
+//
+
+no_such_property::~no_such_property() throw() {}
+no_such_property::no_such_property(const string& name, const exception& other)
+ : exception(string("No such property: '") + name + string("'."), other) { }
+
+exception* no_such_property::clone() const { return new no_such_property(*this); }
+const char* no_such_property::name() const throw() { return "no_such_property"; }
+
+
+//
+// invalid_property_type
+//
+
+invalid_property_type::~invalid_property_type() throw() {}
+invalid_property_type::invalid_property_type(const exception& other)
+ : exception("Invalid property type.", other) {}
+
+exception* invalid_property_type::clone() const { return new invalid_property_type(*this); }
+const char* invalid_property_type::name() const throw() { return "invalid_property_type"; }
+
+
+//
+// invalid_argument
+//
+
+invalid_argument::~invalid_argument() throw() {}
+invalid_argument::invalid_argument(const exception& other)
+ : exception("Invalid argument.", other) {}
+
+exception* invalid_argument::clone() const { return new invalid_argument(*this); }
+const char* invalid_argument::name() const throw() { return "invalid_argument"; }
+
+
+//
+// system_error
+//
+
+system_error::~system_error() throw() { }
+system_error::system_error(const string& what, const exception& other)
+ : exception(what, other) {}
+
+exception* system_error::clone() const { return new system_error(*this); }
+const char* system_error::name() const throw() { return "system_error"; }
+
+
+//
+// malformed_url
+//
+
+malformed_url::~malformed_url() throw() {}
+malformed_url::malformed_url(const string& error, const exception& other)
+ : exception("Malformed URL: " + error + ".", other) {}
+
+exception* malformed_url::clone() const { return new malformed_url(*this); }
+const char* malformed_url::name() const throw() { return "malformed_url"; }
+
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+//
+// net_exception
+//
+
+net_exception::~net_exception() throw() {}
+net_exception::net_exception(const string& what, const exception& other)
+ : exception(what, other) {}
+
+exception* net_exception::clone() const { return new net_exception(*this); }
+const char* net_exception::name() const throw() { return "net_exception"; }
+
+
+//
+// socket_exception
+//
+
+socket_exception::~socket_exception() throw() {}
+socket_exception::socket_exception(const string& what, const exception& other)
+ : net_exception(what.empty()
+ ? "Socket error." : what, other) {}
+
+exception* socket_exception::clone() const { return new socket_exception(*this); }
+const char* socket_exception::name() const throw() { return "socket_exception"; }
+
+
+//
+// socket_not_connected_exception
+//
+
+socket_not_connected_exception::~socket_not_connected_exception() throw() {}
+socket_not_connected_exception::socket_not_connected_exception(const string& what, const exception& other)
+ : socket_exception(what.empty()
+ ? "Socket is not connected." : what, other) {}
+
+exception* socket_not_connected_exception::clone() const { return new socket_not_connected_exception(*this); }
+const char* socket_not_connected_exception::name() const throw() { return "socket_not_connected_exception"; }
+
+
+//
+// connection_error
+//
+
+connection_error::~connection_error() throw() {}
+connection_error::connection_error(const string& what, const exception& other)
+ : socket_exception(what.empty()
+ ? "Connection error." : what, other) {}
+
+exception* connection_error::clone() const { return new connection_error(*this); }
+const char* connection_error::name() const throw() { return "connection_error"; }
+
+
+//
+// connection_greeting_error
+//
+
+connection_greeting_error::~connection_greeting_error() throw() {}
+connection_greeting_error::connection_greeting_error(const string& response, const exception& other)
+ : net_exception("Greeting error.", other), m_response(response) {}
+
+const string& connection_greeting_error::response() const { return (m_response); }
+
+exception* connection_greeting_error::clone() const { return new connection_greeting_error(*this); }
+const char* connection_greeting_error::name() const throw() { return "connection_greeting_error"; }
+
+
+//
+// authentication_error
+//
+
+authentication_error::~authentication_error() throw() {}
+authentication_error::authentication_error(const string& response, const exception& other)
+ : net_exception("Authentication error.", other), m_response(response) {}
+
+const string& authentication_error::response() const { return (m_response); }
+
+exception* authentication_error::clone() const { return new authentication_error(*this); }
+const char* authentication_error::name() const throw() { return "authentication_error"; }
+
+
+//
+// unsupported_option
+//
+
+unsupported_option::~unsupported_option() throw() {}
+unsupported_option::unsupported_option(const exception& other)
+ : net_exception("Unsupported option.", other) {}
+
+exception* unsupported_option::clone() const { return new unsupported_option(*this); }
+const char* unsupported_option::name() const throw() { return "unsupported_option"; }
+
+
+//
+// illegal_state
+//
+
+illegal_state::~illegal_state() throw() {}
+illegal_state::illegal_state(const string& state, const exception& other)
+ : net_exception("Illegal state to accomplish the operation: '" + state + "'.", other) {}
+
+exception* illegal_state::clone() const { return new illegal_state(*this); }
+const char* illegal_state::name() const throw() { return "illegal_state"; }
+
+
+//
+// folder_not_found
+//
+
+folder_not_found::~folder_not_found() throw() {}
+folder_not_found::folder_not_found(const exception& other)
+ : net_exception("Folder not found.", other) {}
+
+exception* folder_not_found::clone() const { return new folder_not_found(*this); }
+const char* folder_not_found::name() const throw() { return "folder_not_found"; }
+
+
+//
+// folder_already_open
+//
+
+folder_already_open::~folder_already_open() throw() {}
+folder_already_open::folder_already_open(const exception& other)
+ : net_exception("Folder is already open in the same session.", other) {}
+
+exception* folder_already_open::clone() const { return new folder_already_open(*this); }
+const char* folder_already_open::name() const throw() { return "folder_already_open"; }
+
+
+//
+// message_not_found
+//
+
+message_not_found::~message_not_found() throw() {}
+message_not_found::message_not_found(const exception& other)
+ : net_exception("Message not found.", other) {}
+
+exception* message_not_found::clone() const { return new message_not_found(*this); }
+const char* message_not_found::name() const throw() { return "message_not_found"; }
+
+
+//
+// operation_not_supported
+//
+
+operation_not_supported::~operation_not_supported() throw() {}
+operation_not_supported::operation_not_supported(const exception& other)
+ : net_exception("Operation not supported.", other) {}
+
+exception* operation_not_supported::clone() const { return new operation_not_supported(*this); }
+const char* operation_not_supported::name() const throw() { return "operation_not_supported"; }
+
+
+//
+// operation_timed_out
+//
+
+operation_timed_out::~operation_timed_out() throw() {}
+operation_timed_out::operation_timed_out(const exception& other)
+ : net_exception("Operation timed out.", other) {}
+
+exception* operation_timed_out::clone() const { return new operation_timed_out(*this); }
+const char* operation_timed_out::name() const throw() { return "operation_timed_out"; }
+
+
+//
+// operation_cancelled
+//
+
+operation_cancelled::~operation_cancelled() throw() {}
+operation_cancelled::operation_cancelled(const exception& other)
+ : net_exception("Operation cancelled by the user.", other) {}
+
+exception* operation_cancelled::clone() const { return new operation_cancelled(*this); }
+const char* operation_cancelled::name() const throw() { return "operation_cancelled"; }
+
+
+//
+// unfetched_object
+//
+
+unfetched_object::~unfetched_object() throw() {}
+unfetched_object::unfetched_object(const exception& other)
+ : net_exception("Object not fetched.", other) {}
+
+exception* unfetched_object::clone() const { return new unfetched_object(*this); }
+const char* unfetched_object::name() const throw() { return "unfetched_object"; }
+
+
+//
+// not_connected
+//
+
+not_connected::~not_connected() throw() {}
+not_connected::not_connected(const exception& other)
+ : net_exception("Not connected to a service.", other) {}
+
+exception* not_connected::clone() const { return new not_connected(*this); }
+const char* not_connected::name() const throw() { return "not_connected"; }
+
+
+//
+// already_connected
+//
+
+already_connected::~already_connected() throw() {}
+already_connected::already_connected(const exception& other)
+ : net_exception("Already connected to a service. Disconnect and retry.", other) {}
+
+exception* already_connected::clone() const { return new already_connected(*this); }
+const char* already_connected::name() const throw() { return "already_connected"; }
+
+
+//
+// illegal_operation
+//
+
+illegal_operation::~illegal_operation() throw() {}
+illegal_operation::illegal_operation(const string& msg, const exception& other)
+ : net_exception(msg.empty()
+ ? "Illegal operation."
+ : "Illegal operation: " + msg + ".",
+ other
+ ) {}
+
+exception* illegal_operation::clone() const { return new illegal_operation(*this); }
+const char* illegal_operation::name() const throw() { return "illegal_operation"; }
+
+
+//
+// command_error
+//
+
+command_error::~command_error() throw() {}
+command_error::command_error(const string& command, const string& response,
+ const string& desc, const exception& other)
+ : net_exception(desc.empty()
+ ? "Error while executing command '" + command + "'."
+ : "Error while executing command '" + command + "': " + desc + ".",
+ other
+ ),
+ m_command(command), m_response(response) {}
+
+const string& command_error::command() const { return (m_command); }
+
+const string& command_error::response() const { return (m_response); }
+
+exception* command_error::clone() const { return new command_error(*this); }
+const char* command_error::name() const throw() { return "command_error"; }
+
+
+//
+// invalid_response
+//
+
+invalid_response::~invalid_response() throw() {}
+invalid_response::invalid_response(const string& command, const string& response, const exception& other)
+ : net_exception(command.empty()
+ ? "Received invalid response."
+ : "Received invalid response for command '" + command + "'.",
+ other
+ ),
+ m_command(command), m_response(response) {}
+
+const string& invalid_response::command() const { return (m_command); }
+
+const string& invalid_response::response() const { return (m_response); }
+
+exception* invalid_response::clone() const { return new invalid_response(*this); }
+const char* invalid_response::name() const throw() { return "invalid_response"; }
+
+
+//
+// partial_fetch_not_supported
+//
+
+partial_fetch_not_supported::~partial_fetch_not_supported() throw() {}
+partial_fetch_not_supported::partial_fetch_not_supported(const exception& other)
+ : net_exception("Partial fetch not supported.", other) {}
+
+exception* partial_fetch_not_supported::clone() const { return new partial_fetch_not_supported(*this); }
+const char* partial_fetch_not_supported::name() const throw() { return "partial_fetch_not_supported"; }
+
+
+//
+// invalid_folder_name
+//
+
+invalid_folder_name::~invalid_folder_name() throw() {}
+invalid_folder_name::invalid_folder_name(const string& error, const exception& other)
+ : net_exception(error.empty()
+ ? "Invalid folder name: " + error + "."
+ : "Invalid folder name.",
+ other) {}
+
+exception* invalid_folder_name::clone() const { return new invalid_folder_name(*this); }
+const char* invalid_folder_name::name() const throw() { return "invalid_folder_name"; }
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+//
+// filesystem_exception
+//
+
+filesystem_exception::~filesystem_exception() throw() {}
+filesystem_exception::filesystem_exception(const string& what, const utility::path& path, const exception& other)
+ : exception(what, other), m_path(path) {}
+
+const utility::path& filesystem_exception::path() const { return (m_path); }
+
+exception* filesystem_exception::clone() const { return new filesystem_exception(*this); }
+const char* filesystem_exception::name() const throw() { return "filesystem_exception"; }
+
+
+//
+// not_a_directory
+//
+
+not_a_directory::~not_a_directory() throw() {}
+not_a_directory::not_a_directory(const utility::path& path, const exception& other)
+ : filesystem_exception("Operation failed: this is not a directory.", path, other) {}
+
+exception* not_a_directory::clone() const { return new not_a_directory(*this); }
+const char* not_a_directory::name() const throw() { return "not_a_directory"; }
+
+
+//
+// file_not_found
+//
+
+file_not_found::~file_not_found() throw() {}
+file_not_found::file_not_found(const utility::path& path, const exception& other)
+ : filesystem_exception("File not found.", path, other) {}
+
+exception* file_not_found::clone() const { return new file_not_found(*this); }
+const char* file_not_found::name() const throw() { return "file_not_found"; }
+
+
+#endif // VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+//
+// authentication_exception
+//
+
+authentication_exception::~authentication_exception() throw() {}
+authentication_exception::authentication_exception(const string& what, const exception& other)
+ : exception(what, other) {}
+
+exception* authentication_exception::clone() const { return new authentication_exception(*this); }
+const char* authentication_exception::name() const throw() { return "authentication_exception"; }
+
+
+//
+// no_auth_information
+//
+
+no_auth_information::~no_auth_information() throw() {}
+no_auth_information::no_auth_information(const exception& other)
+ : authentication_exception("Information cannot be provided.", other) {}
+
+exception* no_auth_information::clone() const { return new no_auth_information(*this); }
+const char* no_auth_information::name() const throw() { return "no_auth_information"; }
+
+
+#if VMIME_HAVE_SASL_SUPPORT
+
+
+//
+// sasl_exception
+//
+
+sasl_exception::~sasl_exception() throw() {}
+sasl_exception::sasl_exception(const string& what, const exception& other)
+ : authentication_exception(what, other) {}
+
+exception* sasl_exception::clone() const { return new sasl_exception(*this); }
+const char* sasl_exception::name() const throw() { return "sasl_exception"; }
+
+
+//
+// no_such_mechanism
+//
+
+no_such_mechanism::~no_such_mechanism() throw() {}
+no_such_mechanism::no_such_mechanism(const string& name, const exception& other)
+ : sasl_exception("No such SASL mechanism: '" + name + "'.", other) {}
+
+exception* no_such_mechanism::clone() const { return new no_such_mechanism(*this); }
+const char* no_such_mechanism::name() const throw() { return "no_such_mechanism"; }
+
+
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+
+//
+// tls_exception
+//
+
+tls_exception::~tls_exception() throw() {}
+tls_exception::tls_exception(const string& what, const exception& other)
+ : exception(what, other) {}
+
+exception* tls_exception::clone() const { return new tls_exception(*this); }
+const char* tls_exception::name() const throw() { return "tls_exception"; }
+
+
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+} // exceptions
+
+
+} // vmime
+
diff --git a/vmime-master/src/vmime/exception.hpp b/vmime-master/src/vmime/exception.hpp
new file mode 100644
index 0000000..da0ec24
--- /dev/null
+++ b/vmime-master/src/vmime/exception.hpp
@@ -0,0 +1,865 @@
+//
+// 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_EXCEPTION_HPP_INCLUDED
+#define VMIME_EXCEPTION_HPP_INCLUDED
+
+
+#include <stdexcept>
+
+#include "vmime/config.hpp"
+#include "vmime/base.hpp"
+#include "vmime/utility/path.hpp"
+
+
+namespace vmime {
+
+
+/** Base class for VMime exceptions.
+ */
+class VMIME_EXPORT exception : public std::runtime_error {
+
+private:
+
+ exception* m_other;
+
+ exception();
+
+public:
+
+ exception(const string& what, const exception& other = NO_EXCEPTION);
+ exception(const exception& e);
+
+ virtual ~exception() throw();
+
+ /** Chain the specified exception with this exception.
+ *
+ * @param other next exception in the chain
+ */
+ void chainException(const exception& other);
+
+ /** Return the next exception in the chain, that is the exception
+ * that caused this exception. This permits nesting exceptions.
+ *
+ * @return next exception in the chain
+ */
+ const exception* other() const throw();
+
+ /** Return a name identifying the exception.
+ *
+ * @return exception name
+ */
+ virtual const char* name() const throw();
+
+ /** Clone this object.
+ *
+ * @return a new copy of this object
+ */
+ virtual exception* clone() const;
+
+protected:
+
+ static const exception NO_EXCEPTION;
+};
+
+
+
+/** List of all VMime exceptions. */
+namespace exceptions {
+
+
+class VMIME_EXPORT bad_field_value_type : public vmime::exception {
+
+public:
+
+ bad_field_value_type(const string& fieldName, const exception& other = NO_EXCEPTION);
+ ~bad_field_value_type() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+class VMIME_EXPORT charset_conv_error : public vmime::exception {
+
+public:
+
+ charset_conv_error(const string& what = "", const exception& other = NO_EXCEPTION);
+ ~charset_conv_error() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+class VMIME_EXPORT illegal_byte_sequence_for_charset : public vmime::exception {
+
+public:
+
+ illegal_byte_sequence_for_charset(const string& what = "", const exception& other = NO_EXCEPTION);
+ ~illegal_byte_sequence_for_charset() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** No encoder has been found for the specified encoding name.
+ */
+class VMIME_EXPORT no_encoder_available : public vmime::exception {
+
+public:
+
+ no_encoder_available(const string& name, const exception& other = NO_EXCEPTION);
+ ~no_encoder_available() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** No algorithm has been found for the specified name.
+ */
+class VMIME_EXPORT no_digest_algorithm_available : public vmime::exception {
+
+public:
+
+ no_digest_algorithm_available(const string& name, const exception& other = NO_EXCEPTION);
+ ~no_digest_algorithm_available() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+class VMIME_EXPORT no_such_field : public vmime::exception {
+
+public:
+
+ no_such_field(const exception& other = NO_EXCEPTION);
+ ~no_such_field() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+class VMIME_EXPORT no_such_part : public vmime::exception {
+
+public:
+
+ no_such_part(const exception& other = NO_EXCEPTION);
+ ~no_such_part() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+class VMIME_EXPORT no_such_message_id : public vmime::exception {
+
+public:
+
+ no_such_message_id(const exception& other = NO_EXCEPTION);
+ ~no_such_message_id() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+class VMIME_EXPORT open_file_error : public vmime::exception {
+
+public:
+
+ open_file_error(const exception& other = NO_EXCEPTION);
+ ~open_file_error() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+class VMIME_EXPORT no_factory_available : public vmime::exception {
+
+public:
+
+ no_factory_available(const exception& other = NO_EXCEPTION);
+ ~no_factory_available() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+class VMIME_EXPORT no_platform_handler : public vmime::exception {
+
+public:
+
+ no_platform_handler(const exception& other = NO_EXCEPTION);
+ ~no_platform_handler() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** No expeditor specified.
+ */
+class VMIME_EXPORT no_expeditor : public vmime::exception {
+
+public:
+
+ no_expeditor(const exception& other = NO_EXCEPTION);
+ ~no_expeditor() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** No recipient specified.
+ */
+class VMIME_EXPORT no_recipient : public vmime::exception {
+
+public:
+
+ no_recipient(const exception& other = NO_EXCEPTION);
+ ~no_recipient() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** There is no property with that name in the set.
+ */
+class VMIME_EXPORT no_such_property : public vmime::exception {
+
+public:
+
+ no_such_property(const string& name, const exception& other = NO_EXCEPTION);
+ ~no_such_property() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Bad type specified when reading property.
+ */
+class VMIME_EXPORT invalid_property_type : public vmime::exception {
+
+public:
+
+ invalid_property_type(const exception& other = NO_EXCEPTION);
+ ~invalid_property_type() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Bad argument was passed to the function.
+ */
+class VMIME_EXPORT invalid_argument : public vmime::exception {
+
+public:
+
+ invalid_argument(const exception& other = NO_EXCEPTION);
+ ~invalid_argument() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Underlying operating system error.
+ */
+class VMIME_EXPORT system_error : public vmime::exception {
+
+public:
+
+ system_error(const string& what, const exception& other = NO_EXCEPTION);
+ ~system_error() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** The URL is malformed.
+ */
+class VMIME_EXPORT malformed_url : public vmime::exception {
+
+public:
+
+ malformed_url(const string& error, const exception& other = NO_EXCEPTION);
+ ~malformed_url() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+/** Base class for exceptions thrown by the networking module.
+ */
+class VMIME_EXPORT net_exception : public vmime::exception {
+
+public:
+
+ net_exception(const string& what, const exception& other = NO_EXCEPTION);
+ ~net_exception() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Alias for 'net_exception' (compatibility with version <= 0.7.1);
+ * this is deprecated.
+ */
+typedef net_exception messaging_exception;
+
+
+/** Socket error.
+ */
+class VMIME_EXPORT socket_exception : public net_exception {
+
+public:
+
+ socket_exception(const string& what = "", const exception& other = NO_EXCEPTION);
+ ~socket_exception() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+
+};
+
+
+/** Socket not connected: you are trying to write to/read from a socket which
+ * is not connected to a peer.
+ */
+class VMIME_EXPORT socket_not_connected_exception : public socket_exception {
+
+public:
+
+ socket_not_connected_exception(const string& what = "", const exception& other = NO_EXCEPTION);
+ ~socket_not_connected_exception() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+
+};
+
+
+/** Error while connecting to the server: this may be a DNS resolution error
+ * or a connection error (for example, time-out while connecting).
+ */
+class VMIME_EXPORT connection_error : public socket_exception {
+
+public:
+
+ connection_error(const string& what = "", const exception& other = NO_EXCEPTION);
+ ~connection_error() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Server did not initiated the connection correctly.
+ */
+class VMIME_EXPORT connection_greeting_error : public net_exception {
+
+public:
+
+ connection_greeting_error(const string& response, const exception& other = NO_EXCEPTION);
+ ~connection_greeting_error() throw();
+
+ const string& response() const;
+
+ exception* clone() const;
+ const char* name() const throw();
+
+private:
+
+ string m_response;
+};
+
+
+/** Error while giving credentials to the server (wrong username
+ * or password, or wrong authentication method).
+ */
+class VMIME_EXPORT authentication_error : public net_exception {
+
+public:
+
+ authentication_error(const string& response, const exception& other = NO_EXCEPTION);
+ ~authentication_error() throw();
+
+ const string& response() const;
+
+ exception* clone() const;
+ const char* name() const throw();
+
+private:
+
+ string m_response;
+};
+
+
+/** Option not supported.
+ */
+class VMIME_EXPORT unsupported_option : public net_exception {
+
+public:
+
+ unsupported_option(const exception& other = NO_EXCEPTION);
+ ~unsupported_option() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** The current state of the object does not permit to execute the
+ * operation (for example, you try to close a folder which is not open).
+ */
+class VMIME_EXPORT illegal_state : public net_exception {
+
+public:
+
+ illegal_state(const string& state, const exception& other = NO_EXCEPTION);
+ ~illegal_state() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Folder not found (does not exist).
+ */
+class VMIME_EXPORT folder_not_found : public net_exception {
+
+public:
+
+ folder_not_found(const exception& other = NO_EXCEPTION);
+ ~folder_not_found() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Folder is already open in the same session.
+ */
+class VMIME_EXPORT folder_already_open : public net_exception {
+
+public:
+
+ folder_already_open(const exception& other = NO_EXCEPTION);
+ ~folder_already_open() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Message not found (does not exist).
+ */
+class VMIME_EXPORT message_not_found : public net_exception {
+
+public:
+
+ message_not_found(const exception& other = NO_EXCEPTION);
+ ~message_not_found() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Operation not supported by the underlying protocol.
+ */
+class VMIME_EXPORT operation_not_supported : public net_exception {
+
+public:
+
+ operation_not_supported(const exception& other = NO_EXCEPTION);
+ ~operation_not_supported() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** The operation timed out (time-out delay is elapsed).
+ */
+class VMIME_EXPORT operation_timed_out : public net_exception {
+
+public:
+
+ operation_timed_out(const exception& other = NO_EXCEPTION);
+ ~operation_timed_out() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** The operation has been cancelled.
+ */
+class VMIME_EXPORT operation_cancelled : public net_exception {
+
+public:
+
+ operation_cancelled(const exception& other = NO_EXCEPTION);
+ ~operation_cancelled() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Must call fetchMessage() or fetchHeader() before accessing
+ * the requested object.
+ */
+class VMIME_EXPORT unfetched_object : public net_exception {
+
+public:
+
+ unfetched_object(const exception& other = NO_EXCEPTION);
+ ~unfetched_object() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** The service is not currently connected.
+ */
+class VMIME_EXPORT not_connected : public net_exception {
+
+public:
+
+ not_connected(const exception& other = NO_EXCEPTION);
+ ~not_connected() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** The service is already connected (must disconnect before).
+ */
+class VMIME_EXPORT already_connected : public net_exception {
+
+public:
+
+ already_connected(const exception& other = NO_EXCEPTION);
+ ~already_connected() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Illegal operation: cannot run this operation on the object.
+ */
+class VMIME_EXPORT illegal_operation : public net_exception {
+
+public:
+
+ illegal_operation(const string& msg = "", const exception& other = NO_EXCEPTION);
+ ~illegal_operation() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Command error: operation failed (this is specific to the underlying protocol).
+ */
+class VMIME_EXPORT command_error : public net_exception {
+
+public:
+
+ command_error(
+ const string& command,
+ const string& response,
+ const string& desc = "",
+ const exception& other = NO_EXCEPTION
+ );
+
+ ~command_error() throw();
+
+ /** Return the name of the command which have thrown the exception.
+ * This is protocol-dependent.
+ *
+ * @return command name (protocol-dependent)
+ */
+ const string& command() const;
+
+ /** Return the invalid response line.
+ * The meaning is protocol-dependent.
+ *
+ * @return response line (protocol-dependent)
+ */
+ const string& response() const;
+
+ exception* clone() const;
+ const char* name() const throw();
+
+private:
+
+ string m_command;
+ string m_response;
+};
+
+
+/** The server returned an invalid response.
+ */
+class VMIME_EXPORT invalid_response : public net_exception {
+
+public:
+
+ invalid_response(
+ const string& command,
+ const string& response,
+ const exception& other = NO_EXCEPTION
+ );
+
+ ~invalid_response() throw();
+
+ /** Return the name of the command which have thrown the exception.
+ * This is protocol-dependent.
+ *
+ * @return command name (protocol-dependent)
+ */
+ const string& command() const;
+
+ /** Return the invalid response line.
+ * The meaning is protocol-dependent.
+ *
+ * @return response line (protocol-dependent)
+ */
+ const string& response() const;
+
+ exception* clone() const;
+ const char* name() const throw();
+
+private:
+
+ string m_command;
+ string m_response;
+};
+
+
+/** Partial fetch is not supported by the underlying protocol.
+ */
+class VMIME_EXPORT partial_fetch_not_supported : public net_exception {
+
+public:
+
+ partial_fetch_not_supported(const exception& other = NO_EXCEPTION);
+ ~partial_fetch_not_supported() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** Folder name is invalid.
+ */
+class VMIME_EXPORT invalid_folder_name : public net_exception {
+
+public:
+
+ invalid_folder_name(const string& error = "", const exception& other = NO_EXCEPTION);
+ ~invalid_folder_name() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+/** Base class for exceptions thrown by the filesystem features.
+ */
+class VMIME_EXPORT filesystem_exception : public vmime::exception {
+
+public:
+
+ filesystem_exception(
+ const string& what,
+ const utility::path& path,
+ const exception& other = NO_EXCEPTION
+ );
+
+ ~filesystem_exception() throw();
+
+ /** Return the full path of the file have thrown the exception.
+ *
+ * @return full path of the file/directory
+ */
+ const utility::path& path() const;
+
+ exception* clone() const;
+ const char* name() const throw();
+
+private:
+
+ const utility::path m_path;
+};
+
+
+/** File is not a directory.
+ */
+class VMIME_EXPORT not_a_directory : public filesystem_exception {
+
+public:
+
+ not_a_directory(const utility::path& path, const exception& other = NO_EXCEPTION);
+ ~not_a_directory() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** File not found.
+ */
+class VMIME_EXPORT file_not_found : public filesystem_exception {
+
+public:
+
+ file_not_found(const utility::path& path, const exception& other = NO_EXCEPTION);
+ ~file_not_found() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+#endif // VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+/** Authentication exception.
+ */
+class VMIME_EXPORT authentication_exception : public vmime::exception {
+
+public:
+
+ authentication_exception(const string& what, const exception& other = NO_EXCEPTION);
+ ~authentication_exception() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** The requested information cannot be provided.
+ */
+class VMIME_EXPORT no_auth_information : public authentication_exception {
+
+public:
+
+ no_auth_information(const exception& other = NO_EXCEPTION);
+ ~no_auth_information() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+#if VMIME_HAVE_SASL_SUPPORT
+
+
+/** Base class for exceptions thrown by SASL module.
+ */
+class VMIME_EXPORT sasl_exception : public authentication_exception {
+
+public:
+
+ sasl_exception(const string& what, const exception& other = NO_EXCEPTION);
+ ~sasl_exception() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** No mechanism is registered with the specified name.
+ */
+class VMIME_EXPORT no_such_mechanism : public sasl_exception {
+
+public:
+
+ no_such_mechanism(const string& name, const exception& other = NO_EXCEPTION);
+ ~no_such_mechanism() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+
+/** Base class for exceptions thrown by TLS module.
+ */
+class VMIME_EXPORT tls_exception : public vmime::exception {
+
+public:
+
+ tls_exception(const string& what, const exception& other = NO_EXCEPTION);
+ ~tls_exception() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+} // exceptions
+
+
+} // vmime
+
+
+#endif // VMIME_EXCEPTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/export.hpp b/vmime-master/src/vmime/export.hpp
new file mode 100644
index 0000000..a3b4dfb
--- /dev/null
+++ b/vmime-master/src/vmime/export.hpp
@@ -0,0 +1,36 @@
+//
+// 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_EXPORT_HPP_INCLUDED
+#define VMIME_EXPORT_HPP_INCLUDED
+
+
+// Define VMIME_STATIC if you are linking with the static library
+#ifdef VMIME_STATIC
+# include "vmime/export-static.hpp"
+#else
+# include "vmime/export-shared.hpp"
+#endif
+
+
+#endif // VMIME_EXPORT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/fileAttachment.cpp b/vmime-master/src/vmime/fileAttachment.cpp
new file mode 100644
index 0000000..ac75570
--- /dev/null
+++ b/vmime-master/src/vmime/fileAttachment.cpp
@@ -0,0 +1,253 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include <fstream>
+#include <sstream>
+
+#include "vmime/fileAttachment.hpp"
+#include "vmime/exception.hpp"
+
+#include "vmime/streamContentHandler.hpp"
+#include "vmime/utility/inputStreamPointerAdapter.hpp"
+
+#include "vmime/contentDispositionField.hpp"
+
+#include "vmime/platform.hpp"
+#include "vmime/utility/file.hpp"
+
+
+namespace vmime {
+
+
+fileAttachment::fileAttachment(
+ const string& filepath,
+ const mediaType& type
+) {
+
+ m_type = type;
+
+ setData(filepath);
+
+ m_encoding = encoding::decide(m_data);
+}
+
+
+fileAttachment::fileAttachment(
+ const string& filepath,
+ const mediaType& type,
+ const text& desc
+) {
+
+ m_type = type;
+ m_desc = desc;
+
+ setData(filepath);
+
+ m_encoding = encoding::decide(m_data);
+}
+
+
+fileAttachment::fileAttachment(
+ const string& filepath,
+ const mediaType& type,
+ const text& desc,
+ const encoding& enc
+) {
+
+ m_type = type;
+ m_desc = desc;
+
+ setData(filepath);
+
+ m_encoding = enc;
+}
+
+
+fileAttachment::fileAttachment(
+ const shared_ptr <contentHandler>& cts,
+ const word& filename,
+ const mediaType& type) {
+
+ if (!filename.isEmpty()) {
+ m_fileInfo.setFilename(filename);
+ }
+
+ m_type = type;
+
+ setData(cts);
+
+ m_encoding = encoding::decide(m_data);
+}
+
+
+fileAttachment::fileAttachment(
+ const shared_ptr <contentHandler>& cts,
+ const word& filename,
+ const mediaType& type,
+ const text& desc
+) {
+
+ if (!filename.isEmpty()) {
+ m_fileInfo.setFilename(filename);
+ }
+
+ m_type = type;
+ m_desc = desc;
+
+ setData(cts);
+
+ m_encoding = encoding::decide(m_data);
+}
+
+
+fileAttachment::fileAttachment(
+ const shared_ptr <contentHandler>& cts,
+ const word& filename,
+ const mediaType& type,
+ const text& desc,
+ const encoding& enc
+) {
+
+ if (!filename.isEmpty()) {
+ m_fileInfo.setFilename(filename);
+ }
+
+ m_type = type;
+ m_desc = desc;
+ m_encoding = enc;
+
+ setData(cts);
+}
+
+
+void fileAttachment::setData(const string& filepath) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+ utility::file::path path = fsf->stringToPath(filepath);
+
+ shared_ptr <utility::file> file = fsf->create(path);
+
+ if (!file->isFile()) {
+ throw exceptions::open_file_error();
+ }
+
+ m_data = make_shared <streamContentHandler>(
+ file->getFileReader()->getInputStream(), file->getLength()
+ );
+
+ m_fileInfo.setFilename(path.getLastComponent());
+ m_fileInfo.setSize(file->getLength());
+}
+
+
+void fileAttachment::setData(const shared_ptr <contentHandler>& cts) {
+
+ m_data = cts;
+
+ m_fileInfo.setSize(cts->getLength());
+}
+
+
+void fileAttachment::generatePart(const shared_ptr <bodyPart>& part) const {
+
+ defaultAttachment::generatePart(part);
+
+ shared_ptr <contentDispositionField> cdf =
+ dynamicCast <contentDispositionField>(part->getHeader()->ContentDisposition());
+
+ if (m_fileInfo.hasSize()) cdf->setSize(utility::stringUtils::toString(m_fileInfo.getSize()));
+ if (m_fileInfo.hasFilename() && !m_fileInfo.getFilename().isEmpty()) cdf->setFilename(m_fileInfo.getFilename());
+ if (m_fileInfo.hasCreationDate()) cdf->setCreationDate(m_fileInfo.getCreationDate());
+ if (m_fileInfo.hasModificationDate()) cdf->setModificationDate(m_fileInfo.getModificationDate());
+ if (m_fileInfo.hasReadDate()) cdf->setReadDate(m_fileInfo.getReadDate());
+}
+
+
+const fileAttachment::fileInfo& fileAttachment::getFileInfo() const {
+
+ return m_fileInfo;
+}
+
+
+fileAttachment::fileInfo& fileAttachment::getFileInfo() {
+
+ return m_fileInfo;
+}
+
+
+
+//
+// fileAttachment::fileInfo
+//
+
+fileAttachment::fileInfo::fileInfo()
+ : m_filename(NULL),
+ m_size(NULL),
+ m_creationDate(NULL),
+ m_modifDate(NULL),
+ m_readDate(NULL) {
+
+}
+
+
+fileAttachment::fileInfo::~fileInfo()
+{
+ delete m_filename;
+ delete m_size;
+ delete m_creationDate;
+ delete m_modifDate;
+ delete m_readDate;
+}
+
+bool fileAttachment::fileInfo::hasFilename() const { return m_filename; }
+const word& fileAttachment::fileInfo::getFilename() const { return *m_filename; }
+void fileAttachment::fileInfo::setFilename(const string& name) { if (m_filename) { *m_filename = name; } else { m_filename = new word(name); } }
+void fileAttachment::fileInfo::setFilename(const word& name) { if (m_filename) { *m_filename = name; } else { m_filename = new word(name); } }
+
+bool fileAttachment::fileInfo::hasCreationDate() const { return m_creationDate; }
+const datetime& fileAttachment::fileInfo::getCreationDate() const { return *m_creationDate; }
+void fileAttachment::fileInfo::setCreationDate(const datetime& date) { if (m_creationDate) { *m_creationDate = date; } else { m_creationDate = new datetime(date); } }
+
+bool fileAttachment::fileInfo::hasModificationDate() const { return m_modifDate; }
+const datetime& fileAttachment::fileInfo::getModificationDate() const { return *m_modifDate; }
+void fileAttachment::fileInfo::setModificationDate(const datetime& date) { if (m_modifDate) { *m_modifDate = date; } else { m_modifDate = new datetime(date); } }
+
+bool fileAttachment::fileInfo::hasReadDate() const { return m_readDate; }
+const datetime& fileAttachment::fileInfo::getReadDate() const { return *m_readDate; }
+void fileAttachment::fileInfo::setReadDate(const datetime& date) { if (m_readDate) { *m_readDate = date; } else { m_readDate = new datetime(date); } }
+
+bool fileAttachment::fileInfo::hasSize() const { return m_size; }
+size_t fileAttachment::fileInfo::getSize() const { return *m_size; }
+void fileAttachment::fileInfo::setSize(const size_t size) { if (m_size) { *m_size = size; } else { m_size = new size_t(size); } }
+
+
+} // vmime
+
+
+#endif // VMIME_HAVE_FILESYSTEM_FEATURES
diff --git a/vmime-master/src/vmime/fileAttachment.hpp b/vmime-master/src/vmime/fileAttachment.hpp
new file mode 100644
index 0000000..c77662f
--- /dev/null
+++ b/vmime-master/src/vmime/fileAttachment.hpp
@@ -0,0 +1,226 @@
+//
+// 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_FILEATTACHMENT_HPP_INCLUDED
+#define VMIME_FILEATTACHMENT_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/defaultAttachment.hpp"
+#include "vmime/dateTime.hpp"
+#include "vmime/contentHandler.hpp"
+#include "vmime/utility/stream.hpp"
+
+
+namespace vmime {
+
+
+/** Attachment of type 'file'.
+ */
+class VMIME_EXPORT fileAttachment : public defaultAttachment {
+
+public:
+
+ fileAttachment(
+ const string& filepath,
+ const mediaType& type
+ );
+
+ fileAttachment(
+ const string& filepath,
+ const mediaType& type,
+ const text& desc
+ );
+
+ fileAttachment(
+ const string& filepath,
+ const mediaType& type,
+ const text& desc,
+ const encoding& enc
+ );
+
+ fileAttachment(
+ const shared_ptr <contentHandler>& cts,
+ const word& filename,
+ const mediaType& type
+ );
+
+ fileAttachment(
+ const shared_ptr <contentHandler>& cts,
+ const word& filename,
+ const mediaType& type,
+ const text& desc
+ );
+
+ fileAttachment(
+ const shared_ptr <contentHandler>& cts,
+ const word& filename,
+ const mediaType& type,
+ const text& desc,
+ const encoding& enc
+ );
+
+ /** Stores information about a file attachment.
+ */
+ class VMIME_EXPORT fileInfo {
+
+ public:
+
+ fileInfo();
+ ~fileInfo();
+
+ /** Check whether the 'filename' property is present.
+ *
+ * @return true if the 'filename' property is set,
+ * false otherwise
+ */
+ bool hasFilename() const;
+
+ /** Return the value of the 'filename' property.
+ *
+ * @return file name
+ */
+ const word& getFilename() const;
+
+ /** Set the value of the 'filename' property.
+ *
+ * @param name file name
+ */
+ void setFilename(const string& name);
+
+ /** Set the value of the 'filename' property.
+ *
+ * @param name file name
+ */
+ void setFilename(const word& name);
+
+ /** Check whether the 'creation-date' property is present.
+ *
+ * @return true if the 'creation-date' property is set,
+ * false otherwise
+ */
+ bool hasCreationDate() const;
+
+ /** Return the value of the 'creation-date' property.
+ *
+ * @return file creation time
+ */
+ const datetime& getCreationDate() const;
+
+ /** Set the value of the 'creation-date' property.
+ *
+ * @param date file creation time
+ */
+ void setCreationDate(const datetime& date);
+
+ /** Check whether the 'modification-date' property is present.
+ *
+ * @return true if the 'modification-date' property is set,
+ * false otherwise
+ */
+ bool hasModificationDate() const;
+
+ /** Return the value of the 'modification-date' property.
+ *
+ * @return file modification time
+ */
+ const datetime& getModificationDate() const;
+
+ /** Set the value of the 'modification-date' property.
+ *
+ * @param date file modification time
+ */
+ void setModificationDate(const datetime& date);
+
+ /** Check whether the 'read-date' property is set.
+ *
+ * @return true if the 'read-date' property is set,
+ * false otherwise
+ */
+ bool hasReadDate() const;
+
+ /** Return the value of the 'read-date' property.
+ *
+ * @return file access time
+ */
+ const datetime& getReadDate() const;
+
+ /** Set the value of the 'read-date' property.
+ *
+ * @param date file access time
+ */
+ void setReadDate(const datetime& date);
+
+ /** Check whether the value of the 'size' property is set.
+ *
+ * @return true if the 'size' property is set,
+ * false otherwise
+ */
+ bool hasSize() const;
+
+ /** Return the value of the 'size' property.
+ *
+ * @return file size
+ */
+ size_t getSize() const;
+
+ /** Set the value of the 'size' property.
+ *
+ * @param size file size
+ */
+ void setSize(const size_t size);
+
+ private:
+
+ word* m_filename;
+ size_t * m_size;
+ datetime* m_creationDate;
+ datetime* m_modifDate;
+ datetime* m_readDate;
+ };
+
+ const fileInfo& getFileInfo() const;
+ fileInfo& getFileInfo();
+
+private:
+
+ void setData(const string& filepath);
+ void setData(const shared_ptr <contentHandler>& cts);
+
+ fileInfo m_fileInfo;
+
+ void generatePart(const shared_ptr <bodyPart>& part) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_HAVE_FILESYSTEM_FEATURES
+
+#endif // VMIME_FILEATTACHMENT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/fileContentHandler.cpp b/vmime-master/src/vmime/fileContentHandler.cpp
new file mode 100644
index 0000000..baedf69
--- /dev/null
+++ b/vmime-master/src/vmime/fileContentHandler.cpp
@@ -0,0 +1,94 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/fileContentHandler.hpp"
+
+
+namespace vmime {
+
+
+fileContentHandler::fileContentHandler()
+ : streamContentHandler() {
+
+}
+
+
+fileContentHandler::fileContentHandler(
+ const shared_ptr <utility::file>& file,
+ const vmime::encoding& enc
+) {
+
+ setData(file, enc);
+}
+
+
+fileContentHandler::~fileContentHandler() {
+
+}
+
+
+fileContentHandler::fileContentHandler(const fileContentHandler& cts)
+ : streamContentHandler() {
+
+ setData(cts.m_file, cts.m_encoding);
+}
+
+
+fileContentHandler& fileContentHandler::operator=(const fileContentHandler& cts) {
+
+ setData(cts.m_file, cts.m_encoding);
+
+ return *this;
+}
+
+
+shared_ptr <contentHandler> fileContentHandler::clone() const {
+
+ return make_shared <fileContentHandler>(*this);
+}
+
+
+void fileContentHandler::setData(
+ const shared_ptr <utility::file>& file,
+ const vmime::encoding& enc
+) {
+
+ m_file = file;
+ m_encoding = enc;
+
+ streamContentHandler::setData(
+ file->getFileReader()->getInputStream(), file->getLength(), enc
+ );
+}
+
+
+} // vmime
+
+
+#endif // VMIME_HAVE_FILESYSTEM_FEATURES
diff --git a/vmime-master/src/vmime/fileContentHandler.hpp b/vmime-master/src/vmime/fileContentHandler.hpp
new file mode 100644
index 0000000..80df069
--- /dev/null
+++ b/vmime-master/src/vmime/fileContentHandler.hpp
@@ -0,0 +1,102 @@
+//
+// 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_FILECONTENTHANDLER_HPP_INCLUDED
+#define VMIME_FILECONTENTHANDLER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/streamContentHandler.hpp"
+#include "vmime/utility/file.hpp"
+
+
+namespace vmime {
+
+
+/** A content handler which obtains its data from a file.
+ */
+class VMIME_EXPORT fileContentHandler : public streamContentHandler {
+
+public:
+
+ /** Creates a new empty content handler. No data can be extracted until
+ * a file is attached using setData() function.
+ *
+ * @return a reference to a new content handler
+ */
+ fileContentHandler();
+
+ /** Creates a new content handler using a file.
+ *
+ * @param file file from which data will be obtained
+ * @param enc set to anything other than NO_ENCODING if the data contained
+ * in the file is already encoded with the specified encoding
+ *
+ * @return a reference to a new content handler
+ */
+ fileContentHandler(
+ const shared_ptr <utility::file>& file,
+ const vmime::encoding& enc = NO_ENCODING
+ );
+
+ ~fileContentHandler();
+
+ fileContentHandler(const fileContentHandler& cts);
+ fileContentHandler& operator=(const fileContentHandler& cts);
+
+ shared_ptr <contentHandler> clone() const;
+
+ /** Sets the data managed by this content handler.
+ *
+ * @param file file from which data will be obtained
+ * @param enc set to anything other than NO_ENCODING if the data contained
+ * in the file is already encoded with the specified encoding
+ */
+ void setData(
+ const shared_ptr <utility::file>& file,
+ const vmime::encoding& enc = NO_ENCODING
+ );
+
+private:
+
+ // Equals to NO_ENCODING if data is not encoded, otherwise this
+ // specifies the encoding that have been used to encode the data.
+ vmime::encoding m_encoding;
+
+ // Actual data
+ shared_ptr <utility::file> m_file;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#endif // VMIME_FILECONTENTHANDLER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/generatedMessageAttachment.cpp b/vmime-master/src/vmime/generatedMessageAttachment.cpp
new file mode 100644
index 0000000..ad9e678
--- /dev/null
+++ b/vmime-master/src/vmime/generatedMessageAttachment.cpp
@@ -0,0 +1,108 @@
+//
+// 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.
+//
+
+#include "vmime/generatedMessageAttachment.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+
+namespace vmime {
+
+
+generatedMessageAttachment::generatedMessageAttachment(
+ const shared_ptr <const bodyPart>& part
+)
+ : m_bpa(make_shared <bodyPartAttachment>(part)) {
+
+}
+
+
+const mediaType generatedMessageAttachment::getType() const {
+
+ return mediaType(mediaTypes::MESSAGE, mediaTypes::MESSAGE_RFC822);
+}
+
+
+const text generatedMessageAttachment::getDescription() const {
+
+ return m_bpa->getDescription();
+}
+
+
+const word generatedMessageAttachment::getName() const {
+
+ return m_bpa->getName();
+}
+
+
+const shared_ptr <const contentHandler> generatedMessageAttachment::getData() const {
+
+ return m_bpa->getData();
+}
+
+
+const encoding generatedMessageAttachment::getEncoding() const {
+
+ return m_bpa->getEncoding();
+}
+
+
+shared_ptr <const object> generatedMessageAttachment::getPart() const {
+
+ return m_bpa->getPart();
+}
+
+
+shared_ptr <const header> generatedMessageAttachment::getHeader() const {
+
+ return m_bpa->getHeader();
+}
+
+
+shared_ptr <message> generatedMessageAttachment::getMessage() const {
+
+ if (!m_msg) {
+
+ // Extract data
+ std::ostringstream oss;
+ utility::outputStreamAdapter os(oss);
+
+ getData()->extract(os);
+
+ // Parse message
+ m_msg = make_shared <message>();
+ m_msg->parse(oss.str());
+ }
+
+ return m_msg;
+}
+
+
+void generatedMessageAttachment::generateIn(const shared_ptr <bodyPart>& /* parent */) const {
+
+ // Not used (see 'parsedMessageAttachment')
+}
+
+
+} // vmime
+
diff --git a/vmime-master/src/vmime/generatedMessageAttachment.hpp b/vmime-master/src/vmime/generatedMessageAttachment.hpp
new file mode 100644
index 0000000..b65fcc1
--- /dev/null
+++ b/vmime-master/src/vmime/generatedMessageAttachment.hpp
@@ -0,0 +1,77 @@
+//
+// 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_GENERATEDMESSAGEATTACHMENT_HPP_INCLUDED
+#define VMIME_GENERATEDMESSAGEATTACHMENT_HPP_INCLUDED
+
+
+#ifndef VMIME_BUILDING_DOC // implementation detail
+
+
+#include "vmime/messageAttachment.hpp"
+#include "vmime/bodyPartAttachment.hpp"
+
+
+namespace vmime {
+
+
+/** A message attachment that can be extracted from a message.
+ */
+class VMIME_EXPORT generatedMessageAttachment : public messageAttachment {
+
+public:
+
+ generatedMessageAttachment(const shared_ptr <const bodyPart>& part);
+
+ const mediaType getType() const;
+ const text getDescription() const;
+ const word getName() const;
+
+ const shared_ptr <const contentHandler> getData() const;
+
+ const encoding getEncoding() const;
+
+ shared_ptr <const object> getPart() const;
+
+ shared_ptr <const header> getHeader() const;
+
+ shared_ptr <message> getMessage() const;
+
+protected:
+
+ void generateIn(const shared_ptr <bodyPart>& parent) const;
+
+private:
+
+ shared_ptr <bodyPartAttachment> m_bpa;
+ mutable shared_ptr <message> m_msg;
+};
+
+
+} // vmime
+
+
+#endif // !VMIME_BUILDING_DOC
+
+
+#endif // VMIME_GENERATEDMESSAGEATTACHMENT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/generationContext.cpp b/vmime-master/src/vmime/generationContext.cpp
new file mode 100644
index 0000000..24757c7
--- /dev/null
+++ b/vmime-master/src/vmime/generationContext.cpp
@@ -0,0 +1,139 @@
+//
+// 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.
+//
+
+#include "vmime/generationContext.hpp"
+
+
+namespace vmime {
+
+
+generationContext::generationContext()
+ : m_maxLineLength(lineLengthLimits::convenient),
+ m_prologText("This is a multi-part message in MIME format. Your mail reader " \
+ "does not understand MIME message format."),
+ m_epilogText(""),
+ m_wrapMessageId(true),
+ m_paramValueMode(PARAMETER_VALUE_RFC2231_ONLY) {
+
+}
+
+
+generationContext::generationContext(const generationContext& ctx)
+ : context(ctx),
+ m_maxLineLength(ctx.m_maxLineLength),
+ m_prologText(ctx.m_prologText),
+ m_epilogText(ctx.m_epilogText),
+ m_wrapMessageId(ctx.m_wrapMessageId),
+ m_paramValueMode(ctx.m_paramValueMode) {
+
+}
+
+
+generationContext& generationContext::getDefaultContext() {
+
+ static generationContext ctx;
+ return ctx;
+}
+
+
+size_t generationContext::getMaxLineLength() const {
+
+ return m_maxLineLength;
+}
+
+
+void generationContext::setMaxLineLength(const size_t maxLineLength) {
+
+ m_maxLineLength = maxLineLength;
+}
+
+
+
+const string generationContext::getPrologText() const {
+
+ return m_prologText;
+}
+
+
+void generationContext::setPrologText(const string& prologText) {
+
+ m_prologText = prologText;
+}
+
+
+const string generationContext::getEpilogText() const {
+
+ return m_epilogText;
+}
+
+
+void generationContext::setEpilogText(const string& epilogText) {
+
+ m_epilogText = epilogText;
+}
+
+
+bool generationContext::getWrapMessageId() const {
+
+ return m_wrapMessageId;
+}
+
+
+void generationContext::setWrapMessageId(const bool& wrapMessageId) {
+
+ m_wrapMessageId = wrapMessageId;
+}
+
+
+void generationContext::setEncodedParameterValueMode(const EncodedParameterValueModes mode) {
+
+ m_paramValueMode = mode;
+}
+
+
+generationContext::EncodedParameterValueModes
+ generationContext::getEncodedParameterValueMode() const {
+
+ return m_paramValueMode;
+}
+
+
+generationContext& generationContext::operator=(const generationContext& ctx) {
+
+ copyFrom(ctx);
+ return *this;
+}
+
+
+void generationContext::copyFrom(const generationContext& ctx) {
+
+ context::copyFrom(ctx);
+
+ m_maxLineLength = ctx.m_maxLineLength;
+ m_prologText = ctx.m_prologText;
+ m_epilogText = ctx.m_epilogText;
+ m_paramValueMode = ctx.m_paramValueMode;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/generationContext.hpp b/vmime-master/src/vmime/generationContext.hpp
new file mode 100644
index 0000000..5e36513
--- /dev/null
+++ b/vmime-master/src/vmime/generationContext.hpp
@@ -0,0 +1,171 @@
+//
+// 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_GENERATIONCONTEXT_HPP_INCLUDED
+#define VMIME_GENERATIONCONTEXT_HPP_INCLUDED
+
+
+#include "vmime/context.hpp"
+
+
+namespace vmime {
+
+
+/** Holds configuration parameters used for generating messages.
+ */
+class VMIME_EXPORT generationContext : public context {
+
+public:
+
+ generationContext();
+ generationContext(const generationContext& ctx);
+
+ /** Returns the current maximum line length used when generating messages.
+ *
+ * @return current maximum line length, in bytes
+ */
+ size_t getMaxLineLength() const;
+
+ /** Sets the maximum line length used when generating messages.
+ * You may use the constants lineLengthLimits::convenient,
+ * lineLengthLimits::max and lineLengthLimits::infinite.
+ *
+ * @param maxLineLength new maximum line length, in bytes
+ */
+ void setMaxLineLength(const size_t maxLineLength);
+
+ /** Returns the current prolog text used when generating MIME body parts.
+ *
+ * @return current MIME prolog text
+ */
+ const string getPrologText() const;
+
+ /** Sets the prolog text used when generating MIME body parts. This text
+ * appears before the part, and should be displayed by MUAs which do not
+ * support MIME. This should be 7-bit ASCII text only.
+ *
+ * @param prologText MIME prolog text
+ */
+ void setPrologText(const string& prologText);
+
+ /** Returns the current epilog text used when generating MIME body parts.
+ *
+ * @return current MIME epilog text
+ */
+ const string getEpilogText() const;
+
+ /** Sets the epilog text used when generating MIME body parts. This test
+ * appears after the part, and should be displayed by MUAs which do not
+ * support MIME. This should be 7-bit ASCII text only.
+ */
+ void setEpilogText(const string& epilogText);
+
+ /** Returns a boolean variable that indicates whether the
+ * message id can be wrapped or not, i.e. from
+ *
+ * Message-Id: <very very long@domain>
+ *
+ * to
+ *
+ * Message-Id:
+ * <very very long@domain>
+ *
+ * @return boolean indicating if the Message-Id can be wrapped
+ */
+ bool getWrapMessageId() const;
+
+ /** Sets the boolean variable that indicates whether the
+ * Message-Id can be wrapped or not
+ */
+ void setWrapMessageId(const bool& wrapMessageId);
+
+ /** Modes available for generating values in parameterized header fields.
+ */
+ enum EncodedParameterValueModes {
+
+ PARAMETER_VALUE_NO_ENCODING, /**< Only generate 7-bit (ASCII-only) values,
+ even if the value contains non-ASCII chars or
+ if folding is needed. */
+ PARAMETER_VALUE_RFC2047_ONLY, /**< Only generate RFC-2047 values (do not use
+ RFC-2231). This is non-standard but most
+ mail clients support it. */
+ PARAMETER_VALUE_RFC2231_ONLY, /**< Only generate RFC-2231 values (do not use
+ RFC-2047). Some mail clients may not support
+ it. This is the default. */
+ PARAMETER_VALUE_RFC2231_AND_RFC2047 /**< Generate both RFC-2047- and RFC-2231-encoded
+ values. */
+ };
+
+ /** Sets the mode used for generating parameter values in a parameterized
+ * header field (see parameterizedHeaderField class).
+ *
+ * PARAMETER_VALUE_NO_ENCODING or PARAMETER_VALUE_RFC2047_ONLY
+ * can be used for compatibility with implementations that do not
+ * understand RFC-2231, to generate a normal parameter value.
+ * PARAMETER_VALUE_RFC2047_ONLY is non-standard (and expressly
+ * prohibited by the RFC) but most mail clients support it.
+ *
+ * Notice: if both the normal value and the extended value are present,
+ * the latter can be ignored by mail processing systems. This may lead
+ * to annoying problems, for example, with strange names of attachments
+ * with all but 7-bit ascii characters removed, etc. Either
+ * PARAMETER_VALUE_RFC2231_ONLY or PARAMETER_VALUE_RFC2047_ONLY should
+ * be preferred over PARAMETER_VALUE_RFC2231_AND_RFC2047, not to create
+ * a normal value if the extended value is to be generated.
+ *
+ * @param mode parameter value generation mode
+ */
+ void setEncodedParameterValueMode(const EncodedParameterValueModes mode);
+
+ /** Returns the mode used for generating parameter values in a parameterized
+ * header field (see parameterizedHeaderField class).
+ *
+ * @return parameter value generation mode
+ */
+ EncodedParameterValueModes getEncodedParameterValueMode() const;
+
+ /** Returns the default context used for generating messages.
+ *
+ * @return a reference to the default generation context
+ */
+ static generationContext& getDefaultContext();
+
+ generationContext& operator=(const generationContext& ctx);
+ void copyFrom(const generationContext& ctx);
+
+protected:
+
+ size_t m_maxLineLength;
+
+ string m_prologText;
+ string m_epilogText;
+ bool m_wrapMessageId;
+
+ EncodedParameterValueModes m_paramValueMode;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_GENERATIONCONTEXT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/header.cpp b/vmime-master/src/vmime/header.cpp
new file mode 100644
index 0000000..c7d7ca0
--- /dev/null
+++ b/vmime-master/src/vmime/header.cpp
@@ -0,0 +1,417 @@
+//
+// 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.
+//
+
+#include "vmime/header.hpp"
+#include "vmime/parserHelpers.hpp"
+
+#include <algorithm>
+#include <iterator>
+
+
+namespace vmime {
+
+
+header::header() {
+
+}
+
+
+header::~header() {
+
+ removeAllFields();
+}
+
+
+/*
+
+ RFC #822:
+ 3.2. HEADER FIELD DEFINITIONS
+
+field = field-name ":" [ field-body ] CRLF
+
+field-name = 1*<any CHAR, excluding CTLs, SPACE, and ":">
+
+field-body = field-body-contents
+ [CRLF LWSP-char field-body]
+
+field-body-contents =
+ <the ASCII characters making up the field-body, as
+ defined in the following sections, and consisting
+ of combinations of atom, quoted-string, and
+ specials tokens, or else consisting of texts>
+*/
+
+void header::parseImpl(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ size_t pos = position;
+
+ removeAllFields();
+
+ while (pos < end) {
+
+ shared_ptr <headerField> field = headerField::parseNext(ctx, buffer, pos, end, &pos);
+ if (!field) break;
+
+ m_fields.push_back(field);
+ }
+
+ setParsedBounds(position, pos);
+
+ if (newPosition) {
+ *newPosition = pos;
+ }
+}
+
+
+void header::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t /* curLinePos */,
+ size_t* newLinePos
+) const {
+
+ // Generate the fields
+ for (std::vector <shared_ptr <headerField> >::const_iterator it = m_fields.begin() ;
+ it != m_fields.end() ; ++it) {
+
+ (*it)->generate(ctx, os);
+ os << CRLF;
+ }
+
+ if (newLinePos) {
+ *newLinePos = 0;
+ }
+}
+
+
+size_t header::getGeneratedSize(const generationContext& ctx) {
+
+ return component::getGeneratedSize(ctx) + 2 * m_fields.size() /* CRLF */;
+}
+
+
+shared_ptr <component> header::clone() const {
+
+ shared_ptr <header> hdr = make_shared <header>();
+
+ hdr->m_fields.reserve(m_fields.size());
+
+ for (std::vector <shared_ptr <headerField> >::const_iterator it = m_fields.begin() ;
+ it != m_fields.end() ; ++it) {
+
+ hdr->m_fields.push_back(vmime::clone(*it));
+ }
+
+ return hdr;
+}
+
+
+void header::copyFrom(const component& other) {
+
+ const header& h = dynamic_cast <const header&>(other);
+
+ std::vector <shared_ptr <headerField> > fields;
+
+ fields.reserve(h.m_fields.size());
+
+ for (std::vector <shared_ptr <headerField> >::const_iterator it = h.m_fields.begin() ;
+ it != h.m_fields.end() ; ++it) {
+
+ fields.push_back(vmime::clone(*it));
+ }
+
+ m_fields.clear();
+ m_fields.resize(fields.size());
+
+ std::copy(fields.begin(), fields.end(), m_fields.begin());
+}
+
+
+header& header::operator=(const header& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+bool header::hasField(const string& fieldName) const {
+
+ std::vector <shared_ptr <headerField> >::const_iterator pos =
+ std::find_if(
+ m_fields.begin(), m_fields.end(),
+ fieldHasName(utility::stringUtils::toLower(fieldName))
+ );
+
+ return pos != m_fields.end();
+}
+
+
+shared_ptr <headerField> header::findField(const string& fieldName) const {
+
+ // Find the first field that matches the specified name
+ std::vector <shared_ptr <headerField> >::const_iterator pos =
+ std::find_if(
+ m_fields.begin(), m_fields.end(),
+ fieldHasName(utility::stringUtils::toLower(fieldName))
+ );
+
+ // No field with this name can be found
+ if (pos == m_fields.end()) {
+ return null;
+ }
+
+ // Else, return a reference to the existing field
+ return *pos;
+}
+
+
+std::vector <shared_ptr <headerField> > header::findAllFields(const string& fieldName) {
+
+ std::vector <shared_ptr <headerField> > result;
+ std::back_insert_iterator <std::vector <shared_ptr <headerField> > > back(result);
+
+ std::remove_copy_if(
+ m_fields.begin(), m_fields.end(), back,
+ fieldHasNotName(utility::stringUtils::toLower(fieldName))
+ );
+
+ return result;
+}
+
+
+shared_ptr <headerField> header::getField(const string& fieldName) {
+
+ const string name = utility::stringUtils::toLower(fieldName);
+
+ // Find the first field that matches the specified name
+ std::vector <shared_ptr <headerField> >::const_iterator pos = m_fields.begin();
+ const std::vector <shared_ptr <headerField> >::const_iterator end = m_fields.end();
+
+ while (pos != end && utility::stringUtils::toLower((*pos)->getName()) != name) {
+ ++pos;
+ }
+
+ // If no field with this name can be found, create a new one
+ if (pos == end) {
+
+ shared_ptr <headerField> field = headerFieldFactory::getInstance()->create(fieldName);
+
+ appendField(field);
+
+ // Return a reference to the new field
+ return (field);
+
+ // Else, return a reference to the existing field
+ } else {
+
+ return *pos;
+ }
+}
+
+
+void header::appendField(const shared_ptr <headerField>& field) {
+
+ m_fields.push_back(field);
+}
+
+
+void header::insertFieldBefore(
+ const shared_ptr <headerField>& beforeField,
+ const shared_ptr <headerField>& field
+) {
+
+ const std::vector <shared_ptr <headerField> >::iterator it =
+ std::find(m_fields.begin(), m_fields.end(), beforeField);
+
+ if (it == m_fields.end()) {
+ throw exceptions::no_such_field();
+ }
+
+ m_fields.insert(it, field);
+}
+
+
+void header::insertFieldBefore(const size_t pos, const shared_ptr <headerField>& field) {
+
+ m_fields.insert(m_fields.begin() + pos, field);
+}
+
+
+void header::insertFieldAfter(
+ const shared_ptr <headerField>& afterField,
+ const shared_ptr <headerField>& field
+) {
+
+ const std::vector <shared_ptr <headerField> >::iterator it =
+ std::find(m_fields.begin(), m_fields.end(), afterField);
+
+ if (it == m_fields.end()) {
+ throw exceptions::no_such_field();
+ }
+
+ m_fields.insert(it + 1, field);
+}
+
+
+void header::insertFieldAfter(const size_t pos, const shared_ptr <headerField>& field) {
+
+ m_fields.insert(m_fields.begin() + pos + 1, field);
+}
+
+
+void header::removeField(const shared_ptr <headerField>& field) {
+
+ const std::vector <shared_ptr <headerField> >::iterator it =
+ std::find(m_fields.begin(), m_fields.end(), field);
+
+ if (it == m_fields.end()) {
+ throw exceptions::no_such_field();
+ }
+
+ m_fields.erase(it);
+}
+
+
+void header::removeField(const size_t pos) {
+
+ const std::vector <shared_ptr <headerField> >::iterator it = m_fields.begin() + pos;
+
+ m_fields.erase(it);
+}
+
+
+void header::replaceField(
+ const shared_ptr <headerField>& field,
+ const shared_ptr <headerField>& newField
+) {
+
+ insertFieldBefore(field, newField);
+ removeField(field);
+}
+
+
+void header::removeAllFields() {
+
+ m_fields.clear();
+}
+
+
+void header::removeAllFields(const string& fieldName) {
+
+ std::vector <shared_ptr <headerField> > fields = findAllFields(fieldName);
+
+ for (unsigned int i = 0 ; i < fields.size() ; ++i) {
+ removeField(fields[i]);
+ }
+}
+
+
+size_t header::getFieldCount() const {
+
+ return m_fields.size();
+}
+
+
+bool header::isEmpty() const {
+
+ return m_fields.empty();
+}
+
+
+const shared_ptr <headerField> header::getFieldAt(const size_t pos) {
+
+ return m_fields[pos];
+}
+
+
+const shared_ptr <const headerField> header::getFieldAt(const size_t pos) const {
+
+ return m_fields[pos];
+}
+
+
+const std::vector <shared_ptr <const headerField> > header::getFieldList() const {
+
+ std::vector <shared_ptr <const headerField> > list;
+
+ list.reserve(m_fields.size());
+
+ for (std::vector <shared_ptr <headerField> >::const_iterator it = m_fields.begin() ;
+ it != m_fields.end() ; ++it) {
+
+ list.push_back(*it);
+ }
+
+ return list;
+}
+
+
+const std::vector <shared_ptr <headerField> > header::getFieldList() {
+
+ return m_fields;
+}
+
+
+const std::vector <shared_ptr <component> > header::getChildComponents() {
+
+ std::vector <shared_ptr <component> > list;
+
+ copy_vector(m_fields, list);
+
+ return list;
+}
+
+
+
+// Field search
+
+
+header::fieldHasName::fieldHasName(const string& name)
+ : m_name(name) {
+
+}
+
+bool header::fieldHasName::operator() (const shared_ptr <const headerField>& field) {
+
+ return utility::stringUtils::toLower(field->getName()) == m_name;
+}
+
+
+header::fieldHasNotName::fieldHasNotName(const string& name)
+ : m_name(name) {
+
+}
+
+bool header::fieldHasNotName::operator() (const shared_ptr <const headerField>& field) {
+
+ return utility::stringUtils::toLower(field->getName()) != m_name;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/header.hpp b/vmime-master/src/vmime/header.hpp
new file mode 100644
index 0000000..7b4a161
--- /dev/null
+++ b/vmime-master/src/vmime/header.hpp
@@ -0,0 +1,362 @@
+//
+// 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_HEADER_HPP_INCLUDED
+#define VMIME_HEADER_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/component.hpp"
+#include "vmime/exception.hpp"
+
+#include "vmime/headerField.hpp"
+#include "vmime/headerFieldFactory.hpp"
+
+
+namespace vmime {
+
+
+class bodyPart;
+
+
+/** Header section of a MIME part.
+ */
+class VMIME_EXPORT header : public component {
+
+ friend class bodyPart;
+ friend class body;
+ friend class message;
+
+public:
+
+ header();
+ ~header();
+
+#define FIELD_ACCESS(methodName, fieldName) \
+ shared_ptr <headerField> methodName() { return getField(fields::fieldName); } \
+ shared_ptr <const headerField> methodName() const { return findField(fields::fieldName); }
+
+ FIELD_ACCESS(From, FROM)
+ FIELD_ACCESS(Sender, SENDER)
+ FIELD_ACCESS(ReplyTo, REPLY_TO)
+ FIELD_ACCESS(DeliveredTo, DELIVERED_TO)
+ FIELD_ACCESS(InReplyTo, IN_REPLY_TO)
+ FIELD_ACCESS(ReturnPath, RETURN_PATH)
+ FIELD_ACCESS(References, REFERENCES)
+
+ FIELD_ACCESS(To, TO)
+ FIELD_ACCESS(Cc, CC)
+ FIELD_ACCESS(Bcc, BCC)
+ FIELD_ACCESS(Date, DATE)
+ FIELD_ACCESS(Subject, SUBJECT)
+ FIELD_ACCESS(Organization, ORGANIZATION)
+ FIELD_ACCESS(UserAgent, USER_AGENT)
+
+ FIELD_ACCESS(ContentType, CONTENT_TYPE)
+ FIELD_ACCESS(ContentDescription, CONTENT_DESCRIPTION)
+ FIELD_ACCESS(ContentTransferEncoding, CONTENT_TRANSFER_ENCODING)
+ FIELD_ACCESS(MimeVersion, MIME_VERSION)
+ FIELD_ACCESS(ContentDisposition, CONTENT_DISPOSITION)
+ FIELD_ACCESS(ContentId, CONTENT_ID)
+ FIELD_ACCESS(MessageId, MESSAGE_ID)
+ FIELD_ACCESS(ContentLocation, CONTENT_LOCATION)
+
+ FIELD_ACCESS(OriginalMessageId, ORIGINAL_MESSAGE_ID)
+ FIELD_ACCESS(Disposition, DISPOSITION)
+ FIELD_ACCESS(DispositionNotificationTo, DISPOSITION_NOTIFICATION_TO)
+
+#undef FIELD_ACCESS
+
+ /** Checks whether (at least) one field with this name exists.
+ * Field name is case-insensitive.
+ *
+ * @return true if at least one field with the specified name
+ * exists, or false otherwise
+ */
+ bool hasField(const string& fieldName) const;
+
+ /** Find the first field that matches the specified name.
+ * Field name is case-insensitive.
+ * If no field is found, NULL is returned.
+ *
+ * @param fieldName name of field to return (eg: "X-Mailer" or "From",
+ * common field names are available in the vmime::fields namespace)
+ * @return first field with the specified name, or NULL if no field
+ * with this name was found
+ */
+ shared_ptr <headerField> findField(const string& fieldName) const;
+
+ /** Find the first field that matches the specified name,
+ * casted to the specified field type. Field name is case-insensitive.
+ * If no field is found, or the field is not of the specified type,
+ * NULL is returned.
+ *
+ * @param fieldName name of field whose value is to be returned
+ * (eg: "X-Mailer" or "From", common field names are available in
+ * the vmime::fields namespace)
+ * @return first field with the specified name, or NULL if no field
+ * with this name was found
+ */
+ template <typename T>
+ shared_ptr <T> findField(const string& fieldName) const {
+
+ return dynamicCast <T>(findField(fieldName));
+ }
+
+ /** Find the value of the first field that matches the specified name,
+ * casted to the specified value type. Field name is case-insensitive.
+ * If no field is found, or the field value is not of the specified
+ * type, NULL is returned.
+ *
+ * @param fieldName name of field to return (eg: "X-Mailer" or "From",
+ * common field names are available in the vmime::fields namespace)
+ * @return value of the first field with the specified name, or NULL
+ * if no field with this name was found, or the value is not of the
+ * specified type
+ */
+ template <typename T>
+ shared_ptr <T> findFieldValue(const string& fieldName) const {
+
+ shared_ptr <headerField> field = findField(fieldName);
+
+ if (field) {
+ return dynamicCast <T>(field->getValue());
+ } else {
+ return null;
+ }
+ }
+
+ /** Find all fields that match the specified name.
+ * If no field is found, an empty vector is returned.
+ *
+ * @param fieldName name of field to return (eg: "X-Mailer" or "From",
+ * common field names are available in the vmime::fields namespace)
+ * @return list of fields with the specified name
+ */
+ std::vector <shared_ptr <headerField> > findAllFields(const string& fieldName);
+
+ /** Find the first field that matches the specified name.
+ * If no field is found, one will be created and inserted into
+ * the header.
+ *
+ * @param fieldName name of field to return (eg: "X-Mailer" or "From",
+ * common field names are available in the vmime::fields namespace)
+ * @return first field with the specified name or a new field
+ * if no field is found
+ */
+ shared_ptr <headerField> getField(const string& fieldName);
+
+ /** Find the first field that matches the specified name,
+ * casted to the specified type.
+ * If no field is found, one will be created and inserted into
+ * the header.
+ *
+ * @return first field with the specified name or a new field
+ * if no field is found
+ */
+ template <typename T>
+ shared_ptr <T> getField(const string& fieldName) {
+
+ return dynamicCast <T>(getField(fieldName));
+ }
+
+ /** Add a field at the end of the list.
+ *
+ * @param field field to append
+ */
+ void appendField(const shared_ptr <headerField>& field);
+
+ /** Insert a new field before the specified field.
+ *
+ * @param beforeField field before which the new field will be inserted
+ * @param field field to insert
+ * @throw exceptions::no_such_field if the field is not in the list
+ */
+ void insertFieldBefore(
+ const shared_ptr <headerField>& beforeField,
+ const shared_ptr <headerField>& field
+ );
+
+ /** Insert a new field before the specified position.
+ *
+ * @param pos position at which to insert the new field (0 to insert at
+ * the beginning of the list)
+ * @param field field to insert
+ */
+ void insertFieldBefore(
+ const size_t pos,
+ const shared_ptr <headerField>& field
+ );
+
+ /** Insert a new field after the specified field.
+ *
+ * @param afterField field after which the new field will be inserted
+ * @param field field to insert
+ * @throw exceptions::no_such_field if the field is not in the list
+ */
+ void insertFieldAfter(
+ const shared_ptr <headerField>& afterField,
+ const shared_ptr <headerField>& field
+ );
+
+ /** Insert a new field after the specified position.
+ *
+ * @param pos position of the field before the new field
+ * @param field field to insert
+ */
+ void insertFieldAfter(
+ const size_t pos,
+ const shared_ptr <headerField>& field
+ );
+
+ /** Remove the specified field from the list.
+ *
+ * @param field field to remove
+ * @throw exceptions::no_such_field if the field is not in the list
+ */
+ void removeField(const shared_ptr <headerField>& field);
+
+ /** Remove the field at the specified position.
+ *
+ * @param pos position of the field to remove
+ */
+ void removeField(const size_t pos);
+
+ /** Replaces a field with another field.
+ *
+ * @param field field to be replaced
+ * @param newField field to replace with
+ * @throw exceptions::no_such_field if the field is not in the list
+ */
+ void replaceField(
+ const shared_ptr <headerField>& field,
+ const shared_ptr <headerField>& newField
+ );
+
+ /** Remove all fields from the list.
+ */
+ void removeAllFields();
+
+ /** Remove all fields with the specified name.
+ */
+ void removeAllFields(const string& fieldName);
+
+ /** Return the number of fields in the list.
+ *
+ * @return number of fields
+ */
+ size_t getFieldCount() const;
+
+ /** Tests whether the list of fields is empty.
+ *
+ * @return true if there is no field, false otherwise
+ */
+ bool isEmpty() const;
+
+ /** Return the field at the specified position.
+ *
+ * @param pos position
+ * @return field at position 'pos'
+ */
+ const shared_ptr <headerField> getFieldAt(const size_t pos);
+
+ /** Return the field at the specified position.
+ *
+ * @param pos position
+ * @return field at position 'pos'
+ */
+ const shared_ptr <const headerField> getFieldAt(const size_t pos) const;
+
+ /** Return the field list.
+ *
+ * @return list of fields
+ */
+ const std::vector <shared_ptr <const headerField> > getFieldList() const;
+
+ /** Return the field list.
+ *
+ * @return list of fields
+ */
+ const std::vector <shared_ptr <headerField> > getFieldList();
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ header& operator=(const header& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+ size_t getGeneratedSize(const generationContext& ctx);
+
+private:
+
+ std::vector <shared_ptr <headerField> > m_fields;
+
+
+ class fieldHasName {
+
+ public:
+
+ fieldHasName(const string& name);
+ bool operator() (const shared_ptr <const headerField>& field);
+
+ private:
+
+ string m_name;
+ };
+
+ class fieldHasNotName {
+
+ public:
+
+ fieldHasNotName(const string& name);
+ bool operator() (const shared_ptr <const headerField>& field);
+
+ private:
+
+ string m_name;
+ };
+
+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 generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_HEADER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/headerField.cpp b/vmime-master/src/vmime/headerField.cpp
new file mode 100644
index 0000000..bff365d
--- /dev/null
+++ b/vmime-master/src/vmime/headerField.cpp
@@ -0,0 +1,374 @@
+//
+// 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.
+//
+
+#include "vmime/headerField.hpp"
+#include "vmime/headerFieldFactory.hpp"
+
+#include "vmime/parserHelpers.hpp"
+
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+
+
+headerField::headerField()
+ : m_name("X-Undefined") {
+
+}
+
+
+headerField::headerField(const string& fieldName)
+ : m_name(fieldName) {
+
+}
+
+
+headerField::~headerField() {
+
+}
+
+
+shared_ptr <component> headerField::clone() const {
+
+ shared_ptr <headerField> field = headerFieldFactory::getInstance()->create(m_name);
+
+ field->copyFrom(*this);
+
+ return field;
+}
+
+
+void headerField::copyFrom(const component& other) {
+
+ const headerField& hf = dynamic_cast <const headerField&>(other);
+
+ m_value->copyFrom(*hf.m_value);
+}
+
+
+headerField& headerField::operator=(const headerField& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+shared_ptr <headerField> headerField::parseNext(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ size_t pos = position;
+
+ while (pos < end) {
+
+ char_t c = buffer[pos];
+
+ // Check for end of headers (empty line): although RFC-822 recommends
+ // to use CRLF for header/body separator (see 4.1 SYNTAX), here, we
+ // also check for LF for compatibility with broken implementations...
+ if (c == '\n') {
+
+ if (newPosition) {
+ *newPosition = pos + 1; // LF: illegal
+ }
+
+ return null;
+
+ } else if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') {
+
+ if (newPosition) {
+ *newPosition = pos + 2; // CR+LF
+ }
+
+ return null;
+ }
+
+ // This line may be a field description
+ if (!parserHelpers::isSpace(c)) {
+
+ const size_t nameStart = pos; // remember the start position of the line
+
+ while (pos < end && (buffer[pos] != ':' && !parserHelpers::isSpace(buffer[pos]))) {
+ ++pos;
+ }
+
+ const size_t nameEnd = pos;
+
+ while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t')) {
+ ++pos;
+ }
+
+ if (buffer[pos] != ':') {
+
+ switch (ctx.getHeaderParseErrorRecoveryMethod()) {
+
+ case vmime::headerParseRecoveryMethod::SKIP_LINE:
+ // Humm...does not seem to be a valid header line.
+ // Skip this error and advance to the next line
+ pos = nameStart;
+
+ while (pos < end && buffer[pos] != '\n') {
+ ++pos;
+ }
+
+ if (pos < end && buffer[pos] == '\n') {
+ ++pos;
+ }
+
+ break;
+
+// case vmime::headerParseRecoveryMethod::APPEND_TO_PREVIOUS_LINE:
+//
+// // TODO Implement this...
+// break;
+
+ case vmime::headerParseRecoveryMethod::ASSUME_END_OF_HEADERS:
+
+ return null;
+ break;
+ }
+
+ } else {
+
+ // Extract the field name
+ const string name(
+ buffer.begin() + nameStart,
+ buffer.begin() + nameEnd
+ );
+
+ // Skip ':' character
+ while (pos < end && buffer[pos] == ':') {
+ ++pos;
+ }
+
+ // Skip spaces between ':' and the field contents
+ while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t')) {
+ ++pos;
+ }
+
+ const size_t contentsStart = pos;
+ size_t contentsEnd = 0;
+
+ bool firstLine = true;
+
+ // Parse field value, taking care of line folding (value on multiple lines)
+ for (size_t eol = 0 ; parserHelpers::findEOL(buffer, pos, end, &eol) ; pos = eol) {
+
+ // If the line does not start with a folding indicator (SPACE or TAB),
+ // and this is not the first line, then stop parsing lines
+ if (!firstLine && !(buffer[pos] == ' ' || buffer[pos] == '\t')) {
+ break;
+ }
+
+ contentsEnd = eol;
+ firstLine = false;
+ }
+
+ if (pos == end && contentsEnd == 0) {
+
+ // End of data, and no CRLF was found at the end
+ contentsEnd = end;
+ }
+
+ // Strip spaces from end of header lines
+ while (contentsEnd > contentsStart &&
+ (buffer[contentsEnd - 1] == ' ' || buffer[contentsEnd - 1] == '\t' ||
+ buffer[contentsEnd - 1] == '\r' || buffer[contentsEnd - 1] == '\n')) {
+
+ contentsEnd--;
+ }
+
+ // Return a new field
+ shared_ptr <headerField> field = headerFieldFactory::getInstance()->create(name);
+
+ field->parse(ctx, buffer, contentsStart, contentsEnd, NULL);
+ field->setParsedBounds(nameStart, pos);
+
+ if (newPosition) {
+ *newPosition = pos;
+ }
+
+ return field;
+ }
+
+ } else {
+
+ // If the line contains only space characters, we assume it is
+ // the end of the headers.
+ while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t')) {
+ ++pos;
+ }
+
+ if (pos < end && buffer[pos] == '\n') {
+
+ if (newPosition) {
+ *newPosition = pos + 1; // LF: illegal
+ }
+
+ return null;
+
+ } else if (pos + 1 < end && buffer[pos] == '\r' && buffer[pos + 1] == '\n') {
+
+ if (newPosition) {
+ *newPosition = pos + 2; // CR+LF
+ }
+
+ return null;
+ }
+
+ // Skip this error and advance to the next line
+ while (pos < end && buffer[pos] != '\n') {
+ ++pos;
+ }
+
+ if (buffer[pos] == '\n') {
+ ++pos;
+ }
+ }
+ }
+
+ if (newPosition) {
+ *newPosition = pos;
+ }
+
+ return null;
+}
+
+
+void headerField::parseImpl(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ m_value->parse(ctx, buffer, position, end, newPosition);
+}
+
+
+void headerField::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ os << m_name + ": ";
+
+ m_value->generate(ctx, os, curLinePos + m_name.length() + 2, newLinePos);
+}
+
+
+size_t headerField::getGeneratedSize(const generationContext& ctx) {
+
+ return m_name.length() + 2 /* ": " */ + m_value->getGeneratedSize(ctx);
+}
+
+
+const string headerField::getName() const {
+
+ return m_name;
+}
+
+
+void headerField::setName(const string& name) {
+
+ m_name = name;
+}
+
+
+bool headerField::isCustom() const {
+
+ return m_name.length() > 2 && m_name[0] == 'X' && m_name[1] == '-';
+}
+
+
+const std::vector <shared_ptr <component> > headerField::getChildComponents() {
+
+ std::vector <shared_ptr <component> > list;
+
+ if (m_value) {
+ list.push_back(m_value);
+ }
+
+ return list;
+}
+
+
+shared_ptr <const headerFieldValue> headerField::getValue() const {
+
+ return m_value;
+}
+
+
+shared_ptr <headerFieldValue> headerField::getValue() {
+
+ return m_value;
+}
+
+
+void headerField::setValue(const shared_ptr <headerFieldValue>& value) {
+
+ if (!headerFieldFactory::getInstance()->isValueTypeValid(*this, *value)) {
+ throw exceptions::bad_field_value_type(getName());
+ }
+
+ if (value != NULL) {
+ m_value = value;
+ }
+}
+
+
+void headerField::setValueConst(const shared_ptr <const headerFieldValue>& value) {
+
+ if (!headerFieldFactory::getInstance()->isValueTypeValid(*this, *value)) {
+ throw exceptions::bad_field_value_type(getName());
+ }
+
+ m_value = vmime::clone(value);
+}
+
+
+void headerField::setValue(const headerFieldValue& value) {
+
+ if (!headerFieldFactory::getInstance()->isValueTypeValid(*this, value)) {
+ throw exceptions::bad_field_value_type(getName());
+ }
+
+ m_value = vmime::clone(value);
+}
+
+
+void headerField::setValue(const string& value) {
+
+ parse(value);
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/headerField.hpp b/vmime-master/src/vmime/headerField.hpp
new file mode 100644
index 0000000..66e9946
--- /dev/null
+++ b/vmime-master/src/vmime/headerField.hpp
@@ -0,0 +1,191 @@
+//
+// 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_HEADERFIELD_HPP_INCLUDED
+#define VMIME_HEADERFIELD_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/component.hpp"
+#include "vmime/headerFieldValue.hpp"
+
+
+namespace vmime {
+
+
+/** Base class for header fields.
+ */
+class VMIME_EXPORT headerField : public component {
+
+ friend class headerFieldFactory;
+ friend class header;
+
+protected:
+
+ // Protected constructor to prevent the user from creating
+ // new objects without using 'headerFieldFactory'
+ headerField();
+ headerField(const string& fieldName);
+
+public:
+
+ ~headerField();
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ headerField& operator=(const headerField& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+ /** Sets the name of this field.
+ *
+ * @param name field name (eg: "From" or "X-MyField").
+ */
+ void setName(const string& name);
+
+ /** Return the name of this field.
+ *
+ * @return field name
+ */
+ const string getName() const;
+
+ /** Check whether this field is a custom (non-standard) field.
+ * Custom fields have a name beginning with "X-".
+ *
+ * @return true if the field is a custom field, false otherwise
+ */
+ bool isCustom() const;
+
+ /** Return the read-only value object attached to this field.
+ *
+ * @return read-only value object
+ */
+ virtual shared_ptr <const headerFieldValue> getValue() const;
+
+ /** Return the read-only value object attached to this field,
+ * casted to the specified type.
+ *
+ * @return value object
+ */
+ template <typename T>
+ shared_ptr <const T> getValue() const {
+
+ return dynamicCast <const T>(m_value);
+ }
+
+ /** Return the value object attached to this field.
+ *
+ * @return value object
+ */
+ virtual shared_ptr <headerFieldValue> getValue();
+
+ /** Return the value object attached to this field,
+ * casted to the specified type.
+ *
+ * @return value object
+ */
+ template <typename T>
+ shared_ptr <T> getValue() {
+
+ return dynamicCast <T>(m_value);
+ }
+
+ /** Set the value of this field.
+ *
+ * @throw exceptions::bad_field_value_type if the value type is not
+ * valid for this header field
+ * @param value new value
+ */
+ virtual void setValue(const shared_ptr <headerFieldValue>& value);
+
+ /** Set the value of this field by cloning the specified value.
+ *
+ * @throw exceptions::bad_field_value_type if the value type is not
+ * valid for this header field
+ * @param value new value
+ */
+ virtual void setValueConst(const shared_ptr <const headerFieldValue>& value);
+
+ /** Set the value of this field (reference version).
+ * The value will be cloned.
+ *
+ * @throw exceptions::bad_field_value_type if the value type is not
+ * valid for this header field
+ * @param value new value
+ */
+ virtual void setValue(const headerFieldValue& value);
+
+ /** Set the value of this field given a character string.
+ *
+ * @param value value string to parse
+ */
+ void setValue(const string& value);
+
+
+ /** Parse a header field from a buffer.
+ *
+ * @param ctx parsing context
+ * @param buffer input buffer
+ * @param position current position in the input buffer
+ * @param end end position in the input buffer
+ * @param newPosition will receive the new position in the input buffer
+ * @return parsed header field, or NULL if no more header field can be parsed
+ * in the input buffer
+ */
+ static shared_ptr <headerField> parseNext(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition = NULL
+ );
+
+ size_t getGeneratedSize(const generationContext& ctx);
+
+protected:
+
+ void parseImpl(
+ const 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;
+
+
+ string m_name;
+ shared_ptr <headerFieldValue> m_value;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_HEADERFIELD_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/headerFieldFactory.cpp b/vmime-master/src/vmime/headerFieldFactory.cpp
new file mode 100644
index 0000000..db281fa
--- /dev/null
+++ b/vmime-master/src/vmime/headerFieldFactory.cpp
@@ -0,0 +1,158 @@
+//
+// 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.
+//
+
+#include "vmime/headerFieldFactory.hpp"
+#include "vmime/exception.hpp"
+
+#include "vmime/mailboxList.hpp"
+#include "vmime/dateTime.hpp"
+#include "vmime/text.hpp"
+#include "vmime/path.hpp"
+#include "vmime/relay.hpp"
+#include "vmime/encoding.hpp"
+#include "vmime/disposition.hpp"
+#include "vmime/messageIdSequence.hpp"
+
+#include "vmime/contentTypeField.hpp"
+#include "vmime/contentDispositionField.hpp"
+#include "vmime/mailboxField.hpp"
+
+
+namespace vmime {
+
+
+headerFieldFactory::headerFieldFactory() {
+
+ // Register parameterized fields
+ registerField <contentTypeField>(vmime::fields::CONTENT_TYPE);
+ registerField <parameterizedHeaderField>(vmime::fields::CONTENT_TRANSFER_ENCODING);
+ registerField <contentDispositionField>(vmime::fields::CONTENT_DISPOSITION);
+
+ registerField <mailboxField>(vmime::fields::FROM);
+ registerField <mailboxField>(vmime::fields::SENDER);
+ registerField <mailboxField>(vmime::fields::REPLY_TO);
+ registerField <mailboxField>(vmime::fields::DELIVERED_TO);
+
+ // Register standard field values
+ registerFieldValue <mailbox>(vmime::fields::FROM);
+ registerFieldValue <addressList>(vmime::fields::TO);
+ registerFieldValue <addressList>(vmime::fields::CC);
+ registerFieldValue <addressList>(vmime::fields::BCC);
+ registerFieldValue <mailbox>(vmime::fields::SENDER);
+ registerFieldValue <datetime>(vmime::fields::DATE);
+ registerFieldValue <relay>(vmime::fields::RECEIVED);
+ registerFieldValue <text>(vmime::fields::SUBJECT);
+ registerFieldValue <mailbox>(vmime::fields::REPLY_TO);
+ registerFieldValue <mailbox>(vmime::fields::DELIVERED_TO);
+ registerFieldValue <text>(vmime::fields::ORGANIZATION);
+ registerFieldValue <text>(vmime::fields::USER_AGENT);
+ registerFieldValue <path>(vmime::fields::RETURN_PATH);
+ registerFieldValue <mediaType>(vmime::fields::CONTENT_TYPE);
+ registerFieldValue <encoding>(vmime::fields::CONTENT_TRANSFER_ENCODING);
+ registerFieldValue <text>(vmime::fields::CONTENT_DESCRIPTION);
+ registerFieldValue <text>(vmime::fields::MIME_VERSION);
+ registerFieldValue <contentDisposition>(vmime::fields::CONTENT_DISPOSITION);
+ registerFieldValue <messageId>(vmime::fields::CONTENT_ID);
+ registerFieldValue <messageId>(vmime::fields::MESSAGE_ID);
+ registerFieldValue <text>(vmime::fields::CONTENT_LOCATION);
+ registerFieldValue <messageIdSequence>(vmime::fields::IN_REPLY_TO);
+ registerFieldValue <messageIdSequence>(vmime::fields::REFERENCES);
+
+ registerFieldValue <messageId>(vmime::fields::ORIGINAL_MESSAGE_ID);
+ registerFieldValue <disposition>(vmime::fields::DISPOSITION);
+ registerFieldValue <mailboxList>(vmime::fields::DISPOSITION_NOTIFICATION_TO);
+}
+
+
+headerFieldFactory::~headerFieldFactory() {
+
+}
+
+
+shared_ptr <headerFieldFactory> headerFieldFactory::getInstance() {
+
+ static headerFieldFactory instance;
+ return shared_ptr <headerFieldFactory>(&instance, noop_shared_ptr_deleter <headerFieldFactory>());
+}
+
+
+shared_ptr <headerField> headerFieldFactory::create(
+ const string& name,
+ const string& body
+) {
+
+ NameMap::const_iterator pos = m_nameMap.find(utility::stringUtils::toLower(name));
+ shared_ptr <headerField> field;
+
+ if (pos != m_nameMap.end()) {
+ field = ((*pos).second)();
+ } else {
+ field = registerer <headerField, headerField>::creator();
+ }
+
+ field->setName(name);
+ field->setValue(createValue(name));
+
+ if (body != NULL_STRING) {
+ field->parse(body);
+ }
+
+ return field;
+}
+
+
+shared_ptr <headerFieldValue> headerFieldFactory::createValue(const string& fieldName) {
+
+ ValueMap::const_iterator pos = m_valueMap.find(
+ utility::stringUtils::toLower(fieldName)
+ );
+
+ shared_ptr <headerFieldValue> value;
+
+ if (pos != m_valueMap.end()) {
+ value = ((*pos).second.allocFunc)();
+ } else {
+ value = registerer <headerFieldValue, text>::creator();
+ }
+
+ return value;
+}
+
+
+bool headerFieldFactory::isValueTypeValid(
+ const headerField& field,
+ const headerFieldValue& value
+) const {
+
+ ValueMap::const_iterator pos = m_valueMap.find
+ (utility::stringUtils::toLower(field.getName()));
+
+ if (pos != m_valueMap.end()) {
+ return ((*pos).second.checkTypeFunc)(value);
+ }
+
+ return true; // No info on this field
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/headerFieldFactory.hpp b/vmime-master/src/vmime/headerFieldFactory.hpp
new file mode 100644
index 0000000..b3e3415
--- /dev/null
+++ b/vmime-master/src/vmime/headerFieldFactory.hpp
@@ -0,0 +1,159 @@
+//
+// 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_HEADERFIELDFACTORY_HPP_INCLUDED
+#define VMIME_HEADERFIELDFACTORY_HPP_INCLUDED
+
+
+#include "vmime/headerField.hpp"
+#include "vmime/utility/stringUtils.hpp"
+
+
+namespace vmime {
+
+
+/** Creates header field and header field value objects.
+ */
+class VMIME_EXPORT headerFieldFactory {
+
+protected:
+
+ headerFieldFactory();
+ ~headerFieldFactory();
+
+ typedef shared_ptr <headerField> (*AllocFunc)(void);
+ typedef std::map <string, AllocFunc> NameMap;
+
+ NameMap m_nameMap;
+
+
+ struct ValueInfo {
+
+ typedef shared_ptr <headerFieldValue> (*ValueAllocFunc)(void);
+ typedef bool (*ValueTypeCheckFunc)(const object&);
+
+ ValueAllocFunc allocFunc;
+ ValueTypeCheckFunc checkTypeFunc;
+ };
+
+ typedef std::map <string, ValueInfo> ValueMap;
+
+ ValueMap m_valueMap;
+
+public:
+
+ static shared_ptr <headerFieldFactory> getInstance();
+
+#ifndef VMIME_BUILDING_DOC
+
+ // TYPE must inherit from BASE_TYPE
+ template <class BASE_TYPE, class TYPE>
+ class registerer {
+
+ public:
+
+ static bool checkType(const object& obj) {
+
+ const TYPE* typedObj = dynamic_cast <const TYPE*>(&obj);
+ return typedObj != NULL;
+ }
+
+ static shared_ptr <BASE_TYPE> creator() {
+
+ // Allocate a new object
+ return shared_ptr <BASE_TYPE>(new TYPE());
+ }
+ };
+
+#endif // VMIME_BUILDING_DOC
+
+
+ /** Register a field type.
+ *
+ * @param T field class (must inherit from 'headerField')
+ * @param name field name (eg. "X-MyField")
+ */
+ template <class T>
+ void registerField(const string& name) {
+
+ m_nameMap.insert(
+ NameMap::value_type(
+ utility::stringUtils::toLower(name),
+ &registerer <headerField, T>::creator
+ )
+ );
+ }
+
+ /** Register a field value type.
+ *
+ * @param T value class (must inherit from 'headerFieldValue')
+ * @param name field name
+ */
+ template <class T>
+ void registerFieldValue(const string& name) {
+
+ ValueInfo vi;
+ vi.allocFunc = &registerer <headerFieldValue, T>::creator;
+ vi.checkTypeFunc = &registerer <headerField, T>::checkType;
+
+ m_valueMap.insert(
+ ValueMap::value_type(
+ utility::stringUtils::toLower(name),
+ vi
+ )
+ );
+ }
+
+ /** Create a new field object for the specified field name.
+ * If the field name has not been registered, a default type
+ * is used.
+ *
+ * @param name field name
+ * @param body string that will be parsed to initialize
+ * the value of the field
+ * @return a new field object
+ */
+ shared_ptr <headerField> create(const string& name, const string& body = NULL_STRING);
+
+ /** Create a new field value for the specified field.
+ *
+ * @param fieldName name of the field for which to create value
+ * @return a new value object for the field
+ */
+ shared_ptr <headerFieldValue> createValue(const string& fieldName);
+
+ /** Returns whether the specified value type is valid for the specified field.
+ *
+ * @param field header field
+ * @param value value for this header field
+ * @return true if the value type is compatible with the header field, or
+ * false otherwise
+ */
+ bool isValueTypeValid(const headerField& field, const headerFieldValue& value) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_HEADERFIELDFACTORY_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/headerFieldValue.cpp b/vmime-master/src/vmime/headerFieldValue.cpp
new file mode 100644
index 0000000..073edbe
--- /dev/null
+++ b/vmime-master/src/vmime/headerFieldValue.cpp
@@ -0,0 +1,43 @@
+//
+// 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.
+//
+
+#include "vmime/headerFieldValue.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+
+namespace vmime {
+
+
+size_t headerFieldValue::getGeneratedSize(const generationContext& ctx) {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter osa(oss);
+
+ generate(ctx, osa);
+
+ return oss.str().length();
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/headerFieldValue.hpp b/vmime-master/src/vmime/headerFieldValue.hpp
new file mode 100644
index 0000000..20d1768
--- /dev/null
+++ b/vmime-master/src/vmime/headerFieldValue.hpp
@@ -0,0 +1,49 @@
+//
+// 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_HEADERFIELDVALUE_HPP_INCLUDED
+#define VMIME_HEADERFIELDVALUE_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/component.hpp"
+
+
+namespace vmime {
+
+
+/** Base class for all classes that can be used as a value
+ * for a header field.
+ */
+class VMIME_EXPORT headerFieldValue : public component {
+
+public:
+
+ size_t getGeneratedSize(const generationContext& ctx);
+};
+
+
+} // vmime
+
+
+#endif // VMIME_HEADERFIELDVALUE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/htmlTextPart.cpp b/vmime-master/src/vmime/htmlTextPart.cpp
new file mode 100644
index 0000000..a30023c
--- /dev/null
+++ b/vmime-master/src/vmime/htmlTextPart.cpp
@@ -0,0 +1,568 @@
+//
+// 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.
+//
+
+#include "vmime/htmlTextPart.hpp"
+#include "vmime/exception.hpp"
+
+#include "vmime/contentTypeField.hpp"
+#include "vmime/contentDisposition.hpp"
+#include "vmime/text.hpp"
+
+#include "vmime/emptyContentHandler.hpp"
+#include "vmime/stringContentHandler.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+
+namespace vmime {
+
+
+htmlTextPart::htmlTextPart()
+ : m_plainText(make_shared <emptyContentHandler>()),
+ m_text(make_shared <emptyContentHandler>()) {
+
+}
+
+
+htmlTextPart::~htmlTextPart() {
+
+}
+
+
+const mediaType htmlTextPart::getType() const {
+
+ return mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML);
+}
+
+
+size_t htmlTextPart::getPartCount() const {
+
+ return m_plainText->isEmpty() ? 1 : 2;
+}
+
+
+void htmlTextPart::generateIn(
+ const shared_ptr <bodyPart>& /* message */,
+ const shared_ptr <bodyPart>& parent
+) const {
+
+ // Plain text
+ if (!m_plainText->isEmpty()) {
+
+ // -- Create a new part
+ shared_ptr <bodyPart> part = make_shared <bodyPart>();
+ parent->getBody()->appendPart(part);
+
+ // -- Set contents
+ part->getBody()->setContents(
+ m_plainText,
+ mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN),
+ m_charset,
+ encoding::decide(m_plainText, m_charset, encoding::USAGE_TEXT)
+ );
+ }
+
+ // HTML text
+ // -- Create a new part
+ shared_ptr <bodyPart> htmlPart = make_shared <bodyPart>();
+
+ // -- Set contents
+ htmlPart->getBody()->setContents(
+ m_text,
+ mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML),
+ m_charset,
+ encoding::decide(m_text, m_charset, encoding::USAGE_TEXT)
+ );
+
+ // Handle the case we have embedded objects
+ if (!m_objects.empty()) {
+
+ // Create a "multipart/related" body part
+ shared_ptr <bodyPart> relPart = make_shared <bodyPart>();
+ parent->getBody()->appendPart(relPart);
+
+ relPart->getHeader()->ContentType()->setValue(
+ mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_RELATED)
+ );
+
+ // Add the HTML part into this part
+ relPart->getBody()->appendPart(htmlPart);
+
+ // Also add objects into this part
+ for (std::vector <shared_ptr <embeddedObject> >::const_iterator it = m_objects.begin() ;
+ it != m_objects.end() ; ++it) {
+
+ shared_ptr <bodyPart> objPart = make_shared <bodyPart>();
+ relPart->getBody()->appendPart(objPart);
+
+ string id = (*it)->getId();
+
+ if (id.length() >= 4 &&
+ (id[0] == 'c' || id[0] == 'C') &&
+ (id[1] == 'i' || id[1] == 'I') &&
+ (id[2] == 'd' || id[2] == 'D') &&
+ id[3] == ':') {
+
+ id = id.substr(4);
+ }
+
+ objPart->getHeader()->ContentType()->setValue((*it)->getType());
+ objPart->getHeader()->ContentId()->setValue(messageId("<" + id + ">"));
+ objPart->getHeader()->ContentDisposition()->setValue(contentDisposition(contentDispositionTypes::INLINE));
+ objPart->getHeader()->ContentTransferEncoding()->setValue((*it)->getEncoding());
+ //encoding(encodingTypes::BASE64);
+
+ objPart->getBody()->setContents((*it)->getData()->clone());
+ }
+
+ } else {
+
+ // Add the HTML part into the parent part
+ parent->getBody()->appendPart(htmlPart);
+ }
+}
+
+
+void htmlTextPart::findEmbeddedParts(
+ const bodyPart& part,
+ std::vector <shared_ptr <const bodyPart> >& cidParts,
+ std::vector <shared_ptr <const bodyPart> >& locParts
+) {
+
+ for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i) {
+
+ shared_ptr <const bodyPart> p = part.getBody()->getPartAt(i);
+
+ // For a part to be an embedded object, it must have either a
+ // Content-Id field or a Content-Location field.
+ if (p->getHeader()->hasField(fields::CONTENT_ID)) {
+ cidParts.push_back(p);
+ }
+
+ if (p->getHeader()->hasField(fields::CONTENT_LOCATION)) {
+ locParts.push_back(p);
+ }
+
+ findEmbeddedParts(*p, cidParts, locParts);
+ }
+}
+
+
+void htmlTextPart::addEmbeddedObject(
+ const bodyPart& part,
+ const string& id,
+ const embeddedObject::ReferenceType refType
+) {
+
+ // The object may already exists. This can happen if an object is
+ // identified by both a Content-Id and a Content-Location. In this
+ // case, there will be two embedded objects with two different IDs
+ // but referencing the same content.
+
+ mediaType type;
+
+ shared_ptr <const headerField> ctf =
+ part.getHeader()->findField(fields::CONTENT_TYPE);
+
+ if (ctf) {
+
+ type = *ctf->getValue <mediaType>();
+
+ } else {
+
+ // No "Content-type" field: assume "application/octet-stream".
+ }
+
+ m_objects.push_back(
+ make_shared <embeddedObject>(
+ vmime::clone(part.getBody()->getContents()),
+ part.getBody()->getEncoding(),
+ id,
+ type,
+ refType
+ )
+ );
+}
+
+
+void htmlTextPart::parse(
+ const shared_ptr <const bodyPart>& message,
+ const shared_ptr <const bodyPart>& parent,
+ const shared_ptr <const bodyPart>& textPart
+) {
+
+ // Search for possible embedded objects in the _whole_ message.
+ std::vector <shared_ptr <const bodyPart> > cidParts;
+ std::vector <shared_ptr <const bodyPart> > locParts;
+
+ findEmbeddedParts(*message, cidParts, locParts);
+
+ // Extract HTML text
+ std::ostringstream oss;
+ utility::outputStreamAdapter adapter(oss);
+
+ textPart->getBody()->getContents()->extract(adapter);
+
+ const string data = oss.str();
+
+ m_text = textPart->getBody()->getContents()->clone();
+
+ // Find charset
+ shared_ptr <const contentTypeField> ctf =
+ textPart->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
+
+ if (ctf && ctf->hasCharset()) {
+ m_charset = ctf->getCharset();
+ } else {
+ m_charset = charset();
+ }
+
+ // Extract embedded objects. The algorithm is quite simple: for each previously
+ // found inline part, we check if its CID/Location is contained in the HTML text.
+ for (std::vector <shared_ptr <const bodyPart> >::const_iterator p = cidParts.begin() ;
+ p != cidParts.end() ; ++p) {
+
+ const shared_ptr <const headerField> midField =
+ (*p)->getHeader()->findField(fields::CONTENT_ID);
+
+ const messageId mid = *midField->getValue <messageId>();
+
+ if (data.find("CID:" + mid.getId()) != string::npos ||
+ data.find("cid:" + mid.getId()) != string::npos) {
+
+ // This part is referenced in the HTML text.
+ // Add it to the embedded object list.
+ addEmbeddedObject(**p, mid.getId(), embeddedObject::REFERENCED_BY_ID);
+ }
+ }
+
+ for (std::vector <shared_ptr <const bodyPart> >::const_iterator p = locParts.begin() ;
+ p != locParts.end() ; ++p) {
+
+ const shared_ptr <const headerField> locField =
+ (*p)->getHeader()->findField(fields::CONTENT_LOCATION);
+
+ const text loc = *locField->getValue <text>();
+ const string locStr = loc.getWholeBuffer();
+
+ if (data.find(locStr) != string::npos) {
+
+ // This part is referenced in the HTML text.
+ // Add it to the embedded object list.
+ addEmbeddedObject(**p, locStr, embeddedObject::REFERENCED_BY_LOCATION);
+ }
+ }
+
+ // Extract plain text, if any.
+ if (!findPlainTextPart(*message, *parent, *textPart)) {
+
+ m_plainText = make_shared <emptyContentHandler>();
+ }
+}
+
+
+bool htmlTextPart::findPlainTextPart(
+ const bodyPart& part,
+ const bodyPart& parent,
+ const bodyPart& textPart
+) {
+
+ // We search for the nearest "multipart/alternative" part.
+ const shared_ptr <const headerField> ctf =
+ part.getHeader()->findField(fields::CONTENT_TYPE);
+
+ if (ctf) {
+
+ const mediaType type = *ctf->getValue <mediaType>();
+
+ if (type.getType() == mediaTypes::MULTIPART &&
+ type.getSubType() == mediaTypes::MULTIPART_ALTERNATIVE) {
+
+ shared_ptr <const bodyPart> foundPart;
+
+ for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i) {
+
+ const shared_ptr <const bodyPart> p = part.getBody()->getPartAt(i);
+
+ if (p.get() == &parent || // if "text/html" is in "multipart/related"
+ p.get() == &textPart) { // if not...
+
+ foundPart = p;
+ }
+ }
+
+ if (foundPart) {
+
+ bool found = false;
+
+ // Now, search for the alternative plain text part
+ for (size_t i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i) {
+
+ const shared_ptr <const bodyPart> p = part.getBody()->getPartAt(i);
+
+ const shared_ptr <const headerField> ctf =
+ p->getHeader()->findField(fields::CONTENT_TYPE);
+
+ if (ctf) {
+
+ const mediaType type = *ctf->getValue <mediaType>();
+
+ if (type.getType() == mediaTypes::TEXT &&
+ type.getSubType() == mediaTypes::TEXT_PLAIN) {
+
+ m_plainText = p->getBody()->getContents()->clone();
+ found = true;
+ }
+
+ } else {
+
+ // No "Content-type" field.
+ }
+ }
+
+ // If we don't have found the plain text part here, it means that
+ // it does not exists (the MUA which built this message probably
+ // did not include it...).
+ return found;
+ }
+ }
+
+ } else {
+
+ // No "Content-type" field.
+ }
+
+ bool found = false;
+
+ for (size_t i = 0 ; !found && i < part.getBody()->getPartCount() ; ++i) {
+
+ found = findPlainTextPart(*part.getBody()->getPartAt(i), parent, textPart);
+ }
+
+ return found;
+}
+
+
+const charset& htmlTextPart::getCharset() const {
+
+ return m_charset;
+}
+
+
+void htmlTextPart::setCharset(const charset& ch) {
+
+ m_charset = ch;
+}
+
+
+shared_ptr <const contentHandler> htmlTextPart::getPlainText() const {
+
+ return m_plainText;
+}
+
+
+void htmlTextPart::setPlainText(const shared_ptr <contentHandler>& plainText) {
+
+ m_plainText = plainText->clone();
+}
+
+
+const shared_ptr <const contentHandler> htmlTextPart::getText() const {
+
+ return m_text;
+}
+
+
+void htmlTextPart::setText(const shared_ptr <contentHandler>& text) {
+
+ m_text = text->clone();
+}
+
+
+size_t htmlTextPart::getObjectCount() const {
+
+ return m_objects.size();
+}
+
+
+shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::getObjectAt(const size_t pos) const {
+
+ return m_objects[pos];
+}
+
+
+shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::findObject(const string& id) const
+{
+ for (std::vector <shared_ptr <embeddedObject> >::const_iterator o = m_objects.begin() ;
+ o != m_objects.end() ; ++o) {
+
+ if ((*o)->matchesId(id)) {
+ return *o;
+ }
+ }
+
+ return null;
+}
+
+
+bool htmlTextPart::hasObject(const string& id) const {
+
+ for (std::vector <shared_ptr <embeddedObject> >::const_iterator o = m_objects.begin() ;
+ o != m_objects.end() ; ++o) {
+
+ if ((*o)->matchesId(id)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::addObject(
+ const shared_ptr <contentHandler>& data,
+ const vmime::encoding& enc,
+ const mediaType& type
+) {
+
+ const messageId mid(messageId::generateId());
+
+ shared_ptr <embeddedObject> obj = make_shared <embeddedObject>(
+ data, enc, mid.getId(), type, embeddedObject::REFERENCED_BY_ID
+ );
+
+ m_objects.push_back(obj);
+
+ return obj;
+}
+
+
+shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::addObject(
+ const shared_ptr <contentHandler>& data,
+ const mediaType& type
+) {
+
+ return addObject(data, encoding::decide(data), type);
+}
+
+
+shared_ptr <const htmlTextPart::embeddedObject> htmlTextPart::addObject(
+ const string& data,
+ const mediaType& type
+) {
+
+ shared_ptr <stringContentHandler> cts = make_shared <stringContentHandler>(data);
+ return addObject(cts, encoding::decide(cts), type);
+}
+
+
+
+//
+// htmlTextPart::embeddedObject
+//
+
+htmlTextPart::embeddedObject::embeddedObject(
+ const shared_ptr <contentHandler>& data,
+ const encoding& enc,
+ const string& id,
+ const mediaType& type,
+ const ReferenceType refType
+)
+ : m_data(vmime::clone(data)),
+ m_encoding(enc),
+ m_id(id),
+ m_type(type),
+ m_refType(refType) {
+
+}
+
+
+shared_ptr <const contentHandler> htmlTextPart::embeddedObject::getData() const {
+
+ return m_data;
+}
+
+
+const vmime::encoding htmlTextPart::embeddedObject::getEncoding() const {
+
+ return m_encoding;
+}
+
+
+const string htmlTextPart::embeddedObject::getId() const {
+
+ return m_id;
+}
+
+
+const string htmlTextPart::embeddedObject::getReferenceId() const {
+
+ if (m_refType == REFERENCED_BY_ID) {
+ return string("cid:") + m_id;
+ } else {
+ return m_id;
+ }
+}
+
+
+const mediaType htmlTextPart::embeddedObject::getType() const {
+
+ return m_type;
+}
+
+
+htmlTextPart::embeddedObject::ReferenceType htmlTextPart::embeddedObject::getReferenceType() const {
+
+ return m_refType;
+}
+
+
+bool htmlTextPart::embeddedObject::matchesId(const string& id) const {
+
+ if (m_refType == REFERENCED_BY_ID) {
+ return m_id == cleanId(id);
+ } else {
+ return m_id == id;
+ }
+}
+
+
+// static
+const string htmlTextPart::embeddedObject::cleanId(const string& id) {
+
+ if (id.length() >= 4 &&
+ (id[0] == 'c' || id[0] == 'C') &&
+ (id[1] == 'i' || id[1] == 'I') &&
+ (id[2] == 'd' || id[2] == 'D') &&
+ id[3] == ':') {
+
+ return id.substr(4);
+
+ } else {
+
+ return id;
+ }
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/htmlTextPart.hpp b/vmime-master/src/vmime/htmlTextPart.hpp
new file mode 100644
index 0000000..ac2711b
--- /dev/null
+++ b/vmime-master/src/vmime/htmlTextPart.hpp
@@ -0,0 +1,268 @@
+//
+// 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_HTMLTEXTPART_HPP_INCLUDED
+#define VMIME_HTMLTEXTPART_HPP_INCLUDED
+
+
+#include "vmime/textPart.hpp"
+#include "vmime/messageId.hpp"
+#include "vmime/encoding.hpp"
+
+#include "vmime/contentHandler.hpp"
+
+
+namespace vmime {
+
+
+/** Text part of type 'text/html'.
+ */
+class VMIME_EXPORT htmlTextPart : public textPart {
+
+public:
+
+ htmlTextPart();
+ ~htmlTextPart();
+
+ const mediaType getType() const;
+
+ const charset& getCharset() const;
+ void setCharset(const charset& ch);
+
+ shared_ptr <const contentHandler> getPlainText() const;
+ void setPlainText(const shared_ptr <contentHandler>& plainText);
+
+ const shared_ptr <const contentHandler> getText() const;
+ void setText(const shared_ptr <contentHandler>& text);
+
+ /** Embedded object (eg: image for &lt;IMG> tag).
+ */
+ class VMIME_EXPORT embeddedObject : public object {
+ public:
+
+ /** The ways embedded objects can be referenced. */
+ enum ReferenceType {
+ REFERENCED_BY_ID, /**< Referenced by Content-Id. */
+ REFERENCED_BY_LOCATION /**< Referenced by Content-Location. */
+ };
+
+ /** Constructs an embedded object.
+ *
+ * @param data content of the object
+ * @param enc encoding of the data
+ * @param id object identifier
+ * @param type object content type
+ * @param refType reference type
+ * @return a reference to a new embedded object
+ */
+ embeddedObject(
+ const shared_ptr <contentHandler>& data,
+ const encoding& enc,
+ const string& id,
+ const mediaType& type,
+ const ReferenceType refType
+ );
+
+ /** Return data stored in this embedded object.
+ *
+ * @return stored data
+ */
+ shared_ptr <const contentHandler> getData() const;
+
+ /** Return the encoding used for data in this
+ * embedded object.
+ *
+ * @return data encoding
+ */
+ const vmime::encoding getEncoding() const;
+
+ /** Returns the identifier of this embedded object (either a
+ * unique ID or a location).
+ *
+ * @return object identifier
+ */
+ const string getId() const;
+
+ /** Return the identifier used to reference this embedded object
+ * in a text document (for example, you can use the result as
+ * the "src" attribute of an &lt;img> tag).
+ *
+ * @return object reference identifier
+ */
+ const string getReferenceId() const;
+
+ /** Return the content type of data stored in
+ * this embedded object.
+ *
+ * @return data type
+ */
+ const mediaType getType() const;
+
+ /** Returns the way this object is referenced.
+ *
+ * @return reference type (see ReferenceType enum)
+ */
+ ReferenceType getReferenceType() const;
+
+ /** Returns whether this object matches the specified identifier.
+ *
+ * @param id identifier to test
+ * @return true if the specified identifier references this
+ * object, or false otherwise
+ */
+ bool matchesId(const string& id) const;
+
+ private:
+
+ static const string cleanId(const string& id);
+
+ shared_ptr <contentHandler> m_data;
+ encoding m_encoding;
+ string m_id;
+ mediaType m_type;
+ ReferenceType m_refType;
+ };
+
+
+ /** Test the existence of an embedded object given its identifier.
+ *
+ * @param id object identifier
+ * @return true if an object with this identifier exists,
+ * false otherwise
+ */
+ bool hasObject(const string& id) const;
+
+ /** Return the embedded object with the specified identifier.
+ *
+ * @param id object identifier
+ * @return embedded object with the specified identifier, or NULL if
+ * no object has been found
+ */
+ shared_ptr <const embeddedObject> findObject(const string& id) const;
+
+ /** Return the number of embedded objects.
+ *
+ * @return number of embedded objects
+ */
+ size_t getObjectCount() const;
+
+ /** Return the embedded object at the specified position.
+ *
+ * @param pos position of the embedded object
+ * @return embedded object at position 'pos'
+ */
+ shared_ptr <const embeddedObject> getObjectAt(const size_t pos) const;
+
+ /** Embed an object and returns a string which identifies it.
+ * The returned identifier is suitable for use in the 'src' attribute
+ * of an &lt;img> tag.
+ *
+ * \deprecated Use the addObject() methods which take a 'contentHandler'
+ * parameter type instead.
+ *
+ * @param data object data
+ * @param type data type
+ * @return an unique object identifier used to identify the new
+ * object among all other embedded objects
+ */
+ shared_ptr <const embeddedObject> addObject(
+ const string& data,
+ const mediaType& type
+ );
+
+ /** Embed an object and returns a string which identifies it.
+ * The returned identifier is suitable for use in the 'src' attribute
+ * of an &lt;img> tag.
+ *
+ * @param data object data
+ * @param type data type
+ * @return an unique object identifier used to identify the new
+ * object among all other embedded objects
+ */
+ shared_ptr <const embeddedObject> addObject(
+ const shared_ptr <contentHandler>& data,
+ const mediaType& type
+ );
+
+ /** Embed an object and returns a string which identifies it.
+ * The returned identifier is suitable for use in the 'src' attribute
+ * of an &lt;img> tag.
+ *
+ * @param data object data
+ * @param enc data encoding
+ * @param type data type
+ * @return an unique object identifier used to identify the new
+ * object among all other embedded objects
+ */
+ shared_ptr <const embeddedObject> addObject(
+ const shared_ptr <contentHandler>& data,
+ const encoding& enc,
+ const mediaType& type
+ );
+
+
+ size_t getPartCount() const;
+
+ void generateIn(
+ const shared_ptr <bodyPart>& message,
+ const shared_ptr <bodyPart>& parent
+ ) const;
+
+ void parse(
+ const shared_ptr <const bodyPart>& message,
+ const shared_ptr <const bodyPart>& parent,
+ const shared_ptr <const bodyPart>& textPart
+ );
+
+private:
+
+ shared_ptr <contentHandler> m_plainText;
+ shared_ptr <contentHandler> m_text;
+ charset m_charset;
+
+ std::vector <shared_ptr <embeddedObject> > m_objects;
+
+ void findEmbeddedParts(
+ const bodyPart& part,
+ std::vector <shared_ptr <const bodyPart> >& cidParts,
+ std::vector <shared_ptr <const bodyPart> >& locParts
+ );
+
+ void addEmbeddedObject(
+ const bodyPart& part,
+ const string& id,
+ const embeddedObject::ReferenceType refType
+ );
+
+ bool findPlainTextPart(
+ const bodyPart& part,
+ const bodyPart& parent,
+ const bodyPart& textPart
+ );
+};
+
+
+} // vmime
+
+
+#endif // VMIME_HTMLTEXTPART_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/mailbox.cpp b/vmime-master/src/vmime/mailbox.cpp
new file mode 100644
index 0000000..30a082e
--- /dev/null
+++ b/vmime-master/src/vmime/mailbox.cpp
@@ -0,0 +1,476 @@
+//
+// 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.
+//
+
+#include "vmime/mailbox.hpp"
+#include "vmime/parserHelpers.hpp"
+#include "vmime/utility/outputStreamStringAdapter.hpp"
+
+
+namespace vmime {
+
+
+mailbox::mailbox() {
+
+}
+
+
+mailbox::mailbox(const mailbox& mbox)
+ : address(),
+ m_name(mbox.m_name),
+ m_email(mbox.m_email) {
+
+}
+
+
+mailbox::mailbox(const emailAddress& email)
+ : m_email(email) {
+
+}
+
+
+mailbox::mailbox(const text& name, const emailAddress& email)
+ : m_name(name),
+ m_email(email) {
+
+}
+
+
+/*
+
+ RFC #2822:
+ 3.4. ADDRESS SPECIFICATION
+
+mailbox = name-addr / addr-spec
+
+name-addr = [display-name] angle-addr
+
+angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
+
+*/
+
+void mailbox::parseImpl(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ const char* const pend = buffer.data() + end;
+ const char* const pstart = buffer.data() + position;
+ const char* p = pstart;
+
+ // Current state for parsing machine
+ enum States {
+ State_None,
+ State_String,
+ State_Name,
+ State_Bracket,
+ State_Address_Bracketed,
+ State_Address_Unbracketed,
+ State_NameAt,
+ };
+
+ States state = State_None;
+
+ // Temporary buffers for extracted name and address
+ string name, address;
+ unsigned int hold = 0;
+ bool hadBrackets = false;
+
+ while (p < pend) {
+ if (state == State_None) {
+ while (p < pend && parserHelpers::isSpace(*p))
+ ++p;
+ if (*p == ',' || *p == ';')
+ /* Completely new mailbox -- stop parsing this one. */
+ break;
+ if (*p == '<') {
+ state = State_Bracket;
+ continue;
+ }
+ if (*p == '"') { // Quoted string
+ state = State_String;
+ ++p;
+ continue;
+ }
+ state = State_Name;
+ } else if (state == State_String) {
+ bool escaped = false;
+
+ for (; p < pend; ++p) {
+ if (escaped) {
+ name += *p;
+ escaped = false;
+ continue;
+ } else if (*p == '\\') {
+ escaped = true;
+ continue;
+ }
+ if (*p == '"') {
+ ++p;
+ state = State_None;
+ break;
+ }
+ name += *p;
+ }
+ } else if (state == State_Address_Bracketed) {
+ bool escaped = false;
+ int comment = 0;
+
+ for (; p < pend; ++p) {
+ if (escaped) {
+ if (!comment) {
+ address += *p;
+ name += *p;
+ ++hold;
+ }
+ escaped = false;
+ } else if (comment) {
+ if (*p == '\\') {
+ escaped = true;
+ } else if (*p == '(') {
+ ++comment;
+ } else if (*p == ')') {
+ --comment;
+ }
+ } else if (*p == '(') {
+ ++comment;
+ } else if (*p == '\\') {
+ escaped = true;
+ } else if (*p == '<') {
+ state = State_Bracket;
+ break;
+ } else if (*p == '>') {
+ hadBrackets = true;
+ name += *p++;
+ ++hold;
+ state = State_Name;
+ break;
+ } else if (parserHelpers::isSpace(*p)) {
+ name += *p;
+ ++hold;
+ } else {
+ address += *p;
+ name += *p;
+ ++hold;
+ }
+ }
+ } else if (state == State_Address_Unbracketed) {
+ bool escaped = false;
+ int comment = 0;
+
+ for (; p < pend; ++p) {
+ if (escaped) {
+ if (!comment) {
+ address += *p;
+ name += *p;
+ ++hold;
+ }
+ escaped = false;
+ } else if (comment) {
+ if (*p == '\\')
+ escaped = true;
+ else if (*p == '(')
+ ++comment;
+ else if (*p == ')')
+ --comment;
+ } else if (*p == '(') {
+ ++comment;
+ } else if (*p == '\\') {
+ escaped = true;
+ } else if (*p == '<') {
+ state = State_Bracket;
+ break;
+ } else if (*p == '>') {
+ name += *p++;
+ ++hold;
+ state = State_None;
+ break;
+ } else if (*p == ',' || *p == ';') {
+ state = State_None;
+ break;
+ } else if (parserHelpers::isSpace(*p)) {
+ state = State_Name;
+ break;
+ } else {
+ address += *p;
+ name += *p;
+ ++hold;
+ }
+ }
+ } else if (state == State_Name) {
+ bool escaped = false;
+ unsigned int comment = 0, at_hold = 0;
+
+ for (; p < pend; ++p) {
+ if (escaped) {
+ if (!comment) {
+ name += *p;
+ ++at_hold;
+ }
+ escaped = false;
+ } else if (comment) {
+ if (*p == '\\')
+ escaped = true;
+ else if (*p == '(')
+ ++comment;
+ else if (*p == ')')
+ --comment;
+ } else if (*p == '\\') {
+ escaped = true;
+ } else if (*p == '(') {
+ ++comment;
+ } else if (*p == '<') {
+ state = State_Bracket;
+ break;
+ } else if (*p == '@') {
+ hold = at_hold;
+ state = State_NameAt;
+ break;
+ } else if (parserHelpers::isSpace(*p)) {
+ name += *p;
+ ++hold;
+ at_hold = 1;
+ } else {
+ name += *p;
+ hold = 0;
+ ++at_hold;
+ }
+ }
+ } else if (state == State_Bracket) {
+ string::const_iterator q = name.cend();
+ unsigned int nh = 0;
+ while (nh < hold && q != name.cbegin() && parserHelpers::isSpace(*(q - 1))) {
+ --q;
+ ++nh;
+ }
+ hold = nh;
+ name += *p++;
+ ++hold;
+ if (!address.empty())
+ // If we found a '<' here, it means that the address
+ // starts _only_ here...and the stuff we have parsed
+ // before belongs actually to the display name!
+ address.clear();
+ state = State_Address_Bracketed;
+ } else if (state == State_NameAt) {
+ name += *p++;
+ ++hold;
+ // (*) Actually, we were parsing the local-part of an address
+ // and not a display name...
+ // Back up to the last whitespace and treat as address
+ string::const_iterator q = name.cend();
+ unsigned int nh = 0;
+ while (nh < hold && q != name.cbegin() && !parserHelpers::isSpace(*(q - 1))) {
+ --q;
+ ++nh;
+ }
+ address.assign(q, name.cend());
+ while (nh < hold && q != name.cbegin() && parserHelpers::isSpace(*(q - 1))) {
+ --q;
+ ++nh;
+ }
+ hold = nh;
+ state = State_Address_Unbracketed;
+ }
+ }
+
+ if (hold <= name.size())
+ name.erase(name.size() - hold);
+
+ // Swap name and address when no address was found
+ // (email address is mandatory, whereas name is optional).
+ if (address.empty() && !name.empty() && !hadBrackets) {
+
+ m_name.removeAllWords();
+ m_email.parse(ctx, name);
+
+ } else {
+
+ text::decodeAndUnfold(ctx, name, &m_name);
+ m_email.parse(ctx, address);
+ }
+
+ setParsedBounds(position, position + (p - pstart));
+
+ if (newPosition) {
+ *newPosition = position + (p - pstart);
+ }
+}
+
+
+void mailbox::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ string generatedEmail;
+ utility::outputStreamStringAdapter generatedEmailStream(generatedEmail);
+ m_email.generate(ctx, generatedEmailStream, 0, NULL);
+
+ if (m_name.isEmpty()) {
+
+ size_t pos = curLinePos;
+
+ // No display name is specified, only email address.
+ if (curLinePos + generatedEmail.length() > ctx.getMaxLineLength()) {
+
+ os << NEW_LINE_SEQUENCE;
+ pos = NEW_LINE_SEQUENCE.length();
+ }
+
+ os << generatedEmail;
+ pos += generatedEmail.length();
+
+ if (newLinePos) {
+ *newLinePos = pos;
+ }
+
+ } else {
+
+ // We have to encode the name:
+ // - if it contains characters in a charset different from "US-ASCII",
+ // - and/or if it contains one or more of these special chars:
+ // CR LF TAB " ; , < > ( ) @ / ? . = :
+ // these special chars only require quoting, not full encoding
+ // Check whether there are words that are not "US-ASCII"
+ // and/or contain the special chars.
+ bool forceEncode = false;
+
+ for (size_t w = 0 ; !forceEncode && w != m_name.getWordCount() ; ++w) {
+
+ if (m_name.getWordAt(w)->getCharset() != charset(charsets::US_ASCII)) {
+ forceEncode = true;
+ }
+ }
+
+ size_t pos = curLinePos;
+
+ m_name.encodeAndFold(
+ ctx, os, pos, &pos,
+ text::QUOTE_IF_POSSIBLE | (forceEncode ? text::FORCE_ENCODING : 0)
+ );
+
+ if (pos + generatedEmail.length() + 3 > ctx.getMaxLineLength()) {
+
+ os << NEW_LINE_SEQUENCE;
+ pos = NEW_LINE_SEQUENCE.length();
+ }
+
+ os << " <" << generatedEmail << ">";
+ pos += 2 + generatedEmail.length() + 1;
+
+ if (newLinePos) {
+ *newLinePos = pos;
+ }
+ }
+}
+
+
+bool mailbox::operator==(const class mailbox& mailbox) const {
+
+ return m_name == mailbox.m_name && m_email == mailbox.m_email;
+}
+
+
+bool mailbox::operator!=(const class mailbox& mailbox) const {
+
+ return !(*this == mailbox);
+}
+
+
+void mailbox::copyFrom(const component& other) {
+
+ const mailbox& source = dynamic_cast <const mailbox&>(other);
+
+ m_name = source.m_name;
+ m_email = source.m_email;
+}
+
+
+mailbox& mailbox::operator=(const mailbox& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+shared_ptr <component>mailbox::clone() const {
+
+ return make_shared <mailbox>(*this);
+}
+
+
+bool mailbox::isEmpty() const {
+
+ return m_email.isEmpty();
+}
+
+
+void mailbox::clear() {
+
+ m_name.removeAllWords();
+ m_email = emailAddress();
+}
+
+
+bool mailbox::isGroup() const {
+
+ return false;
+}
+
+
+const text& mailbox::getName() const {
+
+ return m_name;
+}
+
+
+void mailbox::setName(const text& name) {
+
+ m_name = name;
+}
+
+
+const emailAddress& mailbox::getEmail() const {
+
+ return m_email;
+}
+
+
+void mailbox::setEmail(const emailAddress& email) {
+
+ m_email = email;
+}
+
+
+const std::vector <shared_ptr <component> > mailbox::getChildComponents() {
+
+ return std::vector <shared_ptr <component> >();
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/mailbox.hpp b/vmime-master/src/vmime/mailbox.hpp
new file mode 100644
index 0000000..c563129
--- /dev/null
+++ b/vmime-master/src/vmime/mailbox.hpp
@@ -0,0 +1,123 @@
+//
+// 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_MAILBOX_HPP_INCLUDED
+#define VMIME_MAILBOX_HPP_INCLUDED
+
+
+#include "vmime/emailAddress.hpp"
+#include "vmime/address.hpp"
+#include "vmime/text.hpp"
+
+
+namespace vmime {
+
+
+/** A mailbox: full name + email (basic type).
+ */
+class VMIME_EXPORT mailbox : public address {
+
+ friend class mailboxGroup;
+ friend class mailboxField;
+
+public:
+
+ mailbox();
+ mailbox(const mailbox& mbox);
+ mailbox(const emailAddress& email);
+ mailbox(const text& name, const emailAddress& email);
+
+ /** Return the full name of the mailbox (empty if not specified).
+ *
+ * @return full name of the mailbox
+ */
+ const text& getName() const;
+
+ /** Set the full name of the mailbox.
+ *
+ * @param name full name of the mailbox
+ */
+ void setName(const text& name);
+
+ /** Return the email of the mailbox.
+ *
+ * @return email of the mailbox
+ */
+ const emailAddress& getEmail() const;
+
+ /** Set the email of the mailbox.
+ *
+ * @param email email of the mailbox
+ */
+ void setEmail(const emailAddress& email);
+
+ // Comparison
+ bool operator==(const class mailbox& mailbox) const;
+ bool operator!=(const class mailbox& mailbox) const;
+
+ // Assignment
+ void copyFrom(const component& other);
+ shared_ptr <component> clone() const;
+ mailbox& operator=(const mailbox& other);
+
+ bool isEmpty() const;
+
+ void clear();
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+
+ bool isGroup() const;
+
+protected:
+
+ text m_name;
+ emailAddress m_email;
+
+public:
+
+ using address::parse;
+ using address::generate;
+
+ // Component parsing & assembling
+ void parseImpl(
+ const 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;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_MAILBOX_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/mailboxField.cpp b/vmime-master/src/vmime/mailboxField.cpp
new file mode 100644
index 0000000..82ef592
--- /dev/null
+++ b/vmime-master/src/vmime/mailboxField.cpp
@@ -0,0 +1,96 @@
+//
+// 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.
+//
+
+#include "vmime/mailboxField.hpp"
+#include "vmime/mailboxGroup.hpp"
+
+
+#ifndef VMIME_BUILDING_DOC
+
+
+namespace vmime {
+
+
+mailboxField::mailboxField() {
+
+}
+
+
+mailboxField::mailboxField(const mailboxField&)
+ : headerField() {
+
+}
+
+
+void mailboxField::parse(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ shared_ptr <mailbox> mbox = make_shared <mailbox>();
+
+ // Here, we cannot simply call "m_mailbox.parse()" because it
+ // may have more than one address specified (even if this field
+ // should contain only one). We are never too much careful...
+ shared_ptr <address> parsedAddress = address::parseNext(
+ ctx, buffer, position, end, newPosition, NULL
+ );
+
+ if (parsedAddress) {
+
+ if (parsedAddress->isGroup()) {
+
+ // If it is a group of mailboxes, take the first
+ // mailbox of the group
+ shared_ptr <mailboxGroup> group = dynamicCast <mailboxGroup>(parsedAddress);
+
+ if (!group->isEmpty()) {
+ mbox = group->getMailboxAt(0);
+ }
+
+ } else {
+
+ // Parse only if it is a mailbox
+ mbox = dynamicCast <mailbox>(parsedAddress);
+ }
+ }
+
+ mbox->setParsedBounds(position, end);
+
+ setValue(mbox);
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+} // vmime
+
+
+#endif // VMIME_BUILDING_DOC
diff --git a/vmime-master/src/vmime/mailboxField.hpp b/vmime-master/src/vmime/mailboxField.hpp
new file mode 100644
index 0000000..6c65361
--- /dev/null
+++ b/vmime-master/src/vmime/mailboxField.hpp
@@ -0,0 +1,69 @@
+//
+// 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_MAILBOXFIELD_HPP_INCLUDED
+#define VMIME_MAILBOXFIELD_HPP_INCLUDED
+
+
+#include "vmime/headerField.hpp"
+#include "vmime/mailbox.hpp"
+
+
+// Hide implementation details from user
+#ifndef VMIME_BUILDING_DOC
+
+
+namespace vmime {
+
+
+/** Work-around for malformed header fields that are of type 'mailbox'
+ * and contains multiple addresses.
+ */
+class VMIME_EXPORT mailboxField : public headerField {
+
+ friend class headerFieldFactory;
+
+protected:
+
+ mailboxField();
+ mailboxField(const mailboxField&);
+
+public:
+
+ void parse(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t * newPosition = NULL
+ );
+};
+
+
+#endif // VMIME_BUILDING_DOC
+
+
+} // vmime
+
+
+#endif // VMIME_MAILBOXFIELD_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/mailboxGroup.cpp b/vmime-master/src/vmime/mailboxGroup.cpp
new file mode 100644
index 0000000..38a6e35
--- /dev/null
+++ b/vmime-master/src/vmime/mailboxGroup.cpp
@@ -0,0 +1,406 @@
+//
+// 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.
+//
+
+#include "vmime/mailboxGroup.hpp"
+#include "vmime/parserHelpers.hpp"
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+
+
+mailboxGroup::mailboxGroup() {
+
+}
+
+
+mailboxGroup::mailboxGroup(const mailboxGroup& mboxGroup)
+ : address() {
+
+ copyFrom(mboxGroup);
+}
+
+
+mailboxGroup::mailboxGroup(const text& name)
+ : m_name(name) {
+
+}
+
+
+mailboxGroup::~mailboxGroup() {
+
+ removeAllMailboxes();
+}
+
+
+void mailboxGroup::parseImpl(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ const char* const pend = buffer.data() + end;
+ const char* const pstart = buffer.data() + position;
+ const char* p = pstart;
+
+ while (p < pend && parserHelpers::isSpace(*p)) {
+ ++p;
+ }
+
+ string name;
+
+ while (p < pend && *p != ':') {
+ name += *p;
+ ++p;
+ }
+
+ if (p < pend && *p == ':') {
+ ++p;
+ }
+
+
+ size_t pos = position + (p - pstart);
+ bool isLastAddressOfGroup = false;
+
+ while (pos < end && !isLastAddressOfGroup) {
+
+ shared_ptr <address> parsedAddress =
+ address::parseNext(ctx, buffer, pos, end, &pos, &isLastAddressOfGroup);
+
+ if (parsedAddress) {
+
+ if (parsedAddress->isGroup()) {
+
+ shared_ptr <mailboxGroup> group = dynamicCast <mailboxGroup>(parsedAddress);
+
+ // Sub-groups are not allowed in mailbox groups: so, we add all
+ // the contents of the sub-group into this group...
+ for (size_t i = 0 ; i < group->getMailboxCount() ; ++i) {
+ m_list.push_back(vmime::clone(group->getMailboxAt(i)));
+ }
+
+ } else {
+
+ m_list.push_back(dynamicCast <mailbox>(parsedAddress));
+ }
+ }
+ }
+
+ text::decodeAndUnfold(ctx, utility::stringUtils::trim(name), &m_name);
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void mailboxGroup::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ // We have to encode the name:
+ // - if it contains characters in a charset different from "US-ASCII",
+ // - and/or if it contains one or more of these special chars:
+ // SPACE TAB " ; , < > ( ) @ / ? . = :
+
+ // Check whether there are words that are not "US-ASCII"
+ // and/or contain the special chars.
+ bool forceEncode = false;
+
+ for (size_t w = 0 ; !forceEncode && w < m_name.getWordCount() ; ++w) {
+
+ if (m_name.getWordAt(w)->getCharset() == charset(charsets::US_ASCII)) {
+
+ const string& buffer = m_name.getWordAt(w)->getBuffer();
+
+ for (string::const_iterator c = buffer.begin() ;
+ !forceEncode && c != buffer.end() ; ++c) {
+
+ switch (*c) {
+
+ case ' ':
+ case '\t':
+ case ';':
+ case ',':
+ case '<': case '>':
+ case '(': case ')':
+ case '@':
+ case '/':
+ case '?':
+ case '.':
+ case '=':
+ case ':':
+
+ forceEncode = true;
+ break;
+ }
+ }
+ }
+ }
+
+ size_t pos = curLinePos;
+
+ generationContext tmpCtx(ctx);
+ tmpCtx.setMaxLineLength(ctx.getMaxLineLength() - 2);
+
+ m_name.encodeAndFold(
+ ctx, os, pos, &pos,
+ forceEncode ? text::FORCE_ENCODING : 0
+ );
+
+ os << ":";
+ ++pos;
+
+ for (std::vector <shared_ptr <mailbox> >::const_iterator it = m_list.begin() ;
+ it != m_list.end() ; ++it) {
+
+ if (it != m_list.begin()) {
+
+ os << ", ";
+ pos += 2;
+
+ } else {
+
+ os << " ";
+ ++pos;
+ }
+
+ (*it)->generate(tmpCtx, os, pos, &pos);
+ }
+
+ os << ";";
+ pos++;
+
+ if (newLinePos) {
+ *newLinePos = pos;
+ }
+}
+
+
+void mailboxGroup::copyFrom(const component& other) {
+
+ const mailboxGroup& source = dynamic_cast <const mailboxGroup&>(other);
+
+ m_name = source.m_name;
+
+ removeAllMailboxes();
+
+ for (std::vector <shared_ptr <mailbox> >::const_iterator it = source.m_list.begin() ;
+ it != source.m_list.end() ; ++it) {
+
+ m_list.push_back(vmime::clone(*it));
+ }
+}
+
+
+shared_ptr <component> mailboxGroup::clone() const {
+
+ return make_shared <mailboxGroup>(*this);
+}
+
+
+mailboxGroup& mailboxGroup::operator=(const component& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+const text& mailboxGroup::getName() const {
+
+ return m_name;
+}
+
+
+void mailboxGroup::setName(const text& name) {
+
+ m_name = name;
+}
+
+
+bool mailboxGroup::isGroup() const {
+
+ return true;
+}
+
+
+bool mailboxGroup::isEmpty() const {
+
+ return m_list.empty();
+}
+
+
+void mailboxGroup::appendMailbox(const shared_ptr <mailbox>& mbox) {
+
+ m_list.push_back(mbox);
+}
+
+
+void mailboxGroup::insertMailboxBefore(
+ const shared_ptr <mailbox>& beforeMailbox,
+ const shared_ptr <mailbox>& mbox
+) {
+
+ const std::vector <shared_ptr <mailbox> >::iterator it =
+ std::find(m_list.begin(), m_list.end(), beforeMailbox);
+
+ if (it == m_list.end()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ m_list.insert(it, mbox);
+}
+
+
+void mailboxGroup::insertMailboxBefore(
+ const size_t pos,
+ const shared_ptr <mailbox>& mbox
+) {
+
+ if (pos >= m_list.size()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ m_list.insert(m_list.begin() + pos, mbox);
+}
+
+
+void mailboxGroup::insertMailboxAfter(
+ const shared_ptr <mailbox>& afterMailbox,
+ const shared_ptr <mailbox>& mbox
+) {
+
+ const std::vector <shared_ptr <mailbox> >::iterator it =
+ std::find(m_list.begin(), m_list.end(), afterMailbox);
+
+ if (it == m_list.end()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ m_list.insert(it + 1, mbox);
+}
+
+
+void mailboxGroup::insertMailboxAfter(
+ const size_t pos,
+ const shared_ptr <mailbox>& mbox
+) {
+
+ if (pos >= m_list.size()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ m_list.insert(m_list.begin() + pos + 1, mbox);
+}
+
+
+void mailboxGroup::removeMailbox(const shared_ptr <mailbox>& mbox) {
+
+ const std::vector <shared_ptr <mailbox> >::iterator it =
+ std::find(m_list.begin(), m_list.end(), mbox);
+
+ if (it == m_list.end()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ m_list.erase(it);
+}
+
+
+void mailboxGroup::removeMailbox(const size_t pos) {
+
+ if (pos >= m_list.size()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ const std::vector <shared_ptr <mailbox> >::iterator it = m_list.begin() + pos;
+
+ m_list.erase(it);
+}
+
+
+void mailboxGroup::removeAllMailboxes() {
+
+ m_list.clear();
+}
+
+
+size_t mailboxGroup::getMailboxCount() const {
+
+ return m_list.size();
+}
+
+
+shared_ptr <mailbox> mailboxGroup::getMailboxAt(const size_t pos) {
+
+ return m_list[pos];
+}
+
+
+const shared_ptr <const mailbox> mailboxGroup::getMailboxAt(const size_t pos) const {
+
+ return m_list[pos];
+}
+
+
+const std::vector <shared_ptr <const mailbox> > mailboxGroup::getMailboxList() const {
+
+ std::vector <shared_ptr <const mailbox> > list;
+
+ list.reserve(m_list.size());
+
+ for (std::vector <shared_ptr <mailbox> >::const_iterator it = m_list.begin() ;
+ it != m_list.end() ; ++it) {
+
+ list.push_back(*it);
+ }
+
+ return list;
+}
+
+
+const std::vector <shared_ptr <mailbox> > mailboxGroup::getMailboxList() {
+
+ return m_list;
+}
+
+
+const std::vector <shared_ptr <component> > mailboxGroup::getChildComponents() {
+
+ std::vector <shared_ptr <component> > list;
+
+ copy_vector(m_list, list);
+
+ return list;
+
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/mailboxGroup.hpp b/vmime-master/src/vmime/mailboxGroup.hpp
new file mode 100644
index 0000000..4a7da3e
--- /dev/null
+++ b/vmime-master/src/vmime/mailboxGroup.hpp
@@ -0,0 +1,206 @@
+//
+// 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_MAILBOXGROUP_HPP_INCLUDED
+#define VMIME_MAILBOXGROUP_HPP_INCLUDED
+
+
+#include "vmime/address.hpp"
+#include "vmime/mailbox.hpp"
+#include "vmime/text.hpp"
+
+
+namespace vmime {
+
+
+/** A group of mailboxes (basic type).
+ */
+class VMIME_EXPORT mailboxGroup : public address {
+
+public:
+
+ mailboxGroup();
+ mailboxGroup(const mailboxGroup& mboxGroup);
+ mailboxGroup(const text& name);
+
+ ~mailboxGroup();
+
+
+ void copyFrom(const component& other);
+ shared_ptr <component> clone() const;
+ mailboxGroup& operator=(const component& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+ /** Return the name of the group.
+ *
+ * @return group name
+ */
+ const text& getName() const;
+
+ /** Set the name of the group.
+ *
+ * @param name group name
+ */
+ void setName(const text& name);
+
+ /** Add a mailbox at the end of the list.
+ *
+ * @param mbox mailbox to append
+ */
+ void appendMailbox(const shared_ptr <mailbox>& mbox);
+
+ /** Insert a new mailbox before the specified mailbox.
+ *
+ * @param beforeMailbox mailbox before which the new mailbox will be inserted
+ * @param mbox mailbox to insert
+ * @throw std::out_of_range if the mailbox is not in the list
+ */
+ void insertMailboxBefore(
+ const shared_ptr <mailbox>& beforeMailbox,
+ const shared_ptr <mailbox>& mbox
+ );
+
+ /** Insert a new mailbox before the specified position.
+ *
+ * @param pos position at which to insert the new mailbox (0 to insert at
+ * the beginning of the list)
+ * @param mbox mailbox to insert
+ * @throw std::out_of_range if the position is out of range
+ */
+ void insertMailboxBefore(
+ const size_t pos,
+ const shared_ptr <mailbox>& mbox
+ );
+
+ /** Insert a new mailbox after the specified mailbox.
+ *
+ * @param afterMailbox mailbox after which the new mailbox will be inserted
+ * @param mbox mailbox to insert
+ * @throw std::out_of_range if the mailbox is not in the list
+ */
+ void insertMailboxAfter(
+ const shared_ptr <mailbox>& afterMailbox,
+ const shared_ptr <mailbox>& mbox
+ );
+
+ /** Insert a new mailbox after the specified position.
+ *
+ * @param pos position of the mailbox before the new mailbox
+ * @param mbox mailbox to insert
+ * @throw std::out_of_range if the position is out of range
+ */
+ void insertMailboxAfter(
+ const size_t pos,
+ const shared_ptr <mailbox>& mbox
+ );
+
+ /** Remove the specified mailbox from the list.
+ *
+ * @param mbox mailbox to remove
+ * @throw std::out_of_range if the mailbox is not in the list
+ */
+ void removeMailbox(const shared_ptr <mailbox>& mbox);
+
+ /** Remove the mailbox at the specified position.
+ *
+ * @param pos position of the mailbox to remove
+ * @throw std::out_of_range if the position is out of range
+ */
+ void removeMailbox(const size_t pos);
+
+ /** Remove all mailboxes from the list.
+ */
+ void removeAllMailboxes();
+
+ /** Return the number of mailboxes in the list.
+ *
+ * @return number of mailboxes
+ */
+ size_t getMailboxCount() const;
+
+ /** Tests whether the list of mailboxes is empty.
+ *
+ * @return true if there is no mailbox, false otherwise
+ */
+ bool isEmpty() const;
+
+ /** Return the mailbox at the specified position.
+ *
+ * @param pos position
+ * @return mailbox at position 'pos'
+ * @throw std::out_of_range if the position is out of range
+ */
+ shared_ptr <mailbox> getMailboxAt(const size_t pos);
+
+ /** Return the mailbox at the specified position.
+ *
+ * @param pos position
+ * @return mailbox at position 'pos'
+ * @throw std::out_of_range if the position is out of range
+ */
+ const shared_ptr <const mailbox> getMailboxAt(const size_t pos) const;
+
+ /** Return the mailbox list.
+ *
+ * @return list of mailboxes
+ */
+ const std::vector <shared_ptr <const mailbox> > getMailboxList() const;
+
+ /** Return the mailbox list.
+ *
+ * @return list of mailboxes
+ */
+ const std::vector <shared_ptr <mailbox> > getMailboxList();
+
+ bool isGroup() const;
+
+private:
+
+ text m_name;
+ std::vector <shared_ptr <mailbox> > m_list;
+
+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 generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_MAILBOXGROUP_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/mailboxList.cpp b/vmime-master/src/vmime/mailboxList.cpp
new file mode 100644
index 0000000..e7aba81
--- /dev/null
+++ b/vmime-master/src/vmime/mailboxList.cpp
@@ -0,0 +1,252 @@
+//
+// 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.
+//
+
+#include "vmime/mailboxList.hpp"
+#include "vmime/mailboxGroup.hpp"
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+
+
+mailboxList::mailboxList() {
+
+}
+
+
+mailboxList::mailboxList(const mailboxList& mboxList)
+ : headerFieldValue(),
+ m_list(mboxList.m_list) {
+
+}
+
+
+void mailboxList::appendMailbox(const shared_ptr <mailbox>& mbox) {
+
+ m_list.appendAddress(mbox);
+}
+
+
+void mailboxList::insertMailboxBefore(
+ const shared_ptr <mailbox>& beforeMailbox,
+ const shared_ptr <mailbox>& mbox
+) {
+
+ m_list.insertAddressBefore(beforeMailbox, mbox);
+}
+
+
+void mailboxList::insertMailboxBefore(
+ const size_t pos,
+ const shared_ptr <mailbox>& mbox
+) {
+
+ m_list.insertAddressBefore(pos, mbox);
+}
+
+
+void mailboxList::insertMailboxAfter(
+ const shared_ptr <mailbox>& afterMailbox,
+ const shared_ptr <mailbox>& mbox
+) {
+
+ m_list.insertAddressAfter(afterMailbox, mbox);
+}
+
+
+void mailboxList::insertMailboxAfter(
+ const size_t pos,
+ const shared_ptr <mailbox>& mbox
+) {
+
+ m_list.insertAddressAfter(pos, mbox);
+}
+
+
+void mailboxList::removeMailbox(const shared_ptr <mailbox>& mbox) {
+
+ m_list.removeAddress(mbox);
+}
+
+
+void mailboxList::removeMailbox(const size_t pos) {
+
+ m_list.removeAddress(pos);
+}
+
+
+void mailboxList::removeAllMailboxes() {
+
+ m_list.removeAllAddresses();
+}
+
+
+size_t mailboxList::getMailboxCount() const {
+
+ return m_list.getAddressCount();
+}
+
+
+bool mailboxList::isEmpty() const {
+
+ return m_list.isEmpty();
+}
+
+
+shared_ptr <mailbox> mailboxList::getMailboxAt(const size_t pos) {
+
+ return dynamicCast <mailbox>(m_list.getAddressAt(pos));
+}
+
+
+const shared_ptr <const mailbox> mailboxList::getMailboxAt(const size_t pos) const {
+
+ return dynamicCast <const mailbox>(m_list.getAddressAt(pos));
+}
+
+
+const std::vector <shared_ptr <const mailbox> > mailboxList::getMailboxList() const {
+
+ const std::vector <shared_ptr <const address> > addrList = m_list.getAddressList();
+ std::vector <shared_ptr <const mailbox> > res;
+
+ for (std::vector <shared_ptr <const address> >::const_iterator it = addrList.begin() ;
+ it != addrList.end() ; ++it) {
+
+ const shared_ptr <const mailbox> mbox = dynamicCast <const mailbox>(*it);
+
+ if (mbox) {
+ res.push_back(mbox);
+ }
+ }
+
+ return res;
+}
+
+
+const std::vector <shared_ptr <mailbox> > mailboxList::getMailboxList() {
+
+ const std::vector <shared_ptr <address> > addrList = m_list.getAddressList();
+ std::vector <shared_ptr <mailbox> > res;
+
+ for (std::vector <shared_ptr <address> >::const_iterator it = addrList.begin() ;
+ it != addrList.end() ; ++it) {
+
+ const shared_ptr <mailbox> mbox = dynamicCast <mailbox>(*it);
+
+ if (mbox) {
+ res.push_back(mbox);
+ }
+ }
+
+ return res;
+}
+
+
+shared_ptr <component> mailboxList::clone() const {
+
+ return make_shared <mailboxList>(*this);
+}
+
+
+void mailboxList::copyFrom(const component& other) {
+
+ const mailboxList& mboxList = dynamic_cast <const mailboxList&>(other);
+
+ m_list = mboxList.m_list;
+}
+
+
+mailboxList& mailboxList::operator=(const mailboxList& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+const std::vector <shared_ptr <component> > mailboxList::getChildComponents() {
+
+ return m_list.getChildComponents();
+}
+
+
+void mailboxList::parseImpl(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ m_list.removeAllAddresses();
+
+ size_t pos = position;
+
+ while (pos < end) {
+
+ shared_ptr <address> parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, NULL);
+
+ if (parsedAddress) {
+
+ if (parsedAddress->isGroup()) {
+
+ shared_ptr <mailboxGroup> group = dynamicCast <mailboxGroup>(parsedAddress);
+
+ for (size_t i = 0 ; i < group->getMailboxCount() ; ++i) {
+ m_list.appendAddress(group->getMailboxAt(i));
+ }
+
+ } else {
+
+ m_list.appendAddress(parsedAddress);
+ }
+ }
+ }
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void mailboxList::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ m_list.generate(ctx, os, curLinePos, newLinePos);
+}
+
+
+shared_ptr <addressList> mailboxList::toAddressList() const {
+
+ return vmime::clone(m_list);
+}
+
+
+} // vmime
+
diff --git a/vmime-master/src/vmime/mailboxList.hpp b/vmime-master/src/vmime/mailboxList.hpp
new file mode 100644
index 0000000..8d799d2
--- /dev/null
+++ b/vmime-master/src/vmime/mailboxList.hpp
@@ -0,0 +1,184 @@
+//
+// 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_MAILBOXLIST_HPP_INCLUDED
+#define VMIME_MAILBOXLIST_HPP_INCLUDED
+
+
+#include "vmime/addressList.hpp"
+#include "vmime/mailbox.hpp"
+
+
+namespace vmime {
+
+
+/** A list of mailboxes (basic type).
+ *
+ * This class works exactly like 'addressList' except it prevents user
+ * from inserting mailbox groups where it is not allowed by the RFC.
+ */
+class VMIME_EXPORT mailboxList : public headerFieldValue {
+
+public:
+
+ mailboxList();
+ mailboxList(const mailboxList& mboxList);
+
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ mailboxList& operator=(const mailboxList& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+ /** Add a mailbox at the end of the list.
+ *
+ * @param mbox mailbox to append
+ */
+ void appendMailbox(const shared_ptr <mailbox>& mbox);
+
+ /** Insert a new mailbox before the specified mailbox.
+ *
+ * @param beforeMailbox mailbox before which the new mailbox will be inserted
+ * @param mbox mailbox to insert
+ * @throw std::out_of_range if the mailbox is not in the list
+ */
+ void insertMailboxBefore(const shared_ptr <mailbox>& beforeMailbox, const shared_ptr <mailbox>& mbox);
+
+ /** Insert a new mailbox before the specified position.
+ *
+ * @param pos position at which to insert the new mailbox (0 to insert at
+ * the beginning of the list)
+ * @param mbox mailbox to insert
+ * @throw std::out_of_range if the position is out of range
+ */
+ void insertMailboxBefore(const size_t pos, const shared_ptr <mailbox>& mbox);
+
+ /** Insert a new mailbox after the specified mailbox.
+ *
+ * @param afterMailbox mailbox after which the new mailbox will be inserted
+ * @param mbox mailbox to insert
+ * @throw std::out_of_range if the mailbox is not in the list
+ */
+ void insertMailboxAfter(const shared_ptr <mailbox>& afterMailbox, const shared_ptr <mailbox>& mbox);
+
+ /** Insert a new mailbox after the specified position.
+ *
+ * @param pos position of the mailbox before the new mailbox
+ * @param mbox mailbox to insert
+ * @throw std::out_of_range if the position is out of range
+ */
+ void insertMailboxAfter(const size_t pos, const shared_ptr <mailbox>& mbox);
+
+ /** Remove the specified mailbox from the list.
+ *
+ * @param mbox mailbox to remove
+ * @throw std::out_of_range if the mailbox is not in the list
+ */
+ void removeMailbox(const shared_ptr <mailbox>& mbox);
+
+ /** Remove the mailbox at the specified position.
+ *
+ * @param pos position of the mailbox to remove
+ * @throw std::out_of_range if the position is out of range
+ */
+ void removeMailbox(const size_t pos);
+
+ /** Remove all mailboxes from the list.
+ */
+ void removeAllMailboxes();
+
+ /** Return the number of mailboxes in the list.
+ *
+ * @return number of mailboxes
+ */
+ size_t getMailboxCount() const;
+
+ /** Tests whether the list of mailboxes is empty.
+ *
+ * @return true if there is no mailbox, false otherwise
+ */
+ bool isEmpty() const;
+
+ /** Return the mailbox at the specified position.
+ *
+ * @param pos position
+ * @return mailbox at position 'pos'
+ * @throw std::out_of_range if the position is out of range
+ */
+ shared_ptr <mailbox> getMailboxAt(const size_t pos);
+
+ /** Return the mailbox at the specified position.
+ *
+ * @param pos position
+ * @return mailbox at position 'pos'
+ * @throw std::out_of_range if the position is out of range
+ */
+ const shared_ptr <const mailbox> getMailboxAt(const size_t pos) const;
+
+ /** Return the mailbox list.
+ *
+ * @return list of mailboxes
+ */
+ const std::vector <shared_ptr <const mailbox> > getMailboxList() const;
+
+ /** Return the mailbox list.
+ *
+ * @return list of mailboxes
+ */
+ const std::vector <shared_ptr <mailbox> > getMailboxList();
+
+ /** Return a list of addresses.
+ *
+ * @return list of addresses
+ */
+ shared_ptr <addressList> toAddressList() const;
+
+private:
+
+ addressList m_list;
+
+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 generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_MAILBOXLIST_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/mdn/MDNHelper.cpp b/vmime-master/src/vmime/mdn/MDNHelper.cpp
new file mode 100644
index 0000000..a21a181
--- /dev/null
+++ b/vmime-master/src/vmime/mdn/MDNHelper.cpp
@@ -0,0 +1,362 @@
+//
+// 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.
+//
+
+#include "vmime/mdn/MDNHelper.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/stringContentHandler.hpp"
+
+#include "vmime/contentTypeField.hpp"
+
+#include "vmime/path.hpp"
+#include "vmime/dateTime.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+void MDNHelper::attachMDNRequest(const shared_ptr <message>& msg, const mailboxList& mailboxes) {
+
+ shared_ptr <header> hdr = msg->getHeader();
+
+ hdr->DispositionNotificationTo()->setValue(mailboxes);
+}
+
+
+void MDNHelper::attachMDNRequest(const shared_ptr <message>& msg, const mailbox& mbox) {
+
+ mailboxList mboxList;
+ mboxList.appendMailbox(vmime::clone(mbox));
+
+ attachMDNRequest(msg, mboxList);
+}
+
+
+const std::vector <sendableMDNInfos> MDNHelper::getPossibleMDNs(const shared_ptr <const message>& msg) {
+
+ std::vector <sendableMDNInfos> result;
+
+ const shared_ptr <const header> hdr = msg->getHeader();
+
+ if (hdr->hasField(fields::DISPOSITION_NOTIFICATION_TO)) {
+
+ const mailboxList& dnto =
+ *hdr->DispositionNotificationTo()->getValue <mailboxList>();
+
+ for (size_t i = 0 ; i < dnto.getMailboxCount() ; ++i) {
+ result.push_back(sendableMDNInfos(msg, *dnto.getMailboxAt(i)));
+ }
+ }
+
+ return result;
+}
+
+
+bool MDNHelper::isMDN(const shared_ptr <const message>& msg)
+{
+ const shared_ptr <const header> hdr = msg->getHeader();
+
+ // A MDN message implies the following:
+ // - a Content-Type field is present and its value is "multipart/report"
+ // - a "report-type" parameter is present in the Content-Type field,
+ // and its value is "disposition-notification"
+ if (hdr->hasField(fields::CONTENT_TYPE)) {
+
+ const contentTypeField& ctf = *dynamicCast <const contentTypeField>(hdr->ContentType());
+
+ const mediaType type = *ctf.getValue <mediaType>();
+
+ if (type.getType() == vmime::mediaTypes::MULTIPART &&
+ type.getSubType() == vmime::mediaTypes::MULTIPART_REPORT) {
+
+ if (ctf.hasParameter("report-type") &&
+ ctf.getReportType() == "disposition-notification") {
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+receivedMDNInfos MDNHelper::getReceivedMDN(const shared_ptr <const message>& msg)
+{
+ if (!isMDN(msg)) {
+ throw exceptions::invalid_argument();
+ }
+
+ return receivedMDNInfos(msg);
+}
+
+
+bool MDNHelper::needConfirmation(const shared_ptr <const message>& msg)
+{
+ shared_ptr <const header> hdr = msg->getHeader();
+
+ // No "Return-Path" field
+ if (!hdr->hasField(fields::RETURN_PATH)) {
+ return true;
+ }
+
+ // More than one address in Disposition-Notification-To
+ if (hdr->hasField(fields::DISPOSITION_NOTIFICATION_TO)) {
+
+ const mailboxList& dnto = *hdr->DispositionNotificationTo()->getValue <mailboxList>();
+
+ if (dnto.getMailboxCount() > 1) {
+ return true;
+ } else if (dnto.getMailboxCount() == 0) {
+ return false;
+ }
+
+ // Return-Path != Disposition-Notification-To
+ const mailbox& mbox = *dnto.getMailboxAt(0);
+ const path& rp = *hdr->ReturnPath()->getValue <path>();
+
+ if (mbox.getEmail() != rp.getLocalPart() + "@" + rp.getDomain()) {
+ return true;
+ }
+ }
+
+ // User confirmation not needed
+ return false;
+}
+
+
+shared_ptr <message> MDNHelper::buildMDN(
+ const sendableMDNInfos& mdnInfos,
+ const string& text,
+ const charset& ch,
+ const mailbox& expeditor,
+ const disposition& dispo,
+ const string& reportingUA,
+ const std::vector <string>& reportingUAProducts,
+ const std::map <string, string>& fields
+) {
+
+ // Create a new message
+ shared_ptr <message> msg = make_shared <message>();
+
+ // Fill-in header fields
+ shared_ptr <header> hdr = msg->getHeader();
+
+ hdr->ContentType()->setValue(
+ mediaType(vmime::mediaTypes::MULTIPART, vmime::mediaTypes::MULTIPART_REPORT)
+ );
+
+ dynamicCast <contentTypeField>(hdr->ContentType())->setReportType("disposition-notification");
+
+ hdr->Disposition()->setValue(dispo);
+
+ addressList to;
+ to.appendAddress(make_shared <mailbox>(mdnInfos.getRecipient()));
+ hdr->To()->setValue(to);
+
+ hdr->From()->setValue(expeditor);
+
+ hdr->Subject()->setValue(vmime::text(word("Disposition notification")));
+
+ hdr->Date()->setValue(datetime::now());
+ hdr->MimeVersion()->setValue(string(SUPPORTED_MIME_VERSION));
+
+ msg->getBody()->appendPart(createFirstMDNPart(mdnInfos, text, ch));
+ msg->getBody()->appendPart(createSecondMDNPart(mdnInfos,
+ dispo, reportingUA, reportingUAProducts, fields));
+ msg->getBody()->appendPart(createThirdMDNPart(mdnInfos));
+
+ return msg;
+}
+
+
+shared_ptr <bodyPart> MDNHelper::createFirstMDNPart(
+ const sendableMDNInfos& /* mdnInfos */,
+ const string& text,
+ const charset& ch
+) {
+
+ shared_ptr <bodyPart> part = make_shared <bodyPart>();
+
+ // Header
+ shared_ptr <header> hdr = part->getHeader();
+
+ hdr->ContentType()->setValue(
+ mediaType(vmime::mediaTypes::TEXT, vmime::mediaTypes::TEXT_PLAIN)
+ );
+
+ dynamicCast <contentTypeField>(hdr->ContentType())->setCharset(ch);
+
+ // Body
+ part->getBody()->setContents(make_shared <stringContentHandler>(text));
+
+ return part;
+}
+
+
+shared_ptr <bodyPart> MDNHelper::createSecondMDNPart(
+ const sendableMDNInfos& mdnInfos,
+ const disposition& dispo,
+ const string& reportingUA,
+ const std::vector <string>& reportingUAProducts,
+ const std::map <string, string>& additionalFields
+) {
+
+ shared_ptr <bodyPart> part = make_shared <bodyPart>();
+
+ // Header
+ shared_ptr <header> hdr = part->getHeader();
+
+ hdr->ContentDisposition()->setValue(vmime::contentDispositionTypes::INLINE);
+ hdr->ContentType()->setValue(mediaType(vmime::mediaTypes::MESSAGE,
+ vmime::mediaTypes::MESSAGE_DISPOSITION_NOTIFICATION));
+
+ // Body
+ //
+ // The body of a message/disposition-notification consists of one or
+ // more "fields" formatted according to the ABNF of [RFC-MSGFMT] header
+ // "fields". The syntax of the message/disposition-notification content
+ // is as follows:
+ //
+ // disposition-notification-content = [ reporting-ua-field CRLF ]
+ // [ mdn-gateway-field CRLF ]
+ // [ original-recipient-field CRLF ]
+ // final-recipient-field CRLF
+ // [ original-message-id-field CRLF ]
+ // disposition-field CRLF
+ // *( failure-field CRLF )
+ // *( error-field CRLF )
+ // *( warning-field CRLF )
+ // *( extension-field CRLF )
+ //
+ header fields;
+
+ // -- Reporting-UA (optional)
+ if (!reportingUA.empty()) {
+
+ string ruaText;
+ ruaText = reportingUA;
+
+ for (unsigned int i = 0 ; i < reportingUAProducts.size() ; ++i) {
+
+ if (i == 0) {
+ ruaText += "; ";
+ } else {
+ ruaText += ", ";
+ }
+
+ ruaText += reportingUAProducts[i];
+ }
+
+ shared_ptr <headerField> rua = headerFieldFactory::getInstance()->
+ create(vmime::fields::REPORTING_UA);
+
+ rua->setValue(ruaText);
+
+ fields.appendField(rua);
+ }
+
+ // -- Final-Recipient
+ shared_ptr <headerField> fr = headerFieldFactory::getInstance()->
+ create(vmime::fields::FINAL_RECIPIENT);
+
+ fr->setValue("rfc822; " + mdnInfos.getRecipient().getEmail().generate());
+
+ fields.appendField(fr);
+
+ // -- Original-Message-ID
+ if (mdnInfos.getMessage()->getHeader()->hasField(vmime::fields::MESSAGE_ID)) {
+
+ fields.OriginalMessageId()->setValueConst
+ (mdnInfos.getMessage()->getHeader()->MessageId()->getValue());
+ }
+
+ // -- Disposition
+ fields.Disposition()->setValue(dispo);
+
+ // -- Failure, Error and Warning fields
+ std::map <string, string>::const_iterator it;
+
+ if (additionalFields.size() > 0) {
+
+ if ((it = additionalFields.find(vmime::fields::ERROR)) != additionalFields.end()) {
+
+ shared_ptr <headerField> error = headerFieldFactory::getInstance()->create(vmime::fields::ERROR);
+ error->setValue(it->second);
+ fields.appendField(error);
+ }
+
+ if ((it = additionalFields.find(vmime::fields::WARNING)) != additionalFields.end()) {
+
+ shared_ptr <headerField> warn = headerFieldFactory::getInstance()->create(vmime::fields::WARNING);
+ warn->setValue(it->second);
+ fields.appendField(warn);
+ }
+
+ if ((it = additionalFields.find(vmime::fields::FAILURE)) != additionalFields.end()) {
+
+ shared_ptr <headerField> fail = headerFieldFactory::getInstance()->create(vmime::fields::FAILURE);
+ fail->setValue(it->second);
+ fields.appendField(fail);
+ }
+ }
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter vos(oss);
+
+ fields.generate(vos);
+
+ part->getBody()->setContents(make_shared <stringContentHandler>(oss.str()));
+
+ return part;
+}
+
+
+shared_ptr <bodyPart> MDNHelper::createThirdMDNPart(const sendableMDNInfos& mdnInfos) {
+
+ shared_ptr <bodyPart> part = make_shared <bodyPart>();
+
+ // Header
+ shared_ptr <header> hdr = part->getHeader();
+
+ hdr->ContentDisposition()->setValue(vmime::contentDispositionTypes::INLINE);
+ hdr->ContentType()->setValue(mediaType(vmime::mediaTypes::TEXT,
+ vmime::mediaTypes::TEXT_RFC822_HEADERS));
+
+ // Body: original message headers
+ std::ostringstream oss;
+ utility::outputStreamAdapter vos(oss);
+
+ mdnInfos.getMessage()->getHeader()->generate(vos);
+
+ part->getBody()->setContents(make_shared <stringContentHandler>(oss.str()));
+
+ return part;
+}
+
+
+} // mdn
+} // vmime
diff --git a/vmime-master/src/vmime/mdn/MDNHelper.hpp b/vmime-master/src/vmime/mdn/MDNHelper.hpp
new file mode 100644
index 0000000..c1bec2f
--- /dev/null
+++ b/vmime-master/src/vmime/mdn/MDNHelper.hpp
@@ -0,0 +1,142 @@
+//
+// 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_MDN_MDNHELPER_HPP_INCLUDED
+#define VMIME_MDN_MDNHELPER_HPP_INCLUDED
+
+
+#include "vmime/mdn/receivedMDNInfos.hpp"
+#include "vmime/mdn/sendableMDNInfos.hpp"
+
+#include "vmime/mailboxList.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+/** Helper for creating or extracting Message Disposition
+ * Notifications (MDN), as defined in RFC-3798.
+ */
+class VMIME_EXPORT MDNHelper {
+
+public:
+
+ /** Attach a MDN request to the specified message.
+ *
+ * @param msg message in which to add a MDN request
+ * @param mailboxes list of mailboxes to which the MDN will be sent
+ */
+ static void attachMDNRequest(const shared_ptr <message>& msg, const mailboxList& mailboxes);
+
+ /** Attach a MDN request to the specified message.
+ *
+ * @param msg message in which to add a MDN request
+ * @param mbox mailbox to which the MDN will be sent
+ */
+ static void attachMDNRequest(const shared_ptr <message>& msg, const mailbox& mbox);
+
+ /** Return a list of possible MDNs that can be generated
+ * for the specified message.
+ *
+ * @param msg message for which to send a MDN
+ * @return list of possible MDNs
+ */
+ static const std::vector <sendableMDNInfos> getPossibleMDNs(const shared_ptr <const message>& msg);
+
+ /** Test whether the specified message is a MDN.
+ *
+ * @param msg message
+ * @return true if the message is a MDN, false otherwise
+ */
+ static bool isMDN(const shared_ptr <const message>& msg);
+
+ /** If the specified message is a MDN, return information
+ * about it.
+ *
+ * @param msg message
+ * @throw exceptions::invalid_argument if the message is not a MDN
+ * @return information about the MDN
+ */
+ static receivedMDNInfos getReceivedMDN(const shared_ptr <const message>& msg);
+
+ /** Check whether we need user confirmation for sending a MDN even
+ * if he/she explicitely allowed automatic send of MDNs. This can
+ * happen in some situations, described in RFC-3798.
+ *
+ * @param msg message for which to send a MDN
+ * @return true if user confirmation should be asked, false otherwise
+ */
+ static bool needConfirmation(const shared_ptr <const message>& msg);
+
+ /** Build a new MDN for the message. The resulting MDN can then be
+ * sent over SMTP transport service.
+ *
+ * @param mdnInfos information about the MDN to construct
+ * @param text human readable message. The purpose of this message is
+ * to provide an easily-understood description of the
+ * condition(s) that caused the report to be generated.
+ * @param ch charset of the text
+ * @param expeditor expeditor of the MDN
+ * @param dispo disposition information
+ * @param reportingUA name of reporting user-agent (optional)
+ * @param reportingUAProducts list of products in the reporting user-agent (optional)
+ * @param fields additional MDN fields, like "Error", "Warning" or "Failure" (optional)
+ * @return a new message object containing the MDN
+ */
+ static shared_ptr <message> buildMDN(
+ const sendableMDNInfos& mdnInfos,
+ const string& text,
+ const charset& ch,
+ const mailbox& expeditor,
+ const disposition& dispo,
+ const string& reportingUA = NULL_STRING,
+ const std::vector <string>& reportingUAProducts = std::vector <string>(),
+ const std::map <string, string>& fields = std::map <string, string>()
+ );
+
+private:
+
+ static shared_ptr <bodyPart> createFirstMDNPart(
+ const sendableMDNInfos& mdnInfos,
+ const string& text,
+ const charset& ch
+ );
+
+ static shared_ptr <bodyPart> createSecondMDNPart(
+ const sendableMDNInfos& mdnInfos,
+ const disposition& dispo,
+ const string& reportingUA,
+ const std::vector <string>& reportingUAProducts,
+ const std::map <string, string>& fields
+ );
+
+ static shared_ptr <bodyPart> createThirdMDNPart(const sendableMDNInfos& mdnInfos);
+};
+
+
+} // mdn
+} // vmime
+
+
+#endif // VMIME_MDN_MDNHELPER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/mdn/MDNInfos.cpp b/vmime-master/src/vmime/mdn/MDNInfos.cpp
new file mode 100644
index 0000000..3efe9f9
--- /dev/null
+++ b/vmime-master/src/vmime/mdn/MDNInfos.cpp
@@ -0,0 +1,38 @@
+//
+// 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.
+//
+
+#include "vmime/mdn/MDNInfos.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+
+MDNInfos::~MDNInfos() {
+
+}
+
+
+} // mdn
+} // vmime
diff --git a/vmime-master/src/vmime/mdn/MDNInfos.hpp b/vmime-master/src/vmime/mdn/MDNInfos.hpp
new file mode 100644
index 0000000..f6d7929
--- /dev/null
+++ b/vmime-master/src/vmime/mdn/MDNInfos.hpp
@@ -0,0 +1,57 @@
+//
+// 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_MDN_MDNINFOS_HPP_INCLUDED
+#define VMIME_MDN_MDNINFOS_HPP_INCLUDED
+
+
+#include "vmime/types.hpp"
+#include "vmime/message.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+/** Holds information about Message Disposition Notifications (MDN).
+ */
+class VMIME_EXPORT MDNInfos : public object {
+
+public:
+
+ virtual ~MDNInfos();
+
+
+ /** Return the message related to this MDN.
+ *
+ * @return related message
+ */
+ virtual const shared_ptr <const message> getMessage() const = 0;
+};
+
+
+} // mdn
+} // vmime
+
+
+#endif // VMIME_MDN_MDNINFOS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/mdn/receivedMDNInfos.cpp b/vmime-master/src/vmime/mdn/receivedMDNInfos.cpp
new file mode 100644
index 0000000..6f4463e
--- /dev/null
+++ b/vmime-master/src/vmime/mdn/receivedMDNInfos.cpp
@@ -0,0 +1,140 @@
+//
+// 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.
+//
+
+#include "vmime/mdn/receivedMDNInfos.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+receivedMDNInfos::receivedMDNInfos(const shared_ptr <const message>& msg)
+ : m_msg(msg) {
+
+ extract();
+}
+
+
+receivedMDNInfos::receivedMDNInfos(const receivedMDNInfos& other)
+ : MDNInfos() {
+
+ copyFrom(other);
+}
+
+
+receivedMDNInfos& receivedMDNInfos::operator=(const receivedMDNInfos& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+const shared_ptr <const message> receivedMDNInfos::getMessage() const {
+
+ return m_msg;
+}
+
+
+const messageId receivedMDNInfos::getOriginalMessageId() const {
+
+ return m_omid;
+}
+
+
+const disposition receivedMDNInfos::getDisposition() const {
+
+ return m_disp;
+}
+
+
+const string receivedMDNInfos::getContentMIC() const {
+
+ return m_contentMIC;
+}
+
+
+void receivedMDNInfos::copyFrom(const receivedMDNInfos& other) {
+
+ m_msg = other.m_msg;
+ m_omid = other.m_omid;
+ m_disp = other.m_disp;
+ m_contentMIC = other.m_contentMIC;
+}
+
+
+void receivedMDNInfos::extract() {
+
+ const shared_ptr <const body> bdy = m_msg->getBody();
+
+ for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) {
+
+ const shared_ptr <const bodyPart> part = bdy->getPartAt(i);
+
+ if (!part->getHeader()->hasField(fields::CONTENT_TYPE)) {
+ continue;
+ }
+
+ const mediaType& type = *part->getHeader()->ContentType()->getValue <mediaType>();
+
+ // Extract from second part (message/disposition-notification)
+ if (type.getType() == vmime::mediaTypes::MESSAGE &&
+ type.getSubType() == vmime::mediaTypes::MESSAGE_DISPOSITION_NOTIFICATION) {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter vos(oss);
+
+ part->getBody()->getContents()->extract(vos);
+
+ // Body actually contains fields
+ header fields;
+ fields.parse(oss.str());
+
+ shared_ptr <messageId> omid =
+ fields.findFieldValue <messageId>(fields::ORIGINAL_MESSAGE_ID);
+
+ if (omid) {
+ m_omid = *omid;
+ }
+
+ shared_ptr <disposition> disp =
+ fields.findFieldValue <disposition>(fields::DISPOSITION);
+
+ if (disp) {
+ m_disp = *disp;
+ }
+
+ shared_ptr <text> contentMIC =
+ fields.findFieldValue <text>("Received-content-MIC");
+
+ if (contentMIC) {
+ m_contentMIC = contentMIC->generate();
+ }
+ }
+ }
+}
+
+
+} // mdn
+} // vmime
diff --git a/vmime-master/src/vmime/mdn/receivedMDNInfos.hpp b/vmime-master/src/vmime/mdn/receivedMDNInfos.hpp
new file mode 100644
index 0000000..7809acb
--- /dev/null
+++ b/vmime-master/src/vmime/mdn/receivedMDNInfos.hpp
@@ -0,0 +1,93 @@
+//
+// 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_MDN_RECEIVEDMDNINFOS_HPP_INCLUDED
+#define VMIME_MDN_RECEIVEDMDNINFOS_HPP_INCLUDED
+
+
+#include "vmime/mdn/MDNInfos.hpp"
+
+#include "vmime/disposition.hpp"
+#include "vmime/messageId.hpp"
+#include "vmime/mailbox.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+/** Holds information about a Message Disposition Notification (MDN)
+ * that has been received.
+ */
+class VMIME_EXPORT receivedMDNInfos : public MDNInfos {
+
+public:
+
+ receivedMDNInfos(const shared_ptr <const message>& msg);
+ receivedMDNInfos(const receivedMDNInfos& other);
+
+ receivedMDNInfos& operator=(const receivedMDNInfos& other);
+
+
+ const shared_ptr <const message> getMessage() const;
+
+ /** Return the identifier of the message for which this MDN
+ * has been generated.
+ *
+ * @return original message-id
+ */
+ const messageId getOriginalMessageId() const;
+
+ /** Return information about the disposition.
+ *
+ * @return disposition information
+ */
+ const disposition getDisposition() const;
+
+ /** Return the Message Integrity Check (MIC), that is the value
+ * of the "Received-content-MIC" field.
+ *
+ * @return MIC hash value, or an empty string if not specified
+ */
+ const string getContentMIC() const;
+
+private:
+
+ void copyFrom(const receivedMDNInfos& other);
+
+ void extract();
+
+
+ shared_ptr <const message> m_msg;
+
+ disposition m_disp;
+ messageId m_omid;
+ string m_contentMIC;
+};
+
+
+} // mdn
+} // vmime
+
+
+#endif // VMIME_MDN_RECEIVEDMDNINFOS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/mdn/sendableMDNInfos.cpp b/vmime-master/src/vmime/mdn/sendableMDNInfos.cpp
new file mode 100644
index 0000000..281655f
--- /dev/null
+++ b/vmime-master/src/vmime/mdn/sendableMDNInfos.cpp
@@ -0,0 +1,72 @@
+//
+// 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.
+//
+
+#include "vmime/mdn/sendableMDNInfos.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+sendableMDNInfos::sendableMDNInfos(const shared_ptr <const message>& msg, const mailbox& mbox)
+ : m_msg(msg),
+ m_mailbox(mbox) {
+
+}
+
+
+sendableMDNInfos::sendableMDNInfos(const sendableMDNInfos& other)
+ : MDNInfos() {
+
+ copyFrom(other);
+}
+
+
+sendableMDNInfos& sendableMDNInfos::operator=(const sendableMDNInfos& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+const shared_ptr <const message> sendableMDNInfos::getMessage() const {
+
+ return m_msg;
+}
+
+
+const mailbox& sendableMDNInfos::getRecipient() const {
+
+ return m_mailbox;
+}
+
+
+void sendableMDNInfos::copyFrom(const sendableMDNInfos& other) {
+
+ m_msg = other.m_msg;
+ m_mailbox = other.m_mailbox;
+}
+
+
+} // mdn
+} // vmime
diff --git a/vmime-master/src/vmime/mdn/sendableMDNInfos.hpp b/vmime-master/src/vmime/mdn/sendableMDNInfos.hpp
new file mode 100644
index 0000000..5b69b94
--- /dev/null
+++ b/vmime-master/src/vmime/mdn/sendableMDNInfos.hpp
@@ -0,0 +1,72 @@
+//
+// 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_MDN_SENDABLEMDNINFOS_HPP_INCLUDED
+#define VMIME_MDN_SENDABLEMDNINFOS_HPP_INCLUDED
+
+
+#include "vmime/mdn/MDNInfos.hpp"
+
+#include "vmime/mailbox.hpp"
+
+
+namespace vmime {
+namespace mdn {
+
+
+/** Holds information about a Message Disposition Notifications (MDN)
+ * that is to be sent.
+ */
+class VMIME_EXPORT sendableMDNInfos : public MDNInfos {
+
+public:
+
+ sendableMDNInfos(const shared_ptr <const message>& msg, const mailbox& mbox);
+ sendableMDNInfos(const sendableMDNInfos& other);
+
+ sendableMDNInfos& operator=(const sendableMDNInfos& other);
+
+ const shared_ptr <const message> getMessage() const;
+
+ /** Return the recipient of the MDN (the mailbox that will receive
+ * the notification message).
+ *
+ * @return recipient of the MDN
+ */
+ const mailbox& getRecipient() const;
+
+private:
+
+ void copyFrom(const sendableMDNInfos& other);
+
+
+ shared_ptr <const message> m_msg;
+ mailbox m_mailbox;
+};
+
+
+} // mdn
+} // vmime
+
+
+#endif // VMIME_MDN_SENDABLEMDNINFOS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/mediaType.cpp b/vmime-master/src/vmime/mediaType.cpp
new file mode 100644
index 0000000..9547593
--- /dev/null
+++ b/vmime-master/src/vmime/mediaType.cpp
@@ -0,0 +1,207 @@
+//
+// 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.
+//
+
+#include "vmime/mediaType.hpp"
+#include "vmime/parserHelpers.hpp"
+
+
+namespace vmime {
+
+
+mediaType::mediaType()
+ : m_type(mediaTypes::APPLICATION),
+ m_subType(mediaTypes::APPLICATION_OCTET_STREAM) {
+
+}
+
+
+mediaType::mediaType(const string& type) {
+
+ parse(type);
+}
+
+
+mediaType::mediaType(const string& type, const string& subType)
+ : m_type(utility::stringUtils::toLower(type)),
+ m_subType(utility::stringUtils::toLower(subType)) {
+
+}
+
+
+void mediaType::parseImpl(
+ const parsingContext& /* ctx */,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ const char* const pend = buffer.data() + end;
+ const char* const pstart = buffer.data() + position;
+ const char* p = pstart;
+
+ // Extract the type
+ const size_t typeStart = position;
+
+ while (p < pend && *p != '/') ++p;
+
+ m_type = utility::stringUtils::trim(
+ utility::stringUtils::toLower(
+ string(
+ buffer.begin() + typeStart,
+ buffer.begin() + position + (p - pstart)
+ )
+ )
+ );
+
+ if (p < pend) {
+
+ // Skip '/' character
+ ++p;
+
+ // Extract the sub-type
+ m_subType = utility::stringUtils::trim(
+ utility::stringUtils::toLower(
+ string(
+ buffer.begin() + position + (p - pstart),
+ buffer.begin() + end
+ )
+ )
+ );
+ }
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void mediaType::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ const string value = m_type + "/" + m_subType;
+
+ if (curLinePos + value.length() > ctx.getMaxLineLength()) {
+
+ os << NEW_LINE_SEQUENCE;
+ os << value;
+
+ if (newLinePos) {
+ *newLinePos = NEW_LINE_SEQUENCE_LENGTH + value.length();
+ }
+
+ } else {
+
+ os << value;
+
+ if (newLinePos) {
+ *newLinePos = curLinePos + value.length();
+ }
+ }
+}
+
+
+bool mediaType::operator==(const mediaType& type) const {
+
+ return m_type == type.m_type && m_subType == type.m_subType;
+}
+
+
+bool mediaType::operator!=(const mediaType& type) const {
+
+ return !(*this == type);
+}
+
+
+mediaType& mediaType::operator=(const string& type) {
+
+ parse(type);
+ return *this;
+}
+
+
+shared_ptr <component> mediaType::clone() const {
+
+ return make_shared <mediaType>(m_type, m_subType);
+}
+
+
+void mediaType::copyFrom(const component& other) {
+
+ const mediaType& mt = dynamic_cast <const mediaType&>(other);
+
+ m_type = mt.m_type;
+ m_subType = mt.m_subType;
+}
+
+
+mediaType& mediaType::operator=(const mediaType& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+const string& mediaType::getType() const {
+
+ return m_type;
+}
+
+
+void mediaType::setType(const string& type) {
+
+ m_type = utility::stringUtils::toLower(type);
+}
+
+
+const string& mediaType::getSubType() const {
+
+ return m_subType;
+}
+
+
+void mediaType::setSubType(const string& subType) {
+
+ m_subType = utility::stringUtils::toLower(subType);
+}
+
+
+void mediaType::setFromString(const string& type) {
+
+ parse(type);
+}
+
+
+const std::vector <shared_ptr <component> > mediaType::getChildComponents() {
+
+ return std::vector <shared_ptr <component> >();
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/mediaType.hpp b/vmime-master/src/vmime/mediaType.hpp
new file mode 100644
index 0000000..4026167
--- /dev/null
+++ b/vmime-master/src/vmime/mediaType.hpp
@@ -0,0 +1,119 @@
+//
+// 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_MEDIATYPE_HPP_INCLUDED
+#define VMIME_MEDIATYPE_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/headerFieldValue.hpp"
+
+
+namespace vmime {
+
+
+/** Content media type (basic type).
+ */
+class VMIME_EXPORT mediaType : public headerFieldValue {
+
+public:
+
+ mediaType();
+ mediaType(const string& type);
+ mediaType(const string& type, const string& subType);
+
+public:
+
+ bool operator==(const mediaType& type) const;
+ bool operator!=(const mediaType& type) const;
+
+ mediaType& operator=(const string& type);
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ mediaType& operator=(const mediaType& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+ /** Return the media type.
+ * See the constants in vmime::mediaTypes.
+ *
+ * @return media type
+ */
+ const string& getType() const;
+
+ /** Set the media type.
+ * See the constants in vmime::mediaTypes.
+ *
+ * @param type media type
+ */
+ void setType(const string& type);
+
+ /** Return the media subtype.
+ * See the constants in vmime::mediaTypes.
+ *
+ * @return media subtype
+ */
+ const string& getSubType() const;
+
+ /** Set the media subtype.
+ * See the constants in vmime::mediaTypes.
+ *
+ * @param subType media subtype
+ */
+ void setSubType(const string& subType);
+
+ /** Set the media type and subtype from a string
+ * in the form "type/subtype" (eg: "image/jpeg").
+ *
+ * @param type media type and subtype
+ */
+ void setFromString(const string& type);
+
+protected:
+
+ string m_type;
+ string m_subType;
+
+ // Component parsing & assembling
+ void parseImpl(
+ const 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;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_MEDIATYPE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/message.cpp b/vmime-master/src/vmime/message.cpp
new file mode 100644
index 0000000..f034cdb
--- /dev/null
+++ b/vmime-master/src/vmime/message.cpp
@@ -0,0 +1,49 @@
+//
+// 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.
+//
+
+#include "vmime/message.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+#include <sstream>
+
+
+namespace vmime {
+
+
+message::message() {
+
+}
+
+
+const string message::generate(
+ const size_t maxLineLength,
+ const size_t curLinePos
+) const {
+
+ return bodyPart::generate(maxLineLength, curLinePos);
+}
+
+
+} // vmime
+
diff --git a/vmime-master/src/vmime/message.hpp b/vmime-master/src/vmime/message.hpp
new file mode 100644
index 0000000..1b97a5d
--- /dev/null
+++ b/vmime-master/src/vmime/message.hpp
@@ -0,0 +1,60 @@
+//
+// 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_MESSAGE_HPP_INCLUDED
+#define VMIME_MESSAGE_HPP_INCLUDED
+
+
+#include "vmime/bodyPart.hpp"
+#include "vmime/generationContext.hpp"
+
+
+namespace vmime {
+
+
+/** A MIME message.
+ */
+class VMIME_EXPORT message : public bodyPart {
+
+public:
+
+ message();
+
+public:
+
+ using bodyPart::parse;
+ using bodyPart::generate;
+
+ // Override default generate() functions so that we can change
+ // the default 'maxLineLength' value
+ const string generate(
+ const size_t maxLineLength = generationContext::getDefaultContext().getMaxLineLength(),
+ const size_t curLinePos = 0
+ ) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_MESSAGE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/messageAttachment.hpp b/vmime-master/src/vmime/messageAttachment.hpp
new file mode 100644
index 0000000..2d95d20
--- /dev/null
+++ b/vmime-master/src/vmime/messageAttachment.hpp
@@ -0,0 +1,52 @@
+//
+// 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_MESSAGEATTACHMENT_HPP_INCLUDED
+#define VMIME_MESSAGEATTACHMENT_HPP_INCLUDED
+
+
+#include "vmime/attachment.hpp"
+#include "vmime/message.hpp"
+
+
+namespace vmime {
+
+
+/** Attachment of type message/rfc822.
+ */
+class VMIME_EXPORT messageAttachment : public attachment {
+
+public:
+
+ /** Return the message encapsulated in this attachment.
+ *
+ * @return encapsulated message
+ */
+ virtual shared_ptr <message> getMessage() const = 0;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_MESSAGEATTACHMENT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/messageBuilder.cpp b/vmime-master/src/vmime/messageBuilder.cpp
new file mode 100644
index 0000000..4de81bf
--- /dev/null
+++ b/vmime-master/src/vmime/messageBuilder.cpp
@@ -0,0 +1,333 @@
+//
+// 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.
+//
+
+#include "vmime/messageBuilder.hpp"
+
+#include "vmime/dateTime.hpp"
+#include "vmime/textPartFactory.hpp"
+
+
+namespace vmime {
+
+
+messageBuilder::messageBuilder() {
+
+ // By default there is one text part of type "text/plain"
+ constructTextPart(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN));
+}
+
+
+messageBuilder::~messageBuilder() {
+
+}
+
+
+shared_ptr <message> messageBuilder::construct() const {
+
+ // Create a new message
+ shared_ptr <message> msg = make_shared <message>();
+
+ // Generate the header fields
+ msg->getHeader()->Subject()->setValue(m_subject);
+
+ if (((m_to.isEmpty()) || (m_to.getAddressAt(0)->isEmpty() && !m_to.getAddressAt(0)->isGroup())) &&
+ (m_cc.isEmpty() || m_cc.getAddressAt(0)->isEmpty()) &&
+ (m_bcc.isEmpty() || m_bcc.getAddressAt(0)->isEmpty())) {
+
+ throw exceptions::no_recipient();
+ }
+
+ if (!m_from.isEmpty()) {
+ msg->getHeader()->From()->setValue(m_from);
+ }
+
+ if (!m_to.isEmpty()) {
+ msg->getHeader()->To()->setValue(m_to);
+ }
+
+ if (!m_cc.isEmpty()) {
+ msg->getHeader()->Cc()->setValue(m_cc);
+ }
+
+ if (!m_bcc.isEmpty()) {
+ msg->getHeader()->Bcc()->setValue(m_bcc);
+ }
+
+ // Add a "Date" field
+ msg->getHeader()->Date()->setValue(datetime::now());
+
+ // Add a "Mime-Version" header field
+ msg->getHeader()->MimeVersion()->setValue(string(SUPPORTED_MIME_VERSION));
+
+ // If there is one or more attachments (or other parts that are
+ // not "text/...") and if there is more than one parts for the
+ // text part, we generate these text parts into a sub-part:
+ //
+ // [message]
+ // |
+ // +-- multipart/mixed
+ // |
+ // +-- multipart/alternative
+ // | |
+ // | +-- text part #1 (eg. plain text "text/plain")
+ // | +-- text part #2 (eg. HTML "text/html")
+ // | +-- ...
+ // |
+ // +-- application/octet-stream (attachment #1)
+ // |
+ // +-- ... (other attachments/parts)
+ //
+ if (!m_attach.empty() && m_textPart->getPartCount() > 1) {
+
+ // Set parent part (message) to "multipart/mixed"
+ msg->getHeader()->ContentType()->setValue(
+ mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED)
+ );
+
+ // Create a sub-part "multipart/alternative" for text parts
+ shared_ptr <bodyPart> subPart = make_shared <bodyPart>();
+ msg->getBody()->appendPart(subPart);
+
+ subPart->getHeader()->ContentType()->setValue(
+ mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE)
+ );
+
+ // Generate the text parts into this sub-part (normally, this
+ // sub-part will have the "multipart/alternative" content-type...)
+ m_textPart->generateIn(msg, subPart);
+
+ } else {
+
+ // Generate the text part(s) directly into the message
+ m_textPart->generateIn(msg, msg);
+
+ // If any attachment, set message content-type to "multipart/mixed"
+ if (!m_attach.empty()) {
+
+ msg->getHeader()->ContentType()->setValue(
+ mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED)
+ );
+
+ // Else, set it to "multipart/alternative" if there are more than one text part.
+ } else if (m_textPart->getPartCount() > 1) {
+
+ msg->getHeader()->ContentType()->setValue(
+ mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_ALTERNATIVE)
+ );
+ }
+ }
+
+ // Generate the attachments
+ if (!m_attach.empty()) {
+
+ for (std::vector <shared_ptr <attachment> >::const_iterator a = m_attach.begin() ;
+ a != m_attach.end() ; ++a) {
+
+ (*a)->generateIn(msg);
+ }
+ }
+
+ // If there is only one part in the message, move it into the message
+ // (hence, the message will not be multipart...)
+ if (msg->getBody()->getPartCount() == 1) {
+
+ const bodyPart& part = *msg->getBody()->getPartAt(0);
+
+ // Make a full copy of the body, otherwise the copyFrom() will delete the body we're copying
+ shared_ptr <body> bodyCopy = vmime::clone(part.getBody());
+
+ // First, copy (and replace) the header fields
+ const std::vector <shared_ptr <const headerField> > fields = part.getHeader()->getFieldList();
+
+ for (std::vector <shared_ptr <const headerField> >::const_iterator it = fields.begin() ;
+ it != fields.end() ; ++it) {
+
+ *(msg->getHeader()->getField((*it)->getName())) = **it;
+ }
+
+ // Second, copy the body contents and sub-parts (this also remove
+ // the body part we are copying...)
+ msg->getBody()->copyFrom(*bodyCopy);
+ }
+
+ return msg;
+}
+
+
+void messageBuilder::attach(const shared_ptr <attachment>& attach) {
+
+ appendAttachment(attach);
+}
+
+
+void messageBuilder::appendAttachment(const shared_ptr <attachment>& attach) {
+
+ m_attach.push_back(attach);
+}
+
+
+void messageBuilder::constructTextPart(const mediaType& type) {
+
+ shared_ptr <textPart> part;
+
+ try {
+ part = textPartFactory::getInstance()->create(type);
+ } catch (exceptions::no_factory_available& e) {
+ throw;
+ }
+
+ m_textPart = part;
+}
+
+
+shared_ptr <textPart> messageBuilder::getTextPart() {
+
+ return m_textPart;
+}
+
+
+const mailbox& messageBuilder::getExpeditor() const {
+
+ return m_from;
+}
+
+
+void messageBuilder::setExpeditor(const mailbox& expeditor) {
+
+ m_from = expeditor;
+}
+
+
+const addressList& messageBuilder::getRecipients() const {
+
+ return m_to;
+}
+
+
+addressList& messageBuilder::getRecipients() {
+
+ return m_to;
+}
+
+
+void messageBuilder::setRecipients(const addressList& recipients) {
+
+ m_to = recipients;
+}
+
+
+const addressList& messageBuilder::getCopyRecipients() const {
+
+ return m_cc;
+}
+
+
+addressList& messageBuilder::getCopyRecipients() {
+
+ return m_cc;
+}
+
+
+void messageBuilder::setCopyRecipients(const addressList& cc) {
+
+ m_cc = cc;
+}
+
+
+const addressList& messageBuilder::getBlindCopyRecipients() const {
+
+ return m_bcc;
+}
+
+
+addressList& messageBuilder::getBlindCopyRecipients() {
+
+ return m_bcc;
+}
+
+
+void messageBuilder::setBlindCopyRecipients(const addressList& bcc) {
+
+ m_bcc = bcc;
+}
+
+
+const text& messageBuilder::getSubject() const {
+
+ return m_subject;
+}
+
+
+void messageBuilder::setSubject(const text& subject) {
+
+ m_subject = subject;
+}
+
+
+void messageBuilder::removeAttachment(const size_t pos) {
+
+ m_attach.erase(m_attach.begin() + pos);
+}
+
+
+const shared_ptr <const attachment> messageBuilder::getAttachmentAt(const size_t pos) const {
+
+ return m_attach[pos];
+}
+
+
+shared_ptr <attachment> messageBuilder::getAttachmentAt(const size_t pos) {
+
+ return m_attach[pos];
+}
+
+
+size_t messageBuilder::getAttachmentCount() const {
+
+ return m_attach.size();
+}
+
+
+const std::vector <shared_ptr <const attachment> > messageBuilder::getAttachmentList() const {
+
+ std::vector <shared_ptr <const attachment> > res;
+
+ res.reserve(m_attach.size());
+
+ for (std::vector <shared_ptr <attachment> >::const_iterator it = m_attach.begin() ;
+ it != m_attach.end() ; ++it) {
+
+ res.push_back(*it);
+ }
+
+ return res;
+}
+
+
+const std::vector <shared_ptr <attachment> > messageBuilder::getAttachmentList() {
+
+ return m_attach;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/messageBuilder.hpp b/vmime-master/src/vmime/messageBuilder.hpp
new file mode 100644
index 0000000..bfe5ed9
--- /dev/null
+++ b/vmime-master/src/vmime/messageBuilder.hpp
@@ -0,0 +1,221 @@
+//
+// 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_MESSAGEBUILDER_HPP_INCLUDED
+#define VMIME_MESSAGEBUILDER_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+
+#include "vmime/mailbox.hpp"
+#include "vmime/addressList.hpp"
+#include "vmime/text.hpp"
+#include "vmime/message.hpp"
+#include "vmime/mediaType.hpp"
+#include "vmime/attachment.hpp"
+#include "vmime/textPart.hpp"
+#include "vmime/bodyPart.hpp"
+
+
+namespace vmime {
+
+
+/** A helper for building MIME messages.
+ */
+class VMIME_EXPORT messageBuilder {
+
+public:
+
+ messageBuilder();
+ ~messageBuilder();
+
+public:
+
+ /** Return the expeditor of the message (From:).
+ *
+ * @return expeditor of the message
+ */
+ const mailbox& getExpeditor() const;
+
+ /** Set the expeditor of the message (From:).
+ *
+ * @param expeditor expeditor of the message
+ */
+ void setExpeditor(const mailbox& expeditor);
+
+ /** Return the recipients of the message (To:).
+ *
+ * return recipients of the message
+ */
+ const addressList& getRecipients() const;
+
+ /** Return the recipients of the message (To:).
+ *
+ * return recipients of the message
+ */
+ addressList& getRecipients();
+
+ /** Set the recipients of the message (To:).
+ *
+ * @param recipients list of recipients
+ */
+ void setRecipients(const addressList& recipients);
+
+ /** Return the copy recipients of the message (Cc:).
+ *
+ * @return copy recipients of the message
+ */
+ const addressList& getCopyRecipients() const;
+
+ /** Return the copy recipients of the message (Cc:).
+ *
+ * @return copy recipients of the message
+ */
+ addressList& getCopyRecipients();
+
+ /** Set the copy recipients of the message (Cc:).
+ *
+ * @param cc list of copy recipients
+ */
+ void setCopyRecipients(const addressList& cc);
+
+ /** Return the blind-copy recipients of the message (Bcc:).
+ *
+ * @return blind-copy recipients of the message
+ */
+ const addressList& getBlindCopyRecipients() const;
+
+ /** Return the blind-copy recipients of the message (Bcc:).
+ *
+ * @return blind-copy recipients of the message
+ */
+ addressList& getBlindCopyRecipients();
+
+ /** Set the blind-copy recipients of the message (Bcc:).
+ *
+ * @param bcc list of blind-copy recipients
+ */
+ void setBlindCopyRecipients(const addressList& bcc);
+
+ /** Return the subject of the message.
+ *
+ * @return subject of the message
+ */
+ const text& getSubject() const;
+
+ /** Set the subject of the message.
+ *
+ * @param subject message subject
+ */
+ void setSubject(const text& subject);
+
+ /** Attach a new object to the message.
+ * \deprecated Use messageBuilder::appendAttachment() instead.
+ *
+ * @param attach new attachment
+ */
+ void attach(const shared_ptr <attachment>& attach);
+
+ /** Attach a new object to the message.
+ *
+ * @param attach new attachment
+ */
+ void appendAttachment(const shared_ptr <attachment>& attach);
+
+ /** Remove the attachment at the specified position.
+ *
+ * @param pos position of the attachment to remove
+ */
+ void removeAttachment(const size_t pos);
+
+ /** Return the attachment at the specified position.
+ *
+ * @param pos position of the attachment
+ * @return attachment at the specified position
+ */
+ const shared_ptr <const attachment> getAttachmentAt(const size_t pos) const;
+
+ /** Return the attachment at the specified position.
+ *
+ * @param pos position of the attachment
+ * @return attachment at the specified position
+ */
+ shared_ptr <attachment> getAttachmentAt(const size_t pos);
+
+ /** Return the number of attachments in the message.
+ *
+ * @return number of attachments
+ */
+ size_t getAttachmentCount() const;
+
+ /** Return the list of attachments.
+ *
+ * @return list of attachments
+ */
+ const std::vector <shared_ptr <const attachment> > getAttachmentList() const;
+
+ /** Return the list of attachments.
+ *
+ * @return list of attachments
+ */
+ const std::vector <shared_ptr <attachment> > getAttachmentList();
+
+ /** Change the type of the text part and construct a new part.
+ *
+ * @param type media type of the text part
+ */
+ void constructTextPart(const mediaType& type);
+
+ /** Return the text part of the message.
+ *
+ * @return text part of the message
+ */
+ shared_ptr <textPart> getTextPart();
+
+ /** Construct a new message based on the information specified
+ * in this object.
+ *
+ * @return a new message
+ */
+ shared_ptr <message> construct() const;
+
+private:
+
+ mailbox m_from;
+
+ addressList m_to;
+ addressList m_cc;
+ addressList m_bcc;
+
+ text m_subject;
+
+ shared_ptr <textPart> m_textPart;
+
+ std::vector <shared_ptr <attachment> > m_attach;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_MESSAGEBUILDER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/messageId.cpp b/vmime-master/src/vmime/messageId.cpp
new file mode 100644
index 0000000..c8ea642
--- /dev/null
+++ b/vmime-master/src/vmime/messageId.cpp
@@ -0,0 +1,329 @@
+//
+// 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.
+//
+
+#include "vmime/messageId.hpp"
+#include "vmime/utility/random.hpp"
+#include "vmime/platform.hpp"
+#include "vmime/parserHelpers.hpp"
+
+
+namespace vmime {
+
+
+messageId::messageId() {
+
+}
+
+
+messageId::messageId(const string& id) {
+
+ parse(id);
+}
+
+
+messageId::messageId(const messageId& mid)
+ : headerFieldValue(),
+ m_left(mid.m_left),
+ m_right(mid.m_right) {
+
+}
+
+
+messageId::messageId(const string& left, const string& right)
+ : m_left(left),
+ m_right(right) {
+
+}
+
+
+/*
+ RFC-2822:
+ 3.6.4. Identification fields
+
+ msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
+*/
+
+void messageId::parseImpl(
+ const parsingContext& /* ctx */,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ const char* const pend = buffer.data() + end;
+ const char* const pstart = buffer.data() + position;
+ const char* p = pstart;
+
+ m_left.clear();
+ m_right.clear();
+
+ unsigned int commentLevel = 0;
+ bool escape = false;
+ bool stop = false;
+
+ for ( ; !stop && p < pend ; ++p) {
+
+ if (escape) {
+
+ // Ignore this character
+
+ } else {
+
+ switch (*p) {
+
+ case '(': ++commentLevel; break;
+ case ')': --commentLevel; break;
+ case '\\': escape = true; break;
+ case '<': {
+
+ if (commentLevel == 0) {
+ stop = true;
+ break;
+ }
+ }
+
+ }
+ }
+ }
+
+ // Fix for message ids without angle brackets (invalid)
+ bool hasBrackets = true;
+
+ if (p == pend) { // no opening angle bracket found
+
+ hasBrackets = false;
+ p = pstart;
+
+ while (p < pend && parserHelpers::isSpace(*p)) {
+ ++p;
+ }
+ }
+
+ if (p < pend) {
+
+ // Extract left part
+ const size_t leftStart = position + (p - pstart);
+
+ while (p < pend && *p != '@' && *p != '>') ++p;
+
+ m_left = string(
+ buffer.begin() + leftStart,
+ buffer.begin() + position + (p - pstart)
+ );
+
+ if (p < pend) {
+
+ // Skip '@'
+ ++p;
+
+ // Extract right part
+ const size_t rightStart = position + (p - pstart);
+
+ while (p < pend && *p != '>' && (hasBrackets || !parserHelpers::isSpace(*p))) ++p;
+
+ m_right = string(
+ buffer.begin() + rightStart,
+ buffer.begin() + position + (p - pstart)
+ );
+ }
+ }
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+shared_ptr <messageId> messageId::parseNext(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ size_t pos = position;
+
+ while (pos < end && parserHelpers::isSpace(buffer[pos])) {
+ ++pos;
+ }
+
+ if (pos != end) {
+
+ const size_t begin = pos;
+
+ while (pos < end && !parserHelpers::isSpace(buffer[pos])) {
+ ++pos;
+ }
+
+ shared_ptr <messageId> mid = make_shared <messageId>();
+ mid->parse(ctx, buffer, begin, pos, NULL);
+
+ if (newPosition) {
+ *newPosition = pos;
+ }
+
+ return mid;
+ }
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+
+ return null;
+}
+
+
+const string messageId::getId() const {
+
+ if (m_right.empty()) {
+ return m_left;
+ }
+
+ return m_left + '@' + m_right;
+}
+
+
+void messageId::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ size_t pos = curLinePos;
+
+ if (ctx.getWrapMessageId() &&
+ (curLinePos + m_left.length() + m_right.length() + 3 > ctx.getMaxLineLength())) {
+
+ os << NEW_LINE_SEQUENCE;
+ pos = NEW_LINE_SEQUENCE_LENGTH;
+ }
+
+ os << '<' << m_left;
+
+ if (m_right != "") {
+ os << '@' << m_right;
+ }
+
+ os << '>';
+
+ if (newLinePos) {
+ *newLinePos = pos + m_left.length() + m_right.length() + 3;
+ }
+}
+
+
+messageId& messageId::operator=(const string& id) {
+
+ parse(id);
+ return *this;
+}
+
+
+messageId messageId::generateId() {
+
+ std::ostringstream left;
+ left.imbue(std::locale::classic());
+
+ left << "vmime";
+ left << '.';
+ left << std::hex << utility::random::getTime();
+ left << '.';
+ left << std::hex << utility::random::getProcess();
+ left << '.';
+ left << std::hex << utility::random::getNext();
+ left << std::hex << utility::random::getNext();
+
+ return messageId(left.str(), platform::getHandler()->getHostName());
+}
+
+
+bool messageId::operator==(const messageId& mid) const {
+
+ return m_left == mid.m_left && m_right == mid.m_right;
+}
+
+
+bool messageId::operator!=(const messageId& mid) const {
+
+ return !(*this == mid);
+}
+
+
+shared_ptr <component> messageId::clone() const {
+
+ return make_shared <messageId>(*this);
+}
+
+
+void messageId::copyFrom(const component& other) {
+
+ const messageId& mid = dynamic_cast <const messageId&>(other);
+
+ m_left = mid.m_left;
+ m_right = mid.m_right;
+}
+
+
+messageId& messageId::operator=(const messageId& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+const string& messageId::getLeft() const {
+
+ return m_left;
+}
+
+
+void messageId::setLeft(const string& left) {
+
+ m_left = left;
+}
+
+
+const string& messageId::getRight() const {
+
+ return m_right;
+}
+
+
+void messageId::setRight(const string& right) {
+
+ m_right = right;
+}
+
+
+const std::vector <shared_ptr <component> > messageId::getChildComponents() {
+
+ return std::vector <shared_ptr <component> >();
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/messageId.hpp b/vmime-master/src/vmime/messageId.hpp
new file mode 100644
index 0000000..8edbe3e
--- /dev/null
+++ b/vmime-master/src/vmime/messageId.hpp
@@ -0,0 +1,144 @@
+//
+// 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_MESSAGEID_HPP_INCLUDED
+#define VMIME_MESSAGEID_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/headerFieldValue.hpp"
+
+
+namespace vmime {
+
+
+/** Message identifier (basic type).
+ */
+class VMIME_EXPORT messageId : public headerFieldValue {
+
+ friend class messageIdSequence;
+
+public:
+
+ messageId();
+ messageId(const string& id);
+ messageId(const messageId& mid);
+ messageId(const string& left, const string& right);
+
+public:
+
+ /** Return the left part of the message identifier.
+ *
+ * @return left part of message identifier
+ */
+ const string& getLeft() const;
+
+ /** Set the left part of the message identifier.
+ *
+ * @param left left part of message identifier
+ */
+ void setLeft(const string& left);
+
+ /** Return the right part of the message identifier.
+ *
+ * @return right part of message identifier
+ */
+ const string& getRight() const;
+
+ /** Set the right part of the message identifier.
+ *
+ * @param right right part of message identifier
+ */
+ void setRight(const string& right);
+
+
+ messageId& operator=(const string& id);
+
+ bool operator==(const messageId& mid) const;
+ bool operator!=(const messageId& mid) const;
+
+ /** Generate a random message identifier.
+ *
+ * @return randomly created message identifier
+ */
+ static messageId generateId();
+
+ /** Return the message identifier constructed by using
+ * the right part and the left part, separated by
+ * a '@' character.
+ *
+ * @return full message identifier
+ */
+ const string getId() const;
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ messageId& operator=(const messageId& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+private:
+
+ string m_left;
+ string m_right;
+
+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 generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const;
+
+ /** Parse a message-id from an input buffer.
+ *
+ * @param buffer input buffer
+ * @param position position in the input buffer
+ * @param end end position in the input buffer
+ * @param newPosition will receive the new position in the input buffer
+ * @return a new message-id object, or null if no more message-id can be parsed from the input buffer
+ */
+ static shared_ptr <messageId> parseNext(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+ );
+};
+
+
+} // vmime
+
+
+#endif // VMIME_MESSAGEID_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/messageIdSequence.cpp b/vmime-master/src/vmime/messageIdSequence.cpp
new file mode 100644
index 0000000..2b68bcc
--- /dev/null
+++ b/vmime-master/src/vmime/messageIdSequence.cpp
@@ -0,0 +1,277 @@
+//
+// 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.
+//
+
+#include "vmime/messageIdSequence.hpp"
+#include "vmime/exception.hpp"
+
+#include <algorithm>
+
+
+namespace vmime {
+
+
+messageIdSequence::messageIdSequence() {
+
+}
+
+
+messageIdSequence::~messageIdSequence() {
+
+ removeAllMessageIds();
+}
+
+
+messageIdSequence::messageIdSequence(const messageIdSequence& midSeq)
+ : headerFieldValue() {
+
+ copyFrom(midSeq);
+}
+
+
+shared_ptr <component> messageIdSequence::clone() const {
+
+ return make_shared <messageIdSequence>(*this);
+}
+
+
+void messageIdSequence::copyFrom(const component& other) {
+
+ const messageIdSequence& midSeq = dynamic_cast <const messageIdSequence&>(other);
+
+ removeAllMessageIds();
+
+ for (unsigned int i = 0 ; i < midSeq.m_list.size() ; ++i) {
+ m_list.push_back(vmime::clone(midSeq.m_list[i]));
+ }
+}
+
+
+messageIdSequence& messageIdSequence::operator=(const messageIdSequence& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+const std::vector <shared_ptr <component> > messageIdSequence::getChildComponents() {
+
+ std::vector <shared_ptr <component> > res;
+
+ copy_vector(m_list, res);
+
+ return res;
+}
+
+
+void messageIdSequence::parseImpl(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ removeAllMessageIds();
+
+ size_t pos = position;
+
+ while (pos < end) {
+
+ shared_ptr <messageId> parsedMid = messageId::parseNext(ctx, buffer, pos, end, &pos);
+
+ if (parsedMid) {
+ m_list.push_back(parsedMid);
+ }
+ }
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void messageIdSequence::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ size_t pos = curLinePos;
+
+ if (!m_list.empty()) {
+
+ generationContext tmpCtx(ctx);
+ tmpCtx.setMaxLineLength(ctx.getMaxLineLength() - 2);
+
+ for (std::vector <shared_ptr <messageId> >::const_iterator it = m_list.begin() ; ; ) {
+
+ (*it)->generate(ctx, os, pos, &pos);
+
+ if (++it == m_list.end()) {
+ break;
+ }
+
+ os << " ";
+ pos++;
+ }
+ }
+
+ if (newLinePos) {
+ *newLinePos = pos;
+ }
+}
+
+
+void messageIdSequence::appendMessageId(const shared_ptr <messageId>& mid) {
+
+ m_list.push_back(mid);
+}
+
+
+void messageIdSequence::insertMessageIdBefore(
+ const shared_ptr <messageId>& beforeMid,
+ const shared_ptr <messageId>& mid
+) {
+
+ const std::vector <shared_ptr <messageId> >::iterator it =
+ std::find(m_list.begin(), m_list.end(), beforeMid);
+
+ if (it == m_list.end()) {
+ throw exceptions::no_such_message_id();
+ }
+
+ m_list.insert(it, mid);
+}
+
+
+void messageIdSequence::insertMessageIdBefore(
+ const size_t pos,
+ const shared_ptr <messageId>& mid
+) {
+
+ m_list.insert(m_list.begin() + pos, mid);
+}
+
+
+void messageIdSequence::insertMessageIdAfter(
+ const shared_ptr <messageId>& afterMid,
+ const shared_ptr <messageId>& mid
+) {
+
+ const std::vector <shared_ptr <messageId> >::iterator it =
+ std::find(m_list.begin(), m_list.end(), afterMid);
+
+ if (it == m_list.end()) {
+ throw exceptions::no_such_message_id();
+ }
+
+ m_list.insert(it + 1, mid);
+}
+
+
+void messageIdSequence::insertMessageIdAfter(
+ const size_t pos,
+ const shared_ptr <messageId>& mid
+) {
+
+ m_list.insert(m_list.begin() + pos + 1, mid);
+}
+
+
+void messageIdSequence::removeMessageId(const shared_ptr <messageId>& mid)
+{
+ const std::vector <shared_ptr <messageId> >::iterator it =
+ std::find(m_list.begin(), m_list.end(), mid);
+
+ if (it == m_list.end()) {
+ throw exceptions::no_such_message_id();
+ }
+
+ m_list.erase(it);
+}
+
+
+void messageIdSequence::removeMessageId(const size_t pos) {
+
+ const std::vector <shared_ptr <messageId> >::iterator it = m_list.begin() + pos;
+
+ m_list.erase(it);
+}
+
+
+void messageIdSequence::removeAllMessageIds() {
+
+ m_list.clear();
+}
+
+
+size_t messageIdSequence::getMessageIdCount() const {
+
+ return m_list.size();
+}
+
+
+bool messageIdSequence::isEmpty() const {
+
+ return m_list.empty();
+}
+
+
+const shared_ptr <messageId> messageIdSequence::getMessageIdAt(const size_t pos) {
+
+ return m_list[pos];
+}
+
+
+const shared_ptr <const messageId> messageIdSequence::getMessageIdAt(const size_t pos) const {
+
+ return m_list[pos];
+}
+
+
+const std::vector <shared_ptr <const messageId> > messageIdSequence::getMessageIdList() const {
+
+ std::vector <shared_ptr <const messageId> > list;
+
+ list.reserve(m_list.size());
+
+ for (std::vector <shared_ptr <messageId> >::const_iterator it = m_list.begin() ;
+ it != m_list.end() ; ++it) {
+
+ list.push_back(*it);
+ }
+
+ return list;
+}
+
+
+const std::vector <shared_ptr <messageId> > messageIdSequence::getMessageIdList() {
+
+ return m_list;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/messageIdSequence.hpp b/vmime-master/src/vmime/messageIdSequence.hpp
new file mode 100644
index 0000000..e5d0eb6
--- /dev/null
+++ b/vmime-master/src/vmime/messageIdSequence.hpp
@@ -0,0 +1,175 @@
+//
+// 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_MESSAGEIDSEQUENCE_HPP_INCLUDED
+#define VMIME_MESSAGEIDSEQUENCE_HPP_INCLUDED
+
+
+#include "vmime/messageId.hpp"
+
+
+namespace vmime {
+
+
+/** A list of message identifiers (basic type).
+ */
+class VMIME_EXPORT messageIdSequence : public headerFieldValue {
+
+public:
+
+ messageIdSequence();
+ messageIdSequence(const messageIdSequence& midSeq);
+
+ ~messageIdSequence();
+
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ messageIdSequence& operator=(const messageIdSequence& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+
+ /** Add a message-id at the end of the list.
+ *
+ * @param mid message-id to append
+ */
+ void appendMessageId(const shared_ptr <messageId>& mid);
+
+ /** Insert a new message-id before the specified message-id.
+ *
+ * @param beforeMid message-id before which the new message-id will be inserted
+ * @param mid message-id to insert
+ * @throw exceptions::no_such_messageid if the message-id is not in the list
+ */
+ void insertMessageIdBefore(const shared_ptr <messageId>& beforeMid, const shared_ptr <messageId>& mid);
+
+ /** Insert a new message-id before the specified position.
+ *
+ * @param pos position at which to insert the new message-id (0 to insert at
+ * the beginning of the list)
+ * @param mid message-id to insert
+ */
+ void insertMessageIdBefore(const size_t pos, const shared_ptr <messageId>& mid);
+
+ /** Insert a new message-id after the specified message-id.
+ *
+ * @param afterMid message-id after which the new message-id will be inserted
+ * @param mid message-id to insert
+ * @throw exceptions::no_such_message_id if the message-id is not in the list
+ */
+ void insertMessageIdAfter(
+ const shared_ptr <messageId>& afterMid,
+ const shared_ptr <messageId>& mid
+ );
+
+ /** Insert a new message-id after the specified position.
+ *
+ * @param pos position of the message-id before the new message-id
+ * @param mid message-id to insert
+ */
+ void insertMessageIdAfter(const size_t pos, const shared_ptr <messageId>& mid);
+
+ /** Remove the specified message-id from the list.
+ *
+ * @param mid message-id to remove
+ * @throw exceptions::no_such_message_id if the message-id is not in the list
+ */
+ void removeMessageId(const shared_ptr <messageId>& mid);
+
+ /** Remove the message-id at the specified position.
+ *
+ * @param pos position of the message-id to remove
+ */
+ void removeMessageId(const size_t pos);
+
+ /** Remove all message-ids from the list.
+ */
+ void removeAllMessageIds();
+
+ /** Return the number of message-ides in the list.
+ *
+ * @return number of message-ides
+ */
+ size_t getMessageIdCount() const;
+
+ /** Tests whether the list of message-ides is empty.
+ *
+ * @return true if there is no message-id, false otherwise
+ */
+ bool isEmpty() const;
+
+ /** Return the message-id at the specified position.
+ *
+ * @param pos position
+ * @return message-id at position 'pos'
+ */
+ const shared_ptr <messageId> getMessageIdAt(const size_t pos);
+
+ /** Return the message-id at the specified position.
+ *
+ * @param pos position
+ * @return message-id at position 'pos'
+ */
+ const shared_ptr <const messageId> getMessageIdAt(const size_t pos) const;
+
+ /** Return the message-id list.
+ *
+ * @return list of message-ids
+ */
+ const std::vector <shared_ptr <const messageId> > getMessageIdList() const;
+
+ /** Return the message-id list.
+ *
+ * @return list of message-ids
+ */
+ const std::vector <shared_ptr <messageId> > getMessageIdList();
+
+private:
+
+ std::vector <shared_ptr <messageId> > m_list;
+
+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 generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos = 0,
+ size_t* newLinePos = NULL
+ ) const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_MESSAGEIDSEQUENCE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/messageParser.cpp b/vmime-master/src/vmime/messageParser.cpp
new file mode 100644
index 0000000..21ac09b
--- /dev/null
+++ b/vmime-master/src/vmime/messageParser.cpp
@@ -0,0 +1,328 @@
+//
+// 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.
+//
+
+#include "vmime/messageParser.hpp"
+
+#include "vmime/attachmentHelper.hpp"
+
+#include "vmime/defaultAttachment.hpp"
+#include "vmime/textPartFactory.hpp"
+
+#include "vmime/relay.hpp"
+#include "vmime/contentTypeField.hpp"
+#include "vmime/contentDispositionField.hpp"
+
+
+namespace vmime {
+
+
+messageParser::messageParser(const string& buffer) {
+
+ shared_ptr <message> msg = make_shared <message>();
+ msg->parse(buffer);
+
+ parse(msg);
+}
+
+
+messageParser::messageParser(const shared_ptr <const message>& msg) {
+
+ parse(msg);
+}
+
+
+messageParser::~messageParser() {
+
+}
+
+
+void messageParser::parse(const shared_ptr <const message>& msg) {
+
+ // Header fields (if field is present, copy its value, else do nothing)
+#ifndef VMIME_BUILDING_DOC
+
+#define TRY_FIELD(var, type, name) { \
+ shared_ptr <type> fldValue = msg->getHeader()->findFieldValue <type>(name); \
+ if (fldValue) { \
+ var = *fldValue; \
+ } \
+ }
+
+ TRY_FIELD(m_from, mailbox, fields::FROM);
+
+ TRY_FIELD(m_to, addressList, fields::TO);
+ TRY_FIELD(m_cc, addressList, fields::CC);
+ TRY_FIELD(m_bcc, addressList, fields::BCC);
+
+ TRY_FIELD(m_subject, text, fields::SUBJECT);
+
+#undef TRY_FIELD
+
+#endif // VMIME_BUILDING_DOC
+
+ // Date
+ shared_ptr <const headerField> recv = msg->getHeader()->findField(fields::RECEIVED);
+
+ if (recv) {
+
+ m_date = recv->getValue <relay>()->getDate();
+
+ } else {
+
+ shared_ptr <const headerField> date = msg->getHeader()->findField(fields::DATE);
+
+ if (date) {
+ m_date = *date->getValue <datetime>();
+ } else {
+ m_date = datetime::now();
+ }
+ }
+
+ // Attachments
+ findAttachments(msg);
+
+ // Text parts
+ findTextParts(msg, msg);
+}
+
+
+void messageParser::findAttachments(const shared_ptr <const message>& msg) {
+
+ m_attach = attachmentHelper::findAttachmentsInMessage(msg);
+}
+
+
+void messageParser::findTextParts(
+ const shared_ptr <const bodyPart>& msg,
+ const shared_ptr <const bodyPart>& part
+) {
+
+ // Handle the case in which the message is not multipart: if the body part is
+ // "text/*", take this part.
+ if (part->getBody()->getPartCount() == 0) {
+
+ mediaType type(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN);
+ bool accept = false;
+
+ shared_ptr <const contentTypeField> ctf =
+ msg->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
+
+ if (ctf) {
+
+ const mediaType ctfType = *ctf->getValue <mediaType>();
+
+ if (ctfType.getType() == mediaTypes::TEXT) {
+
+ type = ctfType;
+ accept = true;
+ }
+
+ } else {
+
+ // No "Content-type" field: assume "text/plain".
+ accept = true;
+ }
+
+ if (accept) {
+
+ shared_ptr <textPart> txtPart = textPartFactory::getInstance()->create(type);
+ txtPart->parse(msg, msg, msg);
+
+ m_textParts.push_back(txtPart);
+ }
+
+ // Multipart message
+ } else {
+
+ findSubTextParts(msg, part);
+ }
+}
+
+
+bool messageParser::findSubTextParts(
+ const shared_ptr <const bodyPart>& msg,
+ const shared_ptr <const bodyPart>& part
+) {
+
+ // In general, all the text parts are contained in parallel in the same
+ // parent part (or message).
+ // So, wherever the text parts are, all we have to do is to find the first
+ // MIME part which is a text part.
+
+ std::vector <shared_ptr <const bodyPart> > textParts;
+
+ for (size_t i = 0 ; i < part->getBody()->getPartCount() ; ++i) {
+
+ const shared_ptr <const bodyPart> p = part->getBody()->getPartAt(i);
+
+ shared_ptr <const contentTypeField> ctf =
+ p->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
+
+ if (ctf) {
+
+ const mediaType type = *ctf->getValue <mediaType>();
+ contentDisposition disp; // default should be inline
+
+ if (type.getType() == mediaTypes::TEXT) {
+
+ shared_ptr <const contentDispositionField> cdf = p->getHeader()->
+ findField <contentDispositionField>(fields::CONTENT_DISPOSITION);
+
+ if (cdf) {
+
+ disp = *cdf->getValue <contentDisposition>();
+
+ } else {
+
+ // No "Content-Disposition" field, assume default
+ }
+
+ if (disp.getName() == contentDispositionTypes::INLINE) {
+ textParts.push_back(p);
+ }
+ }
+
+ } else {
+
+ // No "Content-type" field.
+ }
+ }
+
+ if (textParts.size()) {
+
+ // Okay. So we have found at least one text part
+ for (std::vector <shared_ptr <const bodyPart> >::const_iterator p = textParts.begin() ;
+ p != textParts.end() ; ++p) {
+
+ const contentTypeField& ctf =
+ *(*p)->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
+
+ const mediaType type = *ctf.getValue <mediaType>();
+
+ try {
+
+ shared_ptr <textPart> txtPart = textPartFactory::getInstance()->create(type);
+ txtPart->parse(msg, part, *p);
+
+ m_textParts.push_back(txtPart);
+
+ } catch (exceptions::no_factory_available& e) {
+
+ // Content-type not recognized.
+ }
+ }
+ }
+
+ bool found = false;
+
+ for (size_t i = 0 ; !found && (i < part->getBody()->getPartCount()) ; ++i) {
+ found = findSubTextParts(msg, part->getBody()->getPartAt(i));
+ }
+
+ return found;
+}
+
+
+const mailbox& messageParser::getExpeditor() const {
+
+ return m_from;
+}
+
+
+const addressList& messageParser::getRecipients() const {
+
+ return m_to;
+}
+
+
+const addressList& messageParser::getCopyRecipients() const {
+
+ return m_cc;
+}
+
+
+const addressList& messageParser::getBlindCopyRecipients() const {
+
+ return m_bcc;
+}
+
+
+const text& messageParser::getSubject() const {
+
+ return m_subject;
+}
+
+
+const datetime& messageParser::getDate() const {
+
+ return m_date;
+}
+
+
+const std::vector <shared_ptr <const attachment> > messageParser::getAttachmentList() const {
+
+ return m_attach;
+}
+
+
+size_t messageParser::getAttachmentCount() const {
+
+ return m_attach.size();
+}
+
+
+const shared_ptr <const attachment> messageParser::getAttachmentAt(const size_t pos) const {
+
+ return m_attach[pos];
+}
+
+
+const std::vector <shared_ptr <const textPart> > messageParser::getTextPartList() const {
+
+ std::vector <shared_ptr <const textPart> > res;
+
+ res.reserve(m_textParts.size());
+
+ for (std::vector <shared_ptr <textPart> >::const_iterator it = m_textParts.begin() ;
+ it != m_textParts.end() ; ++it) {
+
+ res.push_back(*it);
+ }
+
+ return res;
+}
+
+
+size_t messageParser::getTextPartCount() const {
+
+ return m_textParts.size();
+}
+
+
+const shared_ptr <const textPart> messageParser::getTextPartAt(const size_t pos) const {
+
+ return m_textParts[pos];
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/messageParser.hpp b/vmime-master/src/vmime/messageParser.hpp
new file mode 100644
index 0000000..8019ef3
--- /dev/null
+++ b/vmime-master/src/vmime/messageParser.hpp
@@ -0,0 +1,164 @@
+//
+// 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_MESSAGEPARSER_HPP_INCLUDED
+#define VMIME_MESSAGEPARSER_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+
+#include "vmime/message.hpp"
+#include "vmime/attachment.hpp"
+
+#include "vmime/mailbox.hpp"
+#include "vmime/addressList.hpp"
+#include "vmime/dateTime.hpp"
+
+#include "vmime/textPart.hpp"
+
+
+namespace vmime {
+
+
+/** A helper for parsing MIME messages.
+ */
+class VMIME_EXPORT messageParser {
+
+public:
+
+ messageParser(const string& buffer);
+ messageParser(const shared_ptr <const message>& msg);
+ ~messageParser();
+
+public:
+
+ /** Return the expeditor of the message (From:).
+ *
+ * @return expeditor of the message
+ */
+ const mailbox& getExpeditor() const;
+
+ /** Return the recipients of the message (To:).
+ *
+ * return recipients of the message
+ */
+ const addressList& getRecipients() const;
+
+ /** Return the copy recipients of the message (Cc:).
+ *
+ * @return copy recipients of the message
+ */
+ const addressList& getCopyRecipients() const;
+
+ /** Return the blind-copy recipients of the message (Bcc:).
+ *
+ * @return blind-copy recipients of the message
+ */
+ const addressList& getBlindCopyRecipients() const;
+
+ /** Return the subject of the message.
+ *
+ * @return subject of the message
+ */
+ const text& getSubject() const;
+
+ /** Return the date of the message.
+ *
+ * @return date of the message
+ */
+ const datetime& getDate() const;
+
+ /** Return the number of attachments in the message.
+ *
+ * @return number of attachments
+ */
+ size_t getAttachmentCount() const;
+
+ /** Return the attachment at the specified position.
+ *
+ * @param pos position of the attachment
+ * @return attachment at position 'pos'
+ */
+ const shared_ptr <const attachment> getAttachmentAt(const size_t pos) const;
+
+ /** Return the attachments of the message.
+ *
+ * @return list of attachments in the message
+ */
+ const std::vector <shared_ptr <const attachment> > getAttachmentList() const;
+
+ /** Return the text parts of the message.
+ *
+ * @return list of text parts in the message
+ */
+ const std::vector <shared_ptr <const textPart> > getTextPartList() const;
+
+ /** Return the number of text parts in the message.
+ *
+ * @return number of text parts
+ */
+ size_t getTextPartCount() const;
+
+ /** Return the text part at the specified position.
+ *
+ * @param pos position of the text part
+ * @return text part at position 'pos'
+ */
+ const shared_ptr <const textPart> getTextPartAt(const size_t pos) const;
+
+private:
+
+ mailbox m_from;
+
+ addressList m_to;
+ addressList m_cc;
+ addressList m_bcc;
+
+ text m_subject;
+
+ datetime m_date;
+
+ std::vector <shared_ptr <const attachment> > m_attach;
+
+ std::vector <shared_ptr <textPart> > m_textParts;
+
+ void parse(const shared_ptr <const message>& msg);
+
+ void findAttachments(const shared_ptr <const message>& msg);
+
+ void findTextParts(
+ const shared_ptr <const bodyPart>& msg,
+ const shared_ptr <const bodyPart>& part
+ );
+
+ bool findSubTextParts(
+ const shared_ptr <const bodyPart>& msg,
+ const shared_ptr <const bodyPart>& part
+ );
+};
+
+
+} // vmime
+
+
+#endif // VMIME_MESSAGEPARSER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/misc/importanceHelper.cpp b/vmime-master/src/vmime/misc/importanceHelper.cpp
new file mode 100644
index 0000000..20c8e13
--- /dev/null
+++ b/vmime-master/src/vmime/misc/importanceHelper.cpp
@@ -0,0 +1,163 @@
+//
+// 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.
+//
+
+#include "vmime/misc/importanceHelper.hpp"
+#include "vmime/exception.hpp"
+
+#include "vmime/text.hpp"
+
+
+namespace vmime {
+namespace misc {
+
+
+void importanceHelper::resetImportance(const shared_ptr <message>& msg) {
+
+ resetImportanceHeader(msg->getHeader());
+}
+
+
+void importanceHelper::resetImportanceHeader(const shared_ptr <header>& hdr) {
+
+ shared_ptr <headerField> fld;
+
+ if ((fld = hdr->findField("X-Priority")))
+ hdr->removeField(fld);
+
+ if ((fld = hdr->findField("Importance")))
+ hdr->removeField(fld);
+}
+
+
+importanceHelper::Importance importanceHelper::getImportance(const shared_ptr <const message>& msg) {
+
+ return getImportanceHeader(msg->getHeader());
+}
+
+
+importanceHelper::Importance importanceHelper::getImportanceHeader(const shared_ptr <const header>& hdr) {
+
+ // Try "X-Priority" field
+ shared_ptr <const headerField> fld = hdr->findField("X-Priority");
+
+ if (fld) {
+
+ const string value = fld->getValue <text>()->getWholeBuffer();
+
+ int n = IMPORTANCE_NORMAL;
+
+ std::istringstream iss(value);
+ iss.imbue(std::locale::classic());
+
+ iss >> n;
+
+ Importance i = IMPORTANCE_NORMAL;
+
+ switch (n) {
+ case 1: i = IMPORTANCE_HIGHEST; break;
+ case 2: i = IMPORTANCE_HIGH; break;
+ case 3: i = IMPORTANCE_NORMAL; break;
+ case 4: i = IMPORTANCE_LOW; break;
+ case 5: i = IMPORTANCE_LOWEST; break;
+ }
+
+ return i;
+
+ } else {
+
+ // Try "Importance" field
+ fld = hdr->findField("Importance");
+
+ if (fld) {
+
+ const string value = utility::stringUtils::toLower(utility::stringUtils::trim
+ (fld->getValue <text>()->getWholeBuffer()));
+
+ if (value == "low") {
+ return IMPORTANCE_LOWEST;
+ } else if (value == "high") {
+ return IMPORTANCE_HIGHEST;
+ } else {
+ return IMPORTANCE_NORMAL;
+ }
+
+ } else {
+
+ // Default
+ return IMPORTANCE_NORMAL;
+ }
+ }
+
+ // Should not go here...
+ return IMPORTANCE_NORMAL;
+}
+
+
+void importanceHelper::setImportance(const shared_ptr <message>& msg, const Importance i) {
+
+ setImportanceHeader(msg->getHeader(), i);
+}
+
+
+void importanceHelper::setImportanceHeader(const shared_ptr <header>& hdr, const Importance i) {
+
+ // "X-Priority:" Field
+ shared_ptr <headerField> fld = hdr->getField("X-Priority");
+
+ switch (i) {
+ case IMPORTANCE_HIGHEST: fld->setValue("1 (Highest)"); break;
+ case IMPORTANCE_HIGH: fld->setValue("2 (High)"); break;
+ default:
+ case IMPORTANCE_NORMAL: fld->setValue("3 (Normal)"); break;
+ case IMPORTANCE_LOW: fld->setValue("4 (Low)"); break;
+ case IMPORTANCE_LOWEST: fld->setValue("5 (Lowest)"); break;
+ }
+
+ // "Importance:" Field
+ fld = hdr->getField("Importance");
+
+ switch (i) {
+
+ case IMPORTANCE_HIGHEST:
+ case IMPORTANCE_HIGH:
+
+ fld->setValue("high");
+ break;
+
+ default:
+ case IMPORTANCE_NORMAL:
+
+ fld->setValue("normal");
+ break;
+
+ case IMPORTANCE_LOWEST:
+ case IMPORTANCE_LOW:
+
+ fld->setValue("low");
+ break;
+ }
+}
+
+
+} // misc
+} // vmime
diff --git a/vmime-master/src/vmime/misc/importanceHelper.hpp b/vmime-master/src/vmime/misc/importanceHelper.hpp
new file mode 100644
index 0000000..45e0bcc
--- /dev/null
+++ b/vmime-master/src/vmime/misc/importanceHelper.hpp
@@ -0,0 +1,103 @@
+//
+// 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_MISC_IMPORTANCEHELPER_HPP_INCLUDED
+#define VMIME_MISC_IMPORTANCEHELPER_HPP_INCLUDED
+
+
+#include "vmime/message.hpp"
+
+
+namespace vmime {
+namespace misc {
+
+
+/** Deals with setting and retrieving message importance (also
+ * known as priority).
+ *
+ * Basically, it wraps the use of the 'X-Priority' (non standard)
+ * and 'Importance' (RFC-1327, RFC-1911) fields.
+ */
+class VMIME_EXPORT importanceHelper {
+
+public:
+
+ /** Different levels of importance. */
+ enum Importance {
+ IMPORTANCE_HIGHEST,
+ IMPORTANCE_HIGH,
+ IMPORTANCE_NORMAL,
+ IMPORTANCE_LOW,
+ IMPORTANCE_LOWEST
+ };
+
+
+ /** Reset the importance of the message to the default importance.
+ *
+ * @param msg message on which to reset importance
+ */
+ static void resetImportance(const shared_ptr <message>& msg);
+
+ /** Reset the importance of a message to the default importance.
+ *
+ * @param hdr message header on which to reset importance
+ */
+ static void resetImportanceHeader(const shared_ptr <header>& hdr);
+
+ /** Return the importance of the specified message.
+ *
+ * @param msg message from which to retrieve importance
+ * @return importance of the message, or default importance is no
+ * information about importance is given in the message
+ */
+ static Importance getImportance(const shared_ptr <const message>& msg);
+
+ /** Return the importance of a message, given its header.
+ *
+ * @param hdr message header from which to retrieve importance
+ * @return importance of the message, or default importance is no
+ * information about importance is given in the message
+ */
+ static Importance getImportanceHeader(const shared_ptr <const header>& hdr);
+
+ /** Set the importance of the specified message.
+ *
+ * @param msg message on which to set importance
+ * @param i new message importance
+ */
+ static void setImportance(const shared_ptr <message>& msg, const Importance i);
+
+ /** Set the importance of a message, given its header.
+ *
+ * @param hdr message header on which to set importance
+ * @param i new message importance
+ */
+ static void setImportanceHeader(const shared_ptr <header>& hdr, const Importance i);
+};
+
+
+} // misc
+} // vmime
+
+
+#endif // VMIME_MISC_IMPORTANCEHELPER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/builtinServices.inl b/vmime-master/src/vmime/net/builtinServices.inl
new file mode 100644
index 0000000..2f67d2e
--- /dev/null
+++ b/vmime-master/src/vmime/net/builtinServices.inl
@@ -0,0 +1,76 @@
+//
+// 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.
+//
+
+
+// Include registration helpers
+#include "vmime/net/serviceRegistration.inl"
+
+
+#ifndef VMIME_BUILDING_DOC
+
+
+#if VMIME_HAVE_MESSAGING_PROTO_POP3
+ #include "vmime/net/pop3/POP3Store.hpp"
+ REGISTER_SERVICE(pop3::POP3Store, pop3, TYPE_STORE);
+
+ #if VMIME_HAVE_TLS_SUPPORT
+ #include "vmime/net/pop3/POP3SStore.hpp"
+ REGISTER_SERVICE(pop3::POP3SStore, pop3s, TYPE_STORE);
+ #endif // VMIME_HAVE_TLS_SUPPORT
+#endif
+
+
+#if VMIME_HAVE_MESSAGING_PROTO_SMTP
+ #include "vmime/net/smtp/SMTPTransport.hpp"
+ REGISTER_SERVICE(smtp::SMTPTransport, smtp, TYPE_TRANSPORT);
+
+ #if VMIME_HAVE_TLS_SUPPORT
+ #include "vmime/net/smtp/SMTPSTransport.hpp"
+ REGISTER_SERVICE(smtp::SMTPSTransport, smtps, TYPE_TRANSPORT);
+ #endif // VMIME_HAVE_TLS_SUPPORT
+#endif
+
+
+#if VMIME_HAVE_MESSAGING_PROTO_IMAP
+ #include "vmime/net/imap/IMAPStore.hpp"
+ REGISTER_SERVICE(imap::IMAPStore, imap, TYPE_STORE);
+
+ #if VMIME_HAVE_TLS_SUPPORT
+ #include "vmime/net/imap/IMAPSStore.hpp"
+ REGISTER_SERVICE(imap::IMAPSStore, imaps, TYPE_STORE);
+ #endif // VMIME_HAVE_TLS_SUPPORT
+#endif
+
+
+#if VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+ #include "vmime/net/maildir/maildirStore.hpp"
+ REGISTER_SERVICE(maildir::maildirStore, maildir, TYPE_STORE);
+#endif
+
+#if VMIME_HAVE_MESSAGING_PROTO_SENDMAIL
+ #include "vmime/net/sendmail/sendmailTransport.hpp"
+ REGISTER_SERVICE(sendmail::sendmailTransport, sendmail, TYPE_TRANSPORT);
+#endif
+
+
+#endif // VMIME_BUILDING_DOC
diff --git a/vmime-master/src/vmime/net/connectionInfos.hpp b/vmime-master/src/vmime/net/connectionInfos.hpp
new file mode 100644
index 0000000..0e519c7
--- /dev/null
+++ b/vmime-master/src/vmime/net/connectionInfos.hpp
@@ -0,0 +1,68 @@
+//
+// 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_NET_CONNECTIONINFOS_HPP_INCLUDED
+#define VMIME_NET_CONNECTIONINFOS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/object.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+/** Information about the connection used by a service.
+ */
+class VMIME_EXPORT connectionInfos : public object {
+
+public:
+
+ /** Return the host to which the service is connected.
+ *
+ * @return server host name or address
+ */
+ virtual const string getHost() const = 0;
+
+ /** Return the port to which the service is connected.
+ *
+ * @return server port
+ */
+ virtual port_t getPort() const = 0;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_CONNECTIONINFOS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/defaultConnectionInfos.cpp b/vmime-master/src/vmime/net/defaultConnectionInfos.cpp
new file mode 100644
index 0000000..889f214
--- /dev/null
+++ b/vmime-master/src/vmime/net/defaultConnectionInfos.cpp
@@ -0,0 +1,60 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/defaultConnectionInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+defaultConnectionInfos::defaultConnectionInfos(const string& host, const port_t port)
+ : m_host(host), m_port(port) {
+
+}
+
+
+const string defaultConnectionInfos::getHost() const {
+
+ return m_host;
+}
+
+
+port_t defaultConnectionInfos::getPort() const {
+
+ return m_port;
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
diff --git a/vmime-master/src/vmime/net/defaultConnectionInfos.hpp b/vmime-master/src/vmime/net/defaultConnectionInfos.hpp
new file mode 100644
index 0000000..f348859
--- /dev/null
+++ b/vmime-master/src/vmime/net/defaultConnectionInfos.hpp
@@ -0,0 +1,66 @@
+//
+// 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_NET_DEFAULTCONNECTIONINFOS_HPP_INCLUDED
+#define VMIME_NET_DEFAULTCONNECTIONINFOS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/connectionInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+/** Information about the connection used by a service.
+ */
+class VMIME_EXPORT defaultConnectionInfos : public connectionInfos {
+
+public:
+
+ defaultConnectionInfos(const string& host, const port_t port);
+
+ const string getHost() const;
+ port_t getPort() const;
+
+private:
+
+ string m_host;
+ port_t m_port;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_DEFAULTCONNECTIONINFOS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/defaultTimeoutHandler.cpp b/vmime-master/src/vmime/net/defaultTimeoutHandler.cpp
new file mode 100644
index 0000000..f5dcc7d
--- /dev/null
+++ b/vmime-master/src/vmime/net/defaultTimeoutHandler.cpp
@@ -0,0 +1,78 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/defaultTimeoutHandler.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+defaultTimeoutHandler::defaultTimeoutHandler() {
+
+ m_startTime = time(NULL);
+}
+
+
+defaultTimeoutHandler::~defaultTimeoutHandler() {
+
+}
+
+
+bool defaultTimeoutHandler::isTimeOut() {
+
+ return time(NULL) - m_startTime >= 30;
+}
+
+
+void defaultTimeoutHandler::resetTimeOut() {
+
+ m_startTime = time(NULL);
+}
+
+
+bool defaultTimeoutHandler::handleTimeOut() {
+
+ return false;
+}
+
+
+
+
+shared_ptr <timeoutHandler> defaultTimeoutHandlerFactory::create() {
+
+ return make_shared <defaultTimeoutHandler>();
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
diff --git a/vmime-master/src/vmime/net/defaultTimeoutHandler.hpp b/vmime-master/src/vmime/net/defaultTimeoutHandler.hpp
new file mode 100644
index 0000000..545c655
--- /dev/null
+++ b/vmime-master/src/vmime/net/defaultTimeoutHandler.hpp
@@ -0,0 +1,80 @@
+//
+// 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_NET_DEFAULTTIMEOUTHANDLER_HPP_INCLUDED
+#define VMIME_NET_DEFAULTTIMEOUTHANDLER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/timeoutHandler.hpp"
+
+#include <ctime>
+
+
+namespace vmime {
+namespace net {
+
+
+/** A default timeout handler for messaging services. The default action
+ * is to throw a exceptions::operation_timed_out exception when an
+ * operation is blocked for more than 30 seconds.
+ */
+class VMIME_EXPORT defaultTimeoutHandler : public timeoutHandler {
+
+public:
+
+ defaultTimeoutHandler();
+ ~defaultTimeoutHandler();
+
+ bool isTimeOut();
+ void resetTimeOut();
+ bool handleTimeOut();
+
+private:
+
+ time_t m_startTime;
+};
+
+
+/** A class that creates default timeout handlers.
+ */
+class defaultTimeoutHandlerFactory : public timeoutHandlerFactory {
+
+public:
+
+ shared_ptr <timeoutHandler> create();
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_DEFAULTTIMEOUTHANDLER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/dsnAttributes.cpp b/vmime-master/src/vmime/net/dsnAttributes.cpp
new file mode 100644
index 0000000..dc949b9
--- /dev/null
+++ b/vmime-master/src/vmime/net/dsnAttributes.cpp
@@ -0,0 +1,71 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2020 Jan Osusky <jan@osusky.name>
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/dsnAttributes.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+dsnAttributes::dsnAttributes(const string& dsnNotify, const string& dsnRet, const string& dsnEnvelopId)
+ : m_notifications(dsnNotify), m_returnFormat(dsnRet), m_envelopId(dsnEnvelopId) {
+
+}
+
+
+string dsnAttributes::getNotificationConditions() const {
+
+ return m_notifications;
+}
+
+
+string dsnAttributes::getReturnFormat() const {
+
+ return m_returnFormat;
+}
+
+
+string dsnAttributes::getEnvelopId() const {
+
+ return m_envelopId;
+}
+
+
+bool dsnAttributes::isEmpty() const {
+
+ return m_notifications.empty() && m_returnFormat.empty() && m_envelopId.empty();
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
diff --git a/vmime-master/src/vmime/net/dsnAttributes.hpp b/vmime-master/src/vmime/net/dsnAttributes.hpp
new file mode 100644
index 0000000..945da28
--- /dev/null
+++ b/vmime-master/src/vmime/net/dsnAttributes.hpp
@@ -0,0 +1,114 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2020 Jan Osusky <jan@osusky.name>
+//
+// 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_NET_DSNATTRIBUTES_HPP_INCLUDED
+#define VMIME_NET_DSNATTRIBUTES_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include <vector>
+
+#include "vmime/types.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+/** Holds a set of attributes for Delivery Status Notifications (DSN).
+ */
+class VMIME_EXPORT dsnAttributes : public object {
+
+public:
+
+ /** Constructs an empty dsnAttributes object.
+ */
+ dsnAttributes() = default;
+
+ /** Constructs a new dsnAttributes object by copying an existing object.
+ *
+ * @param dsn object to copy
+ */
+ dsnAttributes(const dsnAttributes& dsn) = default;
+
+ /** Constructs a new dsnAttributes object by moving an existing object.
+ *
+ * @param dsn object (Rvalue reference) to move from.
+ */
+ dsnAttributes(dsnAttributes&& dsn) = default;
+
+ ~dsnAttributes() = default;
+
+ /** Constructs a new dsnAttributes object by specifying the attributes.
+ *
+ * @param dsnNotify comma separated list of notification conditions as specified in RFC 1891
+ * @param dsnRet content of DSN - full message or headers only ("FULL" or "HDRS")
+ * @param dsnEnvelopId envelop ID to be able to pair the DSN with original message (plain text not in "<" ">")
+ */
+ dsnAttributes(const string& dsnNotify, const string& dsnRet, const string& dsnEnvelopId);
+
+ /** Returns comma separated list of notification conditions as specified in RFC 1891
+ *
+ * @return comma separated list of notification conditions as specified in RFC 1891
+ */
+ string getNotificationConditions() const;
+
+ /** Returns requested format of the notification (RET parameter of the ESMTP MAIL command).
+ *
+ * @return requested format of the notification.
+ */
+ string getReturnFormat() const;
+
+ /** Returns envelop ID used to pair the DSN with the original message.
+ *
+ * @return envelop ID used to pair the DSN with the original message.
+ */
+ string getEnvelopId() const;
+
+ /** Returns whether the object is empty, and no attribute has been set.
+ *
+ * @return true if object is empty, or false otherwise
+ */
+ bool isEmpty() const;
+
+private:
+
+ string m_notifications;
+ string m_returnFormat;
+ string m_envelopId;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+
+#endif // VMIME_NET_DSNATTRIBUTES_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/events.cpp b/vmime-master/src/vmime/net/events.cpp
new file mode 100644
index 0000000..8660812
--- /dev/null
+++ b/vmime-master/src/vmime/net/events.cpp
@@ -0,0 +1,180 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/events.hpp"
+#include "vmime/net/folder.hpp"
+
+#include <algorithm>
+
+
+namespace vmime {
+namespace net {
+namespace events {
+
+
+//
+// event
+//
+
+event::event() {
+
+}
+
+
+event::~event() {
+
+}
+
+
+//
+// messageCountEvent
+//
+
+const char* messageCountEvent::EVENT_CLASS = "messageCountEvent";
+
+
+messageCountEvent::messageCountEvent(
+ const shared_ptr <folder>& folder,
+ const Types type,
+ const std::vector <size_t>& nums
+)
+ : m_folder(folder),
+ m_type(type) {
+
+ m_nums.resize(nums.size());
+ std::copy(nums.begin(), nums.end(), m_nums.begin());
+}
+
+
+shared_ptr <folder> messageCountEvent::getFolder() const { return (m_folder); }
+messageCountEvent::Types messageCountEvent::getType() const { return (m_type); }
+const std::vector <size_t>& messageCountEvent::getNumbers() const { return (m_nums); }
+
+
+void messageCountEvent::dispatch(messageCountListener* listener) {
+
+ if (m_type == TYPE_ADDED) {
+ listener->messagesAdded(dynamicCast <messageCountEvent>(shared_from_this()));
+ } else {
+ listener->messagesRemoved(dynamicCast <messageCountEvent>(shared_from_this()));
+ }
+}
+
+
+const char* messageCountEvent::getClass() const {
+
+ return EVENT_CLASS;
+}
+
+
+//
+// messageChangedEvent
+//
+
+const char* messageChangedEvent::EVENT_CLASS = "messageChangedEvent";
+
+
+messageChangedEvent::messageChangedEvent(
+ const shared_ptr <folder>& folder,
+ const Types type,
+ const std::vector <size_t>& nums
+)
+ : m_folder(folder),
+ m_type(type) {
+
+ m_nums.resize(nums.size());
+ std::copy(nums.begin(), nums.end(), m_nums.begin());
+}
+
+
+shared_ptr <folder> messageChangedEvent::getFolder() const { return (m_folder); }
+messageChangedEvent::Types messageChangedEvent::getType() const { return (m_type); }
+const std::vector <size_t>& messageChangedEvent::getNumbers() const { return (m_nums); }
+
+
+void messageChangedEvent::dispatch(messageChangedListener* listener) {
+
+ listener->messageChanged(dynamicCast <messageChangedEvent>(shared_from_this()));
+}
+
+
+const char* messageChangedEvent::getClass() const {
+
+ return EVENT_CLASS;
+}
+
+
+//
+// folderEvent
+//
+
+const char* folderEvent::EVENT_CLASS = "folderEvent";
+
+
+folderEvent::folderEvent(
+ const shared_ptr <folder>& folder,
+ const Types type,
+ const utility::path& oldPath,
+ const utility::path& newPath
+)
+ : m_folder(folder),
+ m_type(type),
+ m_oldPath(oldPath),
+ m_newPath(newPath) {
+
+}
+
+
+shared_ptr <folder> folderEvent::getFolder() const { return (m_folder); }
+folderEvent::Types folderEvent::getType() const { return (m_type); }
+
+
+void folderEvent::dispatch(folderListener* listener) {
+
+ switch (m_type) {
+ case TYPE_CREATED: listener->folderCreated(dynamicCast <folderEvent>(shared_from_this())); break;
+ case TYPE_RENAMED: listener->folderRenamed(dynamicCast <folderEvent>(shared_from_this())); break;
+ case TYPE_DELETED: listener->folderDeleted(dynamicCast <folderEvent>(shared_from_this())); break;
+ }
+}
+
+
+const char* folderEvent::getClass() const {
+
+ return EVENT_CLASS;
+}
+
+
+} // events
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
diff --git a/vmime-master/src/vmime/net/events.hpp b/vmime-master/src/vmime/net/events.hpp
new file mode 100644
index 0000000..2ad64e7
--- /dev/null
+++ b/vmime-master/src/vmime/net/events.hpp
@@ -0,0 +1,276 @@
+//
+// 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_NET_EVENTS_HPP_INCLUDED
+#define VMIME_NET_EVENTS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include <vector>
+
+#include "vmime/utility/path.hpp"
+
+
+namespace vmime {
+namespace net {
+
+class folder;
+
+namespace events {
+
+
+/** Event occurring on folders or messages.
+ */
+class VMIME_EXPORT event : public object, public enable_shared_from_this <event> {
+
+public:
+
+ event();
+ virtual ~event();
+
+ virtual const char* getClass() const = 0;
+};
+
+
+/** Event about the message count in a folder.
+ */
+class VMIME_EXPORT messageCountEvent : public event {
+
+public:
+
+ static const char* EVENT_CLASS;
+
+
+ enum Types {
+ TYPE_ADDED, /**< New messages have been added. */
+ TYPE_REMOVED /**< Messages have been expunged (renumbering). */
+ };
+
+
+ messageCountEvent(
+ const shared_ptr <folder>& folder,
+ const Types type,
+ const std::vector <size_t>& nums
+ );
+
+ /** Return the folder in which messages have been added/removed.
+ *
+ * @return folder in which message count changed
+ */
+ shared_ptr <folder> getFolder() const;
+
+ /** Return the event type.
+ *
+ * @return event type (see messageCountEvent::Types)
+ */
+ Types getType() const;
+
+ /** Return the numbers of the messages that have been added/removed.
+ *
+ * @return a list of message numbers
+ */
+ const std::vector <size_t>& getNumbers() const;
+
+ /** Dispatch the event to the specified listener.
+ *
+ * @param listener listener to notify
+ */
+ void dispatch(class messageCountListener* listener);
+
+
+ const char* getClass() const;
+
+private:
+
+ shared_ptr <folder> m_folder;
+ const Types m_type;
+ std::vector <size_t> m_nums;
+};
+
+
+/** Listener for events about the message count in a folder.
+ */
+class VMIME_EXPORT messageCountListener {
+
+protected:
+
+ virtual ~messageCountListener() { }
+
+public:
+
+ virtual void messagesAdded(const shared_ptr <messageCountEvent>& event) = 0;
+ virtual void messagesRemoved(const shared_ptr <messageCountEvent>& event) = 0;
+};
+
+
+/** Event occuring on a message.
+ */
+class VMIME_EXPORT messageChangedEvent : public event {
+
+public:
+
+ static const char* EVENT_CLASS;
+
+
+ enum Types {
+ TYPE_FLAGS // flags changed
+ };
+
+
+ messageChangedEvent(
+ const shared_ptr <folder>& folder,
+ const Types type,
+ const std::vector <size_t>& nums
+ );
+
+ /** Return the folder in which messages have changed.
+ *
+ * @return folder in which message count changed
+ */
+ shared_ptr <folder> getFolder() const;
+
+ /** Return the event type.
+ *
+ * @return event type (see messageChangedEvent::Types)
+ */
+ Types getType() const;
+
+ /** Return the numbers of the messages that have changed.
+ *
+ * @return a list of message numbers
+ */
+ const std::vector <size_t>& getNumbers() const;
+
+ /** Dispatch the event to the specified listener.
+ *
+ * @param listener listener to notify
+ */
+ void dispatch(class messageChangedListener* listener);
+
+
+ const char* getClass() const;
+
+private:
+
+ shared_ptr <folder> m_folder;
+ const Types m_type;
+ std::vector <size_t> m_nums;
+};
+
+
+/** Listener for events occuring on a message.
+ */
+class VMIME_EXPORT messageChangedListener {
+
+protected:
+
+ virtual ~messageChangedListener() { }
+
+public:
+
+ virtual void messageChanged(const shared_ptr <messageChangedEvent>& event) = 0;
+};
+
+
+/** Event occuring on a folder.
+ */
+class VMIME_EXPORT folderEvent : public event {
+
+public:
+
+ static const char* EVENT_CLASS;
+
+
+ enum Types {
+ TYPE_CREATED, /**< A folder was created. */
+ TYPE_DELETED, /**< A folder was deleted. */
+ TYPE_RENAMED /**< A folder was renamed. */
+ };
+
+
+ folderEvent(
+ const shared_ptr <folder>& folder,
+ const Types type,
+ const utility::path& oldPath,
+ const utility::path& newPath
+ );
+
+ /** Return the folder on which the event occurred.
+ *
+ * @return folder on which the event occurred
+ */
+ shared_ptr <folder> getFolder() const;
+
+ /** Return the event type.
+ *
+ * @return event type (see folderEvent::Types)
+ */
+ Types getType() const;
+
+ /** Dispatch the event to the specified listener.
+ *
+ * @param listener listener to notify
+ */
+ void dispatch(class folderListener* listener);
+
+
+ const char* getClass() const;
+
+private:
+
+ shared_ptr <folder> m_folder;
+ const Types m_type;
+ const utility::path m_oldPath;
+ const utility::path m_newPath;
+};
+
+
+/** Listener for events occuring on a folder.
+ */
+class VMIME_EXPORT folderListener {
+
+protected:
+
+ virtual ~folderListener() { }
+
+public:
+
+ virtual void folderCreated(const shared_ptr <folderEvent>& event) = 0;
+ virtual void folderRenamed(const shared_ptr <folderEvent>& event) = 0;
+ virtual void folderDeleted(const shared_ptr <folderEvent>& event) = 0;
+};
+
+
+} // events
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_EVENTS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/fetchAttributes.cpp b/vmime-master/src/vmime/net/fetchAttributes.cpp
new file mode 100644
index 0000000..d9b54b8
--- /dev/null
+++ b/vmime-master/src/vmime/net/fetchAttributes.cpp
@@ -0,0 +1,98 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/fetchAttributes.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include <algorithm>
+
+
+namespace vmime {
+namespace net {
+
+
+fetchAttributes::fetchAttributes()
+ : m_predefinedAttribs(0) {
+
+}
+
+
+fetchAttributes::fetchAttributes(const int attribs)
+ : m_predefinedAttribs(attribs) {
+
+}
+
+
+fetchAttributes::fetchAttributes(const fetchAttributes& attribs)
+ : object() {
+
+ m_predefinedAttribs = attribs.m_predefinedAttribs;
+ m_headers = attribs.m_headers;
+}
+
+
+void fetchAttributes::add(const int attribs) {
+
+ m_predefinedAttribs |= attribs;
+}
+
+
+void fetchAttributes::add(const string& header) {
+
+ m_headers.push_back(utility::stringUtils::toLower(header));
+}
+
+
+bool fetchAttributes::has(const int attribs) const {
+
+ return (m_predefinedAttribs & attribs) != 0;
+}
+
+
+bool fetchAttributes::has(const string& header) const {
+
+ return std::find(
+ m_headers.begin(), m_headers.end(),
+ utility::stringUtils::toLower(header)
+ ) != m_headers.end();
+}
+
+
+const std::vector <string> fetchAttributes::getHeaderFields() const {
+
+ return m_headers;
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
diff --git a/vmime-master/src/vmime/net/fetchAttributes.hpp b/vmime-master/src/vmime/net/fetchAttributes.hpp
new file mode 100644
index 0000000..19d9262
--- /dev/null
+++ b/vmime-master/src/vmime/net/fetchAttributes.hpp
@@ -0,0 +1,140 @@
+//
+// 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_NET_FETCHATTRIBUTES_HPP_INCLUDED
+#define VMIME_NET_FETCHATTRIBUTES_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include <vector>
+
+#include "vmime/types.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+/** Holds a set of attributes to fetch for a message.
+ */
+class VMIME_EXPORT fetchAttributes : public object {
+
+public:
+
+ /** Predefined attributes that can be fetched.
+ */
+ enum PredefinedFetchAttributes {
+ ENVELOPE = (1 << 0), /**< Sender, recipients, date, subject. */
+ STRUCTURE = (1 << 1), /**< MIME structure (body parts). */
+ CONTENT_INFO = (1 << 2), /**< Top-level content type. */
+ FLAGS = (1 << 3), /**< Message flags. */
+ SIZE = (1 << 4), /**< Message size (exact or estimated). */
+ FULL_HEADER = (1 << 5), /**< Full RFC-[2]822 header. */
+ UID = (1 << 6), /**< Unique identifier (protocol specific). */
+ IMPORTANCE = (1 << 7), /**< Header fields suitable for use with misc::importanceHelper. */
+
+ CUSTOM = (1 << 16) /**< Reserved for future use. */
+ };
+
+ /** Constructs an empty fetchAttributes object.
+ */
+ fetchAttributes();
+
+ /** Constructs a new fetchAttributes object by specifying one or more
+ * predefined objects.
+ *
+ * @param attribs one or more OR-ed values of the PredefinedFetchAttributes enum
+ */
+ fetchAttributes(const int attribs);
+
+ /** Constructs a new fetchAttributes object by copying an existing object.
+ *
+ * @param attribs object to copy
+ */
+ fetchAttributes(const fetchAttributes& attribs);
+
+ /** Adds the specified predefined attribute to the set of attributes to fetch.
+ *
+ * @param attribs one or more OR-ed values of the PredefinedFetchAttributes enum
+ */
+ void add(const int attribs);
+
+ /** Adds the specified header field to the set of attributes to fetch.
+ * Fetching custom header fields is not supported by all protocols.
+ * At this time, only IMAP supports this.
+ *
+ * @param header name of header field (eg. "X-Mailer")
+ */
+ void add(const string& header);
+
+ /** Returns true if the set contains the specified attribute(s).
+ *
+ * @param attribs one or more OR-ed values of the PredefinedFetchAttributes enum
+ * @return true if the specified attributes are to be fetched
+ */
+ bool has(const int attribs) const;
+
+ /** Returns true if the set contains the specified header field.
+ *
+ * @param header name of header field (eg. "X-Mailer")
+ * @return true if the specified header fields are to be fetched
+ */
+ bool has(const string& header) const;
+
+ /** Returns true if the set contains the specified attribute(s).
+ *
+ * \deprecated Use the has() methods instead
+ *
+ * @param attribs one or more OR-ed values of the PredefinedFetchAttributes enum
+ * @return true if the specified attributes are to be fetched
+ */
+ VMIME_DEPRECATED inline bool operator&(const int attribs) const {
+ return has(attribs);
+ }
+
+ /** Returns a list of header fields to fetch.
+ *
+ * @return list of header names (eg. "X-Mailer")
+ */
+ const std::vector <string> getHeaderFields() const;
+
+private:
+
+ int m_predefinedAttribs;
+ std::vector <string> m_headers;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+
+#endif // VMIME_NET_FETCHATTRIBUTES_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/folder.cpp b/vmime-master/src/vmime/net/folder.cpp
new file mode 100644
index 0000000..6e01b60
--- /dev/null
+++ b/vmime-master/src/vmime/net/folder.cpp
@@ -0,0 +1,134 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/folder.hpp"
+
+#include <algorithm>
+
+
+namespace vmime {
+namespace net {
+
+
+int folder::getType() {
+
+ return getAttributes().getType();
+}
+
+
+int folder::getFlags() {
+
+ return getAttributes().getFlags();
+}
+
+
+void folder::addMessageChangedListener(events::messageChangedListener* l) {
+
+ m_messageChangedListeners.push_back(l);
+}
+
+
+void folder::removeMessageChangedListener(events::messageChangedListener* l) {
+
+ std::remove(m_messageChangedListeners.begin(), m_messageChangedListeners.end(), l);
+}
+
+
+void folder::notifyMessageChanged(const shared_ptr <events::messageChangedEvent>& event) {
+
+ for (std::list <events::messageChangedListener*>::iterator
+ it = m_messageChangedListeners.begin() ; it != m_messageChangedListeners.end() ; ++it) {
+
+ event->dispatch(*it);
+ }
+}
+
+
+void folder::addMessageCountListener(events::messageCountListener* l) {
+
+ m_messageCountListeners.push_back(l);
+}
+
+
+void folder::removeMessageCountListener(events::messageCountListener* l) {
+
+ std::remove(m_messageCountListeners.begin(), m_messageCountListeners.end(), l);
+}
+
+
+void folder::notifyMessageCount(const shared_ptr <events::messageCountEvent>& event) {
+
+ for (std::list <events::messageCountListener*>::iterator
+ it = m_messageCountListeners.begin() ; it != m_messageCountListeners.end() ; ++it) {
+
+ event->dispatch(*it);
+ }
+}
+
+
+void folder::addFolderListener(events::folderListener* l) {
+
+ m_folderListeners.push_back(l);
+}
+
+
+void folder::removeFolderListener(events::folderListener* l) {
+
+ std::remove(m_folderListeners.begin(), m_folderListeners.end(), l);
+}
+
+
+void folder::notifyFolder(const shared_ptr <events::folderEvent>& event) {
+
+ for (std::list <events::folderListener*>::iterator
+ it = m_folderListeners.begin() ; it != m_folderListeners.end() ; ++it) {
+
+ event->dispatch(*it);
+ }
+}
+
+
+void folder::notifyEvent(const shared_ptr <events::event>& event) {
+
+ if (event->getClass() == events::messageCountEvent::EVENT_CLASS) {
+ notifyMessageCount(dynamicCast <events::messageCountEvent>(event));
+ } else if (event->getClass() == events::messageChangedEvent::EVENT_CLASS) {
+ notifyMessageChanged(dynamicCast <events::messageChangedEvent>(event));
+ } else if (event->getClass() == events::folderEvent::EVENT_CLASS) {
+ notifyFolder(dynamicCast <events::folderEvent>(event));
+ }
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
diff --git a/vmime-master/src/vmime/net/folder.hpp b/vmime-master/src/vmime/net/folder.hpp
new file mode 100644
index 0000000..4d5cf6e
--- /dev/null
+++ b/vmime-master/src/vmime/net/folder.hpp
@@ -0,0 +1,440 @@
+//
+// 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_NET_FOLDER_HPP_INCLUDED
+#define VMIME_NET_FOLDER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include <vector>
+
+#include "vmime/types.hpp"
+#include "vmime/dateTime.hpp"
+
+#include "vmime/message.hpp"
+#include "vmime/net/message.hpp"
+#include "vmime/net/messageSet.hpp"
+#include "vmime/net/events.hpp"
+#include "vmime/net/folderStatus.hpp"
+#include "vmime/net/fetchAttributes.hpp"
+#include "vmime/net/folderAttributes.hpp"
+
+#include "vmime/utility/path.hpp"
+#include "vmime/utility/stream.hpp"
+#include "vmime/utility/progressListener.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+class store;
+
+
+/** Abstract representation of a folder in a message store.
+ */
+class VMIME_EXPORT folder : public object, public enable_shared_from_this <folder> {
+
+protected:
+
+ folder(const folder&) : object(), enable_shared_from_this <folder>() { }
+ folder() { }
+
+
+ enum PrivateConstants {
+ TYPE_UNDEFINED = 9999, /**< Used internally to indicate type has not
+ been initialized yet. */
+ FLAG_UNDEFINED = 9999 /**< Used internally to indicate flags have not
+ been initialized yet. */
+ };
+
+public:
+
+ virtual ~folder() { }
+
+ /** Type used for fully qualified path name of a folder.
+ */
+ typedef vmime::utility::path path;
+
+
+ /** Open mode.
+ */
+ enum Modes {
+ MODE_READ_ONLY, /**< Read-only mode (no modification to folder or messages is possible). */
+ MODE_READ_WRITE /**< Full access mode (read and write). */
+ };
+
+
+ /** Return the type of this folder.
+ *
+ * \deprecated Use the getAttributes().getType() method instead
+ *
+ * @return folder type (see folderAttributes::Types enum)
+ */
+ int getType();
+
+ /** Return the flags of this folder.
+ *
+ * \deprecated Use the getAttributes().getFlags() method instead
+ *
+ * @return folder flags (see folderAttributes::Flags enum)
+ */
+ int getFlags();
+
+ /** Return the attributes of the folder.
+ *
+ * @return folder attributes (see folder::Flags)
+ */
+ virtual const folderAttributes getAttributes() = 0;
+
+ /** Return the mode in which the folder has been open.
+ *
+ * @return folder opening mode (see folder::Modes)
+ */
+ virtual int getMode() const = 0;
+
+ /** Return the name of this folder.
+ *
+ * @return folder name
+ */
+ virtual const folder::path::component getName() const = 0;
+
+ /** Return the fully qualified path name of this folder.
+ *
+ * @return absolute path of the folder
+ */
+ virtual const folder::path getFullPath() const = 0;
+
+ /** Open this folder.
+ *
+ * @param mode open mode (see folder::Modes)
+ * @param failIfModeIsNotAvailable if set to false and if the requested mode
+ * is not available, a more restricted mode will be selected automatically.
+ * If set to true and if the requested mode is not available, the opening
+ * will fail.
+ * @throw exceptions::net_exception if an error occurs
+ * @throw exceptions::folder_already_open if the folder is already open
+ * in the same session
+ */
+ virtual void open(const int mode, bool failIfModeIsNotAvailable = false) = 0;
+
+ /** Close this folder.
+ *
+ * @param expunge if set to true, deleted messages are expunged
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual void close(const bool expunge) = 0;
+
+ /** Create this folder.
+ *
+ * @param attribs attributes of the new folder
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual void create(const folderAttributes& attribs) = 0;
+
+ /** Test whether this folder exists.
+ *
+ * @return true if the folder exists, false otherwise
+ */
+ virtual bool exists() = 0;
+
+ /** Delete this folder.
+ * The folder should be closed before attempting to delete it.
+ *
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual void destroy() = 0;
+
+ /** Test whether this folder is open.
+ *
+ * @return true if the folder is open, false otherwise
+ */
+ virtual bool isOpen() const = 0;
+
+ /** Get a new reference to a message in this folder, given its number.
+ *
+ * @param num message sequence number
+ * @return a new object referencing the specified message
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual shared_ptr <message> getMessage(const size_t num) = 0;
+
+ /** Get new references to messages in this folder, given either their
+ * sequence numbers or UIDs.
+ *
+ * To retrieve messages by their number, use:
+ * \code{.cpp}
+ * // Get messages from sequence number 5 to sequence number 8 (including)
+ * folder->getMessage(vmime::net::messageSet::byNumber(5, 8));
+ *
+ * // Get all messages in the folder, starting from number 42
+ * folder->getMessage(vmime::net::messageSet::byNumber(42, -1));
+ * \endcode
+ * Or, to retrieve messages by their UID, use:
+ * \code{.cpp}
+ * // Get messages from UID 1000 to UID 1042 (including)
+ * folder->getMessage(vmime::net::messageSet::byUID(1000, 1042));
+ *
+ * // Get message with UID 1042
+ * folder->getMessage(vmime::net::messageSet::byUID(1042));
+ *
+ * // Get all messages in the folder, starting from UID 1000
+ * folder->getMessage(vmime::net::messageSet::byUID(1000, "*"));
+ * \endcode
+ *
+ * @param msgs index set of messages to retrieve
+ * @return new objects referencing the specified messages
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual std::vector <shared_ptr <message> > getMessages(const messageSet& msgs) = 0;
+
+ /** Return the number of messages in this folder.
+ *
+ * @return number of messages in the folder
+ */
+ virtual size_t getMessageCount() = 0;
+
+ /** Get a new reference to a sub-folder in this folder.
+ *
+ * @param name sub-folder name
+ * @return a new object referencing the specified folder
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual shared_ptr <folder> getFolder(const folder::path::component& name) = 0;
+
+ /** Get the list of all sub-folders in this folder.
+ *
+ * @param recursive if set to true, all the descendant are returned.
+ * If set to false, only the direct children are returned.
+ * @return list of sub-folders
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual std::vector <shared_ptr <folder> > getFolders(const bool recursive = false) = 0;
+
+ /** Rename (move) this folder to another location.
+ *
+ * @param newPath new path of the folder
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual void rename(const folder::path& newPath) = 0;
+
+ /** Remove one or more messages from this folder.
+ *
+ * @param msgs index set of messages to delete
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual void deleteMessages(const messageSet& msgs) = 0;
+
+ /** Change the flags for one or more messages in this folder.
+ *
+ * @param msgs index set of messages on which to set the flags
+ * @param flags set of flags (see message::Flags)
+ * @param mode indicate how to treat old and new flags (see message::FlagsModes)
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual void setMessageFlags(const messageSet& msgs, const int flags, const int mode = message::FLAG_MODE_SET) = 0;
+
+ /** Add a message to this folder.
+ *
+ * @param msg message to add (data: header + body)
+ * @param flags flags for the new message (if -1, default flags are used)
+ * @param date date/time for the new message (if NULL, the current time is used)
+ * @param progress progress listener, or NULL if not used
+ * @return a message set containing the number or UID of the new message, or
+ * an empty set if the information could not be obtained (ie. the server does not
+ * support returning the number or UID of an added message)
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual messageSet addMessage(
+ const shared_ptr <vmime::message>& msg,
+ const int flags = -1,
+ vmime::datetime* date = NULL,
+ utility::progressListener* progress = NULL
+ ) = 0;
+
+ /** Add a message to this folder.
+ *
+ * @param is message to add (data: header + body)
+ * @param size size of the message to add (in bytes)
+ * @param flags flags for the new message (if -1, default flags are used)
+ * @param date date/time for the new message (if NULL, the current time is used)
+ * @param progress progress listener, or NULL if not used
+ * @return a message set containing the number or UID of the new message, or
+ * an empty set if the information could not be obtained (ie. the server does not
+ * support returning the number or UID of an added message)
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual messageSet addMessage(
+ utility::inputStream& is,
+ const size_t size,
+ const int flags = -1,
+ vmime::datetime* date = NULL,
+ utility::progressListener* progress = NULL
+ ) = 0;
+
+ /** Copy messages from this folder to another folder.
+ *
+ * @param dest destination folder path
+ * @param msgs index set of messages to copy
+ * @return a message set containing the number(s) or UID(s) of the copied message(s),
+ * or an empty set if the information could not be obtained (ie. the server does not
+ * support returning the number or UID of a copied message)
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual messageSet copyMessages(
+ const folder::path& dest,
+ const messageSet& msgs
+ ) = 0;
+
+ /** Request folder status without opening it.
+ *
+ * \deprecated Use the new getStatus() method
+ *
+ * @param count will receive the number of messages in the folder
+ * @param unseen will receive the number of unseen messages in the folder
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual void status(size_t& count, size_t& unseen) = 0;
+
+ /** Request folder status without opening it.
+ *
+ * @return current folder status
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual shared_ptr <folderStatus> getStatus() = 0;
+
+ /** Expunge deleted messages.
+ *
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual void expunge() = 0;
+
+ /** Return a new folder object referencing the parent folder of this folder.
+ *
+ * @return parent folder object
+ */
+ virtual shared_ptr <folder> getParent() = 0;
+
+ /** Return a reference to the store to which this folder belongs.
+ *
+ * @return the store object to which this folder is attached
+ */
+ virtual shared_ptr <const store> getStore() const = 0;
+
+ /** Return a reference to the store to which this folder belongs.
+ *
+ * @return the store object to which this folder is attached
+ */
+ virtual shared_ptr <store> getStore() = 0;
+
+ /** Fetch objects for the specified messages.
+ *
+ * @param msg list of message sequence numbers
+ * @param attribs set of attributes to fetch
+ * @param progress progress listener, or NULL if not used
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual void fetchMessages(
+ std::vector <shared_ptr <message> >& msg,
+ const fetchAttributes& attribs,
+ utility::progressListener* progress = NULL
+ ) = 0;
+
+ /** Fetch objects for the specified message.
+ *
+ * @param msg the message
+ * @param attribs set of attributes to fetch
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual void fetchMessage(
+ const shared_ptr <message>& msg,
+ const fetchAttributes& attribs
+ ) = 0;
+
+ /** Get new references to messages in this folder, given either their
+ * sequence numbers or UIDs, and fetch objects for them at the same time.
+ *
+ * @param msgs index set of messages to retrieve
+ * @param attribs set of attributes to fetch
+ * @return new objects referencing the specified messages
+ * @throw exceptions::net_exception if an error occurs
+ * @see folder::getMessages()
+ * @see folder::fetchMessages()
+ */
+ virtual std::vector <shared_ptr <message> > getAndFetchMessages(
+ const messageSet& msgs,
+ const fetchAttributes& attribs
+ ) = 0;
+
+ /** Return the list of fetchable objects supported by
+ * the underlying protocol (see folder::fetchAttributes).
+ *
+ * @return list of supported fetchable objects
+ */
+ virtual int getFetchCapabilities() const = 0;
+
+ /** Return the sequence numbers of messages whose UID equal or greater than
+ * the specified UID.
+ *
+ * @param uid the uid of the first message
+ * @throw exceptions::net_exception if an error occurs
+ */
+ virtual std::vector <size_t> getMessageNumbersStartingOnUID(const message::uid& uid) = 0;
+
+ // Event listeners
+ void addMessageChangedListener(events::messageChangedListener* l);
+ void removeMessageChangedListener(events::messageChangedListener* l);
+
+ void addMessageCountListener(events::messageCountListener* l);
+ void removeMessageCountListener(events::messageCountListener* l);
+
+ void addFolderListener(events::folderListener* l);
+ void removeFolderListener(events::folderListener* l);
+
+protected:
+
+ void notifyMessageChanged(const shared_ptr <events::messageChangedEvent>& event);
+ void notifyMessageCount(const shared_ptr <events::messageCountEvent>& event);
+ void notifyFolder(const shared_ptr <events::folderEvent>& event);
+ void notifyEvent(const shared_ptr <events::event>& event);
+
+private:
+
+ std::list <events::messageChangedListener*> m_messageChangedListeners;
+ std::list <events::messageCountListener*> m_messageCountListeners;
+ std::list <events::folderListener*> m_folderListeners;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_FOLDER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/folderAttributes.cpp b/vmime-master/src/vmime/net/folderAttributes.cpp
new file mode 100644
index 0000000..107007c
--- /dev/null
+++ b/vmime-master/src/vmime/net/folderAttributes.cpp
@@ -0,0 +1,122 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/folderAttributes.hpp"
+
+#include <algorithm>
+
+
+namespace vmime {
+namespace net {
+
+
+folderAttributes::folderAttributes()
+ : m_type(TYPE_CONTAINS_FOLDERS | TYPE_CONTAINS_MESSAGES),
+ m_flags(0),
+ m_specialUse(SPECIALUSE_NONE) {
+
+}
+
+
+folderAttributes::folderAttributes(const folderAttributes& attribs)
+ : object(),
+ m_type(attribs.m_type),
+ m_flags(attribs.m_flags),
+ m_userFlags(attribs.m_userFlags),
+ m_specialUse(attribs.m_specialUse) {
+
+}
+
+
+int folderAttributes::getType() const {
+
+ return m_type;
+}
+
+
+void folderAttributes::setType(const int type) {
+
+ m_type = type;
+}
+
+
+int folderAttributes::getSpecialUse() const {
+
+ return m_specialUse;
+}
+
+
+void folderAttributes::setSpecialUse(const int use) {
+
+ m_specialUse = use;
+}
+
+
+int folderAttributes::getFlags() const {
+
+ return m_flags;
+}
+
+
+void folderAttributes::setFlags(const int flags) {
+
+ m_flags = flags;
+}
+
+
+bool folderAttributes::hasFlag(const int flag) {
+
+ return (m_flags & flag) != 0;
+}
+
+
+const std::vector <string> folderAttributes::getUserFlags() const {
+
+ return m_userFlags;
+}
+
+
+void folderAttributes::setUserFlags(const std::vector <string>& flags) {
+
+ m_userFlags = flags;
+}
+
+
+bool folderAttributes::hasUserFlag(const string& flag) {
+
+ return std::find(m_userFlags.begin(), m_userFlags.end(), flag) != m_userFlags.end();
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
diff --git a/vmime-master/src/vmime/net/folderAttributes.hpp b/vmime-master/src/vmime/net/folderAttributes.hpp
new file mode 100644
index 0000000..715b72a
--- /dev/null
+++ b/vmime-master/src/vmime/net/folderAttributes.hpp
@@ -0,0 +1,177 @@
+//
+// 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_NET_FOLDERATTRIBUTES_HPP_INCLUDED
+#define VMIME_NET_FOLDERATTRIBUTES_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include <vector>
+
+#include "vmime/types.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+/** Holds a set of attributes for a folder.
+ */
+class VMIME_EXPORT folderAttributes : public object {
+
+public:
+
+ /** Folder types.
+ */
+ enum Types {
+ TYPE_CONTAINS_FOLDERS = (1 << 0), /**< Folder can contain folders. */
+ TYPE_CONTAINS_MESSAGES = (1 << 1) /**< Folder can contain messages. */
+ };
+
+ /** Folder flags.
+ */
+ enum Flags {
+ FLAG_HAS_CHILDREN = (1 << 0), /**< Folder contains subfolders. */
+ FLAG_NO_OPEN = (1 << 1) /**< Folder cannot be open. */
+ };
+
+ /** Folder special uses.
+ * Not all protocols support this. At the current time, only IMAP supports this,
+ * if the server has the SPECIAL-USE capability.
+ */
+ enum SpecialUses {
+ SPECIALUSE_NONE, /**< User folder, no special use (or unknown). */
+ SPECIALUSE_ALL, /**< Virtual folder containing all messages. */
+ SPECIALUSE_INBOX, /**< Inbox. */
+ SPECIALUSE_ARCHIVE, /**< Folder is used to archives messages (server-dependent). */
+ SPECIALUSE_DRAFTS, /**< Folder is used to hold draft messages - typically, messages
+ that are being composed but have not yet been sent. */
+ SPECIALUSE_FLAGGED, /**< Virtual folder containing all messages which are marked
+ in some way as "important" or "flagged". */
+ SPECIALUSE_JUNK, /**< Folder is used to hold junk mail. */
+ SPECIALUSE_SENT, /**< Folder is is used to hold copies of messages that have
+ been sent. */
+ SPECIALUSE_TRASH, /**< Folder is used to hold messages that have been deleted or
+ marked for deletion (may be a virtual folder). */
+ SPECIALUSE_IMPORTANT /**< Folder contains messages that are likely important to the
+ user. */
+ };
+
+
+ /** Construct a new folderAttributes object with the default set of attributes.
+ */
+ folderAttributes();
+
+ /** Construct a new folderAttributes object by copying an existing object.
+ *
+ * @param attribs object to copy
+ */
+ folderAttributes(const folderAttributes& attribs);
+
+ /** Return the type of the folder.
+ *
+ * @return combination of one ore more folder types (see folderAttributes::Types enum)
+ */
+ int getType() const;
+
+ /** Set the type of the folder.
+ *
+ * @param type combination of one ore more folder types (see folderAttributes::Types enum)
+ */
+ void setType(const int type);
+
+ /** Return the special use of the folder.
+ * Not all protocols support this. At the current time, only IMAP supports this,
+ * if the server has the SPECIAL-USE capability.
+ *
+ * @return a value which indicates a special use (see folderAttributes::SpecialUses enum)
+ */
+ int getSpecialUse() const;
+
+ /** Set the special use of the folder.
+ * Not all protocols support this. At the current time, only IMAP supports this,
+ * if the server has the SPECIAL-USE capability.
+ *
+ * @param use a value which indicates a special use (see folderAttributes::SpecialUses enum)
+ */
+ void setSpecialUse(const int use);
+
+ /** Return the standard (non-user) flags of the folder.
+ *
+ * @return combination of one ore more folder flags (see folderAttributes::Flags enum)
+ */
+ int getFlags() const;
+
+ /** Set the standard (non-user) flags of the folder.
+ *
+ * @param type combination of one ore more folder flags (see folderAttributes::Flags enum)
+ */
+ void setFlags(const int flags);
+
+ /** Return whether the specified folder flag(s) is/are set.
+ *
+ * @param flag combination of one ore more folder flags (see folderAttributes::Flags enum)
+ * @return true if the specified flags are all set, or false otherwise
+ */
+ bool hasFlag(const int flag);
+
+ /** Set the user-defined flags of the folder.
+ *
+ * @return a list of user-defined flags
+ */
+ const std::vector <string> getUserFlags() const;
+
+ /** Set the user-defined flags of the folder.
+ *
+ * @param flags a list of user-defined flags
+ */
+ void setUserFlags(const std::vector <string>& flags);
+
+ /** Return whether the specified user-defined flag is set.
+ *
+ * @return true if the specified flag is set, or false otherwise
+ */
+ bool hasUserFlag(const string& flag);
+
+private:
+
+ int m_type;
+ int m_flags;
+ std::vector <string> m_userFlags;
+ int m_specialUse;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+
+#endif // VMIME_NET_FOLDERATTRIBUTES_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/folderStatus.hpp b/vmime-master/src/vmime/net/folderStatus.hpp
new file mode 100644
index 0000000..fcc4afc
--- /dev/null
+++ b/vmime-master/src/vmime/net/folderStatus.hpp
@@ -0,0 +1,73 @@
+//
+// 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_NET_FOLDERSTATUS_HPP_INCLUDED
+#define VMIME_NET_FOLDERSTATUS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/base.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+/** Holds the status of a mail store folder.
+ */
+class VMIME_EXPORT folderStatus : public object {
+
+public:
+
+ /** Returns the total number of messages in the folder.
+ *
+ * @return number of messages
+ */
+ virtual size_t getMessageCount() const = 0;
+
+ /** Returns the number of unseen messages in the folder.
+ *
+ * @return number of unseen messages
+ */
+ virtual size_t getUnseenCount() const = 0;
+
+ /** Clones this object.
+ *
+ * @return a copy of this object
+ */
+ virtual shared_ptr <folderStatus> clone() const = 0;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_FOLDERSTATUS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/imap/IMAPCommand.cpp b/vmime-master/src/vmime/net/imap/IMAPCommand.cpp
new file mode 100644
index 0000000..8911ed0
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPCommand.cpp
@@ -0,0 +1,437 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPCommand.hpp"
+#include "vmime/net/imap/IMAPConnection.hpp"
+#include "vmime/net/imap/IMAPUtils.hpp"
+
+#include <sstream>
+
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPCommand::IMAPCommand(const string& text, const string& traceText)
+ : m_text(text),
+ m_traceText(traceText) {
+
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::LOGIN(const string& username, const string& password) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "LOGIN " << IMAPUtils::quoteString(username)
+ << " " << IMAPUtils::quoteString(password);
+
+ std::ostringstream trace;
+ trace.imbue(std::locale::classic());
+ trace << "LOGIN {username} {password}";
+
+ return createCommand(cmd.str(), trace.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::AUTHENTICATE(const string& mechName) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "AUTHENTICATE " << mechName;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::AUTHENTICATE(const string& mechName, const string& initialResponse) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "AUTHENTICATE " << mechName << " " << initialResponse;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::LIST(const string& refName, const string& mailboxName) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "LIST " << IMAPUtils::quoteString(refName)
+ << " " << IMAPUtils::quoteString(mailboxName);
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::SELECT(
+ const bool readOnly,
+ const string& mailboxName,
+ const std::vector <string>& params
+) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+
+ if (readOnly) {
+ cmd << "EXAMINE ";
+ } else {
+ cmd << "SELECT ";
+ }
+
+ cmd << IMAPUtils::quoteString(mailboxName);
+
+ if (!params.empty()) {
+
+ cmd << " (";
+
+ for (size_t i = 0, n = params.size() ; i < n ; ++i) {
+ if (i != 0) cmd << " ";
+ cmd << params[i];
+ }
+
+ cmd << ")";
+ }
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::STATUS(
+ const string& mailboxName,
+ const std::vector <string>& attribs
+) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "STATUS " << IMAPUtils::quoteString(mailboxName);
+
+ cmd << " (";
+
+ for (size_t i = 0, n = attribs.size() ; i < n ; ++i) {
+ if (i != 0) cmd << " ";
+ cmd << attribs[i];
+ }
+
+ cmd << ")";
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::CREATE(
+ const string& mailboxName,
+ const std::vector <string>& params
+) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "CREATE " << IMAPUtils::quoteString(mailboxName);
+
+ if (!params.empty()) {
+
+ cmd << " (";
+
+ for (size_t i = 0, n = params.size() ; i < n ; ++i) {
+ if (i != 0) cmd << " ";
+ cmd << params[i];
+ }
+
+ cmd << ")";
+ }
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::DELETE(const string& mailboxName) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "DELETE " << IMAPUtils::quoteString(mailboxName);
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::RENAME(
+ const string& mailboxName,
+ const string& newMailboxName
+) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "RENAME " << IMAPUtils::quoteString(mailboxName)
+ << " " << IMAPUtils::quoteString(newMailboxName);
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::FETCH(
+ const messageSet& msgs,
+ const std::vector <string>& params
+) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+
+ if (msgs.isUIDSet()) {
+ cmd << "UID FETCH " << IMAPUtils::messageSetToSequenceSet(msgs);
+ } else {
+ cmd << "FETCH " << IMAPUtils::messageSetToSequenceSet(msgs);
+ }
+
+ if (params.size() == 1) {
+
+ cmd << " " << params[0];
+
+ } else {
+
+ cmd << " (";
+
+ for (size_t i = 0, n = params.size() ; i < n ; ++i) {
+ if (i != 0) cmd << " ";
+ cmd << params[i];
+ }
+
+ cmd << ")";
+ }
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::STORE(
+ const messageSet& msgs,
+ const int mode,
+ const std::vector <string>& flags
+) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+
+ if (msgs.isUIDSet()) {
+ cmd << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs);
+ } else {
+ cmd << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs);
+ }
+
+ if (mode == message::FLAG_MODE_ADD) {
+ cmd << " +FLAGS ";
+ } else if (mode == message::FLAG_MODE_REMOVE) {
+ cmd << " -FLAGS ";
+ } else { // if (mode == message::FLAG_MODE_SET)
+ cmd << " FLAGS ";
+ }
+
+ cmd << "(";
+
+ for (size_t i = 0, n = flags.size() ; i < n ; ++i) {
+ if (i != 0) cmd << " ";
+ cmd << flags[i];
+ }
+
+ cmd << ")";
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::APPEND(
+ const string& mailboxName,
+ const std::vector <string>& flags,
+ vmime::datetime* date,
+ const size_t size
+) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "APPEND " << IMAPUtils::quoteString(mailboxName);
+
+ if (!flags.empty()) {
+
+ cmd << " (";
+
+ for (size_t i = 0, n = flags.size() ; i < n ; ++i) {
+ if (i != 0) cmd << " ";
+ cmd << flags[i];
+ }
+
+ cmd << ")";
+ }
+
+ if (date != NULL) {
+ cmd << " " << IMAPUtils::dateTime(*date);
+ }
+
+ cmd << " {" << size << "}";
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::COPY(
+ const messageSet& msgs,
+ const string& mailboxName
+) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+
+ if (msgs.isUIDSet()) {
+ cmd << "UID COPY " << IMAPUtils::messageSetToSequenceSet(msgs);
+ } else {
+ cmd << "COPY " << IMAPUtils::messageSetToSequenceSet(msgs);
+ }
+
+ cmd << " " << IMAPUtils::quoteString(mailboxName);
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::SEARCH(
+ const std::vector <string>& keys,
+ const vmime::charset* charset
+) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "SEARCH";
+
+ if (charset) {
+ cmd << " CHARSET " << charset->getName();
+ }
+
+ for (size_t i = 0, n = keys.size() ; i < n ; ++i) {
+ cmd << " " << keys[i];
+ }
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::STARTTLS() {
+
+ return createCommand("STARTTLS");
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::CAPABILITY() {
+
+ return createCommand("CAPABILITY");
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::NOOP() {
+
+ return createCommand("NOOP");
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::EXPUNGE() {
+
+ return createCommand("EXPUNGE");
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::CLOSE() {
+
+ return createCommand("CLOSE");
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::LOGOUT() {
+
+ return createCommand("LOGOUT");
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPCommand::createCommand(
+ const string& text,
+ const string& traceText
+) {
+
+ if (traceText.empty()) {
+ return shared_ptr <IMAPCommand>(new IMAPCommand(text, text));
+ } else {
+ return shared_ptr <IMAPCommand>(new IMAPCommand(text, traceText));
+ }
+}
+
+
+const string IMAPCommand::getText() const {
+
+ return m_text;
+}
+
+
+const string IMAPCommand::getTraceText() const {
+
+ return m_traceText;
+}
+
+
+void IMAPCommand::send(const shared_ptr <IMAPConnection>& conn) {
+
+ conn->sendCommand(dynamicCast <IMAPCommand>(shared_from_this()));
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
diff --git a/vmime-master/src/vmime/net/imap/IMAPCommand.hpp b/vmime-master/src/vmime/net/imap/IMAPCommand.hpp
new file mode 100644
index 0000000..4915a57
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPCommand.hpp
@@ -0,0 +1,124 @@
+//
+// 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_NET_IMAP_IMAPCOMMAND_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPCOMMAND_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/object.hpp"
+#include "vmime/base.hpp"
+#include "vmime/dateTime.hpp"
+
+#include "vmime/net/messageSet.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class IMAPConnection;
+
+
+/** An IMAP command that will be sent to the server.
+ */
+class VMIME_EXPORT IMAPCommand : public object, public enable_shared_from_this <IMAPCommand> {
+
+public:
+
+ static shared_ptr <IMAPCommand> LOGIN(const string& username, const string& password);
+ static shared_ptr <IMAPCommand> AUTHENTICATE(const string& mechName);
+ static shared_ptr <IMAPCommand> AUTHENTICATE(const string& mechName, const string& initialResponse);
+ static shared_ptr <IMAPCommand> LIST(const string& refName, const string& mailboxName);
+ static shared_ptr <IMAPCommand> SELECT(const bool readOnly, const string& mailboxName, const std::vector <string>& params);
+ static shared_ptr <IMAPCommand> STATUS(const string& mailboxName, const std::vector <string>& attribs);
+ static shared_ptr <IMAPCommand> CREATE(const string& mailboxName, const std::vector <string>& params);
+ static shared_ptr <IMAPCommand> DELETE(const string& mailboxName);
+ static shared_ptr <IMAPCommand> RENAME(const string& mailboxName, const string& newMailboxName);
+ static shared_ptr <IMAPCommand> FETCH(const messageSet& msgs, const std::vector <string>& params);
+ static shared_ptr <IMAPCommand> STORE(const messageSet& msgs, const int mode, const std::vector <string>& flags);
+ static shared_ptr <IMAPCommand> APPEND(const string& mailboxName, const std::vector <string>& flags, vmime::datetime* date, const size_t size);
+ static shared_ptr <IMAPCommand> COPY(const messageSet& msgs, const string& mailboxName);
+ static shared_ptr <IMAPCommand> SEARCH(const std::vector <string>& keys, const vmime::charset* charset);
+ static shared_ptr <IMAPCommand> STARTTLS();
+ static shared_ptr <IMAPCommand> CAPABILITY();
+ static shared_ptr <IMAPCommand> NOOP();
+ static shared_ptr <IMAPCommand> EXPUNGE();
+ static shared_ptr <IMAPCommand> CLOSE();
+ static shared_ptr <IMAPCommand> LOGOUT();
+
+ /** Creates a new IMAP command with the specified text.
+ *
+ * @param text command text
+ * @param traceText trace text (if empty, command text is used)
+ * @return a new IMAPCommand object
+ */
+ static shared_ptr <IMAPCommand> createCommand(const string& text, const string& traceText = "");
+
+ /** Sends this command over the specified connection.
+ *
+ * @param conn connection onto which the command will be sent
+ */
+ virtual void send(const shared_ptr <IMAPConnection>& conn);
+
+ /** Returns the full text of the command, including command name
+ * and parameters (if any). This is the text that will be sent
+ * to the server.
+ *
+ * @return command text (eg. "LOGIN myusername mypassword")
+ */
+ virtual const string getText() const;
+
+ /** Returns the full text of the command, suitable for outputing
+ * to the tracer.
+ *
+ * @return trace text (eg. "LOGIN {username} {password}")
+ */
+ virtual const string getTraceText() const;
+
+protected:
+
+ IMAPCommand(const string& text, const string& traceText);
+ IMAPCommand(const IMAPCommand&);
+
+private:
+
+ string m_text;
+ string m_traceText;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPCOMMAND_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/imap/IMAPConnection.cpp b/vmime-master/src/vmime/net/imap/IMAPConnection.cpp
new file mode 100644
index 0000000..df3da1c
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPConnection.cpp
@@ -0,0 +1,886 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPTag.hpp"
+#include "vmime/net/imap/IMAPConnection.hpp"
+#include "vmime/net/imap/IMAPUtils.hpp"
+#include "vmime/net/imap/IMAPStore.hpp"
+#include "vmime/net/imap/IMAPCommand.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/platform.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include "vmime/net/defaultConnectionInfos.hpp"
+
+#if VMIME_HAVE_SASL_SUPPORT
+ #include "vmime/security/sasl/SASLContext.hpp"
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+#if VMIME_HAVE_TLS_SUPPORT
+ #include "vmime/net/tls/TLSSession.hpp"
+ #include "vmime/net/tls/TLSSecuredConnectionInfos.hpp"
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+#include <sstream>
+
+
+// Helpers for service properties
+#define GET_PROPERTY(type, prop) \
+ (m_store.lock()->getInfos().getPropertyValue <type>(getSession(), \
+ dynamic_cast <const IMAPServiceInfos&>(m_store.lock()->getInfos()).getProperties().prop))
+#define HAS_PROPERTY(prop) \
+ (m_store.lock()->getInfos().hasProperty(getSession(), \
+ dynamic_cast <const IMAPServiceInfos&>(m_store.lock()->getInfos()).getProperties().prop))
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPConnection::IMAPConnection(
+ const shared_ptr <IMAPStore>& store,
+ const shared_ptr <security::authenticator>& auth
+)
+ : m_store(store),
+ m_auth(auth),
+ m_socket(null),
+ m_parser(null),
+ m_tag(null),
+ m_hierarchySeparator('\0'),
+ m_state(STATE_NONE),
+ m_timeoutHandler(null),
+ m_secured(false),
+ m_firstTag(true),
+ m_capabilitiesFetched(false),
+ m_noModSeq(false) {
+
+ static int connectionId = 0;
+
+ m_tag = make_shared <IMAPTag>();
+
+ if (store->getTracerFactory()) {
+ m_tracer = store->getTracerFactory()->create(store, ++connectionId);
+ }
+
+ m_parser = make_shared <IMAPParser>();
+ m_parser->setTracer(m_tracer);
+}
+
+
+IMAPConnection::~IMAPConnection() {
+
+ try {
+
+ if (isConnected()) {
+ disconnect();
+ } else if (m_socket) {
+ internalDisconnect();
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+void IMAPConnection::connect() {
+
+ if (isConnected()) {
+ throw exceptions::already_connected();
+ }
+
+ m_state = STATE_NONE;
+ m_hierarchySeparator = '\0';
+
+ const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS);
+ const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT);
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ // Create the time-out handler
+ if (store->getTimeoutHandlerFactory()) {
+ m_timeoutHandler = store->getTimeoutHandlerFactory()->create();
+ }
+
+ // Create and connect the socket
+ m_socket = store->getSocketFactory()->create(m_timeoutHandler);
+ m_socket->setTracer(m_tracer);
+
+#if VMIME_HAVE_TLS_SUPPORT
+ if (store->isIMAPS()) { // dedicated port/IMAPS
+
+ shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create
+ (store->getCertificateVerifier(),
+ store->getSession()->getTLSProperties());
+
+ shared_ptr <tls::TLSSocket> tlsSocket =
+ tlsSession->getSocket(m_socket);
+
+ m_socket = tlsSocket;
+
+ m_secured = true;
+ m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>(address, port, tlsSession, tlsSocket);
+
+ } else
+#endif // VMIME_HAVE_TLS_SUPPORT
+ {
+ m_cntInfos = make_shared <defaultConnectionInfos>(address, port);
+ }
+
+ m_socket->connect(address, port);
+
+
+ m_parser->setSocket(m_socket);
+ m_parser->setTimeoutHandler(m_timeoutHandler);
+
+
+ setState(STATE_NON_AUTHENTICATED);
+
+
+ // Connection greeting
+ //
+ // eg: C: <connection to server>
+ // --- S: * OK mydomain.org IMAP4rev1 v12.256 server ready
+
+ scoped_ptr <IMAPParser::greeting> greet(m_parser->readGreeting());
+ bool needAuth = false;
+
+ if (greet->resp_cond_bye) {
+
+ internalDisconnect();
+ throw exceptions::connection_greeting_error(greet->getErrorLog());
+
+ } else if (greet->resp_cond_auth->condition != IMAPParser::resp_cond_auth::PREAUTH) {
+
+ needAuth = true;
+ }
+
+ if (greet->resp_cond_auth->resp_text->resp_text_code &&
+ greet->resp_cond_auth->resp_text->resp_text_code->capability_data) {
+
+ processCapabilityResponseData(greet->resp_cond_auth->resp_text->resp_text_code->capability_data.get());
+ }
+
+#if VMIME_HAVE_TLS_SUPPORT
+ // Setup secured connection, if requested
+ const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS)
+ && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS);
+ const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED)
+ && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED);
+
+ if (!store->isIMAPS() && tls) { // only if not IMAPS
+
+ try {
+
+ startTLS();
+
+ // Non-fatal error
+ } catch (exceptions::command_error&) {
+
+ if (tlsRequired) {
+ m_state = STATE_NONE;
+ throw;
+ } else {
+ // TLS is not required, so don't bother
+ }
+
+ // Fatal error
+ } catch (...) {
+
+ m_state = STATE_NONE;
+ throw;
+ }
+ }
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ // Authentication
+ if (needAuth) {
+
+ try {
+
+ authenticate();
+
+ } catch (...) {
+
+ m_state = STATE_NONE;
+ throw;
+ }
+ }
+
+ // Get the hierarchy separator character
+ initHierarchySeparator();
+
+ // Switch to state "Authenticated"
+ setState(STATE_AUTHENTICATED);
+}
+
+
+void IMAPConnection::authenticate() {
+
+ getAuthenticator()->setService(m_store.lock());
+
+#if VMIME_HAVE_SASL_SUPPORT
+ // First, try SASL authentication
+ if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) {
+
+ try {
+
+ authenticateSASL();
+ return;
+
+ } catch (exceptions::authentication_error&) {
+
+ if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) {
+
+ // Can't fallback on normal authentication
+ internalDisconnect();
+ throw;
+
+ } else {
+
+ // Ignore, will try normal authentication
+ }
+
+ } catch (exception&) {
+
+ internalDisconnect();
+ throw;
+ }
+ }
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ // Normal authentication
+ const string username = getAuthenticator()->getUsername();
+ const string password = getAuthenticator()->getPassword();
+
+ shared_ptr <IMAPConnection> conn = dynamicCast <IMAPConnection>(shared_from_this());
+ IMAPCommand::LOGIN(username, password)->send(conn);
+
+ scoped_ptr <IMAPParser::response> resp(m_parser->readResponse(*m_tag));
+
+ if (resp->isBad()) {
+
+ internalDisconnect();
+ throw exceptions::command_error("LOGIN", resp->getErrorLog());
+
+ } else if (resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ internalDisconnect();
+ throw exceptions::authentication_error(resp->getErrorLog());
+ }
+
+ // Server capabilities may change when logged in
+ if (!processCapabilityResponseData(resp.get())) {
+ invalidateCapabilities();
+ }
+}
+
+
+#if VMIME_HAVE_SASL_SUPPORT
+
+void IMAPConnection::authenticateSASL() {
+
+ if (!dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())) {
+ throw exceptions::authentication_error("No SASL authenticator available.");
+ }
+
+ const std::vector <string> capa = getCapabilities();
+ std::vector <string> saslMechs;
+
+ for (unsigned int i = 0 ; i < capa.size() ; ++i) {
+
+ const string& x = capa[i];
+
+ if (x.length() > 5 &&
+ (x[0] == 'A' || x[0] == 'a') &&
+ (x[1] == 'U' || x[1] == 'u') &&
+ (x[2] == 'T' || x[2] == 't') &&
+ (x[3] == 'H' || x[3] == 'h') &&
+ x[4] == '=') {
+
+ saslMechs.push_back(string(x.begin() + 5, x.end()));
+ }
+ }
+
+ if (saslMechs.empty()) {
+ throw exceptions::authentication_error("No SASL mechanism available.");
+ }
+
+ std::vector <shared_ptr <security::sasl::SASLMechanism> > mechList;
+
+ shared_ptr <security::sasl::SASLContext> saslContext =
+ security::sasl::SASLContext::create();
+
+ for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) {
+
+ try {
+ mechList.push_back(saslContext->createMechanism(saslMechs[i]));
+ } catch (exceptions::no_such_mechanism&) {
+ // Ignore mechanism
+ }
+ }
+
+ if (mechList.empty()) {
+ throw exceptions::authentication_error("No SASL mechanism available.");
+ }
+
+ // Try to suggest a mechanism among all those supported
+ shared_ptr <security::sasl::SASLMechanism> suggestedMech =
+ saslContext->suggestMechanism(mechList);
+
+ if (!suggestedMech) {
+ throw exceptions::authentication_error("Unable to suggest SASL mechanism.");
+ }
+
+ // Allow application to choose which mechanisms to use
+ mechList = dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())->
+ getAcceptableMechanisms(mechList, suggestedMech);
+
+ if (mechList.empty()) {
+ throw exceptions::authentication_error("No SASL mechanism available.");
+ }
+
+ // Try each mechanism in the list in turn
+ for (unsigned int i = 0 ; i < mechList.size() ; ++i) {
+
+ shared_ptr <security::sasl::SASLMechanism> mech = mechList[i];
+
+ shared_ptr <security::sasl::SASLSession> saslSession =
+ saslContext->createSession("imap", getAuthenticator(), mech);
+
+ saslSession->init();
+
+ shared_ptr <IMAPCommand> authCmd;
+
+ if (saslSession->getMechanism()->hasInitialResponse()) {
+
+ byte_t* initialResp = 0;
+ size_t initialRespLen = 0;
+
+ saslSession->evaluateChallenge(NULL, 0, &initialResp, &initialRespLen);
+
+ string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen));
+ delete [] initialResp;
+
+ if (encodedInitialResp.empty()) {
+ authCmd = IMAPCommand::AUTHENTICATE(mech->getName(), "=");
+ } else {
+ authCmd = IMAPCommand::AUTHENTICATE(mech->getName(), encodedInitialResp);
+ }
+
+ } else {
+
+ authCmd = IMAPCommand::AUTHENTICATE(mech->getName());
+ }
+
+ authCmd->send(dynamicCast <IMAPConnection>(shared_from_this()));
+
+ for (bool cont = true ; cont ; ) {
+
+ scoped_ptr <IMAPParser::response> resp(m_parser->readResponse(*m_tag));
+
+ if (resp->response_done &&
+ resp->response_done->response_tagged &&
+ resp->response_done->response_tagged->resp_cond_state->
+ status == IMAPParser::resp_cond_state::OK) {
+
+ m_socket = saslSession->getSecuredSocket(m_socket);
+ return;
+
+ } else {
+
+ string response;
+ bool hasResponse = false;
+
+ for (auto &respData : resp->continue_req_or_response_data) {
+
+ if (respData->continue_req) {
+
+ response = respData->continue_req->resp_text->text;
+ hasResponse = true;
+ break;
+ }
+ }
+
+ if (!hasResponse) {
+ cont = false;
+ continue;
+ }
+
+ byte_t* challenge = 0;
+ size_t challengeLen = 0;
+
+ byte_t* resp = 0;
+ size_t respLen = 0;
+
+ try {
+
+ // Extract challenge
+ saslContext->decodeB64(response, &challenge, &challengeLen);
+
+ // Prepare response
+ saslSession->evaluateChallenge
+ (challenge, challengeLen, &resp, &respLen);
+
+ // Send response
+ const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n";
+ sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length());
+
+ if (m_tracer) {
+ m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange");
+ }
+
+ // Server capabilities may change when logged in
+ invalidateCapabilities();
+
+ } catch (exceptions::sasl_exception& e) {
+
+ if (challenge) {
+ delete [] challenge;
+ challenge = NULL;
+ }
+
+ if (resp) {
+ delete [] resp;
+ resp = NULL;
+ }
+
+ // Cancel SASL exchange
+ sendRaw(utility::stringUtils::bytesFromString("*\r\n"), 3);
+
+ if (m_tracer) {
+ m_tracer->traceSend("*");
+ }
+
+ } catch (...) {
+
+ if (challenge) {
+ delete [] challenge;
+ }
+
+ if (resp) {
+ delete [] resp;
+ }
+
+ throw;
+ }
+
+ if (challenge) {
+ delete [] challenge;
+ }
+
+ if (resp) {
+ delete [] resp;
+ }
+ }
+ }
+ }
+
+ throw exceptions::authentication_error("Could not authenticate using SASL: all mechanisms failed.");
+}
+
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+void IMAPConnection::startTLS() {
+
+ try {
+
+ IMAPCommand::STARTTLS()->send(dynamicCast <IMAPConnection>(shared_from_this()));
+
+ scoped_ptr <IMAPParser::response> resp(m_parser->readResponse(*m_tag));
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("STARTTLS", resp->getErrorLog(), "bad response");
+ }
+
+ shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create(
+ m_store.lock()->getCertificateVerifier(),
+ m_store.lock()->getSession()->getTLSProperties()
+ );
+
+ shared_ptr <tls::TLSSocket> tlsSocket = tlsSession->getSocket(m_socket);
+
+ tlsSocket->handshake();
+
+ m_socket = tlsSocket;
+ m_parser->setSocket(m_socket);
+
+ m_secured = true;
+ m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>(
+ m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket
+ );
+
+ // " Once TLS has been started, the client MUST discard cached
+ // information about server capabilities and SHOULD re-issue the
+ // CAPABILITY command. This is necessary to protect against
+ // man-in-the-middle attacks which alter the capabilities list prior
+ // to STARTTLS. " (RFC-2595)
+ invalidateCapabilities();
+
+ } catch (exceptions::command_error&) {
+
+ // Non-fatal error
+ throw;
+
+ } catch (exception&) {
+
+ // Fatal error
+ internalDisconnect();
+ throw;
+ }
+}
+
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+const std::vector <string> IMAPConnection::getCapabilities() {
+
+ if (!m_capabilitiesFetched) {
+ fetchCapabilities();
+ }
+
+ return m_capabilities;
+}
+
+
+bool IMAPConnection::hasCapability(const string& capa) {
+
+ if (!m_capabilitiesFetched) {
+ fetchCapabilities();
+ }
+
+ const string normCapa = utility::stringUtils::toUpper(capa);
+
+ for (size_t i = 0, n = m_capabilities.size() ; i < n ; ++i) {
+
+ if (m_capabilities[i] == normCapa) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+bool IMAPConnection::hasCapability(const string& capa) const {
+
+ const string normCapa = utility::stringUtils::toUpper(capa);
+
+ for (size_t i = 0, n = m_capabilities.size() ; i < n ; ++i) {
+
+ if (m_capabilities[i] == normCapa)
+ return true;
+ }
+
+ return false;
+}
+
+
+void IMAPConnection::invalidateCapabilities() {
+
+ m_capabilities.clear();
+ m_capabilitiesFetched = false;
+}
+
+
+void IMAPConnection::fetchCapabilities() {
+
+ IMAPCommand::CAPABILITY()->send(dynamicCast <IMAPConnection>(shared_from_this()));
+
+ scoped_ptr <IMAPParser::response> resp(m_parser->readResponse(*m_tag));
+
+ if (resp->response_done->response_tagged->
+ resp_cond_state->status == IMAPParser::resp_cond_state::OK) {
+
+ processCapabilityResponseData(resp.get());
+ }
+}
+
+
+bool IMAPConnection::processCapabilityResponseData(const IMAPParser::response* resp) {
+
+ for (auto &respData : resp->continue_req_or_response_data) {
+
+ if (respData->response_data == NULL) {
+ continue;
+ }
+
+ auto &capaData = respData->response_data->capability_data;
+
+ if (!capaData) {
+ continue;
+ }
+
+ processCapabilityResponseData(capaData.get());
+ return true;
+ }
+
+ return false;
+}
+
+
+void IMAPConnection::processCapabilityResponseData(const IMAPParser::capability_data* capaData) {
+
+ std::vector <string> res;
+
+ for (auto &cap : capaData->capabilities) {
+
+ if (cap->auth_type) {
+ res.push_back("AUTH=" + cap->auth_type->name);
+ } else {
+ res.push_back(utility::stringUtils::toUpper(cap->atom->value));
+ }
+ }
+
+ m_capabilities = res;
+ m_capabilitiesFetched = true;
+}
+
+
+shared_ptr <security::authenticator> IMAPConnection::getAuthenticator() {
+
+ return m_auth;
+}
+
+
+bool IMAPConnection::isConnected() const {
+
+ return m_socket
+ && m_socket->isConnected()
+ && (m_state == STATE_AUTHENTICATED || m_state == STATE_SELECTED);
+}
+
+
+bool IMAPConnection::isSecuredConnection() const {
+
+ return m_secured;
+}
+
+
+shared_ptr <connectionInfos> IMAPConnection::getConnectionInfos() const {
+
+ return m_cntInfos;
+}
+
+
+void IMAPConnection::disconnect() {
+
+ if (!isConnected()) {
+ throw exceptions::not_connected();
+ }
+
+ internalDisconnect();
+}
+
+
+void IMAPConnection::internalDisconnect() {
+
+ if (isConnected()) {
+
+ IMAPCommand::LOGOUT()->send(dynamicCast <IMAPConnection>(shared_from_this()));
+
+ m_socket->disconnect();
+ m_socket = null;
+ }
+
+ m_timeoutHandler = null;
+
+ m_state = STATE_LOGOUT;
+
+ m_secured = false;
+ m_cntInfos = null;
+}
+
+
+void IMAPConnection::initHierarchySeparator() {
+
+ IMAPCommand::LIST("", "")->send(dynamicCast <IMAPConnection>(shared_from_this()));
+
+ scoped_ptr <IMAPParser::response> resp(m_parser->readResponse(*m_tag));
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ internalDisconnect();
+ throw exceptions::command_error("LIST", resp->getErrorLog(), "bad response");
+ }
+
+ const auto& respDataList = resp->continue_req_or_response_data;
+
+ bool found = false;
+
+ for (unsigned int i = 0 ; !found && i < respDataList.size() ; ++i) {
+
+ if (!respDataList[i]->response_data) {
+ continue;
+ }
+
+ auto &mailboxData = respDataList[i]->response_data->mailbox_data;
+
+ if (!mailboxData || mailboxData->type != IMAPParser::mailbox_data::LIST) {
+ continue;
+ }
+
+ if (mailboxData->mailbox_list->quoted_char != '\0') {
+ m_hierarchySeparator = mailboxData->mailbox_list->quoted_char;
+ found = true;
+ }
+ }
+
+ if (!found) { // default
+ m_hierarchySeparator = '/';
+ }
+}
+
+
+void IMAPConnection::sendCommand(const shared_ptr <IMAPCommand>& cmd) {
+
+ if (!m_firstTag) {
+ ++(*m_tag);
+ }
+
+ m_socket->send(*m_tag);
+ m_socket->send(" ");
+ m_socket->send(cmd->getText());
+ m_socket->send("\r\n");
+
+ m_firstTag = false;
+
+ if (m_tracer) {
+
+ std::ostringstream oss;
+ oss << string(*m_tag) << " " << cmd->getText();
+
+ m_tracer->traceSend(oss.str());
+ }
+}
+
+
+void IMAPConnection::sendRaw(const byte_t* buffer, const size_t count) {
+
+ m_socket->sendRaw(buffer, count);
+}
+
+
+IMAPParser::response* IMAPConnection::readResponse(IMAPParser::literalHandler* lh) {
+
+ return m_parser->readResponse(*m_tag, lh);
+}
+
+
+IMAPConnection::ProtocolStates IMAPConnection::state() const {
+
+ return m_state;
+}
+
+
+void IMAPConnection::setState(const ProtocolStates state) {
+
+ m_state = state;
+}
+
+
+char IMAPConnection::hierarchySeparator() const {
+
+ return m_hierarchySeparator;
+}
+
+
+shared_ptr <const IMAPStore> IMAPConnection::getStore() const {
+
+ return m_store.lock();
+}
+
+
+shared_ptr <IMAPStore> IMAPConnection::getStore() {
+
+ return m_store.lock();
+}
+
+
+shared_ptr <session> IMAPConnection::getSession() {
+
+ return m_store.lock()->getSession();
+}
+
+
+shared_ptr <const socket> IMAPConnection::getSocket() const {
+
+ return m_socket;
+}
+
+
+void IMAPConnection::setSocket(const shared_ptr <socket>& sok) {
+
+ m_socket = sok;
+ m_parser->setSocket(sok);
+}
+
+
+shared_ptr <tracer> IMAPConnection::getTracer() {
+
+ return m_tracer;
+}
+
+
+shared_ptr <IMAPTag> IMAPConnection::getTag() {
+
+ return m_tag;
+}
+
+
+bool IMAPConnection::isMODSEQDisabled() const {
+
+ return m_noModSeq;
+}
+
+
+void IMAPConnection::disableMODSEQ() {
+
+ m_noModSeq = true;
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPConnection.hpp b/vmime-master/src/vmime/net/imap/IMAPConnection.hpp
new file mode 100644
index 0000000..99750d4
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPConnection.hpp
@@ -0,0 +1,172 @@
+//
+// 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_NET_IMAP_IMAPCONNECTION_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPCONNECTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/socket.hpp"
+#include "vmime/net/timeoutHandler.hpp"
+#include "vmime/net/tracer.hpp"
+#include "vmime/net/session.hpp"
+#include "vmime/net/connectionInfos.hpp"
+
+#include "vmime/net/imap/IMAPParser.hpp"
+
+#include "vmime/security/authenticator.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class IMAPTag;
+class IMAPStore;
+class IMAPCommand;
+
+
+class VMIME_EXPORT IMAPConnection : public object, public enable_shared_from_this <IMAPConnection> {
+
+public:
+
+ IMAPConnection(const shared_ptr <IMAPStore>& store, const shared_ptr <security::authenticator>& auth);
+ ~IMAPConnection();
+
+
+ void connect();
+ bool isConnected() const;
+ void disconnect();
+
+
+ enum ProtocolStates {
+ STATE_NONE,
+ STATE_NON_AUTHENTICATED,
+ STATE_AUTHENTICATED,
+ STATE_SELECTED,
+ STATE_LOGOUT
+ };
+
+ ProtocolStates state() const;
+ void setState(const ProtocolStates state);
+
+
+ char hierarchySeparator() const;
+
+
+ void sendCommand(const shared_ptr <IMAPCommand>& cmd);
+ void sendRaw(const byte_t* buffer, const size_t count);
+
+ IMAPParser::response* readResponse(IMAPParser::literalHandler* lh = NULL);
+
+
+ shared_ptr <const IMAPStore> getStore() const;
+ shared_ptr <IMAPStore> getStore();
+
+ shared_ptr <session> getSession();
+
+ void fetchCapabilities();
+ void invalidateCapabilities();
+ const std::vector <string> getCapabilities();
+ bool hasCapability(const string& capa);
+ bool hasCapability(const string& capa) const;
+
+ shared_ptr <security::authenticator> getAuthenticator();
+
+ bool isSecuredConnection() const;
+ shared_ptr <connectionInfos> getConnectionInfos() const;
+
+ shared_ptr <const socket> getSocket() const;
+ void setSocket(const shared_ptr <socket>& sok);
+
+ shared_ptr <tracer> getTracer();
+
+ shared_ptr <IMAPTag> getTag();
+
+ bool isMODSEQDisabled() const;
+ void disableMODSEQ();
+
+private:
+
+ void authenticate();
+#if VMIME_HAVE_SASL_SUPPORT
+ void authenticateSASL();
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+#if VMIME_HAVE_TLS_SUPPORT
+ void startTLS();
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ bool processCapabilityResponseData(const IMAPParser::response* resp);
+ void processCapabilityResponseData(const IMAPParser::capability_data* capaData);
+
+
+ weak_ptr <IMAPStore> m_store;
+
+ shared_ptr <security::authenticator> m_auth;
+
+ shared_ptr <socket> m_socket;
+
+ shared_ptr <IMAPParser> m_parser;
+
+ shared_ptr <IMAPTag> m_tag;
+
+ char m_hierarchySeparator;
+
+ ProtocolStates m_state;
+
+ shared_ptr <timeoutHandler> m_timeoutHandler;
+
+ bool m_secured;
+ shared_ptr <connectionInfos> m_cntInfos;
+
+ bool m_firstTag;
+
+ std::vector <string> m_capabilities;
+ bool m_capabilitiesFetched;
+
+ bool m_noModSeq;
+
+ shared_ptr <tracer> m_tracer;
+
+
+ void internalDisconnect();
+
+ void initHierarchySeparator();
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPCONNECTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/imap/IMAPFolder.cpp b/vmime-master/src/vmime/net/imap/IMAPFolder.cpp
new file mode 100644
index 0000000..98bc05d
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPFolder.cpp
@@ -0,0 +1,1622 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPFolder.hpp"
+
+#include "vmime/net/imap/IMAPStore.hpp"
+#include "vmime/net/imap/IMAPParser.hpp"
+#include "vmime/net/imap/IMAPMessage.hpp"
+#include "vmime/net/imap/IMAPUtils.hpp"
+#include "vmime/net/imap/IMAPConnection.hpp"
+#include "vmime/net/imap/IMAPFolderStatus.hpp"
+#include "vmime/net/imap/IMAPCommand.hpp"
+
+#include "vmime/message.hpp"
+
+#include "vmime/exception.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+#include <algorithm>
+#include <sstream>
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPFolder::IMAPFolder(
+ const folder::path& path,
+ const shared_ptr <IMAPStore>& store,
+ const shared_ptr <folderAttributes>& attribs
+)
+ : m_store(store),
+ m_connection(store->connection()),
+ m_path(path),
+ m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()),
+ m_mode(-1),
+ m_open(false),
+ m_attribs(attribs) {
+
+ store->registerFolder(this);
+
+ m_status = make_shared <IMAPFolderStatus>();
+}
+
+
+IMAPFolder::~IMAPFolder() {
+
+ try {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (store) {
+
+ if (m_open) {
+ close(false);
+ }
+
+ store->unregisterFolder(this);
+
+ } else if (m_open) {
+
+ m_connection = null;
+ onClose();
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+int IMAPFolder::getMode() const {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ return m_mode;
+}
+
+
+const folderAttributes IMAPFolder::getAttributes() {
+
+ // Root folder
+ if (m_path.isEmpty()) {
+
+ folderAttributes attribs;
+ attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS);
+ attribs.setFlags(folderAttributes::FLAG_HAS_CHILDREN | folderAttributes::FLAG_NO_OPEN);
+
+ return attribs;
+
+ } else {
+
+ if (!m_attribs) {
+ testExistAndGetType();
+ }
+
+ return *m_attribs;
+ }
+}
+
+
+const folder::path::component IMAPFolder::getName() const {
+
+ return m_name;
+}
+
+
+const folder::path IMAPFolder::getFullPath() const {
+
+ return m_path;
+}
+
+
+void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ // Ensure this folder is not already open in the same session
+ for (std::list <IMAPFolder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && (*it)->getFullPath() == m_path) {
+ throw exceptions::folder_already_open();
+ }
+ }
+
+ // Open a connection for this folder
+ shared_ptr <IMAPConnection> connection =
+ make_shared <IMAPConnection>(store, store->getAuthenticator());
+
+ try {
+
+ connection->connect();
+
+ // Emit the "SELECT" command
+ //
+ // Example: C: A142 SELECT INBOX
+ // S: * 172 EXISTS
+ // S: * 1 RECENT
+ // S: * OK [UNSEEN 12] Message 12 is first unseen
+ // S: * OK [UIDVALIDITY 3857529045] UIDs valid
+ // S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
+ // S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited
+ // S: A142 OK [READ-WRITE] SELECT completed
+
+ std::vector <string> selectParams;
+
+ if (m_connection->hasCapability("CONDSTORE")) {
+ selectParams.push_back("CONDSTORE");
+ }
+
+ IMAPCommand::SELECT(
+ mode == MODE_READ_ONLY,
+ IMAPUtils::pathToString(connection->hierarchySeparator(), getFullPath()),
+ selectParams
+ )->send(connection);
+
+ // Read the response
+ scoped_ptr <IMAPParser::response> resp(connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("SELECT", resp->getErrorLog(), "bad response");
+ }
+
+ auto &respDataList = resp->continue_req_or_response_data;
+
+ for (auto it = respDataList.begin() ; it != respDataList.end() ; ++it) {
+
+ auto *responseData = (*it)->response_data.get();
+
+ if (!responseData) {
+ throw exceptions::command_error("SELECT", resp->getErrorLog(), "invalid response");
+ }
+
+ // OK Untagged responses: UNSEEN, PERMANENTFLAGS, UIDVALIDITY (optional)
+ if (responseData->resp_cond_state) {
+
+ auto *code = responseData->resp_cond_state->resp_text->resp_text_code.get();
+
+ if (code) {
+
+ switch (code->type) {
+
+ case IMAPParser::resp_text_code::NOMODSEQ:
+
+ connection->disableMODSEQ();
+ break;
+
+ default:
+
+ break;
+ }
+ }
+
+ // Untagged responses: FLAGS, EXISTS, RECENT (required)
+ } else if (responseData->mailbox_data) {
+
+ switch (responseData->mailbox_data->type) {
+
+ default: break;
+
+ case IMAPParser::mailbox_data::FLAGS: {
+
+ if (!m_attribs) {
+ m_attribs = make_shared <folderAttributes>();
+ }
+
+ IMAPUtils::mailboxFlagsToFolderAttributes(
+ connection,
+ m_path,
+ *responseData->mailbox_data->mailbox_flag_list,
+ *m_attribs
+ );
+
+ break;
+ }
+ }
+ }
+ }
+
+ processStatusUpdate(resp.get());
+
+ // Check for access mode (read-only or read-write)
+ auto *respTextCode = resp->response_done->response_tagged->resp_cond_state->resp_text->resp_text_code.get();
+
+ if (respTextCode) {
+
+ const int openMode =
+ (respTextCode->type == IMAPParser::resp_text_code::READ_WRITE)
+ ? MODE_READ_WRITE
+ : MODE_READ_ONLY;
+
+ if (failIfModeIsNotAvailable &&
+ mode == MODE_READ_WRITE && openMode == MODE_READ_ONLY) {
+
+ throw exceptions::operation_not_supported();
+ }
+ }
+
+ m_connection = connection;
+ m_open = true;
+ m_mode = mode;
+
+ } catch (std::exception&) {
+
+ throw;
+ }
+}
+
+
+void IMAPFolder::close(const bool expunge) {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ shared_ptr <IMAPConnection> oldConnection = m_connection;
+
+ // Emit the "CLOSE" command to expunge messages marked
+ // as deleted (this is fastest than "EXPUNGE")
+ if (expunge) {
+
+ if (m_mode == MODE_READ_ONLY) {
+ throw exceptions::operation_not_supported();
+ }
+
+ IMAPCommand::CLOSE()->send(oldConnection);
+ }
+
+ // Close this folder connection
+ oldConnection->disconnect();
+
+ // Now use default store connection
+ m_connection = m_store.lock()->connection();
+
+ m_open = false;
+ m_mode = -1;
+
+ m_status = make_shared <IMAPFolderStatus>();
+
+ onClose();
+}
+
+
+void IMAPFolder::onClose() {
+
+ for (std::vector <IMAPMessage*>::iterator it = m_messages.begin() ;
+ it != m_messages.end() ; ++it) {
+
+ (*it)->onFolderClosed();
+ }
+
+ m_messages.clear();
+}
+
+
+void IMAPFolder::create(const folderAttributes& attribs) {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (isOpen()) {
+ throw exceptions::illegal_state("Folder is open");
+ } else if (exists()) {
+ throw exceptions::illegal_state("Folder already exists");
+ } else if (!store->isValidFolderName(m_name)) {
+ throw exceptions::invalid_folder_name();
+ }
+
+ // Emit the "CREATE" command
+ //
+ // Example: C: A003 CREATE owatagusiam/
+ // S: A003 OK CREATE completed
+ // C: A004 CREATE owatagusiam/blurdybloop
+ // S: A004 OK CREATE completed
+
+ string mailbox = IMAPUtils::pathToString
+ (m_connection->hierarchySeparator(), getFullPath());
+
+ if (attribs.getType() & folderAttributes::TYPE_CONTAINS_FOLDERS) {
+ mailbox += m_connection->hierarchySeparator();
+ }
+
+ std::vector <string> createParams;
+
+ if (attribs.getSpecialUse() != folderAttributes::SPECIALUSE_NONE) {
+
+ if (!m_connection->hasCapability("CREATE-SPECIAL-USE")) {
+ throw exceptions::operation_not_supported();
+ }
+
+ // C: t2 CREATE MySpecial (USE (\Drafts \Sent))
+ std::ostringstream oss;
+ oss << "USE (";
+
+ switch (attribs.getSpecialUse()) {
+
+ case folderAttributes::SPECIALUSE_NONE: // should not happen
+ case folderAttributes::SPECIALUSE_ALL: oss << "\\All"; break;
+ case folderAttributes::SPECIALUSE_ARCHIVE: oss << "\\Archive"; break;
+ case folderAttributes::SPECIALUSE_DRAFTS: oss << "\\Drafts"; break;
+ case folderAttributes::SPECIALUSE_FLAGGED: oss << "\\Flagged"; break;
+ case folderAttributes::SPECIALUSE_JUNK: oss << "\\Junk"; break;
+ case folderAttributes::SPECIALUSE_SENT: oss << "\\Sent"; break;
+ case folderAttributes::SPECIALUSE_TRASH: oss << "\\Trash"; break;
+ case folderAttributes::SPECIALUSE_IMPORTANT: oss << "\\Important"; break;
+ }
+
+ oss << ")";
+
+ createParams.push_back(oss.str());
+ }
+
+ IMAPCommand::CREATE(mailbox, createParams)->send(m_connection);
+
+
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("CREATE", resp->getErrorLog(), "bad response");
+ }
+
+ // Notify folder created
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::folderEvent::TYPE_CREATED,
+ m_path, m_path
+ );
+
+ notifyFolder(event);
+}
+
+
+void IMAPFolder::destroy() {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ if (isOpen()) {
+ throw exceptions::illegal_state("Folder is open");
+ }
+
+ const string mailbox = IMAPUtils::pathToString(
+ m_connection->hierarchySeparator(), getFullPath()
+ );
+
+ IMAPCommand::DELETE(mailbox)->send(m_connection);
+
+
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("DELETE", resp->getErrorLog(), "bad response");
+ }
+
+ // Notify folder deleted
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::folderEvent::TYPE_DELETED,
+ m_path, m_path
+ );
+
+ notifyFolder(event);
+}
+
+
+bool IMAPFolder::exists() {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!isOpen() && !store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ return testExistAndGetType() != -1;
+}
+
+
+int IMAPFolder::testExistAndGetType() {
+
+ // To test whether a folder exists, we simple list it using
+ // the "LIST" command, and there should be one unique mailbox
+ // with this name...
+ //
+ // Eg. Test whether '/foo/bar' exists
+ //
+ // C: a005 list "" foo/bar
+ // S: * LIST (\NoSelect) "/" foo/bar
+ // S: a005 OK LIST completed
+ //
+ // ==> OK, exists
+ //
+ // Test whether '/foo/bar/zap' exists
+ //
+ // C: a005 list "" foo/bar/zap
+ // S: a005 OK LIST completed
+ //
+ // ==> NO, does not exist
+
+ IMAPCommand::LIST(
+ "",
+ IMAPUtils::pathToString(
+ m_connection->hierarchySeparator(),
+ getFullPath()
+ )
+ )->send(m_connection);
+
+
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("LIST", resp->getErrorLog(), "bad response");
+ }
+
+ // Check whether the result mailbox list contains this folder
+ auto& respDataList = resp->continue_req_or_response_data;
+
+ folderAttributes attribs;
+ attribs.setType(-1);
+
+ for (auto it = respDataList.begin() ; it != respDataList.end() ; ++it) {
+
+ if (!(*it)->response_data) {
+ throw exceptions::command_error("LIST", resp->getErrorLog(), "invalid response");
+ }
+
+ auto *mailboxData = (*it)->response_data->mailbox_data.get();
+
+ // We are only interested in responses of type "LIST"
+ if (mailboxData &&
+ mailboxData->type == IMAPParser::mailbox_data::LIST) {
+
+ // Get the folder type/flags at the same time
+ IMAPUtils::mailboxFlagsToFolderAttributes(
+ m_connection,
+ m_path,
+ *mailboxData->mailbox_list->mailbox_flag_list,
+ attribs
+ );
+ }
+ }
+
+ m_attribs = make_shared <folderAttributes>(attribs);
+
+ return m_attribs->getType();
+}
+
+
+bool IMAPFolder::isOpen() const {
+
+ return m_open;
+}
+
+
+shared_ptr <message> IMAPFolder::getMessage(const size_t num) {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (num < 1 || num > m_status->getMessageCount()) {
+ throw exceptions::message_not_found();
+ }
+
+ return make_shared <IMAPMessage>(dynamicCast <IMAPFolder>(shared_from_this()), num);
+}
+
+
+std::vector <shared_ptr <message> > IMAPFolder::getMessages(const messageSet& msgs) {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (msgs.isEmpty()) {
+ return std::vector <shared_ptr <message> >();
+ }
+
+ std::vector <shared_ptr <message> > messages;
+
+ // Sequence number message set:
+ // C: . FETCH uuuu1,uuuu2,uuuu3 UID
+ // S: * nnnn1 FETCH (UID uuuu1)
+ // S: * nnnn2 FETCH (UID uuuu2)
+ // S: * nnnn3 FETCH (UID uuuu3)
+ // S: . OK FETCH completed
+
+ // UID message set:
+ // C: . UID FETCH uuuu1,uuuu2,uuuu3 UID
+ // S: * nnnn1 FETCH (UID uuuu1)
+ // S: * nnnn2 FETCH (UID uuuu2)
+ // S: * nnnn3 FETCH (UID uuuu3)
+ // S: . OK UID FETCH completed
+
+ std::vector <string> params;
+ params.push_back("UID");
+
+ IMAPCommand::FETCH(msgs, params)->send(m_connection);
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("UID FETCH ... UID", resp->getErrorLog(), "bad response");
+ }
+
+ // Process the response
+ auto &respDataList = resp->continue_req_or_response_data;
+
+ for (auto it = respDataList.begin() ; it != respDataList.end() ; ++it) {
+
+ if (!(*it)->response_data) {
+ throw exceptions::command_error("UID FETCH ... UID", resp->getErrorLog(), "invalid response");
+ }
+
+ auto *messageData = (*it)->response_data->message_data.get();
+
+ // We are only interested in responses of type "FETCH"
+ if (!messageData || messageData->type != IMAPParser::message_data::FETCH) {
+ continue;
+ }
+
+ // Find UID in message attributes
+ const size_t msgNum = messageData->number;
+ message::uid msgUID;
+
+ for (auto &att : messageData->msg_att->items) {
+
+ if (att->type == IMAPParser::msg_att_item::UID) {
+ msgUID = att->uniqueid->value;
+ break;
+ }
+ }
+
+ if (!msgUID.empty()) {
+ shared_ptr <IMAPFolder> thisFolder = dynamicCast <IMAPFolder>(shared_from_this());
+ messages.push_back(make_shared <IMAPMessage>(thisFolder, msgNum, msgUID));
+ }
+ }
+
+ return messages;
+}
+
+
+size_t IMAPFolder::getMessageCount() {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ return m_status->getMessageCount();
+}
+
+
+vmime_uint32 IMAPFolder::getUIDValidity() const {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ return m_status->getUIDValidity();
+}
+
+
+vmime_uint64 IMAPFolder::getHighestModSequence() const {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ return m_status->getHighestModSeq();
+}
+
+
+shared_ptr <folder> IMAPFolder::getFolder(const folder::path::component& name) {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ return make_shared <IMAPFolder>(m_path / name, store, shared_ptr <folderAttributes>());
+}
+
+
+std::vector <shared_ptr <folder> > IMAPFolder::getFolders(const bool recursive) {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!isOpen() && !store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ // Eg. List folders in '/foo/bar'
+ //
+ // C: a005 list "foo/bar" *
+ // S: * LIST (\NoSelect) "/" foo/bar
+ // S: * LIST (\NoInferiors) "/" foo/bar/zap
+ // S: a005 OK LIST completed
+
+ shared_ptr <IMAPCommand> cmd;
+
+ const string pathString = IMAPUtils::pathToString(
+ m_connection->hierarchySeparator(), getFullPath()
+ );
+
+ if (recursive) {
+
+ cmd = IMAPCommand::LIST(pathString, "*");
+
+ } else {
+
+ cmd = IMAPCommand::LIST(
+ pathString.empty()
+ ? ""
+ : (pathString + m_connection->hierarchySeparator()),
+ "%"
+ );
+ }
+
+ cmd->send(m_connection);
+
+
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("LIST", resp->getErrorLog(), "bad response");
+ }
+
+ auto &respDataList = resp->continue_req_or_response_data;
+
+ std::vector <shared_ptr <folder> > v;
+
+ for (auto it = respDataList.begin() ; it != respDataList.end() ; ++it) {
+
+ if (!(*it)->response_data) {
+ throw exceptions::command_error("LIST", resp->getErrorLog(), "invalid response");
+ }
+
+ auto *mailboxData = (*it)->response_data->mailbox_data.get();
+
+ if (!mailboxData || mailboxData->type != IMAPParser::mailbox_data::LIST) {
+ continue;
+ }
+
+ // Get folder path
+ auto &mailbox = mailboxData->mailbox_list->mailbox;
+
+ folder::path path = IMAPUtils::stringToPath(
+ mailboxData->mailbox_list->quoted_char, mailbox->name
+ );
+
+ if (recursive || m_path.isDirectParentOf(path)) {
+
+ // Append folder to list
+ shared_ptr <folderAttributes> attribs = make_shared <folderAttributes>();
+
+ IMAPUtils::mailboxFlagsToFolderAttributes(
+ m_connection,
+ path,
+ *mailboxData->mailbox_list->mailbox_flag_list,
+ *attribs
+ );
+
+ v.push_back(make_shared <IMAPFolder>(path, store, attribs));
+ }
+ }
+
+ return v;
+}
+
+
+void IMAPFolder::fetchMessages(
+ std::vector <shared_ptr <message> >& msg,
+ const fetchAttributes& options,
+ utility::progressListener* progress
+) {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (msg.empty()) {
+ return;
+ }
+
+ // Build message numbers list
+ std::vector <size_t> list;
+ list.reserve(msg.size());
+
+ std::map <size_t, shared_ptr <IMAPMessage> > numberToMsg;
+
+ for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ; it != msg.end() ; ++it) {
+
+ list.push_back((*it)->getNumber());
+ numberToMsg[(*it)->getNumber()] = dynamicCast <IMAPMessage>(*it);
+ }
+
+ // Send the request
+ IMAPUtils::buildFetchCommand(
+ m_connection, messageSet::byNumber(list), options
+ )->send(m_connection);
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("FETCH", resp->getErrorLog(), "bad response");
+ }
+
+ auto &respDataList = resp->continue_req_or_response_data;
+
+ const size_t total = msg.size();
+ size_t current = 0;
+
+ if (progress) {
+ progress->start(total);
+ }
+
+ try {
+
+ for (auto it = respDataList.begin() ; it != respDataList.end() ; ++it) {
+
+ if (!(*it)->response_data) {
+ throw exceptions::command_error("FETCH", resp->getErrorLog(), "invalid response");
+ }
+
+ auto *messageData = (*it)->response_data->message_data.get();
+
+ // We are only interested in responses of type "FETCH"
+ if (!messageData || messageData->type != IMAPParser::message_data::FETCH) {
+ continue;
+ }
+
+ // Process fetch response for this message
+ const size_t num = messageData->number;
+
+ std::map <size_t, shared_ptr <IMAPMessage> >::iterator msg = numberToMsg.find(num);
+
+ if (msg != numberToMsg.end()) {
+
+ (*msg).second->processFetchResponse(options, *messageData);
+
+ if (progress) {
+ progress->progress(++current, total);
+ }
+ }
+ }
+
+ } catch (...) {
+
+ if (progress) {
+ progress->stop(total);
+ }
+
+ throw;
+ }
+
+ if (progress) {
+ progress->stop(total);
+ }
+
+ processStatusUpdate(resp.get());
+}
+
+
+void IMAPFolder::fetchMessage(const shared_ptr <message>& msg, const fetchAttributes& options) {
+
+ std::vector <shared_ptr <message> > msgs;
+ msgs.push_back(msg);
+
+ fetchMessages(msgs, options, /* progress */ NULL);
+}
+
+
+std::vector <shared_ptr <message> > IMAPFolder::getAndFetchMessages(
+ const messageSet& msgs,
+ const fetchAttributes& attribs
+) {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (msgs.isEmpty()) {
+ return std::vector <shared_ptr <message> >();
+ }
+
+ // Ensure we also get the UID for each message
+ fetchAttributes attribsWithUID(attribs);
+ attribsWithUID.add(fetchAttributes::UID);
+
+ // Send the request
+ IMAPUtils::buildFetchCommand(m_connection, msgs, attribsWithUID)->send(m_connection);
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("FETCH", resp->getErrorLog(), "bad response");
+ }
+
+ auto &respDataList = resp->continue_req_or_response_data;
+
+ std::vector <shared_ptr <message> > messages;
+
+ for (auto it = respDataList.begin() ; it != respDataList.end() ; ++it) {
+
+ if (!(*it)->response_data) {
+ throw exceptions::command_error("FETCH", resp->getErrorLog(), "invalid response");
+ }
+
+ auto *messageData = (*it)->response_data->message_data.get();
+
+ // We are only interested in responses of type "FETCH"
+ if (!messageData || messageData->type != IMAPParser::message_data::FETCH) {
+ continue;
+ }
+
+ // Get message number
+ const size_t msgNum = messageData->number;
+
+ // Get message UID
+ message::uid msgUID;
+
+ for (auto &att : messageData->msg_att->items) {
+
+ if (att->type == IMAPParser::msg_att_item::UID) {
+ msgUID = att->uniqueid->value;
+ break;
+ }
+ }
+
+ // Create a new message reference
+ shared_ptr <IMAPFolder> thisFolder = dynamicCast <IMAPFolder>(shared_from_this());
+ shared_ptr <IMAPMessage> msg = make_shared <IMAPMessage>(thisFolder, msgNum, msgUID);
+
+ messages.push_back(msg);
+
+ // Process fetch response for this message
+ msg->processFetchResponse(attribsWithUID, *messageData);
+ }
+
+ processStatusUpdate(resp.get());
+
+ return messages;
+}
+
+
+int IMAPFolder::getFetchCapabilities() const {
+
+ return fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO |
+ fetchAttributes::STRUCTURE | fetchAttributes::FLAGS |
+ fetchAttributes::SIZE | fetchAttributes::FULL_HEADER |
+ fetchAttributes::UID | fetchAttributes::IMPORTANCE;
+}
+
+
+shared_ptr <folder> IMAPFolder::getParent() {
+
+ if (m_path.isEmpty()) {
+
+ return null;
+
+ } else {
+
+ return make_shared <IMAPFolder>(
+ m_path.getParent(), m_store.lock(), shared_ptr <folderAttributes>()
+ );
+ }
+}
+
+
+shared_ptr <const store> IMAPFolder::getStore() const {
+
+ return m_store.lock();
+}
+
+
+shared_ptr <store> IMAPFolder::getStore() {
+
+ return m_store.lock();
+}
+
+
+void IMAPFolder::registerMessage(IMAPMessage* msg) {
+
+ m_messages.push_back(msg);
+}
+
+
+void IMAPFolder::unregisterMessage(IMAPMessage* msg) {
+
+ std::vector <IMAPMessage*>::iterator it =
+ std::find(m_messages.begin(), m_messages.end(), msg);
+
+ if (it != m_messages.end()) {
+ m_messages.erase(it);
+ }
+}
+
+
+void IMAPFolder::onStoreDisconnected() {
+
+ m_store.reset();
+}
+
+
+void IMAPFolder::deleteMessages(const messageSet& msgs) {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (msgs.isEmpty()) {
+ throw exceptions::invalid_argument();
+ }
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ } else if (m_mode == MODE_READ_ONLY) {
+ throw exceptions::illegal_state("Folder is read-only");
+ }
+
+ // Send the request
+ IMAPCommand::STORE(
+ msgs, message::FLAG_MODE_ADD,
+ IMAPUtils::messageFlagList(message::FLAG_DELETED)
+ )->send(m_connection);
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("STORE", resp->getErrorLog(), "bad response");
+ }
+
+ processStatusUpdate(resp.get());
+}
+
+
+void IMAPFolder::setMessageFlags(
+ const messageSet& msgs,
+ const int flags,
+ const int mode
+) {
+
+ const std::vector <string> flagList = IMAPUtils::messageFlagList(flags);
+
+ if ((mode == message::FLAG_MODE_SET) || !flagList.empty()) {
+
+ // Send the request
+ IMAPCommand::STORE(msgs, mode, flagList)->send(m_connection);
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("STORE", resp->getErrorLog(), "bad response");
+ }
+
+ processStatusUpdate(resp.get());
+ }
+}
+
+
+messageSet IMAPFolder::addMessage(
+ const shared_ptr <vmime::message>& msg,
+ const int flags,
+ vmime::datetime* date,
+ utility::progressListener* progress
+) {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter ossAdapter(oss);
+
+ msg->generate(ossAdapter);
+
+ const string& str = oss.str();
+ utility::inputStreamStringAdapter strAdapter(str);
+
+ return addMessage(strAdapter, str.length(), flags, date, progress);
+}
+
+
+messageSet IMAPFolder::addMessage(
+ utility::inputStream& is,
+ const size_t size,
+ const int flags,
+ vmime::datetime* date,
+ utility::progressListener* progress
+) {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ } else if (m_mode == MODE_READ_ONLY) {
+ throw exceptions::illegal_state("Folder is read-only");
+ }
+
+ // Send the request
+ IMAPCommand::APPEND(
+ IMAPUtils::pathToString(m_connection->hierarchySeparator(), getFullPath()),
+ IMAPUtils::messageFlagList(flags), date, size
+ )->send(m_connection);
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ bool ok = false;
+ auto &respList = resp->continue_req_or_response_data;
+
+ for (auto it = respList.begin() ; !ok && (it != respList.end()) ; ++it) {
+
+ if ((*it)->continue_req) {
+ ok = true;
+ }
+ }
+
+ if (!ok) {
+ throw exceptions::command_error("APPEND", resp->getErrorLog(), "bad response");
+ }
+
+ processStatusUpdate(resp.get());
+
+ // Send message data
+ const size_t total = size;
+ size_t current = 0;
+
+ if (progress) {
+ progress->start(total);
+ }
+
+ const size_t blockSize = std::min(
+ is.getBlockSize(),
+ static_cast <size_t>(m_connection->getSocket()->getBlockSize())
+ );
+
+ std::vector <byte_t> vbuffer(blockSize);
+ byte_t* buffer = &vbuffer.front();
+
+ while (!is.eof()) {
+
+ // Read some data from the input stream
+ const size_t read = is.read(buffer, blockSize);
+ current += read;
+
+ // Put read data into socket output stream
+ m_connection->sendRaw(buffer, read);
+
+ // Notify progress
+ if (progress) {
+ progress->progress(current, total);
+ }
+ }
+
+ m_connection->sendRaw(utility::stringUtils::bytesFromString("\r\n"), 2);
+
+ if (m_connection->getTracer()) {
+ m_connection->getTracer()->traceSendBytes(current);
+ }
+
+ if (progress) {
+ progress->stop(total);
+ }
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> finalResp(m_connection->readResponse());
+
+ if (finalResp->isBad() || finalResp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("APPEND", resp->getErrorLog(), "bad response");
+ }
+
+ processStatusUpdate(finalResp.get());
+
+ auto *respTextCode =
+ finalResp->response_done->response_tagged->resp_cond_state->resp_text->resp_text_code.get();
+
+ if (respTextCode && respTextCode->type == IMAPParser::resp_text_code::APPENDUID) {
+ return IMAPUtils::buildMessageSet(*respTextCode->uid_set);
+ }
+
+ return messageSet::empty();
+}
+
+
+void IMAPFolder::expunge() {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ } else if (m_mode == MODE_READ_ONLY) {
+ throw exceptions::illegal_state("Folder is read-only");
+ }
+
+ // Send the request
+ IMAPCommand::EXPUNGE()->send(m_connection);
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("EXPUNGE", resp->getErrorLog(), "bad response");
+ }
+
+ processStatusUpdate(resp.get());
+}
+
+
+void IMAPFolder::rename(const folder::path& newPath) {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (m_path.isEmpty() || newPath.isEmpty()) {
+ throw exceptions::illegal_operation("Cannot rename root folder");
+ } else if (m_path.getSize() == 1 && m_name.getBuffer() == "INBOX") {
+ throw exceptions::illegal_operation("Cannot rename 'INBOX' folder");
+ } else if (!store->isValidFolderName(newPath.getLastComponent())) {
+ throw exceptions::invalid_folder_name();
+ }
+
+ // Send the request
+ IMAPCommand::RENAME(
+ IMAPUtils::pathToString(m_connection->hierarchySeparator(), getFullPath()),
+ IMAPUtils::pathToString(m_connection->hierarchySeparator(), newPath)
+ )->send(m_connection);
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("RENAME", resp->getErrorLog(), "bad response");
+ }
+
+ // Notify folder renamed
+ folder::path oldPath(m_path);
+
+ m_path = newPath;
+ m_name = newPath.getLastComponent();
+
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::folderEvent::TYPE_RENAMED,
+ oldPath,
+ newPath
+ );
+
+ notifyFolder(event);
+
+ // Notify sub-folders
+ for (std::list <IMAPFolder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) {
+
+ folder::path oldPath((*it)->m_path);
+
+ (*it)->m_path.renameParent(oldPath, newPath);
+
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>((*it)->shared_from_this()),
+ events::folderEvent::TYPE_RENAMED,
+ oldPath, (*it)->m_path
+ );
+
+ (*it)->notifyFolder(event);
+ }
+ }
+
+ processStatusUpdate(resp.get());
+}
+
+
+messageSet IMAPFolder::copyMessages(const folder::path& dest, const messageSet& set) {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ // Send the request
+ IMAPCommand::COPY(
+ set,
+ IMAPUtils::pathToString(m_connection->hierarchySeparator(), dest)
+ )->send(m_connection);
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("COPY", resp->getErrorLog(), "bad response");
+ }
+
+ processStatusUpdate(resp.get());
+
+ auto *respTextCode =
+ resp->response_done->response_tagged->resp_cond_state->resp_text->resp_text_code.get();
+
+ if (respTextCode && respTextCode->type == IMAPParser::resp_text_code::COPYUID) {
+ return IMAPUtils::buildMessageSet(*respTextCode->uid_set2);
+ }
+
+ return messageSet::empty();
+}
+
+
+void IMAPFolder::status(size_t& count, size_t& unseen) {
+
+ count = 0;
+ unseen = 0;
+
+ shared_ptr <folderStatus> status = getStatus();
+
+ count = status->getMessageCount();
+ unseen = status->getUnseenCount();
+}
+
+
+shared_ptr <folderStatus> IMAPFolder::getStatus() {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ // Build the attributes list
+ std::vector <string> attribs;
+
+ attribs.push_back("MESSAGES");
+ attribs.push_back("UNSEEN");
+ attribs.push_back("UIDNEXT");
+ attribs.push_back("UIDVALIDITY");
+
+ if (m_connection->hasCapability("CONDSTORE")) {
+ attribs.push_back("HIGHESTMODSEQ");
+ }
+
+ // Send the request
+ IMAPCommand::STATUS(
+ IMAPUtils::pathToString(m_connection->hierarchySeparator(), getFullPath()),
+ attribs
+ )->send(m_connection);
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("STATUS", resp->getErrorLog(), "bad response");
+ }
+
+ auto &respDataList = resp->continue_req_or_response_data;
+
+ for (auto it = respDataList.begin() ; it != respDataList.end() ; ++it) {
+
+ if ((*it)->response_data) {
+
+ auto &responseData = (*it)->response_data;
+
+ if (responseData->mailbox_data &&
+ responseData->mailbox_data->type == IMAPParser::mailbox_data::STATUS) {
+
+ shared_ptr <IMAPFolderStatus> status = make_shared <IMAPFolderStatus>();
+ status->updateFromResponse(*responseData->mailbox_data);
+
+ m_status->updateFromResponse(*responseData->mailbox_data);
+
+ return status;
+ }
+ }
+ }
+
+ throw exceptions::command_error("STATUS", resp->getErrorLog(), "invalid response");
+}
+
+
+void IMAPFolder::noop() {
+
+ shared_ptr <IMAPStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ IMAPCommand::NOOP()->send(m_connection);
+
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("NOOP", resp->getErrorLog());
+ }
+
+ processStatusUpdate(resp.get());
+}
+
+
+std::vector <size_t> IMAPFolder::getMessageNumbersStartingOnUID(const message::uid& uid) {
+
+ // Send the request
+ std::ostringstream uidSearchKey;
+ uidSearchKey.imbue(std::locale::classic());
+ uidSearchKey << "UID " << uid << ":*";
+
+ std::vector <string> searchKeys;
+ searchKeys.push_back(uidSearchKey.str());
+
+ IMAPCommand::SEARCH(searchKeys, /* charset */ NULL)->send(m_connection);
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() ||
+ resp->response_done->response_tagged->resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("SEARCH", resp->getErrorLog(), "bad response");
+ }
+
+ auto& respDataList = resp->continue_req_or_response_data;
+
+ std::vector <size_t> seqNumbers;
+
+ for (auto it = respDataList.begin() ; it != respDataList.end() ; ++it) {
+
+ if (!(*it)->response_data) {
+ throw exceptions::command_error("SEARCH", resp->getErrorLog(), "invalid response");
+ }
+
+ auto *mailboxData = (*it)->response_data->mailbox_data.get();
+
+ // We are only interested in responses of type "SEARCH"
+ if (!mailboxData ||
+ mailboxData->type != IMAPParser::mailbox_data::SEARCH) {
+
+ continue;
+ }
+
+ for (auto &nzn : mailboxData->search_nz_number_list) {
+ seqNumbers.push_back(nzn->value);
+ }
+ }
+
+ processStatusUpdate(resp.get());
+
+ return seqNumbers;
+}
+
+
+void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) {
+
+ std::vector <shared_ptr <events::event> > events;
+
+ shared_ptr <IMAPFolderStatus> oldStatus = vmime::clone(m_status);
+ int expungedMessageCount = 0;
+
+ // Process tagged response
+ if (resp->response_done &&
+ resp->response_done->response_tagged &&
+ resp->response_done->response_tagged->resp_cond_state->resp_text->resp_text_code) {
+
+ m_status->updateFromResponse(
+ *resp->response_done->response_tagged->resp_cond_state->resp_text->resp_text_code
+ );
+ }
+
+ // Process untagged responses
+ for (auto it = resp->continue_req_or_response_data.begin() ;
+ it != resp->continue_req_or_response_data.end() ; ++it) {
+
+ if ((*it)->response_data &&
+ (*it)->response_data->resp_cond_state &&
+ (*it)->response_data->resp_cond_state->resp_text->resp_text_code) {
+
+ m_status->updateFromResponse(
+ *(*it)->response_data->resp_cond_state->resp_text->resp_text_code
+ );
+
+ } else if ((*it)->response_data &&
+ (*it)->response_data->mailbox_data) {
+
+ m_status->updateFromResponse(*(*it)->response_data->mailbox_data);
+
+ // Update folder attributes, if available
+ if ((*it)->response_data->mailbox_data->type == IMAPParser::mailbox_data::LIST) {
+
+ folderAttributes attribs;
+ IMAPUtils::mailboxFlagsToFolderAttributes(
+ m_connection,
+ m_path,
+ *(*it)->response_data->mailbox_data->mailbox_list->mailbox_flag_list,
+ attribs
+ );
+
+ m_attribs = make_shared <folderAttributes>(attribs);
+ }
+
+ } else if ((*it)->response_data && (*it)->response_data->message_data) {
+
+ auto* msgData = (*it)->response_data->message_data.get();
+ const size_t msgNumber = msgData->number;
+
+ if (msgData->type == IMAPParser::message_data::FETCH) {
+
+ // Message changed
+ for (std::vector <IMAPMessage*>::iterator mit =
+ m_messages.begin() ; mit != m_messages.end() ; ++mit) {
+
+ if ((*mit)->getNumber() == msgNumber) {
+ (*mit)->processFetchResponse(/* options */ 0, *msgData);
+ }
+ }
+
+ events.push_back(
+ make_shared <events::messageChangedEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageChangedEvent::TYPE_FLAGS,
+ std::vector <size_t>(1, msgNumber)
+ )
+ );
+
+ } else if (msgData->type == IMAPParser::message_data::EXPUNGE) {
+
+ // A message has been expunged, renumber messages
+ for (std::vector <IMAPMessage*>::iterator jt =
+ m_messages.begin() ; jt != m_messages.end() ; ++jt) {
+
+ if ((*jt)->getNumber() == msgNumber) {
+ (*jt)->setExpunged();
+ } else if ((*jt)->getNumber() > msgNumber) {
+ (*jt)->renumber((*jt)->getNumber() - 1);
+ }
+ }
+
+ events.push_back(
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageCountEvent::TYPE_REMOVED,
+ std::vector <size_t>(1, msgNumber)
+ )
+ );
+
+ expungedMessageCount++;
+ }
+ }
+ }
+
+ // New messages arrived
+ if (m_status->getMessageCount() > oldStatus->getMessageCount() - expungedMessageCount) {
+
+ std::vector <size_t> newMessageNumbers;
+
+ for (size_t msgNumber = oldStatus->getMessageCount() - expungedMessageCount ;
+ msgNumber <= m_status->getMessageCount() ; ++msgNumber) {
+
+ newMessageNumbers.push_back(msgNumber);
+ }
+
+ events.push_back(
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageCountEvent::TYPE_ADDED,
+ newMessageNumbers
+ )
+ );
+ }
+
+ // Dispatch notifications
+ for (std::vector <shared_ptr <events::event> >::iterator evit =
+ events.begin() ; evit != events.end() ; ++evit) {
+
+ notifyEvent(*evit);
+ }
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPFolder.hpp b/vmime-master/src/vmime/net/imap/IMAPFolder.hpp
new file mode 100644
index 0000000..3e6b04b
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPFolder.hpp
@@ -0,0 +1,230 @@
+//
+// 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_NET_IMAP_IMAPFOLDER_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPFOLDER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include <vector>
+#include <map>
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/folder.hpp"
+
+#include "vmime/net/imap/IMAPParser.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class IMAPStore;
+class IMAPMessage;
+class IMAPConnection;
+class IMAPFolderStatus;
+
+
+/** IMAP folder implementation.
+ */
+class VMIME_EXPORT IMAPFolder : public folder {
+
+private:
+
+ friend class IMAPStore;
+ friend class IMAPMessage;
+
+ IMAPFolder(const IMAPFolder&);
+
+public:
+
+ IMAPFolder(
+ const folder::path& path,
+ const shared_ptr <IMAPStore>& store,
+ const shared_ptr <folderAttributes>& attribs
+ );
+
+ ~IMAPFolder();
+
+ int getMode() const;
+
+ const folderAttributes getAttributes();
+
+ const folder::path::component getName() const;
+ const folder::path getFullPath() const;
+
+ void open(const int mode, bool failIfModeIsNotAvailable = false);
+ void close(const bool expunge);
+ void create(const folderAttributes& attribs);
+
+ bool exists();
+
+ void destroy();
+
+ bool isOpen() const;
+
+ shared_ptr <message> getMessage(const size_t num);
+ std::vector <shared_ptr <message> > getMessages(const messageSet& msgs);
+
+ std::vector <size_t> getMessageNumbersStartingOnUID(const message::uid& uid);
+
+ size_t getMessageCount();
+
+ shared_ptr <folder> getFolder(const folder::path::component& name);
+ std::vector <shared_ptr <folder> > getFolders(const bool recursive = false);
+
+ void rename(const folder::path& newPath);
+
+ void deleteMessages(const messageSet& msgs);
+
+ void setMessageFlags(
+ const messageSet& msgs,
+ const int flags,
+ const int mode = message::FLAG_MODE_SET
+ );
+
+ messageSet addMessage(
+ const shared_ptr <vmime::message>& msg,
+ const int flags = -1,
+ vmime::datetime* date = NULL,
+ utility::progressListener* progress = NULL
+ );
+
+ messageSet addMessage(
+ utility::inputStream& is,
+ const size_t size,
+ const int flags = -1,
+ vmime::datetime* date = NULL,
+ utility::progressListener* progress = NULL
+ );
+
+ messageSet copyMessages(const folder::path& dest, const messageSet& msgs);
+
+ void status(size_t& count, size_t& unseen);
+ shared_ptr <folderStatus> getStatus();
+
+ void noop();
+
+ void expunge();
+
+ shared_ptr <folder> getParent();
+
+ shared_ptr <const store> getStore() const;
+ shared_ptr <store> getStore();
+
+
+ void fetchMessages(
+ std::vector <shared_ptr <message> >& msg,
+ const fetchAttributes& options,
+ utility::progressListener* progress = NULL
+ );
+
+ void fetchMessage(const shared_ptr <message>& msg, const fetchAttributes& options);
+
+ std::vector <shared_ptr <message> > getAndFetchMessages(
+ const messageSet& msgs,
+ const fetchAttributes& attribs
+ );
+
+ int getFetchCapabilities() const;
+
+ /** Returns the UID validity of the folder for the current session.
+ * If the server is capable of persisting UIDs accross sessions,
+ * this value should never change for a folder. If the UID validity
+ * differs across sessions, then the UIDs obtained during a previous
+ * session may not correspond to the UIDs of the same messages in
+ * this session.
+ *
+ * @return UID validity of the folder
+ */
+ vmime_uint32 getUIDValidity() const;
+
+ /** Returns the highest modification sequence of this folder, ie the
+ * modification sequence of the last message that changed in this
+ * folder.
+ *
+ * @return modification sequence, or zero if not supported by
+ * the underlying protocol
+ */
+ vmime_uint64 getHighestModSequence() const;
+
+private:
+
+ void registerMessage(IMAPMessage* msg);
+ void unregisterMessage(IMAPMessage* msg);
+
+ void onStoreDisconnected();
+
+ void onClose();
+
+ int testExistAndGetType();
+
+ void setMessageFlagsImpl(const string& set, const int flags, const int mode);
+
+ void copyMessagesImpl(const string& set, const folder::path& dest);
+
+
+ /** Process status updates ("unsolicited responses") contained in the
+ * specified response. Example:
+ *
+ * C: a006 NOOP
+ * S: * 930 EXISTS <-- this is a status update
+ * S: a006 OK Success
+ *
+ * @param resp parsed IMAP response
+ */
+ void processStatusUpdate(const IMAPParser::response* resp);
+
+
+ weak_ptr <IMAPStore> m_store;
+ shared_ptr <IMAPConnection> m_connection;
+
+ folder::path m_path;
+ folder::path::component m_name;
+
+ int m_mode;
+ bool m_open;
+
+ shared_ptr <folderAttributes> m_attribs;
+
+ shared_ptr <IMAPFolderStatus> m_status;
+
+ std::vector <IMAPMessage*> m_messages;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPFOLDER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/imap/IMAPFolderStatus.cpp b/vmime-master/src/vmime/net/imap/IMAPFolderStatus.cpp
new file mode 100644
index 0000000..55df337
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPFolderStatus.cpp
@@ -0,0 +1,292 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPFolderStatus.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPFolderStatus::IMAPFolderStatus()
+ : m_count(0),
+ m_unseen(0),
+ m_recent(0),
+ m_uidValidity(0),
+ m_uidNext(0),
+ m_highestModSeq(0) {
+
+}
+
+
+IMAPFolderStatus::IMAPFolderStatus(const IMAPFolderStatus& other)
+ : folderStatus(),
+ m_count(other.m_count),
+ m_unseen(other.m_unseen),
+ m_recent(other.m_recent),
+ m_uidValidity(other.m_uidValidity),
+ m_uidNext(other.m_uidNext),
+ m_highestModSeq(other.m_highestModSeq) {
+
+}
+
+
+size_t IMAPFolderStatus::getMessageCount() const {
+
+ return m_count;
+}
+
+
+size_t IMAPFolderStatus::getUnseenCount() const {
+
+ return m_unseen;
+}
+
+
+size_t IMAPFolderStatus::getRecentCount() const {
+
+ return m_recent;
+}
+
+
+vmime_uint32 IMAPFolderStatus::getUIDValidity() const {
+
+ return m_uidValidity;
+}
+
+
+vmime_uint32 IMAPFolderStatus::getUIDNext() const {
+
+ return m_uidNext;
+}
+
+
+vmime_uint64 IMAPFolderStatus::getHighestModSeq() const {
+
+ return m_highestModSeq;
+}
+
+
+shared_ptr <folderStatus> IMAPFolderStatus::clone() const {
+
+ return make_shared <IMAPFolderStatus>(*this);
+}
+
+
+bool IMAPFolderStatus::updateFromResponse(const IMAPParser::mailbox_data& resp) {
+
+ bool changed = false;
+
+ if (resp.type == IMAPParser::mailbox_data::STATUS) {
+
+ for (auto &attval : resp.status_att_list->values) {
+
+ switch (attval->type) {
+
+ case IMAPParser::status_att_val::MESSAGES: {
+
+ const size_t count =
+ static_cast <size_t>(attval->value_as_number()->value);
+
+ if (m_count != count) {
+ m_count = count;
+ changed = true;
+ }
+
+ break;
+ }
+ case IMAPParser::status_att_val::UNSEEN: {
+
+ const size_t unseen =
+ static_cast <size_t>(attval->value_as_number()->value);
+
+ if (m_unseen != unseen) {
+ m_unseen = unseen;
+ changed = true;
+ }
+
+ break;
+ }
+ case IMAPParser::status_att_val::RECENT: {
+
+ const size_t recent =
+ static_cast <size_t>(attval->value_as_number()->value);
+
+ if (m_recent != recent) {
+ m_recent = recent;
+ changed = true;
+ }
+
+ break;
+ }
+ case IMAPParser::status_att_val::UIDNEXT: {
+
+ const vmime_uint32 uidNext =
+ static_cast <vmime_uint32>(attval->value_as_number()->value);
+
+ if (m_uidNext != uidNext) {
+ m_uidNext = uidNext;
+ changed = true;
+ }
+
+ break;
+ }
+ case IMAPParser::status_att_val::UIDVALIDITY: {
+
+ const vmime_uint32 uidValidity =
+ static_cast <vmime_uint32>(attval->value_as_number()->value);
+
+ if (m_uidValidity != uidValidity) {
+ m_uidValidity = uidValidity;
+ changed = true;
+ }
+
+ break;
+ }
+ case IMAPParser::status_att_val::HIGHESTMODSEQ: {
+
+ const vmime_uint64 highestModSeq =
+ static_cast <vmime_uint64>(attval->value_as_mod_sequence_value()->value);
+
+ if (m_highestModSeq != highestModSeq) {
+ m_highestModSeq = highestModSeq;
+ changed = true;
+ }
+
+ break;
+ }
+
+ }
+ }
+
+ } else if (resp.type == IMAPParser::mailbox_data::EXISTS) {
+
+ const size_t count =
+ static_cast <size_t>(resp.number->value);
+
+ if (m_count != count) {
+ m_count = count;
+ changed = true;
+ }
+
+ } else if (resp.type == IMAPParser::mailbox_data::RECENT) {
+
+ const size_t recent =
+ static_cast <size_t>(resp.number->value);
+
+ if (m_recent != recent) {
+ m_recent = recent;
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+
+bool IMAPFolderStatus::updateFromResponse(const IMAPParser::resp_text_code& resp) {
+
+ bool changed = false;
+
+ switch (resp.type) {
+
+ case IMAPParser::resp_text_code::UIDVALIDITY: {
+
+ const vmime_uint32 uidValidity =
+ static_cast <vmime_uint32>(resp.nz_number->value);
+
+ if (m_uidValidity != uidValidity) {
+ m_uidValidity = uidValidity;
+ changed = true;
+ }
+
+ break;
+ }
+ case IMAPParser::resp_text_code::UIDNEXT: {
+
+ const vmime_uint32 uidNext =
+ static_cast <vmime_uint32>(resp.nz_number->value);
+
+ if (m_uidNext != uidNext) {
+ m_uidNext = uidNext;
+ changed = true;
+ }
+
+ break;
+ }
+ case IMAPParser::resp_text_code::UNSEEN: {
+
+ const size_t unseen =
+ static_cast <size_t>(resp.nz_number->value);
+
+ if (m_unseen != unseen)
+ {
+ m_unseen = unseen;
+ changed = true;
+ }
+
+ break;
+ }
+ case IMAPParser::resp_text_code::HIGHESTMODSEQ: {
+
+ const vmime_uint64 highestModSeq =
+ static_cast <vmime_uint64>(resp.mod_sequence_value->value);
+
+ if (m_highestModSeq != highestModSeq) {
+ m_highestModSeq = highestModSeq;
+ changed = true;
+ }
+
+ break;
+ }
+ case IMAPParser::resp_text_code::NOMODSEQ: {
+
+ if (m_highestModSeq != 0) {
+ m_highestModSeq = 0;
+ changed = true;
+ }
+
+ break;
+ }
+ default:
+
+ break;
+ }
+
+ return changed;
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
diff --git a/vmime-master/src/vmime/net/imap/IMAPFolderStatus.hpp b/vmime-master/src/vmime/net/imap/IMAPFolderStatus.hpp
new file mode 100644
index 0000000..b9a73ec
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPFolderStatus.hpp
@@ -0,0 +1,123 @@
+//
+// 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_NET_IMAP_IMAPFOLDERSTATUS_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPFOLDERSTATUS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/folderStatus.hpp"
+
+#include "vmime/net/imap/IMAPParser.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+/** Holds the status of an IMAP folder.
+ */
+class VMIME_EXPORT IMAPFolderStatus : public folderStatus {
+
+public:
+
+ IMAPFolderStatus();
+ IMAPFolderStatus(const IMAPFolderStatus& other);
+
+ // Inherited from folderStatus
+ size_t getMessageCount() const;
+ size_t getUnseenCount() const;
+
+ shared_ptr <folderStatus> clone() const;
+
+ /** Returns the the number of messages with the Recent flag set.
+ *
+ * @return number of messages flagged Recent
+ */
+ size_t getRecentCount() const;
+
+ /** Returns the UID validity of the folder for the current session.
+ * If the server is capable of persisting UIDs accross sessions,
+ * this value should never change for a folder.
+ *
+ * @return UID validity of the folder
+ */
+ vmime_uint32 getUIDValidity() const;
+
+ /** Returns the UID value that will be assigned to a new message
+ * in the folder. If the server does not support the UIDPLUS
+ * extension, it will return 0.
+ *
+ * @return UID of the next message
+ */
+ vmime_uint32 getUIDNext() const;
+
+ /** Returns the highest modification sequence of all messages
+ * in the folder, or 0 if not available for this folder, or not
+ * supported by the server. The server must support the CONDSTORE
+ * extension for this to be available.
+ *
+ * @return highest modification sequence
+ */
+ vmime_uint64 getHighestModSeq() const;
+
+
+ /** Reads the folder status from the specified IMAP response.
+ *
+ * @param resp parsed IMAP response
+ * @return true if the status changed, or false otherwise
+ */
+ bool updateFromResponse(const IMAPParser::mailbox_data& resp);
+
+ /** Reads the folder status from the specified IMAP response.
+ *
+ * @param resp parsed IMAP response
+ * @return true if the status changed, or false otherwise
+ */
+ bool updateFromResponse(const IMAPParser::resp_text_code& resp);
+
+private:
+
+ size_t m_count;
+ size_t m_unseen;
+ size_t m_recent;
+ vmime_uint32 m_uidValidity;
+ vmime_uint32 m_uidNext;
+ vmime_uint64 m_highestModSeq;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPFOLDERSTATUS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/imap/IMAPMessage.cpp b/vmime-master/src/vmime/net/imap/IMAPMessage.cpp
new file mode 100644
index 0000000..f74a4a4
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPMessage.cpp
@@ -0,0 +1,760 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPParser.hpp"
+#include "vmime/net/imap/IMAPMessage.hpp"
+#include "vmime/net/imap/IMAPFolder.hpp"
+#include "vmime/net/imap/IMAPFolderStatus.hpp"
+#include "vmime/net/imap/IMAPStore.hpp"
+#include "vmime/net/imap/IMAPConnection.hpp"
+#include "vmime/net/imap/IMAPUtils.hpp"
+#include "vmime/net/imap/IMAPMessageStructure.hpp"
+#include "vmime/net/imap/IMAPMessagePart.hpp"
+#include "vmime/net/imap/IMAPMessagePartContentHandler.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+#include <sstream>
+#include <iterator>
+#include <typeinfo>
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+#ifndef VMIME_BUILDING_DOC
+
+//
+// IMAPMessage_literalHandler
+//
+
+class IMAPMessage_literalHandler : public IMAPParser::literalHandler {
+
+public:
+
+ IMAPMessage_literalHandler(utility::outputStream& os, utility::progressListener* progress) {
+
+ m_target = shared_ptr <target>(new targetStream(progress, os));
+ }
+
+ shared_ptr <target> targetFor(const IMAPParser::component& comp, const int /* data */) {
+
+ if (typeid(comp) == typeid(IMAPParser::msg_att_item)) {
+
+ const int type = static_cast
+ <const IMAPParser::msg_att_item&>(comp).type;
+
+ if (type == IMAPParser::msg_att_item::BODY_SECTION ||
+ type == IMAPParser::msg_att_item::RFC822_TEXT) {
+
+ return m_target;
+ }
+ }
+
+ return shared_ptr <target>();
+ }
+
+ shared_ptr <target> getTarget() {
+
+ return m_target;
+ }
+
+private:
+
+ shared_ptr <target> m_target;
+};
+
+#endif // VMIME_BUILDING_DOC
+
+
+
+//
+// IMAPMessage
+//
+
+
+IMAPMessage::IMAPMessage(
+ const shared_ptr <IMAPFolder>& folder,
+ const size_t num
+)
+ : m_folder(folder),
+ m_num(num),
+ m_size(-1U),
+ m_flags(FLAG_UNDEFINED),
+ m_expunged(false),
+ m_modseq(0),
+ m_structure(null) {
+
+ folder->registerMessage(this);
+}
+
+
+IMAPMessage::IMAPMessage(
+ const shared_ptr <IMAPFolder>& folder,
+ const size_t num,
+ const uid& uid
+)
+ : m_folder(folder),
+ m_num(num),
+ m_size(-1),
+ m_flags(FLAG_UNDEFINED),
+ m_expunged(false),
+ m_uid(uid),
+ m_modseq(0),
+ m_structure(null) {
+
+ folder->registerMessage(this);
+}
+
+
+IMAPMessage::~IMAPMessage() {
+
+ try {
+
+ shared_ptr <IMAPFolder> folder = m_folder.lock();
+
+ if (folder) {
+ folder->unregisterMessage(this);
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+void IMAPMessage::onFolderClosed() {
+
+ m_folder.reset();
+}
+
+
+size_t IMAPMessage::getNumber() const {
+
+ return m_num;
+}
+
+
+const message::uid IMAPMessage::getUID() const {
+
+ return m_uid;
+}
+
+
+vmime_uint64 IMAPMessage::getModSequence() const {
+
+ return m_modseq;
+}
+
+
+size_t IMAPMessage::getSize() const {
+
+ if (m_size == -1U) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_size;
+}
+
+
+bool IMAPMessage::isExpunged() const {
+
+ return m_expunged;
+}
+
+
+int IMAPMessage::getFlags() const {
+
+ if (m_flags == FLAG_UNDEFINED) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_flags;
+}
+
+
+shared_ptr <const messageStructure> IMAPMessage::getStructure() const {
+
+ if (m_structure == NULL) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_structure;
+}
+
+
+shared_ptr <messageStructure> IMAPMessage::getStructure() {
+
+ if (m_structure == NULL) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_structure;
+}
+
+
+shared_ptr <const header> IMAPMessage::getHeader() const {
+
+ if (m_header == NULL) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_header;
+}
+
+
+void IMAPMessage::extract(
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const bool peek
+) const {
+
+ shared_ptr <const IMAPFolder> folder = m_folder.lock();
+
+ if (!folder) {
+ throw exceptions::folder_not_found();
+ }
+
+ extractImpl(
+ null, os, progress, start, length,
+ EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0)
+ );
+}
+
+
+void IMAPMessage::extractPart(
+ const shared_ptr <const messagePart>& p,
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const bool peek
+) const {
+
+ shared_ptr <const IMAPFolder> folder = m_folder.lock();
+
+ if (!folder) {
+ throw exceptions::folder_not_found();
+ }
+
+ extractImpl(
+ p, os, progress, start, length,
+ EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0)
+ );
+}
+
+
+void IMAPMessage::fetchPartHeader(const shared_ptr <messagePart>& p) {
+
+ shared_ptr <IMAPFolder> folder = m_folder.lock();
+
+ if (!folder) {
+ throw exceptions::folder_not_found();
+ }
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter ossAdapter(oss);
+
+ extractImpl(p, ossAdapter, NULL, 0, -1, EXTRACT_HEADER | EXTRACT_PEEK);
+
+ dynamicCast <IMAPMessagePart>(p)->getOrCreateHeader().parse(oss.str());
+}
+
+
+void IMAPMessage::fetchPartHeaderForStructure(const shared_ptr <messageStructure>& str) {
+
+ for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) {
+
+ shared_ptr <messagePart> part = str->getPartAt(i);
+
+ // Fetch header of current part
+ fetchPartHeader(part);
+
+ // Fetch header of sub-parts
+ fetchPartHeaderForStructure(part->getStructure());
+ }
+}
+
+
+size_t IMAPMessage::extractImpl(
+ const shared_ptr <const messagePart>& p,
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const int extractFlags
+) const {
+
+ shared_ptr <const IMAPFolder> folder = m_folder.lock();
+
+ IMAPMessage_literalHandler literalHandler(os, progress);
+
+ if (length == 0) {
+ return 0;
+ }
+
+ // Construct section identifier
+ std::ostringstream section;
+ section.imbue(std::locale::classic());
+
+ if (p != NULL) {
+
+ shared_ptr <const IMAPMessagePart> currentPart = dynamicCast <const IMAPMessagePart>(p);
+ std::vector <size_t> numbers;
+
+ numbers.push_back(currentPart->getNumber());
+ currentPart = currentPart->getParent();
+
+ while (currentPart != NULL) {
+ numbers.push_back(currentPart->getNumber());
+ currentPart = currentPart->getParent();
+ }
+
+ numbers.erase(numbers.end() - 1);
+
+ for (std::vector <size_t>::reverse_iterator it = numbers.rbegin() ; it != numbers.rend() ; ++it) {
+ if (it != numbers.rbegin()) section << ".";
+ section << (*it + 1);
+ }
+ }
+
+ // Build the body descriptor for FETCH
+ /*
+ BODY[] header + body
+ BODY.PEEK[] header + body (peek)
+ BODY[HEADER] header
+ BODY.PEEK[HEADER] header (peek)
+ BODY[TEXT] body
+ BODY.PEEK[TEXT] body (peek)
+ */
+ std::ostringstream bodyDesc;
+ bodyDesc.imbue(std::locale::classic());
+
+ bodyDesc << "BODY";
+
+ if (extractFlags & EXTRACT_PEEK) {
+ bodyDesc << ".PEEK";
+ }
+
+ bodyDesc << "[";
+
+ if (section.str().empty()) {
+
+ // header + body
+ if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) {
+ bodyDesc << "";
+ // body only
+ } else if (extractFlags & EXTRACT_BODY) {
+ bodyDesc << "TEXT";
+ // header only
+ } else if (extractFlags & EXTRACT_HEADER) {
+ bodyDesc << "HEADER";
+ }
+
+ } else {
+
+ bodyDesc << section.str();
+
+ // header + body
+ if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) {
+
+ // First, extract header
+ std::ostringstream header;
+ utility::outputStreamAdapter headerStream(header);
+
+ const size_t headerLength = extractImpl(
+ p, headerStream, /* progress */ NULL,
+ /* start */ 0, /* length */ -1, extractFlags & ~EXTRACT_BODY
+ );
+
+ size_t s = start;
+ size_t l = length;
+
+ if (s < headerLength) {
+
+ if (l == static_cast <size_t>(-1)) {
+
+ os.write(header.str().data() + s, headerLength - s);
+
+ } else {
+
+ size_t headerCopyLength = l;
+
+ if (start + headerCopyLength > headerLength) {
+ headerCopyLength = headerLength - start;
+ }
+
+ os.write(header.str().data() + s, headerCopyLength);
+
+ l -= headerCopyLength;
+ }
+
+ s = 0;
+
+ } else {
+
+ s -= headerLength;
+ }
+
+ // Then, extract body
+ return extractImpl(p, os, progress, s, l, extractFlags & ~EXTRACT_HEADER);
+
+ // header only
+ } else if (extractFlags & EXTRACT_HEADER) {
+
+ bodyDesc << ".MIME"; // "MIME" not "HEADER" for parts
+ }
+ }
+
+ bodyDesc << "]";
+
+ if (start != 0 || length != static_cast <size_t>(-1)) {
+
+ if (length == static_cast <size_t>(-1)) {
+ bodyDesc << "<" << start << "." << static_cast <unsigned int>(-1) << ">";
+ } else {
+ bodyDesc << "<" << start << "." << length << ">";
+ }
+ }
+
+ std::vector <std::string> fetchParams;
+ fetchParams.push_back(bodyDesc.str());
+
+ // Send the request
+ IMAPCommand::FETCH(
+ m_uid.empty() ? messageSet::byNumber(m_num) : messageSet::byUID(m_uid),
+ fetchParams
+ )->send(folder->m_connection);
+
+ // Get the response
+ scoped_ptr <IMAPParser::response> resp(folder->m_connection->readResponse(&literalHandler));
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("FETCH", resp->getErrorLog(), "bad response");
+ }
+
+
+ if (extractFlags & EXTRACT_BODY) {
+ // TODO: update the flags (eg. flag "\Seen" may have been set)
+ }
+
+ return literalHandler.getTarget()->getBytesWritten();
+}
+
+
+int IMAPMessage::processFetchResponse(
+ const fetchAttributes& options,
+ const IMAPParser::message_data& msgData
+) {
+
+ shared_ptr <IMAPFolder> folder = m_folder.lock();
+
+ // Get message attributes
+ int changes = 0;
+
+ for (auto &att : msgData.msg_att->items) {
+
+ switch (att->type) {
+
+ case IMAPParser::msg_att_item::FLAGS: {
+
+ int flags = IMAPUtils::messageFlagsFromFlags(*att->flag_list);
+
+ if (m_flags != flags) {
+ m_flags = flags;
+ changes |= events::messageChangedEvent::TYPE_FLAGS;
+ }
+
+ break;
+ }
+ case IMAPParser::msg_att_item::UID: {
+
+ m_uid = att->uniqueid->value;
+ break;
+ }
+ case IMAPParser::msg_att_item::MODSEQ: {
+
+ m_modseq = att->mod_sequence_value->value;
+ break;
+ }
+ case IMAPParser::msg_att_item::ENVELOPE: {
+
+ if (!options.has(fetchAttributes::FULL_HEADER)) {
+
+ auto* env = att->envelope.get();
+ shared_ptr <vmime::header> hdr = getOrCreateHeader();
+
+ // Date
+ hdr->Date()->setValue(env->env_date->value);
+
+ // Subject
+ text subject;
+ text::decodeAndUnfold(env->env_subject->value, &subject);
+
+ hdr->Subject()->setValue(subject);
+
+ // From
+ mailboxList from;
+ IMAPUtils::convertAddressList(*(env->env_from), from);
+
+ if (!from.isEmpty()) {
+ hdr->From()->setValue(*(from.getMailboxAt(0)));
+ }
+
+ // To
+ mailboxList to;
+ IMAPUtils::convertAddressList(*(env->env_to), to);
+
+ hdr->To()->setValue(to.toAddressList());
+
+ // Sender
+ mailboxList sender;
+ IMAPUtils::convertAddressList(*(env->env_sender), sender);
+
+ if (!sender.isEmpty()) {
+ hdr->Sender()->setValue(*(sender.getMailboxAt(0)));
+ }
+
+ // Reply-to
+ mailboxList replyTo;
+ IMAPUtils::convertAddressList(*(env->env_reply_to), replyTo);
+
+ if (!replyTo.isEmpty()) {
+ hdr->ReplyTo()->setValue(*(replyTo.getMailboxAt(0)));
+ }
+
+ // Cc
+ mailboxList cc;
+ IMAPUtils::convertAddressList(*(env->env_cc), cc);
+
+ if (!cc.isEmpty()) {
+ hdr->Cc()->setValue(cc.toAddressList());
+ }
+
+ // Bcc
+ mailboxList bcc;
+ IMAPUtils::convertAddressList(*(env->env_bcc), bcc);
+
+ if (!bcc.isEmpty()) {
+ hdr->Bcc()->setValue(bcc.toAddressList());
+ }
+ }
+
+ break;
+ }
+ case IMAPParser::msg_att_item::BODY_STRUCTURE: {
+
+ m_structure = make_shared <IMAPMessageStructure>(att->body.get());
+ break;
+ }
+ case IMAPParser::msg_att_item::RFC822_HEADER: {
+
+ getOrCreateHeader()->parse(att->nstring->value);
+ break;
+ }
+ case IMAPParser::msg_att_item::RFC822_SIZE: {
+
+ m_size = static_cast <size_t>(att->number->value);
+ break;
+ }
+ case IMAPParser::msg_att_item::BODY_SECTION: {
+
+ if (!options.has(fetchAttributes::FULL_HEADER)) {
+
+ if (att->section->section_text1 &&
+ att->section->section_text1->type
+ == IMAPParser::section_text::HEADER_FIELDS) {
+
+ header tempHeader;
+ tempHeader.parse(att->nstring->value);
+
+ vmime::header& hdr = *getOrCreateHeader();
+
+ for (auto& fld : tempHeader.getFieldList()) {
+ hdr.appendField(vmime::clone(fld));
+ }
+ }
+ }
+
+ break;
+ }
+ case IMAPParser::msg_att_item::INTERNALDATE:
+ case IMAPParser::msg_att_item::RFC822:
+ case IMAPParser::msg_att_item::RFC822_TEXT:
+ case IMAPParser::msg_att_item::BODY: {
+
+ break;
+ }
+
+ }
+ }
+
+ return changes;
+}
+
+
+shared_ptr <header> IMAPMessage::getOrCreateHeader() {
+
+ if (m_header != NULL) {
+ return m_header;
+ } else {
+ return m_header = make_shared <header>();
+ }
+}
+
+
+void IMAPMessage::setFlags(const int flags, const int mode) {
+
+ shared_ptr <IMAPFolder> folder = m_folder.lock();
+
+ if (!folder) {
+ throw exceptions::folder_not_found();
+ }
+
+ if (!m_uid.empty()) {
+ folder->setMessageFlags(messageSet::byUID(m_uid), flags, mode);
+ } else {
+ folder->setMessageFlags(messageSet::byNumber(m_num), flags, mode);
+ }
+}
+
+
+void IMAPMessage::constructParsedMessage(
+ const shared_ptr <bodyPart>& parentPart,
+ const shared_ptr <messageStructure>& str,
+ int level
+) {
+
+ if (level == 0) {
+
+ shared_ptr <messagePart> part = str->getPartAt(0);
+
+ // Copy header
+ shared_ptr <const header> hdr = part->getHeader();
+ parentPart->getHeader()->copyFrom(*hdr);
+
+ // Initialize body
+ parentPart->getBody()->setContents(
+ make_shared <IMAPMessagePartContentHandler>(
+ dynamicCast <IMAPMessage>(shared_from_this()),
+ part, parentPart->getBody()->getEncoding()
+ )
+ );
+
+ constructParsedMessage(parentPart, part->getStructure(), 1);
+
+ } else {
+
+ for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) {
+
+ shared_ptr <messagePart> part = str->getPartAt(i);
+
+ shared_ptr <bodyPart> childPart = make_shared <bodyPart>();
+
+ // Copy header
+ shared_ptr <const header> hdr = part->getHeader();
+ childPart->getHeader()->copyFrom(*hdr);
+
+ // Initialize body
+ childPart->getBody()->setContents(
+ make_shared <IMAPMessagePartContentHandler>(
+ dynamicCast <IMAPMessage>(shared_from_this()),
+ part, childPart->getBody()->getEncoding()
+ )
+ );
+
+ // Add child part
+ parentPart->getBody()->appendPart(childPart);
+
+ // Construct sub parts
+ constructParsedMessage(childPart, part->getStructure(), ++level);
+ }
+ }
+}
+
+
+shared_ptr <vmime::message> IMAPMessage::getParsedMessage() {
+
+ // Fetch structure
+ shared_ptr <messageStructure> structure;
+
+ try {
+
+ structure = getStructure();
+
+ } catch (exceptions::unfetched_object&) {
+
+ std::vector <shared_ptr <message> > msgs;
+ msgs.push_back(dynamicCast <IMAPMessage>(shared_from_this()));
+
+ m_folder.lock()->fetchMessages(
+ msgs, fetchAttributes(fetchAttributes::STRUCTURE), /* progress */ NULL
+ );
+
+ structure = getStructure();
+ }
+
+ // Fetch header for each part
+ fetchPartHeaderForStructure(structure);
+
+ // Construct message from structure
+ shared_ptr <vmime::message> msg = make_shared <vmime::message>();
+
+ constructParsedMessage(msg, structure);
+
+ return msg;
+}
+
+
+void IMAPMessage::renumber(const size_t number) {
+
+ m_num = number;
+}
+
+
+void IMAPMessage::setExpunged() {
+
+ m_expunged = true;
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPMessage.hpp b/vmime-master/src/vmime/net/imap/IMAPMessage.hpp
new file mode 100644
index 0000000..6d82a3e
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPMessage.hpp
@@ -0,0 +1,200 @@
+//
+// 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_NET_IMAP_IMAPMESSAGE_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPMESSAGE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/message.hpp"
+#include "vmime/net/folder.hpp"
+
+#include "vmime/net/imap/IMAPParser.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class IMAPFolder;
+
+
+/** IMAP message implementation.
+ */
+class VMIME_EXPORT IMAPMessage : public message {
+
+private:
+
+ friend class IMAPFolder;
+ friend class IMAPMessagePartContentHandler;
+
+ IMAPMessage(const IMAPMessage&) : message() { }
+
+public:
+
+ IMAPMessage(const shared_ptr <IMAPFolder>& folder, const size_t num);
+ IMAPMessage(const shared_ptr <IMAPFolder>& folder, const size_t num, const uid& uid);
+
+ ~IMAPMessage();
+
+ size_t getNumber() const;
+
+ const uid getUID() const;
+
+ /** Returns the modification sequence for this message.
+ *
+ * Every time metadata for this message changes, the modification
+ * sequence is updated, and is greater than the previous one. The
+ * server must support the CONDSTORE extension for this to be
+ * available.
+ *
+ * @return modification sequence, or zero if not supported by
+ * the underlying protocol
+ */
+ vmime_uint64 getModSequence() const;
+
+ size_t getSize() const;
+
+ bool isExpunged() const;
+
+ shared_ptr <const messageStructure> getStructure() const;
+ shared_ptr <messageStructure> getStructure();
+
+ shared_ptr <const header> getHeader() const;
+
+ int getFlags() const;
+ void setFlags(const int flags, const int mode = FLAG_MODE_SET);
+
+ void extract(
+ utility::outputStream& os,
+ utility::progressListener* progress = NULL,
+ const size_t start = 0,
+ const size_t length = -1,
+ const bool peek = false
+ ) const;
+
+ void extractPart(
+ const shared_ptr <const messagePart>& p,
+ utility::outputStream& os,
+ utility::progressListener* progress = NULL,
+ const size_t start = 0,
+ const size_t length = -1,
+ const bool peek = false
+ ) const;
+
+ void fetchPartHeader(const shared_ptr <messagePart>& p);
+
+ shared_ptr <vmime::message> getParsedMessage();
+
+private:
+
+ /** Renumbers the message.
+ *
+ * @param number new sequence number
+ */
+ void renumber(const size_t number);
+
+ /** Marks the message as expunged.
+ */
+ void setExpunged();
+
+ /** Processes the parsed response to fill in the attributes
+ * and metadata of this message.
+ *
+ * @param options one or more fetch options (see folder::fetchAttributes)
+ * @param msgData pointer to message_data component of the parsed response
+ * @return a combination of flags that specify what changed exactly on
+ * this message (see events::messageChangedEvent::Types)
+ */
+ int processFetchResponse(const fetchAttributes& options, const IMAPParser::message_data& msgData);
+
+ /** Recursively fetch part header for all parts in the structure.
+ *
+ * @param str structure for which to fetch parts headers
+ */
+ void fetchPartHeaderForStructure(const shared_ptr <messageStructure>& str);
+
+ /** Recursively contruct parsed message from structure.
+ * Called by getParsedMessage().
+ *
+ * @param parentPart root body part (the message)
+ * @param str structure for which to construct part
+ * @param level current nesting level (0 is root)
+ */
+ void constructParsedMessage(
+ const shared_ptr <bodyPart>& parentPart,
+ const shared_ptr <messageStructure>& str,
+ int level = 0
+ );
+
+
+ enum ExtractFlags
+ {
+ EXTRACT_HEADER = 0x1,
+ EXTRACT_BODY = 0x2,
+ EXTRACT_PEEK = 0x10
+ };
+
+ size_t extractImpl(
+ const shared_ptr <const messagePart>& p,
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const int extractFlags
+ ) const;
+
+
+ shared_ptr <header> getOrCreateHeader();
+
+
+ void onFolderClosed();
+
+ weak_ptr <IMAPFolder> m_folder;
+
+ size_t m_num;
+ size_t m_size;
+ int m_flags;
+ bool m_expunged;
+ uid m_uid;
+ vmime_uint64 m_modseq;
+
+ shared_ptr <header> m_header;
+ shared_ptr <messageStructure> m_structure;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPMESSAGE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/imap/IMAPMessagePart.cpp b/vmime-master/src/vmime/net/imap/IMAPMessagePart.cpp
new file mode 100644
index 0000000..ed2c0bd
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPMessagePart.cpp
@@ -0,0 +1,225 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPMessagePart.hpp"
+#include "vmime/net/imap/IMAPMessageStructure.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPMessagePart::IMAPMessagePart(
+ const shared_ptr <IMAPMessagePart>& parent,
+ const size_t number,
+ const IMAPParser::body_type_mpart* mpart
+)
+ : m_parent(parent),
+ m_header(null),
+ m_number(number),
+ m_size(0) {
+
+ m_mediaType = vmime::mediaType(
+ "multipart",
+ mpart->media_subtype->value
+ );
+}
+
+namespace {
+ template<typename T>
+ vmime::string getPartName(const T& body_type) {
+ if (const auto* pparam = body_type->body_fields->body_fld_param.get()) {
+ for (const auto& param : pparam->items) {
+ if (param->string1->value == "NAME") {
+ return param->string2->value;
+ }
+ }
+ }
+
+ return {};
+ }
+}
+
+
+IMAPMessagePart::IMAPMessagePart(
+ const shared_ptr <IMAPMessagePart>& parent,
+ const size_t number,
+ const IMAPParser::body_type_1part* part
+)
+ : m_parent(parent),
+ m_header(null),
+ m_number(number),
+ m_size(0) {
+
+ if (part->body_type_text) {
+
+ m_mediaType = vmime::mediaType(
+ "text",
+ part->body_type_text->media_text->media_subtype->value
+ );
+
+ m_size = part->body_type_text->body_fields->body_fld_octets->value;
+
+ m_name = getPartName(part->body_type_text);
+
+ } else if (part->body_type_msg) {
+
+ m_mediaType = vmime::mediaType(
+ "message",
+ part->body_type_msg->media_message->media_subtype->value
+ );
+
+ } else {
+
+ m_mediaType = vmime::mediaType(
+ part->body_type_basic->media_basic->media_type->value,
+ part->body_type_basic->media_basic->media_subtype->value
+ );
+
+ m_size = part->body_type_basic->body_fields->body_fld_octets->value;
+
+ m_name = getPartName(part->body_type_basic);
+ }
+
+ if (part->body_ext_1part && part->body_ext_1part->body_fld_dsp) {
+ auto *cdisp = part->body_ext_1part->body_fld_dsp->str();
+ if (cdisp) {
+ m_dispType = contentDisposition(cdisp->value);
+ }
+ }
+
+ m_structure = null;
+}
+
+
+shared_ptr <const messageStructure> IMAPMessagePart::getStructure() const {
+
+ if (m_structure) {
+ return m_structure;
+ } else {
+ return IMAPMessageStructure::emptyStructure();
+ }
+}
+
+
+shared_ptr <messageStructure> IMAPMessagePart::getStructure() {
+
+ if (m_structure) {
+ return m_structure;
+ } else {
+ return IMAPMessageStructure::emptyStructure();
+ }
+}
+
+
+shared_ptr <const IMAPMessagePart> IMAPMessagePart::getParent() const {
+
+ return m_parent.lock();
+}
+
+
+const mediaType& IMAPMessagePart::getType() const {
+
+ return m_mediaType;
+}
+
+
+const contentDisposition &IMAPMessagePart::getDisposition() const {
+
+ return m_dispType;
+}
+
+
+size_t IMAPMessagePart::getSize() const {
+
+ return m_size;
+}
+
+
+size_t IMAPMessagePart::getNumber() const {
+
+ return m_number;
+}
+
+
+string IMAPMessagePart::getName() const {
+
+ return m_name;
+}
+
+
+shared_ptr <const header> IMAPMessagePart::getHeader() const {
+
+ if (!m_header) {
+ throw exceptions::unfetched_object();
+ } else {
+ return m_header;
+ }
+}
+
+
+// static
+shared_ptr <IMAPMessagePart> IMAPMessagePart::create(
+ const shared_ptr <IMAPMessagePart>& parent,
+ const size_t number,
+ const IMAPParser::body* body
+) {
+
+ if (body->body_type_mpart) {
+
+ auto part = make_shared <IMAPMessagePart>(parent, number, body->body_type_mpart.get());
+ part->m_structure = make_shared <IMAPMessageStructure>(part, body->body_type_mpart->list);
+
+ return part;
+
+ } else {
+
+ return make_shared <IMAPMessagePart>(parent, number, body->body_type_1part.get());
+ }
+}
+
+
+header& IMAPMessagePart::getOrCreateHeader() {
+
+ if (m_header) {
+ return *m_header;
+ } else {
+ return *(m_header = make_shared <header>());
+ }
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPMessagePart.hpp b/vmime-master/src/vmime/net/imap/IMAPMessagePart.hpp
new file mode 100644
index 0000000..34ea172
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPMessagePart.hpp
@@ -0,0 +1,108 @@
+//
+// 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_NET_IMAP_IMAPMESSAGEPART_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPMESSAGEPART_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/message.hpp"
+
+#include "vmime/net/imap/IMAPParser.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class IMAPMessageStructure;
+
+
+class VMIME_EXPORT IMAPMessagePart : public messagePart {
+
+public:
+
+ IMAPMessagePart(
+ const shared_ptr <IMAPMessagePart>& parent,
+ const size_t number,
+ const IMAPParser::body_type_mpart* mpart
+ );
+
+ IMAPMessagePart(
+ const shared_ptr <IMAPMessagePart>& parent,
+ const size_t number,
+ const IMAPParser::body_type_1part* part
+ );
+
+ shared_ptr <const messageStructure> getStructure() const;
+ shared_ptr <messageStructure> getStructure();
+
+ shared_ptr <const IMAPMessagePart> getParent() const;
+
+ const mediaType& getType() const;
+ const contentDisposition &getDisposition() const;
+ size_t getSize() const;
+ size_t getNumber() const;
+ string getName() const;
+
+ shared_ptr <const header> getHeader() const;
+
+
+ static shared_ptr <IMAPMessagePart> create(
+ const shared_ptr <IMAPMessagePart>& parent,
+ const size_t number,
+ const IMAPParser::body* body
+ );
+
+
+ header& getOrCreateHeader();
+
+private:
+
+ shared_ptr <IMAPMessageStructure> m_structure;
+ weak_ptr <IMAPMessagePart> m_parent;
+ shared_ptr <header> m_header;
+
+ size_t m_number;
+ size_t m_size;
+ string m_name;
+ mediaType m_mediaType;
+ contentDisposition m_dispType;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPMESSAGEPART_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp b/vmime-master/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp
new file mode 100644
index 0000000..85f6cb6
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp
@@ -0,0 +1,227 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPMessagePartContentHandler.hpp"
+#include "vmime/net/imap/IMAPFolder.hpp"
+#include "vmime/net/imap/IMAPConnection.hpp"
+#include "vmime/net/imap/IMAPFolderStatus.hpp"
+#include "vmime/net/imap/IMAPStore.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPMessagePartContentHandler::IMAPMessagePartContentHandler(
+ const shared_ptr <IMAPMessage>& msg,
+ const shared_ptr <messagePart>& part,
+ const vmime::encoding& encoding
+)
+ : m_message(msg),
+ m_part(part),
+ m_encoding(encoding) {
+
+}
+
+
+shared_ptr <contentHandler> IMAPMessagePartContentHandler::clone() const {
+
+ return make_shared <IMAPMessagePartContentHandler>(
+ m_message.lock(), m_part.lock(), m_encoding
+ );
+}
+
+
+void IMAPMessagePartContentHandler::generate(
+ utility::outputStream& os,
+ const vmime::encoding& enc,
+ const size_t maxLineLength
+) const {
+
+ shared_ptr <IMAPMessage> msg = m_message.lock();
+ shared_ptr <messagePart> part = m_part.lock();
+
+ // Data is already encoded
+ if (isEncoded()) {
+
+ // The data is already encoded but the encoding specified for
+ // the generation is different from the current one. We need
+ // to re-encode data: decode from input buffer to temporary
+ // buffer, and then re-encode to output stream...
+ if (m_encoding != enc) {
+
+ // Extract part contents to temporary buffer
+ std::ostringstream oss;
+ utility::outputStreamAdapter tmp(oss);
+
+ msg->extractPart(part, tmp, NULL);
+
+ // Decode to another temporary buffer
+ utility::inputStreamStringAdapter in(oss.str());
+
+ std::ostringstream oss2;
+ utility::outputStreamAdapter tmp2(oss2);
+
+ shared_ptr <utility::encoder::encoder> theDecoder = m_encoding.getEncoder();
+ theDecoder->decode(in, tmp2);
+
+ // Reencode to output stream
+ string str = oss2.str();
+ utility::inputStreamStringAdapter tempIn(str);
+
+ shared_ptr <utility::encoder::encoder> theEncoder = enc.getEncoder();
+ theEncoder->getProperties()["maxlinelength"] = maxLineLength;
+ theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT);
+
+ theEncoder->encode(tempIn, os);
+
+ // No encoding to perform
+ } else {
+
+ msg->extractPart(part, os);
+ }
+
+ // Need to encode data before
+ } else {
+
+ // Extract part contents to temporary buffer
+ std::ostringstream oss;
+ utility::outputStreamAdapter tmp(oss);
+
+ msg->extractPart(part, tmp, NULL);
+
+ // Encode temporary buffer to output stream
+ shared_ptr <utility::encoder::encoder> theEncoder = enc.getEncoder();
+ theEncoder->getProperties()["maxlinelength"] = maxLineLength;
+ theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT);
+
+ utility::inputStreamStringAdapter is(oss.str());
+
+ theEncoder->encode(is, os);
+ }
+}
+
+
+void IMAPMessagePartContentHandler::extract(
+ utility::outputStream& os,
+ utility::progressListener* progress
+) const {
+
+ shared_ptr <IMAPMessage> msg = m_message.lock();
+ shared_ptr <messagePart> part = m_part.lock();
+
+ // No decoding to perform
+ if (!isEncoded()) {
+
+ msg->extractImpl(part, os, progress, 0, -1, IMAPMessage::EXTRACT_BODY);
+
+ // Need to decode data
+ } else {
+
+ // Extract part contents to temporary buffer
+ std::ostringstream oss;
+ utility::outputStreamAdapter tmp(oss);
+
+ msg->extractImpl(part, tmp, NULL, 0, -1, IMAPMessage::EXTRACT_BODY);
+
+ // Encode temporary buffer to output stream
+ utility::inputStreamStringAdapter is(oss.str());
+ utility::progressListenerSizeAdapter plsa(progress, getLength());
+
+ shared_ptr <utility::encoder::encoder> theDecoder = m_encoding.getEncoder();
+ theDecoder->decode(is, os, &plsa);
+ }
+}
+
+
+void IMAPMessagePartContentHandler::extractRaw(
+ utility::outputStream& os,
+ utility::progressListener* progress
+) const {
+
+ shared_ptr <IMAPMessage> msg = m_message.lock();
+ shared_ptr <messagePart> part = m_part.lock();
+
+ msg->extractPart(part, os, progress);
+}
+
+
+size_t IMAPMessagePartContentHandler::getLength() const {
+
+ return m_part.lock()->getSize();
+}
+
+
+bool IMAPMessagePartContentHandler::isEncoded() const {
+
+ return m_encoding != NO_ENCODING;
+}
+
+
+const vmime::encoding& IMAPMessagePartContentHandler::getEncoding() const {
+
+ return m_encoding;
+}
+
+
+bool IMAPMessagePartContentHandler::isEmpty() const {
+
+ return getLength() == 0;
+}
+
+
+bool IMAPMessagePartContentHandler::isBuffered() const {
+
+ return true;
+}
+
+
+void IMAPMessagePartContentHandler::setContentTypeHint(const mediaType& type) {
+
+ m_contentType = type;
+}
+
+
+const mediaType IMAPMessagePartContentHandler::getContentTypeHint() const {
+
+ return m_contentType;
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp b/vmime-master/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp
new file mode 100644
index 0000000..17f53e3
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp
@@ -0,0 +1,95 @@
+//
+// 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_NET_IMAP_IMAPMESSAGEPARTCONTENTHANDLER_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPMESSAGEPARTCONTENTHANDLER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/contentHandler.hpp"
+#include "vmime/net/imap/IMAPMessage.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class VMIME_EXPORT IMAPMessagePartContentHandler : public contentHandler {
+
+public:
+
+ IMAPMessagePartContentHandler(
+ const shared_ptr <IMAPMessage>& msg,
+ const shared_ptr <messagePart>& part,
+ const vmime::encoding& encoding
+ );
+
+ shared_ptr <contentHandler> clone() const;
+
+ void generate(
+ utility::outputStream& os,
+ const vmime::encoding& enc,
+ const size_t maxLineLength = lineLengthLimits::infinite
+ ) const;
+
+ void extract(utility::outputStream& os, utility::progressListener* progress = NULL) const;
+ void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const;
+
+ size_t getLength() const;
+
+ bool isEncoded() const;
+
+ const vmime::encoding& getEncoding() const;
+
+ bool isEmpty() const;
+
+ bool isBuffered() const;
+
+ void setContentTypeHint(const mediaType& type);
+ const mediaType getContentTypeHint() const;
+
+private:
+
+ weak_ptr <IMAPMessage> m_message;
+ weak_ptr <messagePart> m_part;
+
+ vmime::encoding m_encoding;
+ vmime::mediaType m_contentType;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPMESSAGEPARTCONTENTHANDLER_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPMessageStructure.cpp b/vmime-master/src/vmime/net/imap/IMAPMessageStructure.cpp
new file mode 100644
index 0000000..c7ee809
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPMessageStructure.cpp
@@ -0,0 +1,94 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPMessageStructure.hpp"
+#include "vmime/net/imap/IMAPMessagePart.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPMessageStructure::IMAPMessageStructure() {
+}
+
+
+IMAPMessageStructure::IMAPMessageStructure(const IMAPParser::body* body) {
+
+ m_parts.push_back(IMAPMessagePart::create(null, 0, body));
+}
+
+
+IMAPMessageStructure::IMAPMessageStructure(
+ const shared_ptr <IMAPMessagePart>& parent,
+ const std::vector <std::unique_ptr <IMAPParser::body>>& list
+) {
+
+ size_t number = 0;
+
+ for (auto it = list.begin() ; it != list.end() ; ++it, ++number) {
+ m_parts.push_back(IMAPMessagePart::create(parent, number, it->get()));
+ }
+}
+
+
+shared_ptr <const messagePart> IMAPMessageStructure::getPartAt(const size_t x) const {
+
+ return m_parts[x];
+}
+
+
+shared_ptr <messagePart> IMAPMessageStructure::getPartAt(const size_t x) {
+
+ return m_parts[x];
+}
+
+
+size_t IMAPMessageStructure::getPartCount() const {
+
+ return m_parts.size();
+}
+
+
+// static
+shared_ptr <IMAPMessageStructure> IMAPMessageStructure::emptyStructure() {
+
+ static shared_ptr <IMAPMessageStructure> emptyStructure = make_shared <IMAPMessageStructure>();
+ return emptyStructure;
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPMessageStructure.hpp b/vmime-master/src/vmime/net/imap/IMAPMessageStructure.hpp
new file mode 100644
index 0000000..ee1eac4
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPMessageStructure.hpp
@@ -0,0 +1,75 @@
+//
+// 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_NET_IMAP_IMAPMESSAGESTRUCTURE_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPMESSAGESTRUCTURE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/message.hpp"
+
+#include "vmime/net/imap/IMAPParser.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class IMAPMessagePart;
+
+
+class VMIME_EXPORT IMAPMessageStructure : public messageStructure {
+
+public:
+
+ IMAPMessageStructure();
+ IMAPMessageStructure(const IMAPParser::body* body);
+ IMAPMessageStructure(const shared_ptr <IMAPMessagePart>& parent, const std::vector <std::unique_ptr <IMAPParser::body>>& list);
+
+ shared_ptr <const messagePart> getPartAt(const size_t x) const;
+ shared_ptr <messagePart> getPartAt(const size_t x);
+ size_t getPartCount() const;
+
+ static shared_ptr <IMAPMessageStructure> emptyStructure();
+
+private:
+
+ std::vector <shared_ptr <IMAPMessagePart> > m_parts;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPMESSAGESTRUCTURE_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPParser.hpp b/vmime-master/src/vmime/net/imap/IMAPParser.hpp
new file mode 100644
index 0000000..281fcb6
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPParser.hpp
@@ -0,0 +1,4986 @@
+//
+// 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_NET_IMAP_IMAPPARSER_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPPARSER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/base.hpp"
+#include "vmime/dateTime.hpp"
+#include "vmime/charset.hpp"
+#include "vmime/exception.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+#include "vmime/utility/progressListener.hpp"
+
+#include "vmime/utility/encoder/b64Encoder.hpp"
+#include "vmime/utility/encoder/qpEncoder.hpp"
+
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+#include "vmime/utility/outputStreamStringAdapter.hpp"
+
+#include "vmime/platform.hpp"
+
+#include "vmime/net/timeoutHandler.hpp"
+#include "vmime/net/socket.hpp"
+#include "vmime/net/tracer.hpp"
+
+#include "vmime/net/imap/IMAPTag.hpp"
+
+#include <vector>
+#include <stdexcept>
+#include <memory>
+
+
+//#define DEBUG_RESPONSE 1
+
+
+#if DEBUG_RESPONSE
+# include <iostream>
+#endif
+
+
+/** Make the parsing of a component fail.
+ */
+#define VIMAP_PARSER_FAIL() \
+ { \
+ parser.m_errorResponseLine = makeResponseLine(getComponentName(), line, pos); \
+ return false; \
+ }
+
+/** Make the parsing of a component fail if a condition is not matched.
+ * If the specified expression does not resolve to "true", the parsing
+ * will fail.
+ *
+ * @param cond condition expression
+ */
+#define VIMAP_PARSER_FAIL_UNLESS(cond) \
+ if (!(cond)) \
+ { \
+ VIMAP_PARSER_FAIL(); \
+ }
+
+/** Check for a token and advance.
+ * If the token is not matched, parsing will fail.
+ *
+ * @param type token class
+ */
+#define VIMAP_PARSER_CHECK(type) \
+ VIMAP_PARSER_FAIL_UNLESS(parser.check <type>(line, &pos))
+
+/** Check for an optional token and advance.
+ * If the token is not matched, parsing will continue anyway.
+ *
+ * @param type token class
+ */
+#define VIMAP_PARSER_TRY_CHECK(type) \
+ (parser.check <type>(line, &pos))
+
+/** Get a token and advance.
+ * If the token is not matched, parsing will fail.
+ *
+ * @param type token class
+ * @param variable variable which will receive pointer to the retrieved token
+ */
+#define VIMAP_PARSER_GET(type, variable) \
+ { \
+ variable.reset(parser.get <type>(line, &pos)); \
+ VIMAP_PARSER_FAIL_UNLESS(variable.get()); \
+ }
+
+/** Get an optional token and advance.
+ * If the token is not matched, parsing will continue anyway.
+ */
+#define VIMAP_PARSER_TRY_GET(type, variable) \
+ (variable.reset(parser.get <type>(line, &pos)), variable.get())
+
+/** Get an optional token and advance. If found, token will be pushed back
+ * to a vector. If the token is not matched, stopInstr will be executed.
+ *
+ * @param type token class
+ * @param variable variable of type std::vector<> to which the retrieved
+ * token will be pushed
+ * @param stopInstr instruction to execute if token is not found
+ */
+#define VIMAP_PARSER_TRY_GET_PUSHBACK_OR_ELSE(type, variable, stopInstr) \
+ { \
+ std::unique_ptr <type> v; \
+ try \
+ { \
+ v.reset(parser.get <type>(line, &pos)); \
+ if (!v) \
+ { \
+ stopInstr; \
+ } \
+ variable.push_back(std::move(v)); \
+ } \
+ catch (...) \
+ { \
+ throw; \
+ } \
+ }
+
+/** Get a token and advance. Token will be pushed back to a vector.
+ * If the token is not matched, parsing will fail.
+ *
+ * @param type token class
+ * @param variable variable of type std::vector<> to which the retrieved
+ * token will be pushed
+ */
+#define VIMAP_PARSER_GET_PUSHBACK(type, variable) \
+ VIMAP_PARSER_TRY_GET_PUSHBACK_OR_ELSE(type, variable, VIMAP_PARSER_FAIL())
+
+
+/** Check for a token which takes an argument and advance.
+ * If the token is not matched, parsing will fail.
+ *
+ * @param type token class
+ */
+#define VIMAP_PARSER_CHECK_WITHARG(type, arg) \
+ VIMAP_PARSER_FAIL_UNLESS(parser.checkWithArg <type>(line, &pos, arg))
+
+/** Check for an optional token which takes an argument and advance.
+ * If the token is not matched, parsing will continue anyway.
+ *
+ * @param type token class
+ */
+#define VIMAP_PARSER_TRY_CHECK_WITHARG(type, arg) \
+ (parser.checkWithArg <type>(line, &pos, arg))
+
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+#if DEBUG_RESPONSE
+ static int IMAPParserDebugResponse_level = 0;
+ static std::vector <string> IMAPParserDebugResponse_stack;
+
+ class IMAPParserDebugResponse {
+
+ public:
+
+ IMAPParserDebugResponse(
+ const string& name,
+ string& line,
+ const size_t currentPos,
+ const bool &result
+ )
+ : m_name(name),
+ m_line(line),
+ m_pos(currentPos),
+ m_result(result) {
+
+ ++IMAPParserDebugResponse_level;
+ IMAPParserDebugResponse_stack.push_back(name);
+
+ for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i) {
+ std::cout << " ";
+ }
+
+ std::cout << "ENTER(" << m_name << "), pos=" << m_pos;
+ std::cout << std::endl;
+
+ for (std::vector <string>::iterator it = IMAPParserDebugResponse_stack.begin() ;
+ it != IMAPParserDebugResponse_stack.end() ; ++it) {
+
+ std::cout << "> " << *it << " ";
+ }
+
+ std::cout << std::endl;
+ std::cout << string(m_line.begin() + (m_pos < 30 ? 0U : m_pos - 30),
+ m_line.begin() + std::min(m_line.length(), m_pos + 30)) << std::endl;
+
+ for (size_t i = (m_pos < 30 ? m_pos : (m_pos - (m_pos - 30))) ; i != 0 ; --i) {
+ std::cout << " ";
+ }
+
+ std::cout << "^" << std::endl;
+ }
+
+ ~IMAPParserDebugResponse() {
+
+ for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i) {
+ std::cout << " ";
+ }
+
+ std::cout << "LEAVE(" << m_name << "), result=";
+ std::cout << (m_result ? "TRUE" : "FALSE") << ", pos=" << m_pos;
+ std::cout << std::endl;
+
+ --IMAPParserDebugResponse_level;
+ IMAPParserDebugResponse_stack.pop_back();
+ }
+
+ private:
+
+ const string m_name;
+ string m_line;
+ size_t m_pos;
+ const bool& m_result;
+ };
+
+
+ #define DEBUG_ENTER_COMPONENT(x, result) \
+ IMAPParserDebugResponse dbg(x, line, *currentPos, result)
+
+ #define DEBUG_FOUND(x, y) \
+ std::cout << "FOUND: " << x << ": " << y << std::endl;
+#else
+ #define DEBUG_ENTER_COMPONENT(x, result)
+ #define DEBUG_FOUND(x, y)
+#endif
+
+
+class VMIME_EXPORT IMAPParser : public object {
+
+public:
+
+ IMAPParser()
+ : m_progress(NULL),
+ m_strict(false),
+ m_literalHandler(NULL) {
+
+ }
+
+ ~IMAPParser() {
+
+ for (auto it = m_pendingResponses.begin() ; it != m_pendingResponses.end() ; ++it) {
+ delete it->second;
+ }
+ }
+
+
+ /** Set the socket currently used by this parser to receive data
+ * from server.
+ *
+ * @param sok socket
+ */
+ void setSocket(const shared_ptr <socket>& sok) {
+
+ m_socket = sok;
+ }
+
+ /** Set the timeout handler currently used by this parser.
+ *
+ * @param toh timeout handler
+ */
+ void setTimeoutHandler(const shared_ptr <timeoutHandler>& toh) {
+
+ m_timeoutHandler = toh;
+ }
+
+ /** Set the tracer currently used by this parser.
+ *
+ * @param tr tracer
+ */
+ void setTracer(const shared_ptr <tracer>& tr) {
+
+ m_tracer = tr;
+ }
+
+ /** Set whether we operate in strict mode (this may not work
+ * with some servers which are not fully standard-compliant).
+ *
+ * @param strict true to operate in strict mode, or false
+ * to operate in default, relaxed mode
+ */
+ void setStrict(const bool strict) {
+
+ m_strict = strict;
+ }
+
+ /** Return true if the parser operates in strict mode, or
+ * false otherwise.
+ *
+ * @return true if we are in strict mode, false otherwise
+ */
+ bool isStrict() const {
+
+ return m_strict;
+ }
+
+
+
+ //
+ // literalHandler : literal content handler
+ //
+
+ class component;
+
+ class literalHandler {
+
+ public:
+
+ virtual ~literalHandler() { }
+
+
+ // Abstract target class
+ class target {
+
+ protected:
+
+ target(utility::progressListener* progress) : m_progress(progress) {}
+ target(const target&) {}
+
+ public:
+
+ virtual ~target() { }
+
+
+ utility::progressListener* progressListener() { return (m_progress); }
+
+ virtual void putData(const string& chunk) = 0;
+
+ virtual size_t getBytesWritten() const = 0;
+
+ private:
+
+ utility::progressListener* m_progress;
+ };
+
+
+ // Target: put in a string
+ class targetString : public target {
+
+ public:
+
+ targetString(utility::progressListener* progress, vmime::string& str)
+ : target(progress), m_string(str), m_bytesWritten(0) { }
+
+ const vmime::string& string() const { return (m_string); }
+ vmime::string& string() { return (m_string); }
+
+
+ void putData(const vmime::string& chunk) {
+
+ m_string += chunk;
+ m_bytesWritten += chunk.length();
+ }
+
+ size_t getBytesWritten() const {
+
+ return m_bytesWritten;
+ }
+
+ private:
+
+ vmime::string& m_string;
+ size_t m_bytesWritten;
+ };
+
+
+ // Target: redirect to an output stream
+ class targetStream : public target {
+
+ public:
+
+ targetStream(
+ utility::progressListener* progress,
+ utility::outputStream& stream
+ )
+ : target(progress),
+ m_stream(stream),
+ m_bytesWritten(0) {
+
+ }
+
+ const utility::outputStream& stream() const { return (m_stream); }
+ utility::outputStream& stream() { return (m_stream); }
+
+
+ void putData(const string& chunk) {
+
+ m_stream.write(chunk.data(), chunk.length());
+ m_bytesWritten += chunk.length();
+ }
+
+ size_t getBytesWritten() const {
+
+ return m_bytesWritten;
+ }
+
+ private:
+
+ utility::outputStream& m_stream;
+ size_t m_bytesWritten;
+ };
+
+
+ // Called when the parser needs to know what to do with a literal
+ // . comp: the component in which we are at this moment
+ // . data: data specific to the component (may not be used)
+ //
+ // Returns :
+ // . == NULL to put the literal into the response
+ // . != NULL to redirect the literal to the specified target
+
+ virtual shared_ptr <target> targetFor(const component& comp, const int data) = 0;
+ };
+
+
+ //
+ // Base class for a terminal or a non-terminal
+ //
+
+ class component {
+
+ public:
+
+ component() { }
+ virtual ~component() { }
+
+ virtual const string getComponentName() const = 0;
+
+ bool parse(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ bool res = false;
+ DEBUG_ENTER_COMPONENT(getComponentName(), res);
+ res = parseImpl(parser, line, currentPos);
+ return res;
+ }
+
+ virtual bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) = 0;
+
+
+ const string makeResponseLine(
+ const string& comp,
+ const string& line,
+ const size_t pos
+ ) {
+
+#if DEBUG_RESPONSE
+ if (pos > line.length()) {
+ std::cout << "WARNING: component::makeResponseLine(): pos > line.length()" << std::endl;
+ }
+#endif
+
+ string result(line.substr(0, pos));
+ result += "[^]"; // indicates current parser position
+ result += line.substr(pos, line.length());
+ if (!comp.empty()) result += " [" + comp + "]";
+
+ return (result);
+ }
+ };
+
+
+#define COMPONENT_ALIAS(parent, name) \
+ class name : public parent { \
+ virtual const string getComponentName() const { return #name; } \
+ public: \
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { \
+ return parent::parseImpl(parser, line, currentPos); \
+ } \
+ }
+
+#define DECLARE_COMPONENT(name) \
+ class name : public component { \
+ virtual const string getComponentName() const { return #name; } \
+ public:
+
+
+ //
+ // Parse one character
+ //
+
+ template <char C>
+ class one_char : public component {
+
+ public:
+
+ const string getComponentName() const {
+
+ return string("one_char <") + C + ">";
+ }
+
+ bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) {
+
+ const size_t pos = *currentPos;
+
+ if (pos < line.length() && line[pos] == C) {
+ *currentPos = pos + 1;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ };
+
+
+ //
+ // SPACE ::= <ASCII SP, space, 0x20>
+ //
+
+ DECLARE_COMPONENT(SPACE)
+
+ bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ while (pos < line.length() && (line[pos] == ' ' || line[pos] == '\t')) {
+ ++pos;
+ }
+
+ if (pos > *currentPos) {
+ *currentPos = pos;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ };
+
+
+ //
+ // CR ::= <ASCII CR, carriage return, 0x0D>
+ // LF ::= <ASCII LF, line feed, 0x0A>
+ // CRLF ::= CR LF
+ //
+
+ DECLARE_COMPONENT(CRLF)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_TRY_CHECK(SPACE);
+
+ if (pos + 1 < line.length() &&
+ line[pos] == 0x0d && line[pos + 1] == 0x0a) {
+
+ *currentPos = pos + 2;
+ return true;
+
+ } else {
+
+ return false;
+ }
+ }
+ };
+
+
+ //
+ // SPACE ::= <ASCII SP, space, 0x20>
+ // CTL ::= <any ASCII control character and DEL, 0x00 - 0x1f, 0x7f>
+ // CHAR ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f>
+ // ATOM_CHAR ::= <any CHAR except atom_specials>
+ // atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / quoted_specials
+ // list_wildcards ::= "%" / "*"
+ // quoted_specials ::= <"> / "\"
+ //
+ // tag ::= 1*<any ATOM_CHAR except "+"> (named "xtag")
+ //
+
+ DECLARE_COMPONENT(xtag)
+
+ bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ bool end = false;
+
+ tagString.reserve(10);
+
+ while (!end && pos < line.length()) {
+
+ const unsigned char c = line[pos];
+
+ switch (c) {
+
+ case '+':
+ case '(':
+ case ')':
+ case '{':
+ case 0x20: // SPACE
+ case '%': // list_wildcards
+ case '*': // list_wildcards
+ case '"': // quoted_specials
+ case '\\': // quoted_specials
+
+ end = true;
+ break;
+
+ default:
+
+ if (c <= 0x1f || c >= 0x7f) {
+ end = true;
+ } else {
+ tagString += c;
+ ++pos;
+ }
+
+ break;
+ }
+ }
+
+ *currentPos = pos;
+ return true;
+ }
+
+ string tagString;
+ };
+
+
+ //
+ // digit ::= "0" / digit_nz
+ // digit_nz ::= "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"
+ //
+ // number ::= 1*digit
+ // ;; Unsigned 32-bit integer
+ // ;; (0 <= n < 4,294,967,296)
+ //
+
+ DECLARE_COMPONENT(number)
+
+ number(const bool nonZero = false)
+ : value(0),
+ m_nonZero(nonZero) {
+
+ }
+
+ bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ bool valid = true;
+ unsigned int val = 0;
+
+ while (valid && pos < line.length()) {
+
+ const char c = line[pos];
+
+ if (c >= '0' && c <= '9') {
+ val = (val * 10) + (c - '0');
+ ++pos;
+ } else {
+ valid = false;
+ }
+ }
+
+ // Check for non-null length (and for non-zero number)
+ if (!(m_nonZero && val == 0) && pos != *currentPos) {
+ value = val;
+ *currentPos = pos;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ unsigned long value;
+
+ private:
+
+ const bool m_nonZero;
+ };
+
+
+ // nz_number ::= digit_nz *digit
+ // ;; Non-zero unsigned 32-bit integer
+ // ;; (0 < n < 4,294,967,296)
+ //
+
+ class nz_number : public number {
+
+ public:
+
+ nz_number()
+ : number(true) {
+
+ }
+ };
+
+
+ //
+ // uniqueid ::= nz_number
+ // ;; Strictly ascending
+ //
+
+ class uniqueid : public nz_number {
+
+ public:
+
+ uniqueid()
+ : nz_number() {
+
+ }
+ };
+
+
+ // uid-range = (uniqueid ":" uniqueid)
+ // ; two uniqueid values and all values
+ // ; between these two regards of order.
+ // ; Example: 2:4 and 4:2 are equivalent.
+
+ DECLARE_COMPONENT(uid_range)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET(uniqueid, uniqueid1);
+ VIMAP_PARSER_CHECK(one_char <':'>);
+ VIMAP_PARSER_GET(uniqueid, uniqueid2);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <uniqueid> uniqueid1;
+ std::unique_ptr <uniqueid> uniqueid2;
+ };
+
+
+ //
+ // uid-set = (uniqueid / uid-range) *("," uid-set)
+ //
+
+ DECLARE_COMPONENT(uid_set)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ // We have either a 'uid_range' or a 'uniqueid'
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::uid_range, uid_range)) {
+ VIMAP_PARSER_GET(IMAPParser::uniqueid, uniqueid);
+ }
+
+ // And maybe another 'uid-set' following
+ if (VIMAP_PARSER_TRY_CHECK(one_char <','>)) {
+ VIMAP_PARSER_GET(IMAPParser::uid_set, next_uid_set);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::uniqueid> uniqueid;
+ std::unique_ptr <IMAPParser::uid_range> uid_range;
+
+ std::unique_ptr <IMAPParser::uid_set> next_uid_set;
+ };
+
+
+ //
+ // text ::= 1*TEXT_CHAR
+ //
+ // CHAR ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f>
+ // TEXT_CHAR ::= <any CHAR except CR and LF>
+ //
+
+ DECLARE_COMPONENT(text)
+
+ text(bool allow8bits = false, const char except = 0)
+ : m_allow8bits(allow8bits),
+ m_except(except) {
+ }
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+ size_t len = 0;
+
+ if (m_allow8bits || !parser.isStrict()) {
+
+ const unsigned char except = m_except;
+
+ for (bool end = false ; !end && pos < line.length() ; ) {
+
+ const unsigned char c = line[pos];
+
+ if (c == 0x00 || c == 0x0d || c == 0x0a || c == except) {
+ end = true;
+ } else {
+ ++pos;
+ ++len;
+ }
+ }
+
+ } else {
+
+ const unsigned char except = m_except;
+
+ for (bool end = false ; !end && pos < line.length() ; ) {
+
+ const unsigned char c = line[pos];
+
+ if (c < 0x01 || c > 0x7f || c == 0x0d || c == 0x0a || c == except) {
+ end = true;
+ } else {
+ ++pos;
+ ++len;
+ }
+ }
+ }
+
+ if (len == 0) {
+ VIMAP_PARSER_FAIL();
+ }
+
+ value.resize(len);
+ std::copy(line.begin() + *currentPos, line.begin() + pos, value.begin());
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ string value;
+
+ private:
+
+ const bool m_allow8bits;
+ const char m_except;
+ };
+
+
+ class text8 : public text {
+
+ public:
+
+ text8() : text(true) {
+
+ }
+ };
+
+
+ template <char C>
+ class text_except : public text {
+
+ public:
+
+ text_except() : text(false, C) {
+
+ }
+ };
+
+
+ template <char C>
+ class text8_except : public text {
+
+ public:
+
+ text8_except() : text(true, C) {
+
+ }
+ };
+
+
+ //
+ // QUOTED_CHAR ::= <any TEXT_CHAR except quoted_specials> / "\" quoted_specials
+ // quoted_specials ::= <"> / "\"
+ // TEXT_CHAR ::= <any CHAR except CR and LF>
+ // CHAR ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f>
+ //
+
+ DECLARE_COMPONENT(QUOTED_CHAR)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ const unsigned char c = static_cast <unsigned char>(pos < line.length() ? line[pos] : 0);
+
+ if (c >= 0x01 && c <= 0x7f && // 0x01 - 0x7f
+ c != '"' && c != '\\' && // quoted_specials
+ c != '\r' && c != '\n') { // CR and LF
+
+ value = c;
+ *currentPos = pos + 1;
+
+ } else if (c == '\\' && pos + 1 < line.length() &&
+ (line[pos + 1] == '"' || line[pos + 1] == '\\')) {
+
+ value = line[pos + 1];
+ *currentPos = pos + 2;
+
+ } else {
+
+ VIMAP_PARSER_FAIL();
+ }
+
+ return true;
+ }
+
+
+ char value;
+ };
+
+
+ //
+ // quoted ::= <"> *QUOTED_CHAR <">
+ // QUOTED_CHAR ::= <any TEXT_CHAR except quoted_specials> / "\" quoted_specials
+ // quoted_specials ::= <"> / "\"
+ // TEXT_CHAR ::= <any CHAR except CR and LF>
+ // CHAR ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f>
+ //
+
+ DECLARE_COMPONENT(quoted_text)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+ size_t len = 0;
+ bool valid = false;
+
+ value.reserve(line.length() - pos);
+
+ for (bool end = false, quoted = false ; !end && pos < line.length() ; ) {
+
+ const unsigned char c = line[pos];
+
+ if (quoted) {
+
+ if (c == '"' || c == '\\') {
+ value += c;
+ } else {
+ value += '\\';
+ value += c;
+ }
+
+ quoted = false;
+
+ ++pos;
+ ++len;
+
+ } else {
+
+ if (c == '\\') {
+
+ quoted = true;
+
+ ++pos;
+ ++len;
+
+ } else if (c == '"') {
+
+ valid = true;
+ end = true;
+
+ } else if (c >= 0x01 && c <= 0x7f && // CHAR
+ c != 0x0a && c != 0x0d) { // CR and LF
+
+ value += c;
+
+ ++pos;
+ ++len;
+
+ } else {
+
+ valid = false;
+ end = true;
+ }
+ }
+ }
+
+ if (!valid) {
+ VIMAP_PARSER_FAIL();
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ string value;
+ };
+
+
+ //
+ // nil ::= "NIL"
+ //
+
+ DECLARE_COMPONENT(NIL)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "nil");
+
+ *currentPos = pos;
+
+ return true;
+ }
+ };
+
+
+ //
+ // string ::= quoted / literal ----> named 'xstring'
+ //
+ // nil ::= "NIL"
+ // quoted ::= <"> *QUOTED_CHAR <">
+ // QUOTED_CHAR ::= <any TEXT_CHAR except quoted_specials> / "\" quoted_specials
+ // quoted_specials ::= <"> / "\"
+ // TEXT_CHAR ::= <any CHAR except CR and LF>
+ // CHAR ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f>
+ // literal ::= "{" number "}" CRLF *CHAR8
+ // ;; Number represents the number of CHAR8 octets
+ // CHAR8 ::= <any 8-bit octet except NUL, 0x01 - 0xff>
+ //
+
+ DECLARE_COMPONENT(xstring)
+
+ xstring(
+ const bool canBeNIL = false,
+ component* comp = NULL,
+ const int data = 0
+ )
+ : isNIL(true),
+ m_canBeNIL(canBeNIL),
+ m_component(comp),
+ m_data(data) {
+
+ }
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (m_canBeNIL &&
+ VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "nil")) {
+
+ // NIL
+ isNIL = true;
+
+ } else {
+
+ pos = *currentPos;
+
+ isNIL = false;
+
+ // quoted ::= <"> *QUOTED_CHAR <">
+ if (VIMAP_PARSER_TRY_CHECK(one_char <'"'>)) {
+
+ shared_ptr <quoted_text> text;
+ VIMAP_PARSER_GET(quoted_text, text);
+ VIMAP_PARSER_CHECK(one_char <'"'>);
+
+ if (parser.m_literalHandler != NULL) {
+
+ shared_ptr <literalHandler::target> target =
+ parser.m_literalHandler->targetFor(*m_component, m_data);
+
+ if (target != NULL) {
+
+ value = "[literal-handler]";
+
+ const size_t length = text->value.length();
+ utility::progressListener* progress = target->progressListener();
+
+ if (progress) {
+ progress->start(length);
+ }
+
+ target->putData(text->value);
+
+ if (progress) {
+ progress->progress(length, length);
+ progress->stop(length);
+ }
+
+ } else {
+
+ value = text->value;
+ }
+
+ } else {
+
+ value = text->value;
+ }
+
+ DEBUG_FOUND("string[quoted]", "<length=" << value.length() << ", value='" << value << "'>");
+
+ // literal ::= "{" number "}" CRLF *CHAR8
+ } else {
+
+ VIMAP_PARSER_CHECK(one_char <'{'>);
+
+ shared_ptr <number> num;
+ VIMAP_PARSER_GET(number, num);
+
+ const size_t length = num->value;
+
+ VIMAP_PARSER_CHECK(one_char <'}'> );
+
+ VIMAP_PARSER_CHECK(CRLF);
+
+
+ if (parser.m_literalHandler != NULL) {
+
+ shared_ptr <literalHandler::target> target =
+ parser.m_literalHandler->targetFor(*m_component, m_data);
+
+ if (target != NULL) {
+
+ value = "[literal-handler]";
+
+ parser.m_progress = target->progressListener();
+ parser.readLiteral(*target, length);
+ parser.m_progress = NULL;
+
+ } else {
+
+ literalHandler::targetString target(NULL, value);
+ parser.readLiteral(target, length);
+ }
+
+ } else {
+
+ literalHandler::targetString target(NULL, value);
+ parser.readLiteral(target, length);
+ }
+
+ line += parser.readLine();
+
+ DEBUG_FOUND("string[literal]", "<length=" << length << ", value='" << value << "'>");
+ }
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ bool isNIL;
+ string value;
+
+ private:
+
+ bool m_canBeNIL;
+
+ component* m_component;
+ const int m_data;
+ };
+
+
+ //
+ // nstring ::= string / nil
+ //
+
+ class nstring : public xstring {
+
+ public:
+
+ const string getComponentName() const {
+
+ return "nstring";
+ }
+
+ nstring(component* comp = NULL, const int data = 0)
+ : xstring(true, comp, data) {
+
+ }
+ };
+
+
+ //
+ // astring ::= atom / string
+ //
+
+ DECLARE_COMPONENT(astring)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ std::unique_ptr <xstring> str;
+ VIMAP_PARSER_TRY_GET(xstring, str);
+
+ if (str) {
+ value = str->value;
+ } else {
+ std::unique_ptr <atom> at;
+ VIMAP_PARSER_GET(atom, at);
+ value = at->value;
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ string value;
+ };
+
+
+ //
+ // atom ::= 1*ATOM_CHAR
+ //
+ // ATOM_CHAR ::= <any CHAR except atom_specials>
+ // atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / quoted_specials
+ // CHAR ::= <any 7-bit US-ASCII character except NUL, 0x01 - 0x7f>
+ // CTL ::= <any ASCII control character and DEL, 0x00 - 0x1f, 0x7f>
+ // list_wildcards ::= "%" / "*"
+ // quoted_specials ::= <"> / "\"
+ // SPACE ::= <ASCII SP, space, 0x20>
+ //
+
+ DECLARE_COMPONENT(atom)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+ size_t len = 0;
+
+ for (bool end = false ; !end && pos < line.length() ; ) {
+
+ const unsigned char c = line[pos];
+
+ switch (c) {
+
+ case '(':
+ case ')':
+ case '{':
+ case 0x20: // SPACE
+ case '%': // list_wildcards
+ case '*': // list_wildcards
+ case '"': // quoted_specials
+ case '\\': // quoted_specials
+
+ case '[':
+ case ']': // for "special_atom"
+
+ end = true;
+ break;
+
+ default:
+
+ if (c <= 0x1f || c >= 0x7f) {
+ end = true;
+ } else {
+ ++pos;
+ ++len;
+ }
+ }
+ }
+
+ if (len != 0) {
+
+ value.resize(len);
+ std::copy(line.begin() + *currentPos, line.begin() + pos, value.begin());
+
+ *currentPos = pos;
+
+ } else {
+
+ VIMAP_PARSER_FAIL();
+ }
+
+ return true;
+ }
+
+
+ string value;
+ };
+
+
+ //
+ // special atom (eg. "CAPABILITY", "FLAGS", "STATUS"...)
+ //
+ // " Except as noted otherwise, all alphabetic characters are case-
+ // insensitive. The use of upper or lower case characters to define
+ // token strings is for editorial clarity only. Implementations MUST
+ // accept these strings in a case-insensitive fashion. "
+ //
+
+ class special_atom : public atom {
+
+ public:
+
+ const std::string getComponentName() const {
+
+ return string("special_atom <") + m_string + ">";
+ }
+
+ special_atom(const char* str)
+ : m_string(str) { // 'string' must be in lower-case
+
+ }
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (!atom::parseImpl(parser, line, &pos)) {
+ return false;
+ }
+
+ const char* cmp = value.c_str();
+ const char* with = m_string;
+
+ bool ok = true;
+
+ while (ok && *cmp && *with) {
+
+ ok = (std::tolower(*cmp, std::locale()) == *with);
+
+ ++cmp;
+ ++with;
+ }
+
+ if (!ok || *cmp || *with) {
+ VIMAP_PARSER_FAIL();
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+ private:
+
+ const char* m_string;
+ };
+
+
+ //
+ // text_mime2 ::= "=?" <charset> "?" <encoding> "?" <encoded-text> "?="
+ // ;; Syntax defined in [MIME-HDRS]
+ //
+
+ DECLARE_COMPONENT(text_mime2)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ std::unique_ptr <atom> theCharset, theEncoding;
+ std::unique_ptr <text> theText;
+
+ VIMAP_PARSER_CHECK(one_char <'='> );
+ VIMAP_PARSER_CHECK(one_char <'?'> );
+
+ VIMAP_PARSER_GET(atom, theCharset);
+
+ VIMAP_PARSER_CHECK(one_char <'?'> );
+
+ VIMAP_PARSER_GET(atom, theEncoding);
+
+ VIMAP_PARSER_CHECK(one_char <'?'> );
+
+ VIMAP_PARSER_GET(text8_except <'?'> , theText);
+
+ VIMAP_PARSER_CHECK(one_char <'?'> );
+ VIMAP_PARSER_CHECK(one_char <'='> );
+
+ charset = theCharset->value;
+
+ // Decode text
+ scoped_ptr <utility::encoder::encoder> theEncoder;
+
+ if (theEncoding->value[0] == 'q' || theEncoding->value[0] == 'Q') {
+
+ // Quoted-printable
+ theEncoder.reset(new utility::encoder::qpEncoder());
+ theEncoder->getProperties()["rfc2047"] = true;
+
+ } else if (theEncoding->value[0] == 'b' || theEncoding->value[0] == 'B') {
+
+ // Base64
+ theEncoder.reset(new utility::encoder::b64Encoder());
+ }
+
+ if (theEncoder.get()) {
+
+ utility::inputStreamStringAdapter in(theText->value);
+ utility::outputStreamStringAdapter out(value);
+
+ theEncoder->decode(in, out);
+
+ // No decoder available
+ } else {
+
+ value = theText->value;
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ vmime::charset charset;
+ string value;
+ };
+
+
+ // seq-number = nz-number / "*"
+ // ; message sequence number (COPY, FETCH, STORE
+ // ; commands) or unique identifier (UID COPY,
+ // ; UID FETCH, UID STORE commands).
+
+ DECLARE_COMPONENT(seq_number)
+
+ seq_number()
+ : star(false) {
+
+ }
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (VIMAP_PARSER_TRY_CHECK(one_char <'*'> )) {
+
+ star = true;
+ number.reset();
+
+ } else {
+
+ star = false;
+ VIMAP_PARSER_GET(IMAPParser::number, number);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::number> number;
+ bool star;
+ };
+
+
+ // seq-range = seq-number ":" seq-number
+ // ; two seq-number values and all values between
+ // ; these two regardless of order.
+ // ; Example: 2:4 and 4:2 are equivalent and indicate
+ // ; values 2, 3, and 4.
+
+ DECLARE_COMPONENT(seq_range)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET(seq_number, first);
+
+ VIMAP_PARSER_CHECK(one_char <'*'> );
+
+ VIMAP_PARSER_GET(seq_number, last);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::seq_number> first;
+ std::unique_ptr <IMAPParser::seq_number> last;
+ };
+
+
+ // sequence-set = (seq-number / seq-range) *("," sequence-set)
+ // ; set of seq-number values, regardless of order.
+ // ; Servers MAY coalesce overlaps and/or execute the
+ // ; sequence in any order.
+ // ; Example: a message sequence number set of
+ // ; 2,4:7,9,12:* for a mailbox with 15 messages is
+ // ; equivalent to 2,4,5,6,7,9,12,13,14,15
+
+ DECLARE_COMPONENT(sequence_set)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::seq_range, range)) {
+ VIMAP_PARSER_GET(IMAPParser::seq_number, number);
+ }
+
+ if (VIMAP_PARSER_TRY_CHECK(one_char <','> )) {
+ VIMAP_PARSER_GET(sequence_set, nextSet);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::seq_number> number;
+ std::unique_ptr <IMAPParser::seq_range> range;
+ std::unique_ptr <IMAPParser::sequence_set> nextSet;
+ };
+
+
+ // mod-sequence-value = 1*DIGIT
+ // ;; Positive unsigned 64-bit integer
+ // ;; (mod-sequence)
+ // ;; (1 <= n < 18,446,744,073,709,551,615)
+
+ DECLARE_COMPONENT(mod_sequence_value)
+
+ mod_sequence_value()
+ : value(0) {
+
+ }
+
+ bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ bool valid = true;
+ vmime_uint64 val = 0;
+
+ while (valid && pos < line.length()) {
+
+ const char c = line[pos];
+
+ if (c >= '0' && c <= '9') {
+ val = (val * 10) + (c - '0');
+ ++pos;
+ } else {
+ valid = false;
+ }
+ }
+
+ value = val;
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ vmime_uint64 value;
+ };
+
+
+ //
+ // flag ::= "\Answered" / "\Flagged" / "\Deleted" /
+ // "\Seen" / "\Draft" / flag_keyword / flag_extension
+ //
+ // flag_extension ::= "\" atom
+ // ;; Future expansion. Client implementations
+ // ;; MUST accept flag_extension flags. Server
+ // ;; implementations MUST NOT generate
+ // ;; flag_extension flags except as defined by
+ // ;; future standard or standards-track
+ // ;; revisions of this specification.
+ //
+ // flag_keyword ::= atom
+ //
+
+ DECLARE_COMPONENT(flag)
+
+ flag()
+ : type(UNKNOWN) {
+
+ }
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (VIMAP_PARSER_TRY_CHECK(one_char <'\\'> )) {
+
+ if (VIMAP_PARSER_TRY_CHECK(one_char <'*'> )) {
+
+ type = STAR;
+
+ } else {
+
+ shared_ptr <atom> at;
+ VIMAP_PARSER_GET(atom, at);
+
+ const string tname = utility::stringUtils::toLower(at->value);
+
+ if (tname == "answered") {
+ type = ANSWERED;
+ } else if (tname == "flagged") {
+ type = FLAGGED;
+ } else if (tname == "deleted") {
+ type = DELETED;
+ } else if (tname == "seen") {
+ type = SEEN;
+ } else if (tname == "draft") {
+ type = DRAFT;
+ } else {
+ type = UNKNOWN;
+ name = tname;
+ }
+ }
+
+ } else {
+
+ if (!parser.isStrict() && VIMAP_PARSER_TRY_CHECK(one_char <'*'> )) {
+ type = STAR; // map "*" to "\*"
+ } else {
+ type = KEYWORD_OR_EXTENSION;
+ VIMAP_PARSER_GET(atom, flag_keyword);
+ }
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ enum Type {
+ UNKNOWN,
+ ANSWERED,
+ FLAGGED,
+ DELETED,
+ SEEN,
+ DRAFT,
+ KEYWORD_OR_EXTENSION,
+ STAR // * = custom flags allowed
+ };
+
+
+ Type type;
+ string name;
+
+ std::unique_ptr <IMAPParser::atom> flag_keyword;
+ };
+
+
+ //
+ // flag_list ::= "(" #flag ")"
+ //
+
+ DECLARE_COMPONENT(flag_list)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'('> );
+
+ while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) {
+ VIMAP_PARSER_GET_PUSHBACK(flag, flags);
+ VIMAP_PARSER_TRY_CHECK(SPACE);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::vector <std::unique_ptr <flag>> flags;
+ };
+
+
+ //
+ // mailbox ::= "INBOX" / astring
+ // ;; INBOX is case-insensitive. All case variants of
+ // ;; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX
+ // ;; not as an astring. Refer to section 5.1 for
+ // ;; further semantic details of mailbox names.
+ //
+
+ DECLARE_COMPONENT(mailbox)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "inbox")) {
+
+ type = INBOX;
+ name = "INBOX";
+
+ } else {
+
+ type = OTHER;
+
+ std::unique_ptr <astring> astr;
+ VIMAP_PARSER_GET(astring, astr);
+ name = astr->value;
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ enum Type {
+ INBOX,
+ OTHER
+ };
+
+
+ Type type;
+ string name;
+ };
+
+
+ //
+ // mailbox_flag := "\Marked" / "\Noinferiors" /
+ // "\Noselect" / "\Unmarked" / flag_extension
+ //
+
+ DECLARE_COMPONENT(mailbox_flag)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (VIMAP_PARSER_TRY_CHECK(one_char <'\\'> )) {
+
+ std::unique_ptr <atom> at;
+ VIMAP_PARSER_GET(atom, at);
+
+ const string tname = utility::stringUtils::toLower(at->value);
+
+ type = UNKNOWN; // default
+
+ switch (tname[0]) {
+
+ case 'a':
+
+ if (tname == "all") {
+ type = SPECIALUSE_ALL;
+ } else if (tname == "archive") {
+ type = SPECIALUSE_ARCHIVE;
+ }
+
+ break;
+
+ case 'd':
+
+ if (tname == "drafts") {
+ type = SPECIALUSE_DRAFTS;
+ }
+
+ break;
+
+ case 'f':
+
+ if (tname == "flagged") {
+ type = SPECIALUSE_FLAGGED;
+ }
+
+ break;
+
+ case 'h':
+
+ if (tname == "haschildren") {
+ type = HASCHILDREN;
+ } else if (tname == "hasnochildren") {
+ type = HASNOCHILDREN;
+ }
+
+ break;
+
+ case 'i':
+
+ if (tname == "important") {
+ type = SPECIALUSE_IMPORTANT;
+ }
+
+ break;
+
+ case 'j':
+
+ if (tname == "junk") {
+ type = SPECIALUSE_JUNK;
+ }
+
+ break;
+
+ case 'm':
+
+ if (tname == "marked") {
+ type = MARKED;
+ }
+
+ break;
+
+ case 'n':
+
+ if (tname == "noinferiors") {
+ type = NOINFERIORS;
+ } else if (tname == "noselect") {
+ type = NOSELECT;
+ }
+
+ break;
+
+ case 's':
+
+ if (tname == "sent") {
+ type = SPECIALUSE_SENT;
+ }
+
+ break;
+
+ case 't':
+
+ if (tname == "trash") {
+ type = SPECIALUSE_TRASH;
+ }
+
+ break;
+
+ case 'u':
+
+ if (tname == "unmarked") {
+ type = UNMARKED;
+ }
+
+ break;
+ }
+
+ if (type == UNKNOWN) {
+ name = "\\" + tname;
+ }
+
+ } else {
+
+ std::unique_ptr <atom> at;
+ VIMAP_PARSER_GET(atom, at);
+ const string tname = utility::stringUtils::toLower(at->value);
+
+ type = UNKNOWN;
+ name = tname;
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ enum Type {
+ // RFC-3348 - Child Mailbox Extension
+ HASCHILDREN,
+ HASNOCHILDREN,
+
+ // RFC-6154 - Special-Use Mailboxes
+ SPECIALUSE_ALL,
+ SPECIALUSE_ARCHIVE,
+ SPECIALUSE_DRAFTS,
+ SPECIALUSE_FLAGGED,
+ SPECIALUSE_JUNK,
+ SPECIALUSE_SENT,
+ SPECIALUSE_TRASH,
+ SPECIALUSE_IMPORTANT, // draft
+
+ // Standard mailbox flags
+ UNKNOWN,
+ MARKED,
+ NOINFERIORS,
+ NOSELECT,
+ UNMARKED
+ };
+
+
+ Type type;
+ string name;
+ };
+
+
+ //
+ // mailbox_flag_list ::= "(" #(mailbox_flag) ")"
+ //
+
+ DECLARE_COMPONENT(mailbox_flag_list)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'('> );
+
+ while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) {
+ VIMAP_PARSER_GET_PUSHBACK(mailbox_flag, flags);
+ VIMAP_PARSER_TRY_CHECK(SPACE);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::vector <std::unique_ptr <mailbox_flag>> flags;
+ };
+
+
+ //
+ // mailbox_list ::= mailbox_flag_list SPACE
+ // (<"> QUOTED_CHAR <"> / nil) SPACE mailbox
+ //
+
+ DECLARE_COMPONENT(mailbox_list)
+
+ mailbox_list()
+ : quoted_char('\0') {
+
+ }
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET(IMAPParser::mailbox_flag_list, mailbox_flag_list);
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ if (!VIMAP_PARSER_TRY_CHECK(NIL)) {
+
+ VIMAP_PARSER_CHECK(one_char <'"'> );
+
+ std::unique_ptr <QUOTED_CHAR> qc;
+ VIMAP_PARSER_GET(QUOTED_CHAR, qc);
+ quoted_char = qc->value;
+
+ VIMAP_PARSER_CHECK(one_char <'"'> );
+ }
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::mailbox, mailbox);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::mailbox_flag_list> mailbox_flag_list;
+ std::unique_ptr <IMAPParser::mailbox> mailbox;
+
+ char quoted_char;
+ };
+
+
+ //
+ // auth_type ::= atom
+ // ;; Defined by [IMAP-AUTH]
+ //
+
+ DECLARE_COMPONENT(auth_type)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ std::unique_ptr <atom> at;
+ VIMAP_PARSER_GET(atom, at);
+
+ name = utility::stringUtils::toLower(at->value);
+
+ if (name == "kerberos_v4") {
+ type = KERBEROS_V4;
+ } else if (name == "gssapi") {
+ type = GSSAPI;
+ } else if (name == "skey") {
+ type = SKEY;
+ } else {
+ type = UNKNOWN;
+ }
+
+ return true;
+ }
+
+
+ enum Type {
+ UNKNOWN,
+
+ // RFC 1731 - IMAP4 Authentication Mechanisms
+ KERBEROS_V4,
+ GSSAPI,
+ SKEY
+ };
+
+
+ Type type;
+ string name;
+ };
+
+
+ //
+ // status-att-val = ("MESSAGES" SP number) /
+ // ("RECENT" SP number) /
+ // ("UIDNEXT" SP nz-number) /
+ // ("UIDVALIDITY" SP nz-number) /
+ // ("UNSEEN" SP number)
+ //
+ // IMAP Extension for Conditional STORE (RFC-4551):
+ //
+ // status-att-val =/ "HIGHESTMODSEQ" SP mod-sequence-valzer
+ // ;; extends non-terminal defined in [IMAPABNF].
+ // ;; Value 0 denotes that the mailbox doesn't
+ // ;; support persistent mod-sequences
+ //
+
+ DECLARE_COMPONENT(status_att_val)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ // "HIGHESTMODSEQ" SP mod-sequence-valzer
+ if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "highestmodseq")) {
+
+ type = HIGHESTMODSEQ;
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::mod_sequence_value, value);
+
+ } else {
+
+ if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "messages")) {
+ type = MESSAGES;
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "recent")) {
+ type = RECENT;
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnext")) {
+ type = UIDNEXT;
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidvalidity")) {
+ type = UIDVALIDITY;
+ } else {
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "unseen");
+ type = UNSEEN;
+ }
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::number, value);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ enum Type {
+ // Extensions
+ HIGHESTMODSEQ,
+
+ // Standard IMAP
+ MESSAGES,
+ RECENT,
+ UIDNEXT,
+ UIDVALIDITY,
+ UNSEEN
+ };
+
+
+ Type type;
+ std::unique_ptr <IMAPParser::component> value;
+
+
+ const IMAPParser::number* value_as_number() const {
+ return dynamic_cast <IMAPParser::number *>(value.get());
+ }
+
+ const IMAPParser::mod_sequence_value* value_as_mod_sequence_value() const {
+ return dynamic_cast <IMAPParser::mod_sequence_value *>(value.get());
+ }
+ };
+
+
+ // status-att-list = status-att-val *(SP status-att-val)
+
+ DECLARE_COMPONENT(status_att_list)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET_PUSHBACK(IMAPParser::status_att_val, values);
+
+ while (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+ VIMAP_PARSER_GET_PUSHBACK(IMAPParser::status_att_val, values);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::vector <std::unique_ptr <status_att_val>> values;
+ };
+
+
+ //
+ // capability ::= "AUTH=" auth_type / atom
+ // ;; New capabilities MUST begin with "X" or be
+ // ;; registered with IANA as standard or standards-track
+ //
+
+ DECLARE_COMPONENT(capability)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET(IMAPParser::atom, atom);
+
+ string value = atom->value;
+ const char* str = value.c_str();
+
+ if ((str[0] == 'a' || str[0] == 'A') &&
+ (str[1] == 'u' || str[1] == 'U') &&
+ (str[2] == 't' || str[2] == 'T') &&
+ (str[3] == 'h' || str[3] == 'H') &&
+ (str[4] == '=')) {
+
+ size_t pos = 5;
+ auth_type.reset(parser.get <IMAPParser::auth_type>(value, &pos));
+
+ atom.reset();
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::auth_type> auth_type;
+ std::unique_ptr <IMAPParser::atom> atom;
+ };
+
+
+ //
+ // capability_data ::= "CAPABILITY" SPACE [1#capability SPACE] "IMAP4rev1"
+ // [SPACE 1#capability]
+ // ;; IMAP4rev1 servers which offer RFC 1730
+ // ;; compatibility MUST list "IMAP4" as the first
+ // ;; capability.
+ //
+
+ DECLARE_COMPONENT(capability_data)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "capability");
+
+ while (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+
+ std::unique_ptr <capability> cap;
+
+ if (parser.isStrict() || capabilities.empty()) {
+ VIMAP_PARSER_GET(capability, cap);
+ } else {
+ VIMAP_PARSER_TRY_GET(capability, cap); // allow SPACE at end of line (Apple iCloud IMAP server)
+ }
+
+ if (!cap) {
+ break;
+ }
+
+ capabilities.push_back(std::move(cap));
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::vector <std::unique_ptr <capability>> capabilities;
+ };
+
+
+ //
+ // date_day_fixed ::= (SPACE digit) / 2digit
+ // ;; Fixed-format version of date_day
+ //
+ // date_month ::= "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
+ // "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
+ //
+ // date_year ::= 4digit
+ //
+ // time ::= 2digit ":" 2digit ":" 2digit
+ // ;; Hours minutes seconds
+ //
+ // zone ::= ("+" / "-") 4digit
+ // ;; Signed four-digit value of hhmm representing
+ // ;; hours and minutes west of Greenwich (that is,
+ // ;; (the amount that the given time differs from
+ // ;; Universal Time). Subtracting the timezone
+ // ;; from the given time will give the UT form.
+ // ;; The Universal Time zone is "+0000".
+ //
+ // date_time ::= <"> date_day_fixed "-" date_month "-" date_year
+ // SPACE time SPACE zone <">
+ //
+
+ DECLARE_COMPONENT(date_time)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ // <"> date_day_fixed "-" date_month "-" date_year
+ VIMAP_PARSER_CHECK(one_char <'"'> );
+ VIMAP_PARSER_TRY_CHECK(SPACE);
+
+ shared_ptr <number> nd;
+ VIMAP_PARSER_GET(number, nd);
+
+ VIMAP_PARSER_CHECK(one_char <'-'> );
+
+ shared_ptr <atom> amo;
+ VIMAP_PARSER_GET(atom, amo);
+
+ VIMAP_PARSER_CHECK(one_char <'-'> );
+
+ shared_ptr <number> ny;
+ VIMAP_PARSER_GET(number, ny);
+
+ VIMAP_PARSER_TRY_CHECK(SPACE);
+
+ // 2digit ":" 2digit ":" 2digit
+ shared_ptr <number> nh;
+ VIMAP_PARSER_GET(number, nh);
+
+ VIMAP_PARSER_CHECK(one_char <':'> );
+
+ shared_ptr <number> nmi;
+ VIMAP_PARSER_GET(number, nmi);
+
+ VIMAP_PARSER_CHECK(one_char <':'> );
+
+ shared_ptr <number> ns;
+ VIMAP_PARSER_GET(number, ns);
+
+ VIMAP_PARSER_TRY_CHECK(SPACE);
+
+ // ("+" / "-") 4digit
+ int sign = 1;
+
+ if (!(VIMAP_PARSER_TRY_CHECK(one_char <'+'> ))) {
+ VIMAP_PARSER_CHECK(one_char <'-'> );
+ }
+
+ shared_ptr <number> nz;
+ VIMAP_PARSER_GET(number, nz);
+
+ VIMAP_PARSER_CHECK(one_char <'"'> );
+
+
+ m_datetime.setHour(static_cast <int>(std::min(std::max(nh->value, 0ul), 23ul)));
+ m_datetime.setMinute(static_cast <int>(std::min(std::max(nmi->value, 0ul), 59ul)));
+ m_datetime.setSecond(static_cast <int>(std::min(std::max(ns->value, 0ul), 59ul)));
+
+ const int zone = static_cast <int>(nz->value);
+ const int zh = zone / 100; // hour offset
+ const int zm = zone % 100; // minute offset
+
+ m_datetime.setZone(((zh * 60) + zm) * sign);
+
+ m_datetime.setDay(static_cast <int>(std::min(std::max(nd->value, 1ul), 31ul)));
+ m_datetime.setYear(static_cast <int>(ny->value));
+
+ const string month(utility::stringUtils::toLower(amo->value));
+ int mon = vmime::datetime::JANUARY;
+
+ if (month.length() >= 3) {
+
+ switch (month[0]) {
+
+ case 'j': {
+
+ switch (month[1]) {
+
+ case 'a': mon = vmime::datetime::JANUARY; break;
+ case 'u': {
+
+ switch (month[2]) {
+
+ case 'n': mon = vmime::datetime::JUNE; break;
+ default: mon = vmime::datetime::JULY; break;
+ }
+
+ break;
+ }
+
+ }
+
+ break;
+ }
+ case 'f': mon = vmime::datetime::FEBRUARY; break;
+ case 'm': {
+
+ switch (month[2]) {
+ case 'r': mon = vmime::datetime::MARCH; break;
+ default: mon = vmime::datetime::MAY; break;
+ }
+
+ break;
+ }
+ case 'a':
+ {
+ switch (month[1]) {
+ case 'p': mon = vmime::datetime::APRIL; break;
+ default: mon = vmime::datetime::AUGUST; break;
+ }
+
+ break;
+ }
+ case 's': mon = vmime::datetime::SEPTEMBER; break;
+ case 'o': mon = vmime::datetime::OCTOBER; break;
+ case 'n': mon = vmime::datetime::NOVEMBER; break;
+ case 'd': mon = vmime::datetime::DECEMBER; break;
+ }
+ }
+
+ m_datetime.setMonth(mon);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+ private:
+
+ vmime::datetime m_datetime;
+ };
+
+
+ //
+ // header_fld_name ::= astring
+ //
+
+ COMPONENT_ALIAS(astring, header_fld_name);
+
+
+ //
+ // header_list ::= "(" 1#header_fld_name ")"
+ //
+
+ DECLARE_COMPONENT(header_list)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'('> );
+
+ while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) {
+ VIMAP_PARSER_GET_PUSHBACK(header_fld_name, fld_names);
+ VIMAP_PARSER_TRY_CHECK(SPACE);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::vector <std::unique_ptr <header_fld_name>> fld_names;
+ };
+
+
+ //
+ // body_extension ::= nstring / number / "(" 1#body_extension ")"
+ // ;; Future expansion. Client implementations
+ // ;; MUST accept body_extension fields. Server
+ // ;; implementations MUST NOT generate
+ // ;; body_extension fields except as defined by
+ // ;; future standard or standards-track
+ // ;; revisions of this specification.
+ //
+
+ DECLARE_COMPONENT(body_extension)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) {
+
+ VIMAP_PARSER_GET_PUSHBACK(body_extension, body_extensions);
+
+ while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) {
+ VIMAP_PARSER_GET_PUSHBACK(body_extension, body_extensions);
+ VIMAP_PARSER_TRY_CHECK(SPACE);
+ }
+
+ } else {
+
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::nstring, nstring)) {
+ VIMAP_PARSER_GET(IMAPParser::number, number);
+ }
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::nstring> nstring;
+ std::unique_ptr <IMAPParser::number> number;
+
+ std::vector <std::unique_ptr <body_extension>> body_extensions;
+ };
+
+
+ //
+ // section_text ::= "HEADER" / "HEADER.FIELDS" [".NOT"]
+ // SPACE header_list / "TEXT" / "MIME"
+ //
+
+ DECLARE_COMPONENT(section_text)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ // "HEADER.FIELDS" [".NOT"] SPACE header_list
+ const bool b1 = VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "header.fields.not");
+ const bool b2 = (b1 ? false : VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "header.fields"));
+
+ if (b1 || b2) {
+
+ type = b1 ? HEADER_FIELDS_NOT : HEADER_FIELDS;
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::header_list, header_list);
+
+ // "HEADER"
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "header")) {
+
+ type = HEADER;
+
+ // "MIME"
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "mime")) {
+
+ type = MIME;
+
+ // "TEXT"
+ } else {
+
+ type = TEXT;
+
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "text");
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ enum Type {
+ HEADER,
+ HEADER_FIELDS,
+ HEADER_FIELDS_NOT,
+ MIME,
+ TEXT
+ };
+
+
+ Type type;
+ std::unique_ptr <IMAPParser::header_list> header_list;
+ };
+
+
+ //
+ // section ::= "[" [section_text / (nz_number *["." nz_number]
+ // ["." (section_text / "MIME")])] "]"
+ //
+
+ DECLARE_COMPONENT(section)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'['> );
+
+ if (!VIMAP_PARSER_TRY_CHECK(one_char <']'> )) {
+
+ if (!VIMAP_PARSER_TRY_GET(section_text, section_text1)) {
+
+ std::unique_ptr <nz_number> num;
+ VIMAP_PARSER_GET(nz_number, num);
+ nz_numbers.push_back(static_cast <unsigned int>(num->value));
+
+ while (VIMAP_PARSER_TRY_CHECK(one_char <'.'> )) {
+
+ if (VIMAP_PARSER_TRY_GET(nz_number, num)) {
+ nz_numbers.push_back(static_cast <unsigned int>(num->value));
+ } else {
+ VIMAP_PARSER_GET(section_text, section_text2);
+ break;
+ }
+ }
+ }
+
+ VIMAP_PARSER_CHECK(one_char <']'> );
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <section_text> section_text1;
+ std::unique_ptr <section_text> section_text2;
+ std::vector <unsigned int> nz_numbers;
+ };
+
+
+ //
+ // addr_adl ::= nstring
+ // ;; Holds route from [RFC-822] route-addr if
+ // ;; non-NIL
+ //
+ // addr_host ::= nstring
+ // ;; NIL indicates [RFC-822] group syntax.
+ // ;; Otherwise, holds [RFC-822] domain name
+ //
+ // addr_mailbox ::= nstring
+ // ;; NIL indicates end of [RFC-822] group; if
+ // ;; non-NIL and addr_host is NIL, holds
+ // ;; [RFC-822] group name.
+ // ;; Otherwise, holds [RFC-822] local-part
+ //
+ // addr_name ::= nstring
+ // ;; Holds phrase from [RFC-822] mailbox if
+ // ;; non-NIL
+ //
+ // address ::= "(" addr_name SPACE addr_adl SPACE addr_mailbox
+ // SPACE addr_host ")"
+ //
+
+ DECLARE_COMPONENT(address)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'('> );
+ VIMAP_PARSER_GET(nstring, addr_name);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(nstring, addr_adl);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(nstring, addr_mailbox);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(nstring, addr_host);
+ VIMAP_PARSER_CHECK(one_char <')'> );
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <nstring> addr_name;
+ std::unique_ptr <nstring> addr_adl;
+ std::unique_ptr <nstring> addr_mailbox;
+ std::unique_ptr <nstring> addr_host;
+ };
+
+
+ //
+ // address_list ::= "(" 1*address ")" / nil
+ //
+
+ DECLARE_COMPONENT(address_list)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (!VIMAP_PARSER_TRY_CHECK(NIL)) {
+
+ VIMAP_PARSER_CHECK(one_char <'('> );
+
+ while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) {
+ VIMAP_PARSER_GET_PUSHBACK(address, addresses);
+ VIMAP_PARSER_TRY_CHECK(SPACE);
+ }
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::vector <std::unique_ptr <address>> addresses;
+ };
+
+
+ //
+ // env_bcc ::= "(" 1*address ")" / nil
+ //
+
+ COMPONENT_ALIAS(address_list, env_bcc);
+
+
+ //
+ // env_cc ::= "(" 1*address ")" / nil
+ //
+
+ COMPONENT_ALIAS(address_list, env_cc);
+
+
+ //
+ // env_date ::= nstring
+ //
+
+ COMPONENT_ALIAS(nstring, env_date);
+
+
+ //
+ // env_from ::= "(" 1*address ")" / nil
+ //
+
+ COMPONENT_ALIAS(address_list, env_from);
+
+
+ //
+ // env_in_reply_to ::= nstring
+ //
+
+ COMPONENT_ALIAS(nstring, env_in_reply_to);
+
+
+ //
+ // env_message_id ::= nstring
+ //
+
+ COMPONENT_ALIAS(nstring, env_message_id);
+
+
+ //
+ // env_reply_to ::= "(" 1*address ")" / nil
+ //
+
+ COMPONENT_ALIAS(address_list, env_reply_to);
+
+
+ //
+ // env_sender ::= "(" 1*address ")" / nil
+ //
+
+ COMPONENT_ALIAS(address_list, env_sender);
+
+
+ //
+ // env_subject ::= nstring
+ //
+
+ COMPONENT_ALIAS(nstring, env_subject);
+
+
+ //
+ // env_to ::= "(" 1*address ")" / nil
+ //
+
+ COMPONENT_ALIAS(address_list, env_to);
+
+
+ //
+ // envelope ::= "(" env_date SPACE env_subject SPACE env_from
+ // SPACE env_sender SPACE env_reply_to SPACE env_to
+ // SPACE env_cc SPACE env_bcc SPACE env_in_reply_to
+ // SPACE env_message_id ")"
+ //
+
+ DECLARE_COMPONENT(envelope)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'('> );
+
+ VIMAP_PARSER_GET(IMAPParser::env_date, env_date);
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::env_subject, env_subject);
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::env_from, env_from);
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::env_sender, env_sender);
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::env_reply_to, env_reply_to);
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::env_to, env_to);
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::env_cc, env_cc);
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::env_bcc, env_bcc);
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::env_in_reply_to, env_in_reply_to);
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::env_message_id, env_message_id);
+
+ VIMAP_PARSER_CHECK(one_char <')'> );
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::env_date> env_date;
+ std::unique_ptr <IMAPParser::env_subject> env_subject;
+ std::unique_ptr <IMAPParser::env_from> env_from;
+ std::unique_ptr <IMAPParser::env_sender> env_sender;
+ std::unique_ptr <IMAPParser::env_reply_to> env_reply_to;
+ std::unique_ptr <IMAPParser::env_to> env_to;
+ std::unique_ptr <IMAPParser::env_cc> env_cc;
+ std::unique_ptr <IMAPParser::env_bcc> env_bcc;
+ std::unique_ptr <IMAPParser::env_in_reply_to> env_in_reply_to;
+ std::unique_ptr <IMAPParser::env_message_id> env_message_id;
+ };
+
+
+ //
+ // body_fld_desc ::= nstring
+ //
+
+ COMPONENT_ALIAS(nstring, body_fld_desc);
+
+
+ //
+ // body_fld_id ::= nstring
+ //
+
+ COMPONENT_ALIAS(nstring, body_fld_id);
+
+
+ //
+ // body_fld_md5 ::= nstring
+ //
+
+ COMPONENT_ALIAS(nstring, body_fld_md5);
+
+
+ //
+ // body_fld_octets ::= number
+ //
+
+ COMPONENT_ALIAS(number, body_fld_octets);
+
+
+ //
+ // body_fld_lines ::= number
+ //
+
+ COMPONENT_ALIAS(number, body_fld_lines);
+
+
+ //
+ // body_fld_enc ::= (<"> ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
+ // "QUOTED-PRINTABLE") <">) / string
+ //
+
+ class body_fld_enc : public nstring {
+
+ public:
+
+ const string getComponentName() const {
+
+ return "body_fld_enc";
+ }
+
+ body_fld_enc() {
+
+ }
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (!xstring::parseImpl(parser, line, &pos)) {
+ return false;
+ }
+
+ // " When an IMAP4 client sends a FETCH (bodystructure) request
+ // to a server that is running the Exchange Server 2007 IMAP4
+ // service, a corrupted response is sent as a reply "
+ // (see http://support.microsoft.com/kb/975918/en-us)
+ //
+ // Fail in strict mode
+ if (isNIL && parser.isStrict()) {
+ VIMAP_PARSER_FAIL();
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+ };
+
+
+ //
+ // body_fld_param_item ::= string SPACE string
+ //
+
+ DECLARE_COMPONENT(body_fld_param_item)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (!parser.isStrict()) {
+
+ // Some servers send an <atom> instead of a <string> here:
+ // eg. ... (CHARSET "X-UNKNOWN") ...
+ if (!VIMAP_PARSER_TRY_GET(xstring, string1)) {
+
+ std::unique_ptr <atom> at;
+ VIMAP_PARSER_GET(atom, at);
+
+ string1.reset(new xstring());
+ string1->value = at->value;
+ }
+
+ } else {
+
+ VIMAP_PARSER_GET(xstring, string1);
+ }
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ if (!parser.isStrict()) {
+
+ // In non-strict mode, allow NIL in value
+ std::unique_ptr <nstring> nstr;
+ VIMAP_PARSER_GET(nstring, nstr);
+
+ string2.reset(new xstring());
+ string2->value = nstr->value;
+
+ } else {
+
+ VIMAP_PARSER_GET(xstring, string2);
+ }
+
+ DEBUG_FOUND("body_fld_param_item", "<" << string1->value << ", " << string2->value << ">");
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <xstring> string1;
+ std::unique_ptr <xstring> string2;
+ };
+
+
+ //
+ // body_fld_param ::= "(" 1#(body_fld_param_item) ")" / nil
+ //
+
+ DECLARE_COMPONENT(body_fld_param)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) {
+
+ bool isNIL = false;
+
+ if (!parser.isStrict()) {
+
+ // In non-strict mode, allow "()" instead of "NIL"
+ if (VIMAP_PARSER_TRY_CHECK(one_char <')'> )) {
+ isNIL = true;
+ }
+ }
+
+ if (!isNIL) {
+
+ VIMAP_PARSER_GET_PUSHBACK(body_fld_param_item, items);
+
+ while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) {
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET_PUSHBACK(body_fld_param_item, items);
+ }
+ }
+
+ } else {
+
+ VIMAP_PARSER_CHECK(NIL);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::vector <std::unique_ptr <body_fld_param_item>> items;
+ };
+
+
+ //
+ // body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil
+ //
+
+ DECLARE_COMPONENT(body_fld_dsp)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) {
+
+ VIMAP_PARSER_GET(xstring, m_string);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(class body_fld_param, m_body_fld_param);
+ VIMAP_PARSER_CHECK(one_char <')'> );
+
+ } else {
+
+ VIMAP_PARSER_CHECK(NIL);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+ private:
+
+ std::unique_ptr <class xstring> m_string;
+ std::unique_ptr <class body_fld_param> m_body_fld_param;
+
+ public:
+
+ const class xstring* str() const { return m_string.get(); }
+ const class body_fld_param* body_fld_param() const { return m_body_fld_param.get(); }
+ };
+
+
+ //
+ // body_fld_lang ::= nstring / "(" 1#string ")"
+ //
+
+ DECLARE_COMPONENT(body_fld_lang)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) {
+
+ VIMAP_PARSER_GET_PUSHBACK(xstring, strings);
+
+ while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) {
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET_PUSHBACK(xstring, strings);
+ }
+
+ } else {
+
+ VIMAP_PARSER_GET_PUSHBACK(nstring, strings);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::vector <std::unique_ptr <xstring>> strings;
+ };
+
+
+ //
+ // body_fields ::= body_fld_param SPACE body_fld_id SPACE
+ // body_fld_desc SPACE body_fld_enc SPACE
+ // body_fld_octets
+ //
+
+ DECLARE_COMPONENT(body_fields)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET(IMAPParser::body_fld_param, body_fld_param);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::body_fld_id, body_fld_id);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::body_fld_desc, body_fld_desc);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::body_fld_enc, body_fld_enc);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::body_fld_octets, body_fld_octets);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::body_fld_param> body_fld_param;
+ std::unique_ptr <IMAPParser::body_fld_id> body_fld_id;
+ std::unique_ptr <IMAPParser::body_fld_desc> body_fld_desc;
+ std::unique_ptr <IMAPParser::body_fld_enc> body_fld_enc;
+ std::unique_ptr <IMAPParser::body_fld_octets> body_fld_octets;
+ };
+
+
+ //
+ // media_subtype ::= string
+ // ;; Defined in [MIME-IMT]
+ //
+
+ COMPONENT_ALIAS(xstring, media_subtype);
+
+
+ //
+ // media_text ::= <"> "TEXT" <"> SPACE media_subtype
+ // ;; Defined in [MIME-IMT]
+ //
+
+ DECLARE_COMPONENT(media_text)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'"'> );
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "text");
+ VIMAP_PARSER_CHECK(one_char <'"'> );
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::media_subtype, media_subtype);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::media_subtype> media_subtype;
+ };
+
+
+ //
+ // media_message ::= <"> "MESSAGE" <"> SPACE <"> "RFC822" <">
+ // ;; Defined in [MIME-IMT]
+ //
+
+ DECLARE_COMPONENT(media_message)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'"'> );
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "message");
+ VIMAP_PARSER_CHECK(one_char <'"'> );
+ VIMAP_PARSER_CHECK(SPACE);
+
+ //VIMAP_PARSER_CHECK(one_char <'"'> );
+ //VIMAP_PARSER_CHECK_WITHARG(special_atom, "rfc822");
+ //VIMAP_PARSER_CHECK(one_char <'"'> );
+
+ VIMAP_PARSER_GET(IMAPParser::media_subtype, media_subtype);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::media_subtype> media_subtype;
+ };
+
+
+ //
+ // media_basic ::= (<"> ("APPLICATION" / "AUDIO" / "IMAGE" /
+ // "MESSAGE" / "VIDEO") <">) / string)
+ // SPACE media_subtype
+ // ;; Defined in [MIME-IMT]
+
+ DECLARE_COMPONENT(media_basic)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET(xstring, media_type);
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::media_subtype, media_subtype);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::xstring> media_type;
+ std::unique_ptr <IMAPParser::media_subtype> media_subtype;
+ };
+
+
+ //
+ // body_ext_1part ::= body_fld_md5 [SPACE body_fld_dsp
+ // [SPACE body_fld_lang
+ // [SPACE 1#body_extension]]]
+ // ;; MUST NOT be returned on non-extensible
+ // ;; "BODY" fetch
+ //
+
+ DECLARE_COMPONENT(body_ext_1part)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos)
+ {
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET(IMAPParser::body_fld_md5, body_fld_md5);
+
+ // [SPACE body_fld_dsp
+ if (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+
+ VIMAP_PARSER_GET(IMAPParser::body_fld_dsp, body_fld_dsp);
+
+ // [SPACE body_fld_lang
+ if (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+
+ VIMAP_PARSER_GET(IMAPParser::body_fld_lang, body_fld_lang);
+
+ // [SPACE 1#body_extension]
+ if (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+
+ VIMAP_PARSER_GET_PUSHBACK(body_extension, body_extensions);
+
+ while (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+ VIMAP_PARSER_GET_PUSHBACK(body_extension, body_extensions);
+ }
+ }
+ }
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::body_fld_md5> body_fld_md5;
+ std::unique_ptr <IMAPParser::body_fld_dsp> body_fld_dsp;
+ std::unique_ptr <IMAPParser::body_fld_lang> body_fld_lang;
+
+ std::vector <std::unique_ptr <body_extension>> body_extensions;
+ };
+
+
+ //
+ // body_ext_mpart ::= body_fld_param
+ // [SPACE body_fld_dsp [SPACE body_fld_lang
+ // [SPACE 1#body_extension]]]
+ // ;; MUST NOT be returned on non-extensible
+ // ;; "BODY" fetch
+
+ DECLARE_COMPONENT(body_ext_mpart)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET(IMAPParser::body_fld_param, body_fld_param);
+
+ // [SPACE body_fld_dsp [SPACE body_fld_lang [SPACE 1#body_extension]]]
+ if (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+
+ VIMAP_PARSER_GET(IMAPParser::body_fld_dsp, body_fld_dsp);
+
+ if (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+
+ VIMAP_PARSER_GET(IMAPParser::body_fld_lang, body_fld_lang);
+
+ // [SPACE 1#body_extension]
+ if (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+
+ VIMAP_PARSER_GET_PUSHBACK(body_extension, body_extensions);
+
+ while (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+ VIMAP_PARSER_GET_PUSHBACK(body_extension, body_extensions);
+ }
+ }
+ }
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::body_fld_param> body_fld_param;
+ std::unique_ptr <IMAPParser::body_fld_dsp> body_fld_dsp;
+ std::unique_ptr <IMAPParser::body_fld_lang> body_fld_lang;
+
+ std::vector <std::unique_ptr <body_extension>> body_extensions;
+ };
+
+
+ //
+ // body_type_basic ::= media_basic SPACE body_fields
+ // ;; MESSAGE subtype MUST NOT be "RFC822"
+ //
+
+ DECLARE_COMPONENT(body_type_basic)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET(IMAPParser::media_basic, media_basic);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::body_fields, body_fields);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::media_basic> media_basic;
+ std::unique_ptr <IMAPParser::body_fields> body_fields;
+ };
+
+
+ //
+ // body_type_msg ::= media_message SPACE body_fields SPACE envelope
+ // SPACE body SPACE body_fld_lines
+ //
+
+ class xbody;
+ typedef xbody body;
+
+ DECLARE_COMPONENT(body_type_msg)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET(IMAPParser::media_message, media_message);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::body_fields, body_fields);
+ VIMAP_PARSER_CHECK(SPACE);
+
+ // BUGFIX: made SPACE optional. This is not standard, but some servers
+ // seem to return responses like that...
+ VIMAP_PARSER_GET(IMAPParser::envelope, envelope);
+ VIMAP_PARSER_TRY_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::xbody, body);
+ VIMAP_PARSER_TRY_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::body_fld_lines, body_fld_lines);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::media_message> media_message;
+ std::unique_ptr <IMAPParser::body_fields> body_fields;
+ std::unique_ptr <IMAPParser::envelope> envelope;
+ std::unique_ptr <IMAPParser::xbody> body;
+ std::unique_ptr <IMAPParser::body_fld_lines> body_fld_lines;
+ };
+
+
+ //
+ // body_type_text ::= media_text SPACE body_fields SPACE body_fld_lines
+ //
+
+ DECLARE_COMPONENT(body_type_text)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET(IMAPParser::media_text, media_text);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::body_fields, body_fields);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::body_fld_lines, body_fld_lines);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::media_text> media_text;
+ std::unique_ptr <IMAPParser::body_fields> body_fields;
+ std::unique_ptr <IMAPParser::body_fld_lines> body_fld_lines;
+ };
+
+
+ //
+ // body_type_1part ::= (body_type_basic / body_type_msg / body_type_text)
+ // [SPACE body_ext_1part]
+ //
+
+ DECLARE_COMPONENT(body_type_1part)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_text, body_type_text)) {
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_msg, body_type_msg)) {
+ VIMAP_PARSER_GET(IMAPParser::body_type_basic, body_type_basic);
+ }
+ }
+
+ if (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_ext_1part, body_ext_1part)) {
+ --pos;
+ }
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::body_type_basic> body_type_basic;
+ std::unique_ptr <IMAPParser::body_type_msg> body_type_msg;
+ std::unique_ptr <IMAPParser::body_type_text> body_type_text;
+
+ std::unique_ptr <IMAPParser::body_ext_1part> body_ext_1part;
+ };
+
+
+ //
+ // body_type_mpart ::= 1*body SPACE media_subtype
+ // [SPACE body_ext_mpart]
+ //
+
+ DECLARE_COMPONENT(body_type_mpart)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET_PUSHBACK(xbody, list);
+
+ while (true) {
+ VIMAP_PARSER_TRY_GET_PUSHBACK_OR_ELSE(xbody, list, break);
+ }
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::media_subtype, media_subtype);
+
+ if (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+ VIMAP_PARSER_GET(IMAPParser::body_ext_mpart, body_ext_mpart);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::media_subtype> media_subtype;
+ std::unique_ptr <IMAPParser::body_ext_mpart> body_ext_mpart;
+
+ std::vector <std::unique_ptr <xbody>> list;
+ };
+
+
+ //
+ // xbody ::= "(" body_type_1part / body_type_mpart ")"
+ //
+
+ DECLARE_COMPONENT(xbody)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'('> );
+
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_mpart, body_type_mpart)) {
+ VIMAP_PARSER_GET(IMAPParser::body_type_1part, body_type_1part);
+ }
+
+ VIMAP_PARSER_CHECK(one_char <')'> );
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::body_type_1part> body_type_1part;
+ std::unique_ptr <IMAPParser::body_type_mpart> body_type_mpart;
+ };
+
+
+ // msg_att_item ::= "ENVELOPE" SPACE envelope /
+ // "FLAGS" SPACE "(" #(flag / "\Recent") ")" /
+ // "INTERNALDATE" SPACE date_time /
+ // "RFC822" [".HEADER" / ".TEXT"] SPACE nstring /
+ // "RFC822.SIZE" SPACE number /
+ // "BODY" ["STRUCTURE"] SPACE body /
+ // "BODY" section ["<" number ">"] SPACE nstring /
+ // "UID" SPACE uniqueid
+ //
+ // IMAP Extension for Conditional STORE (RFC-4551):
+ //
+ // msg_att_item /= "MODSEQ" SP "(" mod_sequence_value ")"
+
+ DECLARE_COMPONENT(msg_att_item)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ // "ENVELOPE" SPACE envelope
+ if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "envelope")) {
+
+ type = ENVELOPE;
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::envelope, envelope);
+
+ // "FLAGS" SPACE "(" #(flag / "\Recent") ")"
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "flags")) {
+
+ type = FLAGS;
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::flag_list, flag_list);
+
+ // "INTERNALDATE" SPACE date_time
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "internaldate")) {
+
+ type = INTERNALDATE;
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::date_time, date_time);
+
+ // "RFC822" ".HEADER" SPACE nstring
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.header")) {
+
+ type = RFC822_HEADER;
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::nstring, nstring);
+
+ // "RFC822" ".TEXT" SPACE nstring
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.text")) {
+
+ type = RFC822_TEXT;
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ nstring.reset(parser.getWithArgs <IMAPParser::nstring>(line, &pos, this, RFC822_TEXT));
+
+ VIMAP_PARSER_FAIL_UNLESS(nstring);
+
+ // "RFC822.SIZE" SPACE number
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.size")) {
+
+ type = RFC822_SIZE;
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::number, number);
+
+ // "RFC822" SPACE nstring
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822")) {
+
+ type = RFC822;
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::nstring, nstring);
+
+ // "BODY" "STRUCTURE" SPACE body
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "bodystructure")) {
+
+ type = BODY_STRUCTURE;
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::body, body);
+
+ // "BODY" section ["<" number ">"] SPACE nstring
+ // "BODY" SPACE body
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "body")) {
+
+ VIMAP_PARSER_TRY_GET(IMAPParser::section, section);
+
+ // "BODY" section ["<" number ">"] SPACE nstring
+ if (section != NULL) {
+
+ type = BODY_SECTION;
+
+ if (VIMAP_PARSER_TRY_CHECK(one_char <'<'> )) {
+ VIMAP_PARSER_GET(IMAPParser::number, number);
+ VIMAP_PARSER_CHECK(one_char <'>'> );
+ }
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ nstring.reset(parser.getWithArgs <IMAPParser::nstring>(line, &pos, this, BODY_SECTION));
+
+ VIMAP_PARSER_FAIL_UNLESS(nstring);
+
+ // "BODY" SPACE body
+ } else {
+
+ type = BODY;
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::body, body);
+ }
+
+ // "MODSEQ" SP "(" mod_sequence_value ")"
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "modseq")) {
+
+ type = MODSEQ;
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_CHECK(one_char <'('> );
+
+ VIMAP_PARSER_GET(IMAPParser::mod_sequence_value, mod_sequence_value);
+
+ VIMAP_PARSER_CHECK(one_char <')'> );
+
+ // "UID" SPACE uniqueid
+ } else {
+
+ type = UID;
+
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "uid");
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::uniqueid, uniqueid);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ enum Type {
+ ENVELOPE,
+ FLAGS,
+ INTERNALDATE,
+ RFC822,
+ RFC822_SIZE,
+ RFC822_HEADER,
+ RFC822_TEXT,
+ BODY,
+ BODY_SECTION,
+ BODY_STRUCTURE,
+ UID,
+ MODSEQ
+ };
+
+
+ Type type;
+
+ std::unique_ptr <IMAPParser::date_time> date_time;
+ std::unique_ptr <IMAPParser::number> number;
+ std::unique_ptr <IMAPParser::envelope> envelope;
+ std::unique_ptr <IMAPParser::uniqueid> uniqueid;
+ std::unique_ptr <IMAPParser::nstring> nstring;
+ std::unique_ptr <IMAPParser::xbody> body;
+ std::unique_ptr <IMAPParser::flag_list> flag_list;
+ std::unique_ptr <IMAPParser::section> section;
+ std::unique_ptr <IMAPParser::mod_sequence_value> mod_sequence_value;
+ };
+
+
+ //
+ // msg_att ::= "(" 1#(msg_att_item) ")"
+ //
+
+ DECLARE_COMPONENT(msg_att)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'('> );
+
+ items.push_back(std::move(std::unique_ptr <msg_att_item>(parser.get <msg_att_item>(line, &pos))));
+
+ while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) {
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET_PUSHBACK(msg_att_item, items);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::vector <std::unique_ptr <msg_att_item>> items;
+ };
+
+
+ //
+ // message_data ::= nz_number SPACE ("EXPUNGE" /
+ // ("FETCH" SPACE msg_att))
+ //
+
+ DECLARE_COMPONENT(message_data)
+
+ message_data()
+ : number(0) {
+
+ }
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ scoped_ptr <nz_number> num;
+ VIMAP_PARSER_GET(nz_number, num);
+ number = static_cast <unsigned int>(num->value);
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "expunge")) {
+
+ type = EXPUNGE;
+
+ } else {
+
+ type = FETCH;
+
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "fetch");
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::msg_att, msg_att);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ enum Type {
+ EXPUNGE,
+ FETCH
+ };
+
+
+ Type type;
+ unsigned int number;
+ std::unique_ptr <IMAPParser::msg_att> msg_att;
+ };
+
+
+ //
+ // resp_text_code ::= "ALERT" / "PARSE" /
+ // capability-data /
+ // "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" /
+ // "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
+ // "UIDVALIDITY" SPACE nz_number /
+ // "UNSEEN" SPACE nz_number /
+ // "UIDNEXT" SPACE nz-number /
+ // atom [SPACE 1*<any TEXT_CHAR except "]">]
+ //
+ // IMAP Extension for Conditional STORE (RFC-4551):
+ //
+ // resp-text-code =/ "HIGHESTMODSEQ" SP mod-sequence-value /
+ // "NOMODSEQ" /
+ // "MODIFIED" SP set
+ //
+ // IMAP UIDPLUS Extension (RFC-4315):
+ //
+ // resp-text-code =/ "APPENDUID" SP nz-number SP append-uid /
+ // "COPYUID" SP nz-number SP uid-set SP uid-set /
+ // "UIDNOTSTICKY"
+
+ DECLARE_COMPONENT(resp_text_code)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ // "ALERT"
+ if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "alert")) {
+
+ type = ALERT;
+
+ // "PARSE"
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "parse")) {
+
+ type = PARSE;
+
+ // capability_data
+ } else if (VIMAP_PARSER_TRY_GET(IMAPParser::capability_data, capability_data)) {
+
+ type = CAPABILITY;
+
+ // "PERMANENTFLAGS" SPACE flag_list
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "permanentflags")) {
+
+ type = PERMANENTFLAGS;
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::flag_list, flag_list);
+
+ // "READ-ONLY"
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "read-only")) {
+
+ type = READ_ONLY;
+
+ // "READ-WRITE"
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "read-write")) {
+
+ type = READ_WRITE;
+
+ // "TRYCREATE"
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "trycreate")) {
+
+ type = TRYCREATE;
+
+ // "UIDVALIDITY" SPACE nz_number
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidvalidity")) {
+
+ type = UIDVALIDITY;
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::nz_number, nz_number);
+
+ // "UIDNEXT" SPACE nz_number
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnext")) {
+
+ type = UIDNEXT;
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::nz_number, nz_number);
+
+ // "UNSEEN" SPACE nz_number
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "unseen")) {
+
+ type = UNSEEN;
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::nz_number, nz_number);
+
+ // "HIGHESTMODSEQ" SP mod-sequence-value
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "highestmodseq")) {
+
+ type = HIGHESTMODSEQ;
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::mod_sequence_value, mod_sequence_value);
+
+ // "NOMODSEQ"
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "nomodseq")) {
+
+ type = NOMODSEQ;
+
+ // "MODIFIED" SP sequence-set
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "modified")) {
+
+ type = MODIFIED;
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::sequence_set, sequence_set);
+
+ // "APPENDUID" SP nz-number SP append-uid
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "appenduid")) {
+
+ type = APPENDUID;
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::nz_number, nz_number);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::uid_set, uid_set);
+
+ // "COPYUID" SP nz-number SP uid-set SP uid-set
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "copyuid")) {
+
+ type = COPYUID;
+
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::nz_number, nz_number);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::uid_set, uid_set);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::uid_set, uid_set2);
+
+ // "UIDNOTSTICKY"
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnotsticky")) {
+
+ type = UIDNOTSTICKY;
+
+ // atom [SPACE 1*<any TEXT_CHAR except "]">]
+ } else {
+
+ type = OTHER;
+
+ VIMAP_PARSER_GET(IMAPParser::atom, atom);
+
+ if (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+ VIMAP_PARSER_GET(text_except <']'> , text);
+ }
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ enum Type {
+ // Extensions
+ HIGHESTMODSEQ,
+ NOMODSEQ,
+ MODIFIED,
+ APPENDUID,
+ COPYUID,
+ UIDNOTSTICKY,
+
+ // Standard IMAP
+ ALERT,
+ PARSE,
+ CAPABILITY,
+ PERMANENTFLAGS,
+ READ_ONLY,
+ READ_WRITE,
+ TRYCREATE,
+ UIDVALIDITY,
+ UIDNEXT,
+ UNSEEN,
+ OTHER
+ };
+
+
+ Type type;
+
+ std::unique_ptr <IMAPParser::nz_number> nz_number;
+ std::unique_ptr <IMAPParser::atom> atom;
+ std::unique_ptr <IMAPParser::flag_list> flag_list;
+ std::unique_ptr <IMAPParser::text> text;
+ std::unique_ptr <IMAPParser::mod_sequence_value> mod_sequence_value;
+ std::unique_ptr <IMAPParser::sequence_set> sequence_set;
+ std::unique_ptr <IMAPParser::capability_data> capability_data;
+ std::unique_ptr <IMAPParser::uid_set> uid_set;
+ std::unique_ptr <IMAPParser::uid_set> uid_set2;
+ };
+
+
+ //
+ // resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
+ // ;; text SHOULD NOT begin with "[" or "="
+
+ DECLARE_COMPONENT(resp_text)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (VIMAP_PARSER_TRY_CHECK(one_char <'['> )) {
+
+ VIMAP_PARSER_GET(IMAPParser::resp_text_code, resp_text_code);
+
+ VIMAP_PARSER_CHECK(one_char <']'> );
+ VIMAP_PARSER_TRY_CHECK(SPACE);
+ }
+
+ std::unique_ptr <text_mime2> text1;
+ VIMAP_PARSER_TRY_GET(text_mime2, text1);
+
+ if (text1.get()) {
+
+ text = text1->value;
+
+ } else {
+
+ std::unique_ptr <IMAPParser::text> text2;
+ VIMAP_PARSER_TRY_GET(IMAPParser::text, text2);
+
+ if (text2.get()) {
+ text = text2->value;
+ } else {
+ // Empty response text
+ }
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::resp_text_code> resp_text_code;
+ string text;
+ };
+
+
+ //
+ // continue_req ::= "+" SPACE (resp_text / base64)
+ //
+
+ DECLARE_COMPONENT(continue_req)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'+'> );
+
+ if (!parser.isStrict()) {
+
+ // Some servers do not send SPACE when response text is empty
+ if (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+ VIMAP_PARSER_GET(IMAPParser::resp_text, resp_text);
+ } else {
+ resp_text.reset(new IMAPParser::resp_text()); // empty
+ }
+
+ } else {
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::resp_text, resp_text);
+ }
+
+ VIMAP_PARSER_CHECK(CRLF);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::resp_text> resp_text;
+ };
+
+
+ //
+ // resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text
+ // ;; Status condition
+ //
+
+ DECLARE_COMPONENT(resp_cond_state)
+
+ resp_cond_state()
+ : status(BAD) {
+
+ }
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "ok")) {
+ status = OK;
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "no")) {
+ status = NO;
+ } else {
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "bad");
+ status = BAD;
+ }
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::resp_text, resp_text);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ enum Status {
+ OK,
+ NO,
+ BAD
+ };
+
+
+ std::unique_ptr <IMAPParser::resp_text> resp_text;
+ Status status;
+ };
+
+
+ //
+ // resp_cond_bye ::= "BYE" SPACE resp_text
+ //
+
+ DECLARE_COMPONENT(resp_cond_bye)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "bye");
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::resp_text, resp_text);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::resp_text> resp_text;
+ };
+
+
+ //
+ // resp_cond_auth ::= ("OK" / "PREAUTH") SPACE resp_text
+ // ;; Authentication condition
+ //
+
+ DECLARE_COMPONENT(resp_cond_auth)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "ok")) {
+ condition = OK;
+ } else {
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "preauth");
+ condition = PREAUTH;
+ }
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::resp_text, resp_text);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ enum Condition {
+ OK,
+ PREAUTH
+ };
+
+
+ Condition condition;
+ std::unique_ptr <IMAPParser::resp_text> resp_text;
+ };
+
+
+ //
+ // mailbox_data ::= "FLAGS" SPACE mailbox_flag_list /
+ // "LIST" SPACE mailbox_list /
+ // "LSUB" SPACE mailbox_list /
+ // "MAILBOX" SPACE text /
+ // "SEARCH" [SPACE 1#nz_number] /
+ // "STATUS" SPACE mailbox SPACE
+ // "(" [status-att-list] ")" /
+ // number SPACE "EXISTS" /
+ // number SPACE "RECENT"
+ //
+
+ DECLARE_COMPONENT(mailbox_data)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (VIMAP_PARSER_TRY_GET(IMAPParser::number, number)) {
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "exists")) {
+ type = EXISTS;
+ } else {
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "recent");
+ type = RECENT;
+ }
+
+ } else {
+
+ // "FLAGS" SPACE mailbox_flag_list
+ if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "flags")) {
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::mailbox_flag_list, mailbox_flag_list);
+
+ type = FLAGS;
+
+ // "LIST" SPACE mailbox_list
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "list")) {
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::mailbox_list, mailbox_list);
+
+ type = LIST;
+
+ // "LSUB" SPACE mailbox_list
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "lsub")) {
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::mailbox_list, mailbox_list);
+
+ type = LSUB;
+
+ // "MAILBOX" SPACE text
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "mailbox")) {
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::text, text);
+
+ type = MAILBOX;
+
+ // "SEARCH" [SPACE 1#nz_number]
+ } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "search")) {
+
+ if (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+
+ VIMAP_PARSER_GET_PUSHBACK(nz_number, search_nz_number_list);
+
+ while (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+ VIMAP_PARSER_GET_PUSHBACK(nz_number, search_nz_number_list);
+ }
+ }
+
+ type = SEARCH;
+
+ // "STATUS" SPACE mailbox SPACE
+ // "(" [status_att_list] ")"
+ } else {
+
+ VIMAP_PARSER_CHECK_WITHARG(special_atom, "status");
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::mailbox, mailbox);
+
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_CHECK(one_char <'('> );
+ VIMAP_PARSER_TRY_GET(IMAPParser::status_att_list, status_att_list);
+ VIMAP_PARSER_CHECK(one_char <')'> );
+
+ type = STATUS;
+ }
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ enum Type {
+
+ FLAGS,
+ LIST,
+ LSUB,
+ MAILBOX,
+ SEARCH,
+ STATUS,
+ EXISTS,
+ RECENT
+ };
+
+
+ Type type;
+
+ std::unique_ptr <IMAPParser::number> number;
+ std::unique_ptr <IMAPParser::mailbox_flag_list> mailbox_flag_list;
+ std::unique_ptr <IMAPParser::mailbox_list> mailbox_list;
+ std::unique_ptr <IMAPParser::mailbox> mailbox;
+ std::unique_ptr <IMAPParser::text> text;
+ std::vector <std::unique_ptr <nz_number>> search_nz_number_list;
+ std::unique_ptr <IMAPParser::status_att_list> status_att_list;
+ };
+
+
+ //
+ // response_data ::= "*" SPACE (resp_cond_state / resp_cond_bye /
+ // mailbox_data / message_data / capability_data) CRLF
+ //
+
+ DECLARE_COMPONENT(response_data)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'*'> );
+ VIMAP_PARSER_CHECK(SPACE);
+
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_state, resp_cond_state)) {
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_bye, resp_cond_bye)) {
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::mailbox_data, mailbox_data)) {
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::message_data, message_data)) {
+ VIMAP_PARSER_GET(IMAPParser::capability_data, capability_data);
+ }
+ }
+ }
+ }
+
+ if (!parser.isStrict()) {
+
+ // Allow SPACEs at end of line
+ while (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+ ;
+ }
+ }
+
+ VIMAP_PARSER_CHECK(CRLF);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::resp_cond_state> resp_cond_state;
+ std::unique_ptr <IMAPParser::resp_cond_bye> resp_cond_bye;
+ std::unique_ptr <IMAPParser::mailbox_data> mailbox_data;
+ std::unique_ptr <IMAPParser::message_data> message_data;
+ std::unique_ptr <IMAPParser::capability_data> capability_data;
+ };
+
+
+ DECLARE_COMPONENT(continue_req_or_response_data)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::continue_req, continue_req)) {
+ VIMAP_PARSER_GET(IMAPParser::response_data, response_data);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::continue_req> continue_req;
+ std::unique_ptr <IMAPParser::response_data> response_data;
+ };
+
+
+ //
+ // response_fatal ::= "*" SPACE resp_cond_bye CRLF
+ // ;; Server closes connection immediately
+ //
+
+ DECLARE_COMPONENT(response_fatal)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'*'> );
+ VIMAP_PARSER_CHECK(SPACE);
+
+ VIMAP_PARSER_GET(IMAPParser::resp_cond_bye, resp_cond_bye);
+
+ if (!parser.isStrict()) {
+
+ // Allow SPACEs at end of line
+ while (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+ ;
+ }
+ }
+
+ VIMAP_PARSER_CHECK(CRLF);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::resp_cond_bye> resp_cond_bye;
+ };
+
+
+ //
+ // response_tagged ::= tag SPACE resp_cond_state CRLF
+ //
+
+ DECLARE_COMPONENT(response_tagged)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_GET(IMAPParser::xtag, tag);
+ VIMAP_PARSER_CHECK(SPACE);
+ VIMAP_PARSER_GET(IMAPParser::resp_cond_state, resp_cond_state);
+
+ if (!parser.isStrict()) {
+
+ // Allow SPACEs at end of line
+ while (VIMAP_PARSER_TRY_CHECK(SPACE)) {
+ ;
+ }
+ }
+
+ VIMAP_PARSER_CHECK(CRLF);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::xtag> tag;
+ std::unique_ptr <IMAPParser::resp_cond_state> resp_cond_state;
+ };
+
+
+ //
+ // response_done ::= response_tagged / response_fatal
+ //
+
+ DECLARE_COMPONENT(response_done)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::response_tagged, response_tagged)) {
+ VIMAP_PARSER_GET(IMAPParser::response_fatal, response_fatal);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ std::unique_ptr <IMAPParser::response_tagged> response_tagged;
+ std::unique_ptr <IMAPParser::response_fatal> response_fatal;
+ };
+
+
+ //
+ // response ::= *(continue_req / response_data) response_done
+ //
+
+ DECLARE_COMPONENT(response)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+ string curLine = line;
+ bool partial = false; // partial response
+
+ IMAPParser::continue_req_or_response_data* resp = NULL;
+
+ while ((resp = parser.get <IMAPParser::continue_req_or_response_data>(curLine, &pos))) {
+
+ continue_req_or_response_data.push_back(
+ std::move(
+ std::unique_ptr <IMAPParser::continue_req_or_response_data>(resp)
+ )
+ );
+
+ // Partial response (continue_req)
+ if (resp->continue_req) {
+ partial = true;
+ break;
+ }
+
+ // We have read a CRLF, read another line
+ curLine = parser.readLine();
+ pos = 0;
+ }
+
+ if (!partial) {
+ response_done.reset(parser.get <IMAPParser::response_done>(curLine, &pos));
+ VIMAP_PARSER_FAIL_UNLESS(response_done);
+ }
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+
+ bool isBad() const {
+
+ if (!response_done) { // incomplete (partial) response
+ return true;
+ }
+
+ if (response_done->response_fatal) {
+ return true;
+ }
+
+ if (response_done->response_tagged->resp_cond_state->status == IMAPParser::resp_cond_state::BAD) {
+
+ return true;
+ }
+
+ return false;
+ }
+
+ void setErrorLog(const string& errorLog) {
+
+ m_errorLog = errorLog;
+ }
+
+ const string& getErrorLog() const {
+
+ return m_errorLog;
+ }
+
+
+ std::vector <std::unique_ptr <IMAPParser::continue_req_or_response_data>> continue_req_or_response_data;
+ std::unique_ptr <IMAPParser::response_done> response_done;
+
+ private:
+
+ string m_errorLog;
+ };
+
+
+ //
+ // greeting ::= "*" SPACE (resp_cond_auth / resp_cond_bye) CRLF
+ //
+
+ DECLARE_COMPONENT(greeting)
+
+ bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) {
+
+ size_t pos = *currentPos;
+
+ VIMAP_PARSER_CHECK(one_char <'*'> );
+ VIMAP_PARSER_CHECK(SPACE);
+
+ if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_auth, resp_cond_auth)) {
+ VIMAP_PARSER_GET(IMAPParser::resp_cond_bye, resp_cond_bye);
+ }
+
+ VIMAP_PARSER_CHECK(CRLF);
+
+ *currentPos = pos;
+
+ return true;
+ }
+
+ void setErrorLog(const string& errorLog) {
+
+ m_errorLog = errorLog;
+ }
+
+ const string& getErrorLog() const {
+
+ return m_errorLog;
+ }
+
+
+ std::unique_ptr <IMAPParser::resp_cond_auth> resp_cond_auth;
+ std::unique_ptr <IMAPParser::resp_cond_bye> resp_cond_bye;
+
+ private:
+
+ string m_errorLog;
+ };
+
+
+
+ //
+ // The main functions used to parse a response
+ //
+
+ response* readResponse(const IMAPTag& tag, literalHandler* lh = NULL) {
+
+ while (true) {
+
+ auto it = m_pendingResponses.find(std::string(tag));
+
+ if (it != m_pendingResponses.end()) {
+ auto* resp = it->second;
+ m_pendingResponses.erase(it);
+ return resp;
+ }
+
+ size_t pos = 0;
+ string line = readLine();
+
+ m_literalHandler = lh;
+ response* resp = get <response>(line, &pos);
+ m_literalHandler = NULL;
+
+ if (!resp) {
+ throw exceptions::invalid_response("", m_errorResponseLine);
+ }
+
+ resp->setErrorLog(lastLine());
+
+ // If there is a continue_req, return the response immediately
+ for (auto &respData : resp->continue_req_or_response_data) {
+ if (respData->continue_req) {
+ return resp;
+ }
+ }
+
+ // Else, return response if the tag is the one we expect
+ if (resp->response_done && resp->response_done->response_tagged &&
+ resp->response_done->response_tagged->tag) {
+
+ if (tag == resp->response_done->response_tagged->tag->tagString) {
+ return resp;
+ } else {
+ // Not our response tag, cache it for later
+ m_pendingResponses[resp->response_done->response_tagged->tag->tagString] = resp;
+ }
+ } else {
+ // Untagged response
+ return resp;
+ }
+ }
+ }
+
+
+ greeting* readGreeting() {
+
+ size_t pos = 0;
+ string line = readLine();
+
+ greeting* greet = get <greeting>(line, &pos);
+
+ if (!greet) {
+ throw exceptions::invalid_response("", m_errorResponseLine);
+ }
+
+ greet->setErrorLog(lastLine());
+
+ return greet;
+ }
+
+
+ /** Parse a token and advance.
+ * If the token has been parsed successfully, a raw pointer to it
+ * will be returned. The caller is responsible to free the memory.
+ *
+ * @param TYPE token type (class)
+ * @param line line which is currently being parsed
+ * @param currentPos current position in the line (will be updated
+ * when the function returns)
+ * @return a raw pointer to the parsed token, or NULL otherwise
+ */
+ template <class TYPE>
+ TYPE* get(string& line, size_t* currentPos) {
+
+ component* resp = new TYPE;
+ return internalGet <TYPE>(resp, line, currentPos);
+ }
+
+ /** Parse a token which takes 2 arguments and advance.
+ * If the token has been parsed successfully, a raw pointer to it
+ * will be returned. The caller is responsible to free the memory.
+ *
+ * @param TYPE token type (class)
+ * @param ARG1_TYPE type of argument #1 (class)
+ * @param ARG2_TYPE type of argument #2 (class)
+ * @param line line which is currently being parsed
+ * @param currentPos current position in the line (will be updated
+ * when the function returns)
+ * @param arg1 value of argument 1 to be passed to the token
+ * @param arg2 value of argument 2 to be passed to the token
+ * @return a raw pointer to the parsed token, or NULL otherwise
+ */
+ template <class TYPE, class ARG1_TYPE, class ARG2_TYPE>
+ TYPE* getWithArgs(string& line, size_t* currentPos, ARG1_TYPE arg1, ARG2_TYPE arg2) {
+
+ component* resp = new TYPE(arg1, arg2);
+ return internalGet <TYPE>(resp, line, currentPos);
+ }
+
+private:
+
+ template <class TYPE>
+ TYPE* internalGet(component* resp, string& line, size_t* currentPos) {
+
+ const size_t oldPos = *currentPos;
+
+ if (!resp->parse(*this, line, currentPos)) {
+
+ *currentPos = oldPos;
+
+ delete resp;
+
+ return NULL;
+ }
+
+ return static_cast <TYPE*>(resp);
+ }
+
+ const string lastLine() const {
+
+ // Remove blanks and new lines at the end of the line.
+ string line(m_lastLine);
+
+ string::const_iterator it = line.end();
+ int count = 0;
+
+ while (it != line.begin()) {
+
+ const unsigned char c = *(it - 1);
+
+ if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {
+ break;
+ }
+
+ ++count;
+ --it;
+ }
+
+ line.resize(line.length() - count);
+
+ return (line);
+ }
+
+public:
+
+ /** Check for a token and advance.
+ *
+ * @param TYPE token type (class)
+ * @param line line which is currently being parsed
+ * @param currentPos current position in the line (will be updated
+ * when the function returns)
+ * @return true if the token has been parsed, or false otherwise
+ */
+ template <class TYPE>
+ bool check(string& line, size_t* currentPos) {
+
+ const size_t oldPos = *currentPos;
+
+ TYPE term;
+
+ if (!term.parse(*this, line, currentPos)) {
+ *currentPos = oldPos;
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /** Check for a token which takes an argument and advance.
+ *
+ * @param TYPE token type (class)
+ * @param ARG_TYPE argument type (class)
+ * @param line line which is currently being parsed
+ * @param currentPos current position in the line (will be updated
+ * when the function returns)
+ * @param arg argument to be passed to the token
+ * @return true if the token has been parsed, or false otherwise
+ */
+ template <class TYPE, class ARG_TYPE>
+ bool checkWithArg(string& line, size_t* currentPos, const ARG_TYPE arg) {
+
+ const size_t oldPos = *currentPos;
+
+ TYPE term(arg);
+
+ if (!term.parse(*this, line, currentPos)) {
+ *currentPos = oldPos;
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+
+private:
+
+ weak_ptr <socket> m_socket;
+ shared_ptr <tracer> m_tracer;
+
+ utility::progressListener* m_progress;
+
+ bool m_strict;
+
+ literalHandler* m_literalHandler;
+
+ weak_ptr <timeoutHandler> m_timeoutHandler;
+
+
+ string m_buffer;
+
+ string m_lastLine;
+ string m_errorResponseLine;
+
+ std::map <std::string, response*> m_pendingResponses;
+
+public:
+
+ /** Read a line from the input buffer. The function blocks until a
+ * complete line is read from the buffer. Position in input buffer
+ * will be updated.
+ *
+ * @return next line
+ */
+ const string readLine() {
+
+ size_t pos;
+
+ while ((pos = m_buffer.find('\n')) == string::npos) {
+ read();
+ }
+
+ string line;
+ line.resize(pos + 1);
+ std::copy(m_buffer.begin(), m_buffer.begin() + pos + 1, line.begin());
+
+ m_buffer.erase(m_buffer.begin(), m_buffer.begin() + pos + 1);
+
+ m_lastLine = line;
+
+#if DEBUG_RESPONSE
+ std::cout << std::endl << "Read line:" << std::endl << line << std::endl;
+#endif
+
+ if (m_tracer) {
+ string::size_type len = line.length();
+ while (len != 0 && (line[len - 1] == '\r' || line[len - 1] == '\n')) --len;
+ m_tracer->traceReceive(line.substr(0, len));
+ }
+
+ return (line);
+ }
+
+ /** Fill in the input buffer with data available from the socket stream.
+ * The function blocks until some data is available.
+ */
+ void read() {
+
+ string receiveBuffer;
+
+ shared_ptr <timeoutHandler> toh = m_timeoutHandler.lock();
+ shared_ptr <socket> sok = m_socket.lock();
+
+ if (toh) {
+ toh->resetTimeOut();
+ }
+
+ while (receiveBuffer.empty()) {
+
+ // Check whether the time-out delay is elapsed
+ if (toh && toh->isTimeOut()) {
+ if (!toh->handleTimeOut()) {
+ throw exceptions::operation_timed_out();
+ }
+ }
+
+ // We have received data: reset the time-out counter
+ sok->receive(receiveBuffer);
+
+ if (receiveBuffer.empty()) { // buffer is empty
+
+ if (sok->getStatus() & socket::STATUS_WANT_WRITE) {
+ sok->waitForWrite();
+ } else {
+ sok->waitForRead();
+ }
+
+ continue;
+ }
+
+ // We have received data ...
+ if (toh) {
+ toh->resetTimeOut();
+ }
+ }
+
+ m_buffer += receiveBuffer;
+ }
+
+
+ void readLiteral(literalHandler::target& buffer, size_t count) {
+
+ size_t len = 0;
+ string receiveBuffer;
+
+ shared_ptr <timeoutHandler> toh = m_timeoutHandler.lock();
+ shared_ptr <socket> sok = m_socket.lock();
+
+ if (m_progress) {
+ m_progress->start(count);
+ }
+
+ if (toh) {
+ toh->resetTimeOut();
+ }
+
+ if (!m_buffer.empty()) {
+
+ if (m_buffer.length() > count) {
+
+ buffer.putData(string(m_buffer.begin(), m_buffer.begin() + count));
+ m_buffer.erase(m_buffer.begin(), m_buffer.begin() + count);
+ len = count;
+
+ } else {
+
+ len += m_buffer.length();
+ buffer.putData(m_buffer);
+ m_buffer.clear();
+ }
+ }
+
+ while (len < count) {
+
+ // Check whether the time-out delay is elapsed
+ if (toh && toh->isTimeOut()) {
+
+ if (!toh->handleTimeOut()) {
+ throw exceptions::operation_timed_out();
+ }
+
+ toh->resetTimeOut();
+ }
+
+ // Receive data from the socket
+ sok->receive(receiveBuffer);
+
+ if (receiveBuffer.empty()) { // buffer is empty
+
+ if (sok->getStatus() & socket::STATUS_WANT_WRITE) {
+ sok->waitForWrite();
+ } else {
+ sok->waitForRead();
+ }
+
+ continue;
+ }
+
+ // We have received data: reset the time-out counter
+ if (toh) {
+ toh->resetTimeOut();
+ }
+
+ if (len + receiveBuffer.length() > count) {
+
+ const size_t remaining = count - len;
+
+ // Get the needed amount of data
+ buffer.putData(string(receiveBuffer.begin(), receiveBuffer.begin() + remaining));
+
+ // Put the remaining data into the internal response buffer
+ receiveBuffer.erase(receiveBuffer.begin(), receiveBuffer.begin() + remaining);
+ m_buffer += receiveBuffer;
+
+ len = count;
+
+ } else {
+
+ buffer.putData(receiveBuffer);
+ len += receiveBuffer.length();
+ }
+
+ // Notify progress
+ if (m_progress) {
+ m_progress->progress(len, count);
+ }
+ }
+
+ if (m_tracer) {
+ m_tracer->traceReceiveBytes(count);
+ }
+
+ if (m_progress) {
+ m_progress->stop(count);
+ }
+ }
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#undef VIMAP_PARSER_FAIL
+#undef VIMAP_PARSER_FAIL_UNLESS
+#undef VIMAP_PARSER_CHECK
+#undef VIMAP_PARSER_TRY_CHECK
+#undef VIMAP_PARSER_GET
+#undef VIMAP_PARSER_GET
+#undef VIMAP_PARSER_TRY_GET
+#undef VIMAP_PARSER_TRY_GET
+#undef VIMAP_PARSER_GET_PUSHBACK
+#undef VIMAP_PARSER_CHECK_WITHARG
+#undef VIMAP_PARSER_TRY_CHECK_WITHARG
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPPARSER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/imap/IMAPSStore.cpp b/vmime-master/src/vmime/net/imap/IMAPSStore.cpp
new file mode 100644
index 0000000..dd9c318
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPSStore.cpp
@@ -0,0 +1,82 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPSStore.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPSStore::IMAPSStore(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+)
+ : IMAPStore(sess, auth, true) {
+
+}
+
+
+IMAPSStore::~IMAPSStore() {
+
+}
+
+
+const string IMAPSStore::getProtocolName() const {
+
+ return "imaps";
+}
+
+
+
+// Service infos
+
+IMAPServiceInfos IMAPSStore::sm_infos(true);
+
+
+const serviceInfos& IMAPSStore::getInfosInstance() {
+
+ return sm_infos;
+}
+
+
+const serviceInfos& IMAPSStore::getInfos() const {
+
+ return sm_infos;
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPSStore.hpp b/vmime-master/src/vmime/net/imap/IMAPSStore.hpp
new file mode 100644
index 0000000..e18a067
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPSStore.hpp
@@ -0,0 +1,70 @@
+//
+// 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_NET_IMAP_IMAPSSTORE_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPSSTORE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPStore.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+/** IMAPS store service.
+ */
+class VMIME_EXPORT IMAPSStore : public IMAPStore {
+
+public:
+
+ IMAPSStore(const shared_ptr <session>& sess, const shared_ptr <security::authenticator>& auth);
+ ~IMAPSStore();
+
+ const string getProtocolName() const;
+
+ static const serviceInfos& getInfosInstance();
+ const serviceInfos& getInfos() const;
+
+private:
+
+ static IMAPServiceInfos sm_infos;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPSSTORE_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPServiceInfos.cpp b/vmime-master/src/vmime/net/imap/IMAPServiceInfos.cpp
new file mode 100644
index 0000000..baed6ba
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPServiceInfos.cpp
@@ -0,0 +1,135 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPServiceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPServiceInfos::IMAPServiceInfos(const bool imaps)
+ : m_imaps(imaps) {
+
+}
+
+
+const string IMAPServiceInfos::getPropertyPrefix() const {
+
+ if (m_imaps) {
+ return "store.imaps.";
+ } else {
+ return "store.imap.";
+ }
+}
+
+
+const IMAPServiceInfos::props& IMAPServiceInfos::getProperties() const {
+
+ static props imapProps = {
+ // IMAP-specific options
+#if VMIME_HAVE_SASL_SUPPORT
+ property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"),
+ property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"),
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ // Common properties
+ property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
+ property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
+
+#if VMIME_HAVE_TLS_SUPPORT
+ property(serviceInfos::property::CONNECTION_TLS),
+ property(serviceInfos::property::CONNECTION_TLS_REQUIRED),
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
+ property(serviceInfos::property::SERVER_PORT, "143"),
+ };
+
+ static props imapsProps = {
+ // IMAP-specific options
+#if VMIME_HAVE_SASL_SUPPORT
+ property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"),
+ property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"),
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ // Common properties
+ property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
+ property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
+
+#if VMIME_HAVE_TLS_SUPPORT
+ property(serviceInfos::property::CONNECTION_TLS),
+ property(serviceInfos::property::CONNECTION_TLS_REQUIRED),
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
+ property(serviceInfos::property::SERVER_PORT, "993"),
+ };
+
+ return m_imaps ? imapsProps : imapProps;
+}
+
+
+const std::vector <serviceInfos::property> IMAPServiceInfos::getAvailableProperties() const {
+
+ std::vector <property> list;
+ const props& p = getProperties();
+
+ // IMAP-specific options
+#if VMIME_HAVE_SASL_SUPPORT
+ list.push_back(p.PROPERTY_OPTIONS_SASL);
+ list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK);
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ // Common properties
+ list.push_back(p.PROPERTY_AUTH_USERNAME);
+ list.push_back(p.PROPERTY_AUTH_PASSWORD);
+
+#if VMIME_HAVE_TLS_SUPPORT
+ if (!m_imaps) {
+ list.push_back(p.PROPERTY_CONNECTION_TLS);
+ list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED);
+ }
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ list.push_back(p.PROPERTY_SERVER_ADDRESS);
+ list.push_back(p.PROPERTY_SERVER_PORT);
+
+ return list;
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPServiceInfos.hpp b/vmime-master/src/vmime/net/imap/IMAPServiceInfos.hpp
new file mode 100644
index 0000000..73fca7a
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPServiceInfos.hpp
@@ -0,0 +1,89 @@
+//
+// 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_NET_IMAP_IMAPSERVICEINFOS_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPSERVICEINFOS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/serviceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+/** Information about IMAP service.
+ */
+class VMIME_EXPORT IMAPServiceInfos : public serviceInfos {
+
+public:
+
+ IMAPServiceInfos(const bool imaps);
+
+ struct props {
+ // IMAP-specific options
+#if VMIME_HAVE_SASL_SUPPORT
+ serviceInfos::property PROPERTY_OPTIONS_SASL;
+ serviceInfos::property PROPERTY_OPTIONS_SASL_FALLBACK;
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ // Common properties
+ serviceInfos::property PROPERTY_AUTH_USERNAME;
+ serviceInfos::property PROPERTY_AUTH_PASSWORD;
+
+#if VMIME_HAVE_TLS_SUPPORT
+ serviceInfos::property PROPERTY_CONNECTION_TLS;
+ serviceInfos::property PROPERTY_CONNECTION_TLS_REQUIRED;
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ serviceInfos::property PROPERTY_SERVER_ADDRESS;
+ serviceInfos::property PROPERTY_SERVER_PORT;
+ };
+
+ const props& getProperties() const;
+
+ const string getPropertyPrefix() const;
+ const std::vector <serviceInfos::property> getAvailableProperties() const;
+
+private:
+
+ const bool m_imaps;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPSERVICEINFOS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPStore.cpp b/vmime-master/src/vmime/net/imap/IMAPStore.cpp
new file mode 100644
index 0000000..eafa444
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPStore.cpp
@@ -0,0 +1,287 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPStore.hpp"
+#include "vmime/net/imap/IMAPFolder.hpp"
+#include "vmime/net/imap/IMAPConnection.hpp"
+#include "vmime/net/imap/IMAPFolderStatus.hpp"
+#include "vmime/net/imap/IMAPCommand.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/platform.hpp"
+
+#include <map>
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+IMAPStore::IMAPStore(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth,
+ const bool secured
+)
+ : store(sess, getInfosInstance(), auth),
+ m_connection(null),
+ m_isIMAPS(secured) {
+
+}
+
+
+IMAPStore::~IMAPStore() {
+
+ try {
+
+ if (isConnected()) {
+ disconnect();
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+const string IMAPStore::getProtocolName() const {
+
+ return "imap";
+}
+
+
+shared_ptr <folder> IMAPStore::getRootFolder() {
+
+ if (!isConnected()) {
+ throw exceptions::illegal_state("Not connected");
+ }
+
+ return make_shared <IMAPFolder>(
+ folder::path(),
+ dynamicCast <IMAPStore>(shared_from_this()),
+ shared_ptr <folderAttributes>()
+ );
+}
+
+
+shared_ptr <folder> IMAPStore::getDefaultFolder() {
+
+ if (!isConnected()) {
+ throw exceptions::illegal_state("Not connected");
+ }
+
+ return make_shared <IMAPFolder>(
+ folder::path::component("INBOX"),
+ dynamicCast <IMAPStore>(shared_from_this()),
+ shared_ptr <folderAttributes>()
+ );
+}
+
+
+shared_ptr <folder> IMAPStore::getFolder(const folder::path& path) {
+
+ if (!isConnected()) {
+ throw exceptions::illegal_state("Not connected");
+ }
+
+ return make_shared <IMAPFolder>(
+ path,
+ dynamicCast <IMAPStore>(shared_from_this()),
+ shared_ptr <folderAttributes>()
+ );
+}
+
+
+bool IMAPStore::isValidFolderName(const folder::path::component& /* name */) const {
+
+ return true;
+}
+
+
+void IMAPStore::connect() {
+
+ if (isConnected()) {
+ throw exceptions::already_connected();
+ }
+
+ m_connection = make_shared <IMAPConnection>(
+ dynamicCast <IMAPStore>(shared_from_this()), getAuthenticator()
+ );
+
+ m_connection->connect();
+}
+
+
+bool IMAPStore::isConnected() const {
+
+ return m_connection && m_connection->isConnected();
+}
+
+
+bool IMAPStore::isIMAPS() const {
+
+ return m_isIMAPS;
+}
+
+
+bool IMAPStore::isSecuredConnection() const {
+
+ if (!m_connection) {
+ return false;
+ }
+
+ return m_connection->isSecuredConnection();
+}
+
+
+shared_ptr <connectionInfos> IMAPStore::getConnectionInfos() const {
+
+ if (!m_connection) {
+ return null;
+ }
+
+ return m_connection->getConnectionInfos();
+}
+
+
+shared_ptr <IMAPConnection> IMAPStore::getConnection() {
+
+ return m_connection;
+}
+
+
+void IMAPStore::disconnect() {
+
+ if (!isConnected()) {
+ throw exceptions::not_connected();
+ }
+
+ for (std::list <IMAPFolder*>::iterator it = m_folders.begin() ;
+ it != m_folders.end() ; ++it) {
+
+ (*it)->onStoreDisconnected();
+ }
+
+ m_folders.clear();
+
+
+ m_connection->disconnect();
+
+ m_connection = null;
+}
+
+
+void IMAPStore::noop() {
+
+ if (!isConnected()) {
+ throw exceptions::not_connected();
+ }
+
+ IMAPCommand::NOOP()->send(m_connection);
+
+ scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());
+
+ if (resp->isBad() || resp->response_done->response_tagged->
+ resp_cond_state->status != IMAPParser::resp_cond_state::OK) {
+
+ throw exceptions::command_error("NOOP", resp->getErrorLog());
+ }
+
+
+ for (std::list <IMAPFolder*>::iterator it = m_folders.begin() ;
+ it != m_folders.end() ; ++it) {
+
+ if ((*it)->isOpen()) {
+ (*it)->noop();
+ }
+ }
+}
+
+
+shared_ptr <IMAPConnection> IMAPStore::connection() {
+
+ return m_connection;
+}
+
+
+void IMAPStore::registerFolder(IMAPFolder* folder) {
+
+ m_folders.push_back(folder);
+}
+
+
+void IMAPStore::unregisterFolder(IMAPFolder* folder) {
+
+ std::list <IMAPFolder*>::iterator it = std::find(m_folders.begin(), m_folders.end(), folder);
+
+ if (it != m_folders.end()) {
+ m_folders.erase(it);
+ }
+}
+
+
+int IMAPStore::getCapabilities() const {
+
+ return CAPABILITY_CREATE_FOLDER |
+ CAPABILITY_RENAME_FOLDER |
+ CAPABILITY_ADD_MESSAGE |
+ CAPABILITY_COPY_MESSAGE |
+ CAPABILITY_DELETE_MESSAGE |
+ CAPABILITY_PARTIAL_FETCH |
+ CAPABILITY_MESSAGE_FLAGS |
+ CAPABILITY_EXTRACT_PART;
+}
+
+
+
+// Service infos
+
+IMAPServiceInfos IMAPStore::sm_infos(false);
+
+
+const serviceInfos& IMAPStore::getInfosInstance() {
+
+ return sm_infos;
+}
+
+
+const serviceInfos& IMAPStore::getInfos() const {
+
+ return sm_infos;
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPStore.hpp b/vmime-master/src/vmime/net/imap/IMAPStore.hpp
new file mode 100644
index 0000000..018c195
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPStore.hpp
@@ -0,0 +1,124 @@
+//
+// 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_NET_IMAP_IMAPSTORE_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPSTORE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/store.hpp"
+#include "vmime/net/socket.hpp"
+#include "vmime/net/folder.hpp"
+
+#include "vmime/net/imap/IMAPServiceInfos.hpp"
+#include "vmime/net/imap/IMAPConnection.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class IMAPParser;
+class IMAPTag;
+class IMAPFolder;
+
+
+/** IMAP store service.
+ */
+class VMIME_EXPORT IMAPStore : public store {
+
+ friend class IMAPFolder;
+ friend class IMAPMessage;
+ friend class IMAPConnection;
+
+public:
+
+ IMAPStore(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth,
+ const bool secured = false
+ );
+
+ ~IMAPStore();
+
+ const string getProtocolName() const;
+
+ shared_ptr <folder> getDefaultFolder();
+ shared_ptr <folder> getRootFolder();
+ shared_ptr <folder> getFolder(const folder::path& path);
+
+ bool isValidFolderName(const folder::path::component& name) const;
+
+ static const serviceInfos& getInfosInstance();
+ const serviceInfos& getInfos() const;
+
+ void connect();
+ bool isConnected() const;
+ void disconnect();
+
+ void noop();
+
+ int getCapabilities() const;
+
+ bool isIMAPS() const;
+
+ bool isSecuredConnection() const;
+ shared_ptr <connectionInfos> getConnectionInfos() const;
+ shared_ptr <IMAPConnection> getConnection();
+
+protected:
+
+ // Connection
+ shared_ptr <IMAPConnection> m_connection;
+
+
+
+ shared_ptr <IMAPConnection> connection();
+
+
+ void registerFolder(IMAPFolder* folder);
+ void unregisterFolder(IMAPFolder* folder);
+
+ std::list <IMAPFolder*> m_folders;
+
+ const bool m_isIMAPS; // Use IMAPS
+
+
+ static IMAPServiceInfos sm_infos;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPSTORE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/imap/IMAPTag.cpp b/vmime-master/src/vmime/net/imap/IMAPTag.cpp
new file mode 100644
index 0000000..52cd212
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPTag.cpp
@@ -0,0 +1,148 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPTag.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+const int IMAPTag::sm_maxNumber = 52 * 10 * 10 * 10;
+
+
+IMAPTag::IMAPTag(const int number)
+ : m_number(number) {
+
+ m_tag.resize(4);
+ generate();
+}
+
+
+IMAPTag::IMAPTag(const IMAPTag& tag)
+ : object(),
+ m_number(tag.m_number) {
+
+ m_tag.resize(4);
+ generate();
+}
+
+
+IMAPTag::IMAPTag()
+ : m_number(1) {
+
+ m_tag.resize(4);
+ generate();
+}
+
+
+IMAPTag& IMAPTag::operator++() {
+
+ ++m_number;
+
+ if (m_number >= sm_maxNumber) {
+ m_number = 1;
+ }
+
+ generate();
+
+ return *this;
+}
+
+
+const IMAPTag IMAPTag::operator++(int) {
+
+ IMAPTag old(*this);
+ operator++();
+ return old;
+}
+
+
+bool IMAPTag::operator<(const IMAPTag &other) const {
+
+ return m_number < other.m_number;
+}
+
+
+bool IMAPTag::operator==(const IMAPTag &other) const {
+
+ return m_number == other.m_number;
+}
+
+
+bool IMAPTag::operator!=(const IMAPTag &other) const {
+
+ return m_number != other.m_number;
+}
+
+
+bool IMAPTag::operator==(const std::string &tag) const {
+
+ return m_tag == tag;
+}
+
+
+int IMAPTag::maximumNumber() const {
+
+ return sm_maxNumber - 1;
+}
+
+
+int IMAPTag::number() const {
+
+ return m_number;
+}
+
+
+IMAPTag::operator string() const
+{
+ return m_tag;
+}
+
+
+void IMAPTag::generate() {
+
+ static const char prefixChars[53] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ m_tag[0] = prefixChars[m_number / 1000];
+ m_tag[1] = static_cast <char>('0' + (m_number % 1000) / 100);
+ m_tag[2] = static_cast <char>('0' + (m_number % 100) / 10);
+ m_tag[3] = static_cast <char>('0' + m_number % 10);
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPTag.hpp b/vmime-master/src/vmime/net/imap/IMAPTag.hpp
new file mode 100644
index 0000000..cbab942
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPTag.hpp
@@ -0,0 +1,85 @@
+//
+// 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_NET_IMAP_IMAPTAG_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPTAG_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/types.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class VMIME_EXPORT IMAPTag : public object {
+
+private:
+
+ IMAPTag(const int number);
+
+public:
+
+ IMAPTag();
+ IMAPTag(const IMAPTag& tag);
+
+ IMAPTag& operator++(); // ++IMAPTag
+ const IMAPTag operator++(int); // IMAPTag++
+
+ int maximumNumber() const;
+ int number() const;
+
+ operator string() const;
+
+ bool operator<(const IMAPTag &other) const;
+ bool operator==(const IMAPTag &other) const;
+ bool operator!=(const IMAPTag &other) const;
+
+ bool operator==(const std::string &tag) const;
+
+private:
+
+ void generate();
+
+ static const int sm_maxNumber;
+
+ int m_number;
+ string m_tag;
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPTAG_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/imap/IMAPUtils.cpp b/vmime-master/src/vmime/net/imap/IMAPUtils.cpp
new file mode 100644
index 0000000..59b1e18
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPUtils.cpp
@@ -0,0 +1,854 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/net/imap/IMAPUtils.hpp"
+#include "vmime/net/imap/IMAPStore.hpp"
+
+#include "vmime/net/message.hpp"
+#include "vmime/net/folder.hpp"
+
+#include <sstream>
+#include <iterator>
+#include <algorithm>
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+// static
+const string IMAPUtils::quoteString(const string& text) {
+
+ //
+ // ATOM_CHAR ::= <any CHAR except atom_specials>
+ //
+ // atom_specials ::= "(" / ")" / "{" / SPACE / CTL /
+ // list_wildcards / quoted_specials
+ //
+ // list_wildcards ::= "%" / "*"
+ //
+ // quoted_specials ::= <"> / "\"
+ //
+ // CHAR ::= <any 7-bit US-ASCII character except NUL,
+ // 0x01 - 0x7f>
+ //
+ // CTL ::= <any ASCII control character and DEL,
+ // 0x00 - 0x1f, 0x7f>
+ //
+
+ bool needQuoting = text.empty();
+
+ for (string::const_iterator it = text.begin() ;
+ !needQuoting && it != text.end() ; ++it) {
+
+ const unsigned char c = *it;
+
+ switch (c) {
+
+ case '(':
+ case ')':
+ case '{':
+ case 0x20: // SPACE
+ case '%':
+ case '*':
+ case '"':
+ case '\\':
+
+ needQuoting = true;
+ break;
+
+ default:
+
+ if (c <= 0x1f || c >= 0x7f) {
+ needQuoting = true;
+ }
+ }
+ }
+
+ if (needQuoting) {
+
+ string quoted;
+ quoted.reserve((text.length() * 3) / 2 + 2);
+
+ quoted += '"';
+
+ for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) {
+
+ const unsigned char c = *it;
+
+ if (c == '\\' || c == '"') {
+ quoted += '\\';
+ }
+
+ quoted += c;
+ }
+
+ quoted += '"';
+
+ return quoted;
+
+ } else {
+
+ return text;
+ }
+}
+
+
+const string IMAPUtils::pathToString(
+ const char hierarchySeparator,
+ const folder::path& path
+) {
+
+ string result;
+
+ for (size_t i = 0 ; i < path.getSize() ; ++i) {
+
+ if (i > 0) result += hierarchySeparator;
+ result += toModifiedUTF7(hierarchySeparator, path[i]);
+ }
+
+ return (result);
+}
+
+
+const folder::path IMAPUtils::stringToPath(
+ const char hierarchySeparator,
+ const string& str
+) {
+
+ folder::path result;
+ string::const_iterator begin = str.begin();
+
+ for (string::const_iterator it = str.begin() ; it != str.end() ; ++it) {
+
+ if (*it == hierarchySeparator) {
+ result /= fromModifiedUTF7(string(begin, it));
+ begin = it + 1;
+ }
+ }
+
+ if (begin != str.end()) {
+ result /= fromModifiedUTF7(string(begin, str.end()));
+ }
+
+ return result;
+}
+
+
+const string IMAPUtils::toModifiedUTF7(
+ const char hierarchySeparator,
+ const folder::path::component& text
+) {
+
+ // We will replace the hierarchy separator with an equivalent
+ // UTF-7 sequence, so we compute it here...
+ const char base64alphabet[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,=";
+
+ const unsigned int hs = static_cast <unsigned int>(static_cast <unsigned char>(hierarchySeparator));
+
+ string hsUTF7;
+ hsUTF7.resize(3);
+
+ hsUTF7[0] = base64alphabet[0];
+ hsUTF7[1] = base64alphabet[(hs & 0xF0) >> 4];
+ hsUTF7[2] = base64alphabet[(hs & 0x0F) << 2];
+
+ // iconv() is buggy with UTF-8 to UTF-7 conversion, so we do it "by hand".
+ // This code is largely inspired from "imap/utf7.c", in mutt 1.4.
+ // Copyright (C) 2000 Edmund Grimley Evans <edmundo@rano.org>
+
+ // WARNING: This may throw "exceptions::charset_conv_error"
+ const string cvt = text.getConvertedText(charset(charsets::UTF_8));
+
+ // In the worst case we convert 2 chars to 7 chars.
+ // For example: "\x10&\x10&..." -> "&ABA-&-&ABA-&-...".
+ string out;
+ out.reserve((cvt.length() / 2) * 7 + 6);
+
+ int b = 0, k = 0;
+ bool base64 = false;
+
+ size_t remaining = cvt.length();
+
+ for (size_t i = 0, len = cvt.length() ; i < len ; ) {
+
+ const unsigned char c = cvt[i];
+
+ // Replace hierarchy separator with an equivalent UTF-7 Base64 sequence
+ if (!base64 && c == hierarchySeparator) {
+
+ out += "&" + hsUTF7 + "-";
+
+ ++i;
+ --remaining;
+ continue;
+ }
+
+ size_t n = 0;
+ int ch = 0;
+
+ if (c < 0x80) {
+ ch = c, n = 0;
+ } else if (c < 0xc2) {
+ return "";
+ } else if (c < 0xe0) {
+ ch = c & 0x1f, n = 1;
+ } else if (c < 0xf0) {
+ ch = c & 0x0f, n = 2;
+ } else if (c < 0xf8) {
+ ch = c & 0x07, n = 3;
+ } else if (c < 0xfc) {
+ ch = c & 0x03, n = 4;
+ } else if (c < 0xfe) {
+ ch = c & 0x01, n = 5;
+ } else {
+ return "";
+ }
+
+ if (n > remaining) {
+ return ""; // error
+ }
+
+ ++i;
+ --remaining;
+
+ for (size_t j = 0 ; j < n ; j++) {
+
+ if ((cvt[i + j] & 0xc0) != 0x80) {
+ return ""; // error
+ }
+
+ ch = (ch << 6) | (cvt[i + j] & 0x3f);
+ }
+
+ if (n > 1 && !(ch >> (n * 5 + 1))) {
+ return ""; // error
+ }
+
+ i += n;
+ remaining -= n;
+
+ if (ch < 0x20 || ch >= 0x7f) {
+
+ if (!base64) {
+ out += '&';
+ base64 = true;
+ b = 0;
+ k = 10;
+ }
+
+ if (ch & ~0xffff) {
+ ch = 0xfffe;
+ }
+
+ out += base64alphabet[b | ch >> k];
+
+ k -= 6;
+
+ for ( ; k >= 0 ; k -= 6) {
+ out += base64alphabet[(ch >> k) & 0x3f];
+ }
+
+ b = (ch << (-k)) & 0x3f;
+ k += 16;
+
+ } else {
+
+ if (base64) {
+
+ if (k > 10) {
+ out += base64alphabet[b];
+ }
+
+ out += '-';
+ base64 = false;
+ }
+
+ out += static_cast <char>(ch);
+
+ if (ch == '&') {
+ out += '-';
+ }
+ }
+ }
+
+ if (base64) {
+
+ if (k > 10) {
+ out += base64alphabet[b];
+ }
+
+ out += '-';
+ }
+
+ return (out);
+}
+
+
+const folder::path::component IMAPUtils::fromModifiedUTF7(const string& text) {
+
+ // Transcode from modified UTF-7 (RFC-2060).
+ string out;
+ out.reserve(text.length());
+
+ bool inB64sequence = false;
+ bool plusOutput = false;
+ unsigned char prev = 0;
+
+ for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) {
+
+ const unsigned char c = *it;
+
+ switch (c) {
+
+ // Start of Base64 sequence
+ case '&': {
+
+ if (!inB64sequence) {
+ inB64sequence = true;
+ plusOutput = false;
+ } else {
+ out += '&';
+ }
+
+ break;
+ }
+ // End of Base64 sequence (or "&-" --> "&")
+ case '-': {
+
+ if (inB64sequence && prev == '&') { // special case "&-" --> "&"
+ out += '&';
+ } else {
+ out += '-';
+ }
+
+ inB64sequence = false;
+ break;
+ }
+ // ',' is used instead of '/' in modified Base64
+ case ',': {
+
+ if (inB64sequence && !plusOutput) {
+ out += '+';
+ plusOutput = true;
+ }
+
+ out += (inB64sequence ? '/' : ',');
+ break;
+ }
+ default: {
+
+ if (inB64sequence && !plusOutput) {
+ out += '+';
+ plusOutput = true;
+ }
+
+ out += c;
+ break;
+ }
+ }
+
+ prev = c;
+ }
+
+ // Store it as UTF-8 by default
+ string cvt;
+ charset::convert(out, cvt, charset(charsets::UTF_7), charset(charsets::UTF_8));
+
+ return folder::path::component(cvt, charset(charsets::UTF_8));
+}
+
+
+// static
+void IMAPUtils::mailboxFlagsToFolderAttributes(
+ const shared_ptr <const IMAPConnection>& cnt,
+ const folder::path &path,
+ const IMAPParser::mailbox_flag_list& list,
+ folderAttributes& attribs
+) {
+
+ int specialUse = folderAttributes::SPECIALUSE_NONE;
+ int type = folderAttributes::TYPE_CONTAINS_MESSAGES | folderAttributes::TYPE_CONTAINS_FOLDERS;
+ int flags = 0;
+
+ // If CHILDREN extension (RFC-3348) is not supported, assume folder has children
+ // as we have no hint about it
+ if (!cnt->hasCapability("CHILDREN")) {
+ flags |= folderAttributes::FLAG_HAS_CHILDREN;
+ }
+
+ for (auto it = list.flags.begin() ; it != list.flags.end() ; ++it) {
+
+ switch ((*it)->type) {
+
+ case IMAPParser::mailbox_flag::NOSELECT:
+
+ type &= ~folderAttributes::TYPE_CONTAINS_MESSAGES;
+ flags |= folderAttributes::FLAG_NO_OPEN;
+ break;
+
+ case IMAPParser::mailbox_flag::NOINFERIORS:
+ case IMAPParser::mailbox_flag::HASNOCHILDREN:
+
+ flags &= ~folderAttributes::FLAG_HAS_CHILDREN;
+ break;
+
+ case IMAPParser::mailbox_flag::HASCHILDREN:
+
+ flags |= folderAttributes::FLAG_HAS_CHILDREN;
+ break;
+
+ case IMAPParser::mailbox_flag::SPECIALUSE_ALL:
+
+ specialUse = folderAttributes::SPECIALUSE_ALL;
+ break;
+
+ case IMAPParser::mailbox_flag::SPECIALUSE_ARCHIVE:
+
+ specialUse = folderAttributes::SPECIALUSE_ARCHIVE;
+ break;
+
+ case IMAPParser::mailbox_flag::SPECIALUSE_DRAFTS:
+
+ specialUse = folderAttributes::SPECIALUSE_DRAFTS;
+ break;
+
+ case IMAPParser::mailbox_flag::SPECIALUSE_FLAGGED:
+
+ specialUse = folderAttributes::SPECIALUSE_FLAGGED;
+ break;
+
+ case IMAPParser::mailbox_flag::SPECIALUSE_JUNK:
+
+ specialUse = folderAttributes::SPECIALUSE_JUNK;
+ break;
+
+ case IMAPParser::mailbox_flag::SPECIALUSE_SENT:
+
+ specialUse = folderAttributes::SPECIALUSE_SENT;
+ break;
+
+ case IMAPParser::mailbox_flag::SPECIALUSE_TRASH:
+
+ specialUse = folderAttributes::SPECIALUSE_TRASH;
+ break;
+
+ case IMAPParser::mailbox_flag::SPECIALUSE_IMPORTANT:
+
+ specialUse = folderAttributes::SPECIALUSE_IMPORTANT;
+ break;
+
+ default:
+
+ break;
+ }
+ }
+
+ if (path.getSize() == 1 && path.getLastComponent().getBuffer() == "INBOX") {
+ specialUse = folderAttributes::SPECIALUSE_INBOX;
+ }
+
+ attribs.setSpecialUse(specialUse);
+ attribs.setType(type);
+ attribs.setFlags(flags);
+}
+
+
+int IMAPUtils::messageFlagsFromFlags(const IMAPParser::flag_list& list) {
+
+ int flags = 0;
+
+ for (auto &flag : list.flags) {
+
+ switch (flag->type) {
+
+ case IMAPParser::flag::ANSWERED:
+
+ flags |= message::FLAG_REPLIED;
+ break;
+
+ case IMAPParser::flag::FLAGGED:
+
+ flags |= message::FLAG_MARKED;
+ break;
+
+ case IMAPParser::flag::DELETED:
+
+ flags |= message::FLAG_DELETED;
+ break;
+
+ case IMAPParser::flag::SEEN:
+
+ flags |= message::FLAG_SEEN;
+ break;
+
+ case IMAPParser::flag::DRAFT:
+
+ flags |= message::FLAG_DRAFT;
+ break;
+
+ default:
+ //case IMAPParser::flag::UNKNOWN:
+
+ break;
+ }
+ }
+
+ return flags;
+}
+
+
+// static
+const std::vector <string> IMAPUtils::messageFlagList(const int flags) {
+
+ std::vector <string> flagList;
+
+ if (flags == -1) {
+ return flagList; // default flags
+ }
+
+ if (flags & message::FLAG_REPLIED) flagList.push_back("\\Answered");
+ if (flags & message::FLAG_MARKED) flagList.push_back("\\Flagged");
+ if (flags & message::FLAG_DELETED) flagList.push_back("\\Deleted");
+ if (flags & message::FLAG_SEEN) flagList.push_back("\\Seen");
+ if (flags & message::FLAG_DRAFT) flagList.push_back("\\Draft");
+
+ return flagList;
+}
+
+
+// static
+const string IMAPUtils::dateTime(const vmime::datetime& date) {
+
+ std::ostringstream res;
+ res.imbue(std::locale::classic());
+
+ // date_time ::= <"> date_day_fixed "-" date_month "-" date_year
+ // SPACE time SPACE zone <">
+ //
+ // time ::= 2digit ":" 2digit ":" 2digit
+ // ;; Hours minutes seconds
+ // zone ::= ("+" / "-") 4digit
+ // ;; Signed four-digit value of hhmm representing
+ // ;; hours and minutes west of Greenwich
+ res << '"';
+
+ // Date
+ if (date.getDay() < 10) res << ' ';
+ res << date.getDay();
+
+ res << '-';
+
+ static const char* monthNames[12] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+
+ res << monthNames[std::min(std::max(date.getMonth() - 1, 0), 11)];
+
+ res << '-';
+
+ if (date.getYear() < 10) res << '0';
+ if (date.getYear() < 100) res << '0';
+ if (date.getYear() < 1000) res << '0';
+ res << date.getYear();
+
+ res << ' ';
+
+ // Time
+ if (date.getHour() < 10) res << '0';
+ res << date.getHour() << ':';
+
+ if (date.getMinute() < 10) res << '0';
+ res << date.getMinute() << ':';
+
+ if (date.getSecond() < 10) res << '0';
+ res << date.getSecond();
+
+ res << ' ';
+
+ // Zone
+ const int zs = (date.getZone() < 0 ? -1 : 1);
+ const int zh = (date.getZone() * zs) / 60;
+ const int zm = (date.getZone() * zs) % 60;
+
+ res << (zs < 0 ? '-' : '+');
+
+ if (zh < 10) res << '0';
+ res << zh;
+
+ if (zm < 10) res << '0';
+ res << zm;
+
+ res << '"';
+
+ return res.str();
+}
+
+
+// static
+shared_ptr <IMAPCommand> IMAPUtils::buildFetchCommand(
+ const shared_ptr <IMAPConnection>& cnt,
+ const messageSet& msgs,
+ const fetchAttributes& options
+) {
+
+ // Example:
+ // C: A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)])
+ // S: * 2 FETCH ....
+ // S: * 3 FETCH ....
+ // S: * 4 FETCH ....
+ // S: A654 OK FETCH completed
+
+ std::vector <string> items;
+
+ if (options.has(fetchAttributes::SIZE)) {
+ items.push_back("RFC822.SIZE");
+ }
+
+ if (options.has(fetchAttributes::FLAGS)) {
+ items.push_back("FLAGS");
+ }
+
+ if (options.has(fetchAttributes::STRUCTURE)) {
+ items.push_back("BODYSTRUCTURE");
+ }
+
+ if (options.has(fetchAttributes::UID)) {
+
+ items.push_back("UID");
+
+ // Also fetch MODSEQ if CONDSTORE is supported
+ if (cnt && cnt->hasCapability("CONDSTORE") && !cnt->isMODSEQDisabled()) {
+ items.push_back("MODSEQ");
+ }
+ }
+
+ if (options.has(fetchAttributes::FULL_HEADER)) {
+
+ items.push_back("RFC822.HEADER");
+
+ } else {
+
+ if (options.has(fetchAttributes::ENVELOPE)) {
+ items.push_back("ENVELOPE");
+ }
+
+ std::vector <string> headerFields;
+
+ if (options.has(fetchAttributes::CONTENT_INFO)) {
+ headerFields.push_back("CONTENT_TYPE");
+ }
+
+ if (options.has(fetchAttributes::IMPORTANCE)) {
+ headerFields.push_back("IMPORTANCE");
+ headerFields.push_back("X-PRIORITY");
+ }
+
+ // Also add custom header fields to fetch, if any
+ const std::vector <string> customHeaderFields = options.getHeaderFields();
+ std::copy(customHeaderFields.begin(), customHeaderFields.end(), std::back_inserter(headerFields));
+
+ if (!headerFields.empty()) {
+
+ string list;
+
+ for (std::vector <string>::iterator it = headerFields.begin() ;
+ it != headerFields.end() ; ++it) {
+
+ if (it != headerFields.begin()) {
+ list += " ";
+ }
+
+ list += *it;
+ }
+
+ items.push_back("BODY[HEADER.FIELDS (" + list + ")]");
+ }
+ }
+
+ return IMAPCommand::FETCH(msgs, items);
+}
+
+
+// static
+void IMAPUtils::convertAddressList(
+ const IMAPParser::address_list& src,
+ mailboxList& dest
+) {
+
+ for (auto& addr : src.addresses) {
+
+ text name;
+ text::decodeAndUnfold(addr->addr_name->value, &name);
+
+ string email = addr->addr_mailbox->value
+ + "@" + addr->addr_host->value;
+
+ dest.appendMailbox(make_shared <mailbox>(name, email));
+ }
+}
+
+
+
+class IMAPUIDMessageSetEnumerator : public messageSetEnumerator {
+
+public:
+
+ IMAPUIDMessageSetEnumerator()
+ : m_first(true) {
+
+ m_oss.imbue(std::locale::classic());
+ }
+
+ void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) {
+
+ if (!m_first) {
+ m_oss << ",";
+ }
+
+ if (range.getFirst() == range.getLast()) {
+ m_oss << range.getFirst();
+ } else if (range.getLast() == size_t(-1)) {
+ m_oss << range.getFirst() << ":*";
+ } else {
+ m_oss << range.getFirst() << ":" << range.getLast();
+ }
+
+ m_first = false;
+ }
+
+ void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& range) {
+
+ if (!m_first) {
+ m_oss << ",";
+ }
+
+ if (range.getFirst() == range.getLast()) {
+ m_oss << range.getFirst();
+ } else if (range.getLast() == size_t(-1)) {
+ m_oss << range.getFirst() << ":*";
+ } else {
+ m_oss << range.getFirst() << ":" << range.getLast();
+ }
+
+ m_first = false;
+ }
+
+ const std::string str() const {
+
+ return m_oss.str();
+ }
+
+private:
+
+ std::ostringstream m_oss;
+ bool m_first;
+};
+
+
+class IMAPMessageSetEnumerator : public messageSetEnumerator {
+
+public:
+
+ void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) {
+
+ for (size_t i = range.getFirst(), last = range.getLast() ; i <= last ; ++i) {
+ m_list.push_back(i);
+ }
+ }
+
+ void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) {
+
+ // Not used
+ }
+
+ const std::vector <size_t>& list() const {
+
+ return m_list;
+ }
+
+public:
+
+ std::vector <size_t> m_list;
+};
+
+
+
+// static
+const string IMAPUtils::messageSetToSequenceSet(const messageSet& msgs) {
+
+ IMAPUIDMessageSetEnumerator en;
+ msgs.enumerate(en);
+
+ return en.str();
+}
+
+
+// static
+messageSet IMAPUtils::buildMessageSet(const IMAPParser::uid_set& uidSetRef) {
+
+ messageSet set = messageSet::empty();
+
+ const IMAPParser::uid_set* uidSet = &uidSetRef;
+
+ for ( ; uidSet ; uidSet = uidSet->next_uid_set.get()) {
+
+ if (uidSet->uid_range) {
+
+ set.addRange(
+ UIDMessageRange(
+ message::uid(uidSet->uid_range->uniqueid1->value),
+ message::uid(uidSet->uid_range->uniqueid2->value)
+ )
+ );
+
+ } else {
+
+ set.addRange(
+ UIDMessageRange(
+ message::uid(uidSet->uniqueid->value)
+ )
+ );
+ }
+ }
+
+ return set;
+}
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
diff --git a/vmime-master/src/vmime/net/imap/IMAPUtils.hpp b/vmime-master/src/vmime/net/imap/IMAPUtils.hpp
new file mode 100644
index 0000000..d4bd135
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/IMAPUtils.hpp
@@ -0,0 +1,144 @@
+//
+// 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_NET_IMAP_IMAPUTILS_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAPUTILS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+
+#include "vmime/types.hpp"
+#include "vmime/dateTime.hpp"
+
+#include "vmime/net/folder.hpp"
+#include "vmime/net/message.hpp"
+#include "vmime/net/imap/IMAPParser.hpp"
+#include "vmime/net/imap/IMAPConnection.hpp"
+#include "vmime/net/imap/IMAPCommand.hpp"
+
+#include "vmime/mailboxList.hpp"
+
+#include <vector>
+
+
+namespace vmime {
+namespace net {
+namespace imap {
+
+
+class VMIME_EXPORT IMAPUtils
+{
+public:
+
+ static const string pathToString(const char hierarchySeparator, const folder::path& path);
+ static const folder::path stringToPath(const char hierarchySeparator, const string& str);
+
+ static const string toModifiedUTF7(const char hierarchySeparator, const folder::path::component& text);
+ static const folder::path::component fromModifiedUTF7(const string& text);
+
+ /** Quote string if it contains IMAP-special characters.
+ *
+ * @param text string to quote
+ * @return quoted string
+ */
+ static const string quoteString(const string& text);
+
+ /** Parse mailbox flags and fill in folder attributes.
+ *
+ * @param cnt reference to current IMAP connection (for testing capabilities)
+ * @param path folder full path
+ * @param list list of mailbox flags
+ * @param attribs reference to an object holding folder attributes
+ */
+ static void mailboxFlagsToFolderAttributes(
+ const shared_ptr <const IMAPConnection>& cnt,
+ const folder::path &path,
+ const IMAPParser::mailbox_flag_list& list,
+ folderAttributes& attribs
+ );
+
+ static int messageFlagsFromFlags(const IMAPParser::flag_list& list);
+
+ static const std::vector <string> messageFlagList(const int flags);
+
+ /** Format a date/time to IMAP date/time format.
+ *
+ * @param date date/time to format
+ * @return IMAP-formatted date/time
+ */
+ static const string dateTime(const vmime::datetime& date);
+
+ /** Construct a fetch request for the specified messages, designated
+ * either by their sequence numbers or their UIDs.
+ *
+ * @param cnt connection
+ * @param msgs message set
+ * @param options fetch options
+ * @return fetch request
+ */
+ static shared_ptr <IMAPCommand> buildFetchCommand(
+ const shared_ptr <IMAPConnection>& cnt,
+ const messageSet& msgs,
+ const fetchAttributes& options
+ );
+
+ /** Convert a parser-style address list to a mailbox list.
+ *
+ * @param src input address list
+ * @param dest output mailbox list
+ */
+ static void convertAddressList(const IMAPParser::address_list& src, mailboxList& dest);
+
+ /** Returns an IMAP-formatted sequence set given a message set.
+ *
+ * @param msgs message set
+ * @return IMAP sequence set (eg. "1:5,7,15:*")
+ */
+ static const string messageSetToSequenceSet(const messageSet& msgs);
+
+ /** Constructs a message set from a parser 'uid_set' structure.
+ *
+ * @param uidSet UID set, as returned by the parser
+ * @return message set
+ */
+ static messageSet buildMessageSet(const IMAPParser::uid_set& uidSet);
+
+private:
+
+ static const string buildFetchRequestImpl
+ (const shared_ptr <IMAPConnection>& cnt, const string& mode, const string& set, const int options);
+};
+
+
+} // imap
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
+
+#endif // VMIME_NET_IMAP_IMAPUTILS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/imap/imap.hpp b/vmime-master/src/vmime/net/imap/imap.hpp
new file mode 100644
index 0000000..f25baa4
--- /dev/null
+++ b/vmime-master/src/vmime/net/imap/imap.hpp
@@ -0,0 +1,35 @@
+//
+// 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_NET_IMAP_IMAP_HPP_INCLUDED
+#define VMIME_NET_IMAP_IMAP_HPP_INCLUDED
+
+
+#include "vmime/net/imap/IMAPFolder.hpp"
+#include "vmime/net/imap/IMAPFolderStatus.hpp"
+#include "vmime/net/imap/IMAPMessage.hpp"
+#include "vmime/net/imap/IMAPStore.hpp"
+#include "vmime/net/imap/IMAPSStore.hpp"
+
+
+#endif // VMIME_NET_IMAP_IMAP_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.cpp b/vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.cpp
new file mode 100644
index 0000000..e611949
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.cpp
@@ -0,0 +1,569 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/format/courierMaildirFormat.hpp"
+
+#include "vmime/net/maildir/maildirStore.hpp"
+#include "vmime/net/maildir/maildirUtils.hpp"
+
+#include "vmime/platform.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+namespace format {
+
+
+courierMaildirFormat::courierMaildirFormat(const shared_ptr <context>& ctx)
+ : maildirFormat(ctx) {
+
+}
+
+
+const string courierMaildirFormat::getName() const {
+
+ return "courier";
+}
+
+
+void courierMaildirFormat::createFolder(const folder::path& path) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) {
+ throw exceptions::invalid_folder_name();
+ }
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(path, ROOT_DIRECTORY)
+ );
+
+ shared_ptr <utility::file> newDir = fsf->create(
+ folderPathToFileSystemPath(path, NEW_DIRECTORY)
+ );
+ shared_ptr <utility::file> tmpDir = fsf->create(
+ folderPathToFileSystemPath(path, TMP_DIRECTORY)
+ );
+ shared_ptr <utility::file> curDir = fsf->create(
+ folderPathToFileSystemPath(path, CUR_DIRECTORY)
+ );
+
+ rootDir->createDirectory(true);
+
+ newDir->createDirectory(false);
+ tmpDir->createDirectory(false);
+ curDir->createDirectory(false);
+
+ shared_ptr <utility::file> maildirFile = fsf->create(
+ folderPathToFileSystemPath(path, ROOT_DIRECTORY)
+ / utility::file::path::component("maildirfolder")
+ );
+
+ maildirFile->createFile();
+}
+
+
+void courierMaildirFormat::destroyFolder(const folder::path& path) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ // Recursively delete directories of subfolders
+ const std::vector <folder::path> folders = listFolders(path, true);
+
+ for (std::vector <folder::path>::size_type i = 0, n = folders.size() ; i < n ; ++i) {
+
+ maildirUtils::recursiveFSDelete(
+ fsf->create(folderPathToFileSystemPath(folders[i], ROOT_DIRECTORY))
+ );
+ }
+
+ // Recursively delete the directory of this folder
+ maildirUtils::recursiveFSDelete(
+ fsf->create(folderPathToFileSystemPath(path, ROOT_DIRECTORY))
+ );
+}
+
+
+void courierMaildirFormat::renameFolder(
+ const folder::path& oldPath,
+ const folder::path& newPath
+) {
+
+ const std::vector <folder::path> folders = listFolders(oldPath, true);
+
+ for (std::vector <folder::path>::size_type i = 0, n = folders.size() ; i < n ; ++i) {
+
+ const folder::path folderOldPath = folders[i];
+
+ folder::path folderNewPath = folderOldPath;
+ folderNewPath.renameParent(oldPath, newPath);
+
+ renameFolderImpl(folderOldPath, folderNewPath);
+ }
+
+ renameFolderImpl(oldPath, newPath);
+}
+
+
+void courierMaildirFormat::renameFolderImpl(
+ const folder::path& oldPath,
+ const folder::path& newPath
+) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ const utility::file::path oldFSPath =
+ folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY);
+
+ const utility::file::path newFSPath =
+ folderPathToFileSystemPath(newPath, ROOT_DIRECTORY);
+
+ shared_ptr <utility::file> rootDir = fsf->create(oldFSPath);
+ rootDir->rename(newFSPath);
+}
+
+
+bool courierMaildirFormat::folderExists(const folder::path& path) const {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(path, ROOT_DIRECTORY)
+ );
+
+ shared_ptr <utility::file> newDir = fsf->create(
+ folderPathToFileSystemPath(path, NEW_DIRECTORY)
+ );
+ shared_ptr <utility::file> tmpDir = fsf->create(
+ folderPathToFileSystemPath(path, TMP_DIRECTORY)
+ );
+ shared_ptr <utility::file> curDir = fsf->create(
+ folderPathToFileSystemPath(path, CUR_DIRECTORY)
+ );
+
+ shared_ptr <utility::file> maildirFile = fsf->create(
+ folderPathToFileSystemPath(path, ROOT_DIRECTORY)
+ / utility::file::path::component("maildirfolder")
+ );
+
+ bool exists = rootDir->exists() && rootDir->isDirectory() &&
+ newDir->exists() && newDir->isDirectory() &&
+ tmpDir->exists() && tmpDir->isDirectory() &&
+ curDir->exists() && curDir->isDirectory();
+
+ // If this is not the root folder, then a file named "maildirfolder"
+ // must also be present in the directory
+ if (!path.isRoot()) {
+ exists = exists && maildirFile->exists() && maildirFile->isFile();
+ }
+
+ return exists;
+}
+
+
+bool courierMaildirFormat::folderHasSubfolders(const folder::path& path) const {
+
+ std::vector <string> dirs;
+ return listDirectories(path, dirs, true);
+}
+
+
+const utility::file::path courierMaildirFormat::folderPathToFileSystemPath(
+ const folder::path& path,
+ const DirectoryType type
+) const {
+
+ // Virtual folder "/MyFolder/SubFolder" corresponds to physical
+ // directory "[store root]/.MyFolder.SubFolder"
+ utility::file::path fsPath = getContext()->getStore()->getFileSystemPath();
+
+ if (!path.isRoot()) {
+
+ string folderComp;
+
+ for (size_t i = 0, n = path.getSize() ; i < n ; ++i) {
+ folderComp += "." + toModifiedUTF7(path[i]);
+ }
+
+ fsPath /= utility::file::path::component(folderComp);
+ }
+
+ // Last component
+ switch (type) {
+
+ case ROOT_DIRECTORY:
+
+ // Nothing to add
+ break;
+
+ case NEW_DIRECTORY:
+
+ fsPath /= NEW_DIR;
+ break;
+
+ case CUR_DIRECTORY:
+
+ fsPath /= CUR_DIR;
+ break;
+
+ case TMP_DIRECTORY:
+
+ fsPath /= TMP_DIR;
+ break;
+
+ case CONTAINER_DIRECTORY:
+
+ // Not used
+ break;
+ }
+
+ return fsPath;
+}
+
+
+const std::vector <folder::path> courierMaildirFormat::listFolders(
+ const folder::path& root,
+ const bool recursive
+) const {
+
+ // First, list directories
+ std::vector <string> dirs;
+ listDirectories(root, dirs, false);
+
+ // Then, map directories to folders
+ std::vector <folder::path> folders;
+
+ for (std::vector <string>::size_type i = 0, n = dirs.size() ; i < n ; ++i) {
+
+ const string dir = dirs[i].substr(1) + ".";
+ folder::path path;
+
+ for (size_t pos = dir.find("."), prev = 0 ;
+ pos != string::npos ; prev = pos + 1, pos = dir.find(".", pos + 1)) {
+
+ const string comp = dir.substr(prev, pos - prev);
+ path /= fromModifiedUTF7(comp);
+ }
+
+ if (recursive || path.getSize() == root.getSize() + 1) {
+ folders.push_back(path);
+ }
+ }
+
+ return folders;
+}
+
+
+bool courierMaildirFormat::listDirectories(
+ const folder::path& root,
+ std::vector <string>& dirs,
+ const bool onlyTestForExistence
+) const {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ getContext()->getStore()->getFileSystemPath()
+ );
+
+ if (rootDir->exists()) {
+
+ // To speed up things, and if we are not searching in root folder,
+ // search for directories with a common prefix
+ string base;
+
+ if (!root.isRoot()) {
+ for (size_t i = 0, n = root.getSize() ; i < n ; ++i) {
+ base += "." + toModifiedUTF7(root[i]);
+ }
+ }
+
+ // Enumerate directories
+ shared_ptr <utility::fileIterator> it = rootDir->getFiles();
+
+ while (it->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = it->nextElement();
+
+ if (isSubfolderDirectory(*file)) {
+
+ const string dir = file->getFullPath().getLastComponent().getBuffer();
+
+ if (base.empty() || (dir.length() > base.length() && dir.substr(0, base.length()) == base)) {
+
+ dirs.push_back(dir);
+
+ if (onlyTestForExistence) {
+ return true;
+ }
+ }
+ }
+ }
+
+ } else {
+
+ // No sub-folder
+ }
+
+ std::sort(dirs.begin(), dirs.end());
+
+ return !dirs.empty();
+}
+
+
+// static
+bool courierMaildirFormat::isSubfolderDirectory(const utility::file& file) {
+
+ // A directory which names starts with '.' may be a subfolder
+ if (file.isDirectory() &&
+ file.getFullPath().getLastComponent().getBuffer().length() >= 1 &&
+ file.getFullPath().getLastComponent().getBuffer()[0] == '.') {
+
+ return true;
+ }
+
+ return false;
+}
+
+
+// static
+const string courierMaildirFormat::toModifiedUTF7(const folder::path::component& text) {
+
+ // From http://www.courier-mta.org/?maildir.html:
+ //
+ // Folder names can contain any Unicode character, except for control
+ // characters. US-ASCII characters, U+0x0020 - U+0x007F, except for the
+ // period, forward-slash, and ampersand characters (U+0x002E, U+0x002F,
+ // and U+0x0026) represent themselves. The ampersand is represented by
+ // the two character sequence "&-". The period, forward slash, and non
+ // US-ASCII Unicode characters are represented using the UTF-7 character
+ // set, and encoded with a modified form of base64-encoding.
+ //
+ // The "&" character starts the modified base64-encoded sequence; the
+ // sequence is terminated by the "-" character. The sequence of 16-bit
+ // Unicode characters is written in big-endian order, and encoded using
+ // the base64-encoding method described in section 5.2 of RFC 1521, with
+ // the following modifications:
+ //
+ // * The "=" padding character is omitted. When decoding, an incomplete
+ // 16-bit character is discarded.
+ //
+ // * The comma character, "," is used in place of the "/" character in
+ // the base64 alphabet.
+ //
+ // For example, the word "Resume" with both "e"s being the e-acute
+ // character, U+0x00e9, is encoded as "R&AOk-sum&AOk-" (so a folder of
+ // that name would be a maildir subdirectory called ".R&AOk-sum&AOk-").
+ //
+
+ // Transcode path component to UTF-7 charset.
+ // WARNING: This may throw "exceptions::charset_conv_error"
+ const string cvt = text.getConvertedText(charset(charsets::UTF_7));
+
+ // Transcode to modified UTF-7 (RFC-2060).
+ string out;
+ out.reserve((cvt.length() * 3) / 2);
+
+ bool inB64sequence = false;
+
+ for (string::const_iterator it = cvt.begin() ; it != cvt.end() ; ++it) {
+
+ const unsigned char c = *it;
+
+ switch (c) {
+
+ // Beginning of Base64 sequence: replace '+' with '&'
+ case '+': {
+
+ if (!inB64sequence) {
+ inB64sequence = true;
+ out += '&';
+ } else {
+ out += '+';
+ }
+
+ break;
+ }
+ // End of Base64 sequence
+ case '-': {
+
+ inB64sequence = false;
+ out += '-';
+ break;
+ }
+ // ',' is used instead of '/' in modified Base64,
+ // and simply UTF7-encoded out of a Base64 sequence
+ case '/': {
+
+ if (inB64sequence) {
+ out += ',';
+ } else {
+ out += "&Lw-";
+ }
+
+ break;
+ }
+ // Encode period (should not happen in a Base64 sequence)
+ case '.': {
+
+ out += "&Lg-";
+ break;
+ }
+ // '&' (0x26) is represented by the two-octet sequence "&-"
+ case '&': {
+
+ if (!inB64sequence) {
+ out += "&-";
+ } else {
+ out += '&';
+ }
+
+ break;
+ }
+ default: {
+
+ out += c;
+ break;
+ }
+ }
+ }
+
+ return out;
+}
+
+
+// static
+const folder::path::component courierMaildirFormat::fromModifiedUTF7(const string& text) {
+
+ // Transcode from modified UTF-7
+ string out;
+ out.reserve(text.length());
+
+ bool inB64sequence = false;
+ unsigned char prev = 0;
+
+ for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) {
+
+ const unsigned char c = *it;
+
+ switch (c) {
+
+ // Start of Base64 sequence
+ case '&': {
+
+ if (!inB64sequence) {
+ inB64sequence = true;
+ out += '+';
+ } else {
+ out += '&';
+ }
+
+ break;
+ }
+ // End of Base64 sequence (or "&-" --> "&")
+ case '-': {
+
+ if (inB64sequence && prev == '&') {
+ out += '&';
+ } else {
+ out += '-';
+ }
+
+ inB64sequence = false;
+ break;
+ }
+ // ',' is used instead of '/' in modified Base64
+ case ',': {
+
+ out += (inB64sequence ? '/' : ',');
+ break;
+ }
+ default: {
+
+ out += c;
+ break;
+ }
+
+ }
+
+ prev = c;
+ }
+
+ // Store it as UTF-8 by default
+ string cvt;
+ charset::convert(out, cvt, charset(charsets::UTF_7), charset(charsets::UTF_8));
+
+ return folder::path::component(cvt, charset(charsets::UTF_8));
+}
+
+
+bool courierMaildirFormat::supports() const {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ getContext()->getStore()->getFileSystemPath()
+ );
+
+ if (rootDir->exists()) {
+
+ // Try to find a file named "maildirfolder", which indicates
+ // the Maildir is in Courier format
+ shared_ptr <utility::fileIterator> it = rootDir->getFiles();
+
+ while (it->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = it->nextElement();
+
+ if (isSubfolderDirectory(*file)) {
+
+ shared_ptr <utility::file> folderFile = fsf->create(
+ file->getFullPath() / utility::file::path::component("maildirfolder")
+ );
+
+ if (folderFile->exists() && folderFile->isFile()) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
+} // format
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.hpp b/vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.hpp
new file mode 100644
index 0000000..7db1a83
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/format/courierMaildirFormat.hpp
@@ -0,0 +1,127 @@
+//
+// 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_NET_MAILDIR_FORMAT_COURIERMAILDIRFORMAT_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_FORMAT_COURIERMAILDIRFORMAT_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirFormat.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+namespace format {
+
+
+/** Reads Courier/QMail Maildir format.
+ */
+class VMIME_EXPORT courierMaildirFormat : public maildirFormat {
+
+public:
+
+ courierMaildirFormat(const shared_ptr <context>& ctx);
+
+
+ /* Folder types:
+ *
+ * - ROOT_DIRECTORY: ~/Mail/.MyFolder
+ * - NEW_DIRECTORY: ~/Mail/.MyFolder/new
+ * - CUR_DIRECTORY: ~/Mail/.MyFolder/cur
+ * - TMP_DIRECTORY: ~/Mail/.MyFolder/tmp
+ * - CONTAINER_DIRECTORY: not used
+ */
+
+ const string getName() const;
+
+ void createFolder(const folder::path& path);
+ void destroyFolder(const folder::path& path);
+ void renameFolder(const folder::path& oldPath, const folder::path& newPath);
+
+ bool folderExists(const folder::path& path) const;
+ bool folderHasSubfolders(const folder::path& path) const;
+
+ const utility::file::path folderPathToFileSystemPath(
+ const folder::path& path,
+ const DirectoryType type
+ ) const;
+
+ const std::vector <folder::path> listFolders(
+ const folder::path& root,
+ const bool recursive
+ ) const;
+
+protected:
+
+ bool supports() const;
+
+
+ static const string toModifiedUTF7(const folder::path::component& text);
+ static const folder::path::component fromModifiedUTF7(const string& text);
+
+ void renameFolderImpl(const folder::path& oldPath, const folder::path& newPath);
+
+ /** Test whether the specified file system directory corresponds to
+ * a maildir subfolder. The name of the directory should start
+ * with a '.' to be listed as a subfolder.
+ *
+ * @param file reference to a file system directory
+ * @return true if the specified directory is a maildir subfolder,
+ * false otherwise
+ */
+ static bool isSubfolderDirectory(const utility::file& file);
+
+ /** List directories corresponding to folders which are (direct or
+ * indirect) children of specified folder.
+ *
+ * @param root root folder
+ * @param dirs list in which found directories will be added
+ * @param onlyTestForExistence if true, the function returns as soon
+ * as the first directory is found
+ * @return true if at least one directory has been found,
+ * false otherwise
+ */
+ bool listDirectories(
+ const folder::path& root,
+ std::vector <string>& dirs,
+ const bool onlyTestForExistence
+ ) const;
+};
+
+
+} // format
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_FORMAT_COURIERMAILDIRFORMAT_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.cpp b/vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.cpp
new file mode 100644
index 0000000..4eb89e8
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.cpp
@@ -0,0 +1,337 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/format/kmailMaildirFormat.hpp"
+
+#include "vmime/net/maildir/maildirStore.hpp"
+#include "vmime/net/maildir/maildirUtils.hpp"
+
+#include "vmime/platform.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+namespace format {
+
+
+kmailMaildirFormat::kmailMaildirFormat(const shared_ptr <context>& ctx)
+ : maildirFormat(ctx) {
+
+}
+
+
+const string kmailMaildirFormat::getName() const {
+
+ return "kmail";
+}
+
+
+void kmailMaildirFormat::createFolder(const folder::path& path) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) {
+ throw exceptions::invalid_folder_name();
+ }
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(path, ROOT_DIRECTORY)
+ );
+
+ shared_ptr <utility::file> newDir = fsf->create(
+ folderPathToFileSystemPath(path, NEW_DIRECTORY)
+ );
+ shared_ptr <utility::file> tmpDir = fsf->create(
+ folderPathToFileSystemPath(path, TMP_DIRECTORY)
+ );
+ shared_ptr <utility::file> curDir = fsf->create(
+ folderPathToFileSystemPath(path, CUR_DIRECTORY)
+ );
+
+ rootDir->createDirectory(true);
+
+ newDir->createDirectory(false);
+ tmpDir->createDirectory(false);
+ curDir->createDirectory(false);
+}
+
+
+void kmailMaildirFormat::destroyFolder(const folder::path& path) {
+
+ // Delete 'folder' and '.folder.directory' directories
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ maildirUtils::recursiveFSDelete(
+ fsf->create(folderPathToFileSystemPath(path, ROOT_DIRECTORY)) // root
+ );
+
+ maildirUtils::recursiveFSDelete(
+ fsf->create(folderPathToFileSystemPath(path, CONTAINER_DIRECTORY)) // container
+ );
+}
+
+
+bool kmailMaildirFormat::folderExists(const folder::path& path) const {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(path, ROOT_DIRECTORY)
+ );
+
+ shared_ptr <utility::file> newDir = fsf->create(
+ folderPathToFileSystemPath(path, NEW_DIRECTORY)
+ );
+ shared_ptr <utility::file> tmpDir = fsf->create(
+ folderPathToFileSystemPath(path, TMP_DIRECTORY)
+ );
+ shared_ptr <utility::file> curDir = fsf->create(
+ folderPathToFileSystemPath(path, CUR_DIRECTORY)
+ );
+
+ return rootDir->exists() && rootDir->isDirectory() &&
+ newDir->exists() && newDir->isDirectory() &&
+ tmpDir->exists() && tmpDir->isDirectory() &&
+ curDir->exists() && curDir->isDirectory();
+}
+
+
+const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath(
+ const folder::path& path,
+ const DirectoryType type
+) const {
+
+ // Root path
+ utility::file::path fsPath = getContext()->getStore()->getFileSystemPath();
+
+ const size_t pathSize = path.getSize();
+ const size_t count = (type == CONTAINER_DIRECTORY
+ ? pathSize : (pathSize >= 1 ? pathSize - 1 : 0));
+
+ // Parent folders
+ for (size_t i = 0 ; i < count ; ++i) {
+
+ utility::file::path::component comp(path[i]);
+
+ // TODO: may not work with all encodings...
+ comp.setBuffer("." + comp.getBuffer() + ".directory");
+
+ fsPath /= comp;
+ }
+
+ // Last component
+ if (path.getSize() != 0 && type != CONTAINER_DIRECTORY) {
+
+ fsPath /= path.getLastComponent();
+
+ switch (type) {
+
+ case ROOT_DIRECTORY:
+
+ // Nothing to add
+ break;
+
+ case NEW_DIRECTORY:
+
+ fsPath /= NEW_DIR;
+ break;
+
+ case CUR_DIRECTORY:
+
+ fsPath /= CUR_DIR;
+ break;
+
+ case TMP_DIRECTORY:
+
+ fsPath /= TMP_DIR;
+ break;
+
+ case CONTAINER_DIRECTORY:
+
+ // Can't happen...
+ break;
+ }
+ }
+
+ return fsPath;
+}
+
+
+const std::vector <folder::path> kmailMaildirFormat::listFolders(
+ const folder::path& root,
+ const bool recursive
+) const {
+
+ std::vector <folder::path> list;
+ listFoldersImpl(list, root, recursive);
+
+ return list;
+}
+
+
+void kmailMaildirFormat::listFoldersImpl(
+ std::vector <folder::path>& list,
+ const folder::path& root,
+ const bool recursive
+) const {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(root, root.isEmpty() ? ROOT_DIRECTORY : CONTAINER_DIRECTORY)
+ );
+
+ if (rootDir->exists()) {
+
+ shared_ptr <utility::fileIterator> it = rootDir->getFiles();
+
+ while (it->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = it->nextElement();
+
+ if (isSubfolderDirectory(*file)) {
+
+ const utility::path subPath = root / file->getFullPath().getLastComponent();
+
+ list.push_back(subPath);
+
+ if (recursive) {
+ listFoldersImpl(list, subPath, true);
+ }
+ }
+ }
+
+ } else {
+
+ // No sub-folder
+ }
+}
+
+
+// static
+bool kmailMaildirFormat::isSubfolderDirectory(const utility::file& file) {
+
+ // A directory which name does not start with '.' is listed as a sub-folder
+ if (file.isDirectory() &&
+ file.getFullPath().getLastComponent().getBuffer().length() >= 1 &&
+ file.getFullPath().getLastComponent().getBuffer()[0] != '.') {
+
+ return true;
+ }
+
+ return false;
+}
+
+
+void kmailMaildirFormat::renameFolder(const folder::path& oldPath, const folder::path& newPath) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY)
+ );
+ shared_ptr <utility::file> contDir = fsf->create(
+ folderPathToFileSystemPath(oldPath, CONTAINER_DIRECTORY)
+ );
+
+ try {
+
+ const utility::file::path newRootPath =
+ folderPathToFileSystemPath(newPath, ROOT_DIRECTORY);
+ const utility::file::path newContPath =
+ folderPathToFileSystemPath(newPath, CONTAINER_DIRECTORY);
+
+ rootDir->rename(newRootPath);
+
+ // Container directory may not exist, so ignore error when trying to rename it
+ try {
+ contDir->rename(newContPath);
+ } catch (exceptions::filesystem_exception& e) {
+ // Ignore
+ }
+
+ } catch (exceptions::filesystem_exception& e) {
+
+ // Revert to old location
+ const utility::file::path rootPath =
+ folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY);
+ const utility::file::path contPath =
+ folderPathToFileSystemPath(oldPath, CONTAINER_DIRECTORY);
+
+ try {
+ rootDir->rename(rootPath);
+ contDir->rename(contPath);
+ } catch (exceptions::filesystem_exception& e) {
+ // Ignore (not recoverable)
+ }
+
+ throw;
+ }
+}
+
+
+bool kmailMaildirFormat::folderHasSubfolders(const folder::path& path) const {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> rootDir = fsf->create(
+ folderPathToFileSystemPath(path, CONTAINER_DIRECTORY)
+ );
+
+ shared_ptr <utility::fileIterator> it = rootDir->getFiles();
+
+ while (it->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = it->nextElement();
+
+ if (isSubfolderDirectory(*file)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+bool kmailMaildirFormat::supports() const {
+
+ // This is the default
+ return true;
+}
+
+
+} // format
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.hpp b/vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.hpp
new file mode 100644
index 0000000..26b557a
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/format/kmailMaildirFormat.hpp
@@ -0,0 +1,115 @@
+//
+// 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_NET_MAILDIR_FORMAT_KMAILMAILDIRFORMAT_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_FORMAT_KMAILMAILDIRFORMAT_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirFormat.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+namespace format {
+
+
+/** Reads KMail Maildir format.
+ */
+class VMIME_EXPORT kmailMaildirFormat : public maildirFormat {
+
+public:
+
+ kmailMaildirFormat(const shared_ptr <context>& ctx);
+
+
+ /* Folder types:
+ *
+ * - ROOT_DIRECTORY: ~/Mail/MyFolder
+ * - NEW_DIRECTORY: ~/Mail/MyFolder/new
+ * - CUR_DIRECTORY: ~/Mail/MyFolder/cur
+ * - TMP_DIRECTORY: ~/Mail/MyFolder/tmp
+ * - CONTAINER_DIRECTORY: ~/Mail/.MyFolder.directory
+ */
+
+ const string getName() const;
+
+ void createFolder(const folder::path& path);
+ void destroyFolder(const folder::path& path);
+ void renameFolder(const folder::path& oldPath, const folder::path& newPath);
+
+ bool folderExists(const folder::path& path) const;
+ bool folderHasSubfolders(const folder::path& path) const;
+
+ const utility::file::path folderPathToFileSystemPath(
+ const folder::path& path,
+ const DirectoryType type
+ ) const;
+
+ const std::vector <folder::path> listFolders(
+ const folder::path& root,
+ const bool recursive
+ ) const;
+
+protected:
+
+ bool supports() const;
+
+
+ /** Recursive implementation of listFolders().
+ */
+ void listFoldersImpl(
+ std::vector <folder::path>& list,
+ const folder::path& root,
+ const bool recursive
+ ) const;
+
+ /** Test whether the specified file system directory corresponds to
+ * a maildir subfolder. The name of the directory should not start
+ * with '.' to be listed as a subfolder.
+ *
+ * @param file reference to a file system directory
+ * @return true if the specified directory is a maildir subfolder,
+ * false otherwise
+ */
+ static bool isSubfolderDirectory(const utility::file& file);
+};
+
+
+} // format
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#endif // VMIME_NET_MAILDIR_FORMAT_KMAILMAILDIRFORMAT_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/maildir/maildir.hpp b/vmime-master/src/vmime/net/maildir/maildir.hpp
new file mode 100644
index 0000000..8835bf4
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildir.hpp
@@ -0,0 +1,34 @@
+//
+// 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_NET_MAILDIR_MAILDIR_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIR_HPP_INCLUDED
+
+
+#include "vmime/net/maildir/maildirFolder.hpp"
+#include "vmime/net/maildir/maildirFolderStatus.hpp"
+#include "vmime/net/maildir/maildirMessage.hpp"
+#include "vmime/net/maildir/maildirStore.hpp"
+
+
+#endif // VMIME_NET_MAILDIR_MAILDIR_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirFolder.cpp b/vmime-master/src/vmime/net/maildir/maildirFolder.cpp
new file mode 100644
index 0000000..8c02025
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirFolder.cpp
@@ -0,0 +1,1365 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirFolder.hpp"
+
+#include "vmime/net/maildir/maildirStore.hpp"
+#include "vmime/net/maildir/maildirMessage.hpp"
+#include "vmime/net/maildir/maildirUtils.hpp"
+#include "vmime/net/maildir/maildirFormat.hpp"
+#include "vmime/net/maildir/maildirFolderStatus.hpp"
+
+#include "vmime/message.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/platform.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+maildirFolder::maildirFolder(
+ const folder::path& path,
+ const shared_ptr <maildirStore>& store
+)
+ : m_store(store),
+ m_path(path),
+ m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()),
+ m_mode(-1),
+ m_open(false),
+ m_unreadMessageCount(0),
+ m_messageCount(0) {
+
+ store->registerFolder(this);
+}
+
+
+maildirFolder::~maildirFolder() {
+
+ try {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (store) {
+
+ if (m_open) {
+ close(false);
+ }
+
+ store->unregisterFolder(this);
+
+ } else if (m_open) {
+
+ close(false);
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+void maildirFolder::onStoreDisconnected() {
+
+ m_store.reset();
+}
+
+
+int maildirFolder::getMode() const {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ return m_mode;
+}
+
+
+const folderAttributes maildirFolder::getAttributes() {
+
+ folderAttributes attribs;
+
+ if (m_path.isEmpty()) {
+ attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS);
+ } else {
+ attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS | folderAttributes::TYPE_CONTAINS_MESSAGES);
+ }
+
+ if (m_store.lock()->getFormat()->folderHasSubfolders(m_path)) {
+ attribs.setFlags(folderAttributes::FLAG_HAS_CHILDREN); // contains at least one sub-folder
+ }
+
+ return attribs;
+}
+
+
+const folder::path::component maildirFolder::getName() const {
+
+ return m_name;
+}
+
+
+const folder::path maildirFolder::getFullPath() const {
+
+ return m_path;
+}
+
+
+void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (isOpen()) {
+ throw exceptions::illegal_state("Folder is already open");
+ } else if (!exists()) {
+ throw exceptions::illegal_state("Folder does not exist");
+ }
+
+ scanFolder();
+
+ m_open = true;
+ m_mode = mode;
+}
+
+
+void maildirFolder::close(const bool expunge) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (expunge) {
+ this->expunge();
+ }
+
+ m_open = false;
+ m_mode = -1;
+
+ onClose();
+}
+
+
+void maildirFolder::onClose() {
+
+ for (std::vector <maildirMessage*>::iterator it = m_messages.begin() ;
+ it != m_messages.end() ; ++it) {
+
+ (*it)->onFolderClosed();
+ }
+
+ m_messages.clear();
+}
+
+
+void maildirFolder::registerMessage(maildirMessage* msg) {
+
+ m_messages.push_back(msg);
+}
+
+
+void maildirFolder::unregisterMessage(maildirMessage* msg) {
+
+ std::vector <maildirMessage*>::iterator it =
+ std::find(m_messages.begin(), m_messages.end(), msg);
+
+ if (it != m_messages.end()) {
+ m_messages.erase(it);
+ }
+}
+
+
+void maildirFolder::create(const folderAttributes& /* attribs */) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (isOpen()) {
+ throw exceptions::illegal_state("Folder is open");
+ } else if (exists()) {
+ throw exceptions::illegal_state("Folder already exists");
+ } else if (!store->isValidFolderName(m_name)) {
+ throw exceptions::invalid_folder_name();
+ }
+
+ // Create directory on file system
+ try {
+ store->getFormat()->createFolder(m_path);
+ } catch (exceptions::filesystem_exception& e) {
+ throw exceptions::command_error("CREATE", "", "File system exception", e);
+ }
+
+ // Notify folder created
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::folderEvent::TYPE_CREATED,
+ m_path, m_path
+ );
+
+ notifyFolder(event);
+}
+
+
+void maildirFolder::destroy() {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (isOpen()) {
+ throw exceptions::illegal_state("Folder is open");
+ }
+
+ // Delete folder
+ try {
+ store->getFormat()->destroyFolder(m_path);
+ } catch (std::exception&) {
+ // Ignore exception: anyway, we can't recover from this...
+ }
+
+ // Notify folder deleted
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::folderEvent::TYPE_DELETED,
+ m_path, m_path
+ );
+
+ notifyFolder(event);
+}
+
+
+bool maildirFolder::exists() {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ return store->getFormat()->folderExists(m_path);
+}
+
+
+bool maildirFolder::isOpen() const {
+
+ return m_open;
+}
+
+
+void maildirFolder::scanFolder() {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ try {
+
+ m_messageCount = 0;
+ m_unreadMessageCount = 0;
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ utility::file::path newDirPath =
+ store->getFormat()->folderPathToFileSystemPath(m_path, maildirFormat::NEW_DIRECTORY);
+ shared_ptr <utility::file> newDir = fsf->create(newDirPath);
+
+ utility::file::path curDirPath =
+ store->getFormat()->folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
+ shared_ptr <utility::file> curDir = fsf->create(curDirPath);
+
+ // New received messages (new/)
+ shared_ptr <utility::fileIterator> nit = newDir->getFiles();
+ std::vector <utility::file::path::component> newMessageFilenames;
+
+ while (nit->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = nit->nextElement();
+
+ if (maildirUtils::isMessageFile(*file)) {
+ newMessageFilenames.push_back(file->getFullPath().getLastComponent());
+ }
+ }
+
+ // Current messages (cur/)
+ shared_ptr <utility::fileIterator> cit = curDir->getFiles();
+ std::vector <utility::file::path::component> curMessageFilenames;
+
+ while (cit->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = cit->nextElement();
+
+ if (maildirUtils::isMessageFile(*file)) {
+ curMessageFilenames.push_back(file->getFullPath().getLastComponent());
+ }
+ }
+
+ // Update/delete existing messages (found in previous scan)
+ for (size_t i = 0 ; i < m_messageInfos.size() ; ++i) {
+
+ messageInfos& msgInfos = m_messageInfos[i];
+
+ // NOTE: the flags may have changed (eg. moving from 'new' to 'cur'
+ // may imply the 'S' flag) and so the filename. That's why we use
+ // "maildirUtils::messageIdComparator" to compare only the 'unique'
+ // portion of the filename...
+
+ if (msgInfos.type == messageInfos::TYPE_CUR) {
+
+ const std::vector <utility::file::path::component>::iterator pos =
+ std::find_if(
+ curMessageFilenames.begin(),
+ curMessageFilenames.end(),
+ maildirUtils::messageIdComparator(msgInfos.path)
+ );
+
+ // If we cannot find this message in the 'cur' directory,
+ // it means it has been deleted (and expunged).
+ if (pos == curMessageFilenames.end()) {
+
+ msgInfos.type = messageInfos::TYPE_DELETED;
+
+ // Otherwise, update its information.
+ } else {
+
+ msgInfos.path = *pos;
+ curMessageFilenames.erase(pos);
+ }
+ }
+ }
+
+ m_messageInfos.reserve(m_messageInfos.size()
+ + newMessageFilenames.size() + curMessageFilenames.size());
+
+ // Add new messages from 'new': we are responsible to move the files
+ // from the 'new' directory to the 'cur' directory, and append them
+ // to our message list.
+ for (std::vector <utility::file::path::component>::const_iterator
+ it = newMessageFilenames.begin() ; it != newMessageFilenames.end() ; ++it) {
+
+ const utility::file::path::component newFilename =
+ maildirUtils::buildFilename(maildirUtils::extractId(*it), 0);
+
+ // Move messages from 'new' to 'cur'
+ shared_ptr <utility::file> file = fsf->create(newDirPath / *it);
+ file->rename(curDirPath / newFilename);
+
+ // Append to message list
+ messageInfos msgInfos;
+ msgInfos.path = newFilename;
+
+ if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) {
+ msgInfos.type = messageInfos::TYPE_DELETED;
+ } else {
+ msgInfos.type = messageInfos::TYPE_CUR;
+ }
+
+ m_messageInfos.push_back(msgInfos);
+ }
+
+ // Add new messages from 'cur': the files have already been moved
+ // from 'new' to 'cur'. Just append them to our message list.
+ for (std::vector <utility::file::path::component>::const_iterator
+ it = curMessageFilenames.begin() ; it != curMessageFilenames.end() ; ++it) {
+
+ // Append to message list
+ messageInfos msgInfos;
+ msgInfos.path = *it;
+
+ if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) {
+ msgInfos.type = messageInfos::TYPE_DELETED;
+ } else {
+ msgInfos.type = messageInfos::TYPE_CUR;
+ }
+
+ m_messageInfos.push_back(msgInfos);
+ }
+
+ // Update message count
+ size_t unreadMessageCount = 0;
+
+ for (std::vector <messageInfos>::const_iterator
+ it = m_messageInfos.begin() ; it != m_messageInfos.end() ; ++it) {
+
+ if ((maildirUtils::extractFlags((*it).path) & message::FLAG_SEEN) == 0) {
+ ++unreadMessageCount;
+ }
+ }
+
+ m_unreadMessageCount = unreadMessageCount;
+ m_messageCount = static_cast <size_t>(m_messageInfos.size());
+
+ } catch (exceptions::filesystem_exception&) {
+
+ // Should not happen...
+ }
+}
+
+
+shared_ptr <message> maildirFolder::getMessage(const size_t num) {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (num < 1 || num > m_messageCount) {
+ throw exceptions::message_not_found();
+ }
+
+ return make_shared <maildirMessage>(dynamicCast <maildirFolder>(shared_from_this()), num);
+}
+
+
+std::vector <shared_ptr <message> > maildirFolder::getMessages(const messageSet& msgs) {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (msgs.isNumberSet()) {
+
+ const std::vector <size_t> numbers = maildirUtils::messageSetToNumberList(msgs, m_messageCount);
+
+ std::vector <shared_ptr <message> > messages;
+ shared_ptr <maildirFolder> thisFolder = dynamicCast <maildirFolder>(shared_from_this());
+
+ for (std::vector <size_t>::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) {
+
+ if (*it < 1|| *it > m_messageCount) {
+ throw exceptions::message_not_found();
+ }
+
+ messages.push_back(make_shared <maildirMessage>(thisFolder, *it));
+ }
+
+ return messages;
+
+ } else {
+
+ throw exceptions::operation_not_supported();
+ }
+}
+
+
+size_t maildirFolder::getMessageCount() {
+
+ return m_messageCount;
+}
+
+
+shared_ptr <folder> maildirFolder::getFolder(const folder::path::component& name) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ return shared_ptr <maildirFolder>(new maildirFolder(m_path / name, store));
+}
+
+
+std::vector <shared_ptr <folder> > maildirFolder::getFolders(const bool recursive) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!isOpen() && !store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ std::vector <shared_ptr <folder> > list;
+
+ listFolders(list, recursive);
+
+ return list;
+}
+
+
+void maildirFolder::listFolders(std::vector <shared_ptr <folder> >& list, const bool recursive) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ try {
+
+ std::vector <folder::path> pathList =
+ store->getFormat()->listFolders(m_path, recursive);
+
+ list.reserve(pathList.size());
+
+ for (std::vector <folder::path>::size_type i = 0, n = pathList.size() ; i < n ; ++i) {
+
+ shared_ptr <maildirFolder> subFolder(
+ new maildirFolder(pathList[i], store)
+ );
+
+ list.push_back(subFolder);
+ }
+
+ } catch (exceptions::filesystem_exception& e) {
+
+ throw exceptions::command_error("LIST", "", "", e);
+ }
+}
+
+
+void maildirFolder::rename(const folder::path& newPath) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (m_path.isEmpty() || newPath.isEmpty()) {
+ throw exceptions::illegal_operation("Cannot rename root folder");
+ } else if (!store->isValidFolderName(newPath.getLastComponent())) {
+ throw exceptions::invalid_folder_name();
+ }
+
+ // Rename the directory on the file system
+ try {
+ store->getFormat()->renameFolder(m_path, newPath);
+ } catch (vmime::exception& e) {
+ throw exceptions::command_error("RENAME", "", "", e);
+ }
+
+ // Notify folder renamed
+ folder::path oldPath(m_path);
+
+ m_path = newPath;
+ m_name = newPath.getLastComponent();
+
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::folderEvent::TYPE_RENAMED,
+ oldPath, newPath
+ );
+
+ notifyFolder(event);
+
+ // Notify folders with the same path
+ for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && (*it)->getFullPath() == oldPath) {
+
+ (*it)->m_path = newPath;
+ (*it)->m_name = newPath.getLastComponent();
+
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>((*it)->shared_from_this()),
+ events::folderEvent::TYPE_RENAMED,
+ oldPath, newPath
+ );
+
+ (*it)->notifyFolder(event);
+
+ } else if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) {
+
+ folder::path oldPath((*it)->m_path);
+
+ (*it)->m_path.renameParent(oldPath, newPath);
+
+ shared_ptr <events::folderEvent> event =
+ make_shared <events::folderEvent>(
+ dynamicCast <folder>((*it)->shared_from_this()),
+ events::folderEvent::TYPE_RENAMED,
+ oldPath, (*it)->m_path
+ );
+
+ (*it)->notifyFolder(event);
+ }
+ }
+}
+
+
+void maildirFolder::deleteMessages(const messageSet& msgs) {
+
+ // Mark messages as deleted
+ setMessageFlags(msgs, message::FLAG_DELETED, message::FLAG_MODE_ADD);
+}
+
+
+void maildirFolder::setMessageFlags(
+ const messageSet& msgs,
+ const int flags,
+ const int mode
+) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ } else if (m_mode == MODE_READ_ONLY) {
+ throw exceptions::illegal_state("Folder is read-only");
+ }
+
+ if (msgs.isNumberSet()) {
+
+ const std::vector <size_t> nums = maildirUtils::messageSetToNumberList(msgs, m_messageCount);
+
+ // Change message flags
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ utility::file::path curDirPath = store->getFormat()->
+ folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
+
+ for (std::vector <size_t>::const_iterator it =
+ nums.begin() ; it != nums.end() ; ++it) {
+
+ const size_t num = *it - 1;
+
+ try {
+
+ const utility::file::path::component path = m_messageInfos[num].path;
+ shared_ptr <utility::file> file = fsf->create(curDirPath / path);
+
+ int newFlags = maildirUtils::extractFlags(path);
+
+ switch (mode) {
+ case message::FLAG_MODE_ADD: newFlags |= flags; break;
+ case message::FLAG_MODE_REMOVE: newFlags &= ~flags; break;
+ default:
+ case message::FLAG_MODE_SET: newFlags = flags; break;
+ }
+
+ const utility::file::path::component newPath =
+ maildirUtils::buildFilename(maildirUtils::extractId(path), newFlags);
+
+ file->rename(curDirPath / newPath);
+
+ if (flags & message::FLAG_DELETED) {
+ m_messageInfos[num].type = messageInfos::TYPE_DELETED;
+ } else {
+ m_messageInfos[num].type = messageInfos::TYPE_CUR;
+ }
+
+ m_messageInfos[num].path = newPath;
+
+ } catch (exceptions::filesystem_exception& e) {
+
+ // Ignore (not important)
+ }
+ }
+
+ // Update local flags
+ switch (mode) {
+
+ case message::FLAG_MODE_ADD: {
+
+ for (std::vector <maildirMessage*>::iterator it =
+ m_messages.begin() ; it != m_messages.end() ; ++it) {
+
+ if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) &&
+ (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) {
+
+ (*it)->m_flags |= flags;
+ }
+ }
+
+ break;
+ }
+ case message::FLAG_MODE_REMOVE: {
+
+ for (std::vector <maildirMessage*>::iterator it =
+ m_messages.begin() ; it != m_messages.end() ; ++it) {
+
+ if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) &&
+ (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) {
+
+ (*it)->m_flags &= ~flags;
+ }
+ }
+
+ break;
+ }
+ default:
+ case message::FLAG_MODE_SET: {
+
+ for (std::vector <maildirMessage*>::iterator it =
+ m_messages.begin() ; it != m_messages.end() ; ++it) {
+
+ if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) &&
+ (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) {
+
+ (*it)->m_flags = flags;
+ }
+ }
+
+ break;
+ }
+
+ }
+
+ // Notify message flags changed
+ shared_ptr <events::messageChangedEvent> event =
+ make_shared <events::messageChangedEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageChangedEvent::TYPE_FLAGS,
+ nums
+ );
+
+ notifyMessageChanged(event);
+
+ // TODO: notify other folders with the same path
+
+ } else {
+
+ throw exceptions::operation_not_supported();
+ }
+}
+
+
+messageSet maildirFolder::addMessage(
+ const shared_ptr <vmime::message>& msg,
+ const int flags,
+ vmime::datetime* date,
+ utility::progressListener* progress
+) {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter ossAdapter(oss);
+
+ msg->generate(ossAdapter);
+
+ const string& str = oss.str();
+ utility::inputStreamStringAdapter strAdapter(str);
+
+ return addMessage(strAdapter, str.length(), flags, date, progress);
+}
+
+
+messageSet maildirFolder::addMessage(
+ utility::inputStream& is,
+ const size_t size,
+ const int flags,
+ vmime::datetime* /* date */,
+ utility::progressListener* progress
+) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ } else if (m_mode == MODE_READ_ONLY) {
+ throw exceptions::illegal_state("Folder is read-only");
+ }
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ utility::file::path tmpDirPath = store->getFormat()->
+ folderPathToFileSystemPath(m_path,maildirFormat::TMP_DIRECTORY);
+ utility::file::path dstDirPath = store->getFormat()->
+ folderPathToFileSystemPath(
+ m_path,
+ flags == message::FLAG_RECENT ?
+ maildirFormat::NEW_DIRECTORY :
+ maildirFormat::CUR_DIRECTORY
+ );
+
+ const utility::file::path::component filename =
+ maildirUtils::buildFilename(maildirUtils::generateId(), ((flags == -1) ? 0 : flags));
+
+ try {
+ shared_ptr <utility::file> tmpDir = fsf->create(tmpDirPath);
+ tmpDir->createDirectory(true);
+ } catch (exceptions::filesystem_exception&) {
+ // Don't throw now, it will fail later...
+ }
+
+ try {
+ shared_ptr <utility::file> curDir = fsf->create(dstDirPath);
+ curDir->createDirectory(true);
+ } catch (exceptions::filesystem_exception&) {
+ // Don't throw now, it will fail later...
+ }
+
+ // Actually add the message
+ copyMessageImpl(tmpDirPath, dstDirPath, filename, is, size, progress);
+
+ // Append the message to the cache list
+ messageInfos msgInfos;
+ msgInfos.path = filename;
+ msgInfos.type = messageInfos::TYPE_CUR;
+
+ m_messageInfos.push_back(msgInfos);
+ m_messageCount++;
+
+ if ((flags == -1) || !(flags & message::FLAG_SEEN)) {
+ m_unreadMessageCount++;
+ }
+
+ // Notification
+ std::vector <size_t> nums;
+ nums.push_back(m_messageCount);
+
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageCountEvent::TYPE_ADDED,
+ nums
+ );
+
+ notifyMessageCount(event);
+
+ // Notify folders with the same path
+ for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && (*it)->getFullPath() == m_path) {
+
+ (*it)->m_messageCount = m_messageCount;
+ (*it)->m_unreadMessageCount = m_unreadMessageCount;
+
+ (*it)->m_messageInfos.resize(m_messageInfos.size());
+ std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin());
+
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>((*it)->shared_from_this()),
+ events::messageCountEvent::TYPE_ADDED,
+ nums
+ );
+
+ (*it)->notifyMessageCount(event);
+ }
+ }
+
+ return messageSet::empty();
+}
+
+
+void maildirFolder::copyMessageImpl(
+ const utility::file::path& tmpDirPath,
+ const utility::file::path& dstDirPath,
+ const utility::file::path::component& filename,
+ utility::inputStream& is, const size_t size,
+ utility::progressListener* progress
+) {
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ shared_ptr <utility::file> file = fsf->create(tmpDirPath / filename);
+
+ if (progress) {
+ progress->start(size);
+ }
+
+ // First, write the message into 'tmp'...
+ try {
+
+ file->createFile();
+
+ shared_ptr <utility::fileWriter> fw = file->getFileWriter();
+ shared_ptr <utility::outputStream> os = fw->getOutputStream();
+
+ byte_t buffer[65536];
+ size_t total = 0;
+
+ while (!is.eof()) {
+
+ const size_t read = is.read(buffer, sizeof(buffer));
+
+ if (read != 0) {
+ os->write(buffer, read);
+ total += read;
+ }
+
+ if (progress) {
+ progress->progress(total, size);
+ }
+ }
+
+ os->flush();
+
+ } catch (exception& e) {
+
+ if (progress) {
+ progress->stop(size);
+ }
+
+ // Delete temporary file
+ try {
+ shared_ptr <utility::file> file = fsf->create(tmpDirPath / filename);
+ file->remove();
+ } catch (exceptions::filesystem_exception&) {
+ // Ignore
+ }
+
+ throw exceptions::command_error("ADD", "", "", e);
+ }
+
+ // ...then, move it to 'cur'
+ try {
+
+ file->rename(dstDirPath / filename);
+
+ } catch (exception& e) {
+
+ if (progress) {
+ progress->stop(size);
+ }
+
+ // Delete temporary file
+ try {
+
+ file->remove();
+ shared_ptr <utility::file> file = fsf->create(dstDirPath / filename);
+ file->remove();
+
+ } catch (exceptions::filesystem_exception&) {
+
+ // Ignore
+ }
+
+ throw exceptions::command_error("ADD", "", "", e);
+ }
+
+ if (progress) {
+ progress->stop(size);
+ }
+}
+
+
+messageSet maildirFolder::copyMessages(const folder::path& dest, const messageSet& msgs) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ utility::file::path curDirPath =
+ store->getFormat()->folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
+
+ utility::file::path destCurDirPath = store->getFormat()->
+ folderPathToFileSystemPath(dest, maildirFormat::CUR_DIRECTORY);
+ utility::file::path destTmpDirPath = store->getFormat()->
+ folderPathToFileSystemPath(dest, maildirFormat::TMP_DIRECTORY);
+
+ // Create destination directories
+ try {
+
+ shared_ptr <utility::file> destTmpDir = fsf->create(destTmpDirPath);
+ destTmpDir->createDirectory(true);
+
+ } catch (exceptions::filesystem_exception&) {
+
+ // Don't throw now, it will fail later...
+ }
+
+ try {
+
+ shared_ptr <utility::file> destCurDir = fsf->create(destCurDirPath);
+ destCurDir->createDirectory(true);
+
+ } catch (exceptions::filesystem_exception&) {
+
+ // Don't throw now, it will fail later...
+ }
+
+ // Copy messages
+ const std::vector <size_t> nums = maildirUtils::messageSetToNumberList(msgs, m_messageCount);
+
+ try {
+
+ for (std::vector <size_t>::const_iterator it =
+ nums.begin() ; it != nums.end() ; ++it) {
+
+ const size_t num = *it;
+ const messageInfos& msg = m_messageInfos[num - 1];
+ const int flags = maildirUtils::extractFlags(msg.path);
+
+ const utility::file::path::component filename =
+ maildirUtils::buildFilename(maildirUtils::generateId(), flags);
+
+ shared_ptr <utility::file> file = fsf->create(curDirPath / msg.path);
+ shared_ptr <utility::fileReader> fr = file->getFileReader();
+ shared_ptr <utility::inputStream> is = fr->getInputStream();
+
+ copyMessageImpl(destTmpDirPath, destCurDirPath,
+ filename, *is, file->getLength(), NULL);
+ }
+
+ } catch (exception& e) {
+
+ notifyMessagesCopied(dest);
+ throw exceptions::command_error("COPY", "", "", e);
+ }
+
+ notifyMessagesCopied(dest);
+
+ return messageSet::empty();
+}
+
+
+void maildirFolder::notifyMessagesCopied(const folder::path& dest) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && (*it)->getFullPath() == dest) {
+
+ // We only need to update the first folder we found as calling
+ // status() will notify all the folders with the same path.
+ size_t count, unseen;
+ (*it)->status(count, unseen);
+
+ return;
+ }
+ }
+}
+
+
+void maildirFolder::status(size_t& count, size_t& unseen) {
+
+ count = 0;
+ unseen = 0;
+
+ shared_ptr <folderStatus> status = getStatus();
+
+ count = status->getMessageCount();
+ unseen = status->getUnseenCount();
+
+ m_messageCount = count;
+}
+
+
+shared_ptr <folderStatus> maildirFolder::getStatus() {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ const size_t oldCount = m_messageCount;
+
+ scanFolder();
+
+ shared_ptr <maildirFolderStatus> status = make_shared <maildirFolderStatus>();
+
+ status->setMessageCount(m_messageCount);
+ status->setUnseenCount(m_unreadMessageCount);
+
+ // Notify message count changed (new messages)
+ if (m_messageCount > oldCount) {
+
+ std::vector <size_t> nums;
+ nums.reserve(m_messageCount - oldCount);
+
+ for (size_t i = oldCount + 1, j = 0 ; i <= m_messageCount ; ++i, ++j) {
+ nums[j] = i;
+ }
+
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageCountEvent::TYPE_ADDED,
+ nums
+ );
+
+ notifyMessageCount(event);
+
+ // Notify folders with the same path
+ for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && (*it)->getFullPath() == m_path) {
+
+ (*it)->m_messageCount = m_messageCount;
+ (*it)->m_unreadMessageCount = m_unreadMessageCount;
+
+ (*it)->m_messageInfos.resize(m_messageInfos.size());
+ std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin());
+
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>((*it)->shared_from_this()),
+ events::messageCountEvent::TYPE_ADDED,
+ nums
+ );
+
+ (*it)->notifyMessageCount(event);
+ }
+ }
+ }
+
+ return status;
+}
+
+
+void maildirFolder::expunge() {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ } else if (m_mode == MODE_READ_ONLY) {
+ throw exceptions::illegal_state("Folder is read-only");
+ }
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ utility::file::path curDirPath = store->getFormat()->
+ folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
+
+ std::vector <size_t> nums;
+ size_t unreadCount = 0;
+
+ for (size_t num = 1 ; num <= m_messageCount ; ++num) {
+
+ messageInfos& infos = m_messageInfos[num - 1];
+
+ if (infos.type == messageInfos::TYPE_DELETED) {
+
+ nums.push_back(num);
+
+ for (std::vector <maildirMessage*>::iterator it =
+ m_messages.begin() ; it != m_messages.end() ; ++it) {
+
+ if ((*it)->m_num == num) {
+ (*it)->m_expunged = true;
+ } else if ((*it)->m_num > num) {
+ (*it)->m_num--;
+ }
+ }
+
+ if (maildirUtils::extractFlags(infos.path) & message::FLAG_SEEN) {
+ ++unreadCount;
+ }
+
+ // Delete file from file system
+ try {
+ shared_ptr <utility::file> file = fsf->create(curDirPath / infos.path);
+ file->remove();
+ } catch (exceptions::filesystem_exception& e) {
+ // Ignore (not important)
+ }
+ }
+ }
+
+ if (!nums.empty()) {
+
+ for (std::vector <size_t>::size_type i = nums.size() ; i != 0 ; --i) {
+ m_messageInfos.erase(m_messageInfos.begin() + (i - 1));
+ }
+ }
+
+ m_messageCount -= static_cast <size_t>(nums.size());
+ m_unreadMessageCount -= unreadCount;
+
+ // Notify message expunged
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageCountEvent::TYPE_REMOVED,
+ nums
+ );
+
+ notifyMessageCount(event);
+
+ // Notify folders with the same path
+ for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && (*it)->getFullPath() == m_path) {
+
+ (*it)->m_messageCount = m_messageCount;
+ (*it)->m_unreadMessageCount = m_unreadMessageCount;
+
+ (*it)->m_messageInfos.resize(m_messageInfos.size());
+ std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin());
+
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>((*it)->shared_from_this()),
+ events::messageCountEvent::TYPE_REMOVED,
+ nums
+ );
+
+ (*it)->notifyMessageCount(event);
+ }
+ }
+}
+
+
+shared_ptr <folder> maildirFolder::getParent() {
+
+ if (m_path.isEmpty()) {
+ return null;
+ } else {
+ return shared_ptr <maildirFolder>(new maildirFolder(m_path.getParent(), m_store.lock()));
+ }
+}
+
+
+shared_ptr <const store> maildirFolder::getStore() const {
+
+ return m_store.lock();
+}
+
+
+shared_ptr <store> maildirFolder::getStore() {
+
+ return m_store.lock();
+}
+
+
+void maildirFolder::fetchMessages(
+ std::vector <shared_ptr <message> >& msg,
+ const fetchAttributes& options,
+ utility::progressListener* progress
+) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (msg.empty()) {
+ return;
+ }
+
+ const size_t total = msg.size();
+ size_t current = 0;
+
+ if (progress) {
+ progress->start(total);
+ }
+
+ shared_ptr <maildirFolder> thisFolder = dynamicCast <maildirFolder>(shared_from_this());
+
+ for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ;
+ it != msg.end() ; ++it) {
+
+ dynamicCast <maildirMessage>(*it)->fetch(thisFolder, options);
+
+ if (progress) {
+ progress->progress(++current, total);
+ }
+ }
+
+ if (progress) {
+ progress->stop(total);
+ }
+}
+
+
+void maildirFolder::fetchMessage(
+ const shared_ptr <message>& msg,
+ const fetchAttributes& options
+) {
+
+ shared_ptr <maildirStore> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ dynamicCast <maildirMessage>(msg)->fetch(
+ dynamicCast <maildirFolder>(shared_from_this()),
+ options
+ );
+}
+
+
+std::vector <shared_ptr <message> > maildirFolder::getAndFetchMessages(
+ const messageSet& msgs,
+ const fetchAttributes& attribs
+) {
+
+ if (msgs.isEmpty()) {
+ return std::vector <shared_ptr <message> >();
+ }
+
+ std::vector <shared_ptr <message> > messages = getMessages(msgs);
+ fetchMessages(messages, attribs);
+
+ return messages;
+}
+
+
+int maildirFolder::getFetchCapabilities() const {
+
+ return fetchAttributes::ENVELOPE |
+ fetchAttributes::STRUCTURE |
+ fetchAttributes::CONTENT_INFO |
+ fetchAttributes::FLAGS |
+ fetchAttributes::SIZE |
+ fetchAttributes::FULL_HEADER |
+ fetchAttributes::UID |
+ fetchAttributes::IMPORTANCE;
+}
+
+
+const utility::file::path maildirFolder::getMessageFSPath(const size_t number) const {
+
+ utility::file::path curDirPath = m_store.lock()->getFormat()->
+ folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
+
+ return curDirPath / m_messageInfos[number - 1].path;
+}
+
+
+std::vector <size_t> maildirFolder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirFolder.hpp b/vmime-master/src/vmime/net/maildir/maildirFolder.hpp
new file mode 100644
index 0000000..24f2bf8
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirFolder.hpp
@@ -0,0 +1,211 @@
+//
+// 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_NET_MAILDIR_MAILDIRFOLDER_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRFOLDER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include <vector>
+#include <map>
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/folder.hpp"
+
+#include "vmime/utility/file.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirStore;
+class maildirMessage;
+
+
+/** maildir folder implementation.
+ */
+class VMIME_EXPORT maildirFolder : public folder {
+
+private:
+
+ friend class maildirStore;
+ friend class maildirMessage;
+
+ maildirFolder(const maildirFolder&) : folder() { }
+ maildirFolder(const folder::path& path, const shared_ptr <maildirStore>& store);
+
+public:
+
+ ~maildirFolder();
+
+
+ int getMode() const;
+
+ const folderAttributes getAttributes();
+
+ const folder::path::component getName() const;
+ const folder::path getFullPath() const;
+
+ void open(const int mode, bool failIfModeIsNotAvailable = false);
+ void close(const bool expunge);
+ void create(const folderAttributes& attribs);
+
+ bool exists();
+
+ void destroy();
+
+ bool isOpen() const;
+
+ shared_ptr <message> getMessage(const size_t num);
+ std::vector <shared_ptr <message> > getMessages(const messageSet& msgs);
+
+ size_t getMessageCount();
+
+ shared_ptr <folder> getFolder(const folder::path::component& name);
+ std::vector <shared_ptr <folder> > getFolders(const bool recursive = false);
+
+ void rename(const folder::path& newPath);
+
+ void deleteMessages(const messageSet& msgs);
+
+ void setMessageFlags(
+ const messageSet& msgs,
+ const int flags,
+ const int mode = message::FLAG_MODE_SET
+ );
+
+ messageSet addMessage(
+ const shared_ptr <vmime::message>& msg,
+ const int flags = -1,
+ vmime::datetime* date = NULL,
+ utility::progressListener* progress = NULL
+ );
+
+ messageSet addMessage(
+ utility::inputStream& is,
+ const size_t size,
+ const int flags = -1,
+ vmime::datetime* date = NULL,
+ utility::progressListener* progress = NULL
+ );
+
+ messageSet copyMessages(const folder::path& dest, const messageSet& msgs);
+
+ void status(size_t& count, size_t& unseen);
+ shared_ptr <folderStatus> getStatus();
+
+ void expunge();
+
+ shared_ptr <folder> getParent();
+
+ shared_ptr <const store> getStore() const;
+ shared_ptr <store> getStore();
+
+
+ void fetchMessages(
+ std::vector <shared_ptr <message> >& msg,
+ const fetchAttributes& options,
+ utility::progressListener* progress = NULL
+ );
+
+ void fetchMessage(const shared_ptr <message>& msg, const fetchAttributes& options);
+
+ std::vector <shared_ptr <message> > getAndFetchMessages(
+ const messageSet& msgs,
+ const fetchAttributes& attribs
+ );
+
+ int getFetchCapabilities() const;
+
+ std::vector <size_t> getMessageNumbersStartingOnUID(const message::uid& uid);
+
+private:
+
+ void scanFolder();
+
+ void listFolders(std::vector <shared_ptr <folder> >& list, const bool recursive);
+
+ void registerMessage(maildirMessage* msg);
+ void unregisterMessage(maildirMessage* msg);
+
+ const utility::file::path getMessageFSPath(const size_t number) const;
+
+ void onStoreDisconnected();
+
+ void onClose();
+
+ void deleteMessagesImpl(const std::vector <size_t>& nums);
+ void setMessageFlagsImpl(const std::vector <size_t>& nums, const int flags, const int mode);
+
+ void copyMessagesImpl(const folder::path& dest, const std::vector <size_t>& nums);
+ void copyMessageImpl(const utility::file::path& tmpDirPath, const utility::file::path& curDirPath, const utility::file::path::component& filename, utility::inputStream& is, const size_t size, utility::progressListener* progress);
+
+ void notifyMessagesCopied(const folder::path& dest);
+
+
+ weak_ptr <maildirStore> m_store;
+
+ folder::path m_path;
+ folder::path::component m_name;
+
+ int m_mode;
+ bool m_open;
+
+ size_t m_unreadMessageCount;
+ size_t m_messageCount;
+
+ // Store information about scanned messages
+ struct messageInfos {
+
+ enum Type {
+ TYPE_CUR,
+ TYPE_DELETED
+ };
+
+ utility::file::path::component path; // filename
+ Type type; // current location
+ };
+
+ std::vector <messageInfos> m_messageInfos;
+
+ // Instanciated message objects
+ std::vector <maildirMessage*> m_messages;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRFOLDER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirFolderStatus.cpp b/vmime-master/src/vmime/net/maildir/maildirFolderStatus.cpp
new file mode 100644
index 0000000..7438d8c
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirFolderStatus.cpp
@@ -0,0 +1,88 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirFolderStatus.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+maildirFolderStatus::maildirFolderStatus()
+ : m_count(0),
+ m_unseen(0) {
+
+}
+
+
+maildirFolderStatus::maildirFolderStatus(const maildirFolderStatus& other)
+ : folderStatus(),
+ m_count(other.m_count),
+ m_unseen(other.m_unseen) {
+
+}
+
+
+size_t maildirFolderStatus::getMessageCount() const {
+
+ return m_count;
+}
+
+
+size_t maildirFolderStatus::getUnseenCount() const {
+
+ return m_unseen;
+}
+
+
+void maildirFolderStatus::setMessageCount(const size_t count) {
+
+ m_count = count;
+}
+
+
+void maildirFolderStatus::setUnseenCount(const size_t unseen) {
+
+ m_unseen = unseen;
+}
+
+
+shared_ptr <folderStatus> maildirFolderStatus::clone() const {
+
+ return make_shared <maildirFolderStatus>(*this);
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
diff --git a/vmime-master/src/vmime/net/maildir/maildirFolderStatus.hpp b/vmime-master/src/vmime/net/maildir/maildirFolderStatus.hpp
new file mode 100644
index 0000000..3b69375
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirFolderStatus.hpp
@@ -0,0 +1,75 @@
+//
+// 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_NET_MAILDIR_MAILDIRFOLDERSTATUS_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRFOLDERSTATUS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/folderStatus.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+/** Holds the status of a Maildir folder.
+ */
+class VMIME_EXPORT maildirFolderStatus : public folderStatus {
+
+public:
+
+ maildirFolderStatus();
+ maildirFolderStatus(const maildirFolderStatus& other);
+
+ // Inherited from folderStatus
+ size_t getMessageCount() const;
+ size_t getUnseenCount() const;
+
+ shared_ptr <folderStatus> clone() const;
+
+
+ void setMessageCount(const size_t count);
+ void setUnseenCount(const size_t unseen);
+
+private:
+
+ size_t m_count;
+ size_t m_unseen;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRFOLDERSTATUS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirFormat.cpp b/vmime-master/src/vmime/net/maildir/maildirFormat.cpp
new file mode 100644
index 0000000..914c078
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirFormat.cpp
@@ -0,0 +1,104 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirFormat.hpp"
+#include "vmime/net/maildir/maildirStore.hpp"
+
+#include "vmime/net/maildir/format/kmailMaildirFormat.hpp"
+#include "vmime/net/maildir/format/courierMaildirFormat.hpp"
+
+#include "vmime/utility/file.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+const utility::file::path::component maildirFormat::TMP_DIR("tmp", vmime::charset(vmime::charsets::US_ASCII));
+const utility::file::path::component maildirFormat::CUR_DIR("cur", vmime::charset(vmime::charsets::US_ASCII));
+const utility::file::path::component maildirFormat::NEW_DIR("new", vmime::charset(vmime::charsets::US_ASCII));
+
+
+//
+// maildirFormat::context
+//
+
+maildirFormat::context::context(const shared_ptr <maildirStore>& store)
+ : m_store(store) {
+
+}
+
+
+shared_ptr <maildirStore> maildirFormat::context::getStore() {
+
+ return m_store.lock();
+}
+
+
+//
+// maildirFormat
+//
+
+maildirFormat::maildirFormat(const shared_ptr <context>& ctx)
+ : m_context(ctx) {
+
+}
+
+
+shared_ptr <maildirFormat::context> maildirFormat::getContext() const {
+
+ return m_context;
+}
+
+
+// static
+shared_ptr <maildirFormat> maildirFormat::detect(const shared_ptr <maildirStore>& store) {
+
+ shared_ptr <context> ctx = make_shared <context>(store);
+
+ // Try Courier format
+ shared_ptr <maildirFormat> fmt = make_shared <format::courierMaildirFormat>(ctx);
+
+ if (fmt->supports()) {
+ return fmt;
+ }
+
+ // Default is KMail format
+ return make_shared <format::kmailMaildirFormat>(ctx);
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirFormat.hpp b/vmime-master/src/vmime/net/maildir/maildirFormat.hpp
new file mode 100644
index 0000000..9b9e063
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirFormat.hpp
@@ -0,0 +1,192 @@
+//
+// 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_NET_MAILDIR_FORMAT_MAILDIRFORMAT_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_FORMAT_MAILDIRFORMAT_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/folder.hpp"
+
+#include "vmime/utility/file.hpp"
+#include "vmime/utility/path.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirStore;
+
+
+/** Interface for an object capable of reading a specific Maildir format.
+ */
+class VMIME_EXPORT maildirFormat : public object {
+
+public:
+
+ class context : public object {
+
+ public:
+
+ context(const shared_ptr <maildirStore>& store);
+
+ shared_ptr <maildirStore> getStore();
+
+ private:
+
+ weak_ptr <maildirStore> m_store;
+ };
+
+
+ /** Physical directory types. */
+ enum DirectoryType {
+ ROOT_DIRECTORY, /**< Root directory. */
+ NEW_DIRECTORY, /**< Directory containing unread messages. */
+ CUR_DIRECTORY, /**< Directory containing messages that have been seen. */
+ TMP_DIRECTORY, /**< Temporary directory used for reliable delivery. */
+ CONTAINER_DIRECTORY /**< Container for subfolders. */
+ };
+
+ /** Return the name of this Maildir format.
+ *
+ * @return format name
+ */
+ virtual const string getName() const = 0;
+
+ /** Create the specified folder.
+ *
+ * @param path virtual path of the folder
+ * @throw exceptions::filesystem_exception, invalid_folder_name
+ */
+ virtual void createFolder(const folder::path& path) = 0;
+
+ /** Destroy the specified folder.
+ *
+ * @param path virtual path of the folder
+ * @throw exceptions::filesystem_exception
+ */
+ virtual void destroyFolder(const folder::path& path) = 0;
+
+ /** Rename the specified folder.
+ *
+ * @param oldPath old virtual path of the folder
+ * @param newPath new virtual path of the folder
+ * @throw exceptions::filesystem_exception
+ */
+ virtual void renameFolder(const folder::path& oldPath, const folder::path& newPath) = 0;
+
+ /** Test whether the specified folder exists.
+ *
+ * @param path virtual path of the folder
+ * @return true if the folder exists, false otherwise
+ */
+ virtual bool folderExists(const folder::path& path) const = 0;
+
+ /** Test whether the specified folder has subfolders.
+ *
+ * @param path virtual path of the folder
+ * @return true if the folder has at least one subfolder,
+ * false otherwise
+ */
+ virtual bool folderHasSubfolders(const folder::path& path) const = 0;
+
+ /** Returns the directory which represents the specified
+ * folder on the file system.
+ *
+ * @param path virtual path of the folder
+ * @param type type of directory to return
+ * @return corresponding directory on the file system
+ */
+ virtual const utility::file::path folderPathToFileSystemPath(
+ const folder::path& path,
+ const DirectoryType type
+ ) const = 0;
+
+ /** List subfolders in the specified folder.
+ *
+ * @param root root folder in which to start the search
+ * @param recursive if set to true, all the descendant are
+ * returned; if set to false, only direct children are returned.
+ * @return list of subfolders
+ */
+ virtual const std::vector <folder::path> listFolders(
+ const folder::path& root,
+ const bool recursive
+ ) const = 0;
+
+
+ /** Try to detect the format of the specified Maildir store.
+ * If the format cannot be detected, a compatible implementation
+ * will be returned.
+ *
+ * @param store of which to detect format
+ * @return a Maildir format implementation for the specified store
+ */
+ static shared_ptr <maildirFormat> detect(const shared_ptr <maildirStore>& store);
+
+protected:
+
+ static const utility::file::path::component TMP_DIR; /**< Ensure reliable delivery (not to be listed). */
+ static const utility::file::path::component CUR_DIR; /**< No longer new messages. */
+ static const utility::file::path::component NEW_DIR; /**< Unread messages. */
+
+
+ maildirFormat(const shared_ptr <context>& ctx);
+
+
+ /** Returns the current context.
+ *
+ * @return current context
+ */
+ shared_ptr <context> getContext() const;
+
+ /** Quick checks whether this implementation can read the Maildir
+ * format in the specified directory.
+ *
+ * @return true if the implementation supports the specified
+ * Maildir, or false otherwise
+ */
+ virtual bool supports() const = 0;
+
+private:
+
+ shared_ptr <context> m_context;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_FORMAT_MAILDIRFORMAT_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirMessage.cpp b/vmime-master/src/vmime/net/maildir/maildirMessage.cpp
new file mode 100644
index 0000000..ae99c59
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirMessage.cpp
@@ -0,0 +1,410 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirMessage.hpp"
+#include "vmime/net/maildir/maildirMessagePart.hpp"
+#include "vmime/net/maildir/maildirMessageStructure.hpp"
+#include "vmime/net/maildir/maildirFolder.hpp"
+#include "vmime/net/maildir/maildirUtils.hpp"
+#include "vmime/net/maildir/maildirStore.hpp"
+
+#include "vmime/message.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/platform.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+#include "vmime/utility/stringUtils.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+maildirMessage::maildirMessage(const shared_ptr <maildirFolder>& folder, const size_t num)
+ : m_folder(folder),
+ m_num(num),
+ m_size(-1),
+ m_flags(FLAG_UNDEFINED),
+ m_expunged(false),
+ m_structure(null) {
+
+ folder->registerMessage(this);
+}
+
+
+maildirMessage::~maildirMessage() {
+
+ try {
+
+ shared_ptr <maildirFolder> folder = m_folder.lock();
+
+ if (folder) {
+ folder->unregisterMessage(this);
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+void maildirMessage::onFolderClosed() {
+
+ m_folder.reset();
+}
+
+
+size_t maildirMessage::getNumber() const {
+
+ return m_num;
+}
+
+
+const message::uid maildirMessage::getUID() const {
+
+ return m_uid;
+}
+
+
+size_t maildirMessage::getSize() const {
+
+ if (m_size == static_cast <size_t>(-1)) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_size;
+}
+
+
+bool maildirMessage::isExpunged() const {
+
+ return m_expunged;
+}
+
+
+shared_ptr <const messageStructure> maildirMessage::getStructure() const {
+
+ if (!m_structure) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_structure;
+}
+
+
+shared_ptr <messageStructure> maildirMessage::getStructure() {
+
+ if (!m_structure) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_structure;
+}
+
+
+shared_ptr <const header> maildirMessage::getHeader() const {
+
+ if (!m_header) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_header;
+}
+
+
+int maildirMessage::getFlags() const {
+
+ if (m_flags == FLAG_UNDEFINED) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_flags;
+}
+
+
+void maildirMessage::setFlags(const int flags, const int mode) {
+
+ shared_ptr <maildirFolder> folder = m_folder.lock();
+
+ if (!folder) {
+ throw exceptions::folder_not_found();
+ }
+
+ folder->setMessageFlags(messageSet::byNumber(m_num), flags, mode);
+}
+
+
+void maildirMessage::extract(
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const bool peek
+) const {
+
+ extractImpl(os, progress, 0, m_size, start, length, peek);
+}
+
+
+void maildirMessage::extractPart(
+ const shared_ptr <const messagePart>& p,
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const bool peek
+) const {
+
+ shared_ptr <const maildirMessagePart> mp = dynamicCast <const maildirMessagePart>(p);
+
+ extractImpl(
+ os, progress, mp->getBodyParsedOffset(), mp->getBodyParsedLength(),
+ start, length, peek
+ );
+}
+
+
+void maildirMessage::extractImpl(
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const size_t partialStart,
+ const size_t partialLength,
+ const bool /* peek */
+) const {
+
+ shared_ptr <const maildirFolder> folder = m_folder.lock();
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ const utility::file::path path = folder->getMessageFSPath(m_num);
+ shared_ptr <utility::file> file = fsf->create(path);
+
+ shared_ptr <utility::fileReader> reader = file->getFileReader();
+ shared_ptr <utility::inputStream> is = reader->getInputStream();
+
+ is->skip(start + partialStart);
+
+ byte_t buffer[8192];
+ size_t remaining =
+ (partialLength == static_cast <size_t>(-1)
+ ? length
+ : std::min(partialLength, length)
+ );
+
+ const size_t total = remaining;
+ size_t current = 0;
+
+ if (progress) {
+ progress->start(total);
+ }
+
+ while (!is->eof() && remaining > 0) {
+
+ const size_t read = is->read(buffer, std::min(remaining, sizeof(buffer)));
+
+ remaining -= read;
+ current += read;
+
+ os.write(buffer, read);
+
+ if (progress) {
+ progress->progress(current, total);
+ }
+ }
+
+ if (progress) {
+ progress->stop(total);
+ }
+
+ // TODO: mark as read unless 'peek' is set
+}
+
+
+void maildirMessage::fetchPartHeader(const shared_ptr <messagePart>& p) {
+
+ shared_ptr <maildirFolder> folder = m_folder.lock();
+
+ shared_ptr <maildirMessagePart> mp = dynamicCast <maildirMessagePart>(p);
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ const utility::file::path path = folder->getMessageFSPath(m_num);
+ shared_ptr <utility::file> file = fsf->create(path);
+
+ shared_ptr <utility::fileReader> reader = file->getFileReader();
+ shared_ptr <utility::inputStream> is = reader->getInputStream();
+
+ is->skip(mp->getHeaderParsedOffset());
+
+ byte_t buffer[1024];
+ size_t remaining = mp->getHeaderParsedLength();
+
+ string contents;
+ contents.reserve(remaining);
+
+ while (!is->eof() && remaining > 0) {
+
+ const size_t read = is->read(buffer, std::min(remaining, sizeof(buffer)));
+
+ remaining -= read;
+
+ vmime::utility::stringUtils::appendBytesToString(contents, buffer, read);
+ }
+
+ mp->getOrCreateHeader().parse(contents);
+}
+
+
+void maildirMessage::fetch(const shared_ptr <maildirFolder>& msgFolder, const fetchAttributes& options) {
+
+ shared_ptr <maildirFolder> folder = m_folder.lock();
+
+ if (folder != msgFolder) {
+ throw exceptions::folder_not_found();
+ }
+
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ const utility::file::path path = folder->getMessageFSPath(m_num);
+ shared_ptr <utility::file> file = fsf->create(path);
+
+ if (options.has(fetchAttributes::FLAGS)) {
+ m_flags = maildirUtils::extractFlags(path.getLastComponent());
+ }
+
+ if (options.has(fetchAttributes::SIZE)) {
+ m_size = file->getLength();
+ }
+
+ if (options.has(fetchAttributes::UID)) {
+ m_uid = maildirUtils::extractId(path.getLastComponent()).getBuffer();
+ }
+
+ if (options.has(fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO |
+ fetchAttributes::FULL_HEADER | fetchAttributes::STRUCTURE |
+ fetchAttributes::IMPORTANCE)) {
+
+ string contents;
+
+ shared_ptr <utility::fileReader> reader = file->getFileReader();
+ shared_ptr <utility::inputStream> is = reader->getInputStream();
+
+ // Need whole message contents for structure
+ if (options.has(fetchAttributes::STRUCTURE)) {
+
+ byte_t buffer[16384];
+
+ contents.reserve(file->getLength());
+
+ while (!is->eof()) {
+ const size_t read = is->read(buffer, sizeof(buffer));
+ vmime::utility::stringUtils::appendBytesToString(contents, buffer, read);
+ }
+
+ // Need only header
+ } else {
+
+ byte_t buffer[1024];
+
+ contents.reserve(4096);
+
+ while (!is->eof()) {
+
+ const size_t read = is->read(buffer, sizeof(buffer));
+ vmime::utility::stringUtils::appendBytesToString(contents, buffer, read);
+
+ const size_t sep1 = contents.rfind("\r\n\r\n");
+ const size_t sep2 = contents.rfind("\n\n");
+
+ if (sep1 != string::npos) {
+ contents.erase(contents.begin() + sep1 + 4, contents.end());
+ break;
+ } else if (sep2 != string::npos) {
+ contents.erase(contents.begin() + sep2 + 2, contents.end());
+ break;
+ }
+ }
+ }
+
+ vmime::message msg;
+ msg.parse(contents);
+
+ // Extract structure
+ if (options.has(fetchAttributes::STRUCTURE)) {
+ m_structure = make_shared <maildirMessageStructure>(shared_ptr <maildirMessagePart>(), msg);
+ }
+
+ // Extract some header fields or whole header
+ if (options.has(fetchAttributes::ENVELOPE |
+ fetchAttributes::CONTENT_INFO |
+ fetchAttributes::FULL_HEADER |
+ fetchAttributes::IMPORTANCE)) {
+
+ getOrCreateHeader()->copyFrom(*(msg.getHeader()));
+ }
+ }
+}
+
+
+shared_ptr <header> maildirMessage::getOrCreateHeader() {
+
+ if (m_header) {
+ return m_header;
+ } else {
+ return (m_header = make_shared <header>());
+ }
+}
+
+
+shared_ptr <vmime::message> maildirMessage::getParsedMessage() {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter os(oss);
+
+ extract(os);
+
+ shared_ptr <vmime::message> msg = make_shared <vmime::message>();
+ msg->parse(oss.str());
+
+ return msg;
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirMessage.hpp b/vmime-master/src/vmime/net/maildir/maildirMessage.hpp
new file mode 100644
index 0000000..8cd0aac
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirMessage.hpp
@@ -0,0 +1,137 @@
+//
+// 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_NET_MAILDIR_MAILDIRMESSAGE_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRMESSAGE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/message.hpp"
+#include "vmime/net/folder.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirFolder;
+
+
+/** maildir message implementation.
+ */
+class VMIME_EXPORT maildirMessage : public message {
+
+ friend class maildirFolder;
+
+ maildirMessage(const maildirMessage&) : message() { }
+
+public:
+
+ maildirMessage(const shared_ptr <maildirFolder>& folder, const size_t num);
+
+ ~maildirMessage();
+
+
+ size_t getNumber() const;
+
+ const uid getUID() const;
+
+ size_t getSize() const;
+
+ bool isExpunged() const;
+
+ shared_ptr <const messageStructure> getStructure() const;
+ shared_ptr <messageStructure> getStructure();
+
+ shared_ptr <const header> getHeader() const;
+
+ int getFlags() const;
+ void setFlags(const int flags, const int mode = FLAG_MODE_SET);
+
+ void extract(
+ utility::outputStream& os,
+ utility::progressListener* progress = NULL,
+ const size_t start = 0,
+ const size_t length = -1,
+ const bool peek = false
+ ) const;
+
+ void extractPart(
+ const shared_ptr <const messagePart>& p,
+ utility::outputStream& os,
+ utility::progressListener* progress = NULL,
+ const size_t start = 0,
+ const size_t length = -1,
+ const bool peek = false
+ ) const;
+
+ void fetchPartHeader(const shared_ptr <messagePart>& p);
+
+ shared_ptr <vmime::message> getParsedMessage();
+
+private:
+
+ void fetch(const shared_ptr <maildirFolder>& folder, const fetchAttributes& options);
+
+ void onFolderClosed();
+
+ shared_ptr <header> getOrCreateHeader();
+
+ void extractImpl(
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const size_t partialStart,
+ const size_t partialLength,
+ const bool peek
+ ) const;
+
+
+ weak_ptr <maildirFolder> m_folder;
+
+ size_t m_num;
+ size_t m_size;
+ int m_flags;
+ bool m_expunged;
+ uid m_uid;
+
+ shared_ptr <header> m_header;
+ shared_ptr <messageStructure> m_structure;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRMESSAGE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirMessagePart.cpp b/vmime-master/src/vmime/net/maildir/maildirMessagePart.cpp
new file mode 100644
index 0000000..7448d7e
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirMessagePart.cpp
@@ -0,0 +1,178 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirMessagePart.hpp"
+#include "vmime/net/maildir/maildirMessageStructure.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+maildirMessagePart::maildirMessagePart(
+ const shared_ptr <maildirMessagePart>& parent,
+ const size_t number,
+ const bodyPart& part
+)
+ : m_parent(parent),
+ m_header(null),
+ m_number(number) {
+
+ m_headerParsedOffset = part.getHeader()->getParsedOffset();
+ m_headerParsedLength = part.getHeader()->getParsedLength();
+
+ m_bodyParsedOffset = part.getBody()->getParsedOffset();
+ m_bodyParsedLength = part.getBody()->getParsedLength();
+
+ m_size = part.getBody()->getContents()->getLength();
+
+ m_mediaType = part.getBody()->getContentType();
+
+ auto cdispField = part.getHeader()->ContentDisposition();
+ if (cdispField) {
+ m_dispType = dynamic_cast <const contentDisposition&>(*cdispField->getValue());
+ }
+}
+
+
+maildirMessagePart::~maildirMessagePart() {
+
+}
+
+
+void maildirMessagePart::initStructure(const bodyPart& part) {
+
+ if (part.getBody()->getPartList().size() == 0) {
+
+ m_structure = null;
+
+ } else {
+
+ m_structure = make_shared <maildirMessageStructure>(
+ dynamicCast <maildirMessagePart>(shared_from_this()), part.getBody()->getPartList()
+ );
+ }
+}
+
+
+shared_ptr <const messageStructure> maildirMessagePart::getStructure() const {
+
+ if (m_structure) {
+ return m_structure;
+ } else {
+ return maildirMessageStructure::emptyStructure();
+ }
+}
+
+
+shared_ptr <messageStructure> maildirMessagePart::getStructure() {
+
+ if (m_structure) {
+ return m_structure;
+ } else {
+ return maildirMessageStructure::emptyStructure();
+ }
+}
+
+
+const mediaType& maildirMessagePart::getType() const {
+
+ return m_mediaType;
+}
+
+
+const contentDisposition &maildirMessagePart::getDisposition() const {
+
+ return m_dispType;
+}
+
+
+size_t maildirMessagePart::getSize() const {
+
+ return m_size;
+}
+
+
+size_t maildirMessagePart::getNumber() const {
+
+ return m_number;
+}
+
+
+shared_ptr <const header> maildirMessagePart::getHeader() const {
+
+ if (!m_header) {
+ throw exceptions::unfetched_object();
+ } else {
+ return m_header;
+ }
+}
+
+
+header& maildirMessagePart::getOrCreateHeader() {
+
+ if (m_header) {
+ return *m_header;
+ } else {
+ return *(m_header = make_shared <header>());
+ }
+}
+
+
+size_t maildirMessagePart::getHeaderParsedOffset() const {
+
+ return m_headerParsedOffset;
+}
+
+
+size_t maildirMessagePart::getHeaderParsedLength() const {
+
+ return m_headerParsedLength;
+}
+
+
+size_t maildirMessagePart::getBodyParsedOffset() const {
+
+ return m_bodyParsedOffset;
+}
+
+
+size_t maildirMessagePart::getBodyParsedLength() const {
+
+ return m_bodyParsedLength;
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
diff --git a/vmime-master/src/vmime/net/maildir/maildirMessagePart.hpp b/vmime-master/src/vmime/net/maildir/maildirMessagePart.hpp
new file mode 100644
index 0000000..5ecc739
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirMessagePart.hpp
@@ -0,0 +1,106 @@
+//
+// 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_NET_MAILDIR_MAILDIRMESSAGEPART_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRMESSAGEPART_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/message.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirMessageStructure;
+
+
+class maildirMessagePart : public messagePart
+{
+public:
+
+ maildirMessagePart(
+ const shared_ptr <maildirMessagePart>& parent,
+ const size_t number,
+ const bodyPart& part
+ );
+
+ ~maildirMessagePart();
+
+
+ shared_ptr <const messageStructure> getStructure() const;
+ shared_ptr <messageStructure> getStructure();
+
+ weak_ptr <const maildirMessagePart> getParent() const { return (m_parent); }
+
+ const mediaType& getType() const;
+ const contentDisposition &getDisposition() const;
+ size_t getSize() const;
+ size_t getNumber() const;
+
+ shared_ptr <const header> getHeader() const;
+
+ header& getOrCreateHeader();
+
+ size_t getHeaderParsedOffset() const;
+ size_t getHeaderParsedLength() const;
+
+ size_t getBodyParsedOffset() const;
+ size_t getBodyParsedLength() const;
+
+ void initStructure(const bodyPart& part);
+
+private:
+
+ shared_ptr <maildirMessageStructure> m_structure;
+ weak_ptr <maildirMessagePart> m_parent;
+ shared_ptr <header> m_header;
+
+ size_t m_number;
+ size_t m_size;
+ mediaType m_mediaType;
+ contentDisposition m_dispType;
+
+ size_t m_headerParsedOffset;
+ size_t m_headerParsedLength;
+
+ size_t m_bodyParsedOffset;
+ size_t m_bodyParsedLength;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRMESSAGEPART_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirMessageStructure.cpp b/vmime-master/src/vmime/net/maildir/maildirMessageStructure.cpp
new file mode 100644
index 0000000..1e2f2cc
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirMessageStructure.cpp
@@ -0,0 +1,104 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirMessageStructure.hpp"
+#include "vmime/net/maildir/maildirMessagePart.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+shared_ptr <maildirMessageStructure> maildirMessageStructure::m_emptyStructure = make_shared <maildirMessageStructure>();
+
+
+maildirMessageStructure::maildirMessageStructure()
+{
+}
+
+
+maildirMessageStructure::maildirMessageStructure(
+ const shared_ptr <maildirMessagePart>& parent,
+ const bodyPart& part
+) {
+
+ shared_ptr <maildirMessagePart> mpart = make_shared <maildirMessagePart>(parent, 0, part);
+ mpart->initStructure(part);
+
+ m_parts.push_back(mpart);
+}
+
+
+maildirMessageStructure::maildirMessageStructure(
+ const shared_ptr <maildirMessagePart>& parent,
+ const std::vector <shared_ptr <const vmime::bodyPart> >& list
+) {
+
+ for (size_t i = 0 ; i < list.size() ; ++i) {
+
+ shared_ptr <maildirMessagePart> mpart = make_shared <maildirMessagePart>(parent, i, *list[i]);
+ mpart->initStructure(*list[i]);
+
+ m_parts.push_back(mpart);
+ }
+}
+
+
+shared_ptr <const messagePart> maildirMessageStructure::getPartAt(const size_t x) const {
+
+ return m_parts[x];
+}
+
+
+shared_ptr <messagePart> maildirMessageStructure::getPartAt(const size_t x) {
+
+ return m_parts[x];
+}
+
+
+size_t maildirMessageStructure::getPartCount() const {
+
+ return m_parts.size();
+}
+
+
+// static
+shared_ptr <maildirMessageStructure> maildirMessageStructure::emptyStructure() {
+
+ return m_emptyStructure;
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
diff --git a/vmime-master/src/vmime/net/maildir/maildirMessageStructure.hpp b/vmime-master/src/vmime/net/maildir/maildirMessageStructure.hpp
new file mode 100644
index 0000000..1a20ea4
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirMessageStructure.hpp
@@ -0,0 +1,82 @@
+//
+// 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_NET_MAILDIR_MAILDIRMESSAGESTRUCTURE_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRMESSAGESTRUCTURE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/message.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirMessagePart;
+
+
+class maildirMessageStructure : public messageStructure {
+
+public:
+
+ maildirMessageStructure();
+ maildirMessageStructure(
+ const shared_ptr <maildirMessagePart>& parent,
+ const bodyPart& part
+ );
+ maildirMessageStructure(
+ const shared_ptr <maildirMessagePart>& parent,
+ const std::vector <shared_ptr <const vmime::bodyPart> >& list
+ );
+
+
+ shared_ptr <const messagePart> getPartAt(const size_t x) const;
+ shared_ptr <messagePart> getPartAt(const size_t x);
+
+ size_t getPartCount() const;
+
+ static shared_ptr <maildirMessageStructure> emptyStructure();
+
+private:
+
+ static shared_ptr <maildirMessageStructure> m_emptyStructure;
+
+ std::vector <shared_ptr <maildirMessagePart> > m_parts;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRMESSAGESTRUCTURE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirServiceInfos.cpp b/vmime-master/src/vmime/net/maildir/maildirServiceInfos.cpp
new file mode 100644
index 0000000..f9d92d3
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirServiceInfos.cpp
@@ -0,0 +1,76 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirServiceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+maildirServiceInfos::maildirServiceInfos() {
+
+}
+
+
+const string maildirServiceInfos::getPropertyPrefix() const {
+
+ return "store.maildir.";
+}
+
+
+const maildirServiceInfos::props& maildirServiceInfos::getProperties() const {
+
+ static props maildirProps = {
+ property(serviceInfos::property::SERVER_ROOTPATH, serviceInfos::property::FLAG_REQUIRED)
+ };
+
+ return maildirProps;
+}
+
+
+const std::vector <serviceInfos::property> maildirServiceInfos::getAvailableProperties() const {
+
+ std::vector <property> list;
+ const props& p = getProperties();
+
+ list.push_back(p.PROPERTY_SERVER_ROOTPATH);
+
+ return list;
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirServiceInfos.hpp b/vmime-master/src/vmime/net/maildir/maildirServiceInfos.hpp
new file mode 100644
index 0000000..827a7d7
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirServiceInfos.hpp
@@ -0,0 +1,69 @@
+//
+// 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_NET_MAILDIR_MAILDIRSERVICEINFOS_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRSERVICEINFOS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/serviceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+/** Information about maildir service.
+ */
+class VMIME_EXPORT maildirServiceInfos : public serviceInfos {
+
+public:
+
+ maildirServiceInfos();
+
+ struct props {
+ serviceInfos::property PROPERTY_SERVER_ROOTPATH;
+ };
+
+ const props& getProperties() const;
+
+ const string getPropertyPrefix() const;
+ const std::vector <serviceInfos::property> getAvailableProperties() const;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRSERVICEINFOS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirStore.cpp b/vmime-master/src/vmime/net/maildir/maildirStore.cpp
new file mode 100644
index 0000000..a994f45
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirStore.cpp
@@ -0,0 +1,294 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirStore.hpp"
+
+#include "vmime/net/maildir/maildirFolder.hpp"
+#include "vmime/net/maildir/maildirFormat.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/platform.hpp"
+
+#include "vmime/net/defaultConnectionInfos.hpp"
+
+
+// Helpers for service properties
+#define GET_PROPERTY(type, prop) \
+ (getInfos().getPropertyValue <type>(getSession(), \
+ dynamic_cast <const maildirServiceInfos&>(getInfos()).getProperties().prop))
+#define HAS_PROPERTY(prop) \
+ (getInfos().hasProperty(getSession(), \
+ dynamic_cast <const maildirServiceInfos&>(getInfos()).getProperties().prop))
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+maildirStore::maildirStore(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+)
+ : store(sess, getInfosInstance(), auth),
+ m_connected(false) {
+
+}
+
+
+maildirStore::~maildirStore() {
+
+ try {
+
+ if (isConnected()) {
+ disconnect();
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+const string maildirStore::getProtocolName() const {
+
+ return "maildir";
+}
+
+
+shared_ptr <folder> maildirStore::getRootFolder() {
+
+ if (!isConnected()) {
+ throw exceptions::illegal_state("Not connected");
+ }
+
+ return shared_ptr <maildirFolder>(
+ new maildirFolder(
+ folder::path(),
+ dynamicCast <maildirStore>(shared_from_this())
+ )
+ );
+}
+
+
+shared_ptr <folder> maildirStore::getDefaultFolder() {
+
+ if (!isConnected()) {
+ throw exceptions::illegal_state("Not connected");
+ }
+
+ return shared_ptr <maildirFolder>(
+ new maildirFolder(
+ folder::path::component("inbox"),
+ dynamicCast <maildirStore>(shared_from_this())
+ )
+ );
+}
+
+
+shared_ptr <folder> maildirStore::getFolder(const folder::path& path) {
+
+ if (!isConnected()) {
+ throw exceptions::illegal_state("Not connected");
+ }
+
+ return shared_ptr <maildirFolder>(
+ new maildirFolder(
+ path,
+ dynamicCast <maildirStore>(shared_from_this())
+ )
+ );
+}
+
+
+bool maildirStore::isValidFolderName(const folder::path::component& name) const {
+
+ if (!platform::getHandler()->getFileSystemFactory()->isValidPathComponent(name)) {
+ return false;
+ }
+
+ const string& buf = name.getBuffer();
+
+ // Name cannot start/end with spaces
+ if (utility::stringUtils::trim(buf) != buf) {
+ return false;
+ }
+
+ // Name cannot start with '.'
+ const size_t length = buf.length();
+ size_t pos = 0;
+
+ while ((pos < length) && (buf[pos] == '.')) {
+ ++pos;
+ }
+
+ return (pos == 0);
+}
+
+
+void maildirStore::connect() {
+
+ if (isConnected()) {
+ throw exceptions::already_connected();
+ }
+
+ // Get root directory
+ shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
+
+ m_fsPath = fsf->stringToPath(GET_PROPERTY(string, PROPERTY_SERVER_ROOTPATH));
+
+ shared_ptr <utility::file> rootDir = fsf->create(m_fsPath);
+
+ // Try to create the root directory if it does not exist
+ if (!(rootDir->exists() && rootDir->isDirectory())) {
+
+ try {
+ rootDir->createDirectory();
+ } catch (exceptions::filesystem_exception& e) {
+ throw exceptions::connection_error("Cannot create root directory.", e);
+ }
+ }
+
+ m_format = maildirFormat::detect(dynamicCast <maildirStore>(shared_from_this()));
+
+ m_connected = true;
+}
+
+
+bool maildirStore::isConnected() const {
+
+ return m_connected;
+}
+
+
+bool maildirStore::isSecuredConnection() const {
+
+ return false;
+}
+
+
+shared_ptr <connectionInfos> maildirStore::getConnectionInfos() const {
+
+ return make_shared <defaultConnectionInfos>("localhost", static_cast <port_t>(0));
+}
+
+
+void maildirStore::disconnect() {
+
+ for (std::list <maildirFolder*>::iterator it = m_folders.begin() ;
+ it != m_folders.end() ; ++it) {
+
+ (*it)->onStoreDisconnected();
+ }
+
+ m_folders.clear();
+
+ m_connected = false;
+}
+
+
+void maildirStore::noop() {
+
+ // Nothing to do.
+}
+
+
+shared_ptr <maildirFormat> maildirStore::getFormat() {
+
+ return m_format;
+}
+
+
+shared_ptr <const maildirFormat> maildirStore::getFormat() const {
+
+ return m_format;
+}
+
+
+void maildirStore::registerFolder(maildirFolder* folder) {
+
+ m_folders.push_back(folder);
+}
+
+
+void maildirStore::unregisterFolder(maildirFolder* folder) {
+
+ std::list <maildirFolder*>::iterator it = std::find(m_folders.begin(), m_folders.end(), folder);
+
+ if (it != m_folders.end()) {
+ m_folders.erase(it);
+ }
+}
+
+
+const utility::path& maildirStore::getFileSystemPath() const {
+
+ return m_fsPath;
+}
+
+
+int maildirStore::getCapabilities() const {
+
+ return CAPABILITY_CREATE_FOLDER |
+ CAPABILITY_RENAME_FOLDER |
+ CAPABILITY_ADD_MESSAGE |
+ CAPABILITY_COPY_MESSAGE |
+ CAPABILITY_DELETE_MESSAGE |
+ CAPABILITY_PARTIAL_FETCH |
+ CAPABILITY_MESSAGE_FLAGS |
+ CAPABILITY_EXTRACT_PART;
+}
+
+
+
+// Service infos
+
+maildirServiceInfos maildirStore::sm_infos;
+
+
+const serviceInfos& maildirStore::getInfosInstance() {
+
+ return sm_infos;
+}
+
+
+const serviceInfos& maildirStore::getInfos() const {
+
+ return sm_infos;
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirStore.hpp b/vmime-master/src/vmime/net/maildir/maildirStore.hpp
new file mode 100644
index 0000000..13255c0
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirStore.hpp
@@ -0,0 +1,123 @@
+//
+// 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_NET_MAILDIR_MAILDIRSTORE_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRSTORE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/store.hpp"
+#include "vmime/net/socket.hpp"
+#include "vmime/net/folder.hpp"
+
+#include "vmime/net/maildir/maildirFormat.hpp"
+#include "vmime/net/maildir/maildirServiceInfos.hpp"
+
+#include "vmime/utility/file.hpp"
+
+#include <ostream>
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirFolder;
+
+
+/** maildir store service.
+ */
+class VMIME_EXPORT maildirStore : public store {
+
+ friend class maildirFolder;
+
+public:
+
+ maildirStore(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+ );
+
+ ~maildirStore();
+
+ const string getProtocolName() const;
+
+ shared_ptr <folder> getDefaultFolder();
+ shared_ptr <folder> getRootFolder();
+ shared_ptr <folder> getFolder(const folder::path& path);
+
+ bool isValidFolderName(const folder::path::component& name) const;
+
+ static const serviceInfos& getInfosInstance();
+ const serviceInfos& getInfos() const;
+
+ void connect();
+ bool isConnected() const;
+ void disconnect();
+
+ void noop();
+
+ const utility::path& getFileSystemPath() const;
+
+ int getCapabilities() const;
+
+ bool isSecuredConnection() const;
+ shared_ptr <connectionInfos> getConnectionInfos() const;
+
+ shared_ptr <maildirFormat> getFormat();
+ shared_ptr <const maildirFormat> getFormat() const;
+
+private:
+
+ void registerFolder(maildirFolder* folder);
+ void unregisterFolder(maildirFolder* folder);
+
+
+ std::list <maildirFolder*> m_folders;
+
+ shared_ptr <maildirFormat> m_format;
+
+ bool m_connected;
+
+ utility::path m_fsPath;
+
+
+ // Service infos
+ static maildirServiceInfos sm_infos;
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRSTORE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/maildir/maildirUtils.cpp b/vmime-master/src/vmime/net/maildir/maildirUtils.cpp
new file mode 100644
index 0000000..9942e56
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirUtils.cpp
@@ -0,0 +1,288 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/net/maildir/maildirUtils.hpp"
+#include "vmime/net/maildir/maildirStore.hpp"
+
+#include "vmime/utility/random.hpp"
+#include "vmime/platform.hpp"
+
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+bool maildirUtils::isMessageFile(const utility::file& file) {
+
+ // Ignore files which name begins with '.'
+ if (file.isFile() &&
+ file.getFullPath().getLastComponent().getBuffer().length() >= 1 &&
+ file.getFullPath().getLastComponent().getBuffer()[0] != '.') {
+
+ return true;
+ }
+
+ return false;
+}
+
+
+// NOTE ABOUT ID/FLAGS SEPARATOR
+// -----------------------------
+// In the maildir specification, the character ':' is used to separate
+// the unique identifier and the message flags.
+//
+// On Windows (and particularly FAT file systems), ':' is not allowed
+// in a filename, so we use a dash ('-') instead. This is the solution
+// used by Mutt/Win32, so we also use it here.
+//
+// To be compatible between implementations, we check for both
+// characters when reading file names.
+
+
+const utility::file::path::component maildirUtils::extractId(
+ const utility::file::path::component& filename
+) {
+
+ size_t sep = filename.getBuffer().rfind(':'); // try colon
+
+ if (sep == string::npos) {
+ sep = filename.getBuffer().rfind('-'); // try dash (Windows)
+ if (sep == string::npos) return (filename);
+ }
+
+ return utility::path::component(
+ string(filename.getBuffer().begin(), filename.getBuffer().begin() + sep)
+ );
+}
+
+
+int maildirUtils::extractFlags(const utility::file::path::component& comp) {
+
+ size_t sep = comp.getBuffer().rfind(':'); // try colon
+
+ if (sep == string::npos) {
+ sep = comp.getBuffer().rfind('-'); // try dash (Windows)
+ if (sep == string::npos) return 0;
+ }
+
+ const string flagsString(comp.getBuffer().begin() + sep + 1, comp.getBuffer().end());
+ const size_t count = flagsString.length();
+
+ int flags = 0;
+
+ for (size_t i = 0 ; i < count ; ++i) {
+
+ switch (flagsString[i]) {
+ case 'R': case 'r': flags |= message::FLAG_REPLIED; break;
+ case 'S': case 's': flags |= message::FLAG_SEEN; break;
+ case 'T': case 't': flags |= message::FLAG_DELETED; break;
+ case 'F': case 'f': flags |= message::FLAG_MARKED; break;
+ case 'P': case 'p': flags |= message::FLAG_PASSED; break;
+ case 'D': case 'd': flags |= message::FLAG_DRAFT; break;
+ }
+ }
+
+ return flags;
+}
+
+
+const utility::file::path::component maildirUtils::buildFlags(const int flags) {
+
+ string str;
+ str.reserve(8);
+
+ str += "2,";
+
+ if (flags & message::FLAG_MARKED) str += "F";
+ if (flags & message::FLAG_PASSED) str += "P";
+ if (flags & message::FLAG_REPLIED) str += "R";
+ if (flags & message::FLAG_SEEN) str += "S";
+ if (flags & message::FLAG_DELETED) str += "T";
+ if (flags & message::FLAG_DRAFT) str += "D";
+
+ return utility::file::path::component(str);
+}
+
+
+const utility::file::path::component maildirUtils::buildFilename(
+ const utility::file::path::component& id,
+ const int flags
+) {
+
+ if (flags == message::FLAG_RECENT) {
+ return id;
+ } else {
+ return buildFilename(id, buildFlags(flags));
+ }
+}
+
+
+const utility::file::path::component maildirUtils::buildFilename(
+ const utility::file::path::component& id,
+ const utility::file::path::component& flags
+) {
+
+#if VMIME_PLATFORM_IS_WINDOWS
+ static const char DELIMITER[] = "-";
+#else
+ static const char DELIMITER[] = ":";
+#endif
+
+ return utility::path::component(id.getBuffer() + DELIMITER + flags.getBuffer());
+}
+
+
+const utility::file::path::component maildirUtils::generateId() {
+
+ std::ostringstream oss;
+ oss.imbue(std::locale::classic());
+
+ oss << utility::random::getTime();
+ oss << ".";
+ oss << utility::random::getProcess();
+ oss << ".";
+ oss << utility::random::getString(6);
+ oss << ".";
+ oss << platform::getHandler()->getHostName();
+
+ return utility::file::path::component(oss.str());
+}
+
+
+void maildirUtils::recursiveFSDelete(const shared_ptr <utility::file>& dir) {
+
+ shared_ptr <utility::fileIterator> files = dir->getFiles();
+
+ // First, delete files and subdirectories in this directory
+ while (files->hasMoreElements()) {
+
+ shared_ptr <utility::file> file = files->nextElement();
+
+ if (file->isDirectory()) {
+
+ maildirUtils::recursiveFSDelete(file);
+
+ } else {
+
+ try {
+ file->remove();
+ } catch (exceptions::filesystem_exception&) {
+ // Ignore
+ }
+ }
+ }
+
+ // Then, delete this (empty) directory
+ try {
+ dir->remove();
+ } catch (exceptions::filesystem_exception&) {
+ // Ignore
+ }
+}
+
+
+
+class maildirMessageSetEnumerator : public messageSetEnumerator {
+
+public:
+
+ maildirMessageSetEnumerator(const size_t msgCount)
+ : m_msgCount(msgCount) {
+
+ }
+
+ void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) {
+
+ size_t last = range.getLast();
+ if (last == size_t(-1)) last = m_msgCount;
+
+ for (size_t i = range.getFirst() ; i <= last ; ++i) {
+ list.push_back(i);
+ }
+ }
+
+ void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) {
+
+ // Not supported
+ }
+
+public:
+
+ std::vector <size_t> list;
+
+private:
+
+ size_t m_msgCount;
+};
+
+
+// static
+const std::vector <size_t> maildirUtils::messageSetToNumberList(
+ const messageSet& msgs,
+ const size_t msgCount
+) {
+
+ maildirMessageSetEnumerator en(msgCount);
+ msgs.enumerate(en);
+
+ return en.list;
+}
+
+
+
+//
+// messageIdComparator
+//
+
+maildirUtils::messageIdComparator::messageIdComparator(
+ const utility::file::path::component& comp
+)
+ : m_comp(maildirUtils::extractId(comp)) {
+
+}
+
+
+bool maildirUtils::messageIdComparator::operator()(
+ const utility::file::path::component& other
+) const {
+
+ return m_comp == maildirUtils::extractId(other);
+}
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
diff --git a/vmime-master/src/vmime/net/maildir/maildirUtils.hpp b/vmime-master/src/vmime/net/maildir/maildirUtils.hpp
new file mode 100644
index 0000000..94ab998
--- /dev/null
+++ b/vmime-master/src/vmime/net/maildir/maildirUtils.hpp
@@ -0,0 +1,160 @@
+//
+// 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_NET_MAILDIR_MAILDIRUTILS_HPP_INCLUDED
+#define VMIME_NET_MAILDIR_MAILDIRUTILS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+
+#include "vmime/utility/file.hpp"
+#include "vmime/utility/path.hpp"
+
+#include "vmime/net/messageSet.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace maildir {
+
+
+class maildirStore;
+
+
+/** Miscellaneous helpers functions for maildir messaging system.
+ */
+class VMIME_EXPORT maildirUtils {
+
+public:
+
+ /** Comparator for message filenames, based only on the
+ * unique identifier part of the filename.
+ */
+ class messageIdComparator {
+
+ public:
+
+ messageIdComparator(const utility::file::path::component& comp);
+
+ bool operator()(const utility::file::path::component& other) const;
+
+ private:
+
+ const utility::file::path::component m_comp;
+ };
+
+ /** Test whether the specified file-system object is a message.
+ *
+ * @param file reference to a file-system object
+ * @return true if the specified object is a message file,
+ * false otherwise
+ */
+ static bool isMessageFile(const utility::file& file);
+
+ /** Extract the unique identifier part of the message filename.
+ * Eg: for the filename "1071577232.28549.m03s:2,RS", it will
+ * return "1071577232.28549.m03s".
+ *
+ * @param filename filename part
+ * @return part of the filename that corresponds to the unique
+ * identifier of the message
+ */
+ static const utility::file::path::component extractId(const utility::file::path::component& filename);
+
+ /** Extract message flags from the specified message filename.
+ * Eg: for the filename "1071577232.28549.m03s:2,RS", it will
+ * return (message::FLAG_SEEN | message::FLAG_REPLIED).
+ *
+ * @param comp filename part
+ * @return message flags extracted from the specified filename
+ */
+ static int extractFlags(const utility::file::path::component& comp);
+
+ /** Return a string representing the specified message flags.
+ * Eg: for (message::FLAG_SEEN | message::FLAG_REPLIED), it will
+ * return "RS".
+ *
+ * @param flags set of flags
+ * @return message flags in a string representation
+ */
+ static const utility::file::path::component buildFlags(const int flags);
+
+ /** Build a filename with the specified id and flags.
+ *
+ * @param id id part of the filename
+ * @param flags flags part of the filename
+ * @return message filename
+ */
+ static const utility::file::path::component buildFilename(
+ const utility::file::path::component& id,
+ const utility::file::path::component& flags
+ );
+
+ /** Build a filename with the specified id and flags.
+ *
+ * @param id id part of the filename
+ * @param flags set of flags
+ * @return message filename
+ */
+ static const utility::file::path::component buildFilename(
+ const utility::file::path::component& id,
+ const int flags
+ );
+
+ /** Generate a new unique message identifier.
+ *
+ * @return unique message id
+ */
+ static const utility::file::path::component generateId();
+
+ /** Recursively delete a directory on the file system.
+ *
+ * @param dir directory to delete
+ */
+ static void recursiveFSDelete(const shared_ptr <utility::file>& dir);
+
+ /** Returns a list of message numbers given a message set.
+ *
+ * @param msgs message set
+ * @param msgCount number of messages in folder
+ * @return list of message numbers
+ */
+ static const std::vector <size_t> messageSetToNumberList(
+ const messageSet& msgs,
+ const size_t msgCount
+ );
+};
+
+
+} // maildir
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR
+
+#endif // VMIME_NET_MAILDIR_MAILDIRUTILS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/message.cpp b/vmime-master/src/vmime/net/message.cpp
new file mode 100644
index 0000000..2d6f995
--- /dev/null
+++ b/vmime-master/src/vmime/net/message.cpp
@@ -0,0 +1,155 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/message.hpp"
+
+#include <sstream>
+
+
+namespace vmime {
+namespace net {
+
+
+string messagePart::getName() const
+{
+ return {};
+}
+
+shared_ptr <const messagePart> messagePart::getPartAt(const size_t pos) const {
+
+ return getStructure()->getPartAt(pos);
+}
+
+
+shared_ptr <messagePart> messagePart::getPartAt(const size_t pos) {
+
+ return getStructure()->getPartAt(pos);
+}
+
+
+size_t messagePart::getPartCount() const {
+
+ return getStructure()->getPartCount();
+}
+
+
+
+// message::uid
+
+
+message::uid::uid() {
+
+}
+
+
+message::uid::uid(const string& uid)
+ : m_str(uid) {
+
+}
+
+
+message::uid::uid(const unsigned long uid) {
+
+ std::ostringstream oss;
+ oss.imbue(std::locale::classic());
+ oss << uid;
+
+ m_str = oss.str();
+}
+
+
+message::uid::uid(const char* uid)
+ : m_str(uid) {
+
+}
+
+
+message::uid::uid(const uid& other) {
+
+ m_str = other.m_str;
+}
+
+
+message::uid& message::uid::operator=(const uid& other) {
+
+ m_str = other.m_str;
+ return *this;
+}
+
+
+message::uid& message::uid::operator=(const string& uid) {
+
+ m_str = uid;
+ return *this;
+}
+
+
+message::uid& message::uid::operator=(const unsigned long uid) {
+
+ std::ostringstream oss;
+ oss.imbue(std::locale::classic());
+ oss << uid;
+
+ m_str = oss.str();
+
+ return *this;
+}
+
+
+message::uid::operator string() const {
+
+ return m_str;
+}
+
+
+bool message::uid::empty() const {
+
+ return m_str.empty();
+}
+
+
+bool message::uid::operator==(const uid& other) const {
+
+ return m_str == other.m_str;
+}
+
+
+std::ostream& operator<<(std::ostream& os, const message::uid& uid) {
+
+ os << static_cast <string>(uid);
+ return os;
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
diff --git a/vmime-master/src/vmime/net/message.hpp b/vmime-master/src/vmime/net/message.hpp
new file mode 100644
index 0000000..8679879
--- /dev/null
+++ b/vmime-master/src/vmime/net/message.hpp
@@ -0,0 +1,369 @@
+//
+// 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_NET_MESSAGE_HPP_INCLUDED
+#define VMIME_NET_MESSAGE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/header.hpp"
+#include "vmime/mediaType.hpp"
+#include "vmime/contentDisposition.hpp"
+
+#include "vmime/utility/progressListener.hpp"
+#include "vmime/utility/stream.hpp"
+
+#include "vmime/message.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+class messageStructure;
+
+
+/** A MIME part in a message.
+ */
+class VMIME_EXPORT messagePart : public object, public enable_shared_from_this <messagePart> {
+
+protected:
+
+ messagePart() { }
+ messagePart(const messagePart&);
+
+ virtual ~messagePart() { }
+
+public:
+
+ /** Return the structure of this part.
+ *
+ * @return structure of the part
+ */
+ virtual shared_ptr <const messageStructure> getStructure() const = 0;
+
+ /** Return the structure of this part.
+ *
+ * @return structure of the part
+ */
+ virtual shared_ptr <messageStructure> getStructure() = 0;
+
+ /** Return the header section for this part (you must fetch header
+ * before using this function: see message::fetchPartHeader).
+ *
+ * @return header section
+ */
+ virtual shared_ptr <const header> getHeader() const = 0;
+
+ /** Return the media-type of the content in this part.
+ *
+ * @return content media type
+ */
+ virtual const mediaType& getType() const = 0;
+
+ /** Return the disposition type of the content in this part.
+ *
+ * @return content disposition type
+ */
+ virtual const contentDisposition &getDisposition() const = 0;
+
+ /** Return the size of this part.
+ *
+ * @return size of the part (in bytes)
+ */
+ virtual size_t getSize() const = 0;
+
+ /** Return the part sequence number (index).
+ * The first part is at index zero.
+ *
+ * @return part number
+ */
+ virtual size_t getNumber() const = 0;
+
+ /** Return the name of this part. In particular, this corresponds to
+ * the attachment file name for attachment parts.
+ *
+ * The part name may be empty if the part does not advertise it or
+ * if the underlying protocol does not support it.
+ *
+ * @return part name
+ */
+ virtual string getName() const;
+
+ /** Return the sub-part at the specified position (zero is the
+ * first part).
+ *
+ * @param pos index of the sub-part
+ * @return sub-part at position 'pos'
+ */
+ shared_ptr <const messagePart> getPartAt(const size_t pos) const;
+
+ /** Return the sub-part at the specified position (zero is the
+ * first part).
+ *
+ * @param pos index of the sub-part
+ * @return sub-part at position 'pos'
+ */
+ shared_ptr <messagePart> getPartAt(const size_t pos);
+
+ /** Return the number of sub-parts in this part.
+ *
+ * @return number of sub-parts
+ */
+ size_t getPartCount() const;
+};
+
+
+/** Structure of a MIME part/message.
+ */
+class VMIME_EXPORT messageStructure : public object, public enable_shared_from_this <messageStructure> {
+
+protected:
+
+ messageStructure() { }
+ messageStructure(const messageStructure&);
+
+public:
+
+ virtual ~messageStructure() { }
+
+ /** Return the part at the specified position (first
+ * part is at position 0).
+ *
+ * @param pos position
+ * @return part at position 'pos'
+ */
+ virtual shared_ptr <const messagePart> getPartAt(const size_t pos) const = 0;
+
+ /** Return the part at the specified position (first
+ * part is at position 0).
+ *
+ * @param pos position
+ * @return part at position 'pos'
+ */
+ virtual shared_ptr <messagePart> getPartAt(const size_t pos) = 0;
+
+ /** Return the number of parts in this part.
+ *
+ * @return number of parts
+ */
+ virtual size_t getPartCount() const = 0;
+};
+
+
+/** Abstract representation of a message in a store/transport service.
+ */
+class VMIME_EXPORT message : public object, public enable_shared_from_this <message> {
+
+protected:
+
+ message() { }
+ message(const message&);
+
+ enum PrivateConstants {
+ FLAG_UNDEFINED = 9999 /**< Used internally to indicate flags have not
+ been initialized yet. */
+ };
+
+public:
+
+ /** The type for an unique message identifier.
+ */
+ class VMIME_EXPORT uid {
+
+ public:
+
+ uid();
+ uid(const string& uid);
+ uid(const unsigned long uid);
+ uid(const char* uid);
+ uid(const uid& other);
+
+ uid& operator=(const uid& other);
+ uid& operator=(const string& uid);
+ uid& operator=(const unsigned long uid);
+
+ operator string() const;
+
+ bool empty() const;
+
+ bool operator==(const uid& other) const;
+
+ private:
+
+ string m_str;
+ };
+
+ /** Return the MIME structure of the message (must fetch before).
+ *
+ * @return MIME structure of the message
+ */
+ virtual shared_ptr <const messageStructure> getStructure() const = 0;
+
+ /** Return the MIME structure of the message (must fetch before).
+ *
+ * @return MIME structure of the message
+ */
+ virtual shared_ptr <messageStructure> getStructure() = 0;
+
+ /** Return a reference to the header fields of the message (must fetch before).
+ *
+ * @return header section of the message
+ */
+ virtual shared_ptr <const header> getHeader() const = 0;
+
+ /** Return the sequence number of this message. This number is
+ * used to reference the message in the folder.
+ *
+ * @return sequence number of the message
+ */
+ virtual size_t getNumber() const = 0;
+
+ /** Return the unique identifier (UID) of this message in its
+ * folder (must fetch before).
+ *
+ * @return UID of the message
+ */
+ virtual const uid getUID() const = 0;
+
+ /** Return the size of the message (must fetch before).
+ *
+ * @return size of the message (in bytes)
+ */
+ virtual size_t getSize() const = 0;
+
+ /** Check whether this message has been expunged (ie: definitively
+ * deleted) and does not exist in the folder anymore.
+ *
+ * @return true if the message is expunged, false otherwise
+ */
+ virtual bool isExpunged() const = 0;
+
+ /** Possible flags for a message.
+ */
+ enum Flags {
+ FLAG_SEEN = (1 << 0), /**< Message has been seen. */
+ FLAG_RECENT = (1 << 1), /**< Message has been recently received. */
+ FLAG_DELETED = (1 << 2), /**< Message is marked for deletion. */
+ FLAG_REPLIED = (1 << 3), /**< User replied to this message. */
+ FLAG_MARKED = (1 << 4), /**< Used-defined flag. */
+ FLAG_PASSED = (1 << 5), /**< Message has been resent/forwarded/bounced. */
+ FLAG_DRAFT = (1 << 6) /**< Message is marked as a 'draft'. */
+ };
+
+ /** Methods for setting the flags.
+ */
+ enum FlagsModes {
+ FLAG_MODE_SET, /**< Set (replace) the flags. */
+ FLAG_MODE_ADD, /**< Add the flags. */
+ FLAG_MODE_REMOVE /**< Remove the flags. */
+ };
+
+ /** Return the flags of this message.
+ *
+ * @return flags of the message
+ */
+ virtual int getFlags() const = 0;
+
+ /** Set the flags of this message.
+ *
+ * @param flags set of flags (see Flags)
+ * @param mode indicate how to treat old and new flags (see FlagsModes)
+ */
+ virtual void setFlags(const int flags, const int mode = FLAG_MODE_SET) = 0;
+
+ /** Extract the whole message data (header + contents).
+ *
+ * \warning Partial fetch might not be supported by the underlying protocol.
+ *
+ * @param os output stream in which to write message data
+ * @param progress progress listener, or NULL if not used
+ * @param start index of the first byte to retrieve (used for partial fetch)
+ * @param length number of bytes to retrieve (used for partial fetch)
+ * @param peek if true, try not to mark the message as read. This may not
+ * be supported by the protocol (IMAP supports this), but it will NOT throw
+ * an exception if not supported.
+ */
+ virtual void extract(
+ utility::outputStream& os,
+ utility::progressListener* progress = NULL,
+ const size_t start = 0,
+ const size_t length = -1,
+ const bool peek = false
+ ) const = 0;
+
+ /** Extract the specified MIME part of the message (header + contents).
+ *
+ * \warning Partial fetch might not be supported by the underlying protocol.
+ *
+ * @param p part to extract
+ * @param os output stream in which to write part data
+ * @param progress progress listener, or NULL if not used
+ * @param start index of the first byte to retrieve (used for partial fetch)
+ * @param length number of bytes to retrieve (used for partial fetch)
+ * @param peek if true, try not to mark the message as read. This may not
+ * be supported by the protocol (IMAP supports this), but it will NOT throw
+ * an exception if not supported.
+ */
+ virtual void extractPart(
+ const shared_ptr <const messagePart>& p,
+ utility::outputStream& os,
+ utility::progressListener* progress = NULL,
+ const size_t start = 0,
+ const size_t length = -1,
+ const bool peek = false
+ ) const = 0;
+
+ /** Fetch the MIME header for the specified part.
+ *
+ * @param p the part for which to fetch the header
+ */
+ virtual void fetchPartHeader(const shared_ptr <messagePart>& p) = 0;
+
+ /** Get the RFC-822 message for this abstract message.
+ * Warning: This may require getting some data (ie: structure and headers) from
+ * the server, which is done automatically. Actual message contents (ie: body)
+ * will not be fetched if possible (IMAP allows it, whereas POP3 will require
+ * to fetch the whole message).
+ *
+ * @return a RFC-822-parsed message
+ */
+ virtual shared_ptr <vmime::message> getParsedMessage() = 0;
+};
+
+
+VMIME_EXPORT std::ostream& operator<<(std::ostream& os, const message::uid& uid);
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_MESSAGE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/messageSet.cpp b/vmime-master/src/vmime/net/messageSet.cpp
new file mode 100644
index 0000000..fe2d645
--- /dev/null
+++ b/vmime-master/src/vmime/net/messageSet.cpp
@@ -0,0 +1,430 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/messageSet.hpp"
+
+#include <iterator>
+#include <algorithm>
+#include <typeinfo>
+
+
+namespace vmime {
+namespace net {
+
+// messageSetEnumerator
+
+messageSetEnumerator::~messageSetEnumerator()
+{
+}
+
+// messageRange
+
+messageRange::messageRange() {
+
+}
+
+
+messageRange::~messageRange() {
+
+}
+
+
+// numberMessageRange
+
+numberMessageRange::numberMessageRange(const size_t number)
+ : m_first(number),
+ m_last(number) {
+
+ if (number < 1) {
+ throw std::invalid_argument("number");
+ }
+}
+
+
+numberMessageRange::numberMessageRange(const size_t first, const size_t last)
+ : m_first(first),
+ m_last(last) {
+
+ if (first < 1 || first == static_cast <size_t>(-1)) {
+ throw std::invalid_argument("first");
+ } else if (last != static_cast <size_t>(-1) && last < first) {
+ throw std::invalid_argument("last");
+ }
+}
+
+
+numberMessageRange::numberMessageRange(const numberMessageRange& other)
+ : messageRange(),
+ m_first(other.m_first),
+ m_last(other.m_last) {
+
+}
+
+
+size_t numberMessageRange::getFirst() const {
+
+ return m_first;
+}
+
+
+size_t numberMessageRange::getLast() const {
+
+ return m_last;
+}
+
+
+void numberMessageRange::enumerate(messageSetEnumerator& en) const {
+
+ en.enumerateNumberMessageRange(*this);
+}
+
+
+messageRange* numberMessageRange::clone() const {
+
+ return new numberMessageRange(*this);
+}
+
+
+// UIDMessageRange
+
+UIDMessageRange::UIDMessageRange(const message::uid& uid)
+ : m_first(uid),
+ m_last(uid) {
+
+}
+
+
+UIDMessageRange::UIDMessageRange(const message::uid& first, const message::uid& last)
+ : m_first(first),
+ m_last(last) {
+
+}
+
+
+UIDMessageRange::UIDMessageRange(const UIDMessageRange& other)
+ : messageRange(),
+ m_first(other.m_first),
+ m_last(other.m_last) {
+
+}
+
+
+const message::uid UIDMessageRange::getFirst() const {
+
+ return m_first;
+}
+
+
+const message::uid UIDMessageRange::getLast() const {
+
+ return m_last;
+}
+
+
+void UIDMessageRange::enumerate(messageSetEnumerator& en) const {
+
+ en.enumerateUIDMessageRange(*this);
+}
+
+
+messageRange* UIDMessageRange::clone() const {
+
+ return new UIDMessageRange(*this);
+}
+
+
+// messageSet
+
+
+messageSet::messageSet() {
+
+}
+
+
+messageSet::messageSet(const messageSet& other)
+ : object() {
+
+ m_ranges.resize(other.m_ranges.size());
+
+ for (size_t i = 0, n = other.m_ranges.size() ; i < n ; ++i) {
+ m_ranges[i] = other.m_ranges[i]->clone();
+ }
+}
+
+
+messageSet::~messageSet() {
+
+ for (size_t i = 0, n = m_ranges.size() ; i < n ; ++i) {
+ delete m_ranges[i];
+ }
+}
+
+
+// static
+messageSet messageSet::empty() {
+
+ return messageSet();
+}
+
+
+// static
+messageSet messageSet::byNumber(const size_t number) {
+
+ messageSet set;
+ set.m_ranges.push_back(new numberMessageRange(number));
+
+ return set;
+}
+
+
+// static
+messageSet messageSet::byNumber(const size_t first, const size_t last) {
+
+ messageSet set;
+ set.m_ranges.push_back(new numberMessageRange(first, last));
+
+ return set;
+}
+
+
+// static
+messageSet messageSet::byNumber(const std::vector <size_t>& numbers) {
+
+ // Sort a copy of the list
+ std::vector <size_t> sortedNumbers;
+
+ sortedNumbers.resize(numbers.size());
+
+ std::copy(numbers.begin(), numbers.end(), sortedNumbers.begin());
+ std::sort(sortedNumbers.begin(), sortedNumbers.end());
+
+ // Build the set by detecting ranges of continuous numbers
+ size_t previous = static_cast <size_t>(-1), rangeStart = static_cast <size_t>(-1);
+ messageSet set;
+
+ for (std::vector <size_t>::const_iterator it = sortedNumbers.begin() ;
+ it != sortedNumbers.end() ; ++it) {
+
+ const size_t current = *it;
+
+ if (current == previous) {
+ continue; // skip duplicates
+ }
+
+ if (current == static_cast <size_t>(-1)) {
+ throw std::invalid_argument("numbers");
+ }
+
+ if (previous == static_cast <size_t>(-1)) {
+
+ previous = current;
+ rangeStart = current;
+
+ } else {
+
+ if (current == previous + 1) {
+
+ previous = current;
+
+ } else {
+
+ set.m_ranges.push_back(new numberMessageRange(rangeStart, previous));
+
+ previous = current;
+ rangeStart = current;
+ }
+ }
+ }
+
+ set.m_ranges.push_back(new numberMessageRange(rangeStart, previous));
+
+ return set;
+}
+
+
+// static
+messageSet messageSet::byUID(const message::uid& uid) {
+
+ messageSet set;
+ set.m_ranges.push_back(new UIDMessageRange(uid));
+
+ return set;
+}
+
+
+messageSet messageSet::byUID(const message::uid& first, const message::uid& last) {
+
+ messageSet set;
+ set.m_ranges.push_back(new UIDMessageRange(first, last));
+
+ return set;
+}
+
+
+messageSet messageSet::byUID(const std::vector <message::uid>& uids) {
+
+ std::vector <vmime_uint32> numericUIDs;
+
+ for (size_t i = 0, n = uids.size() ; i < n ; ++i) {
+
+ const string uid = uids[i];
+ int numericUID = 0;
+
+ const char* p = uid.c_str();
+
+ for ( ; *p >= '0' && *p <= '9' ; ++p) {
+ numericUID = (numericUID * 10) + (*p - '0');
+ }
+
+ if (*p != '\0') {
+
+ messageSet set;
+
+ // Non-numeric UID, fall back to plain UID list (single-UID ranges)
+ for (size_t i = 0, n = uids.size() ; i < n ; ++i) {
+ set.m_ranges.push_back(new UIDMessageRange(uids[i]));
+ }
+
+ return set;
+ }
+
+ numericUIDs.push_back(numericUID);
+ }
+
+ // Sort a copy of the list
+ std::vector <vmime_uint32> sortedUIDs;
+
+ sortedUIDs.resize(numericUIDs.size());
+
+ std::copy(numericUIDs.begin(), numericUIDs.end(), sortedUIDs.begin());
+ std::sort(sortedUIDs.begin(), sortedUIDs.end());
+
+ // Build the set by detecting ranges of continuous numbers
+ vmime_uint32 previous = static_cast <vmime_uint32>(-1), rangeStart = static_cast <vmime_uint32>(-1);
+ messageSet set;
+
+ for (std::vector <vmime_uint32>::const_iterator it = sortedUIDs.begin() ;
+ it != sortedUIDs.end() ; ++it) {
+
+ const vmime_uint32 current = *it;
+
+ if (current == previous) {
+ continue; // skip duplicates
+ }
+
+ if (previous == static_cast <vmime_uint32>(-1)) {
+
+ previous = current;
+ rangeStart = current;
+
+ } else {
+
+ if (current == previous + 1) {
+
+ previous = current;
+
+ } else {
+
+ set.m_ranges.push_back(
+ new UIDMessageRange(
+ utility::stringUtils::toString(rangeStart),
+ utility::stringUtils::toString(previous)
+ )
+ );
+
+ previous = current;
+ rangeStart = current;
+ }
+ }
+ }
+
+ set.m_ranges.push_back(
+ new UIDMessageRange(
+ utility::stringUtils::toString(rangeStart),
+ utility::stringUtils::toString(previous)
+ )
+ );
+
+ return set;
+}
+
+
+void messageSet::addRange(const messageRange& range) {
+
+ if (!m_ranges.empty() && typeid(*m_ranges[0]) != typeid(range)) {
+ throw std::invalid_argument("range");
+ }
+
+ m_ranges.push_back(range.clone());
+}
+
+
+void messageSet::enumerate(messageSetEnumerator& en) const {
+
+ for (size_t i = 0, n = m_ranges.size() ; i < n ; ++i) {
+ m_ranges[i]->enumerate(en);
+ }
+}
+
+
+bool messageSet::isEmpty() const {
+
+ return m_ranges.empty();
+}
+
+
+bool messageSet::isNumberSet() const {
+
+ return !isEmpty() && dynamic_cast <numberMessageRange*>(m_ranges[0]) != NULL;
+}
+
+
+bool messageSet::isUIDSet() const {
+
+ return !isEmpty() && dynamic_cast <UIDMessageRange*>(m_ranges[0]) != NULL;
+}
+
+
+size_t messageSet::getRangeCount() const {
+
+ return m_ranges.size();
+}
+
+
+const messageRange& messageSet::getRangeAt(const size_t i) const {
+
+ return *m_ranges[i];
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
diff --git a/vmime-master/src/vmime/net/messageSet.hpp b/vmime-master/src/vmime/net/messageSet.hpp
new file mode 100644
index 0000000..848c4c9
--- /dev/null
+++ b/vmime-master/src/vmime/net/messageSet.hpp
@@ -0,0 +1,358 @@
+//
+// 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_NET_MESSAGESET_HPP_INCLUDED
+#define VMIME_NET_MESSAGESET_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/message.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+// Forward references
+class numberMessageRange;
+class UIDMessageRange;
+
+
+/** Enumerator used to retrieve the message number/UID ranges contained
+ * in a messageSet object.
+ */
+class VMIME_EXPORT messageSetEnumerator {
+
+public:
+ virtual ~messageSetEnumerator();
+ virtual void enumerateNumberMessageRange(const numberMessageRange& range) = 0;
+ virtual void enumerateUIDMessageRange(const UIDMessageRange& range) = 0;
+};
+
+
+/** A range of (continuous) messages, designated either by their
+ * sequence number, or by their UID.
+ */
+class VMIME_EXPORT messageRange : public object {
+
+public:
+
+ virtual ~messageRange();
+
+ /** Enumerates this range with the specified enumerator.
+ *
+ * @param en enumerator that will receive the method calls while
+ * enumerating this range
+ */
+ virtual void enumerate(messageSetEnumerator& en) const = 0;
+
+ /** Clones this message range.
+ */
+ virtual messageRange* clone() const = 0;
+
+protected:
+
+ messageRange();
+ messageRange(const messageRange&);
+};
+
+
+/** A range of (continuous) messages designated by their sequence number.
+ */
+class VMIME_EXPORT numberMessageRange : public messageRange {
+
+public:
+
+ /** Constructs a message range containing a single message.
+ *
+ * @param number message number (numbering starts at 1, not 0)
+ */
+ numberMessageRange(const size_t number);
+
+ /** Constructs a message range for multiple messages.
+ *
+ * @param first number of the first message in the range (numbering
+ * starts at 1, not 0)
+ * @param last number of the last message in the range, or use the
+ * special value -1 to designate the last message in the folder
+ */
+ numberMessageRange(const size_t first, const size_t last);
+
+ /** Constructs a message range by copying from another range.
+ *
+ * @param other range to copy
+ */
+ numberMessageRange(const numberMessageRange& other);
+
+ /** Returns the number of the first message in the range.
+ *
+ * @return number of the first message
+ */
+ size_t getFirst() const;
+
+ /** Returns the number of the last message in the range, or -1
+ * to designate the last message in the folder
+ *
+ * @return number of the last message
+ */
+ size_t getLast() const;
+
+ void enumerate(messageSetEnumerator& en) const;
+
+ messageRange* clone() const;
+
+private:
+
+ size_t m_first, m_last;
+};
+
+
+/** A range of (continuous) messages represented by their UID.
+ */
+class VMIME_EXPORT UIDMessageRange : public messageRange {
+
+public:
+
+ /** Constructs a message range containing a single message.
+ *
+ * @param uid message UID
+ */
+ UIDMessageRange(const message::uid& uid);
+
+ /** Constructs a message range for multiple messages.
+ *
+ * @param first UID of the first message in the range
+ * @param last UID of the last message in the range, or use the
+ * special value '*' to designate the last message in the folder
+ */
+ UIDMessageRange(const message::uid& first, const message::uid& last);
+
+ /** Constructs a message range by copying from another range.
+ *
+ * @param other range to copy
+ */
+ UIDMessageRange(const UIDMessageRange& other);
+
+ /** Returns the UID of the first message in the range.
+ *
+ * @return UID of the first message
+ */
+ const message::uid getFirst() const;
+
+ /** Returns the UID of the last message in the range, or '*'
+ * to designate the last message in the folder
+ *
+ * @return UID of the last message
+ */
+ const message::uid getLast() const;
+
+ void enumerate(messageSetEnumerator& en) const;
+
+ messageRange* clone() const;
+
+private:
+
+ message::uid m_first, m_last;
+};
+
+
+/** Represents a set of messages, designated either by their sequence
+ * number, or by their UID (but not both).
+ *
+ * Following is example code to designate messages by their number:
+ * \code{.cpp}
+ * // Designate a single message with sequence number 42
+ * vmime::net::messageSet::byNumber(42)
+ *
+ * // Designate messages from sequence number 5 to sequence number 8 (including)
+ * vmime::net::messageSet::byNumber(5, 8)
+ *
+ * // Designate all messages in the folder, starting from number 42
+ * vmime::net::messageSet::byNumber(42, -1)
+ * \endcode
+ * Or, to designate messages by their UID, use:
+ * \code{.cpp}
+ * // Designate a single message with UID 1042
+ * vmime::net::messageSet::byUID(1042)
+ *
+ * // Designate messages from UID 1000 to UID 1042 (including)
+ * vmime::net::messageSet::byUID(1000, 1042)
+ *
+ * // Designate all messages in the folder, starting from UID 1000
+ * vmime::net::messageSet::byUID(1000, "*")
+ * \endcode
+ */
+class VMIME_EXPORT messageSet : public object {
+
+public:
+
+ ~messageSet();
+
+ messageSet(const messageSet& other);
+
+ /** Constructs an empty set.
+ *
+ * @return new empty message set
+ */
+ static messageSet empty();
+
+ /** Constructs a new message set and initializes it with a single
+ * message represented by its sequence number.
+ *
+ * @param number message number (numbering starts at 1, not 0)
+ * @return new message set
+ */
+ static messageSet byNumber(const size_t number);
+
+ /** Constructs a new message set and initializes it with a range
+ * of messages represented by their sequence number.
+ *
+ * @param first number of the first message in the range (numbering
+ * starts at 1, not 0)
+ * @param last number of the last message in the range, or use the
+ * special value -1 to designate the last message in the folder
+ * @return new message set
+ */
+ static messageSet byNumber(const size_t first, const size_t last);
+
+ /** Constructs a new message set and initializes it with a possibly
+ * unsorted list of messages represented by their sequence number.
+ * Please note that numbering starts at 1, not 0.
+ *
+ * The function tries to group consecutive message numbers into
+ * ranges to reduce the size of the resulting set.
+ *
+ * For example, given the list "1,2,3,4,5,7,8,13,15,16,17" it will
+ * result in the following ranges: "1:5,7:8,13,15:17".
+ *
+ * @param numbers a vector containing numbers of the messages
+ * @return new message set
+ */
+ static messageSet byNumber(const std::vector <size_t>& numbers);
+
+ /** Constructs a new message set and initializes it with a single
+ * message represented by its UID.
+ *
+ * @param uid message UID
+ * @return new message set
+ */
+ static messageSet byUID(const message::uid& uid);
+
+ /** Constructs a new message set and initializes it with a range
+ * of messages represented by their sequence number.
+ *
+ * @param first UID of the first message in the range
+ * @param last UID of the last message in the range, or use the
+ * special value '*' to designate the last message in the folder
+ * @return new message set
+ */
+ static messageSet byUID(const message::uid& first, const message::uid& last);
+
+ /** Constructs a new message set and initializes it with a possibly
+ * unsorted list of messages represented by their UID.
+ *
+ * For UIDs that actually are numbers (this is the case for IMAP), the
+ * function tries to group consecutive UIDs into ranges to reduce the
+ * size of the resulting set.
+ *
+ * For example, given the list "1,2,3,4,5,7,8,13,15,16,17" it will
+ * result in the following ranges: "1:5,7:8,13,15:17".
+ *
+ * @param uids a vector containing UIDs of the messages
+ * @return new message set
+ */
+ static messageSet byUID(const std::vector <message::uid>& uids);
+
+ /** Adds the specified range to this set. The type of message range
+ * (either number or UID) must match the type of the ranges already
+ * contained in this set (ie. it's not possible to have a message
+ * set which contains both number ranges and UID ranges).
+ *
+ * @param range range to add
+ * @throw std::invalid_argument exception if the range type does
+ * not match the type of the ranges in this set
+ */
+ void addRange(const messageRange& range);
+
+ /** Enumerates this set with the specified enumerator.
+ *
+ * @param en enumerator that will receive the method calls while
+ * enumerating the ranges in this set
+ */
+ void enumerate(messageSetEnumerator& en) const;
+
+ /** Returns whether this set is empty (contains no range).
+ *
+ * @return true if this set is empty, or false otherwise
+ */
+ bool isEmpty() const;
+
+ /** Returns whether this set references messages by their sequence
+ * number.
+ *
+ * @return true if this set references messages by their sequence
+ * number, or false otherwise
+ */
+ bool isNumberSet() const;
+
+ /** Returns whether this set references messages by their UID.
+ *
+ * @return true if this set references messages by their UID,
+ * or false otherwise
+ */
+ bool isUIDSet() const;
+
+ /** Returns the number of ranges contained in this set.
+ *
+ * @return range count
+ */
+ size_t getRangeCount() const;
+
+ /** Returns the message range at the specified index.
+ *
+ * @param i range index (from 0 to getRangeCount())
+ * @return a reference to the message range at the specified index
+ */
+ const messageRange& getRangeAt(const size_t i) const;
+
+private:
+
+ messageSet();
+
+ std::vector <messageRange*> m_ranges;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+
+#endif // VMIME_NET_MESSAGESET_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/pop3/POP3Command.cpp b/vmime-master/src/vmime/net/pop3/POP3Command.cpp
new file mode 100644
index 0000000..0e79888
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Command.cpp
@@ -0,0 +1,267 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/pop3/POP3Command.hpp"
+#include "vmime/net/pop3/POP3Connection.hpp"
+#include "vmime/net/pop3/POP3Store.hpp"
+
+#include "vmime/net/socket.hpp"
+
+#include "vmime/mailbox.hpp"
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+POP3Command::POP3Command(const string& text, const string& traceText)
+ : m_text(text),
+ m_traceText(traceText) {
+
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::CAPA() {
+
+ return createCommand("CAPA");
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::NOOP() {
+
+ return createCommand("NOOP");
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::AUTH(const string& mechName) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "AUTH " << mechName;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::AUTH(const string& mechName, const string& initialResponse) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "AUTH " << mechName << " " << initialResponse;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::STLS() {
+
+ return createCommand("STLS");
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::APOP(const string& username, const string& digest) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "APOP " << username << " " << digest;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::USER(const string& username) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "USER " << username;
+
+ std::ostringstream trace;
+ trace.imbue(std::locale::classic());
+ trace << "USER {username}";
+
+ return createCommand(cmd.str(), trace.str());
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::PASS(const string& password) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "PASS " << password;
+
+ std::ostringstream trace;
+ trace.imbue(std::locale::classic());
+ trace << "PASS {password}";
+
+ return createCommand(cmd.str(), trace.str());
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::STAT() {
+
+ return createCommand("STAT");
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::LIST() {
+
+ return createCommand("LIST");
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::LIST(const unsigned long msg) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "LIST " << msg;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::UIDL() {
+
+ return createCommand("UIDL");
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::UIDL(const unsigned long msg) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "UIDL " << msg;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::DELE(const unsigned long msg) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "DELE " << msg;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::RETR(const unsigned long msg) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "RETR " << msg;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::TOP(const unsigned long msg, const unsigned long lines) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "TOP " << msg << " " << lines;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::RSET() {
+
+ return createCommand("RSET");
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::QUIT() {
+
+ return createCommand("QUIT");
+}
+
+
+// static
+shared_ptr <POP3Command> POP3Command::createCommand(
+ const string& text,
+ const string& traceText
+) {
+
+ if (traceText.empty()) {
+ return shared_ptr <POP3Command>(new POP3Command(text, text));
+ } else {
+ return shared_ptr <POP3Command>(new POP3Command(text, traceText));
+ }
+}
+
+
+const string POP3Command::getText() const {
+
+ return m_text;
+}
+
+
+const string POP3Command::getTraceText() const {
+
+ return m_traceText;
+}
+
+
+void POP3Command::send(const shared_ptr <POP3Connection>& conn) {
+
+ conn->getSocket()->send(m_text + "\r\n");
+
+ if (conn->getTracer()) {
+ conn->getTracer()->traceSend(m_traceText);
+ }
+}
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
diff --git a/vmime-master/src/vmime/net/pop3/POP3Command.hpp b/vmime-master/src/vmime/net/pop3/POP3Command.hpp
new file mode 100644
index 0000000..06a61b9
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Command.hpp
@@ -0,0 +1,123 @@
+//
+// 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_NET_POP3_POP3COMMAND_HPP_INCLUDED
+#define VMIME_NET_POP3_POP3COMMAND_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/object.hpp"
+#include "vmime/base.hpp"
+
+
+namespace vmime {
+
+
+class mailbox;
+
+
+namespace net {
+namespace pop3 {
+
+
+class POP3Connection;
+
+
+/** A POP3 command that will be sent to the server.
+ */
+class VMIME_EXPORT POP3Command : public object {
+
+public:
+
+ static shared_ptr <POP3Command> CAPA();
+ static shared_ptr <POP3Command> NOOP();
+ static shared_ptr <POP3Command> AUTH(const string& mechName);
+ static shared_ptr <POP3Command> AUTH(const string& mechName, const string& initialResponse);
+ static shared_ptr <POP3Command> STLS();
+ static shared_ptr <POP3Command> APOP(const string& username, const string& digest);
+ static shared_ptr <POP3Command> USER(const string& username);
+ static shared_ptr <POP3Command> PASS(const string& password);
+ static shared_ptr <POP3Command> STAT();
+ static shared_ptr <POP3Command> LIST();
+ static shared_ptr <POP3Command> LIST(const unsigned long msg);
+ static shared_ptr <POP3Command> UIDL();
+ static shared_ptr <POP3Command> UIDL(const unsigned long msg);
+ static shared_ptr <POP3Command> DELE(const unsigned long msg);
+ static shared_ptr <POP3Command> RETR(const unsigned long msg);
+ static shared_ptr <POP3Command> TOP(const unsigned long msg, const unsigned long lines);
+ static shared_ptr <POP3Command> RSET();
+ static shared_ptr <POP3Command> QUIT();
+
+ /** Creates a new POP3 command with the specified text.
+ *
+ * @param text command text
+ * @param traceText trace text (if empty, command text is used)
+ * @return a new POP3Command object
+ */
+ static shared_ptr <POP3Command> createCommand(const string& text, const string& traceText = "");
+
+ /** Sends this command over the specified connection.
+ *
+ * @param conn connection onto which the command will be sent
+ */
+ virtual void send(const shared_ptr <POP3Connection>& conn);
+
+ /** Returns the full text of the command, including command name
+ * and parameters (if any).
+ *
+ * @return command text (eg. "LIST 42")
+ */
+ virtual const string getText() const;
+
+ /** Returns the full text of the command, suitable for outputing
+ * to the tracer.
+ *
+ * @return trace text (eg. "USER myusername")
+ */
+ virtual const string getTraceText() const;
+
+protected:
+
+ POP3Command(const string& text, const string& traceText);
+ POP3Command(const POP3Command&);
+
+private:
+
+ string m_text;
+ string m_traceText;
+};
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+#endif // VMIME_NET_POP3_POP3COMMAND_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/pop3/POP3Connection.cpp b/vmime-master/src/vmime/net/pop3/POP3Connection.cpp
new file mode 100644
index 0000000..749f7ef
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Connection.cpp
@@ -0,0 +1,737 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/pop3/POP3Connection.hpp"
+#include "vmime/net/pop3/POP3Store.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/platform.hpp"
+
+#include "vmime/security/digest/messageDigestFactory.hpp"
+
+#include "vmime/net/defaultConnectionInfos.hpp"
+
+#if VMIME_HAVE_SASL_SUPPORT
+ #include "vmime/security/sasl/SASLContext.hpp"
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+#if VMIME_HAVE_TLS_SUPPORT
+ #include "vmime/net/tls/TLSSession.hpp"
+ #include "vmime/net/tls/TLSSecuredConnectionInfos.hpp"
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+
+// Helpers for service properties
+#define GET_PROPERTY(type, prop) \
+ (m_store.lock()->getInfos().getPropertyValue <type>(getSession(), \
+ dynamic_cast <const POP3ServiceInfos&>(m_store.lock()->getInfos()).getProperties().prop))
+#define HAS_PROPERTY(prop) \
+ (m_store.lock()->getInfos().hasProperty(getSession(), \
+ dynamic_cast <const POP3ServiceInfos&>(m_store.lock()->getInfos()).getProperties().prop))
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+
+POP3Connection::POP3Connection(
+ const shared_ptr <POP3Store>& store,
+ const shared_ptr <security::authenticator>& auth
+)
+ : m_store(store),
+ m_auth(auth),
+ m_socket(null),
+ m_timeoutHandler(null),
+ m_authenticated(false),
+ m_secured(false),
+ m_capabilitiesFetched(false) {
+
+ static int connectionId = 0;
+
+ if (store->getTracerFactory()) {
+ m_tracer = store->getTracerFactory()->create(store, ++connectionId);
+ }
+}
+
+
+POP3Connection::~POP3Connection() {
+
+ try {
+
+ if (isConnected()) {
+ disconnect();
+ } else if (m_socket) {
+ internalDisconnect();
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+void POP3Connection::connect() {
+
+ if (isConnected()) {
+ throw exceptions::already_connected();
+ }
+
+ const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS);
+ const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT);
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ // Create the time-out handler
+ if (store->getTimeoutHandlerFactory()) {
+ m_timeoutHandler = store->getTimeoutHandlerFactory()->create();
+ }
+
+ // Create and connect the socket
+ m_socket = store->getSocketFactory()->create(m_timeoutHandler);
+ m_socket->setTracer(m_tracer);
+
+#if VMIME_HAVE_TLS_SUPPORT
+ if (store->isPOP3S()) { // dedicated port/POP3S
+
+ shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create
+ (store->getCertificateVerifier(),
+ store->getSession()->getTLSProperties());
+
+ shared_ptr <tls::TLSSocket> tlsSocket =
+ tlsSession->getSocket(m_socket);
+
+ m_socket = tlsSocket;
+
+ m_secured = true;
+ m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>(address, port, tlsSession, tlsSocket);
+ } else
+#endif // VMIME_HAVE_TLS_SUPPORT
+ {
+ m_cntInfos = make_shared <defaultConnectionInfos>(address, port);
+ }
+
+ m_socket->connect(address, port);
+
+ // Connection
+ //
+ // eg: C: <connection to server>
+ // --- S: +OK MailSite POP3 Server 5.3.4.0 Ready <36938848.1056800841.634@somewhere.com>
+
+ shared_ptr <POP3Response> response = POP3Response::readResponse(
+ dynamicCast <POP3Connection>(shared_from_this())
+ );
+
+ if (!response->isSuccess()) {
+
+ internalDisconnect();
+ throw exceptions::connection_greeting_error(response->getFirstLine());
+ }
+
+#if VMIME_HAVE_TLS_SUPPORT
+ // Setup secured connection, if requested
+ const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS)
+ && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS);
+ const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED)
+ && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED);
+
+ if (!store->isPOP3S() && tls) { // only if not POP3S
+
+ try {
+
+ startTLS();
+
+ // Non-fatal error
+ } catch (exceptions::command_error&) {
+
+ if (tlsRequired) {
+ throw;
+ } else {
+ // TLS is not required, so don't bother
+ }
+
+ // Fatal error
+ } catch (...) {
+ throw;
+ }
+ }
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ // Start authentication process
+ authenticate(messageId(response->getText()));
+}
+
+
+void POP3Connection::disconnect() {
+
+ if (!isConnected()) {
+ throw exceptions::not_connected();
+ }
+
+ internalDisconnect();
+}
+
+
+void POP3Connection::internalDisconnect() {
+
+ if (m_socket) {
+
+ if (m_socket->isConnected()) {
+
+ try {
+
+ POP3Command::QUIT()->send(dynamicCast <POP3Connection>(shared_from_this()));
+ POP3Response::readResponse(dynamicCast <POP3Connection>(shared_from_this()));
+
+ } catch (exception&) {
+
+ // Not important
+ }
+
+ m_socket->disconnect();
+ }
+
+ m_socket = null;
+ }
+
+ m_timeoutHandler = null;
+
+ m_authenticated = false;
+ m_secured = false;
+
+ m_cntInfos = null;
+}
+
+
+void POP3Connection::authenticate(const messageId& randomMID) {
+
+ getAuthenticator()->setService(m_store.lock());
+
+#if VMIME_HAVE_SASL_SUPPORT
+ // First, try SASL authentication
+ if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) {
+
+ try {
+
+ authenticateSASL();
+
+ m_authenticated = true;
+ return;
+
+ } catch (exceptions::authentication_error&) {
+
+ if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) {
+
+ // Can't fallback on APOP/normal authentication
+ internalDisconnect();
+ throw;
+
+ } else {
+
+ // Ignore, will try APOP/normal authentication
+ }
+
+ } catch (exception&) {
+
+ internalDisconnect();
+ throw;
+ }
+ }
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ // Secured authentication with APOP (if requested and if available)
+ //
+ // eg: C: APOP vincent <digest>
+ // --- S: +OK vincent is a valid mailbox
+
+ const string username = getAuthenticator()->getUsername();
+ const string password = getAuthenticator()->getPassword();
+
+ shared_ptr <POP3Connection> conn = dynamicCast <POP3Connection>(shared_from_this());
+ shared_ptr <POP3Response> response;
+
+ if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP)) {
+
+ if (randomMID.getLeft().length() != 0 &&
+ randomMID.getRight().length() != 0) {
+
+ // <digest> is the result of MD5 applied to "<message-id>password"
+ shared_ptr <security::digest::messageDigest> md5 =
+ security::digest::messageDigestFactory::getInstance()->create("md5");
+
+ md5->update(randomMID.generate() + password);
+ md5->finalize();
+
+ POP3Command::APOP(username, md5->getHexDigest())->send(conn);
+ response = POP3Response::readResponse(conn);
+
+ if (response->isSuccess()) {
+
+ m_authenticated = true;
+ return;
+
+ } else {
+
+ // Some servers close the connection after an unsuccessful APOP
+ // command, so the fallback may not always work...
+ //
+ // S: +OK Qpopper (version 4.0.5) at xxx starting. <30396.1126730747@xxx>
+ // C: APOP plop c5e0a87d088ec71d60e32692d4c5bdf4
+ // S: -ERR [AUTH] Password supplied for "plop" is incorrect.
+ // S: +OK Pop server at xxx signing off.
+ // [Connection closed by foreign host.]
+
+ if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) {
+
+ // Can't fallback on basic authentication
+ internalDisconnect();
+ throw exceptions::authentication_error(response->getFirstLine());
+ }
+
+ // Ensure connection is valid (cf. note above)
+ try {
+
+ POP3Command::NOOP()->send(conn);
+ POP3Response::readResponse(conn);
+
+ } catch (exceptions::socket_exception&) {
+
+ internalDisconnect();
+ throw exceptions::authentication_error(response->getFirstLine());
+ }
+ }
+
+ } else {
+
+ // APOP not supported
+ if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) {
+
+ // Can't fallback on basic authentication
+ internalDisconnect();
+ throw exceptions::authentication_error("APOP not supported");
+ }
+ }
+ }
+
+ // Basic authentication
+ //
+ // eg: C: USER vincent
+ // --- S: +OK vincent is a valid mailbox
+ //
+ // C: PASS couic
+ // S: +OK vincent's maildrop has 2 messages (320 octets)
+ POP3Command::USER(username)->send(conn);
+ response = POP3Response::readResponse(conn);
+
+ if (!response->isSuccess()) {
+
+ internalDisconnect();
+ throw exceptions::authentication_error(response->getFirstLine());
+ }
+
+ POP3Command::PASS(password)->send(conn);
+ response = POP3Response::readResponse(conn);
+
+ if (!response->isSuccess()) {
+
+ internalDisconnect();
+ throw exceptions::authentication_error(response->getFirstLine());
+ }
+
+ m_authenticated = true;
+}
+
+
+#if VMIME_HAVE_SASL_SUPPORT
+
+void POP3Connection::authenticateSASL() {
+
+ if (!dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())) {
+ throw exceptions::authentication_error("No SASL authenticator available.");
+ }
+
+ std::vector <string> capa = getCapabilities();
+ std::vector <string> saslMechs;
+
+ for (unsigned int i = 0 ; i < capa.size() ; ++i) {
+
+ const string& x = capa[i];
+
+ // C: CAPA
+ // S: +OK List of capabilities follows
+ // S: LOGIN-DELAY 0
+ // S: PIPELINING
+ // S: UIDL
+ // S: ...
+ // S: SASL DIGEST-MD5 CRAM-MD5 <-----
+ // S: EXPIRE NEVER
+ // S: ...
+
+ if (x.length() > 5 &&
+ (x[0] == 'S' || x[0] == 's') &&
+ (x[1] == 'A' || x[1] == 'a') &&
+ (x[2] == 'S' || x[2] == 's') &&
+ (x[3] == 'L' || x[3] == 'l') &&
+ (x[4] == ' ' || x[4] == '\t')) {
+
+ const string list(x.begin() + 5, x.end());
+
+ std::istringstream iss(list);
+ iss.imbue(std::locale::classic());
+
+ string mech;
+
+ while (iss >> mech) {
+ saslMechs.push_back(mech);
+ }
+ }
+ }
+
+ if (saslMechs.empty()) {
+ throw exceptions::authentication_error("No SASL mechanism available.");
+ }
+
+ std::vector <shared_ptr <security::sasl::SASLMechanism> > mechList;
+
+ shared_ptr <security::sasl::SASLContext> saslContext =
+ security::sasl::SASLContext::create();
+
+ for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) {
+
+ try {
+ mechList.push_back(saslContext->createMechanism(saslMechs[i]));
+ } catch (exceptions::no_such_mechanism&) {
+ // Ignore mechanism
+ }
+ }
+
+ if (mechList.empty()) {
+ throw exceptions::authentication_error("No SASL mechanism available.");
+ }
+
+ // Try to suggest a mechanism among all those supported
+ shared_ptr <security::sasl::SASLMechanism> suggestedMech =
+ saslContext->suggestMechanism(mechList);
+
+ if (!suggestedMech) {
+ throw exceptions::authentication_error("Unable to suggest SASL mechanism.");
+ }
+
+ // Allow application to choose which mechanisms to use
+ mechList = dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())->
+ getAcceptableMechanisms(mechList, suggestedMech);
+
+ if (mechList.empty()) {
+ throw exceptions::authentication_error("No SASL mechanism available.");
+ }
+
+ // Try each mechanism in the list in turn
+ for (unsigned int i = 0 ; i < mechList.size() ; ++i) {
+
+ shared_ptr <security::sasl::SASLMechanism> mech = mechList[i];
+
+ shared_ptr <security::sasl::SASLSession> saslSession =
+ saslContext->createSession("pop3", getAuthenticator(), mech);
+
+ saslSession->init();
+
+ shared_ptr <POP3Command> authCmd;
+
+ if (saslSession->getMechanism()->hasInitialResponse()) {
+
+ byte_t* initialResp = 0;
+ size_t initialRespLen = 0;
+
+ saslSession->evaluateChallenge(NULL, 0, &initialResp, &initialRespLen);
+
+ string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen));
+ delete [] initialResp;
+
+ if (encodedInitialResp.empty()) {
+ authCmd = POP3Command::AUTH(mech->getName(), "=");
+ } else {
+ authCmd = POP3Command::AUTH(mech->getName(), encodedInitialResp);
+ }
+
+ } else {
+
+ authCmd = POP3Command::AUTH(mech->getName());
+ }
+
+ authCmd->send(dynamicCast <POP3Connection>(shared_from_this()));
+
+ for (bool cont = true ; cont ; ) {
+
+ shared_ptr <POP3Response> response =
+ POP3Response::readResponse(dynamicCast <POP3Connection>(shared_from_this()));
+
+ switch (response->getCode()) {
+
+ case POP3Response::CODE_OK: {
+
+ m_socket = saslSession->getSecuredSocket(m_socket);
+ return;
+ }
+
+ case POP3Response::CODE_READY: {
+
+ byte_t* challenge = 0;
+ size_t challengeLen = 0;
+
+ byte_t* resp = 0;
+ size_t respLen = 0;
+
+ try {
+
+ // Extract challenge
+ saslContext->decodeB64(response->getText(), &challenge, &challengeLen);
+
+ // Prepare response
+ saslSession->evaluateChallenge(challenge, challengeLen, &resp, &respLen);
+
+ // Send response
+ const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n";
+ m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length());
+
+ if (m_tracer) {
+ m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange");
+ }
+
+ } catch (exceptions::sasl_exception& e) {
+
+ if (challenge) {
+ delete [] challenge;
+ challenge = NULL;
+ }
+
+ if (resp) {
+ delete [] resp;
+ resp = NULL;
+ }
+
+ // Cancel SASL exchange
+ m_socket->send("*\r\n");
+
+ if (m_tracer) {
+ m_tracer->traceSend("*");
+ }
+
+ } catch (...) {
+
+ if (challenge) {
+ delete [] challenge;
+ }
+
+ if (resp) {
+ delete [] resp;
+ }
+
+ throw;
+ }
+
+ if (challenge) {
+ delete [] challenge;
+ }
+
+ if (resp) {
+ delete [] resp;
+ }
+
+ break;
+ }
+
+ default:
+
+ cont = false;
+ break;
+ }
+ }
+ }
+
+ throw exceptions::authentication_error("Could not authenticate using SASL: all mechanisms failed.");
+}
+
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+void POP3Connection::startTLS() {
+
+ try {
+
+ POP3Command::STLS()->send(dynamicCast <POP3Connection>(shared_from_this()));
+
+ shared_ptr <POP3Response> response =
+ POP3Response::readResponse(dynamicCast <POP3Connection>(shared_from_this()));
+
+ if (!response->isSuccess()) {
+ throw exceptions::command_error("STLS", response->getFirstLine());
+ }
+
+ shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create(
+ m_store.lock()->getCertificateVerifier(),
+ m_store.lock()->getSession()->getTLSProperties()
+ );
+
+ shared_ptr <tls::TLSSocket> tlsSocket = tlsSession->getSocket(m_socket);
+
+ tlsSocket->handshake();
+
+ m_socket = tlsSocket;
+
+ m_secured = true;
+ m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>(
+ m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket
+ );
+
+ // " Once TLS has been started, the client MUST discard cached
+ // information about server capabilities and SHOULD re-issue
+ // the CAPA command. This is necessary to protect against
+ // man-in-the-middle attacks which alter the capabilities list
+ // prior to STLS. " (RFC-2595)
+ invalidateCapabilities();
+
+ } catch (exceptions::command_error&) {
+
+ // Non-fatal error
+ throw;
+
+ } catch (exception&) {
+
+ // Fatal error
+ internalDisconnect();
+ throw;
+ }
+}
+
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+const std::vector <string> POP3Connection::getCapabilities() {
+
+ if (!m_capabilitiesFetched) {
+ fetchCapabilities();
+ }
+
+ return m_capabilities;
+}
+
+
+void POP3Connection::invalidateCapabilities() {
+
+ m_capabilities.clear();
+ m_capabilitiesFetched = false;
+}
+
+
+void POP3Connection::fetchCapabilities() {
+
+ POP3Command::CAPA()->send(dynamicCast <POP3Connection>(shared_from_this()));
+
+ shared_ptr <POP3Response> response =
+ POP3Response::readMultilineResponse(dynamicCast <POP3Connection>(shared_from_this()));
+
+ std::vector <string> res;
+
+ if (response->isSuccess()) {
+
+ for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) {
+ res.push_back(response->getLineAt(i));
+ }
+ }
+
+ m_capabilities = res;
+ m_capabilitiesFetched = true;
+}
+
+
+bool POP3Connection::isConnected() const {
+
+ return m_socket && m_socket->isConnected() && m_authenticated;
+}
+
+
+bool POP3Connection::isSecuredConnection() const {
+
+ return m_secured;
+}
+
+
+shared_ptr <connectionInfos> POP3Connection::getConnectionInfos() const {
+
+ return m_cntInfos;
+}
+
+
+shared_ptr <POP3Store> POP3Connection::getStore() {
+
+ return m_store.lock();
+}
+
+
+shared_ptr <session> POP3Connection::getSession() {
+
+ return m_store.lock()->getSession();
+}
+
+
+shared_ptr <socket> POP3Connection::getSocket() {
+
+ return m_socket;
+}
+
+
+shared_ptr <tracer> POP3Connection::getTracer() {
+
+ return m_tracer;
+}
+
+
+shared_ptr <timeoutHandler> POP3Connection::getTimeoutHandler() {
+
+ return m_timeoutHandler;
+}
+
+
+shared_ptr <security::authenticator> POP3Connection::getAuthenticator() {
+
+ return m_auth;
+}
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
diff --git a/vmime-master/src/vmime/net/pop3/POP3Connection.hpp b/vmime-master/src/vmime/net/pop3/POP3Connection.hpp
new file mode 100644
index 0000000..26b3f3c
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Connection.hpp
@@ -0,0 +1,132 @@
+//
+// 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_NET_POP3_POP3CONNECTION_HPP_INCLUDED
+#define VMIME_NET_POP3_POP3CONNECTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/messageId.hpp"
+
+#include "vmime/net/socket.hpp"
+#include "vmime/net/timeoutHandler.hpp"
+#include "vmime/net/session.hpp"
+#include "vmime/net/connectionInfos.hpp"
+#include "vmime/net/tracer.hpp"
+
+#include "vmime/net/pop3/POP3Command.hpp"
+#include "vmime/net/pop3/POP3Response.hpp"
+
+#include "vmime/security/authenticator.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+class socket;
+class timeoutHandler;
+
+
+namespace pop3 {
+
+
+class POP3Store;
+
+
+/** Manage connection to a POP3 server.
+ */
+class VMIME_EXPORT POP3Connection : public object, public enable_shared_from_this <POP3Connection> {
+
+public:
+
+ POP3Connection(
+ const shared_ptr <POP3Store>& store,
+ const shared_ptr <security::authenticator>& auth
+ );
+
+ virtual ~POP3Connection();
+
+
+ virtual void connect();
+ virtual bool isConnected() const;
+ virtual void disconnect();
+
+ bool isSecuredConnection() const;
+ shared_ptr <connectionInfos> getConnectionInfos() const;
+
+ virtual shared_ptr <POP3Store> getStore();
+ virtual shared_ptr <socket> getSocket();
+ virtual shared_ptr <timeoutHandler> getTimeoutHandler();
+ virtual shared_ptr <security::authenticator> getAuthenticator();
+ virtual shared_ptr <session> getSession();
+ virtual shared_ptr <tracer> getTracer();
+
+private:
+
+ void authenticate(const messageId& randomMID);
+#if VMIME_HAVE_SASL_SUPPORT
+ void authenticateSASL();
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+#if VMIME_HAVE_TLS_SUPPORT
+ void startTLS();
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ void fetchCapabilities();
+ void invalidateCapabilities();
+ const std::vector <string> getCapabilities();
+
+ void internalDisconnect();
+
+
+ weak_ptr <POP3Store> m_store;
+
+ shared_ptr <security::authenticator> m_auth;
+ shared_ptr <socket> m_socket;
+ shared_ptr <timeoutHandler> m_timeoutHandler;
+ shared_ptr <tracer> m_tracer;
+
+ bool m_authenticated;
+ bool m_secured;
+
+ shared_ptr <connectionInfos> m_cntInfos;
+
+ std::vector <string> m_capabilities;
+ bool m_capabilitiesFetched;
+};
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+#endif // VMIME_NET_POP3_POP3CONNECTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/pop3/POP3Folder.cpp b/vmime-master/src/vmime/net/pop3/POP3Folder.cpp
new file mode 100644
index 0000000..b69a483
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Folder.cpp
@@ -0,0 +1,822 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/pop3/POP3Folder.hpp"
+
+#include "vmime/net/pop3/POP3Store.hpp"
+#include "vmime/net/pop3/POP3Message.hpp"
+#include "vmime/net/pop3/POP3Command.hpp"
+#include "vmime/net/pop3/POP3Response.hpp"
+#include "vmime/net/pop3/POP3FolderStatus.hpp"
+
+#include "vmime/net/pop3/POP3Utils.hpp"
+
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+POP3Folder::POP3Folder(
+ const folder::path& path,
+ const shared_ptr <POP3Store>& store
+)
+ : m_store(store),
+ m_path(path),
+ m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()),
+ m_mode(-1),
+ m_open(false) {
+
+ store->registerFolder(this);
+}
+
+
+POP3Folder::~POP3Folder() {
+
+ try {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ if (store) {
+
+ if (m_open) {
+ close(false);
+ }
+
+ store->unregisterFolder(this);
+
+ } else if (m_open) {
+
+ onClose();
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+int POP3Folder::getMode() const {
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ return m_mode;
+}
+
+
+const folderAttributes POP3Folder::getAttributes() {
+
+ folderAttributes attribs;
+
+ if (m_path.isEmpty()) {
+ attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS);
+ } else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") {
+ attribs.setType(folderAttributes::TYPE_CONTAINS_MESSAGES);
+ attribs.setSpecialUse(folderAttributes::SPECIALUSE_INBOX);
+ } else {
+ throw exceptions::folder_not_found();
+ }
+
+ attribs.setFlags(0);
+
+ return attribs;
+}
+
+
+const folder::path::component POP3Folder::getName() const {
+
+ return m_name;
+}
+
+
+const folder::path POP3Folder::getFullPath() const {
+
+ return m_path;
+}
+
+
+void POP3Folder::open(const int mode, bool failIfModeIsNotAvailable) {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ if (m_path.isEmpty()) {
+
+ if (mode != MODE_READ_ONLY && failIfModeIsNotAvailable) {
+ throw exceptions::operation_not_supported();
+ }
+
+ m_open = true;
+ m_mode = mode;
+
+ m_messageCount = 0;
+
+ } else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") {
+
+ POP3Command::STAT()->send(store->getConnection());
+
+ shared_ptr <POP3Response> response = POP3Response::readResponse(store->getConnection());
+
+ if (!response->isSuccess()) {
+ throw exceptions::command_error("STAT", response->getFirstLine());
+ }
+
+ std::istringstream iss(response->getText());
+ iss.imbue(std::locale::classic());
+ iss >> m_messageCount;
+
+ if (iss.fail()) {
+ throw exceptions::invalid_response("STAT", response->getFirstLine());
+ }
+
+ m_open = true;
+ m_mode = mode;
+
+ } else {
+
+ throw exceptions::folder_not_found();
+ }
+}
+
+
+void POP3Folder::close(const bool expunge) {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (!expunge) {
+ POP3Command::RSET()->send(store->getConnection());
+ POP3Response::readResponse(store->getConnection());
+ }
+
+ m_open = false;
+ m_mode = -1;
+
+ onClose();
+}
+
+
+void POP3Folder::onClose() {
+
+ for (MessageMap::iterator it = m_messages.begin() ; it != m_messages.end() ; ++it) {
+ (*it).first->onFolderClosed();
+ }
+
+ m_messages.clear();
+}
+
+
+void POP3Folder::create(const folderAttributes& /* attribs */) {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+void POP3Folder::destroy() {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+bool POP3Folder::exists() {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ return m_path.isEmpty() || (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX");
+}
+
+
+bool POP3Folder::isOpen() const {
+
+ return m_open;
+}
+
+
+shared_ptr <message> POP3Folder::getMessage(const size_t num) {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ } else if (num < 1 || num > m_messageCount) {
+ throw exceptions::message_not_found();
+ }
+
+ return make_shared <POP3Message>(dynamicCast <POP3Folder>(shared_from_this()), num);
+}
+
+
+std::vector <shared_ptr <message> > POP3Folder::getMessages(const messageSet& msgs) {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (msgs.isNumberSet()) {
+
+ const std::vector <size_t> numbers = POP3Utils::messageSetToNumberList(msgs, m_messageCount);
+
+ std::vector <shared_ptr <message> > messages;
+ shared_ptr <POP3Folder> thisFolder(dynamicCast <POP3Folder>(shared_from_this()));
+
+ for (std::vector <size_t>::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) {
+
+ if (*it < 1|| *it > m_messageCount) {
+ throw exceptions::message_not_found();
+ }
+
+ messages.push_back(make_shared <POP3Message>(thisFolder, *it));
+ }
+
+ return messages;
+
+ } else {
+
+ throw exceptions::operation_not_supported();
+ }
+}
+
+
+size_t POP3Folder::getMessageCount() {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ return m_messageCount;
+}
+
+
+shared_ptr <folder> POP3Folder::getFolder(const folder::path::component& name) {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ return shared_ptr <POP3Folder>(new POP3Folder(m_path / name, store));
+}
+
+
+std::vector <shared_ptr <folder> > POP3Folder::getFolders(const bool /* recursive */) {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ if (m_path.isEmpty()) {
+
+ std::vector <shared_ptr <folder> > v;
+ v.push_back(shared_ptr <POP3Folder>(new POP3Folder(folder::path::component("INBOX"), store)));
+ return v;
+
+ } else {
+
+ std::vector <shared_ptr <folder> > v;
+ return v;
+ }
+}
+
+
+void POP3Folder::fetchMessages(
+ std::vector <shared_ptr <message> >& msg,
+ const fetchAttributes& options,
+ utility::progressListener* progress
+) {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ if (msg.empty()) {
+ return;
+ }
+
+ const size_t total = msg.size();
+ size_t current = 0;
+
+ if (progress) {
+ progress->start(total);
+ }
+
+ for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ;
+ it != msg.end() ; ++it) {
+
+ dynamicCast <POP3Message>(*it)->fetch(
+ dynamicCast <POP3Folder>(shared_from_this()),
+ options
+ );
+
+ if (progress) {
+ progress->progress(++current, total);
+ }
+ }
+
+ if (options.has(fetchAttributes::SIZE)) {
+
+ // Send the "LIST" command
+ POP3Command::LIST()->send(store->getConnection());
+
+ // Get the response
+ shared_ptr <POP3Response> response =
+ POP3Response::readMultilineResponse(store->getConnection());
+
+ if (response->isSuccess()) {
+
+ // C: LIST
+ // S: +OK
+ // S: 1 47548
+ // S: 2 12653
+ // S: .
+ std::map <size_t, string> result;
+ POP3Utils::parseMultiListOrUidlResponse(response, result);
+
+ for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ;
+ it != msg.end() ; ++it) {
+
+ shared_ptr <POP3Message> m = dynamicCast <POP3Message>(*it);
+
+ std::map <size_t, string>::const_iterator x = result.find(m->m_num);
+
+ if (x != result.end()) {
+
+ size_t size = 0;
+
+ std::istringstream iss((*x).second);
+ iss.imbue(std::locale::classic());
+ iss >> size;
+
+ m->m_size = size;
+ }
+ }
+ }
+ }
+
+ if (options.has(fetchAttributes::UID)) {
+
+ // Send the "UIDL" command
+ POP3Command::UIDL()->send(store->getConnection());
+
+ // Get the response
+ shared_ptr <POP3Response> response =
+ POP3Response::readMultilineResponse(store->getConnection());
+
+ if (response->isSuccess()) {
+
+ // C: UIDL
+ // S: +OK
+ // S: 1 whqtswO00WBw418f9t5JxYwZ
+ // S: 2 QhdPYR:00WBw1Ph7x7
+ // S: .
+ std::map <size_t, string> result;
+ POP3Utils::parseMultiListOrUidlResponse(response, result);
+
+ for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ;
+ it != msg.end() ; ++it) {
+
+ shared_ptr <POP3Message> m = dynamicCast <POP3Message>(*it);
+
+ std::map <size_t, string>::const_iterator x = result.find(m->m_num);
+
+ if (x != result.end()) {
+ m->m_uid = (*x).second;
+ }
+ }
+ }
+ }
+
+ if (progress) {
+ progress->stop(total);
+ }
+}
+
+
+void POP3Folder::fetchMessage(const shared_ptr <message>& msg, const fetchAttributes& options) {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ dynamicCast <POP3Message>(msg)->fetch(
+ dynamicCast <POP3Folder>(shared_from_this()),
+ options
+ );
+
+ if (options.has(fetchAttributes::SIZE)) {
+
+ // Send the "LIST" command
+ POP3Command::LIST(msg->getNumber())->send(store->getConnection());
+
+ // Get the response
+ shared_ptr <POP3Response> response =
+ POP3Response::readResponse(store->getConnection());
+
+ if (response->isSuccess()) {
+
+ string responseText = response->getText();
+
+ // C: LIST 2
+ // S: +OK 2 4242
+ string::iterator it = responseText.begin();
+
+ while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it;
+ while (it != responseText.end() && !(*it == ' ' || *it == '\t')) ++it;
+ while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it;
+
+ if (it != responseText.end()) {
+
+ size_t size = 0;
+
+ std::istringstream iss(string(it, responseText.end()));
+ iss.imbue(std::locale::classic());
+ iss >> size;
+
+ dynamicCast <POP3Message>(msg)->m_size = size;
+ }
+ }
+ }
+
+ if (options.has(fetchAttributes::UID)) {
+
+ // Send the "UIDL" command
+ POP3Command::UIDL(msg->getNumber())->send(store->getConnection());
+
+ // Get the response
+ shared_ptr <POP3Response> response =
+ POP3Response::readResponse(store->getConnection());
+
+ if (response->isSuccess()) {
+
+ string responseText = response->getText();
+
+ // C: UIDL 2
+ // S: +OK 2 QhdPYR:00WBw1Ph7x7
+ string::iterator it = responseText.begin();
+
+ while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it;
+ while (it != responseText.end() && !(*it == ' ' || *it == '\t')) ++it;
+ while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it;
+
+ if (it != responseText.end()) {
+ dynamicCast <POP3Message>(msg)->m_uid = string(it, responseText.end());
+ }
+ }
+ }
+}
+
+
+std::vector <shared_ptr <message> > POP3Folder::getAndFetchMessages(
+ const messageSet& msgs,
+ const fetchAttributes& attribs
+) {
+
+ if (msgs.isEmpty()) {
+ return std::vector <shared_ptr <message> >();
+ }
+
+ std::vector <shared_ptr <message> > messages = getMessages(msgs);
+ fetchMessages(messages, attribs);
+
+ return messages;
+}
+
+
+int POP3Folder::getFetchCapabilities() const {
+
+ return fetchAttributes::ENVELOPE |
+ fetchAttributes::CONTENT_INFO |
+ fetchAttributes::SIZE |
+ fetchAttributes::FULL_HEADER |
+ fetchAttributes::UID |
+ fetchAttributes::IMPORTANCE;
+}
+
+
+shared_ptr <folder> POP3Folder::getParent() {
+
+ if (m_path.isEmpty()) {
+ return null;
+ } else {
+ return shared_ptr <POP3Folder>(new POP3Folder(m_path.getParent(), m_store.lock()));
+ }
+}
+
+
+shared_ptr <const store> POP3Folder::getStore() const {
+
+ return m_store.lock();
+}
+
+
+shared_ptr <store> POP3Folder::getStore() {
+
+ return m_store.lock();
+}
+
+
+void POP3Folder::registerMessage(POP3Message* msg) {
+
+ m_messages.insert(MessageMap::value_type(msg, msg->getNumber()));
+}
+
+
+void POP3Folder::unregisterMessage(POP3Message* msg) {
+
+ m_messages.erase(msg);
+}
+
+
+void POP3Folder::onStoreDisconnected() {
+
+ m_store.reset();
+}
+
+
+void POP3Folder::deleteMessages(const messageSet& msgs) {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ const std::vector <size_t> nums = POP3Utils::messageSetToNumberList(msgs, m_messageCount);
+
+ if (nums.empty()) {
+ throw exceptions::invalid_argument();
+ }
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ } else if (!isOpen()) {
+ throw exceptions::illegal_state("Folder not open");
+ }
+
+ for (std::vector <size_t>::const_iterator
+ it = nums.begin() ; it != nums.end() ; ++it) {
+
+ POP3Command::DELE(*it)->send(store->getConnection());
+
+ shared_ptr <POP3Response> response =
+ POP3Response::readResponse(store->getConnection());
+
+ if (!response->isSuccess()) {
+ throw exceptions::command_error("DELE", response->getFirstLine());
+ }
+ }
+
+ // Sort message list
+ std::vector <size_t> list;
+
+ list.resize(nums.size());
+ std::copy(nums.begin(), nums.end(), list.begin());
+
+ std::sort(list.begin(), list.end());
+
+ // Update local flags
+ for (std::map <POP3Message*, size_t>::iterator it =
+ m_messages.begin() ; it != m_messages.end() ; ++it) {
+
+ POP3Message* msg = (*it).first;
+
+ if (std::binary_search(list.begin(), list.end(), msg->getNumber())) {
+ msg->m_deleted = true;
+ }
+ }
+
+ // Notify message flags changed
+ shared_ptr <events::messageChangedEvent> event =
+ make_shared <events::messageChangedEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageChangedEvent::TYPE_FLAGS,
+ list
+ );
+
+ notifyMessageChanged(event);
+}
+
+
+void POP3Folder::setMessageFlags(
+ const messageSet& /* msgs */,
+ const int /* flags */,
+ const int /* mode */
+) {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+void POP3Folder::rename(const folder::path& /* newPath */) {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+messageSet POP3Folder::addMessage(
+ const shared_ptr <vmime::message>& /* msg */,
+ const int /* flags */,
+ vmime::datetime* /* date */,
+ utility::progressListener* /* progress */
+) {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+messageSet POP3Folder::addMessage(
+ utility::inputStream& /* is */,
+ const size_t /* size */,
+ const int /* flags */,
+ vmime::datetime* /* date */,
+ utility::progressListener* /* progress */
+) {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+messageSet POP3Folder::copyMessages(
+ const folder::path& /* dest */,
+ const messageSet& /* msgs */
+) {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+void POP3Folder::status(size_t& count, size_t& unseen) {
+
+ count = 0;
+ unseen = 0;
+
+ shared_ptr <folderStatus> status = getStatus();
+
+ count = status->getMessageCount();
+ unseen = status->getUnseenCount();
+
+ m_messageCount = count;
+}
+
+
+shared_ptr <folderStatus> POP3Folder::getStatus() {
+
+ shared_ptr <POP3Store> store = m_store.lock();
+
+ if (!store) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ POP3Command::STAT()->send(store->getConnection());
+
+ shared_ptr <POP3Response> response =
+ POP3Response::readResponse(store->getConnection());
+
+ if (!response->isSuccess()) {
+ throw exceptions::command_error("STAT", response->getFirstLine());
+ }
+
+
+ size_t count = 0;
+
+ std::istringstream iss(response->getText());
+ iss.imbue(std::locale::classic());
+ iss >> count;
+
+ shared_ptr <POP3FolderStatus> status = make_shared <POP3FolderStatus>();
+
+ status->setMessageCount(count);
+ status->setUnseenCount(count);
+
+ // Update local message count
+ if (m_messageCount != count) {
+
+ const size_t oldCount = m_messageCount;
+
+ m_messageCount = count;
+
+ if (count > oldCount) {
+
+ std::vector <size_t> nums;
+ nums.resize(count - oldCount);
+
+ for (size_t i = oldCount + 1, j = 0 ; i <= count ; ++i, ++j) {
+ nums[j] = i;
+ }
+
+ // Notify message count changed
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>(shared_from_this()),
+ events::messageCountEvent::TYPE_ADDED,
+ nums
+ );
+
+ notifyMessageCount(event);
+
+ // Notify folders with the same path
+ for (std::list <POP3Folder*>::iterator it = store->m_folders.begin() ;
+ it != store->m_folders.end() ; ++it) {
+
+ if ((*it) != this && (*it)->getFullPath() == m_path) {
+
+ (*it)->m_messageCount = count;
+
+ shared_ptr <events::messageCountEvent> event =
+ make_shared <events::messageCountEvent>(
+ dynamicCast <folder>((*it)->shared_from_this()),
+ events::messageCountEvent::TYPE_ADDED,
+ nums
+ );
+
+ (*it)->notifyMessageCount(event);
+ }
+ }
+ }
+ }
+
+ return status;
+}
+
+
+void POP3Folder::expunge() {
+
+ // Not supported by POP3 protocol (deleted messages are automatically
+ // expunged at the end of the session...).
+}
+
+
+std::vector <size_t> POP3Folder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
diff --git a/vmime-master/src/vmime/net/pop3/POP3Folder.hpp b/vmime-master/src/vmime/net/pop3/POP3Folder.hpp
new file mode 100644
index 0000000..73e29f9
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Folder.hpp
@@ -0,0 +1,179 @@
+//
+// 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_NET_POP3_POP3FOLDER_HPP_INCLUDED
+#define VMIME_NET_POP3_POP3FOLDER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include <vector>
+#include <map>
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/folder.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+class POP3Store;
+class POP3Message;
+
+
+/** POP3 folder implementation.
+ */
+class VMIME_EXPORT POP3Folder : public folder {
+
+private:
+
+ friend class POP3Store;
+ friend class POP3Message;
+
+ POP3Folder(const POP3Folder&);
+ POP3Folder(const folder::path& path, const shared_ptr <POP3Store>& store);
+
+public:
+
+ ~POP3Folder();
+
+ int getMode() const;
+
+ const folderAttributes getAttributes();
+
+ const folder::path::component getName() const;
+ const folder::path getFullPath() const;
+
+ void open(const int mode, bool failIfModeIsNotAvailable = false);
+ void close(const bool expunge);
+ void create(const folderAttributes& attribs);
+
+ bool exists();
+
+ void destroy();
+
+ bool isOpen() const;
+
+ shared_ptr <message> getMessage(const size_t num);
+ std::vector <shared_ptr <message> > getMessages(const messageSet& msgs);
+
+ size_t getMessageCount();
+
+ shared_ptr <folder> getFolder(const folder::path::component& name);
+ std::vector <shared_ptr <folder> > getFolders(const bool recursive = false);
+
+ void rename(const folder::path& newPath);
+
+ void deleteMessages(const messageSet& msgs);
+
+ void setMessageFlags(
+ const messageSet& msgs,
+ const int flags,
+ const int mode = message::FLAG_MODE_SET
+ );
+
+ messageSet addMessage(
+ const shared_ptr <vmime::message>& msg,
+ const int flags = -1,
+ vmime::datetime* date = NULL,
+ utility::progressListener* progress = NULL
+ );
+
+ messageSet addMessage(
+ utility::inputStream& is,
+ const size_t size,
+ const int flags = -1,
+ vmime::datetime* date = NULL,
+ utility::progressListener* progress = NULL
+ );
+
+ messageSet copyMessages(const folder::path& dest, const messageSet& msgs);
+
+ void status(size_t& count, size_t& unseen);
+ shared_ptr <folderStatus> getStatus();
+
+ void expunge();
+
+ shared_ptr <folder> getParent();
+
+ shared_ptr <const store> getStore() const;
+ shared_ptr <store> getStore();
+
+
+ void fetchMessages(
+ std::vector <shared_ptr <message> >& msg,
+ const fetchAttributes& options,
+ utility::progressListener* progress = NULL
+ );
+
+ void fetchMessage(const shared_ptr <message>& msg, const fetchAttributes& options);
+
+ std::vector <shared_ptr <message> > getAndFetchMessages(
+ const messageSet& msgs,
+ const fetchAttributes& attribs
+ );
+
+ int getFetchCapabilities() const;
+
+ std::vector <size_t> getMessageNumbersStartingOnUID(const message::uid& uid);
+
+private:
+
+ void registerMessage(POP3Message* msg);
+ void unregisterMessage(POP3Message* msg);
+
+ void onStoreDisconnected();
+
+ void onClose();
+
+
+ weak_ptr <POP3Store> m_store;
+
+ folder::path m_path;
+ folder::path::component m_name;
+
+ int m_mode;
+ bool m_open;
+
+ size_t m_messageCount;
+
+ typedef std::map <POP3Message*, size_t> MessageMap;
+ MessageMap m_messages;
+};
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+#endif // VMIME_NET_POP3_POP3FOLDER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/pop3/POP3FolderStatus.cpp b/vmime-master/src/vmime/net/pop3/POP3FolderStatus.cpp
new file mode 100644
index 0000000..9f2c49f
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3FolderStatus.cpp
@@ -0,0 +1,88 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/pop3/POP3FolderStatus.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+POP3FolderStatus::POP3FolderStatus()
+ : m_count(0),
+ m_unseen(0) {
+
+}
+
+
+POP3FolderStatus::POP3FolderStatus(const POP3FolderStatus& other)
+ : folderStatus(),
+ m_count(other.m_count),
+ m_unseen(other.m_unseen) {
+
+}
+
+
+size_t POP3FolderStatus::getMessageCount() const {
+
+ return m_count;
+}
+
+
+size_t POP3FolderStatus::getUnseenCount() const {
+
+ return m_unseen;
+}
+
+
+void POP3FolderStatus::setMessageCount(const size_t count) {
+
+ m_count = count;
+}
+
+
+void POP3FolderStatus::setUnseenCount(const size_t unseen) {
+
+ m_unseen = unseen;
+}
+
+
+shared_ptr <folderStatus> POP3FolderStatus::clone() const {
+
+ return make_shared <POP3FolderStatus>(*this);
+}
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
diff --git a/vmime-master/src/vmime/net/pop3/POP3FolderStatus.hpp b/vmime-master/src/vmime/net/pop3/POP3FolderStatus.hpp
new file mode 100644
index 0000000..0ce413e
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3FolderStatus.hpp
@@ -0,0 +1,75 @@
+//
+// 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_NET_POP3_POP3FOLDERSTATUS_HPP_INCLUDED
+#define VMIME_NET_POP3_POP3FOLDERSTATUS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/folderStatus.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+/** Holds the status of a POP3 folder.
+ */
+class VMIME_EXPORT POP3FolderStatus : public folderStatus {
+
+public:
+
+ POP3FolderStatus();
+ POP3FolderStatus(const POP3FolderStatus& other);
+
+ // Inherited from folderStatus
+ size_t getMessageCount() const;
+ size_t getUnseenCount() const;
+
+ shared_ptr <folderStatus> clone() const;
+
+
+ void setMessageCount(const size_t count);
+ void setUnseenCount(const size_t unseen);
+
+private:
+
+ size_t m_count;
+ size_t m_unseen;
+};
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+#endif // VMIME_NET_POP3_POP3FOLDERSTATUS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/pop3/POP3Message.cpp b/vmime-master/src/vmime/net/pop3/POP3Message.cpp
new file mode 100644
index 0000000..8d6b7f5
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Message.cpp
@@ -0,0 +1,283 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/pop3/POP3Message.hpp"
+#include "vmime/net/pop3/POP3Command.hpp"
+#include "vmime/net/pop3/POP3Response.hpp"
+#include "vmime/net/pop3/POP3Folder.hpp"
+#include "vmime/net/pop3/POP3Store.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+#include "vmime/utility/outputStreamStringAdapter.hpp"
+
+#include <sstream>
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+POP3Message::POP3Message(
+ const shared_ptr <POP3Folder>& folder,
+ const size_t num
+)
+ : m_folder(folder),
+ m_num(num),
+ m_size(-1),
+ m_deleted(false) {
+
+ folder->registerMessage(this);
+}
+
+
+POP3Message::~POP3Message() {
+
+ try {
+
+ shared_ptr <POP3Folder> folder = m_folder.lock();
+
+ if (folder) {
+ folder->unregisterMessage(this);
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+void POP3Message::onFolderClosed() {
+
+ m_folder.reset();
+}
+
+
+size_t POP3Message::getNumber() const {
+
+ return m_num;
+}
+
+
+const message::uid POP3Message::getUID() const {
+
+ return m_uid;
+}
+
+
+size_t POP3Message::getSize() const {
+
+ if (m_size == static_cast <size_t>(-1)) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_size;
+}
+
+
+bool POP3Message::isExpunged() const {
+
+ return false;
+}
+
+
+int POP3Message::getFlags() const {
+
+ int flags = 0;
+
+ if (m_deleted) {
+ flags |= FLAG_DELETED;
+ }
+
+ return flags;
+}
+
+
+shared_ptr <const messageStructure> POP3Message::getStructure() const {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+shared_ptr <messageStructure> POP3Message::getStructure() {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+shared_ptr <const header> POP3Message::getHeader() const {
+
+ if (!m_header) {
+ throw exceptions::unfetched_object();
+ }
+
+ return m_header;
+}
+
+
+void POP3Message::extract(
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t start,
+ const size_t length,
+ const bool /* peek */
+) const {
+
+ shared_ptr <const POP3Folder> folder = m_folder.lock();
+
+ if (!folder) {
+ throw exceptions::illegal_state("Folder closed");
+ } else if (!folder->getStore()) {
+ throw exceptions::illegal_state("Store disconnected");
+ }
+
+ if (start != 0 && length != static_cast <size_t>(-1)) {
+ throw exceptions::partial_fetch_not_supported();
+ }
+
+ // Emit the "RETR" command
+ shared_ptr <POP3Store> store = folder->m_store.lock();
+
+ POP3Command::RETR(m_num)->send(store->getConnection());
+
+ try {
+
+ POP3Response::readLargeResponse(
+ store->getConnection(), os, progress,
+ m_size == static_cast <size_t>(-1) ? 0 : m_size
+ );
+
+ } catch (exceptions::command_error& e) {
+
+ throw exceptions::command_error("RETR", e.response());
+ }
+}
+
+
+void POP3Message::extractPart(
+ const shared_ptr <const messagePart>& /* p */,
+ utility::outputStream& /* os */,
+ utility::progressListener* /* progress */,
+ const size_t /* start */,
+ const size_t /* length */,
+ const bool /* peek */
+) const {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+void POP3Message::fetchPartHeader(const shared_ptr <messagePart>& /* p */) {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+void POP3Message::fetch(
+ const shared_ptr <POP3Folder>& msgFolder,
+ const fetchAttributes& options
+) {
+
+ shared_ptr <POP3Folder> folder = m_folder.lock();
+
+ if (folder != msgFolder) {
+ throw exceptions::folder_not_found();
+ }
+
+ // STRUCTURE and FLAGS attributes are not supported by POP3
+ if (options.has(fetchAttributes::STRUCTURE | fetchAttributes::FLAGS)) {
+ throw exceptions::operation_not_supported();
+ }
+
+ // Check for the real need to fetch the full header
+ static const int optionsRequiringHeader =
+ fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO |
+ fetchAttributes::FULL_HEADER | fetchAttributes::IMPORTANCE;
+
+ if (!options.has(optionsRequiringHeader)) {
+ return;
+ }
+
+ // No need to differenciate between ENVELOPE, CONTENT_INFO, ...
+ // since POP3 only permits to retrieve the whole header and not
+ // fields in particular.
+
+ // Emit the "TOP" command
+ shared_ptr <POP3Store> store = folder->m_store.lock();
+
+ POP3Command::TOP(m_num, 0)->send(store->getConnection());
+
+ try {
+
+ string buffer;
+ utility::outputStreamStringAdapter bufferStream(buffer);
+
+ POP3Response::readLargeResponse(
+ store->getConnection(),
+ bufferStream, /* progress */ NULL, /* predictedSize */ 0
+ );
+
+ m_header = make_shared <header>();
+ m_header->parse(buffer);
+
+ } catch (exceptions::command_error& e) {
+
+ throw exceptions::command_error("TOP", e.response());
+ }
+}
+
+
+void POP3Message::setFlags(const int /* flags */, const int /* mode */) {
+
+ throw exceptions::operation_not_supported();
+}
+
+
+shared_ptr <vmime::message> POP3Message::getParsedMessage() {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter os(oss);
+
+ extract(os);
+
+ shared_ptr <vmime::message> msg = make_shared <vmime::message>();
+ msg->parse(oss.str());
+
+ return msg;
+}
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
diff --git a/vmime-master/src/vmime/net/pop3/POP3Message.hpp b/vmime-master/src/vmime/net/pop3/POP3Message.hpp
new file mode 100644
index 0000000..3d6dc92
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Message.hpp
@@ -0,0 +1,124 @@
+//
+// 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_NET_POP3_POP3MESSAGE_HPP_INCLUDED
+#define VMIME_NET_POP3_POP3MESSAGE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/message.hpp"
+#include "vmime/net/folder.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+class POP3Folder;
+
+
+/** POP3 message implementation.
+ */
+class VMIME_EXPORT POP3Message : public message {
+
+private:
+
+ friend class POP3Folder;
+
+ POP3Message(const POP3Message&);
+
+public:
+
+ POP3Message(const shared_ptr <POP3Folder>& folder, const size_t num);
+
+ ~POP3Message();
+
+
+ size_t getNumber() const;
+
+ const uid getUID() const;
+
+ size_t getSize() const;
+
+ bool isExpunged() const;
+
+ shared_ptr <const messageStructure> getStructure() const;
+ shared_ptr <messageStructure> getStructure();
+
+ shared_ptr <const header> getHeader() const;
+
+ int getFlags() const;
+ void setFlags(const int flags, const int mode = FLAG_MODE_SET);
+
+ void extract(
+ utility::outputStream& os,
+ utility::progressListener* progress = NULL,
+ const size_t start = 0,
+ const size_t length = -1,
+ const bool peek = false
+ ) const;
+
+ void extractPart(
+ const shared_ptr <const messagePart>& p,
+ utility::outputStream& os,
+ utility::progressListener* progress = NULL,
+ const size_t start = 0,
+ const size_t length = -1,
+ const bool peek = false
+ ) const;
+
+ void fetchPartHeader(const shared_ptr <messagePart>& p);
+
+ shared_ptr <vmime::message> getParsedMessage();
+
+private:
+
+ void fetch(const shared_ptr <POP3Folder>& folder, const fetchAttributes& options);
+
+ void onFolderClosed();
+
+ weak_ptr <POP3Folder> m_folder;
+ size_t m_num;
+ uid m_uid;
+ size_t m_size;
+
+ bool m_deleted;
+
+ shared_ptr <header> m_header;
+};
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+#endif // VMIME_NET_POP3_POP3MESSAGE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/pop3/POP3Response.cpp b/vmime-master/src/vmime/net/pop3/POP3Response.cpp
new file mode 100644
index 0000000..725841e
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Response.cpp
@@ -0,0 +1,504 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/pop3/POP3Response.hpp"
+#include "vmime/net/pop3/POP3Connection.hpp"
+
+#include "vmime/platform.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+#include "vmime/utility/filteredStream.hpp"
+#include "vmime/utility/stringUtils.hpp"
+#include "vmime/utility/inputStreamSocketAdapter.hpp"
+
+#include "vmime/net/socket.hpp"
+#include "vmime/net/timeoutHandler.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+POP3Response::POP3Response(
+ const shared_ptr <socket>& sok,
+ const shared_ptr <timeoutHandler>& toh,
+ const shared_ptr <tracer>& tracer
+)
+ : m_socket(sok),
+ m_timeoutHandler(toh),
+ m_tracer(tracer) {
+
+}
+
+
+// static
+shared_ptr <POP3Response> POP3Response::readResponse(
+ const shared_ptr <POP3Connection>& conn
+) {
+
+ shared_ptr <POP3Response> resp = shared_ptr <POP3Response>(
+ new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer())
+ );
+
+ string buffer;
+ resp->readResponseImpl(buffer, /* multiLine */ false);
+
+ resp->m_firstLine = buffer;
+ resp->m_code = getResponseCode(buffer);
+ stripResponseCode(buffer, resp->m_text);
+
+ if (resp->m_tracer) {
+ resp->m_tracer->traceReceive(buffer);
+ }
+
+ return resp;
+}
+
+
+// static
+shared_ptr <POP3Response> POP3Response::readMultilineResponse(
+ const shared_ptr <POP3Connection>& conn
+) {
+
+ shared_ptr <POP3Response> resp = shared_ptr <POP3Response>(
+ new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer())
+ );
+
+ string buffer;
+ resp->readResponseImpl(buffer, /* multiLine */ true);
+
+ string firstLine, nextLines;
+ stripFirstLine(buffer, nextLines, &firstLine);
+
+ resp->m_firstLine = firstLine;
+ resp->m_code = getResponseCode(firstLine);
+ stripResponseCode(firstLine, resp->m_text);
+
+ std::istringstream iss(nextLines);
+ string line;
+
+ if (resp->m_tracer) {
+ resp->m_tracer->traceReceive(firstLine);
+ }
+
+ while (std::getline(iss, line, '\n')) {
+
+ line = utility::stringUtils::trim(line);
+ resp->m_lines.push_back(line);
+
+ if (resp->m_tracer) {
+ resp->m_tracer->traceReceive(line);
+ }
+ }
+
+ if (resp->m_tracer) {
+ resp->m_tracer->traceReceive(".");
+ }
+
+ return resp;
+}
+
+
+// static
+shared_ptr <POP3Response> POP3Response::readLargeResponse(
+ const shared_ptr <POP3Connection>& conn,
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t predictedSize
+) {
+
+ shared_ptr <POP3Response> resp = shared_ptr <POP3Response>(
+ new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer())
+ );
+
+ string firstLine;
+ const size_t length = resp->readResponseImpl(firstLine, os, progress, predictedSize);
+
+ resp->m_firstLine = firstLine;
+ resp->m_code = getResponseCode(firstLine);
+ stripResponseCode(firstLine, resp->m_text);
+
+ if (resp->m_tracer) {
+ resp->m_tracer->traceReceive(firstLine);
+ resp->m_tracer->traceReceiveBytes(length - firstLine.length());
+ resp->m_tracer->traceReceive(".");
+ }
+
+ return resp;
+}
+
+
+bool POP3Response::isSuccess() const {
+
+ return m_code == CODE_OK;
+}
+
+
+const string POP3Response::getFirstLine() const {
+
+ return m_firstLine;
+}
+
+
+POP3Response::ResponseCode POP3Response::getCode() const {
+
+ return m_code;
+}
+
+
+const string POP3Response::getText() const {
+
+ return m_text;
+}
+
+
+const string POP3Response::getLineAt(const size_t pos) const {
+
+ return m_lines[pos];
+}
+
+
+size_t POP3Response::getLineCount() const {
+
+ return m_lines.size();
+}
+
+
+void POP3Response::readResponseImpl(string& buffer, const bool multiLine) {
+
+ bool foundTerminator = false;
+
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ buffer.clear();
+
+ char last1 = '\0', last2 = '\0';
+
+ for ( ; !foundTerminator ; ) {
+
+ // Check whether the time-out delay is elapsed
+ if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+ throw exceptions::operation_timed_out();
+ }
+
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ // Receive data from the socket
+ string receiveBuffer;
+ m_socket->receive(receiveBuffer);
+
+ if (receiveBuffer.empty()) { // buffer is empty
+
+ if (m_socket->getStatus() & socket::STATUS_WANT_WRITE) {
+ m_socket->waitForWrite();
+ } else {
+ m_socket->waitForRead();
+ }
+
+ continue;
+ }
+
+ // We have received data: reset the time-out counter
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ // Check for transparent characters: '\n..' becomes '\n.'
+ const char first = receiveBuffer[0];
+
+ if (first == '.' && last2 == '\n' && last1 == '.') {
+
+ receiveBuffer.erase(receiveBuffer.begin());
+
+ } else if (receiveBuffer.length() >= 2 && first == '.' &&
+ receiveBuffer[1] == '.' && last1 == '\n') {
+
+ receiveBuffer.erase(receiveBuffer.begin());
+ }
+
+ for (size_t trans ;
+ string::npos != (trans = receiveBuffer.find("\n..")) ; ) {
+
+ receiveBuffer.replace(trans, 3, "\n.");
+ }
+
+ last1 = receiveBuffer[receiveBuffer.length() - 1];
+ last2 = static_cast <char>((receiveBuffer.length() >= 2) ? receiveBuffer[receiveBuffer.length() - 2] : 0);
+
+ // Append the data to the response buffer
+ buffer += receiveBuffer;
+
+ // Check for terminator string (and strip it if present)
+ foundTerminator = checkTerminator(buffer, multiLine);
+
+ // If there is an error (-ERR) when executing a command that
+ // requires a multi-line response, the error response will
+ // include only one line, so we stop waiting for a multi-line
+ // terminator and check for a "normal" one.
+ if (multiLine &&
+ !foundTerminator &&
+ buffer.length() >= 4 && buffer[0] == '-') {
+
+ foundTerminator = checkTerminator(buffer, false);
+ }
+ }
+}
+
+
+size_t POP3Response::readResponseImpl(
+ string& firstLine,
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t predictedSize
+) {
+
+ size_t current = 0, total = predictedSize;
+
+ string temp;
+ bool codeDone = false;
+
+ if (progress) {
+ progress->start(total);
+ }
+
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ utility::inputStreamSocketAdapter sis(*m_socket);
+ utility::stopSequenceFilteredInputStream <5> sfis1(sis, "\r\n.\r\n");
+ utility::stopSequenceFilteredInputStream <3> sfis2(sfis1, "\n.\n");
+ utility::dotFilteredInputStream dfis(sfis2); // "\n.." --> "\n."
+
+ utility::inputStream& is = dfis;
+
+ while (!is.eof()) {
+
+ // Check whether the time-out delay is elapsed
+ if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+ throw exceptions::operation_timed_out();
+ }
+ }
+
+ // Receive data from the socket
+ byte_t buffer[65536];
+ const size_t read = is.read(buffer, sizeof(buffer));
+
+ if (read == 0) { // buffer is empty
+
+ if (m_socket->getStatus() & socket::STATUS_WANT_WRITE) {
+ m_socket->waitForWrite();
+ } else if (m_socket->getStatus() & socket::STATUS_WANT_READ) {
+ m_socket->waitForRead();
+ } else {
+ // Input stream needs more bytes to continue, but there
+ // is enough data into socket buffer. Do not waitForRead(),
+ // just retry read()ing on the stream.
+ }
+
+ continue;
+ }
+
+ // We have received data: reset the time-out counter
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ // Notify progress
+ current += read;
+
+ if (progress) {
+ total = std::max(total, current);
+ progress->progress(current, total);
+ }
+
+ // If we don't have extracted the response code yet
+ if (!codeDone) {
+
+ vmime::utility::stringUtils::appendBytesToString(temp, buffer, read);
+
+ string responseData;
+
+ if (stripFirstLine(temp, responseData, &firstLine) == true) {
+
+ if (getResponseCode(firstLine) != CODE_OK) {
+ throw exceptions::command_error("?", firstLine);
+ }
+
+ codeDone = true;
+
+ os.write(responseData.data(), responseData.length());
+ temp.clear();
+
+ continue;
+ }
+
+ } else {
+
+ // Inject the data into the output stream
+ os.write(buffer, read);
+ }
+ }
+
+ if (progress) {
+ progress->stop(total);
+ }
+
+ return current;
+}
+
+
+// static
+bool POP3Response::stripFirstLine(
+ const string& buffer,
+ string& result,
+ string* firstLine
+) {
+
+ const size_t end = buffer.find('\n');
+
+ if (end != string::npos) {
+
+ if (firstLine) {
+ *firstLine = utility::stringUtils::trim(buffer.substr(0, end));
+ }
+
+ result = buffer.substr(end + 1);
+
+ return true;
+
+ } else {
+
+ if (firstLine) {
+ *firstLine = utility::stringUtils::trim(buffer);
+ }
+
+ result = "";
+
+ return false;
+ }
+}
+
+
+// static
+POP3Response::ResponseCode POP3Response::getResponseCode(const string& buffer) {
+
+ if (buffer.length() >= 2) {
+
+ // +[space]
+ if (buffer[0] == '+' &&
+ (buffer[1] == ' ' || buffer[1] == '\t')) {
+
+ return CODE_READY;
+ }
+
+ // +OK
+ if (buffer.length() >= 3) {
+
+ if (buffer[0] == '+' &&
+ (buffer[1] == 'O' || buffer[1] == 'o') &&
+ (buffer[2] == 'K' || buffer[1] == 'k')) {
+
+ return CODE_OK;
+ }
+ }
+ }
+
+ // -ERR or whatever
+ return CODE_ERR;
+}
+
+
+// static
+void POP3Response::stripResponseCode(const string& buffer, string& result) {
+
+ const size_t pos = buffer.find_first_of(" \t");
+
+ if (pos != string::npos) {
+ result = buffer.substr(pos + 1);
+ } else {
+ result = buffer;
+ }
+}
+
+
+// static
+bool POP3Response::checkTerminator(string& buffer, const bool multiLine) {
+
+ // Multi-line response
+ if (multiLine) {
+
+ static const string term1("\r\n.\r\n");
+ static const string term2("\n.\n");
+
+ return checkOneTerminator(buffer, term1) ||
+ checkOneTerminator(buffer, term2);
+
+ // Normal response
+ } else {
+
+ static const string term1("\r\n");
+ static const string term2("\n");
+
+ return checkOneTerminator(buffer, term1) ||
+ checkOneTerminator(buffer, term2);
+ }
+
+ return false;
+}
+
+
+// static
+bool POP3Response::checkOneTerminator(string& buffer, const string& term) {
+
+ if (buffer.length() >= term.length() &&
+ std::equal(buffer.end() - term.length(), buffer.end(), term.begin())) {
+
+ buffer.erase(buffer.end() - term.length(), buffer.end());
+ return true;
+ }
+
+ return false;
+}
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
diff --git a/vmime-master/src/vmime/net/pop3/POP3Response.hpp b/vmime-master/src/vmime/net/pop3/POP3Response.hpp
new file mode 100644
index 0000000..69f8d5d
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Response.hpp
@@ -0,0 +1,194 @@
+//
+// 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_NET_SMTP_POP3RESPONSE_HPP_INCLUDED
+#define VMIME_NET_SMTP_POP3RESPONSE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/object.hpp"
+#include "vmime/base.hpp"
+
+#include "vmime/utility/outputStream.hpp"
+#include "vmime/utility/progressListener.hpp"
+
+#include "vmime/net/socket.hpp"
+#include "vmime/net/tracer.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+class timeoutHandler;
+
+
+namespace pop3 {
+
+
+class POP3Connection;
+
+
+/** A POP3 response, as sent by the server.
+ */
+class VMIME_EXPORT POP3Response : public object {
+
+public:
+
+ /** Possible response codes. */
+ enum ResponseCode {
+ CODE_OK = 0,
+ CODE_READY,
+ CODE_ERR
+ };
+
+
+ /** Receive and parse a POP3 response from the
+ * specified connection.
+ *
+ * @param conn connection from which to read
+ * @return POP3 response
+ * @throws exceptions::operation_timed_out if no data
+ * has been received within the granted time
+ */
+ static shared_ptr <POP3Response> readResponse(const shared_ptr <POP3Connection>& conn);
+
+ /** Receive and parse a multiline POP3 response from
+ * the specified connection.
+ *
+ * @param conn connection from which to read
+ * @return POP3 response
+ * @throws exceptions::operation_timed_out if no data
+ * has been received within the granted time
+ */
+ static shared_ptr <POP3Response> readMultilineResponse(const shared_ptr <POP3Connection>& conn);
+
+ /** Receive and parse a large POP3 response (eg. message data)
+ * from the specified connection.
+ *
+ * @param conn connection from which to read
+ * @param os output stream to which response data will be written
+ * @param progress progress listener (can be NULL)
+ * @param predictedSize estimated size of response data (in bytes)
+ * @return POP3 response
+ * @throws exceptions::operation_timed_out if no data
+ * has been received within the granted time
+ */
+ static shared_ptr <POP3Response> readLargeResponse(
+ const shared_ptr <POP3Connection>& conn,
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t predictedSize
+ );
+
+
+ /** Returns whether the response is successful ("OK").
+ *
+ * @return true if the response if successful, false otherwise
+ */
+ bool isSuccess() const;
+
+ /** Return the POP3 response code.
+ *
+ * @return response code
+ */
+ ResponseCode getCode() const;
+
+ /** Return the POP3 response text (first line).
+ *
+ * @return response text
+ */
+ const string getText() const;
+
+ /** Return the first POP3 response line.
+ *
+ * @return first response line
+ */
+ const string getFirstLine() const;
+
+ /** Return the response line at the specified position.
+ *
+ * @param pos line index
+ * @return line at the specified index
+ */
+ const string getLineAt(const size_t pos) const;
+
+ /** Return the number of lines in the response.
+ *
+ * @return number of lines in the response
+ */
+ size_t getLineCount() const;
+
+private:
+
+ POP3Response(
+ const shared_ptr <socket>& sok,
+ const shared_ptr <timeoutHandler>& toh,
+ const shared_ptr <tracer>& tracer
+ );
+
+ void readResponseImpl(string& buffer, const bool multiLine);
+
+ size_t readResponseImpl(
+ string& firstLine,
+ utility::outputStream& os,
+ utility::progressListener* progress,
+ const size_t predictedSize
+ );
+
+
+ static bool stripFirstLine(const string& buffer, string& result, string* firstLine);
+
+ static ResponseCode getResponseCode(const string& buffer);
+
+ static void stripResponseCode(const string& buffer, string& result);
+
+ static bool checkTerminator(string& buffer, const bool multiLine);
+ static bool checkOneTerminator(string& buffer, const string& term);
+
+
+ shared_ptr <socket> m_socket;
+ shared_ptr <timeoutHandler> m_timeoutHandler;
+ shared_ptr <tracer> m_tracer;
+
+ string m_firstLine;
+ ResponseCode m_code;
+ string m_text;
+
+ std::vector <string> m_lines;
+};
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+#endif // VMIME_NET_SMTP_POP3RESPONSE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/pop3/POP3SStore.cpp b/vmime-master/src/vmime/net/pop3/POP3SStore.cpp
new file mode 100644
index 0000000..81a50bc
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3SStore.cpp
@@ -0,0 +1,82 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/pop3/POP3SStore.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+POP3SStore::POP3SStore(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+)
+ : POP3Store(sess, auth, true) {
+
+}
+
+
+POP3SStore::~POP3SStore() {
+
+}
+
+
+const string POP3SStore::getProtocolName() const {
+
+ return "pop3s";
+}
+
+
+
+// Service infos
+
+POP3ServiceInfos POP3SStore::sm_infos(true);
+
+
+const serviceInfos& POP3SStore::getInfosInstance() {
+
+ return sm_infos;
+}
+
+
+const serviceInfos& POP3SStore::getInfos() const {
+
+ return sm_infos;
+}
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
diff --git a/vmime-master/src/vmime/net/pop3/POP3SStore.hpp b/vmime-master/src/vmime/net/pop3/POP3SStore.hpp
new file mode 100644
index 0000000..76a6ee1
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3SStore.hpp
@@ -0,0 +1,74 @@
+//
+// 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_NET_POP3_POP3SSTORE_HPP_INCLUDED
+#define VMIME_NET_POP3_POP3SSTORE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/pop3/POP3Store.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+/** POP3S store service.
+ */
+class VMIME_EXPORT POP3SStore : public POP3Store {
+
+public:
+
+ POP3SStore(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+ );
+
+ ~POP3SStore();
+
+ const string getProtocolName() const;
+
+ static const serviceInfos& getInfosInstance();
+ const serviceInfos& getInfos() const;
+
+private:
+
+ static POP3ServiceInfos sm_infos;
+};
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+#endif // VMIME_NET_POP3_POP3SSTORE_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/pop3/POP3ServiceInfos.cpp b/vmime-master/src/vmime/net/pop3/POP3ServiceInfos.cpp
new file mode 100644
index 0000000..4deee74
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3ServiceInfos.cpp
@@ -0,0 +1,142 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/pop3/POP3ServiceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+POP3ServiceInfos::POP3ServiceInfos(const bool pop3s)
+ : m_pop3s(pop3s) {
+
+}
+
+
+const string POP3ServiceInfos::getPropertyPrefix() const {
+
+ if (m_pop3s) {
+ return "store.pop3s.";
+ } else {
+ return "store.pop3.";
+ }
+}
+
+
+const POP3ServiceInfos::props& POP3ServiceInfos::getProperties() const {
+
+ static props pop3Props = {
+ // POP3-specific options
+ property("options.apop", serviceInfos::property::TYPE_BOOLEAN, "true"),
+ property("options.apop.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"),
+#if VMIME_HAVE_SASL_SUPPORT
+ property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"),
+ property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"),
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ // Common properties
+ property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
+ property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
+
+#if VMIME_HAVE_TLS_SUPPORT
+ property(serviceInfos::property::CONNECTION_TLS),
+ property(serviceInfos::property::CONNECTION_TLS_REQUIRED),
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
+ property(serviceInfos::property::SERVER_PORT, "110"),
+ };
+
+ static props pop3sProps = {
+
+ // POP3-specific options
+ property("options.apop", serviceInfos::property::TYPE_BOOLEAN, "true"),
+ property("options.apop.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"),
+#if VMIME_HAVE_SASL_SUPPORT
+ property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"),
+ property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"),
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ // Common properties
+ property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
+ property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
+
+#if VMIME_HAVE_TLS_SUPPORT
+ property(serviceInfos::property::CONNECTION_TLS),
+ property(serviceInfos::property::CONNECTION_TLS_REQUIRED),
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
+ property(serviceInfos::property::SERVER_PORT, "995"),
+ };
+
+ return m_pop3s ? pop3sProps : pop3Props;
+}
+
+
+const std::vector <serviceInfos::property> POP3ServiceInfos::getAvailableProperties() const {
+
+ std::vector <property> list;
+ const props& p = getProperties();
+
+ // POP3-specific options
+ list.push_back(p.PROPERTY_OPTIONS_APOP);
+ list.push_back(p.PROPERTY_OPTIONS_APOP_FALLBACK);
+#if VMIME_HAVE_SASL_SUPPORT
+ list.push_back(p.PROPERTY_OPTIONS_SASL);
+ list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK);
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ // Common properties
+ list.push_back(p.PROPERTY_AUTH_USERNAME);
+ list.push_back(p.PROPERTY_AUTH_PASSWORD);
+
+#if VMIME_HAVE_TLS_SUPPORT
+ if (!m_pop3s) {
+ list.push_back(p.PROPERTY_CONNECTION_TLS);
+ list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED);
+ }
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ list.push_back(p.PROPERTY_SERVER_ADDRESS);
+ list.push_back(p.PROPERTY_SERVER_PORT);
+
+ return list;
+}
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
diff --git a/vmime-master/src/vmime/net/pop3/POP3ServiceInfos.hpp b/vmime-master/src/vmime/net/pop3/POP3ServiceInfos.hpp
new file mode 100644
index 0000000..590a6be
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3ServiceInfos.hpp
@@ -0,0 +1,91 @@
+//
+// 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_NET_POP3_POP3SERVICEINFOS_HPP_INCLUDED
+#define VMIME_NET_POP3_POP3SERVICEINFOS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/serviceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+/** Information about POP3 service.
+ */
+class VMIME_EXPORT POP3ServiceInfos : public serviceInfos {
+
+public:
+
+ POP3ServiceInfos(const bool pop3s);
+
+ struct props {
+ // POP3-specific options
+ serviceInfos::property PROPERTY_OPTIONS_APOP;
+ serviceInfos::property PROPERTY_OPTIONS_APOP_FALLBACK;
+#if VMIME_HAVE_SASL_SUPPORT
+ serviceInfos::property PROPERTY_OPTIONS_SASL;
+ serviceInfos::property PROPERTY_OPTIONS_SASL_FALLBACK;
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ // Common properties
+ serviceInfos::property PROPERTY_AUTH_USERNAME;
+ serviceInfos::property PROPERTY_AUTH_PASSWORD;
+
+#if VMIME_HAVE_TLS_SUPPORT
+ serviceInfos::property PROPERTY_CONNECTION_TLS;
+ serviceInfos::property PROPERTY_CONNECTION_TLS_REQUIRED;
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ serviceInfos::property PROPERTY_SERVER_ADDRESS;
+ serviceInfos::property PROPERTY_SERVER_PORT;
+ };
+
+ const props& getProperties() const;
+
+ const string getPropertyPrefix() const;
+ const std::vector <serviceInfos::property> getAvailableProperties() const;
+
+private:
+
+ const bool m_pop3s;
+};
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+#endif // VMIME_NET_POP3_POP3SERVICEINFOS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/pop3/POP3Store.cpp b/vmime-master/src/vmime/net/pop3/POP3Store.cpp
new file mode 100644
index 0000000..b06640f
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Store.cpp
@@ -0,0 +1,262 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/pop3/POP3Store.hpp"
+#include "vmime/net/pop3/POP3Folder.hpp"
+#include "vmime/net/pop3/POP3Command.hpp"
+#include "vmime/net/pop3/POP3Response.hpp"
+
+#include "vmime/exception.hpp"
+
+#include <algorithm>
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+POP3Store::POP3Store(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth,
+ const bool secured
+)
+ : store(sess, getInfosInstance(), auth),
+ m_isPOP3S(secured) {
+
+}
+
+
+POP3Store::~POP3Store() {
+
+ try {
+
+ if (isConnected()) {
+ disconnect();
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+const string POP3Store::getProtocolName() const {
+
+ return "pop3";
+}
+
+
+shared_ptr <folder> POP3Store::getDefaultFolder() {
+
+ if (!isConnected()) {
+ throw exceptions::illegal_state("Not connected");
+ }
+
+ return shared_ptr <POP3Folder>(
+ new POP3Folder(
+ folder::path(folder::path::component("INBOX")),
+ dynamicCast <POP3Store>(shared_from_this())
+ )
+ );
+}
+
+
+shared_ptr <folder> POP3Store::getRootFolder() {
+
+ if (!isConnected()) {
+ throw exceptions::illegal_state("Not connected");
+ }
+
+ return shared_ptr <POP3Folder>(
+ new POP3Folder(
+ folder::path(),
+ dynamicCast <POP3Store>(shared_from_this())
+ )
+ );
+}
+
+
+shared_ptr <folder> POP3Store::getFolder(const folder::path& path) {
+
+ if (!isConnected()) {
+ throw exceptions::illegal_state("Not connected");
+ }
+
+ return shared_ptr <POP3Folder>(
+ new POP3Folder(
+ path,
+ dynamicCast <POP3Store>(shared_from_this())
+ )
+ );
+}
+
+
+bool POP3Store::isValidFolderName(const folder::path::component& /* name */) const {
+
+ return true;
+}
+
+
+void POP3Store::connect() {
+
+ if (isConnected()) {
+ throw exceptions::already_connected();
+ }
+
+ m_connection = make_shared <POP3Connection>(
+ dynamicCast <POP3Store>(shared_from_this()), getAuthenticator()
+ );
+
+ m_connection->connect();
+}
+
+
+bool POP3Store::isPOP3S() const {
+
+ return m_isPOP3S;
+}
+
+
+bool POP3Store::isConnected() const {
+
+ return m_connection && m_connection->isConnected();
+}
+
+
+bool POP3Store::isSecuredConnection() const {
+
+ if (!m_connection) {
+ return false;
+ }
+
+ return m_connection->isSecuredConnection();
+}
+
+
+shared_ptr <connectionInfos> POP3Store::getConnectionInfos() const {
+
+ if (!m_connection) {
+ return null;
+ }
+
+ return m_connection->getConnectionInfos();
+}
+
+
+shared_ptr <POP3Connection> POP3Store::getConnection() {
+
+ return m_connection;
+}
+
+
+void POP3Store::disconnect() {
+
+ if (!isConnected()) {
+ throw exceptions::not_connected();
+ }
+
+ for (std::list <POP3Folder*>::iterator it = m_folders.begin() ;
+ it != m_folders.end() ; ++it) {
+
+ (*it)->onStoreDisconnected();
+ }
+
+ m_folders.clear();
+
+
+ m_connection->disconnect();
+ m_connection = null;
+}
+
+
+void POP3Store::noop() {
+
+ if (!m_connection) {
+ throw exceptions::not_connected();
+ }
+
+ POP3Command::NOOP()->send(m_connection);
+
+ shared_ptr <POP3Response> response = POP3Response::readResponse(m_connection);
+
+ if (!response->isSuccess()) {
+ throw exceptions::command_error("NOOP", response->getFirstLine());
+ }
+}
+
+
+void POP3Store::registerFolder(POP3Folder* folder) {
+
+ m_folders.push_back(folder);
+}
+
+
+void POP3Store::unregisterFolder(POP3Folder* folder) {
+
+ std::list <POP3Folder*>::iterator it = std::find(m_folders.begin(), m_folders.end(), folder);
+
+ if (it != m_folders.end()) {
+ m_folders.erase(it);
+ }
+}
+
+
+int POP3Store::getCapabilities() const {
+
+ return CAPABILITY_DELETE_MESSAGE;
+}
+
+
+
+// Service infos
+
+POP3ServiceInfos POP3Store::sm_infos(false);
+
+
+const serviceInfos& POP3Store::getInfosInstance() {
+
+ return sm_infos;
+}
+
+
+const serviceInfos& POP3Store::getInfos() const {
+
+ return sm_infos;
+}
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
diff --git a/vmime-master/src/vmime/net/pop3/POP3Store.hpp b/vmime-master/src/vmime/net/pop3/POP3Store.hpp
new file mode 100644
index 0000000..140a1ab
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Store.hpp
@@ -0,0 +1,120 @@
+//
+// 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_NET_POP3_POP3STORE_HPP_INCLUDED
+#define VMIME_NET_POP3_POP3STORE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/store.hpp"
+
+#include "vmime/net/pop3/POP3ServiceInfos.hpp"
+#include "vmime/net/pop3/POP3Connection.hpp"
+
+#include "vmime/utility/stream.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+class POP3Folder;
+class POP3Command;
+class POP3Response;
+
+
+/** POP3 store service.
+ */
+class VMIME_EXPORT POP3Store : public store {
+
+ friend class POP3Folder;
+ friend class POP3Message;
+
+public:
+
+ POP3Store(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth,
+ const bool secured = false
+ );
+
+ ~POP3Store();
+
+ const string getProtocolName() const;
+
+ shared_ptr <folder> getDefaultFolder();
+ shared_ptr <folder> getRootFolder();
+ shared_ptr <folder> getFolder(const folder::path& path);
+
+ bool isValidFolderName(const folder::path::component& name) const;
+
+ static const serviceInfos& getInfosInstance();
+ const serviceInfos& getInfos() const;
+
+ void connect();
+ bool isConnected() const;
+ void disconnect();
+
+ void noop();
+
+ int getCapabilities() const;
+
+ bool isSecuredConnection() const;
+ shared_ptr <connectionInfos> getConnectionInfos() const;
+ shared_ptr <POP3Connection> getConnection();
+
+ bool isPOP3S() const;
+
+private:
+
+ shared_ptr <POP3Connection> m_connection;
+
+
+ void registerFolder(POP3Folder* folder);
+ void unregisterFolder(POP3Folder* folder);
+
+ std::list <POP3Folder*> m_folders;
+
+
+ const bool m_isPOP3S;
+
+
+ // Service infos
+ static POP3ServiceInfos sm_infos;
+};
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+#endif // VMIME_NET_POP3_POP3STORE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/pop3/POP3Utils.cpp b/vmime-master/src/vmime/net/pop3/POP3Utils.cpp
new file mode 100644
index 0000000..b38161e
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Utils.cpp
@@ -0,0 +1,135 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include "vmime/net/pop3/POP3Utils.hpp"
+#include "vmime/net/pop3/POP3Response.hpp"
+
+#include <sstream>
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+// static
+void POP3Utils::parseMultiListOrUidlResponse(
+ const shared_ptr <POP3Response>& response,
+ std::map <size_t, string>& result
+) {
+
+ std::map <size_t, string> ids;
+
+ for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) {
+
+ string line = response->getLineAt(i);
+ string::iterator it = line.begin();
+
+ while (it != line.end() && (*it == ' ' || *it == '\t')) {
+ ++it;
+ }
+
+ if (it != line.end()) {
+
+ size_t number = 0;
+
+ while (it != line.end() && (*it >= '0' && *it <= '9')) {
+ number = (number * 10) + (*it - '0');
+ ++it;
+ }
+
+ while (it != line.end() && !(*it == ' ' || *it == '\t')) ++it;
+ while (it != line.end() && (*it == ' ' || *it == '\t')) ++it;
+
+ if (it != line.end()) {
+ result.insert(std::map <size_t, string>::value_type(number, string(it, line.end())));
+ }
+ }
+ }
+}
+
+
+
+class POP3MessageSetEnumerator : public messageSetEnumerator {
+
+public:
+
+ POP3MessageSetEnumerator(const size_t msgCount)
+ : m_msgCount(msgCount) {
+
+ }
+
+ void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) {
+
+ size_t last = range.getLast();
+
+ if (last == size_t(-1)) {
+ last = m_msgCount;
+ }
+
+ for (size_t i = range.getFirst() ; i <= last ; ++i) {
+ list.push_back(i);
+ }
+ }
+
+ void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) {
+
+ // Not supported
+ }
+
+public:
+
+ std::vector <size_t> list;
+
+private:
+
+ size_t m_msgCount;
+};
+
+
+// static
+const std::vector <size_t> POP3Utils::messageSetToNumberList(
+ const messageSet& msgs,
+ const size_t msgCount
+) {
+
+ POP3MessageSetEnumerator en(msgCount);
+ msgs.enumerate(en);
+
+ return en.list;
+}
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
diff --git a/vmime-master/src/vmime/net/pop3/POP3Utils.hpp b/vmime-master/src/vmime/net/pop3/POP3Utils.hpp
new file mode 100644
index 0000000..09d15d5
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/POP3Utils.hpp
@@ -0,0 +1,92 @@
+//
+// 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_NET_POP3_POP3UTILS_HPP_INCLUDED
+#define VMIME_NET_POP3_POP3UTILS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+
+#include <map>
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/messageSet.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace pop3 {
+
+
+class POP3Response;
+
+
+class VMIME_EXPORT POP3Utils {
+
+public:
+
+ /** Parse a response of type ([integer] [string] \n)*.
+ * This is used in LIST or UIDL commands:
+ *
+ * C: UIDL
+ * S: +OK
+ * S: 1 whqtswO00WBw418f9t5JxYwZ
+ * S: 2 QhdPYR:00WBw1Ph7x7
+ * S: .
+ *
+ * @param response raw response string as returned by the server
+ * @param result points to an associative array which maps a message
+ * number to its corresponding data (either UID or size)
+ */
+ static void parseMultiListOrUidlResponse(
+ const shared_ptr <POP3Response>& response,
+ std::map <size_t, string>& result
+ );
+
+ /** Returns a list of message numbers given a message set.
+ *
+ * @param msgs message set
+ * @param msgCount number of messages in folder
+ * @return list of message numbers
+ */
+ static const std::vector <size_t> messageSetToNumberList(
+ const messageSet& msgs,
+ const size_t msgCount
+ );
+};
+
+
+} // pop3
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3
+
+#endif // VMIME_NET_POP3_POP3UTILS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/pop3/pop3.hpp b/vmime-master/src/vmime/net/pop3/pop3.hpp
new file mode 100644
index 0000000..ced3a97
--- /dev/null
+++ b/vmime-master/src/vmime/net/pop3/pop3.hpp
@@ -0,0 +1,35 @@
+//
+// 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_NET_POP3_POP3_HPP_INCLUDED
+#define VMIME_NET_POP3_POP3_HPP_INCLUDED
+
+
+#include "vmime/net/pop3/POP3Folder.hpp"
+#include "vmime/net/pop3/POP3FolderStatus.hpp"
+#include "vmime/net/pop3/POP3Message.hpp"
+#include "vmime/net/pop3/POP3Store.hpp"
+#include "vmime/net/pop3/POP3SStore.hpp"
+
+
+#endif // VMIME_NET_POP3_POP3_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/securedConnectionInfos.hpp b/vmime-master/src/vmime/net/securedConnectionInfos.hpp
new file mode 100644
index 0000000..6025801
--- /dev/null
+++ b/vmime-master/src/vmime/net/securedConnectionInfos.hpp
@@ -0,0 +1,55 @@
+//
+// 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_NET_SECUREDCONNECTIONINFOS_HPP_INCLUDED
+#define VMIME_NET_SECUREDCONNECTIONINFOS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/connectionInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+/** Information about the secured connection used by a service.
+ */
+class VMIME_EXPORT securedConnectionInfos : public connectionInfos {
+
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_SECUREDCONNECTIONINFOS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/sendmail/sendmail.hpp b/vmime-master/src/vmime/net/sendmail/sendmail.hpp
new file mode 100644
index 0000000..a8d1412
--- /dev/null
+++ b/vmime-master/src/vmime/net/sendmail/sendmail.hpp
@@ -0,0 +1,31 @@
+//
+// 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_NET_SENDMAIL_SENDMAIL_HPP_INCLUDED
+#define VMIME_NET_SENDMAIL_SENDMAIL_HPP_INCLUDED
+
+
+#include "vmime/net/sendmail/sendmailTransport.hpp"
+
+
+#endif // VMIME_NET_SENDMAIL_SENDMAIL_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/sendmail/sendmailServiceInfos.cpp b/vmime-master/src/vmime/net/sendmail/sendmailServiceInfos.cpp
new file mode 100644
index 0000000..b865446
--- /dev/null
+++ b/vmime-master/src/vmime/net/sendmail/sendmailServiceInfos.cpp
@@ -0,0 +1,77 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SENDMAIL
+
+
+#include "vmime/net/sendmail/sendmailServiceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace sendmail {
+
+
+sendmailServiceInfos::sendmailServiceInfos() {
+
+}
+
+
+const string sendmailServiceInfos::getPropertyPrefix() const {
+
+ return "transport.sendmail.";
+}
+
+
+const sendmailServiceInfos::props& sendmailServiceInfos::getProperties() const {
+
+ static props sendmailProps = {
+ // Path to sendmail (override default)
+ property("binpath", serviceInfos::property::TYPE_STRING, string(VMIME_SENDMAIL_PATH))
+ };
+
+ return sendmailProps;
+}
+
+
+const std::vector <serviceInfos::property> sendmailServiceInfos::getAvailableProperties() const {
+
+ std::vector <property> list;
+ const props& p = getProperties();
+
+ list.push_back(p.PROPERTY_BINPATH);
+
+ return list;
+}
+
+
+} // sendmail
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SENDMAIL
+
diff --git a/vmime-master/src/vmime/net/sendmail/sendmailServiceInfos.hpp b/vmime-master/src/vmime/net/sendmail/sendmailServiceInfos.hpp
new file mode 100644
index 0000000..bfec2e0
--- /dev/null
+++ b/vmime-master/src/vmime/net/sendmail/sendmailServiceInfos.hpp
@@ -0,0 +1,69 @@
+//
+// 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_NET_SENDMAIL_SENDMAILSERVICEINFOS_HPP_INCLUDED
+#define VMIME_NET_SENDMAIL_SENDMAILSERVICEINFOS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SENDMAIL
+
+
+#include "vmime/net/serviceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace sendmail {
+
+
+/** Information about sendmail service.
+ */
+class VMIME_EXPORT sendmailServiceInfos : public serviceInfos {
+
+public:
+
+ sendmailServiceInfos();
+
+ struct props {
+ serviceInfos::property PROPERTY_BINPATH;
+ };
+
+ const props& getProperties() const;
+
+ const string getPropertyPrefix() const;
+ const std::vector <serviceInfos::property> getAvailableProperties() const;
+};
+
+
+} // sendmail
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SENDMAIL
+
+#endif // VMIME_NET_SENDMAIL_SENDMAILSERVICEINFOS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/sendmail/sendmailTransport.cpp b/vmime-master/src/vmime/net/sendmail/sendmailTransport.cpp
new file mode 100644
index 0000000..7010fd8
--- /dev/null
+++ b/vmime-master/src/vmime/net/sendmail/sendmailTransport.cpp
@@ -0,0 +1,244 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SENDMAIL
+
+
+#include "vmime/net/sendmail/sendmailTransport.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/platform.hpp"
+#include "vmime/message.hpp"
+#include "vmime/mailboxList.hpp"
+
+#include "vmime/utility/filteredStream.hpp"
+#include "vmime/utility/childProcess.hpp"
+
+#include "vmime/utility/streamUtils.hpp"
+
+#include "vmime/net/defaultConnectionInfos.hpp"
+
+#include "vmime/config.hpp"
+
+
+// Helpers for service properties
+#define GET_PROPERTY(type, prop) \
+ (getInfos().getPropertyValue <type>(getSession(), \
+ dynamic_cast <const sendmailServiceInfos&>(getInfos()).getProperties().prop))
+#define HAS_PROPERTY(prop) \
+ (getInfos().hasProperty(getSession(), \
+ dynamic_cast <const sendmailServiceInfos&>(getInfos()).getProperties().prop))
+
+
+namespace vmime {
+namespace net {
+namespace sendmail {
+
+
+sendmailTransport::sendmailTransport(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+)
+ : transport(sess, getInfosInstance(), auth),
+ m_connected(false) {
+
+}
+
+
+sendmailTransport::~sendmailTransport() {
+
+ try {
+
+ if (isConnected()) {
+ disconnect();
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+const string sendmailTransport::getProtocolName() const {
+
+ return "sendmail";
+}
+
+
+void sendmailTransport::connect() {
+
+ if (isConnected()) {
+ throw exceptions::already_connected();
+ }
+
+ // Use the specified path for 'sendmail' or a default one if no path is specified
+ m_sendmailPath = GET_PROPERTY(string, PROPERTY_BINPATH);
+
+ m_connected = true;
+}
+
+
+bool sendmailTransport::isConnected() const {
+
+ return m_connected;
+}
+
+
+bool sendmailTransport::isSecuredConnection() const {
+
+ return false;
+}
+
+
+shared_ptr <connectionInfos> sendmailTransport::getConnectionInfos() const {
+
+ return make_shared <defaultConnectionInfos>("localhost", static_cast <port_t>(0));
+}
+
+
+void sendmailTransport::disconnect() {
+
+ if (!isConnected()) {
+ throw exceptions::not_connected();
+ }
+
+ internalDisconnect();
+}
+
+
+void sendmailTransport::internalDisconnect() {
+
+ m_connected = false;
+}
+
+
+void sendmailTransport::noop() {
+
+ // Do nothing
+}
+
+
+void sendmailTransport::send(
+ const mailbox& expeditor,
+ const mailboxList& recipients,
+ utility::inputStream& is,
+ const size_t size,
+ utility::progressListener* progress,
+ const mailbox& sender,
+ const dsnAttributes& /*dsnAttrs*/
+) {
+
+ // If no recipient/expeditor was found, throw an exception
+ if (recipients.isEmpty()) {
+ throw exceptions::no_recipient();
+ } else if (expeditor.isEmpty()) {
+ throw exceptions::no_expeditor();
+ }
+
+ // Construct the argument list
+ std::vector <string> args;
+
+ args.push_back("-i");
+ args.push_back("-f");
+
+ if (!sender.isEmpty()) {
+ args.push_back(expeditor.getEmail().generate());
+ } else {
+ args.push_back(sender.getEmail().generate());
+ }
+
+ args.push_back("--");
+
+ for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) {
+ args.push_back(recipients.getMailboxAt(i)->getEmail().generate());
+ }
+
+ // Call sendmail
+ try {
+ internalSend(args, is, size, progress);
+ } catch (vmime::exception& e) {
+ throw exceptions::command_error("SEND", "", "sendmail failed", e);
+ }
+}
+
+
+void sendmailTransport::internalSend(
+ const std::vector <string>& args,
+ utility::inputStream& is,
+ const size_t size,
+ utility::progressListener* progress
+) {
+
+ const utility::file::path path = vmime::platform::getHandler()->
+ getFileSystemFactory()->stringToPath(m_sendmailPath);
+
+ shared_ptr <utility::childProcess> proc =
+ vmime::platform::getHandler()->getChildProcessFactory()->create(path);
+
+ proc->start(args, utility::childProcess::FLAG_REDIRECT_STDIN);
+
+ // Copy message data from input stream to output pipe
+ utility::outputStream& os = *(proc->getStdIn());
+
+ // Workaround for lame sendmail implementations that
+ // can't handle CRLF eoln sequences: we transform CRLF
+ // sequences into LF characters.
+ utility::CRLFToLFFilteredOutputStream fos(os);
+
+ // TODO: remove 'Bcc:' field from message header
+
+ utility::bufferedStreamCopy(is, fos, size, progress);
+
+ // Wait for sendmail to exit
+ proc->waitForFinish();
+}
+
+
+// Service infos
+
+sendmailServiceInfos sendmailTransport::sm_infos;
+
+
+const serviceInfos& sendmailTransport::getInfosInstance() {
+
+ return sm_infos;
+}
+
+
+const serviceInfos& sendmailTransport::getInfos() const {
+
+ return sm_infos;
+}
+
+
+} // sendmail
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SENDMAIL
+
diff --git a/vmime-master/src/vmime/net/sendmail/sendmailTransport.hpp b/vmime-master/src/vmime/net/sendmail/sendmailTransport.hpp
new file mode 100644
index 0000000..ce2cfe9
--- /dev/null
+++ b/vmime-master/src/vmime/net/sendmail/sendmailTransport.hpp
@@ -0,0 +1,112 @@
+//
+// 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_NET_SENDMAIL_SENDMAILTRANSPORT_HPP_INCLUDED
+#define VMIME_NET_SENDMAIL_SENDMAILTRANSPORT_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SENDMAIL
+
+
+#include "vmime/net/transport.hpp"
+#include "vmime/net/socket.hpp"
+#include "vmime/net/timeoutHandler.hpp"
+
+#include "vmime/net/sendmail/sendmailServiceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace sendmail {
+
+
+/** Sendmail local transport service.
+ */
+class VMIME_EXPORT sendmailTransport : public transport {
+
+public:
+
+ sendmailTransport(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+ );
+
+ ~sendmailTransport();
+
+ const string getProtocolName() const;
+
+ static const serviceInfos& getInfosInstance();
+ const serviceInfos& getInfos() const;
+
+ void connect();
+ bool isConnected() const;
+ void disconnect();
+
+ void noop();
+
+ void send(
+ const mailbox& expeditor,
+ const mailboxList& recipients,
+ utility::inputStream& is,
+ const size_t size,
+ utility::progressListener* progress = NULL,
+ const mailbox& sender = mailbox(),
+ const dsnAttributes& dsnAttrs = dsnAttributes()
+ );
+
+ bool isSecuredConnection() const;
+ shared_ptr <connectionInfos> getConnectionInfos() const;
+
+private:
+
+ void internalDisconnect();
+
+ void internalSend(
+ const std::vector <string>& args,
+ utility::inputStream& is,
+ const size_t size,
+ utility::progressListener* progress
+ );
+
+
+ string m_sendmailPath;
+
+ bool m_connected;
+
+
+ // Service infos
+ static sendmailServiceInfos sm_infos;
+};
+
+
+} // sendmail
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SENDMAIL
+
+#endif // VMIME_NET_SENDMAIL_SENDMAILTRANSPORT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/service.cpp b/vmime-master/src/vmime/net/service.cpp
new file mode 100644
index 0000000..b43c3e2
--- /dev/null
+++ b/vmime-master/src/vmime/net/service.cpp
@@ -0,0 +1,170 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/service.hpp"
+
+#include "vmime/platform.hpp"
+
+#include "vmime/net/defaultTimeoutHandler.hpp"
+
+#if VMIME_HAVE_SASL_SUPPORT
+ #include "vmime/security/sasl/defaultSASLAuthenticator.hpp"
+#else
+ #include "vmime/security/defaultAuthenticator.hpp"
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+#if VMIME_HAVE_TLS_SUPPORT
+ #include "vmime/security/cert/defaultCertificateVerifier.hpp"
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+namespace vmime {
+namespace net {
+
+
+service::service(
+ const shared_ptr <session>& sess,
+ const serviceInfos& /* infos */,
+ const shared_ptr <security::authenticator>& auth
+)
+ : m_session(sess),
+ m_auth(auth) {
+
+ if (!auth) {
+
+#if VMIME_HAVE_SASL_SUPPORT
+ m_auth = make_shared <security::sasl::defaultSASLAuthenticator>();
+#else
+ m_auth = make_shared <security::defaultAuthenticator>();
+#endif // VMIME_HAVE_SASL_SUPPORT
+ }
+
+#if VMIME_HAVE_TLS_SUPPORT
+ m_certVerifier = make_shared <security::cert::defaultCertificateVerifier>();
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ m_socketFactory = platform::getHandler()->getSocketFactory();
+
+ m_toHandlerFactory = make_shared <defaultTimeoutHandlerFactory>();
+}
+
+
+service::~service() {
+
+}
+
+
+shared_ptr <const session> service::getSession() const {
+
+ return m_session;
+}
+
+
+shared_ptr <session> service::getSession() {
+
+ return m_session;
+}
+
+
+shared_ptr <const security::authenticator> service::getAuthenticator() const {
+
+ return m_auth;
+}
+
+
+shared_ptr <security::authenticator> service::getAuthenticator() {
+
+ return m_auth;
+}
+
+
+void service::setAuthenticator(const shared_ptr <security::authenticator>& auth) {
+
+ m_auth = auth;
+}
+
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+void service::setCertificateVerifier(const shared_ptr <security::cert::certificateVerifier>& cv) {
+
+ m_certVerifier = cv;
+}
+
+
+shared_ptr <security::cert::certificateVerifier> service::getCertificateVerifier() {
+
+ return m_certVerifier;
+}
+
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+void service::setSocketFactory(const shared_ptr <socketFactory>& sf) {
+
+ m_socketFactory = sf;
+}
+
+
+shared_ptr <socketFactory> service::getSocketFactory() {
+
+ return m_socketFactory;
+}
+
+
+void service::setTracerFactory(const shared_ptr <tracerFactory>& tf) {
+
+ m_tracerFactory = tf;
+}
+
+
+shared_ptr <tracerFactory> service::getTracerFactory() {
+
+ return m_tracerFactory;
+}
+
+
+void service::setTimeoutHandlerFactory(const shared_ptr <timeoutHandlerFactory>& thf) {
+
+ m_toHandlerFactory = thf;
+}
+
+
+shared_ptr <timeoutHandlerFactory> service::getTimeoutHandlerFactory() {
+
+ return m_toHandlerFactory;
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
diff --git a/vmime-master/src/vmime/net/service.hpp b/vmime-master/src/vmime/net/service.hpp
new file mode 100644
index 0000000..a1869de
--- /dev/null
+++ b/vmime-master/src/vmime/net/service.hpp
@@ -0,0 +1,239 @@
+//
+// 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_NET_SERVICE_HPP_INCLUDED
+#define VMIME_NET_SERVICE_HPP_INCLUDED
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/session.hpp"
+
+#include "vmime/net/serviceInfos.hpp"
+#include "vmime/net/connectionInfos.hpp"
+
+#include "vmime/net/socket.hpp"
+#include "vmime/net/timeoutHandler.hpp"
+#include "vmime/net/tracer.hpp"
+
+#if VMIME_HAVE_TLS_SUPPORT
+ #include "vmime/security/cert/certificateVerifier.hpp"
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+#include "vmime/utility/progressListener.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+/** Base class for messaging services.
+ */
+class VMIME_EXPORT service : public object, public enable_shared_from_this <service> {
+
+protected:
+
+ service(
+ const shared_ptr <session>& sess,
+ const serviceInfos& infos,
+ const shared_ptr <security::authenticator>& auth
+ );
+
+public:
+
+ virtual ~service();
+
+ /** Possible service types. */
+ enum Type {
+ TYPE_STORE = 0, /**< The service is a message store. */
+ TYPE_TRANSPORT /**< The service sends messages. */
+ };
+
+ /** Return the type of service.
+ *
+ * @return type of service
+ */
+ virtual Type getType() const = 0;
+
+ /** Return the protocol name of this service.
+ *
+ * @return protocol name
+ */
+ virtual const string getProtocolName() const = 0;
+
+ /** Return the session object associated with this service instance.
+ *
+ * @return session object
+ */
+ shared_ptr <const session> getSession() const;
+
+ /** Return the session object associated with this service instance.
+ *
+ * @return session object
+ */
+ shared_ptr <session> getSession();
+
+ /** Return information about this service.
+ *
+ * @return information about the service
+ */
+ virtual const serviceInfos& getInfos() const = 0;
+
+ /** Connect to service.
+ */
+ virtual void connect() = 0;
+
+ /** Disconnect from service.
+ */
+ virtual void disconnect() = 0;
+
+ /** Test whether this service is connected.
+ *
+ * @return true if the service is connected, false otherwise
+ */
+ virtual bool isConnected() const = 0;
+
+ /** Do nothing but ensure the server do not disconnect (for
+ * example, this can reset the auto-logout timer on the
+ * server, if one exists).
+ */
+ virtual void noop() = 0;
+
+ /** Return the authenticator object used with this service instance.
+ *
+ * @return authenticator object
+ */
+ shared_ptr <const security::authenticator> getAuthenticator() const;
+
+ /** Return the authenticator object used with this service instance.
+ *
+ * @return authenticator object
+ */
+ shared_ptr <security::authenticator> getAuthenticator();
+
+ /** Set the authenticator object used with this service instance.
+ *
+ * @param auth authenticator object
+ */
+ void setAuthenticator(const shared_ptr <security::authenticator>& auth);
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+ /** Set the object responsible for verifying certificates when
+ * using secured connections (TLS/SSL).
+ */
+ void setCertificateVerifier(const shared_ptr <security::cert::certificateVerifier>& cv);
+
+ /** Get the object responsible for verifying certificates when
+ * using secured connections (TLS/SSL).
+ */
+ shared_ptr <security::cert::certificateVerifier> getCertificateVerifier();
+
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ /** Set the factory used to create socket objects for this
+ * service.
+ *
+ * @param sf socket factory
+ */
+ void setSocketFactory(const shared_ptr <socketFactory>& sf);
+
+ /** Return the factory used to create socket objects for this
+ * service.
+ *
+ * @return socket factory
+ */
+ shared_ptr <socketFactory> getSocketFactory();
+
+ /** Set the factory used to create timeoutHandler objects for
+ * this service. By default, the defaultTimeoutHandler class
+ * is used. Not all services support timeout handling.
+ *
+ * @param thf timeoutHandler factory
+ */
+ void setTimeoutHandlerFactory(const shared_ptr <timeoutHandlerFactory>& thf);
+
+ /** Return the factory used to create timeoutHandler objects for
+ * this service.
+ *
+ * @return timeoutHandler factory
+ */
+ shared_ptr <timeoutHandlerFactory> getTimeoutHandlerFactory();
+
+
+ void setTracerFactory(const shared_ptr <tracerFactory>& tf);
+
+ shared_ptr <tracerFactory> getTracerFactory();
+
+ /** Set a property for this service (service prefix is added automatically).
+ *
+ * WARNING: this sets the property on the session object, so all service
+ * instances created with the session object will inherit the property.
+ *
+ * @param name property name
+ * @param value property value
+ */
+ template <typename TYPE>
+ void setProperty(const string& name, const TYPE& value) {
+ m_session->getProperties()[getInfos().getPropertyPrefix() + name] = value;
+ }
+
+ /** Check whether the connection is secured.
+ *
+ * @return true if the connection is secured, false otherwise
+ */
+ virtual bool isSecuredConnection() const = 0;
+
+ /** Get information about the connection.
+ *
+ * @return information about the connection
+ */
+ virtual shared_ptr <connectionInfos> getConnectionInfos() const = 0;
+
+private:
+
+ shared_ptr <session> m_session;
+ shared_ptr <security::authenticator> m_auth;
+
+#if VMIME_HAVE_TLS_SUPPORT
+ shared_ptr <security::cert::certificateVerifier> m_certVerifier;
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ shared_ptr <socketFactory> m_socketFactory;
+ shared_ptr <timeoutHandlerFactory> m_toHandlerFactory;
+ shared_ptr <tracerFactory> m_tracerFactory;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_SERVICE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/serviceFactory.cpp b/vmime-master/src/vmime/net/serviceFactory.cpp
new file mode 100644
index 0000000..72b96fe
--- /dev/null
+++ b/vmime-master/src/vmime/net/serviceFactory.cpp
@@ -0,0 +1,157 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/serviceFactory.hpp"
+#include "vmime/net/service.hpp"
+
+#include "vmime/exception.hpp"
+
+#include "vmime/net/builtinServices.inl"
+
+
+namespace vmime {
+namespace net {
+
+
+serviceFactory::serviceFactory() {
+
+}
+
+
+serviceFactory::~serviceFactory() {
+
+}
+
+
+shared_ptr <serviceFactory> serviceFactory::getInstance() {
+
+ static serviceFactory instance;
+ return shared_ptr <serviceFactory>(&instance, noop_shared_ptr_deleter <serviceFactory>());
+}
+
+
+shared_ptr <service> serviceFactory::create(
+ const shared_ptr <session>& sess,
+ const string& protocol,
+ const shared_ptr <security::authenticator>& auth
+) {
+
+ shared_ptr <const registeredService> rserv = getServiceByProtocol(protocol);
+
+ if (!rserv) {
+ throw exceptions::no_factory_available("No service is registered for protocol '" + protocol + "'.");
+ }
+
+ return rserv->create(sess, auth);
+}
+
+
+shared_ptr <service> serviceFactory::create(
+ const shared_ptr <session>& sess,
+ const utility::url& u,
+ const shared_ptr <security::authenticator>& auth
+) {
+
+ shared_ptr <service> serv = create(sess, u.getProtocol(), auth);
+
+ sess->getProperties()[serv->getInfos().getPropertyPrefix() + "server.address"] = u.getHost();
+
+ if (u.getPort() != utility::url::UNSPECIFIED_PORT) {
+ sess->getProperties()[serv->getInfos().getPropertyPrefix() + "server.port"] = u.getPort();
+ }
+
+ // Path portion of the URL is used to point a specific folder (empty = root).
+ // In maildir, this is used to point to the root of the message repository.
+ if (!u.getPath().empty()) {
+ sess->getProperties()[serv->getInfos().getPropertyPrefix() + "server.rootpath"] = u.getPath();
+ }
+
+ if (!u.getUsername().empty()) {
+ sess->getProperties()[serv->getInfos().getPropertyPrefix() + "auth.username"] = u.getUsername();
+ sess->getProperties()[serv->getInfos().getPropertyPrefix() + "auth.password"] = u.getPassword();
+ }
+
+ return serv;
+}
+
+
+shared_ptr <const serviceFactory::registeredService> serviceFactory::getServiceByProtocol(const string& protocol) const {
+
+ const string name(utility::stringUtils::toLower(protocol));
+
+ for (std::vector <shared_ptr <registeredService> >::const_iterator it = m_services.begin() ;
+ it != m_services.end() ; ++it) {
+
+ if ((*it)->getName() == name) {
+ return (*it);
+ }
+ }
+
+ return null;
+}
+
+
+size_t serviceFactory::getServiceCount() const {
+
+ return m_services.size();
+}
+
+
+shared_ptr <const serviceFactory::registeredService> serviceFactory::getServiceAt(const size_t pos) const {
+
+ return m_services[pos];
+}
+
+
+const std::vector <shared_ptr <const serviceFactory::registeredService> > serviceFactory::getServiceList() const {
+
+ std::vector <shared_ptr <const registeredService> > res;
+
+ for (std::vector <shared_ptr <registeredService> >::const_iterator it = m_services.begin() ;
+ it != m_services.end() ; ++it) {
+
+ res.push_back(*it);
+ }
+
+ return (res);
+}
+
+
+void serviceFactory::registerService(const shared_ptr <registeredService>& reg) {
+
+ m_services.push_back(reg);
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
diff --git a/vmime-master/src/vmime/net/serviceFactory.hpp b/vmime-master/src/vmime/net/serviceFactory.hpp
new file mode 100644
index 0000000..8911e08
--- /dev/null
+++ b/vmime-master/src/vmime/net/serviceFactory.hpp
@@ -0,0 +1,168 @@
+//
+// 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_NET_SERVICEFACTORY_HPP_INCLUDED
+#define VMIME_NET_SERVICEFACTORY_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include <map>
+
+#include "vmime/types.hpp"
+#include "vmime/base.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+#include "vmime/utility/url.hpp"
+
+#include "vmime/net/service.hpp"
+#include "vmime/net/serviceInfos.hpp"
+#include "vmime/net/timeoutHandler.hpp"
+
+#include "vmime/security/authenticator.hpp"
+
+#include "vmime/utility/progressListener.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+class session;
+
+
+/** A factory to create 'service' objects for a specified protocol.
+ */
+
+class VMIME_EXPORT serviceFactory {
+
+private:
+
+ serviceFactory();
+ ~serviceFactory();
+
+public:
+
+ static shared_ptr <serviceFactory> getInstance();
+
+ /** Information about a registered service. */
+ class registeredService : public object {
+
+ friend class serviceFactory;
+
+ protected:
+
+ virtual ~registeredService() { }
+
+ public:
+
+ virtual shared_ptr <service> create(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+ ) const = 0;
+
+ virtual int getType() const = 0;
+ virtual const string& getName() const = 0;
+ virtual const serviceInfos& getInfos() const = 0;
+ };
+
+
+ /** Register a new service by its protocol name.
+ *
+ * @param reg service registration infos
+ */
+ void registerService(const shared_ptr <registeredService>& reg);
+
+ /** Create a new service instance from a protocol name.
+ *
+ * @param sess session
+ * @param protocol protocol name (eg. "pop3")
+ * @param auth authenticator used to provide credentials (can be NULL if not used)
+ * @return a new service instance for the specified protocol, or NULL if no service
+ * is registered for this protocol
+ */
+ shared_ptr <service> create(
+ const shared_ptr <session>& sess,
+ const string& protocol,
+ const shared_ptr <security::authenticator>& auth = null
+ );
+
+ /** Create a new service instance from a URL.
+ *
+ * @param sess session
+ * @param u full URL with at least protocol and server (you can also specify
+ * port, username and password)
+ * @param auth authenticator used to provide credentials (can be NULL if not used)
+ * @return a new service instance for the specified protocol or NULL if no service
+ * is registered for this protocol
+ */
+ shared_ptr <service> create(
+ const shared_ptr <session>& sess,
+ const utility::url& u,
+ const shared_ptr <security::authenticator>& auth = null
+ );
+
+ /** Return information about a registered protocol.
+ *
+ * @param protocol protocol name
+ * @return information about this protocol, or NULL if no service is registered
+ * for this protocol
+ */
+ shared_ptr <const registeredService> getServiceByProtocol(const string& protocol) const;
+
+ /** Return the number of registered services.
+ *
+ * @return number of registered services
+ */
+ size_t getServiceCount() const;
+
+ /** Return the registered service at the specified position.
+ *
+ * @param pos position of the registered service to return
+ * @return registered service at the specified position
+ */
+ shared_ptr <const registeredService> getServiceAt(const size_t pos) const;
+
+ /** Return a list of all registered services.
+ *
+ * @return list of registered services
+ */
+ const std::vector <shared_ptr <const registeredService> > getServiceList() const;
+
+private:
+
+ std::vector <shared_ptr <registeredService> > m_services;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_SERVICEFACTORY_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/serviceInfos.cpp b/vmime-master/src/vmime/net/serviceInfos.cpp
new file mode 100644
index 0000000..2c7b044
--- /dev/null
+++ b/vmime-master/src/vmime/net/serviceInfos.cpp
@@ -0,0 +1,198 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/serviceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+// Common properties
+const serviceInfos::property serviceInfos::property::SERVER_ADDRESS(
+ "server.address",
+ serviceInfos::property::TYPE_STRING
+);
+
+const serviceInfos::property serviceInfos::property::SERVER_PORT(
+ "server.port",
+ serviceInfos::property::TYPE_INTEGER
+);
+
+const serviceInfos::property serviceInfos::property::SERVER_ROOTPATH(
+ "server.rootpath",
+ serviceInfos::property::TYPE_STRING
+);
+
+const serviceInfos::property serviceInfos::property::AUTH_USERNAME(
+ "auth.username",
+ serviceInfos::property::TYPE_STRING
+);
+
+const serviceInfos::property serviceInfos::property::AUTH_PASSWORD(
+ "auth.password",
+ serviceInfos::property::TYPE_STRING
+);
+
+const serviceInfos::property serviceInfos::property::AUTH_ACCESS_TOKEN(
+ "auth.accesstoken",
+ serviceInfos::property::TYPE_STRING
+);
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+const serviceInfos::property serviceInfos::property::CONNECTION_TLS(
+ "connection.tls",
+ serviceInfos::property::TYPE_BOOLEAN,
+ "false"
+);
+
+const serviceInfos::property serviceInfos::property::CONNECTION_TLS_REQUIRED(
+ "connection.tls.required",
+ serviceInfos::property::TYPE_BOOLEAN,
+ "false"
+);
+
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+
+// serviceInfos
+
+serviceInfos::serviceInfos() {
+
+}
+
+
+serviceInfos::serviceInfos(const serviceInfos&) {
+
+}
+
+
+serviceInfos& serviceInfos::operator=(const serviceInfos&) {
+
+ return *this;
+}
+
+
+serviceInfos::~serviceInfos() {
+
+}
+
+
+bool serviceInfos::hasProperty(const shared_ptr <session>& s, const property& p) const {
+ return s->getProperties().hasProperty(getPropertyPrefix() + p.getName());
+}
+
+
+
+// serviceInfos::property
+
+serviceInfos::property::property(
+ const string& name,
+ const Types type,
+ const string& defaultValue,
+ const int flags
+)
+ : m_name(name),
+ m_defaultValue(defaultValue),
+ m_type(type),
+ m_flags(flags) {
+
+}
+
+
+serviceInfos::property::property(
+ const property& p,
+ const int addFlags,
+ const int removeFlags
+) {
+
+ m_name = p.m_name;
+ m_type = p.m_type;
+ m_defaultValue = p.m_defaultValue;
+ m_flags = (p.m_flags | addFlags) & ~removeFlags;
+}
+
+
+serviceInfos::property::property(
+ const property& p,
+ const string& newDefaultValue,
+ const int addFlags,
+ const int removeFlags
+) {
+
+ m_name = p.m_name;
+ m_type = p.m_type;
+ m_defaultValue = newDefaultValue;
+ m_flags = (p.m_flags | addFlags) & ~removeFlags;
+}
+
+
+serviceInfos::property& serviceInfos::property::operator=(const property& p) {
+
+ m_name = p.m_name;
+ m_type = p.m_type;
+ m_defaultValue = p.m_defaultValue;
+ m_flags = p.m_flags;
+
+ return *this;
+}
+
+
+const string& serviceInfos::property::getName() const {
+
+ return m_name;
+}
+
+
+const string& serviceInfos::property::getDefaultValue() const {
+
+ return m_defaultValue;
+}
+
+
+serviceInfos::property::Types serviceInfos::property::getType() const {
+
+ return m_type;
+}
+
+
+int serviceInfos::property::getFlags() const {
+
+ return m_flags;
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
diff --git a/vmime-master/src/vmime/net/serviceInfos.hpp b/vmime-master/src/vmime/net/serviceInfos.hpp
new file mode 100644
index 0000000..1c4ac99
--- /dev/null
+++ b/vmime-master/src/vmime/net/serviceInfos.hpp
@@ -0,0 +1,263 @@
+//
+// 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_NET_SERVICEINFOS_HPP_INCLUDED
+#define VMIME_NET_SERVICEINFOS_HPP_INCLUDED
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include <vector>
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/session.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+/** Stores information about a messaging service.
+ */
+class VMIME_EXPORT serviceInfos {
+
+ friend class serviceFactory;
+
+protected:
+
+ serviceInfos();
+ serviceInfos(const serviceInfos&);
+
+private:
+
+ serviceInfos& operator=(const serviceInfos&);
+
+public:
+
+ virtual ~serviceInfos();
+
+
+ /** A service property.
+ */
+ class VMIME_EXPORT property {
+
+ public:
+
+ /** The common property 'server.address' which is
+ * the host name or the IP address of the server. */
+ static const property SERVER_ADDRESS;
+
+ /** The common property 'server.port' which is
+ * the port used to connect to the server. */
+ static const property SERVER_PORT;
+
+ /** The common property 'server.rootpath' which is
+ * the full path of the folder on the server (for
+ * maildir, this is the local filesystem directory). */
+ static const property SERVER_ROOTPATH;
+
+ /** The common property 'auth.username' which is the
+ * username used to authenticate with the server. */
+ static const property AUTH_USERNAME;
+
+ /** The common property 'auth.password' which is the
+ * password used to authenticate with the server. */
+ static const property AUTH_PASSWORD;
+
+ /** The common property 'auth.accesstoken' which is the
+ * access token used to authenticate with the server. */
+ static const property AUTH_ACCESS_TOKEN;
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+ /** The common property 'connection.tls': this is used to
+ * start a secured connection if it is supported by the
+ * server (STARTTLS extension).
+ */
+ static const property CONNECTION_TLS;
+
+ /** The common property 'connection.tls.required' should be
+ * set to 'true' to make the connection process fail if the
+ * server can't start a secured connection (no effect if
+ * 'connection.tls' is not set to 'true').
+ */
+ static const property CONNECTION_TLS_REQUIRED;
+
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+ /** Value types.
+ */
+ enum Types {
+ TYPE_INTEGER, /*< Integer number. */
+ TYPE_STRING, /*< Character string. */
+ TYPE_BOOLEAN, /*< Boolean (true or false). */
+
+ TYPE_DEFAULT = TYPE_STRING
+ };
+
+ /** Property flags.
+ */
+ enum Flags {
+ FLAG_NONE = 0, /*< No flags. */
+ FLAG_REQUIRED = (1 << 0), /*< The property must be valued. */
+ FLAG_HIDDEN = (1 << 1), /*< The property should not be shown
+ to the user but can be modified. */
+
+ FLAG_DEFAULT = FLAG_NONE /*< Default flags. */
+ };
+
+
+ /** Construct a new property.
+ *
+ * @param name property name
+ * @param type value type
+ * @param defaultValue default value
+ * @param flags property attributes
+ */
+ property(
+ const string& name,
+ const Types type,
+ const string& defaultValue = "",
+ const int flags = FLAG_DEFAULT
+ );
+
+ /** Construct a new property from an existing property.
+ *
+ * @param p source property
+ * @param addFlags flags to add
+ * @param removeFlags flags to remove
+ */
+ property(
+ const property& p,
+ const int addFlags = FLAG_NONE,
+ const int removeFlags = FLAG_NONE
+ );
+
+ /** Construct a new property from an existing property.
+ *
+ * @param p source property
+ * @param newDefaultValue new default value
+ * @param addFlags flags to add
+ * @param removeFlags flags to remove
+ */
+ property(
+ const property& p,
+ const string& newDefaultValue,
+ const int addFlags = FLAG_NONE,
+ const int removeFlags = FLAG_NONE
+ );
+
+ property& operator=(const property& p);
+
+ /** Return the name of the property.
+ *
+ * @return property name
+ */
+ const string& getName() const;
+
+ /** Return the default value of the property or
+ * an empty string if there is no default value.
+ *
+ * @return default value for the property
+ */
+ const string& getDefaultValue() const;
+
+ /** Return the value type of the property.
+ *
+ * @return property value type
+ */
+ Types getType() const;
+
+ /** Return the attributes of the property (see
+ * serviceInfos::property::Types constants).
+ *
+ * @return property attributes
+ */
+ int getFlags() const;
+
+ private:
+
+ string m_name;
+ string m_defaultValue;
+ Types m_type;
+ int m_flags;
+ };
+
+
+ /** Return the property prefix used by this service.
+ * Use this to set/get properties in the session object.
+ *
+ * @return property prefix
+ */
+ virtual const string getPropertyPrefix() const = 0;
+
+ /** Return a list of available properties for this service.
+ *
+ * @return list of properties
+ */
+ virtual const std::vector <property> getAvailableProperties() const = 0;
+
+ /** Helper function to retrieve the value of a property.
+ *
+ * @param s session object
+ * @param p property to retrieve
+ * @throw exceptions::no_such_property if the property does not exist
+ * and has the flag property::FLAG_REQUIRED
+ * @return value of the property
+ */
+ template <typename TYPE>
+ const TYPE getPropertyValue(const shared_ptr <session>& s, const property& p) const {
+
+ if (p.getFlags() & property::FLAG_REQUIRED) {
+ return s->getProperties()[getPropertyPrefix() + p.getName()].template getValue <TYPE>();
+ }
+
+ return s->getProperties().template getProperty <TYPE>(
+ getPropertyPrefix() + p.getName(),
+ propertySet::valueFromString <TYPE>(p.getDefaultValue())
+ );
+ }
+
+ /** Helper function to test if the specified property is set in
+ * the session object.
+ *
+ * @param s session object
+ * @param p property to test
+ * @return true if the property is set, false otherwise
+ */
+ bool hasProperty(const shared_ptr <session>& s, const property& p) const;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_SERVICEINFOS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/serviceRegistration.inl b/vmime-master/src/vmime/net/serviceRegistration.inl
new file mode 100644
index 0000000..9365199
--- /dev/null
+++ b/vmime-master/src/vmime/net/serviceRegistration.inl
@@ -0,0 +1,105 @@
+//
+// 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.
+//
+
+#include "vmime/net/serviceFactory.hpp"
+
+
+#ifndef VMIME_BUILDING_DOC
+
+
+namespace vmime {
+namespace net {
+
+
+template <class S>
+class registeredServiceImpl : public serviceFactory::registeredService {
+
+public:
+
+ registeredServiceImpl(
+ const string& name,
+ const int type
+ )
+ : m_type(type),
+ m_name(name),
+ m_servInfos(S::getInfosInstance()) {
+
+ }
+
+ shared_ptr <service> create(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+ ) const {
+
+ return make_shared <S>(sess, auth);
+ }
+
+ const serviceInfos& getInfos() const {
+
+ return m_servInfos;
+ }
+
+ const string& getName() const {
+
+ return m_name;
+ }
+
+ int getType() const {
+
+ return m_type;
+ }
+
+private:
+
+ const int m_type;
+ const string m_name;
+ const serviceInfos& m_servInfos;
+};
+
+
+// Basic service registerer
+template <class S>
+class serviceRegisterer {
+
+public:
+
+ serviceRegisterer(const string& protocol, const service::Type type) {
+
+ serviceFactory::getInstance()->registerService(
+ make_shared <registeredServiceImpl <S> >(protocol, type)
+ );
+ }
+};
+
+
+} // net
+} // vmime
+
+
+#define REGISTER_SERVICE(p_class, p_name, p_type) \
+ vmime::net::serviceRegisterer <vmime::net::p_class> \
+ p_name(#p_name, vmime::net::service::p_type)
+
+
+#endif // VMIME_BUILDING_DOC
+
diff --git a/vmime-master/src/vmime/net/session.cpp b/vmime-master/src/vmime/net/session.cpp
new file mode 100644
index 0000000..d4b13b4
--- /dev/null
+++ b/vmime-master/src/vmime/net/session.cpp
@@ -0,0 +1,188 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/session.hpp"
+#include "vmime/net/serviceFactory.hpp"
+
+#include "vmime/net/store.hpp"
+#include "vmime/net/transport.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+session::session() {
+
+#if VMIME_HAVE_TLS_SUPPORT
+ m_tlsProps = make_shared <tls::TLSProperties>();
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+}
+
+
+session::session(const propertySet& props)
+ : m_props(props) {
+
+#if VMIME_HAVE_TLS_SUPPORT
+ m_tlsProps = make_shared <tls::TLSProperties>();
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+}
+
+
+session::~session() {
+
+}
+
+
+// static
+shared_ptr <session> session::create() {
+
+ return shared_ptr <session>(new session());
+}
+
+
+// static
+shared_ptr <session> session::create(const propertySet& props) {
+
+ return shared_ptr <session>(new session(props));
+}
+
+
+shared_ptr <transport> session::getTransport(const shared_ptr <security::authenticator>& auth) {
+
+ return getTransport(m_props["transport.protocol"], auth);
+}
+
+
+shared_ptr <transport> session::getTransport(
+ const string& protocol,
+ const shared_ptr <security::authenticator>& auth
+) {
+
+ shared_ptr <session> sess(dynamicCast <session>(shared_from_this()));
+ shared_ptr <service> sv = serviceFactory::getInstance()->create(sess, protocol, auth);
+
+ if (!sv || sv->getType() != service::TYPE_TRANSPORT) {
+ return null;
+ }
+
+ return dynamicCast <transport>(sv);
+}
+
+
+shared_ptr <transport> session::getTransport(
+ const utility::url& url,
+ const shared_ptr <security::authenticator>& auth
+) {
+
+ shared_ptr <session> sess(dynamicCast <session>(shared_from_this()));
+ shared_ptr <service> sv = serviceFactory::getInstance()->create(sess, url, auth);
+
+ if (!sv || sv->getType() != service::TYPE_TRANSPORT) {
+ return null;
+ }
+
+ return dynamicCast <transport>(sv);
+}
+
+
+shared_ptr <store> session::getStore(const shared_ptr <security::authenticator>& auth) {
+
+ return getStore(m_props["store.protocol"], auth);
+}
+
+
+shared_ptr <store> session::getStore(
+ const string& protocol,
+ const shared_ptr <security::authenticator>& auth
+) {
+
+ shared_ptr <session> sess(dynamicCast <session>(shared_from_this()));
+ shared_ptr <service> sv = serviceFactory::getInstance()->create(sess, protocol, auth);
+
+ if (!sv || sv->getType() != service::TYPE_STORE) {
+ return null;
+ }
+
+ return dynamicCast <store>(sv);
+}
+
+
+shared_ptr <store> session::getStore(
+ const utility::url& url,
+ const shared_ptr <security::authenticator>& auth
+) {
+
+ shared_ptr <session> sess(dynamicCast <session>(shared_from_this()));
+ shared_ptr <service> sv = serviceFactory::getInstance()->create(sess, url, auth);
+
+ if (!sv || sv->getType() != service::TYPE_STORE) {
+ return null;
+ }
+
+ return dynamicCast <store>(sv);
+}
+
+
+const propertySet& session::getProperties() const {
+
+ return m_props;
+}
+
+
+propertySet& session::getProperties() {
+
+ return m_props;
+}
+
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+void session::setTLSProperties(const shared_ptr <tls::TLSProperties>& tlsProps) {
+
+ m_tlsProps = make_shared <tls::TLSProperties>(*tlsProps);
+}
+
+
+shared_ptr <tls::TLSProperties> session::getTLSProperties() const {
+
+ return m_tlsProps;
+}
+
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
diff --git a/vmime-master/src/vmime/net/session.hpp b/vmime-master/src/vmime/net/session.hpp
new file mode 100644
index 0000000..7ccd0be
--- /dev/null
+++ b/vmime-master/src/vmime/net/session.hpp
@@ -0,0 +1,206 @@
+//
+// 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_NET_SESSION_HPP_INCLUDED
+#define VMIME_NET_SESSION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/security/authenticator.hpp"
+
+#if VMIME_HAVE_TLS_SUPPORT
+# include "vmime/net/tls/TLSProperties.hpp"
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+#include "vmime/utility/url.hpp"
+
+#include "vmime/propertySet.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+class store;
+class transport;
+
+
+/** An object that contains all the information needed
+ * for connection to a service.
+ */
+class VMIME_EXPORT session : public object, public enable_shared_from_this <session> {
+
+public:
+
+ /** Construct a new session.
+ *
+ * @return pointer to a new session
+ */
+ static shared_ptr <session> create();
+
+ /** Construct a new session given properties.
+ *
+ * @param props session properties
+ * @return pointer to a new session
+ */
+ static shared_ptr <session> create(const propertySet& props);
+
+ ~session();
+
+ /** Return a transport service instance for the protocol specified
+ * in the session properties.
+ *
+ * The property "transport.protocol" specify the protocol to use.
+ *
+ * @param auth authenticator object to use for the new transport service. If
+ * NULL, a default one is used. The default authenticator simply return user
+ * credentials by reading the session properties "auth.username" and "auth.password".
+ * @return a new transport service, or NULL if no service is registered for this
+ * protocol or is not a transport protocol
+ */
+ shared_ptr <transport> getTransport(
+ const shared_ptr <security::authenticator>& auth = null
+ );
+
+ /** Return a transport service instance for the specified protocol.
+ *
+ * @param protocol transport protocol to use (eg. "smtp")
+ * @param auth authenticator object to use for the new transport service. If
+ * NULL, a default one is used. The default authenticator simply return user
+ * credentials by reading the session properties "auth.username" and "auth.password".
+ * @return a new transport service, or NULL if no service is registered for this
+ * protocol or is not a transport protocol
+ */
+ shared_ptr <transport> getTransport(
+ const string& protocol,
+ const shared_ptr <security::authenticator>& auth = null
+ );
+
+ /** Return a transport service instance for the specified URL.
+ *
+ * @param url full URL with at least the protocol to use (eg: "smtp://myserver.com/")
+ * @param auth authenticator object to use for the new transport service. If
+ * NULL, a default one is used. The default authenticator simply return user
+ * credentials by reading the session properties "auth.username" and "auth.password".
+ * @return a new transport service, or NULL if no service is registered for this
+ * protocol or is not a transport protocol
+ */
+ shared_ptr <transport> getTransport(
+ const utility::url& url,
+ const shared_ptr <security::authenticator>& auth = null
+ );
+
+ /** Return a transport service instance for the protocol specified
+ * in the session properties.
+ *
+ * The property "store.protocol" specify the protocol to use.
+ *
+ * @param auth authenticator object to use for the new store service. If
+ * NULL, a default one is used. The default authenticator simply return user
+ * credentials by reading the session properties "auth.username" and "auth.password".
+ * @return a new store service, or NULL if no service is registered for this
+ * protocol or is not a store protocol
+ */
+ shared_ptr <store> getStore(
+ const shared_ptr <security::authenticator>& auth = null
+ );
+
+ /** Return a store service instance for the specified protocol.
+ *
+ * @param protocol store protocol to use (eg. "imap")
+ * @param auth authenticator object to use for the new store service. If
+ * NULL, a default one is used. The default authenticator simply return user
+ * credentials by reading the session properties "auth.username" and "auth.password".
+ * @return a new store service, or NULL if no service is registered for this
+ * protocol or is not a store protocol
+ */
+ shared_ptr <store> getStore(
+ const string& protocol,
+ const shared_ptr <security::authenticator>& auth = null
+ );
+
+ /** Return a store service instance for the specified URL.
+ *
+ * @param url full URL with at least the protocol to use (eg: "imap://username:password@myserver.com/")
+ * @param auth authenticator object to use for the new store service. If
+ * NULL, a default one is used. The default authenticator simply return user
+ * credentials by reading the session properties "auth.username" and "auth.password".
+ * @return a new store service, or NULL if no service is registered for this
+ * protocol or is not a store protocol
+ */
+ shared_ptr <store> getStore(
+ const utility::url& url,
+ const shared_ptr <security::authenticator>& auth = null
+ );
+
+ /** Properties for the session and for the services.
+ */
+ const propertySet& getProperties() const;
+
+ /** Properties for the session and for the services.
+ */
+ propertySet& getProperties();
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+ /** Set properties for SSL/TLS secured connections in this session.
+ *
+ * @param tlsProps SSL/TLS properties
+ */
+ void setTLSProperties(const shared_ptr <tls::TLSProperties>& tlsProps);
+
+ /** Get properties for SSL/TLS secured connections in this session.
+ *
+ * @return SSL/TLS properties
+ */
+ shared_ptr <tls::TLSProperties> getTLSProperties() const;
+
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+private:
+
+ session();
+ session(const propertySet& props);
+
+
+ propertySet m_props;
+
+#if VMIME_HAVE_TLS_SUPPORT
+ shared_ptr <tls::TLSProperties> m_tlsProps;
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_SESSION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp b/vmime-master/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp
new file mode 100644
index 0000000..3b242d1
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp
@@ -0,0 +1,180 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp"
+
+#include "vmime/net/smtp/SMTPConnection.hpp"
+#include "vmime/net/smtp/SMTPTransport.hpp"
+
+#include <algorithm>
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+SMTPChunkingOutputStreamAdapter::SMTPChunkingOutputStreamAdapter(
+ const shared_ptr <SMTPConnection>& conn,
+ const size_t size,
+ utility::progressListener* progress
+)
+ : m_connection(conn),
+ m_bufferSize(0),
+ m_chunkCount(0),
+ m_totalSize(size),
+ m_totalSent(0),
+ m_progress(progress) {
+
+ if (progress) {
+ progress->start(size);
+ }
+}
+
+
+void SMTPChunkingOutputStreamAdapter::sendChunk(
+ const byte_t* const data,
+ const size_t count,
+ const bool last
+) {
+
+ if (count == 0 && !last) {
+ // Nothing to send
+ return;
+ }
+
+ // Send this chunk
+ m_connection->sendRequest(SMTPCommand::BDAT(count, last));
+ m_connection->getSocket()->sendRaw(data, count);
+
+ ++m_chunkCount;
+
+ if (m_progress) {
+
+ m_totalSent += count;
+ m_totalSize = std::max(m_totalSize, m_totalSent);
+
+ m_progress->progress(m_totalSent, m_totalSize);
+ }
+
+ if (m_connection->getTracer()) {
+ m_connection->getTracer()->traceSendBytes(count);
+ }
+
+ // If PIPELINING is not supported, read one response for this BDAT command
+ if (!m_connection->hasExtension("PIPELINING")) {
+
+ shared_ptr <SMTPResponse> resp = m_connection->readResponse();
+
+ if (resp->getCode() != 250) {
+ m_connection->getTransport()->disconnect();
+ throw exceptions::command_error("BDAT", resp->getText());
+ }
+
+ // If PIPELINING is supported, read one response for each chunk (ie. number
+ // of BDAT commands issued) after the last chunk has been sent
+ } else if (last) {
+
+ bool invalidReply = false;
+ shared_ptr <SMTPResponse> resp;
+
+ for (unsigned int i = 0 ; i < m_chunkCount ; ++i) {
+
+ resp = m_connection->readResponse();
+
+ if (resp->getCode() != 250) {
+ invalidReply = true;
+ }
+ }
+
+ if (invalidReply) {
+ m_connection->getTransport()->disconnect();
+ throw exceptions::command_error("BDAT", resp->getText());
+ }
+ }
+}
+
+
+void SMTPChunkingOutputStreamAdapter::writeImpl(
+ const byte_t* const data,
+ const size_t count
+) {
+
+ const byte_t* curData = data;
+ size_t curCount = count;
+
+ while (curCount != 0) {
+
+ // Fill the buffer
+ const size_t remaining = sizeof(m_buffer) - m_bufferSize;
+ const size_t bytesToCopy = std::min(remaining, curCount);
+
+ std::copy(curData, curData + bytesToCopy, m_buffer + m_bufferSize);
+
+ m_bufferSize += bytesToCopy;
+ curData += bytesToCopy;
+ curCount -= bytesToCopy;
+
+ // If the buffer is full, send this chunk
+ if (m_bufferSize >= sizeof(m_buffer)) {
+
+ sendChunk(m_buffer, m_bufferSize, /* last */ false);
+ m_bufferSize = 0;
+ }
+ }
+}
+
+
+void SMTPChunkingOutputStreamAdapter::flush() {
+
+ sendChunk(m_buffer, m_bufferSize, /* last */ true);
+ m_bufferSize = 0;
+
+ if (m_progress) {
+ m_progress->stop(m_totalSize);
+ }
+
+ if (m_connection->getTracer()) {
+ m_connection->getTracer()->traceSendBytes(m_bufferSize);
+ }
+}
+
+
+size_t SMTPChunkingOutputStreamAdapter::getBlockSize() {
+
+ return sizeof(m_buffer);
+}
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
diff --git a/vmime-master/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp b/vmime-master/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp
new file mode 100644
index 0000000..4ef466a
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp
@@ -0,0 +1,94 @@
+//
+// 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_NET_SMTP_SMTPCHUNKINGOUTPUTSTREAMADAPTER_HPP_INCLUDED
+#define VMIME_NET_SMTP_SMTPCHUNKINGOUTPUTSTREAMADAPTER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/utility/outputStream.hpp"
+#include "vmime/utility/progressListener.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+class SMTPConnection;
+
+
+/** An output stream adapter used with ESMTP CHUNKING extension.
+ */
+class VMIME_EXPORT SMTPChunkingOutputStreamAdapter : public utility::outputStream {
+
+public:
+
+ SMTPChunkingOutputStreamAdapter(
+ const shared_ptr <SMTPConnection>& conn,
+ const size_t size,
+ utility::progressListener* progress
+ );
+
+ void flush();
+
+ size_t getBlockSize();
+
+protected:
+
+ void writeImpl(const byte_t* const data, const size_t count);
+
+private:
+
+ SMTPChunkingOutputStreamAdapter(const SMTPChunkingOutputStreamAdapter&);
+
+
+ void sendChunk(const byte_t* const data, const size_t count, const bool last);
+
+
+ shared_ptr <SMTPConnection> m_connection;
+
+ byte_t m_buffer[262144]; // 256 KB
+ size_t m_bufferSize;
+
+ unsigned int m_chunkCount;
+
+ size_t m_totalSize;
+ size_t m_totalSent;
+ utility::progressListener* m_progress;
+};
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+#endif // VMIME_NET_SMTP_SMTPCHUNKINGOUTPUTSTREAMADAPTER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/smtp/SMTPCommand.cpp b/vmime-master/src/vmime/net/smtp/SMTPCommand.cpp
new file mode 100644
index 0000000..5e533d1
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPCommand.cpp
@@ -0,0 +1,258 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/net/smtp/SMTPCommand.hpp"
+
+#include "vmime/net/socket.hpp"
+#include "vmime/net/tracer.hpp"
+
+#include "vmime/mailbox.hpp"
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+SMTPCommand::SMTPCommand(const string& text, const string& traceText)
+ : m_text(text),
+ m_traceText(traceText)
+{
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::EHLO(const string& hostname) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "EHLO " << hostname;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::HELO(const string& hostname) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "HELO " << hostname;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::AUTH(const string& mechName) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "AUTH " << mechName;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::AUTH(const string& mechName, const std::string& initialResponse) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "AUTH " << mechName << " " << initialResponse;
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::STARTTLS() {
+
+ return createCommand("STARTTLS");
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox, const bool utf8,
+ const std::string& dsnRet, const std::string& dsnEnvelopId) {
+
+ return MAIL(mbox, utf8, 0, dsnRet, dsnEnvelopId);
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox, const bool utf8, const size_t size,
+ const std::string& dsnRet, const std::string& dsnEnvelopId) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "MAIL FROM:<";
+
+ if (utf8) {
+
+ cmd << mbox.getEmail().toText().getConvertedText(vmime::charsets::UTF_8);
+
+ } else {
+
+ vmime::utility::outputStreamAdapter cmd2(cmd);
+ mbox.getEmail().generate(cmd2);
+ }
+
+ cmd << ">";
+
+ if (!dsnRet.empty()) {
+ cmd << " " << dsn::RET << "=" << dsnRet;
+ }
+ if (!dsnEnvelopId.empty()) {
+ cmd << " " << dsn::ENVID << "=<" << dsnEnvelopId << ">";
+ }
+
+ if (utf8) {
+ cmd << " SMTPUTF8";
+ }
+
+ if (size != 0) {
+ cmd << " SIZE=" << size;
+ }
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::RCPT(const mailbox& mbox, const bool utf8,
+ const string& dsnNotify) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "RCPT TO:<";
+
+ if (utf8) {
+
+ cmd << mbox.getEmail().toText().getConvertedText(vmime::charsets::UTF_8);
+
+ } else {
+
+ vmime::utility::outputStreamAdapter cmd2(cmd);
+ mbox.getEmail().generate(cmd2);
+ }
+
+ cmd << ">";
+
+ if (!dsnNotify.empty()) {
+ cmd << " " << dsn::NOTIFY << "=" << dsnNotify;
+ }
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::RSET() {
+
+ return createCommand("RSET");
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::DATA() {
+
+ return createCommand("DATA");
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::BDAT(const size_t chunkSize, const bool last) {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+ cmd << "BDAT " << chunkSize;
+
+ if (last) {
+ cmd << " LAST";
+ }
+
+ return createCommand(cmd.str());
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::NOOP() {
+
+ return createCommand("NOOP");
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::QUIT() {
+
+ return createCommand("QUIT");
+}
+
+
+// static
+shared_ptr <SMTPCommand> SMTPCommand::createCommand(const string& text, const string& traceText) {
+
+ if (traceText.empty()) {
+ return shared_ptr <SMTPCommand>(new SMTPCommand(text, text));
+ } else {
+ return shared_ptr <SMTPCommand>(new SMTPCommand(text, traceText));
+ }
+}
+
+
+const string SMTPCommand::getText() const {
+
+ return m_text;
+}
+
+
+const string SMTPCommand::getTraceText() const {
+
+ return m_traceText;
+}
+
+
+void SMTPCommand::writeToSocket(const shared_ptr <socket>& sok, shared_ptr <tracer> tr) {
+
+ sok->send(m_text + "\r\n");
+
+ if (tr) {
+ tr->traceSend(m_traceText);
+ }
+}
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
diff --git a/vmime-master/src/vmime/net/smtp/SMTPCommand.hpp b/vmime-master/src/vmime/net/smtp/SMTPCommand.hpp
new file mode 100644
index 0000000..9a32d1e
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPCommand.hpp
@@ -0,0 +1,125 @@
+//
+// 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_NET_SMTP_SMTPCOMMAND_HPP_INCLUDED
+#define VMIME_NET_SMTP_SMTPCOMMAND_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/object.hpp"
+#include "vmime/base.hpp"
+
+
+namespace vmime {
+
+
+class mailbox;
+
+
+namespace net {
+
+
+class socket;
+class timeoutHandler;
+class tracer;
+
+
+namespace smtp {
+
+
+/** A SMTP command, as sent to server.
+ */
+class VMIME_EXPORT SMTPCommand : public object {
+
+public:
+
+ static shared_ptr <SMTPCommand> HELO(const string& hostname);
+ static shared_ptr <SMTPCommand> EHLO(const string& hostname);
+ static shared_ptr <SMTPCommand> AUTH(const string& mechName);
+ static shared_ptr <SMTPCommand> AUTH(const string& mechName, const std::string& initialResponse);
+ static shared_ptr <SMTPCommand> STARTTLS();
+ static shared_ptr <SMTPCommand> MAIL(const mailbox& mbox, const bool utf8,
+ const std::string& dsnRet, const std::string& dsnEnvelopId);
+ static shared_ptr <SMTPCommand> MAIL(const mailbox& mbox, const bool utf8, const size_t size,
+ const std::string& dsnRet, const std::string& dsnEnvelopId);
+ static shared_ptr <SMTPCommand> RCPT(const mailbox& mbox, const bool utf8,
+ const std::string& dsnNotify);
+ static shared_ptr <SMTPCommand> RSET();
+ static shared_ptr <SMTPCommand> DATA();
+ static shared_ptr <SMTPCommand> BDAT(const size_t chunkSize, const bool last);
+ static shared_ptr <SMTPCommand> NOOP();
+ static shared_ptr <SMTPCommand> QUIT();
+
+ /** Creates a new SMTP command with the specified text.
+ *
+ * @param text command text
+ * @return a new SMTPCommand object
+ */
+ static shared_ptr <SMTPCommand> createCommand(const string& text, const string& traceText = "");
+
+ /** Sends this command to the specified socket.
+ *
+ * @param sok socket to which the command will be written
+ * @param tr tracer
+ */
+ virtual void writeToSocket(const shared_ptr <socket>& sok, shared_ptr <tracer> tr);
+
+ /** Returns the full text of the command, including command name
+ * and parameters (if any).
+ *
+ * @return command text (eg. "RCPT TO:<vincent@kisli.com>")
+ */
+ virtual const string getText() const;
+
+ /** Returns the full text of the command, suitable for outputing
+ * to the tracer.
+ *
+ * @return trace text (eg. "LOGIN myusername ***")
+ */
+ virtual const string getTraceText() const;
+
+protected:
+
+ SMTPCommand(const string& text, const string& traceText);
+ SMTPCommand(const SMTPCommand&);
+
+private:
+
+ string m_text;
+ string m_traceText;
+};
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+#endif // VMIME_NET_SMTP_SMTPCOMMAND_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/smtp/SMTPCommandSet.cpp b/vmime-master/src/vmime/net/smtp/SMTPCommandSet.cpp
new file mode 100644
index 0000000..eab7086
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPCommandSet.cpp
@@ -0,0 +1,160 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/net/smtp/SMTPCommandSet.hpp"
+
+#include "vmime/net/socket.hpp"
+
+#include "vmime/mailbox.hpp"
+
+#include <stdexcept>
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+SMTPCommandSet::SMTPCommandSet(const bool pipeline)
+ : SMTPCommand("", ""),
+ m_pipeline(pipeline),
+ m_started(false),
+ m_lastCommandSent() {
+
+}
+
+
+// static
+shared_ptr <SMTPCommandSet> SMTPCommandSet::create(const bool pipeline) {
+
+ return shared_ptr <SMTPCommandSet>(new SMTPCommandSet(pipeline));
+}
+
+
+void SMTPCommandSet::addCommand(const shared_ptr <SMTPCommand>& cmd) {
+
+ if (m_started) {
+ throw std::runtime_error("Could not add command to pipeline: "
+ "one or more commands have already been sent to the server.");
+ }
+
+ m_commands.push_back(cmd);
+}
+
+
+void SMTPCommandSet::writeToSocket(const shared_ptr <socket>& sok, const shared_ptr <tracer>& tr) {
+
+ if (m_pipeline) {
+
+ if (!m_started) {
+
+ // Send all commands at once
+ for (std::list <shared_ptr <SMTPCommand> >::const_iterator it = m_commands.begin() ;
+ it != m_commands.end() ; ++it) {
+
+ shared_ptr <SMTPCommand> cmd = *it;
+ cmd->writeToSocket(sok, tr);
+ }
+ }
+
+ if (!m_commands.empty()) {
+
+ // Advance the pointer to last command sent
+ shared_ptr <SMTPCommand> cmd = m_commands.front();
+ m_commands.pop_front();
+
+ m_lastCommandSent = cmd;
+ }
+
+ } else {
+
+ if (!m_commands.empty()) {
+
+ // Send only one command
+ shared_ptr <SMTPCommand> cmd = m_commands.front();
+ m_commands.pop_front();
+
+ cmd->writeToSocket(sok, tr);
+
+ m_lastCommandSent = cmd;
+ }
+ }
+
+ m_started = true;
+}
+
+
+const string SMTPCommandSet::getText() const {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+
+ for (std::list <shared_ptr <SMTPCommand> >::const_iterator it = m_commands.begin() ;
+ it != m_commands.end() ; ++it) {
+
+ cmd << (*it)->getText() << "\r\n";
+ }
+
+ return cmd.str();
+}
+
+
+const string SMTPCommandSet::getTraceText() const {
+
+ std::ostringstream cmd;
+ cmd.imbue(std::locale::classic());
+
+ for (std::list <shared_ptr <SMTPCommand> >::const_iterator it = m_commands.begin() ;
+ it != m_commands.end() ; ++it) {
+
+ cmd << (*it)->getTraceText() << "\r\n";
+ }
+
+ return cmd.str();
+}
+
+
+bool SMTPCommandSet::isFinished() const {
+
+ return (m_pipeline && m_started) || (m_commands.size() == 0 && m_started);
+}
+
+
+shared_ptr <SMTPCommand> SMTPCommandSet::getLastCommandSent() const {
+
+ return m_lastCommandSent;
+}
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
diff --git a/vmime-master/src/vmime/net/smtp/SMTPCommandSet.hpp b/vmime-master/src/vmime/net/smtp/SMTPCommandSet.hpp
new file mode 100644
index 0000000..2fd977c
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPCommandSet.hpp
@@ -0,0 +1,106 @@
+//
+// 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_NET_SMTP_SMTPCOMMANDSET_HPP_INCLUDED
+#define VMIME_NET_SMTP_SMTPCOMMANDSET_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include <list>
+
+#include "vmime/net/smtp/SMTPCommand.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+/** A set of SMTP commands, which may be sent all at once
+ * to the server if pipelining is supported.
+ */
+class VMIME_EXPORT SMTPCommandSet : public SMTPCommand {
+
+public:
+
+ /** Creates a new set of SMTP commands.
+ *
+ * @param pipeline set to true if the server supports pipelining
+ * @return a new SMTPCommandSet object
+ */
+ static shared_ptr <SMTPCommandSet> create(const bool pipeline);
+
+ /** Adds a new command to this set.
+ * If one or more comments have already been sent to the server,
+ * an exception will be thrown.
+ *
+ * @param cmd command to add
+ */
+ void addCommand(const shared_ptr <SMTPCommand>& cmd);
+
+ /** Tests whether all commands have been sent.
+ *
+ * @return true if all commands have been sent,
+ * or false otherwise
+ */
+ bool isFinished() const;
+
+ /** Returns the last command which has been sent.
+ *
+ * @return a pointer to a SMTPCommand, of NULL if no command
+ * has been sent yet
+ */
+ shared_ptr <SMTPCommand> getLastCommandSent() const;
+
+
+ void writeToSocket(const shared_ptr <socket>& sok, const shared_ptr <tracer>& tr);
+
+ const string getText() const;
+ const string getTraceText() const;
+
+private:
+
+ SMTPCommandSet(const bool pipeline);
+ SMTPCommandSet(const SMTPCommandSet&);
+
+
+ bool m_pipeline;
+ bool m_started;
+ std::list <shared_ptr <SMTPCommand> > m_commands;
+ shared_ptr <SMTPCommand> m_lastCommandSent;
+};
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+#endif // VMIME_NET_SMTP_SMTPCOMMANDSET_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/smtp/SMTPConnection.cpp b/vmime-master/src/vmime/net/smtp/SMTPConnection.cpp
new file mode 100644
index 0000000..07d0376
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPConnection.cpp
@@ -0,0 +1,714 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/net/smtp/SMTPConnection.hpp"
+#include "vmime/net/smtp/SMTPTransport.hpp"
+#include "vmime/net/smtp/SMTPExceptions.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/platform.hpp"
+
+#include "vmime/security/digest/messageDigestFactory.hpp"
+
+#include "vmime/net/defaultConnectionInfos.hpp"
+
+#if VMIME_HAVE_SASL_SUPPORT
+ #include "vmime/security/sasl/SASLContext.hpp"
+#else
+ #include "vmime/utility/encoder/b64Encoder.hpp"
+ #include "vmime/utility/inputStreamStringAdapter.hpp"
+ #include "vmime/utility/outputStreamStringAdapter.hpp"
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+#if VMIME_HAVE_TLS_SUPPORT
+ #include "vmime/net/tls/TLSSession.hpp"
+ #include "vmime/net/tls/TLSSecuredConnectionInfos.hpp"
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+// Helpers for service properties
+#define GET_PROPERTY(type, prop) \
+ (m_transport.lock()->getInfos().getPropertyValue <type>(getSession(), \
+ dynamic_cast <const SMTPServiceInfos&>(m_transport.lock()->getInfos()).getProperties().prop))
+#define HAS_PROPERTY(prop) \
+ (m_transport.lock()->getInfos().hasProperty(getSession(), \
+ dynamic_cast <const SMTPServiceInfos&>(m_transport.lock()->getInfos()).getProperties().prop))
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+
+SMTPConnection::SMTPConnection(
+ const shared_ptr <SMTPTransport>& transport,
+ const shared_ptr <security::authenticator>& auth
+)
+ : m_transport(transport),
+ m_auth(auth),
+ m_socket(null),
+ m_timeoutHandler(null),
+ m_authenticated(false),
+ m_secured(false),
+ m_extendedSMTP(false) {
+
+ static int connectionId = 0;
+
+ if (transport->getTracerFactory()) {
+ m_tracer = transport->getTracerFactory()->create(transport, ++connectionId);
+ }
+}
+
+
+SMTPConnection::~SMTPConnection() {
+
+ try {
+
+ if (isConnected()) {
+ disconnect();
+ } else if (m_socket) {
+ internalDisconnect();
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+void SMTPConnection::connect() {
+
+ if (isConnected()) {
+ throw exceptions::already_connected();
+ }
+
+ const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS);
+ const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT);
+
+ shared_ptr <SMTPTransport> transport = m_transport.lock();
+
+ // Create the time-out handler
+ if (transport->getTimeoutHandlerFactory()) {
+ m_timeoutHandler = transport->getTimeoutHandlerFactory()->create();
+ }
+
+ // Create and connect the socket
+ m_socket = transport->getSocketFactory()->create(m_timeoutHandler);
+ m_socket->setTracer(m_tracer);
+
+#if VMIME_HAVE_TLS_SUPPORT
+ if (transport->isSMTPS()) { // dedicated port/SMTPS
+
+ shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create(
+ transport->getCertificateVerifier(),
+ transport->getSession()->getTLSProperties()
+ );
+
+ shared_ptr <tls::TLSSocket> tlsSocket = tlsSession->getSocket(m_socket);
+
+ m_socket = tlsSocket;
+
+ m_secured = true;
+ m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>(address, port, tlsSession, tlsSocket);
+
+ } else
+#endif // VMIME_HAVE_TLS_SUPPORT
+ {
+ m_cntInfos = make_shared <defaultConnectionInfos>(address, port);
+ }
+
+ m_socket->connect(address, port);
+
+ // Connection
+ //
+ // eg: C: <connection to server>
+ // --- S: 220 smtp.domain.com Service ready
+
+ shared_ptr <SMTPResponse> resp;
+
+ if ((resp = readResponse())->getCode() != 220) {
+ internalDisconnect();
+ throw exceptions::connection_greeting_error(resp->getText());
+ }
+
+ // Identification
+ helo();
+
+#if VMIME_HAVE_TLS_SUPPORT
+ // Setup secured connection, if requested
+ const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS)
+ && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS);
+ const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED)
+ && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED);
+
+ if (!transport->isSMTPS() && tls) { // only if not SMTPS
+
+ try {
+
+ startTLS();
+
+ // Non-fatal error
+ } catch (exceptions::command_error&) {
+
+ if (tlsRequired) {
+ throw;
+ } else {
+ // TLS is not required, so don't bother
+ }
+
+ // Fatal error
+ } catch (...) {
+
+ throw;
+ }
+
+ // Must reissue a EHLO command [RFC-2487, 5.2]
+ helo();
+ }
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ // Authentication
+ if (GET_PROPERTY(bool, PROPERTY_OPTIONS_NEEDAUTH)) {
+ authenticate();
+ } else {
+ m_authenticated = true;
+ }
+}
+
+
+void SMTPConnection::helo() {
+
+ // First, try Extended SMTP (ESMTP)
+ //
+ // eg: C: EHLO thismachine.ourdomain.com
+ // S: 250-smtp.theserver.com
+ // S: 250-AUTH CRAM-MD5 DIGEST-MD5
+ // S: 250-PIPELINING
+ // S: 250 SIZE 2555555555
+
+ sendRequest(SMTPCommand::EHLO(platform::getHandler()->getHostName()));
+
+ shared_ptr <SMTPResponse> resp;
+
+ if ((resp = readResponse())->getCode() != 250) {
+
+ // Next, try "Basic" SMTP
+ //
+ // eg: C: HELO thismachine.ourdomain.com
+ // S: 250 OK
+
+ sendRequest(SMTPCommand::HELO(platform::getHandler()->getHostName()));
+
+ if ((resp = readResponse())->getCode() != 250) {
+ internalDisconnect();
+ throw exceptions::connection_greeting_error(resp->getLastLine().getText());
+ }
+
+ m_extendedSMTP = false;
+ m_extensions.clear();
+
+ } else {
+
+ m_extendedSMTP = true;
+ m_extensions.clear();
+
+ // Get supported extensions from SMTP response
+ // One extension per line, format is: EXT PARAM1 PARAM2...
+ for (size_t i = 1, n = resp->getLineCount() ; i < n ; ++i) {
+
+ const string line = resp->getLineAt(i).getText();
+
+ std::istringstream iss(line);
+ iss.imbue(std::locale::classic());
+
+ string ext;
+ iss >> ext;
+
+ std::vector <string> params;
+ string param;
+
+ // Special case: some servers send "AUTH=MECH [MECH MECH...]"
+ if (ext.length() >= 5 && utility::stringUtils::toUpper(ext.substr(0, 5)) == "AUTH=") {
+
+ params.push_back(utility::stringUtils::toUpper(ext.substr(5)));
+ ext = "AUTH";
+ }
+
+ while (iss >> param) {
+ params.push_back(utility::stringUtils::toUpper(param));
+ }
+
+ m_extensions[ext] = params;
+ }
+ }
+}
+
+
+bool SMTPConnection::hasExtension(
+ const std::string& extName,
+ std::vector <string>* params
+) const {
+
+ std::map <string, std::vector <string> >::const_iterator
+ it = m_extensions.find(extName);
+
+ if (it != m_extensions.end()) {
+
+ if (params) {
+ *params = (*it).second;
+ }
+
+ return true;
+
+ } else {
+
+ return false;
+ }
+}
+
+
+void SMTPConnection::authenticate() {
+
+ if (!m_extendedSMTP) {
+ internalDisconnect();
+ throw exceptions::command_error("AUTH", "ESMTP not supported.");
+ }
+
+ getAuthenticator()->setService(m_transport.lock());
+
+#if VMIME_HAVE_SASL_SUPPORT
+ // Try SASL authentication
+ if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) {
+
+ try {
+
+ authenticateSASL();
+
+ m_authenticated = true;
+ return;
+
+ } catch (exception&) {
+
+ internalDisconnect();
+ throw;
+ }
+ }
+#else // no SASL
+
+ // allow AUTH PLAIN over TLS - it is a popular and simple mechanism
+ if (m_secured) {
+
+ std::vector <string> authMechs;
+ hasExtension("AUTH", &authMechs);
+
+ if (authMechs.empty()) {
+ throw exceptions::authentication_error("No AUTH mechanism available.");
+ }
+
+ const string plain("PLAIN");
+
+ if (std::find(authMechs.begin(), authMechs.end(), plain) != authMechs.end()) {
+
+ const string username = getAuthenticator()->getUsername();
+ const string password = getAuthenticator()->getPassword();
+ const string authToken = username + '\0' + username + '\0' + password;
+
+ utility::inputStreamStringAdapter in(authToken);
+ string authTokenBase64;
+ utility::outputStreamStringAdapter out(authTokenBase64);
+
+ vmime::utility::encoder::b64Encoder encoder;
+ encoder.encode(in, out);
+
+ sendRequest(SMTPCommand::AUTH(plain, authTokenBase64));
+
+ shared_ptr <SMTPResponse> response = readResponse();
+
+ const int code = response ? response->getCode() : -1;
+
+ if (code == 235) {
+ m_authenticated = true;
+ return;
+ }
+ }
+ }
+
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ // No other authentication method is possible
+ throw exceptions::authentication_error("All authentication methods failed");
+}
+
+
+
+#if VMIME_HAVE_SASL_SUPPORT
+
+void SMTPConnection::authenticateSASL() {
+
+ if (!dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())) {
+ throw exceptions::authentication_error("No SASL authenticator available.");
+ }
+
+ // Obtain SASL mechanisms supported by server from ESMTP extensions
+ std::vector <string> saslMechs;
+ hasExtension("AUTH", &saslMechs);
+
+ if (saslMechs.empty()) {
+ throw exceptions::authentication_error("No SASL mechanism available.");
+ }
+
+ std::vector <shared_ptr <security::sasl::SASLMechanism> > mechList;
+
+ shared_ptr <security::sasl::SASLContext> saslContext =
+ security::sasl::SASLContext::create();
+
+ for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) {
+
+ try {
+
+ mechList.push_back
+ (saslContext->createMechanism(saslMechs[i]));
+
+ } catch (exceptions::no_such_mechanism&) {
+
+ // Ignore mechanism
+ }
+ }
+
+ if (mechList.empty()) {
+ throw exceptions::authentication_error("No SASL mechanism available.");
+ }
+
+ // Try to suggest a mechanism among all those supported
+ shared_ptr <security::sasl::SASLMechanism> suggestedMech =
+ saslContext->suggestMechanism(mechList);
+
+ if (!suggestedMech) {
+ throw exceptions::authentication_error("Unable to suggest SASL mechanism.");
+ }
+
+ // Allow application to choose which mechanisms to use
+ mechList = dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())->
+ getAcceptableMechanisms(mechList, suggestedMech);
+
+ if (mechList.empty()) {
+ throw exceptions::authentication_error("No SASL mechanism available.");
+ }
+
+ // Try each mechanism in the list in turn
+ for (unsigned int i = 0 ; i < mechList.size() ; ++i) {
+
+ shared_ptr <security::sasl::SASLMechanism> mech = mechList[i];
+
+ shared_ptr <security::sasl::SASLSession> saslSession =
+ saslContext->createSession("smtp", getAuthenticator(), mech);
+
+ saslSession->init();
+
+ if (saslSession->getMechanism()->hasInitialResponse()) {
+
+ byte_t* initialResp = 0;
+ size_t initialRespLen = 0;
+
+ saslSession->evaluateChallenge(NULL, 0, &initialResp, &initialRespLen);
+
+ string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen));
+ delete [] initialResp;
+
+ if (encodedInitialResp.empty()) {
+ sendRequest(SMTPCommand::AUTH(mech->getName(), "="));
+ } else {
+ sendRequest(SMTPCommand::AUTH(mech->getName(), encodedInitialResp));
+ }
+
+ } else {
+
+ sendRequest(SMTPCommand::AUTH(mech->getName()));
+ }
+
+ for (bool cont = true ; cont ; ) {
+
+ shared_ptr <SMTPResponse> response = readResponse();
+
+ switch (response->getCode()) {
+
+ case 235: {
+
+ m_socket = saslSession->getSecuredSocket(m_socket);
+ return;
+ }
+ case 334: {
+
+ byte_t* challenge = 0;
+ size_t challengeLen = 0;
+
+ byte_t* resp = 0;
+ size_t respLen = 0;
+
+ try {
+
+ // Extract challenge
+ saslContext->decodeB64(response->getText(), &challenge, &challengeLen);
+
+ // Prepare response
+ saslSession->evaluateChallenge(challenge, challengeLen, &resp, &respLen);
+
+ // Send response
+ const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n";
+ m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length());
+
+ if (m_tracer) {
+ m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange");
+ }
+
+ } catch (exceptions::sasl_exception& e) {
+
+ if (challenge) {
+ delete [] challenge;
+ challenge = NULL;
+ }
+
+ if (resp) {
+ delete [] resp;
+ resp = NULL;
+ }
+
+ // Cancel SASL exchange
+ m_socket->send("*\r\n");
+
+ if (m_tracer) {
+ m_tracer->traceSend("*");
+ }
+
+ } catch (...) {
+
+ if (challenge) {
+ delete [] challenge;
+ }
+
+ if (resp) {
+ delete [] resp;
+ }
+
+ throw;
+ }
+
+ if (challenge) {
+ delete [] challenge;
+ }
+
+ if (resp) {
+ delete [] resp;
+ }
+
+ break;
+ }
+ default:
+
+ cont = false;
+ break;
+ }
+ }
+ }
+
+ throw exceptions::authentication_error("Could not authenticate using SASL: all mechanisms failed.");
+}
+
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+
+#if VMIME_HAVE_TLS_SUPPORT
+
+void SMTPConnection::startTLS() {
+
+ try {
+
+ sendRequest(SMTPCommand::STARTTLS());
+
+ shared_ptr <SMTPResponse> resp = readResponse();
+
+ if (resp->getCode() != 220) {
+
+ throw SMTPCommandError(
+ "STARTTLS", resp->getText(), resp->getCode(), resp->getEnhancedCode()
+ );
+ }
+
+ shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create(
+ getTransport()->getCertificateVerifier(),
+ getTransport()->getSession()->getTLSProperties()
+ );
+
+ shared_ptr <tls::TLSSocket> tlsSocket = tlsSession->getSocket(m_socket);
+
+ tlsSocket->handshake();
+
+ m_socket = tlsSocket;
+
+ m_secured = true;
+ m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>(
+ m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket
+ );
+
+ } catch (exceptions::command_error&) {
+
+ // Non-fatal error
+ throw;
+
+ } catch (exception&) {
+
+ // Fatal error
+ internalDisconnect();
+ throw;
+ }
+}
+
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+void SMTPConnection::disconnect() {
+
+ if (!isConnected()) {
+ throw exceptions::not_connected();
+ }
+
+ internalDisconnect();
+}
+
+
+void SMTPConnection::internalDisconnect() {
+
+ if (isConnected()) {
+
+ try {
+
+ sendRequest(SMTPCommand::QUIT());
+
+ // Do not wait for server response. This is contrary to the RFC, but
+ // some servers never send a response to a QUIT command.
+
+ } catch (exception&) {
+
+ // Not important
+ }
+ }
+
+ m_socket->disconnect();
+ m_socket = null;
+
+ m_timeoutHandler = null;
+
+ m_authenticated = false;
+ m_extendedSMTP = false;
+
+ m_secured = false;
+ m_cntInfos = null;
+}
+
+
+void SMTPConnection::sendRequest(const shared_ptr <SMTPCommand>& cmd) {
+
+ cmd->writeToSocket(m_socket, m_tracer);
+}
+
+
+shared_ptr <SMTPResponse> SMTPConnection::readResponse() {
+
+ shared_ptr <SMTPResponse> resp = SMTPResponse::readResponse(
+ m_tracer, m_socket, m_timeoutHandler, m_responseState
+ );
+
+ m_responseState = resp->getCurrentState();
+
+ return resp;
+}
+
+
+bool SMTPConnection::isConnected() const {
+
+ return m_socket && m_socket->isConnected() && m_authenticated;
+}
+
+
+bool SMTPConnection::isSecuredConnection() const {
+
+ return m_secured;
+}
+
+
+shared_ptr <connectionInfos> SMTPConnection::getConnectionInfos() const {
+
+ return m_cntInfos;
+}
+
+
+shared_ptr <SMTPTransport> SMTPConnection::getTransport() {
+
+ return m_transport.lock();
+}
+
+
+shared_ptr <session> SMTPConnection::getSession() {
+
+ return m_transport.lock()->getSession();
+}
+
+
+shared_ptr <socket> SMTPConnection::getSocket() {
+
+ return m_socket;
+}
+
+
+shared_ptr <tracer> SMTPConnection::getTracer() {
+
+ return m_tracer;
+}
+
+
+shared_ptr <timeoutHandler> SMTPConnection::getTimeoutHandler() {
+
+ return m_timeoutHandler;
+}
+
+
+shared_ptr <security::authenticator> SMTPConnection::getAuthenticator() {
+
+ return m_auth;
+}
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
diff --git a/vmime-master/src/vmime/net/smtp/SMTPConnection.hpp b/vmime-master/src/vmime/net/smtp/SMTPConnection.hpp
new file mode 100644
index 0000000..d8a2375
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPConnection.hpp
@@ -0,0 +1,136 @@
+//
+// 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_NET_SMTP_SMTPCONNECTION_HPP_INCLUDED
+#define VMIME_NET_SMTP_SMTPCONNECTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/messageId.hpp"
+
+#include "vmime/net/socket.hpp"
+#include "vmime/net/timeoutHandler.hpp"
+#include "vmime/net/session.hpp"
+#include "vmime/net/connectionInfos.hpp"
+#include "vmime/net/tracer.hpp"
+
+#include "vmime/net/smtp/SMTPCommand.hpp"
+#include "vmime/net/smtp/SMTPResponse.hpp"
+
+#include "vmime/security/authenticator.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+class socket;
+class timeoutHandler;
+
+
+namespace smtp {
+
+
+class SMTPTransport;
+
+
+/** Manage connection to a SMTP server.
+ */
+class VMIME_EXPORT SMTPConnection : public object {
+
+public:
+
+ SMTPConnection(
+ const shared_ptr <SMTPTransport>& transport,
+ const shared_ptr <security::authenticator>& auth
+ );
+
+ ~SMTPConnection();
+
+
+ virtual void connect();
+ virtual bool isConnected() const;
+ virtual void disconnect();
+
+ bool isSecuredConnection() const;
+ shared_ptr <connectionInfos> getConnectionInfos() const;
+
+ virtual shared_ptr <SMTPTransport> getTransport();
+ virtual shared_ptr <socket> getSocket();
+ virtual shared_ptr <timeoutHandler> getTimeoutHandler();
+ virtual shared_ptr <security::authenticator> getAuthenticator();
+ virtual shared_ptr <session> getSession();
+ virtual shared_ptr <tracer> getTracer();
+
+ void sendRequest(const shared_ptr <SMTPCommand>& cmd);
+ shared_ptr <SMTPResponse> readResponse();
+
+ bool hasExtension(const std::string& extName, std::vector <string>* params = NULL) const;
+
+private:
+
+ void internalDisconnect();
+
+ void helo();
+ void authenticate();
+#if VMIME_HAVE_SASL_SUPPORT
+ void authenticateSASL();
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+#if VMIME_HAVE_TLS_SUPPORT
+ void startTLS();
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+
+ weak_ptr <SMTPTransport> m_transport;
+
+ shared_ptr <security::authenticator> m_auth;
+ shared_ptr <socket> m_socket;
+ shared_ptr <timeoutHandler> m_timeoutHandler;
+ shared_ptr <tracer> m_tracer;
+
+ SMTPResponse::state m_responseState;
+
+ bool m_authenticated;
+ bool m_secured;
+
+ shared_ptr <connectionInfos> m_cntInfos;
+
+ bool m_extendedSMTP;
+ std::map <string, std::vector <string> > m_extensions;
+};
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+#endif // VMIME_NET_SMTP_SMTPCONNECTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/smtp/SMTPExceptions.cpp b/vmime-master/src/vmime/net/smtp/SMTPExceptions.cpp
new file mode 100644
index 0000000..e3b4652
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPExceptions.cpp
@@ -0,0 +1,212 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/net/smtp/SMTPExceptions.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+//
+// SMTPCommandError
+//
+
+SMTPCommandError::SMTPCommandError(
+ const string& command,
+ const string& response,
+ const string& desc,
+ const int statusCode,
+ const SMTPResponse::enhancedStatusCode& extendedStatusCode,
+ const exception& other
+)
+ : command_error(command, response, desc, other),
+ m_status(statusCode),
+ m_exStatus(extendedStatusCode) {
+
+}
+
+
+SMTPCommandError::SMTPCommandError(
+ const string& command,
+ const string& response,
+ const int statusCode,
+ const SMTPResponse::enhancedStatusCode& extendedStatusCode,
+ const exception& other
+)
+ : command_error(command, response, "", other),
+ m_status(statusCode),
+ m_exStatus(extendedStatusCode) {
+
+}
+
+
+SMTPCommandError::~SMTPCommandError() throw() {
+
+}
+
+
+int SMTPCommandError::statusCode() const {
+
+ return m_status;
+}
+
+
+const SMTPResponse::enhancedStatusCode SMTPCommandError::extendedStatusCode() const {
+
+ return m_exStatus;
+}
+
+
+exception* SMTPCommandError::clone() const {
+
+ return new SMTPCommandError(*this);
+}
+
+
+const char* SMTPCommandError::name() const throw() {
+
+ return "SMTPCommandError";
+}
+
+
+//
+// SMTPMessageSizeExceedsMaxLimitsException
+//
+
+SMTPMessageSizeExceedsMaxLimitsException::SMTPMessageSizeExceedsMaxLimitsException(const exception& other)
+ : net_exception("Message size exceeds maximum server limits (permanent error).", other) {
+
+}
+
+
+SMTPMessageSizeExceedsMaxLimitsException::~SMTPMessageSizeExceedsMaxLimitsException() throw() {
+
+}
+
+
+exception* SMTPMessageSizeExceedsMaxLimitsException::clone() const {
+
+ return new SMTPMessageSizeExceedsMaxLimitsException(*this);
+}
+
+
+const char* SMTPMessageSizeExceedsMaxLimitsException::name() const throw() {
+
+ return "SMTPMessageSizeExceedsMaxLimitsException";
+}
+
+
+//
+// SMTPMessageSizeExceedsCurLimitsException
+//
+
+SMTPMessageSizeExceedsCurLimitsException::SMTPMessageSizeExceedsCurLimitsException(const exception& other)
+ : net_exception("Message size exceeds current server limits (temporary storage error).", other) {
+
+}
+
+
+SMTPMessageSizeExceedsCurLimitsException::~SMTPMessageSizeExceedsCurLimitsException() throw() {
+
+}
+
+
+exception* SMTPMessageSizeExceedsCurLimitsException::clone() const {
+
+ return new SMTPMessageSizeExceedsCurLimitsException(*this);
+}
+
+
+const char* SMTPMessageSizeExceedsCurLimitsException::name() const throw() {
+
+ return "SMTPMessageSizeExceedsCurLimitsException";
+}
+
+
+//
+// SMTPExtensionNotSupportedException
+//
+
+SMTPExtensionNotSupportedException::SMTPExtensionNotSupportedException(const string &what, const exception& other)
+ : net_exception(what.empty() ? "A required extension is not supported by the SMTP server." : what, other) {
+
+}
+
+
+SMTPExtensionNotSupportedException::~SMTPExtensionNotSupportedException() throw() {
+
+}
+
+
+exception* SMTPExtensionNotSupportedException::clone() const {
+
+ return new SMTPExtensionNotSupportedException(*this);
+}
+
+
+const char* SMTPExtensionNotSupportedException::name() const throw() {
+
+ return "SMTPExtensionNotSupportedException";
+}
+
+
+//
+// SMTPDSNExtensionNotSupportedException
+//
+
+SMTPDSNExtensionNotSupportedException::SMTPDSNExtensionNotSupportedException(const exception& other)
+ : SMTPExtensionNotSupportedException("RFC-1891 DSN extension is not supported by the SMTP server.", other) {
+
+}
+
+
+SMTPDSNExtensionNotSupportedException::~SMTPDSNExtensionNotSupportedException() throw() {
+
+}
+
+
+exception* SMTPDSNExtensionNotSupportedException::clone() const {
+ return new SMTPDSNExtensionNotSupportedException(*this);
+}
+
+
+const char* SMTPDSNExtensionNotSupportedException::name() const throw() {
+
+ return "SMTPDSNExtensionNotSupportedException";
+}
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
diff --git a/vmime-master/src/vmime/net/smtp/SMTPExceptions.hpp b/vmime-master/src/vmime/net/smtp/SMTPExceptions.hpp
new file mode 100644
index 0000000..488ee2e
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPExceptions.hpp
@@ -0,0 +1,159 @@
+//
+// 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_NET_SMTP_SMTPEXCEPTIONS_HPP_INCLUDED
+#define VMIME_NET_SMTP_SMTPEXCEPTIONS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/exception.hpp"
+#include "vmime/base.hpp"
+
+#include "vmime/net/smtp/SMTPResponse.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+/** SMTP Command error: a SMTP command failed.
+ */
+class VMIME_EXPORT SMTPCommandError : public exceptions::command_error {
+
+public:
+
+ SMTPCommandError(
+ const string& command,
+ const string& response,
+ const string& desc,
+ const int statusCode,
+ const SMTPResponse::enhancedStatusCode& extendedStatusCode,
+ const exception& other = NO_EXCEPTION
+ );
+
+ SMTPCommandError(
+ const string& command,
+ const string& response,
+ const int statusCode, const SMTPResponse::enhancedStatusCode& extendedStatusCode,
+ const exception& other = NO_EXCEPTION
+ );
+
+ ~SMTPCommandError() throw();
+
+ /** Returns the SMTP status code for this error.
+ *
+ * @return status code (protocol-dependent)
+ */
+ int statusCode() const;
+
+ /** Returns the extended status code (following RFC-3463) for this
+ * error, if available.
+ *
+ * @return status code
+ */
+ const SMTPResponse::enhancedStatusCode extendedStatusCode() const;
+
+
+ exception* clone() const;
+ const char* name() const throw();
+
+private:
+
+ int m_status;
+ SMTPResponse::enhancedStatusCode m_exStatus;
+};
+
+
+/** SMTP error: message size exceeds maximum server limits.
+ * This is a permanent error.
+ */
+class VMIME_EXPORT SMTPMessageSizeExceedsMaxLimitsException : public exceptions::net_exception {
+
+public:
+
+ SMTPMessageSizeExceedsMaxLimitsException(const exception& other = NO_EXCEPTION);
+ ~SMTPMessageSizeExceedsMaxLimitsException() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** SMTP error: message size exceeds current server limits.
+ * This is a temporary error (you may retry later).
+ */
+class VMIME_EXPORT SMTPMessageSizeExceedsCurLimitsException : public exceptions::net_exception {
+
+public:
+
+ SMTPMessageSizeExceedsCurLimitsException(const exception& other = NO_EXCEPTION);
+ ~SMTPMessageSizeExceedsCurLimitsException() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** SMTP error: a required extension is not supported by the server.
+ */
+class VMIME_EXPORT SMTPExtensionNotSupportedException : public exceptions::net_exception {
+
+public:
+
+ SMTPExtensionNotSupportedException(const string& what, const exception& other = NO_EXCEPTION);
+ ~SMTPExtensionNotSupportedException() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+/** SMTP error: RFC-1891 DSN extension is not supported by the server.
+ */
+class VMIME_EXPORT SMTPDSNExtensionNotSupportedException : public SMTPExtensionNotSupportedException {
+
+public:
+
+ SMTPDSNExtensionNotSupportedException(const exception& other = NO_EXCEPTION);
+ ~SMTPDSNExtensionNotSupportedException() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+};
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+#endif // VMIME_NET_SMTP_SMTPEXCEPTIONS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/smtp/SMTPResponse.cpp b/vmime-master/src/vmime/net/smtp/SMTPResponse.cpp
new file mode 100644
index 0000000..2234705
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPResponse.cpp
@@ -0,0 +1,366 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/net/smtp/SMTPResponse.hpp"
+
+#include "vmime/platform.hpp"
+#include "vmime/utility/stringUtils.hpp"
+
+#include "vmime/net/socket.hpp"
+#include "vmime/net/timeoutHandler.hpp"
+#include "vmime/net/tracer.hpp"
+
+#include <cctype>
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+SMTPResponse::SMTPResponse(
+ const shared_ptr <tracer>& tr,
+ const shared_ptr <socket>& sok,
+ const shared_ptr <timeoutHandler>& toh,
+ const state& st
+)
+ : m_socket(sok),
+ m_timeoutHandler(toh),
+ m_tracer(tr),
+ m_responseBuffer(st.responseBuffer),
+ m_responseContinues(false) {
+
+}
+
+
+SMTPResponse::SMTPResponse(const SMTPResponse&)
+ : vmime::object() {
+
+ // Not used
+}
+
+
+int SMTPResponse::getCode() const {
+
+ const int firstCode = m_lines[0].getCode();
+
+ for (unsigned int i = 1 ; i < m_lines.size() ; ++i) {
+
+ // All response codes returned must be equal
+ // or else this in an error...
+ if (m_lines[i].getCode() != firstCode) {
+ return 0;
+ }
+ }
+
+ return firstCode;
+}
+
+
+const SMTPResponse::enhancedStatusCode SMTPResponse::getEnhancedCode() const {
+
+ return m_lines[m_lines.size() - 1].getEnhancedCode();
+}
+
+
+const string SMTPResponse::getText() const {
+
+ string text = m_lines[0].getText();
+
+ for (unsigned int i = 1 ; i < m_lines.size() ; ++i) {
+
+ text += '\n';
+ text += m_lines[i].getText();
+ }
+
+ return text;
+}
+
+
+// static
+shared_ptr <SMTPResponse> SMTPResponse::readResponse(
+ const shared_ptr <tracer>& tr,
+ const shared_ptr <socket>& sok,
+ const shared_ptr <timeoutHandler>& toh,
+ const state& st
+) {
+
+ shared_ptr <SMTPResponse> resp =
+ shared_ptr <SMTPResponse>(new SMTPResponse(tr, sok, toh, st));
+
+ resp->readResponse();
+
+ return resp;
+}
+
+
+void SMTPResponse::readResponse() {
+
+ responseLine line = getNextResponse();
+ m_lines.push_back(line);
+
+ while (m_responseContinues) {
+ line = getNextResponse();
+ m_lines.push_back(line);
+ }
+}
+
+
+const string SMTPResponse::readResponseLine() {
+
+ string currentBuffer = m_responseBuffer;
+
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ while (true) {
+
+ // Get a line from the response buffer
+ const size_t lineEnd = currentBuffer.find_first_of('\n');
+
+ if (lineEnd != string::npos) {
+
+ size_t actualLineEnd = lineEnd;
+
+ if (actualLineEnd != 0 && currentBuffer[actualLineEnd - 1] == '\r') { // CRLF case
+ actualLineEnd--;
+ }
+
+ const string line(currentBuffer.begin(), currentBuffer.begin() + actualLineEnd);
+
+ currentBuffer.erase(currentBuffer.begin(), currentBuffer.begin() + lineEnd + 1);
+ m_responseBuffer = currentBuffer;
+
+ if (m_tracer) {
+ m_tracer->traceReceive(line);
+ }
+
+ return line;
+ }
+
+ // Check whether the time-out delay is elapsed
+ if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+ throw exceptions::operation_timed_out();
+ }
+
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ // Receive data from the socket
+ string receiveBuffer;
+ m_socket->receive(receiveBuffer);
+
+ if (receiveBuffer.empty()) { // buffer is empty
+ m_socket->waitForRead();
+ continue;
+ }
+
+ currentBuffer += receiveBuffer;
+ }
+}
+
+
+const SMTPResponse::responseLine SMTPResponse::getNextResponse() {
+
+ string line = readResponseLine();
+
+ const int code = extractResponseCode(line);
+ string text;
+
+ m_responseContinues = (line.length() >= 4 && line[3] == '-');
+
+ if (line.length() > 4) {
+ text = utility::stringUtils::trim(line.substr(4));
+ } else {
+ text = "";
+ }
+
+ return responseLine(code, text, extractEnhancedCode(text));
+}
+
+
+// static
+int SMTPResponse::extractResponseCode(const string& response) {
+
+ int code = 0;
+
+ if (response.length() >= 3) {
+
+ code = (response[0] - '0') * 100
+ + (response[1] - '0') * 10
+ + (response[2] - '0');
+ }
+
+ return code;
+}
+
+
+// static
+const SMTPResponse::enhancedStatusCode SMTPResponse::extractEnhancedCode(const string& responseText) {
+
+ enhancedStatusCode enhCode;
+
+ std::istringstream iss(responseText);
+ iss.imbue(std::locale::classic());
+
+ if (std::isdigit(iss.peek())) {
+
+ iss >> enhCode.klass;
+
+ if (iss.get() == '.' && std::isdigit(iss.peek())) {
+
+ iss >> enhCode.subject;
+
+ if (iss.get() == '.' && std::isdigit(iss.peek())) {
+
+ iss >> enhCode.detail;
+ return enhCode;
+ }
+ }
+ }
+
+ return enhancedStatusCode(); // no enhanced code found
+}
+
+
+const SMTPResponse::responseLine SMTPResponse::getLineAt(const size_t pos) const {
+
+ return m_lines[pos];
+}
+
+
+size_t SMTPResponse::getLineCount() const {
+
+ return m_lines.size();
+}
+
+
+const SMTPResponse::responseLine SMTPResponse::getLastLine() const {
+
+ return m_lines[m_lines.size() - 1];
+}
+
+
+const SMTPResponse::state SMTPResponse::getCurrentState() const {
+
+ state st;
+ st.responseBuffer = m_responseBuffer;
+
+ return st;
+}
+
+
+
+// SMTPResponse::responseLine
+
+SMTPResponse::responseLine::responseLine(
+ const int code,
+ const string& text,
+ const enhancedStatusCode& enhCode
+)
+ : m_code(code),
+ m_text(text),
+ m_enhCode(enhCode) {
+
+}
+
+
+void SMTPResponse::responseLine::setCode(const int code) {
+
+ m_code = code;
+}
+
+
+int SMTPResponse::responseLine::getCode() const {
+
+ return m_code;
+}
+
+
+void SMTPResponse::responseLine::setEnhancedCode(const enhancedStatusCode& enhCode) {
+
+ m_enhCode = enhCode;
+}
+
+
+const SMTPResponse::enhancedStatusCode SMTPResponse::responseLine::getEnhancedCode() const {
+
+ return m_enhCode;
+}
+
+
+void SMTPResponse::responseLine::setText(const string& text) {
+
+ m_text = text;
+}
+
+
+const string SMTPResponse::responseLine::getText() const {
+
+ return m_text;
+}
+
+
+
+// SMTPResponse::enhancedStatusCode
+
+
+SMTPResponse::enhancedStatusCode::enhancedStatusCode()
+ : klass(0),
+ subject(0),
+ detail(0) {
+
+}
+
+
+SMTPResponse::enhancedStatusCode::enhancedStatusCode(const enhancedStatusCode& enhCode)
+ : klass(enhCode.klass),
+ subject(enhCode.subject),
+ detail(enhCode.detail) {
+
+}
+
+
+std::ostream& operator<<(std::ostream& os, const SMTPResponse::enhancedStatusCode& code) {
+
+ os << code.klass << '.' << code.subject << '.' << code.detail;
+ return os;
+}
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
diff --git a/vmime-master/src/vmime/net/smtp/SMTPResponse.hpp b/vmime-master/src/vmime/net/smtp/SMTPResponse.hpp
new file mode 100644
index 0000000..2eec7f4
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPResponse.hpp
@@ -0,0 +1,200 @@
+//
+// 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_NET_SMTP_SMTPRESPONSE_HPP_INCLUDED
+#define VMIME_NET_SMTP_SMTPRESPONSE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/object.hpp"
+#include "vmime/base.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+class socket;
+class timeoutHandler;
+class tracer;
+
+
+namespace smtp {
+
+
+/** A SMTP response, as sent by the server.
+ */
+class VMIME_EXPORT SMTPResponse : public object {
+
+public:
+
+ /** Current state of response parser. */
+ struct state {
+
+ string responseBuffer;
+ };
+
+ /** Enhanced status code (as per RFC-3463). */
+ struct enhancedStatusCode {
+
+ enhancedStatusCode();
+ enhancedStatusCode(const enhancedStatusCode& enhCode);
+
+ unsigned short klass; /**< Success/failure. */
+ unsigned short subject; /**< Source of anomaly. */
+ unsigned short detail; /**< Precise error condition. */
+ };
+
+ /** An element of a SMTP response. */
+ class responseLine {
+
+ public:
+
+ responseLine(const int code, const string& text, const enhancedStatusCode& enhCode);
+
+ void setCode(const int code);
+ int getCode() const;
+
+ void setEnhancedCode(const enhancedStatusCode& enhCode);
+ const enhancedStatusCode getEnhancedCode() const;
+
+ void setText(const string& text);
+ const string getText() const;
+
+ private:
+
+ int m_code;
+ string m_text;
+ enhancedStatusCode m_enhCode;
+ };
+
+ /** Receive and parse a new SMTP response from the
+ * specified socket.
+ *
+ * @param tr tracer
+ * @param sok socket from which to read
+ * @param toh time-out handler
+ * @param st previous state of response parser for the specified socket
+ * @return SMTP response
+ * @throws exceptions::operation_timed_out if no data
+ * has been received within the granted time
+ */
+ static shared_ptr <SMTPResponse> readResponse(
+ const shared_ptr <tracer>& tr,
+ const shared_ptr <socket>& sok,
+ const shared_ptr <timeoutHandler>& toh,
+ const state& st
+ );
+
+ /** Return the SMTP response code.
+ *
+ * @return response code
+ */
+ int getCode() const;
+
+ /** Return the SMTP enhanced status code, if available.
+ *
+ * @return enhanced status code
+ */
+ const enhancedStatusCode getEnhancedCode() const;
+
+ /** Return the SMTP response text.
+ * The text of each line is concatenated.
+ *
+ * @return response text
+ */
+ const string getText() const;
+
+ /** Return the response line at the specified position.
+ *
+ * @param pos line index
+ * @return line at the specified index
+ */
+ const responseLine getLineAt(const size_t pos) const;
+
+ /** Return the number of lines in the response.
+ *
+ * @return number of lines in the response
+ */
+ size_t getLineCount() const;
+
+ /** Return the last line in the response.
+ *
+ * @return last response line
+ */
+ const responseLine getLastLine() const;
+
+ /** Returns the current state of the response parser.
+ *
+ * @return current parser state
+ */
+ const state getCurrentState() const;
+
+private:
+
+ SMTPResponse(
+ const shared_ptr <tracer>& tr,
+ const shared_ptr <socket>& sok,
+ const shared_ptr <timeoutHandler>& toh,
+ const state& st
+ );
+
+ SMTPResponse(const SMTPResponse&);
+
+ void readResponse();
+
+ const string readResponseLine();
+ const responseLine getNextResponse();
+
+ static int extractResponseCode(const string& response);
+ static const enhancedStatusCode extractEnhancedCode(const string& responseText);
+
+
+ std::vector <responseLine> m_lines;
+
+ shared_ptr <socket> m_socket;
+ shared_ptr <timeoutHandler> m_timeoutHandler;
+ shared_ptr <tracer> m_tracer;
+
+ string m_responseBuffer;
+ bool m_responseContinues;
+};
+
+
+VMIME_EXPORT std::ostream& operator<<(std::ostream& os, const SMTPResponse::enhancedStatusCode& code);
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+#endif // VMIME_NET_SMTP_SMTPRESPONSE_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/smtp/SMTPSTransport.cpp b/vmime-master/src/vmime/net/smtp/SMTPSTransport.cpp
new file mode 100644
index 0000000..5158aa9
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPSTransport.cpp
@@ -0,0 +1,82 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/net/smtp/SMTPSTransport.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+SMTPSTransport::SMTPSTransport(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+)
+ : SMTPTransport(sess, auth, true) {
+
+}
+
+
+SMTPSTransport::~SMTPSTransport() {
+
+}
+
+
+const string SMTPSTransport::getProtocolName() const {
+
+ return "smtps";
+}
+
+
+
+// Service infos
+
+SMTPServiceInfos SMTPSTransport::sm_infos(true);
+
+
+const serviceInfos& SMTPSTransport::getInfosInstance() {
+
+ return sm_infos;
+}
+
+
+const serviceInfos& SMTPSTransport::getInfos() const {
+
+ return sm_infos;
+}
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
diff --git a/vmime-master/src/vmime/net/smtp/SMTPSTransport.hpp b/vmime-master/src/vmime/net/smtp/SMTPSTransport.hpp
new file mode 100644
index 0000000..f19b3c5
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPSTransport.hpp
@@ -0,0 +1,74 @@
+//
+// 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_NET_SMTP_SMTPSSTORE_HPP_INCLUDED
+#define VMIME_NET_SMTP_SMTPSSTORE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/net/smtp/SMTPTransport.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+/** SMTPS transport service.
+ */
+class VMIME_EXPORT SMTPSTransport : public SMTPTransport {
+
+public:
+
+ SMTPSTransport(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth
+ );
+
+ ~SMTPSTransport();
+
+ const string getProtocolName() const;
+
+ static const serviceInfos& getInfosInstance();
+ const serviceInfos& getInfos() const;
+
+private:
+
+ static SMTPServiceInfos sm_infos;
+};
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+#endif // VMIME_NET_SMTP_SMTPSSTORE_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/smtp/SMTPServiceInfos.cpp b/vmime-master/src/vmime/net/smtp/SMTPServiceInfos.cpp
new file mode 100644
index 0000000..a2ee3d5
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPServiceInfos.cpp
@@ -0,0 +1,144 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/net/smtp/SMTPServiceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+SMTPServiceInfos::SMTPServiceInfos(const bool smtps)
+ : m_smtps(smtps) {
+
+}
+
+
+const string SMTPServiceInfos::getPropertyPrefix() const {
+
+ if (m_smtps) {
+ return "transport.smtps.";
+ } else {
+ return "transport.smtp.";
+ }
+}
+
+
+const SMTPServiceInfos::props& SMTPServiceInfos::getProperties() const {
+
+ static props smtpProps = {
+ // SMTP-specific options
+ property("options.need-authentication", serviceInfos::property::TYPE_BOOLEAN, "false"),
+#if VMIME_HAVE_SASL_SUPPORT
+ property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"),
+ property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "false"),
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ property("options.pipelining", serviceInfos::property::TYPE_BOOLEAN, "true"),
+ property("options.chunking", serviceInfos::property::TYPE_BOOLEAN, "true"),
+
+ // Common properties
+ property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
+ property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
+
+#if VMIME_HAVE_TLS_SUPPORT
+ property(serviceInfos::property::CONNECTION_TLS),
+ property(serviceInfos::property::CONNECTION_TLS_REQUIRED),
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
+ property(serviceInfos::property::SERVER_PORT, "25"),
+ };
+
+ static props smtpsProps = {
+ // SMTP-specific options
+ property("options.need-authentication", serviceInfos::property::TYPE_BOOLEAN, "false"),
+#if VMIME_HAVE_SASL_SUPPORT
+ property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"),
+ property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "false"),
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ property("options.pipelining", serviceInfos::property::TYPE_BOOLEAN, "true"),
+ property("options.chunking", serviceInfos::property::TYPE_BOOLEAN, "true"),
+
+ // Common properties
+ property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED),
+ property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED),
+
+#if VMIME_HAVE_TLS_SUPPORT
+ property(serviceInfos::property::CONNECTION_TLS),
+ property(serviceInfos::property::CONNECTION_TLS_REQUIRED),
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED),
+ property(serviceInfos::property::SERVER_PORT, "465"),
+ };
+
+ return m_smtps ? smtpsProps : smtpProps;
+}
+
+
+const std::vector <serviceInfos::property> SMTPServiceInfos::getAvailableProperties() const {
+
+ std::vector <property> list;
+ const props& p = getProperties();
+
+ // SMTP-specific options
+ list.push_back(p.PROPERTY_OPTIONS_NEEDAUTH);
+#if VMIME_HAVE_SASL_SUPPORT
+ list.push_back(p.PROPERTY_OPTIONS_SASL);
+ list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK);
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ // Common properties
+ list.push_back(p.PROPERTY_AUTH_USERNAME);
+ list.push_back(p.PROPERTY_AUTH_PASSWORD);
+
+#if VMIME_HAVE_TLS_SUPPORT
+ if (!m_smtps) {
+ list.push_back(p.PROPERTY_CONNECTION_TLS);
+ list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED);
+ }
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ list.push_back(p.PROPERTY_SERVER_ADDRESS);
+ list.push_back(p.PROPERTY_SERVER_PORT);
+
+ return list;
+}
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
diff --git a/vmime-master/src/vmime/net/smtp/SMTPServiceInfos.hpp b/vmime-master/src/vmime/net/smtp/SMTPServiceInfos.hpp
new file mode 100644
index 0000000..005a0a2
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPServiceInfos.hpp
@@ -0,0 +1,93 @@
+//
+// 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_NET_SMTP_SMTPSERVICEINFOS_HPP_INCLUDED
+#define VMIME_NET_SMTP_SMTPSERVICEINFOS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/net/serviceInfos.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+/** Information about SMTP service.
+ */
+class VMIME_EXPORT SMTPServiceInfos : public serviceInfos {
+
+public:
+
+ SMTPServiceInfos(const bool smtps);
+
+ struct props {
+ // SMTP-specific options
+ serviceInfos::property PROPERTY_OPTIONS_NEEDAUTH;
+#if VMIME_HAVE_SASL_SUPPORT
+ serviceInfos::property PROPERTY_OPTIONS_SASL;
+ serviceInfos::property PROPERTY_OPTIONS_SASL_FALLBACK;
+#endif // VMIME_HAVE_SASL_SUPPORT
+
+ serviceInfos::property PROPERTY_OPTIONS_PIPELINING;
+ serviceInfos::property PROPERTY_OPTIONS_CHUNKING;
+
+ // Common properties
+ serviceInfos::property PROPERTY_AUTH_USERNAME;
+ serviceInfos::property PROPERTY_AUTH_PASSWORD;
+
+#if VMIME_HAVE_TLS_SUPPORT
+ serviceInfos::property PROPERTY_CONNECTION_TLS;
+ serviceInfos::property PROPERTY_CONNECTION_TLS_REQUIRED;
+#endif // VMIME_HAVE_TLS_SUPPORT
+
+ serviceInfos::property PROPERTY_SERVER_ADDRESS;
+ serviceInfos::property PROPERTY_SERVER_PORT;
+ };
+
+ const props& getProperties() const;
+
+ const string getPropertyPrefix() const;
+ const std::vector <serviceInfos::property> getAvailableProperties() const;
+
+private:
+
+ const bool m_smtps;
+};
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+#endif // VMIME_NET_SMTP_SMTPSERVICEINFOS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/smtp/SMTPTransport.cpp b/vmime-master/src/vmime/net/smtp/SMTPTransport.cpp
new file mode 100644
index 0000000..561bd59
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPTransport.cpp
@@ -0,0 +1,502 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/net/smtp/SMTPTransport.hpp"
+#include "vmime/net/smtp/SMTPResponse.hpp"
+#include "vmime/net/smtp/SMTPCommand.hpp"
+#include "vmime/net/smtp/SMTPCommandSet.hpp"
+#include "vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp"
+#include "vmime/net/smtp/SMTPExceptions.hpp"
+
+#include "vmime/exception.hpp"
+#include "vmime/mailboxList.hpp"
+#include "vmime/message.hpp"
+
+#include "vmime/utility/filteredStream.hpp"
+#include "vmime/utility/stringUtils.hpp"
+#include "vmime/utility/outputStreamSocketAdapter.hpp"
+#include "vmime/utility/streamUtils.hpp"
+#include "vmime/utility/outputStreamAdapter.hpp"
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+SMTPTransport::SMTPTransport(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth,
+ const bool secured
+)
+ : transport(sess, getInfosInstance(), auth),
+ m_isSMTPS(secured),
+ m_needReset(false) {
+
+}
+
+
+SMTPTransport::~SMTPTransport() {
+
+ try {
+
+ if (isConnected()) {
+ disconnect();
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+const string SMTPTransport::getProtocolName() const {
+
+ return "smtp";
+}
+
+
+bool SMTPTransport::isSMTPS() const {
+
+ return m_isSMTPS;
+}
+
+
+void SMTPTransport::connect() {
+
+ if (isConnected()) {
+ throw exceptions::already_connected();
+ }
+
+ m_connection = make_shared <SMTPConnection>(
+ dynamicCast <SMTPTransport>(shared_from_this()), getAuthenticator()
+ );
+
+ m_connection->connect();
+}
+
+
+bool SMTPTransport::isConnected() const {
+
+ return m_connection && m_connection->isConnected();
+}
+
+
+bool SMTPTransport::isSecuredConnection() const {
+
+ if (!m_connection) {
+ return false;
+ }
+
+ return m_connection->isSecuredConnection();
+}
+
+
+shared_ptr <connectionInfos> SMTPTransport::getConnectionInfos() const {
+
+ if (!m_connection) {
+ return null;
+ }
+
+ return m_connection->getConnectionInfos();
+}
+
+
+shared_ptr <SMTPConnection> SMTPTransport::getConnection() {
+
+ return m_connection;
+}
+
+
+void SMTPTransport::disconnect() {
+
+ if (!isConnected()) {
+ throw exceptions::not_connected();
+ }
+
+ m_connection->disconnect();
+ m_connection = null;
+}
+
+
+void SMTPTransport::noop() {
+
+ if (!isConnected()) {
+ throw exceptions::not_connected();
+ }
+
+ m_connection->sendRequest(SMTPCommand::NOOP());
+
+ shared_ptr <SMTPResponse> resp = m_connection->readResponse();
+
+ if (resp->getCode() != 250) {
+ throw SMTPCommandError("NOOP", resp->getText(), resp->getCode(), resp->getEnhancedCode());
+ }
+}
+
+
+// static
+bool SMTPTransport::mailboxNeedsUTF8(const mailbox& mb) {
+
+ bool all7bit =
+ utility::stringUtils::is7bit(mb.getEmail().getLocalName().getBuffer())
+ && utility::stringUtils::is7bit(mb.getEmail().getDomainName().getBuffer());
+
+ for (size_t i = 0, n = mb.getName().getWordCount() ; all7bit && i != n ; ++i) {
+ all7bit = utility::stringUtils::is7bit(mb.getName().getWordAt(i)->getBuffer());
+ }
+
+ return !all7bit;
+}
+
+
+void SMTPTransport::sendEnvelope(
+ const mailbox& expeditor,
+ const mailboxList& recipients,
+ const mailbox& sender,
+ bool sendDATACommand,
+ const size_t size,
+ const dsnAttributes& dsnAttrs
+) {
+
+ // If no recipient/expeditor was found, throw an exception
+ if (recipients.isEmpty()) {
+ throw exceptions::no_recipient();
+ } else if (expeditor.isEmpty()) {
+ throw exceptions::no_expeditor();
+ }
+
+ // If DSN extension is used, ensure it is supported by the server
+ if (!dsnAttrs.isEmpty() && !m_connection->hasExtension("DSN")) {
+ throw SMTPDSNExtensionNotSupportedException();
+ }
+
+
+ const bool needReset = m_needReset;
+ const bool hasPipelining = m_connection->hasExtension("PIPELINING") &&
+ getInfos().getPropertyValue <bool>(getSession(),
+ dynamic_cast <const SMTPServiceInfos&>(getInfos()).getProperties().PROPERTY_OPTIONS_PIPELINING);
+
+ shared_ptr <SMTPResponse> resp;
+ shared_ptr <SMTPCommandSet> commands = SMTPCommandSet::create(hasPipelining);
+
+ // Emit a "RSET" command if we previously sent a message on this connection
+ if (needReset) {
+ commands->addCommand(SMTPCommand::RSET());
+ }
+
+ // Check whether we need SMTPUTF8
+ const bool hasSMTPUTF8 = m_connection->hasExtension("SMTPUTF8");
+ bool needSMTPUTF8 = false;
+
+ if (!sender.isEmpty()) {
+ needSMTPUTF8 = needSMTPUTF8 || mailboxNeedsUTF8(sender);
+ } else {
+ needSMTPUTF8 = needSMTPUTF8 || mailboxNeedsUTF8(expeditor);
+ }
+
+ for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) {
+
+ const mailbox& mbox = *recipients.getMailboxAt(i);
+ needSMTPUTF8 = needSMTPUTF8 || mailboxNeedsUTF8(mbox);
+ }
+
+ // Emit the "MAIL" command
+ const bool hasSize = m_connection->hasExtension("SIZE");
+
+ if (!sender.isEmpty()) {
+
+ commands->addCommand(
+ SMTPCommand::MAIL(
+ sender, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0,
+ dsnAttrs.getNotificationConditions(),
+ dsnAttrs.getEnvelopId()
+ )
+ );
+
+ } else {
+
+ commands->addCommand(
+ SMTPCommand::MAIL(
+ expeditor, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0,
+ dsnAttrs.getNotificationConditions(),
+ dsnAttrs.getEnvelopId()
+ )
+ );
+ }
+
+ // Now, we will need to reset next time
+ m_needReset = true;
+
+ // Emit a "RCPT TO" command for each recipient
+ for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) {
+
+ const mailbox& mbox = *recipients.getMailboxAt(i);
+ commands->addCommand(SMTPCommand::RCPT(mbox, hasSMTPUTF8 && needSMTPUTF8,
+ dsnAttrs.getNotificationConditions()));
+ }
+
+ // Prepare sending of message data
+ if (sendDATACommand) {
+ commands->addCommand(SMTPCommand::DATA());
+ }
+
+ // Read response for "RSET" command
+ if (needReset) {
+
+ commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer());
+
+ resp = m_connection->readResponse();
+
+ if (resp->getCode() != 250 &&
+ resp->getCode() != 200) { // RFC-876: << In reply to a RSET and/or a NOOP command,
+ // some servers reply "200" >>
+
+ disconnect();
+
+ throw SMTPCommandError(
+ commands->getLastCommandSent()->getText(), resp->getText(),
+ resp->getCode(), resp->getEnhancedCode()
+ );
+ }
+ }
+
+ // Read response for "MAIL" command
+ commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer());
+
+ if ((resp = m_connection->readResponse())->getCode() != 250) {
+
+ // SIZE extension: insufficient system storage
+ if (resp->getCode() == 452) {
+
+ throw SMTPMessageSizeExceedsCurLimitsException(
+ SMTPCommandError(
+ commands->getLastCommandSent()->getText(), resp->getText(),
+ resp->getCode(), resp->getEnhancedCode()
+ )
+ );
+
+ // SIZE extension: message size exceeds fixed maximum message size
+ } else if (resp->getCode() == 552) {
+
+ throw SMTPMessageSizeExceedsMaxLimitsException(
+ SMTPCommandError(
+ commands->getLastCommandSent()->getText(), resp->getText(),
+ resp->getCode(), resp->getEnhancedCode()
+ )
+ );
+
+ // Other error
+ } else {
+
+ throw SMTPCommandError(
+ commands->getLastCommandSent()->getText(), resp->getText(),
+ resp->getCode(), resp->getEnhancedCode()
+ );
+ }
+ }
+
+ // Read responses for "RCPT TO" commands
+ for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) {
+
+ commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer());
+
+ resp = m_connection->readResponse();
+
+ if (resp->getCode() != 250 &&
+ resp->getCode() != 251) {
+
+ // SIZE extension: insufficient system storage
+ if (resp->getCode() == 452) {
+
+ throw SMTPMessageSizeExceedsCurLimitsException(
+ SMTPCommandError(
+ commands->getLastCommandSent()->getText(), resp->getText(),
+ resp->getCode(), resp->getEnhancedCode()
+ )
+ );
+
+ // SIZE extension: message size exceeds fixed maximum message size
+ } else if (resp->getCode() == 552) {
+
+ throw SMTPMessageSizeExceedsMaxLimitsException(
+ SMTPCommandError(
+ commands->getLastCommandSent()->getText(), resp->getText(),
+ resp->getCode(), resp->getEnhancedCode()
+ )
+ );
+
+ // Other error
+ } else {
+
+ throw SMTPCommandError(
+ commands->getLastCommandSent()->getText(), resp->getText(),
+ resp->getCode(), resp->getEnhancedCode()
+ );
+ }
+ }
+ }
+
+ // Read response for "DATA" command
+ if (sendDATACommand) {
+
+ commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer());
+
+ if ((resp = m_connection->readResponse())->getCode() != 354) {
+
+ throw SMTPCommandError(
+ commands->getLastCommandSent()->getText(), resp->getText(),
+ resp->getCode(), resp->getEnhancedCode()
+ );
+ }
+ }
+}
+
+
+void SMTPTransport::send(
+ const mailbox& expeditor,
+ const mailboxList& recipients,
+ utility::inputStream& is,
+ const size_t size,
+ utility::progressListener* progress,
+ const mailbox& sender,
+ const dsnAttributes& dsnAttrs
+) {
+
+ if (!isConnected()) {
+ throw exceptions::not_connected();
+ }
+
+ // Send message envelope
+ sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ true, size,
+ dsnAttrs);
+
+ // Send the message data
+ // Stream copy with "\n." to "\n.." transformation
+ utility::outputStreamSocketAdapter sos(*m_connection->getSocket());
+ utility::dotFilteredOutputStream fos(sos);
+
+ utility::bufferedStreamCopy(is, fos, size, progress);
+
+ fos.flush();
+
+ // Send end-of-data delimiter
+ m_connection->getSocket()->send("\r\n.\r\n");
+
+ if (m_connection->getTracer()) {
+ m_connection->getTracer()->traceSendBytes(size);
+ m_connection->getTracer()->traceSend(".");
+ }
+
+ shared_ptr <SMTPResponse> resp;
+
+ if ((resp = m_connection->readResponse())->getCode() != 250) {
+ throw SMTPCommandError("DATA", resp->getText(), resp->getCode(), resp->getEnhancedCode());
+ }
+}
+
+
+void SMTPTransport::send(
+ const shared_ptr <vmime::message>& msg,
+ const mailbox& expeditor,
+ const mailboxList& recipients,
+ utility::progressListener* progress,
+ const mailbox& sender,
+ const dsnAttributes& dsnAttrs
+) {
+
+ if (!isConnected()) {
+ throw exceptions::not_connected();
+ }
+
+ // Generate the message with Internationalized Email support,
+ // if this is supported by the SMTP server
+ generationContext ctx(generationContext::getDefaultContext());
+ ctx.setInternationalizedEmailSupport(m_connection->hasExtension("SMTPUTF8"));
+
+ // If CHUNKING is not supported, generate the message to a temporary
+ // buffer then use the send() method which takes an inputStream
+ if (!m_connection->hasExtension("CHUNKING") ||
+ !getInfos().getPropertyValue <bool>(getSession(),
+ dynamic_cast <const SMTPServiceInfos&>(getInfos()).getProperties().PROPERTY_OPTIONS_CHUNKING)) {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter ossAdapter(oss);
+
+ msg->generate(ctx, ossAdapter);
+
+ const string& str(oss.str());
+
+ utility::inputStreamStringAdapter isAdapter(str);
+
+ send(expeditor, recipients, isAdapter, str.length(), progress, sender, dsnAttrs);
+ return;
+ }
+
+ // Send message envelope
+ const size_t msgSize = msg->getGeneratedSize(ctx);
+
+ sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ false, msgSize, dsnAttrs);
+
+ // Send the message by chunks
+ SMTPChunkingOutputStreamAdapter chunkStream(m_connection, msgSize, progress);
+
+ msg->generate(ctx, chunkStream);
+
+ chunkStream.flush();
+}
+
+
+
+// Service infos
+
+SMTPServiceInfos SMTPTransport::sm_infos(false);
+
+
+const serviceInfos& SMTPTransport::getInfosInstance() {
+
+ return sm_infos;
+}
+
+
+const serviceInfos& SMTPTransport::getInfos() const {
+
+ return sm_infos;
+}
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
diff --git a/vmime-master/src/vmime/net/smtp/SMTPTransport.hpp b/vmime-master/src/vmime/net/smtp/SMTPTransport.hpp
new file mode 100644
index 0000000..cd7c712
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/SMTPTransport.hpp
@@ -0,0 +1,144 @@
+//
+// 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_NET_SMTP_SMTPTRANSPORT_HPP_INCLUDED
+#define VMIME_NET_SMTP_SMTPTRANSPORT_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+
+#include "vmime/net/transport.hpp"
+#include "vmime/net/socket.hpp"
+#include "vmime/net/timeoutHandler.hpp"
+
+#include "vmime/net/smtp/SMTPServiceInfos.hpp"
+#include "vmime/net/smtp/SMTPConnection.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace smtp {
+
+
+class SMTPCommand;
+
+
+/** SMTP transport service.
+ */
+class VMIME_EXPORT SMTPTransport : public transport {
+
+public:
+
+ SMTPTransport(
+ const shared_ptr <session>& sess,
+ const shared_ptr <security::authenticator>& auth,
+ const bool secured = false
+ );
+
+ ~SMTPTransport();
+
+ const string getProtocolName() const;
+
+ static const serviceInfos& getInfosInstance();
+ const serviceInfos& getInfos() const;
+
+ void connect();
+ bool isConnected() const;
+ void disconnect();
+
+ void noop();
+
+ void send(
+ const mailbox& expeditor,
+ const mailboxList& recipients,
+ utility::inputStream& is,
+ const size_t size,
+ utility::progressListener* progress = NULL,
+ const mailbox& sender = mailbox(),
+ const dsnAttributes& dsnAttrs = dsnAttributes()
+ );
+
+ void send(
+ const shared_ptr <vmime::message>& msg,
+ const mailbox& expeditor,
+ const mailboxList& recipients,
+ utility::progressListener* progress = NULL,
+ const mailbox& sender = mailbox(),
+ const dsnAttributes& dsnAttrs = dsnAttributes()
+ );
+
+ bool isSecuredConnection() const;
+ shared_ptr <connectionInfos> getConnectionInfos() const;
+ shared_ptr <SMTPConnection> getConnection();
+
+ bool isSMTPS() const;
+
+private:
+
+ static bool mailboxNeedsUTF8(const mailbox& mb);
+
+ /** Send the MAIL and RCPT commands to the server, checking the
+ * response, and using pipelining if supported by the server.
+ * Optionally, the DATA command can also be sent.
+ *
+ * @param expeditor expeditor mailbox
+ * @param recipients list of recipient mailboxes
+ * @param sender envelope sender (if empty, expeditor will be used)
+ * @param sendDATACommand if true, the DATA command will be sent
+ * @param size message size, in bytes (or 0, if not known)
+ * @param dsnAttributes attributes for Delivery Status Notification (if needed)
+ */
+ void sendEnvelope(
+ const mailbox& expeditor,
+ const mailboxList& recipients,
+ const mailbox& sender,
+ bool sendDATACommand,
+ const size_t size,
+ const dsnAttributes& dsnAttrs = dsnAttributes()
+ );
+
+
+ shared_ptr <SMTPConnection> m_connection;
+
+
+ const bool m_isSMTPS;
+
+ bool m_needReset;
+
+ // Service infos
+ static SMTPServiceInfos sm_infos;
+};
+
+
+} // smtp
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP
+
+#endif // VMIME_NET_SMTP_SMTPTRANSPORT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/smtp/smtp.hpp b/vmime-master/src/vmime/net/smtp/smtp.hpp
new file mode 100644
index 0000000..4c0b17d
--- /dev/null
+++ b/vmime-master/src/vmime/net/smtp/smtp.hpp
@@ -0,0 +1,33 @@
+//
+// 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_NET_SMTP_SMTP_HPP_INCLUDED
+#define VMIME_NET_SMTP_SMTP_HPP_INCLUDED
+
+
+#include "vmime/net/smtp/SMTPTransport.hpp"
+#include "vmime/net/smtp/SMTPSTransport.hpp"
+#include "vmime/net/smtp/SMTPExceptions.hpp"
+
+
+#endif // VMIME_NET_SMTP_SMTP_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/socket.hpp b/vmime-master/src/vmime/net/socket.hpp
new file mode 100644
index 0000000..a236a9f
--- /dev/null
+++ b/vmime-master/src/vmime/net/socket.hpp
@@ -0,0 +1,223 @@
+//
+// 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_NET_SOCKET_HPP_INCLUDED
+#define VMIME_NET_SOCKET_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/base.hpp"
+
+#include "vmime/net/timeoutHandler.hpp"
+#include "vmime/net/tracer.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+/** Interface for connecting to servers.
+ */
+class VMIME_EXPORT socket : public object {
+
+public:
+
+ enum Status {
+ STATUS_WOULDBLOCK = 0xf, /**< The operation would block. Retry later. */
+ STATUS_WANT_READ = 0x1, /**< The socket wants to read data, retry when data is available. */
+ STATUS_WANT_WRITE = 0x2 /**< The socket wants to write data, retry when data can be written. */
+ };
+
+
+ virtual ~socket() { }
+
+
+ /** Connect to the specified address and port.
+ *
+ * @param address server address (this can be a full qualified domain name
+ * or an IP address, doesn't matter)
+ * @param port server port
+ */
+ virtual void connect(const string& address, const port_t port) = 0;
+
+ /** Disconnect from the server.
+ */
+ virtual void disconnect() = 0;
+
+ /** Test whether this socket is connected.
+ *
+ * @return true if the socket is connected, false otherwise
+ */
+ virtual bool isConnected() const = 0;
+
+ /** Block until new data is available for reading. The function will
+ * timeout after msecs milliseconds.
+ *
+ * @param timeout maximum wait time, in milliseconds (default is 30000);
+ * resolution is 10ms
+ * @return true if data is available, or false if the operation timed out
+ */
+ virtual bool waitForRead(const int msecs = 30000) = 0;
+
+ /** Block until pending data has been written and new data can be written.
+ * The function will timeout after msecs milliseconds.
+ *
+ * @param timeout maximum wait time, in milliseconds (default is 30000);
+ * resolution is 10ms
+ * @return true if new data can be written immediately, or false if the
+ * operation timed out
+ */
+ virtual bool waitForWrite(const int msecs = 30000) = 0;
+
+ /** Receive text data from the socket.
+ *
+ * @param buffer buffer in which to write received data
+ */
+ virtual void receive(string& buffer) = 0;
+
+ /** Receive raw data from the socket.
+ *
+ * @param buffer buffer in which to write received data
+ * @param count maximum number of bytes to receive (size of buffer)
+ * @return number of bytes received/written into output buffer
+ */
+ virtual size_t receiveRaw(byte_t* buffer, const size_t count) = 0;
+
+ /** Send text data to the socket.
+ *
+ * @param buffer data to send
+ */
+ virtual void send(const string& buffer) = 0;
+
+ /** Send text data to the socket.
+ *
+ * @param str null-terminated string
+ */
+ virtual void send(const char* str) = 0;
+
+ /** Send raw data to the socket.
+ *
+ * @param buffer data to send
+ * @param count number of bytes to send (size of buffer)
+ */
+ virtual void sendRaw(const byte_t* buffer, const size_t count) = 0;
+
+ /** Send raw data to the socket.
+ * Function may returns before all data is sent.
+ *
+ * @param buffer data to send
+ * @param count number of bytes to send (size of buffer)
+ * @return number of bytes sent
+ */
+ virtual size_t sendRawNonBlocking(const byte_t* buffer, const size_t count) = 0;
+
+ /** Return the preferred maximum block size when reading
+ * from or writing to this stream.
+ *
+ * @return block size, in bytes
+ */
+ virtual size_t getBlockSize() const = 0;
+
+ /** Return the current status of this socket.
+ *
+ * @return status flags for this socket
+ */
+ virtual unsigned int getStatus() const = 0;
+
+ /** Return the hostname of peer this socket is connected to.
+ *
+ * @return name of the peer, or numeric address if it cannot be found
+ */
+ virtual const string getPeerName() const = 0;
+
+ /** Return the address of peer this socket is connected to.
+ *
+ * @return numeric address of the peer
+ */
+ virtual const string getPeerAddress() const = 0;
+
+ /** Return the timeout handler associated with this socket.
+ *
+ * @return timeout handler, or NULL if none is set
+ */
+ virtual shared_ptr <timeoutHandler> getTimeoutHandler() = 0;
+
+ /** Set the tracer used by this socket. Tracer will only be used
+ * to report socket-specific events such as connection (not when
+ * sending/receiving data).
+ *
+ * @param tracer tracer to use
+ */
+ virtual void setTracer(const shared_ptr <tracer>& tracer) = 0;
+
+ /** Return the tracer used by this socket.
+ *
+ * @return tracer, or NULL if none is set
+ */
+ virtual shared_ptr <tracer> getTracer() = 0;
+
+protected:
+
+ socket() { }
+
+private:
+
+ socket(const socket&) : object() { }
+};
+
+
+/** A class to create 'socket' objects.
+ */
+class socketFactory : public object {
+
+public:
+
+ virtual ~socketFactory() { }
+
+ /** Creates a socket without timeout handler.
+ *
+ * @return a new socket
+ */
+ virtual shared_ptr <socket> create() = 0;
+
+ /** Creates a socket with the specified timeout handler.
+ *
+ * @param th timeout handler
+ * @return a new socket
+ */
+ virtual shared_ptr <socket> create(const shared_ptr <timeoutHandler>& th) = 0;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_SOCKET_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/store.cpp b/vmime-master/src/vmime/net/store.cpp
new file mode 100644
index 0000000..3c9a66d
--- /dev/null
+++ b/vmime-master/src/vmime/net/store.cpp
@@ -0,0 +1,57 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/store.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+store::store(
+ const shared_ptr <session>& sess,
+ const serviceInfos& infos,
+ const shared_ptr <security::authenticator>& auth
+)
+ : service(sess, infos, auth) {
+
+}
+
+
+store::Type store::getType() const {
+
+ return TYPE_STORE;
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
diff --git a/vmime-master/src/vmime/net/store.hpp b/vmime-master/src/vmime/net/store.hpp
new file mode 100644
index 0000000..a96f267
--- /dev/null
+++ b/vmime-master/src/vmime/net/store.hpp
@@ -0,0 +1,115 @@
+//
+// 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_NET_STORE_HPP_INCLUDED
+#define VMIME_NET_STORE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/service.hpp"
+#include "vmime/net/folder.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+/** A store service.
+ * Encapsulate protocols that provide access to user's mail drop.
+ */
+class VMIME_EXPORT store : public service {
+
+protected:
+
+ store(
+ const shared_ptr <session>& sess,
+ const serviceInfos& infos,
+ const shared_ptr <security::authenticator>& auth
+ );
+
+public:
+
+ /** Return the default folder. This is protocol dependent
+ * and usually is the INBOX folder.
+ *
+ * @return default folder
+ */
+ virtual shared_ptr <folder> getDefaultFolder() = 0;
+
+ /** Return the root folder. This is protocol dependent
+ * and usually is the user's mail drop root folder.
+ *
+ * @return root folder
+ */
+ virtual shared_ptr <folder> getRootFolder() = 0;
+
+ /** Return the folder specified by the path.
+ *
+ * @param path absolute folder path
+ * @return folder at the specified path
+ */
+ virtual shared_ptr <folder> getFolder(const folder::path& path) = 0;
+
+ /** Test whether the specified folder name is a syntactically
+ * a valid name.
+ *
+ * @return true if the specified folder name is valid, false otherwise
+ */
+ virtual bool isValidFolderName(const folder::path::component& name) const = 0;
+
+ /** Store capabilities. */
+ enum Capabilities {
+ CAPABILITY_CREATE_FOLDER = (1 << 0), /**< Can create folders. */
+ CAPABILITY_RENAME_FOLDER = (1 << 1), /**< Can rename folders. */
+ CAPABILITY_ADD_MESSAGE = (1 << 2), /**< Can append message to folders. */
+ CAPABILITY_COPY_MESSAGE = (1 << 3), /**< Can copy messages from a folder to another one. */
+ CAPABILITY_DELETE_MESSAGE = (1 << 4), /**< Can delete messages. */
+ CAPABILITY_PARTIAL_FETCH = (1 << 5), /**< Is partial fetch supported? */
+ CAPABILITY_MESSAGE_FLAGS = (1 << 6), /**< Can set flags on messages. */
+ CAPABILITY_EXTRACT_PART = (1 << 7) /**< Can extract a specific part of the message. */
+ };
+
+ /** Return the features supported by this service. This is
+ * a combination of store::CAPABILITY_xxx flags.
+ *
+ * @return features supported by this service
+ */
+ virtual int getCapabilities() const = 0;
+
+
+ Type getType() const;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_STORE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/timeoutHandler.hpp b/vmime-master/src/vmime/net/timeoutHandler.hpp
new file mode 100644
index 0000000..fed1bc4
--- /dev/null
+++ b/vmime-master/src/vmime/net/timeoutHandler.hpp
@@ -0,0 +1,89 @@
+//
+// 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_NET_TIMEOUTHANDLER_HPP_INCLUDED
+#define VMIME_NET_TIMEOUTHANDLER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/types.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+/** A class to manage timeouts in messaging services. This can be used
+ * to stop operations that takes too much time to complete (ie. no data
+ * received from the server for a long time if the network link is down).
+ */
+class VMIME_EXPORT timeoutHandler : public object {
+
+public:
+
+ virtual ~timeoutHandler() { }
+
+ /** Called to test if the time limit has been reached.
+ *
+ * @return true if the timeout delay is elapsed
+ */
+ virtual bool isTimeOut() = 0;
+
+ /** Called to reset the timeout counter.
+ */
+ virtual void resetTimeOut() = 0;
+
+ /** Called when the time limit has been reached (when
+ * isTimeOut() returned true).
+ *
+ * @return true to continue (and reset the timeout)
+ * or false to cancel the current operation
+ */
+ virtual bool handleTimeOut() = 0;
+};
+
+
+/** A class to create 'timeoutHandler' objects.
+ */
+class timeoutHandlerFactory : public object {
+
+public:
+
+ virtual ~timeoutHandlerFactory() { }
+
+ virtual shared_ptr <timeoutHandler> create() = 0;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_TIMEOUTHANDLER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/tls/TLSProperties.cpp b/vmime-master/src/vmime/net/tls/TLSProperties.cpp
new file mode 100644
index 0000000..f7721d4
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/TLSProperties.cpp
@@ -0,0 +1,44 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/net/tls/TLSProperties.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
diff --git a/vmime-master/src/vmime/net/tls/TLSProperties.hpp b/vmime-master/src/vmime/net/tls/TLSProperties.hpp
new file mode 100644
index 0000000..94341ca
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/TLSProperties.hpp
@@ -0,0 +1,105 @@
+//
+// 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_NET_TLS_TLSPROPERTIES_HPP_INCLUDED
+#define VMIME_NET_TLS_TLSPROPERTIES_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/types.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+/** Holds options for a TLS session.
+ */
+class VMIME_EXPORT TLSProperties : public object {
+
+public:
+
+ TLSProperties();
+ TLSProperties(const TLSProperties&);
+
+
+ /** Predefined generic cipher suites (work with all TLS libraries). */
+ enum GenericCipherSuite {
+
+ CIPHERSUITE_HIGH, /**< High encryption cipher suites (> 128 bits). */
+ CIPHERSUITE_MEDIUM, /**< Medium encryption cipher suites (>= 128 bits). */
+ CIPHERSUITE_LOW, /**< Low encryption cipher suites (>= 64 bits). */
+
+ CIPHERSUITE_DEFAULT /**< Default cipher suite. */
+ };
+
+ /** Sets the cipher suite preferences for a SSL/TLS session, using
+ * predefined, generic suites. This works with all underlying TLS
+ * libraries (OpenSSL and GNU TLS).
+ *
+ * @param cipherSuite predefined cipher suite
+ */
+ void setCipherSuite(const GenericCipherSuite cipherSuite);
+
+ /** Sets the cipher suite preferences for a SSL/TLS session, using
+ * a character string. The format and meaning of the string depend
+ * on the underlying TLS library.
+ *
+ * For GNU TLS, read this:
+ * http://gnutls.org/manual/html_node/Priority-Strings.html
+ *
+ * For OpenSSL, read this:
+ * http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS
+ *
+ * @param cipherSuite cipher suite as a string
+ */
+ void setCipherSuite(const string& cipherSuite);
+
+ /** Returns the cipher suite preferences for a SSL/TLS session, as
+ * a character string. The format and meaning of the string depend
+ * on the underlying TLS library (see setCipherSuite() method).
+ *
+ * @return cipher suite string
+ */
+ const string getCipherSuite() const;
+
+private:
+
+ shared_ptr <object> m_data;
+};
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+#endif // VMIME_NET_TLS_TLSPROPERTIES_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp b/vmime-master/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp
new file mode 100644
index 0000000..055dfea
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp
@@ -0,0 +1,77 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/net/tls/TLSSecuredConnectionInfos.hpp"
+#include "vmime/net/tls/TLSSession.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+TLSSecuredConnectionInfos::TLSSecuredConnectionInfos(
+ const string& host,
+ const port_t port,
+ const shared_ptr <TLSSession>& tlsSession,
+ const shared_ptr <TLSSocket>& tlsSocket
+)
+ : m_host(host),
+ m_port(port),
+ m_tlsSession(tlsSession),
+ m_tlsSocket(tlsSocket) {
+
+}
+
+
+const string TLSSecuredConnectionInfos::getHost() const {
+
+ return m_host;
+}
+
+
+port_t TLSSecuredConnectionInfos::getPort() const {
+
+ return m_port;
+}
+
+
+shared_ptr <const security::cert::certificateChain> TLSSecuredConnectionInfos::getPeerCertificates() const {
+
+ return m_tlsSocket->getPeerCertificates();
+}
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
diff --git a/vmime-master/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp b/vmime-master/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp
new file mode 100644
index 0000000..c65e9d2
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp
@@ -0,0 +1,88 @@
+//
+// 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_NET_TLSSECUREDCONNECTIONINFOS_HPP_INCLUDED
+#define VMIME_NET_TLSSECUREDCONNECTIONINFOS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/net/securedConnectionInfos.hpp"
+
+#include "vmime/security/cert/certificateChain.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+class TLSSession;
+class TLSSocket;
+
+
+/** Information about a TLS-secured connection used by a service.
+ */
+class VMIME_EXPORT TLSSecuredConnectionInfos : public securedConnectionInfos {
+
+public:
+
+ TLSSecuredConnectionInfos(
+ const string& host,
+ const port_t port,
+ const shared_ptr <TLSSession>& tlsSession,
+ const shared_ptr <TLSSocket>& tlsSocket
+ );
+
+ const string getHost() const;
+ port_t getPort() const;
+
+ /** Return the peer's certificate (chain) as sent by the peer.
+ *
+ * @return server certificate chain
+ */
+ shared_ptr <const security::cert::certificateChain> getPeerCertificates() const;
+
+private:
+
+ string m_host;
+ port_t m_port;
+
+ shared_ptr <TLSSession> m_tlsSession;
+ shared_ptr <TLSSocket> m_tlsSocket;
+};
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+#endif // VMIME_NET_TLSSECUREDCONNECTIONINFOS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/tls/TLSSession.cpp b/vmime-master/src/vmime/net/tls/TLSSession.cpp
new file mode 100644
index 0000000..ab8b7c3
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/TLSSession.cpp
@@ -0,0 +1,48 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/net/tls/TLSSession.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+TLSSession::TLSSession() {
+
+}
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
diff --git a/vmime-master/src/vmime/net/tls/TLSSession.hpp b/vmime-master/src/vmime/net/tls/TLSSession.hpp
new file mode 100644
index 0000000..9e84fe7
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/TLSSession.hpp
@@ -0,0 +1,96 @@
+//
+// 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_NET_TLS_TLSSESSION_HPP_INCLUDED
+#define VMIME_NET_TLS_TLSSESSION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/tls/TLSSocket.hpp"
+#include "vmime/net/tls/TLSProperties.hpp"
+
+#include "vmime/security/cert/certificateVerifier.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+/** Describe a TLS connection between a client and a server.
+ */
+class VMIME_EXPORT TLSSession : public object, public enable_shared_from_this <TLSSession> {
+
+public:
+
+ /** Create and initialize a new TLS session.
+ *
+ * @param cv object responsible for verifying certificates
+ * sent by the server
+ * @param props TLS properties for this session
+ * @return a new TLS session
+ */
+ static shared_ptr <TLSSession> create(
+ const shared_ptr <security::cert::certificateVerifier>& cv,
+ const shared_ptr <TLSProperties>& props
+ );
+
+ /** Create a new socket that adds a TLS security layer around
+ * an existing socket. You should create only one socket
+ * per session.
+ *
+ * @param sok socket to wrap
+ * @return TLS socket wrapper
+ */
+ virtual shared_ptr <TLSSocket> getSocket(const shared_ptr <socket>& sok) = 0;
+
+ /** Get the object responsible for verifying certificates when
+ * using secured connections (TLS/SSL).
+ */
+ virtual shared_ptr <security::cert::certificateVerifier> getCertificateVerifier() = 0;
+
+protected:
+
+ TLSSession();
+
+private:
+
+ TLSSession(const TLSSession&);
+};
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+#endif // VMIME_NET_TLS_TLSSESSION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/tls/TLSSocket.cpp b/vmime-master/src/vmime/net/tls/TLSSocket.cpp
new file mode 100644
index 0000000..fbca082
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/TLSSocket.cpp
@@ -0,0 +1,44 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/net/tls/TLSSocket.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
diff --git a/vmime-master/src/vmime/net/tls/TLSSocket.hpp b/vmime-master/src/vmime/net/tls/TLSSocket.hpp
new file mode 100644
index 0000000..ca50aa8
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/TLSSocket.hpp
@@ -0,0 +1,88 @@
+//
+// 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_NET_TLS_TLSSOCKET_HPP_INCLUDED
+#define VMIME_NET_TLS_TLSSOCKET_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/exception.hpp"
+
+#include "vmime/net/socket.hpp"
+#include "vmime/net/timeoutHandler.hpp"
+
+#include "vmime/security/cert/certificateChain.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+class TLSSession;
+
+
+/** Add a TLS security layer to an existing socket.
+ */
+class VMIME_EXPORT TLSSocket : public socket {
+
+public:
+
+ /** Create a new socket object that adds a security layer
+ * around an existing socket.
+ *
+ * @param session TLS session
+ * @param sok socket to wrap
+ */
+ static shared_ptr <TLSSocket> wrap(const shared_ptr <TLSSession>& session, const shared_ptr <socket>& sok);
+
+ /** Starts a TLS handshake on this connection.
+ *
+ * @throw exceptions::tls_exception if a fatal error occurs
+ * during the negociation process, exceptions::operation_timed_out
+ * if a time-out occurs
+ */
+ virtual void handshake() = 0;
+
+ /** Return the peer's certificate (chain) as sent by the peer.
+ *
+ * @return server certificate chain, or NULL if the handshake
+ * has not been performed yet
+ */
+ virtual shared_ptr <security::cert::certificateChain> getPeerCertificates() = 0;
+};
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+#endif // VMIME_NET_TLS_TLSSOCKET_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp b/vmime-master/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp
new file mode 100644
index 0000000..b2996fb
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp
@@ -0,0 +1,113 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+
+#include "vmime/base.hpp"
+#include "vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp"
+
+#include <gnutls/gnutls.h>
+#if GNUTLS_VERSION_NUMBER < 0x030000
+#include <gnutls/extra.h>
+#endif
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+TLSProperties::TLSProperties()
+ : m_data(make_shared <TLSProperties_GnuTLS>()) {
+
+ setCipherSuite(CIPHERSUITE_DEFAULT);
+}
+
+
+TLSProperties::TLSProperties(const TLSProperties& props)
+ : object(),
+ m_data(make_shared <TLSProperties_GnuTLS>()) {
+
+ *dynamicCast <TLSProperties_GnuTLS>(m_data) = *dynamicCast <TLSProperties_GnuTLS>(props.m_data);
+}
+
+
+void TLSProperties::setCipherSuite(const GenericCipherSuite cipherSuite) {
+
+ switch (cipherSuite) {
+
+ case CIPHERSUITE_HIGH:
+
+ setCipherSuite("SECURE256:%SSL3_RECORD_VERSION");
+ break;
+
+ case CIPHERSUITE_MEDIUM:
+
+ setCipherSuite("SECURE128:%SSL3_RECORD_VERSION");
+ break;
+
+ case CIPHERSUITE_LOW:
+
+ setCipherSuite("NORMAL:%SSL3_RECORD_VERSION");
+ break;
+
+ default:
+ case CIPHERSUITE_DEFAULT:
+
+ setCipherSuite("NORMAL:%SSL3_RECORD_VERSION");
+ break;
+ }
+}
+
+
+void TLSProperties::setCipherSuite(const string& cipherSuite) {
+
+ dynamicCast <TLSProperties_GnuTLS>(m_data)->cipherSuite = cipherSuite;
+}
+
+
+const string TLSProperties::getCipherSuite() const {
+
+ return dynamicCast <TLSProperties_GnuTLS>(m_data)->cipherSuite;
+}
+
+
+
+TLSProperties_GnuTLS& TLSProperties_GnuTLS::operator=(const TLSProperties_GnuTLS& other) {
+
+ cipherSuite = other.cipherSuite;
+
+ return *this;
+}
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
diff --git a/vmime-master/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp b/vmime-master/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp
new file mode 100644
index 0000000..96bbaea
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp
@@ -0,0 +1,68 @@
+//
+// 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_NET_TLS_TLSPROPERTIES_GNUTLS_HPP_INCLUDED
+#define VMIME_NET_TLS_TLSPROPERTIES_GNUTLS_HPP_INCLUDED
+
+
+#ifndef VMIME_BUILDING_DOC
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/tls/TLSProperties.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+class TLSProperties_GnuTLS : public object {
+
+public:
+
+ TLSProperties_GnuTLS& operator=(const TLSProperties_GnuTLS& other);
+
+
+ string cipherSuite;
+};
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+#endif // VMIME_BUILDING_DOC
+
+#endif // VMIME_NET_TLS_TLSPROPERTIES_GNUTLS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp b/vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp
new file mode 100644
index 0000000..8586537
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp
@@ -0,0 +1,313 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+
+#include <gnutls/gnutls.h>
+#if GNUTLS_VERSION_NUMBER < 0x030000
+#include <gnutls/extra.h>
+#endif
+
+
+// Dependency on gcrypt is not needed since GNU TLS version 2.12.
+// See here: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=638651
+#if GNUTLS_VERSION_NUMBER <= 0x020b00
+# define VMIME_GNUTLS_NEEDS_GCRYPT 1
+#endif
+
+#if VMIME_HAVE_PTHREAD
+# include <pthread.h>
+# if VMIME_GNUTLS_NEEDS_GCRYPT
+# include <gcrypt.h>
+# endif
+# include <errno.h>
+#endif // VMIME_HAVE_PTHREAD
+
+#include "vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp"
+#include "vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp"
+#include "vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp"
+
+#include "vmime/exception.hpp"
+
+
+// Enable GnuTLS debugging by defining GNUTLS_DEBUG
+//#define GNUTLS_DEBUG 1
+
+
+#include <sstream>
+#include <iomanip>
+
+#if VMIME_DEBUG && GNUTLS_DEBUG
+ #include <iostream>
+#endif // VMIME_DEBUG && GNUTLS_DEBUG
+
+
+#if VMIME_HAVE_PTHREAD && VMIME_GNUTLS_NEEDS_GCRYPT && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL)
+extern "C"
+{
+ GCRY_THREAD_OPTION_PTHREAD_IMPL;
+}
+#endif // VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+#ifndef VMIME_BUILDING_DOC
+
+// Initialize GNU TLS library
+struct TLSGlobal {
+
+ TLSGlobal() {
+
+#if VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL)
+ #if VMIME_GNUTLS_NEEDS_GCRYPT
+ gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+ #endif // VMIME_GNUTLS_NEEDS_GCRYPT
+#endif // VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL
+
+ gnutls_global_init();
+ //gnutls_global_init_extra();
+
+#if VMIME_DEBUG && GNUTLS_DEBUG
+ gnutls_global_set_log_function(TLSLogFunc);
+ gnutls_global_set_log_level(10);
+#endif // VMIME_DEBUG && GNUTLS_DEBUG
+
+ gnutls_anon_allocate_client_credentials(&anonCred);
+ gnutls_certificate_allocate_credentials(&certCred);
+ }
+
+ ~TLSGlobal() {
+
+ gnutls_anon_free_client_credentials(anonCred);
+ gnutls_certificate_free_credentials(certCred);
+
+ gnutls_global_deinit();
+ }
+
+#if VMIME_DEBUG && GNUTLS_DEBUG
+
+ static void TLSLogFunc(int level, const char *str) {
+
+ std::cerr << "GNUTLS: [" << level << "] " << str << std::endl;
+ }
+
+#endif // VMIME_DEBUG && GNUTLS_DEBUG
+
+
+ gnutls_anon_client_credentials_t anonCred;
+ gnutls_certificate_credentials_t certCred;
+};
+
+static TLSGlobal g_gnutlsGlobal;
+
+
+#endif // VMIME_BUILDING_DOC
+
+
+
+// static
+shared_ptr <TLSSession> TLSSession::create(
+ const shared_ptr <security::cert::certificateVerifier>& cv,
+ const shared_ptr <TLSProperties>& props
+) {
+
+ return make_shared <TLSSession_GnuTLS>(cv, props);
+}
+
+
+TLSSession_GnuTLS::TLSSession_GnuTLS(
+ const shared_ptr <security::cert::certificateVerifier>& cv,
+ const shared_ptr <TLSProperties>& props
+)
+ : m_certVerifier(cv),
+ m_props(props) {
+
+ int res;
+
+ m_gnutlsSession = new gnutls_session_t;
+
+ if (gnutls_init(m_gnutlsSession, GNUTLS_CLIENT) != 0) {
+ throw std::bad_alloc();
+ }
+
+ // Sets some default priority on the ciphers, key exchange methods,
+ // macs and compression methods.
+#ifdef VMIME_HAVE_GNUTLS_PRIORITY_FUNCS
+ gnutls_dh_set_prime_bits(*m_gnutlsSession, 128);
+
+ if ((res = gnutls_priority_set_direct
+ (*m_gnutlsSession, m_props->getCipherSuite().c_str(), NULL)) != 0) {
+
+ throwTLSException("gnutls_priority_set_direct", res);
+ }
+
+#else // !VMIME_HAVE_GNUTLS_PRIORITY_FUNCS
+
+ gnutls_set_default_priority(*m_gnutlsSession);
+
+ // Sets the priority on the certificate types supported by gnutls.
+ // Priority is higher for types specified before others. After
+ // specifying the types you want, you must append a 0.
+ const int certTypePriority[] = { GNUTLS_CRT_X509, 0 };
+
+ res = gnutls_certificate_type_set_priority(*m_gnutlsSession, certTypePriority);
+
+ if (res < 0) {
+ throwTLSException("gnutls_certificate_type_set_priority", res);
+ }
+
+ // Sets the priority on the protocol types
+ const int protoPriority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
+
+ res = gnutls_protocol_set_priority(*m_gnutlsSession, protoPriority);
+
+ if (res < 0) {
+ throwTLSException("gnutls_certificate_type_set_priority", res);
+ }
+
+ // Priority on the ciphers
+ const int cipherPriority[] = {
+ GNUTLS_CIPHER_ARCFOUR_128,
+ GNUTLS_CIPHER_3DES_CBC,
+ GNUTLS_CIPHER_AES_128_CBC,
+ GNUTLS_CIPHER_AES_256_CBC,
+ GNUTLS_CIPHER_ARCFOUR_40,
+ GNUTLS_CIPHER_RC2_40_CBC,
+ GNUTLS_CIPHER_DES_CBC,
+ 0
+ };
+
+ gnutls_cipher_set_priority(*m_gnutlsSession, cipherPriority);
+
+ // Priority on MACs
+ const int macPriority[] = {
+ GNUTLS_MAC_SHA,
+ GNUTLS_MAC_MD5,
+ 0
+ };
+
+ gnutls_mac_set_priority(*m_gnutlsSession, macPriority);
+
+ // Priority on key exchange methods
+ const int kxPriority[] = {
+ GNUTLS_KX_RSA,
+ GNUTLS_KX_DHE_DSS,
+ GNUTLS_KX_DHE_RSA,
+ GNUTLS_KX_ANON_DH,
+ GNUTLS_KX_SRP,
+ GNUTLS_KX_RSA_EXPORT,
+ GNUTLS_KX_SRP_RSA,
+ GNUTLS_KX_SRP_DSS,
+ 0
+ };
+
+ gnutls_kx_set_priority(*m_gnutlsSession, kxPriority);
+
+ // Priority on compression methods
+ const int compressionPriority[] = {
+ GNUTLS_COMP_ZLIB,
+ //GNUTLS_COMP_LZO,
+ GNUTLS_COMP_NULL,
+ 0
+ };
+
+ gnutls_compression_set_priority(*m_gnutlsSession, compressionPriority);
+
+#endif // !VMIME_HAVE_GNUTLS_PRIORITY_FUNCS
+
+ // Initialize credentials
+ gnutls_credentials_set(
+ *m_gnutlsSession, GNUTLS_CRD_ANON, g_gnutlsGlobal.anonCred
+ );
+
+ gnutls_credentials_set(
+ *m_gnutlsSession, GNUTLS_CRD_CERTIFICATE, g_gnutlsGlobal.certCred
+ );
+}
+
+
+TLSSession_GnuTLS::TLSSession_GnuTLS(const TLSSession_GnuTLS&)
+ : TLSSession() {
+
+ // Not used
+}
+
+
+TLSSession_GnuTLS::~TLSSession_GnuTLS() {
+
+ try {
+
+ if (m_gnutlsSession) {
+
+ gnutls_deinit(*m_gnutlsSession);
+
+ delete m_gnutlsSession;
+ m_gnutlsSession = NULL;
+ }
+
+ } catch (...) {
+
+ // Don't throw in destructor
+ }
+}
+
+
+shared_ptr <TLSSocket> TLSSession_GnuTLS::getSocket(const shared_ptr <socket>& sok) {
+
+ return TLSSocket::wrap(dynamicCast <TLSSession>(shared_from_this()), sok);
+}
+
+
+shared_ptr <security::cert::certificateVerifier> TLSSession_GnuTLS::getCertificateVerifier() {
+
+ return m_certVerifier;
+}
+
+
+void TLSSession_GnuTLS::throwTLSException(const string& fname, const int code) {
+
+ std::ostringstream msg;
+
+ msg << fname + "() returned code ";
+ msg << std::hex << code;
+ msg << ": ";
+ msg << gnutls_strerror(code);
+
+ throw exceptions::tls_exception(msg.str());
+}
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
diff --git a/vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp b/vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp
new file mode 100644
index 0000000..2a7f9d7
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp
@@ -0,0 +1,95 @@
+//
+// 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_NET_TLS_TLSSESSION_GNUTLS_HPP_INCLUDED
+#define VMIME_NET_TLS_TLSSESSION_GNUTLS_HPP_INCLUDED
+
+
+#ifndef VMIME_BUILDING_DOC
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/tls/TLSSession.hpp"
+#include "vmime/net/tls/TLSSocket.hpp"
+#include "vmime/net/tls/TLSProperties.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+class TLSSession_GnuTLS : public TLSSession {
+
+ friend class TLSSocket_GnuTLS;
+
+public:
+
+ TLSSession_GnuTLS(
+ const shared_ptr <security::cert::certificateVerifier>& cv,
+ const shared_ptr <TLSProperties>& props
+ );
+
+ ~TLSSession_GnuTLS();
+
+
+ shared_ptr <TLSSocket> getSocket(const shared_ptr <socket>& sok);
+
+ shared_ptr <security::cert::certificateVerifier> getCertificateVerifier();
+
+private:
+
+ TLSSession_GnuTLS(const TLSSession_GnuTLS&);
+
+ static void throwTLSException(const string& fname, const int code);
+
+
+#ifdef LIBGNUTLS_VERSION
+ gnutls_session_t* m_gnutlsSession;
+#else
+ void* m_gnutlsSession;
+#endif // LIBGNUTLS_VERSION
+
+ shared_ptr <security::cert::certificateVerifier> m_certVerifier;
+ shared_ptr <TLSProperties> m_props;
+};
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+#endif // VMIME_BUILDING_DOC
+
+#endif // VMIME_NET_TLS_TLSSESSION_GNUTLS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp b/vmime-master/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp
new file mode 100644
index 0000000..53e4eae
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp
@@ -0,0 +1,548 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#include <errno.h>
+
+#include "vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp"
+#include "vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp"
+
+#include "vmime/platform.hpp"
+
+#include "vmime/security/cert/X509Certificate.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include <cstring>
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+// static
+shared_ptr <TLSSocket> TLSSocket::wrap(
+ const shared_ptr <TLSSession>& session,
+ const shared_ptr <socket>& sok
+)
+{
+ return make_shared <TLSSocket_GnuTLS>(dynamicCast <TLSSession_GnuTLS>(session), sok);
+}
+
+
+TLSSocket_GnuTLS::TLSSocket_GnuTLS(
+ const shared_ptr <TLSSession_GnuTLS>& session,
+ const shared_ptr <socket>& sok
+)
+ : m_session(session),
+ m_wrapped(sok),
+ m_connected(false),
+ m_ex(NULL),
+ m_status(0),
+ m_errno(0) {
+
+ gnutls_transport_set_ptr(*m_session->m_gnutlsSession, this);
+
+ gnutls_transport_set_push_function(*m_session->m_gnutlsSession, gnutlsPushFunc);
+ gnutls_transport_set_pull_function(*m_session->m_gnutlsSession, gnutlsPullFunc);
+ gnutls_transport_set_errno_function(*m_session->m_gnutlsSession, gnutlsErrnoFunc);
+}
+
+
+TLSSocket_GnuTLS::~TLSSocket_GnuTLS() {
+
+ resetException();
+
+ try {
+ disconnect();
+ } catch (...) {
+ // Don't throw exception in destructor
+ }
+}
+
+
+void TLSSocket_GnuTLS::connect(const string& address, const port_t port) {
+
+ try {
+
+ m_wrapped->connect(address, port);
+
+ handshake();
+
+ } catch (...) {
+
+ disconnect();
+ throw;
+ }
+}
+
+
+void TLSSocket_GnuTLS::disconnect() {
+
+ if (m_connected) {
+
+ gnutls_bye(*m_session->m_gnutlsSession, GNUTLS_SHUT_RDWR);
+
+ m_wrapped->disconnect();
+
+ m_connected = false;
+ }
+}
+
+
+bool TLSSocket_GnuTLS::isConnected() const {
+
+ return m_wrapped->isConnected() && m_connected;
+}
+
+
+size_t TLSSocket_GnuTLS::getBlockSize() const {
+
+ return 16384; // 16 KB
+}
+
+
+const string TLSSocket_GnuTLS::getPeerName() const {
+
+ return m_wrapped->getPeerName();
+}
+
+
+const string TLSSocket_GnuTLS::getPeerAddress() const {
+
+ return m_wrapped->getPeerAddress();
+}
+
+
+shared_ptr <timeoutHandler> TLSSocket_GnuTLS::getTimeoutHandler() {
+
+ return m_wrapped->getTimeoutHandler();
+}
+
+
+void TLSSocket_GnuTLS::setTracer(const shared_ptr <net::tracer>& tracer) {
+
+ m_wrapped->setTracer(tracer);
+}
+
+
+shared_ptr <net::tracer> TLSSocket_GnuTLS::getTracer() {
+
+ return m_wrapped->getTracer();
+}
+
+
+bool TLSSocket_GnuTLS::waitForRead(const int msecs) {
+
+ return m_wrapped->waitForRead(msecs);
+}
+
+
+bool TLSSocket_GnuTLS::waitForWrite(const int msecs) {
+
+ return m_wrapped->waitForWrite(msecs);
+}
+
+
+void TLSSocket_GnuTLS::receive(string& buffer) {
+
+ const size_t size = receiveRaw(m_buffer, sizeof(m_buffer));
+ buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size);
+}
+
+
+void TLSSocket_GnuTLS::send(const string& buffer) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(buffer.data()), buffer.length());
+}
+
+
+void TLSSocket_GnuTLS::send(const char* str) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(str), ::strlen(str));
+}
+
+
+size_t TLSSocket_GnuTLS::receiveRaw(byte_t* buffer, const size_t count) {
+
+ m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ);
+
+ resetException();
+
+ const ssize_t ret = gnutls_record_recv(
+ *m_session->m_gnutlsSession,
+ buffer, static_cast <size_t>(count)
+ );
+
+ throwException();
+
+ if (ret < 0) {
+
+ if (ret == GNUTLS_E_AGAIN) {
+
+ if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) {
+ m_status |= STATUS_WANT_READ;
+ } else {
+ m_status |= STATUS_WANT_WRITE;
+ }
+
+ return 0;
+ }
+
+ TLSSession_GnuTLS::throwTLSException("gnutls_record_recv", static_cast <int>(ret));
+ }
+
+ return static_cast <size_t>(ret);
+}
+
+
+void TLSSocket_GnuTLS::sendRaw(const byte_t* buffer, const size_t count) {
+
+ m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ);
+
+ for (size_t size = count ; size > 0 ; ) {
+
+ resetException();
+
+ ssize_t ret = gnutls_record_send(
+ *m_session->m_gnutlsSession,
+ buffer, static_cast <size_t>(size)
+ );
+
+ throwException();
+
+ if (ret < 0) {
+
+ if (ret == GNUTLS_E_AGAIN) {
+
+ if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) {
+ m_wrapped->waitForRead();
+ } else {
+ m_wrapped->waitForWrite();
+ }
+
+ continue;
+ }
+
+ TLSSession_GnuTLS::throwTLSException("gnutls_record_send", static_cast <int>(ret));
+
+ } else {
+
+ buffer += ret;
+ size -= ret;
+ }
+ }
+}
+
+
+size_t TLSSocket_GnuTLS::sendRawNonBlocking(const byte_t* buffer, const size_t count) {
+
+ m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ);
+
+ resetException();
+
+ ssize_t ret = gnutls_record_send(
+ *m_session->m_gnutlsSession,
+ buffer, static_cast <size_t>(count)
+ );
+
+ throwException();
+
+ if (ret < 0) {
+
+ if (ret == GNUTLS_E_AGAIN) {
+
+ if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) {
+ m_status |= STATUS_WANT_READ;
+ } else {
+ m_status |= STATUS_WANT_WRITE;
+ }
+
+ return 0;
+ }
+
+ TLSSession_GnuTLS::throwTLSException("gnutls_record_send", static_cast <int>(ret));
+ }
+
+ return static_cast <size_t>(ret);
+}
+
+
+unsigned int TLSSocket_GnuTLS::getStatus() const {
+
+ return m_status | m_wrapped->getStatus();
+}
+
+
+void TLSSocket_GnuTLS::handshake() {
+
+ shared_ptr <timeoutHandler> toHandler = m_wrapped->getTimeoutHandler();
+
+ if (toHandler) {
+ toHandler->resetTimeOut();
+ }
+
+ if (getTracer()) {
+ getTracer()->traceSend("Beginning SSL/TLS handshake");
+ }
+
+ // Start handshaking process
+ try {
+ string peerName = getPeerName();
+
+ gnutls_server_name_set(*m_session->m_gnutlsSession, GNUTLS_NAME_DNS, peerName.c_str(), peerName.size());
+
+ while (true) {
+
+ resetException();
+
+ const int ret = gnutls_handshake(*m_session->m_gnutlsSession);
+
+ throwException();
+
+ if (ret < 0) {
+
+ if (ret == GNUTLS_E_AGAIN) {
+
+ if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) {
+ m_wrapped->waitForRead();
+ } else {
+ m_wrapped->waitForWrite();
+ }
+
+ } else if (ret == GNUTLS_E_INTERRUPTED) {
+
+ // Non-fatal error
+
+ } else {
+
+ TLSSession_GnuTLS::throwTLSException("gnutls_handshake", ret);
+ }
+
+ } else {
+
+ // Successful handshake
+ break;
+ }
+ }
+
+ } catch (...) {
+
+ throw;
+ }
+
+ // Verify server's certificate(s)
+ shared_ptr <security::cert::certificateChain> certs = getPeerCertificates();
+
+ if (certs == NULL) {
+ throw exceptions::tls_exception("No peer certificate.");
+ }
+
+ m_session->getCertificateVerifier()->verify(certs, getPeerName());
+
+ m_connected = true;
+}
+
+
+int TLSSocket_GnuTLS::gnutlsErrnoFunc(gnutls_transport_ptr_t trspt) {
+
+ TLSSocket_GnuTLS* sok = reinterpret_cast <TLSSocket_GnuTLS*>(trspt);
+ return sok->m_errno;
+}
+
+
+ssize_t TLSSocket_GnuTLS::gnutlsPushFunc(
+ gnutls_transport_ptr_t trspt,
+ const void* data,
+ size_t len
+) {
+
+ TLSSocket_GnuTLS* sok = reinterpret_cast <TLSSocket_GnuTLS*>(trspt);
+
+ try {
+
+ const ssize_t ret = static_cast <ssize_t>(
+ sok->m_wrapped->sendRawNonBlocking(reinterpret_cast <const byte_t*>(data), len)
+ );
+
+ if (ret == 0) {
+
+ gnutls_transport_set_errno(*sok->m_session->m_gnutlsSession, EAGAIN);
+ sok->m_errno = EAGAIN;
+ return -1;
+ }
+
+ return ret;
+
+ } catch (exception& e) {
+
+ // Workaround for non-portable behaviour when throwing C++ exceptions
+ // from C functions (GNU TLS)
+ sok->m_ex = e.clone();
+ return -1;
+ }
+}
+
+
+ssize_t TLSSocket_GnuTLS::gnutlsPullFunc(
+ gnutls_transport_ptr_t trspt,
+ void* data,
+ size_t len
+) {
+
+ TLSSocket_GnuTLS* sok = reinterpret_cast <TLSSocket_GnuTLS*>(trspt);
+
+ try {
+
+ const ssize_t n = static_cast <ssize_t>(
+ sok->m_wrapped->receiveRaw(reinterpret_cast <byte_t*>(data), len)
+ );
+
+ if (n == 0) {
+
+ gnutls_transport_set_errno(*sok->m_session->m_gnutlsSession, EAGAIN);
+ sok->m_errno = EAGAIN;
+ return -1;
+ }
+
+ return n;
+
+ } catch (exception& e) {
+
+ // Workaround for non-portable behaviour when throwing C++ exceptions
+ // from C functions (GNU TLS)
+ sok->m_ex = e.clone();
+ return -1;
+ }
+}
+
+
+shared_ptr <security::cert::certificateChain> TLSSocket_GnuTLS::getPeerCertificates() {
+
+ if (getTracer()) {
+ getTracer()->traceSend("Getting peer certificates");
+ }
+
+ unsigned int certCount = 0;
+ const gnutls_datum_t* rawData = gnutls_certificate_get_peers(
+ *m_session->m_gnutlsSession, &certCount
+ );
+
+ if (rawData == NULL) {
+ return null;
+ }
+
+ // Try X.509
+ gnutls_x509_crt_t* x509Certs = new gnutls_x509_crt_t[certCount];
+
+ for (unsigned int i = 0; i < certCount; ++i) {
+
+ gnutls_x509_crt_init(x509Certs + i);
+
+ int res = gnutls_x509_crt_import(x509Certs[i], rawData + i, GNUTLS_X509_FMT_DER);
+
+ if (res < 0) {
+
+ for (unsigned int j = 0 ; j <= i ; ++j) {
+ gnutls_x509_crt_deinit(x509Certs[j]);
+ }
+
+ // XXX more fine-grained error reporting?
+ delete [] x509Certs;
+ return null;
+ }
+ }
+
+ std::vector <shared_ptr <security::cert::certificate> > certs;
+ bool error = false;
+
+ for (unsigned int i = 0 ; i < certCount ; ++i) {
+
+ size_t dataSize = 0;
+
+ gnutls_x509_crt_export(x509Certs[i], GNUTLS_X509_FMT_DER, NULL, &dataSize);
+
+ std::vector <byte_t> data(dataSize);
+
+ gnutls_x509_crt_export(x509Certs[i], GNUTLS_X509_FMT_DER, &data[0], &dataSize);
+
+ shared_ptr <security::cert::X509Certificate> cert =
+ security::cert::X509Certificate::import(&data[0], dataSize);
+
+ if (cert != NULL) {
+ certs.push_back(cert);
+ } else {
+ error = true;
+ }
+
+ gnutls_x509_crt_deinit(x509Certs[i]);
+ }
+
+ delete [] x509Certs;
+
+ if (error) {
+ return null;
+ }
+
+ return make_shared <security::cert::certificateChain>(certs);
+}
+
+
+// Following is a workaround for C++ exceptions to pass correctly between
+// C and C++ calls.
+//
+// gnutls_record_recv() calls TLSSocket::gnutlsPullFunc, and exceptions
+// thrown by the socket can not be caught.
+
+void TLSSocket_GnuTLS::throwException() {
+
+ if (m_ex) {
+ throw *m_ex;
+ }
+}
+
+
+void TLSSocket_GnuTLS::resetException() {
+
+ if (m_ex) {
+ delete m_ex;
+ m_ex = NULL;
+ }
+}
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
diff --git a/vmime-master/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp b/vmime-master/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp
new file mode 100644
index 0000000..0ac3e70
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp
@@ -0,0 +1,129 @@
+//
+// 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_NET_TLS_TLSSOCKET_GNUTLS_HPP_INCLUDED
+#define VMIME_NET_TLS_TLSSOCKET_GNUTLS_HPP_INCLUDED
+
+
+#ifndef VMIME_BUILDING_DOC
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+
+#include "vmime/net/tls/TLSSocket.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+class TLSSession;
+class TLSSession_GnuTLS;
+
+
+class TLSSocket_GnuTLS : public TLSSocket {
+
+public:
+
+ TLSSocket_GnuTLS(const shared_ptr <TLSSession_GnuTLS>& session, const shared_ptr <socket>& sok);
+ ~TLSSocket_GnuTLS();
+
+
+ void handshake();
+
+ shared_ptr <security::cert::certificateChain> getPeerCertificates();
+
+ // Implementation of 'socket'
+ void connect(const string& address, const port_t port);
+ void disconnect();
+ bool isConnected() const;
+
+ bool waitForRead(const int msecs = 30000);
+ bool waitForWrite(const int msecs = 30000);
+
+ void receive(string& buffer);
+ size_t receiveRaw(byte_t* buffer, const size_t count);
+
+ void send(const string& buffer);
+ void send(const char* str);
+ void sendRaw(const byte_t* buffer, const size_t count);
+ size_t sendRawNonBlocking(const byte_t* buffer, const size_t count);
+
+ size_t getBlockSize() const;
+
+ unsigned int getStatus() const;
+
+ const string getPeerName() const;
+ const string getPeerAddress() const;
+
+ shared_ptr <timeoutHandler> getTimeoutHandler();
+
+ void setTracer(const shared_ptr <net::tracer>& tracer);
+ shared_ptr <net::tracer> getTracer();
+
+private:
+
+ void resetException();
+ void throwException();
+
+#ifdef LIBGNUTLS_VERSION
+ static ssize_t gnutlsPushFunc(gnutls_transport_ptr_t trspt, const void* data, size_t len);
+ static ssize_t gnutlsPullFunc(gnutls_transport_ptr_t trspt, void* data, size_t len);
+ static int gnutlsErrnoFunc(gnutls_transport_ptr_t trspt);
+#else
+ static int gnutlsPushFunc(void* trspt, const void* data, size_t len);
+ static int gnutlsPullFunc(void* trspt, void* data, size_t len);
+ static int gnutlsErrnoFunc(void* trspt);
+#endif // LIBGNUTLS_VERSION
+
+
+ shared_ptr <TLSSession_GnuTLS> m_session;
+ shared_ptr <socket> m_wrapped;
+
+ bool m_connected;
+
+ byte_t m_buffer[65536];
+
+ exception* m_ex;
+
+ unsigned int m_status;
+ int m_errno;
+};
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+#endif // VMIME_BUILDING_DOC
+
+#endif // VMIME_NET_TLS_TLSSOCKET_GNUTLS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp b/vmime-master/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp
new file mode 100644
index 0000000..c7b1013
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp
@@ -0,0 +1,169 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+
+#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp"
+
+#include "vmime/platform.hpp"
+
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+# define OPENSSL_API_COMPAT 0x10100000L
+#endif
+
+#include <openssl/ssl.h>
+#include <openssl/rand.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x0907000L
+# include <openssl/conf.h>
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+# include "vmime/utility/sync/autoLock.hpp"
+# include "vmime/utility/sync/criticalSection.hpp"
+#endif
+
+
+// OpenSSL locking callbacks for multithreading support (< v1.1 only)
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
+namespace {
+
+vmime::shared_ptr <vmime::utility::sync::criticalSection >* g_openSSLMutexes = NULL;
+
+extern "C" void VMime_OpenSSLCallback_lock(int mode, int n, const char* /* file */, int /* line */) {
+
+ if (mode & CRYPTO_LOCK) {
+ g_openSSLMutexes[n]->lock();
+ } else {
+ g_openSSLMutexes[n]->unlock();
+ }
+}
+
+extern "C" unsigned long VMime_OpenSSLCallback_id() {
+
+ return vmime::platform::getHandler()->getThreadId();
+}
+
+}
+
+#endif
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+OpenSSLInitializer::autoInitializer::autoInitializer() {
+
+ // The construction of this unique 'oneTimeInitializer' object will be triggered
+ // by the 'autoInitializer' objects from the other translation units
+ static OpenSSLInitializer::oneTimeInitializer oneTimeInitializer;
+}
+
+
+OpenSSLInitializer::autoInitializer::~autoInitializer() {
+
+}
+
+
+OpenSSLInitializer::oneTimeInitializer::oneTimeInitializer() {
+
+ initialize();
+}
+
+
+OpenSSLInitializer::oneTimeInitializer::~oneTimeInitializer() {
+
+ uninitialize();
+}
+
+
+// static
+void OpenSSLInitializer::initialize() {
+
+#if OPENSSL_VERSION_NUMBER >= 0x0907000L && OPENSSL_VERSION_NUMBER < 0x10100000L
+ OPENSSL_config(NULL);
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ SSL_load_error_strings();
+ SSL_library_init();
+ OpenSSL_add_all_algorithms();
+
+ int numMutexes = CRYPTO_num_locks();
+ g_openSSLMutexes = new shared_ptr <vmime::utility::sync::criticalSection>[numMutexes];
+
+ for (int i = 0 ; i < numMutexes ; ++i) {
+ g_openSSLMutexes[i] = vmime::platform::getHandler()->createCriticalSection();
+ }
+
+ CRYPTO_set_locking_callback(VMime_OpenSSLCallback_lock);
+ CRYPTO_set_id_callback(VMime_OpenSSLCallback_id);
+#endif
+
+ // Seed the RNG, in case /dev/urandom is not available. Explicitely calling
+ // RAND_seed() even though /dev/urandom is available is harmless.
+ enum {
+ SEEDSIZE = 256
+ };
+
+ unsigned char seed[SEEDSIZE];
+ vmime::platform::getHandler()->generateRandomBytes(seed, SEEDSIZE);
+ RAND_seed(seed, SEEDSIZE);
+}
+
+
+// static
+void OpenSSLInitializer::uninitialize() {
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ EVP_cleanup();
+ ERR_free_strings();
+
+ CRYPTO_set_locking_callback(NULL);
+ CRYPTO_set_id_callback(NULL);
+
+ delete [] g_openSSLMutexes;
+ g_openSSLMutexes = NULL;
+#endif
+
+}
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
diff --git a/vmime-master/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp b/vmime-master/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp
new file mode 100644
index 0000000..3b8496d
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp
@@ -0,0 +1,90 @@
+//
+// 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_NET_TLS_OPENSSL_OPENSSLINITIALIZER_HPP_INCLUDED
+#define VMIME_NET_TLS_OPENSSL_OPENSSLINITIALIZER_HPP_INCLUDED
+
+
+#ifndef VMIME_BUILDING_DOC
+
+
+#include "vmime/config.hpp"
+
+#include <vector>
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+
+#include "vmime/utility/sync/criticalSection.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+/** Class responsible for setting up OpenSSL
+ */
+class OpenSSLInitializer {
+
+public:
+
+ /** Automatically initialize OpenSSL
+ */
+ struct autoInitializer {
+
+ autoInitializer();
+ ~autoInitializer();
+ };
+
+protected:
+
+ struct oneTimeInitializer {
+
+ oneTimeInitializer();
+ ~oneTimeInitializer();
+ };
+
+
+ /** Initializes the OpenSSL lib
+ */
+ static void initialize();
+
+ /** Shutdown the OpenSSL lib
+ */
+ static void uninitialize();
+};
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+#endif // VMIME_BUILDING_DOC
+
+#endif // VMIME_NET_TLS_OPENSSL_OPENSSLINITIALIZER_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp b/vmime-master/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp
new file mode 100644
index 0000000..ea22f1c
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp
@@ -0,0 +1,112 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+
+#include "vmime/base.hpp"
+#include "vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp"
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+TLSProperties::TLSProperties()
+ : m_data(make_shared <TLSProperties_OpenSSL>()) {
+
+ setCipherSuite(CIPHERSUITE_DEFAULT);
+}
+
+
+TLSProperties::TLSProperties(const TLSProperties& props)
+ : object(),
+ m_data(make_shared <TLSProperties_OpenSSL>()) {
+
+ *dynamicCast <TLSProperties_OpenSSL>(m_data) = *dynamicCast <TLSProperties_OpenSSL>(props.m_data);
+}
+
+
+void TLSProperties::setCipherSuite(const GenericCipherSuite cipherSuite) {
+
+ switch (cipherSuite) {
+
+ case CIPHERSUITE_HIGH:
+
+ setCipherSuite("HIGH:!ADH:@STRENGTH");
+ break;
+
+ case CIPHERSUITE_MEDIUM:
+
+ setCipherSuite("MEDIUM:!ADH:@STRENGTH");
+ break;
+
+ case CIPHERSUITE_LOW:
+
+ setCipherSuite("LOW:!ADH:@STRENGTH");
+ break;
+
+ default:
+ case CIPHERSUITE_DEFAULT:
+
+ setCipherSuite("DEFAULT:!ADH:@STRENGTH");
+ break;
+ }
+}
+
+
+void TLSProperties::setCipherSuite(const string& cipherSuite) {
+
+ dynamicCast <TLSProperties_OpenSSL>(m_data)->cipherSuite = cipherSuite;
+}
+
+
+const string TLSProperties::getCipherSuite() const {
+
+ return dynamicCast <TLSProperties_OpenSSL>(m_data)->cipherSuite;
+}
+
+
+
+TLSProperties_OpenSSL& TLSProperties_OpenSSL::operator=(const TLSProperties_OpenSSL& other) {
+
+ cipherSuite = other.cipherSuite;
+
+ return *this;
+}
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
diff --git a/vmime-master/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp b/vmime-master/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp
new file mode 100644
index 0000000..8304df2
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp
@@ -0,0 +1,68 @@
+//
+// 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_NET_TLS_TLSPROPERTIES_OPENSSL_HPP_INCLUDED
+#define VMIME_NET_TLS_TLSPROPERTIES_OPENSSL_HPP_INCLUDED
+
+
+#ifndef VMIME_BUILDING_DOC
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/tls/TLSProperties.hpp"
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+class TLSProperties_OpenSSL : public object {
+
+public:
+
+ TLSProperties_OpenSSL& operator=(const TLSProperties_OpenSSL& other);
+
+
+ string cipherSuite;
+};
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+#endif // VMIME_BUILDING_DOC
+
+#endif // VMIME_NET_TLS_TLSPROPERTIES_OPENSSL_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp b/vmime-master/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp
new file mode 100644
index 0000000..019341c
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp
@@ -0,0 +1,147 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+
+#include "vmime/net/tls/openssl/TLSSession_OpenSSL.hpp"
+#include "vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp"
+#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp"
+
+#include "vmime/security/cert/certificateException.hpp"
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+static OpenSSLInitializer::autoInitializer openSSLInitializer;
+
+
+// static
+shared_ptr <TLSSession> TLSSession::create(
+ const shared_ptr <security::cert::certificateVerifier>& cv,
+ const shared_ptr <TLSProperties>& props
+) {
+
+ return make_shared <TLSSession_OpenSSL>(cv, props);
+}
+
+
+TLSSession_OpenSSL::TLSSession_OpenSSL(
+ const shared_ptr <vmime::security::cert::certificateVerifier>& cv,
+ const shared_ptr <TLSProperties>& props
+)
+ : m_sslctx(0),
+ m_certVerifier(cv),
+ m_props(props) {
+
+ m_sslctx = SSL_CTX_new(SSLv23_client_method());
+ SSL_CTX_set_options(m_sslctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
+ SSL_CTX_set_mode(m_sslctx, SSL_MODE_AUTO_RETRY);
+ SSL_CTX_set_cipher_list(m_sslctx, m_props->getCipherSuite().c_str());
+ SSL_CTX_set_session_cache_mode(m_sslctx, SSL_SESS_CACHE_OFF);
+}
+
+
+TLSSession_OpenSSL::TLSSession_OpenSSL(const TLSSession_OpenSSL&)
+ : TLSSession() {
+
+ // Not used
+}
+
+
+TLSSession_OpenSSL::~TLSSession_OpenSSL() {
+
+ SSL_CTX_free(m_sslctx);
+}
+
+
+shared_ptr <TLSSocket> TLSSession_OpenSSL::getSocket(const shared_ptr <socket>& sok) {
+
+ return TLSSocket::wrap(dynamicCast <TLSSession>(shared_from_this()), sok);
+}
+
+
+shared_ptr <security::cert::certificateVerifier> TLSSession_OpenSSL::getCertificateVerifier() {
+
+ return m_certVerifier;
+}
+
+
+void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile) {
+
+ ERR_clear_error();
+
+ if (SSL_CTX_use_PrivateKey_file(m_sslctx, keyfile.c_str(), SSL_FILETYPE_PEM) != 1) {
+
+ unsigned long errCode = ERR_get_error();
+ char buffer[256];
+ ERR_error_string_n(errCode, buffer, sizeof(buffer));
+ vmime::string sslErr(buffer);
+ std::ostringstream oss;
+ oss << "Error loading private key from file " << keyfile;
+ oss << " - msg: " << sslErr;
+ throw security::cert::certificateException(oss.str());
+ }
+}
+
+
+void TLSSession_OpenSSL::useCertificateChainFile(const vmime::string& chainFile) {
+
+ ERR_clear_error();
+
+ if (SSL_CTX_use_certificate_chain_file(m_sslctx, chainFile.c_str()) != 1) {
+
+ unsigned long errCode = ERR_get_error();
+ char buffer[256];
+ ERR_error_string_n(errCode, buffer, sizeof(buffer));
+ vmime::string sslErr(buffer);
+ std::ostringstream oss;
+ oss << "Error loading certificate from file " << chainFile;
+ oss << " - msg: " << sslErr;
+ throw security::cert::certificateException(oss.str());
+ }
+}
+
+
+SSL_CTX* TLSSession_OpenSSL::getContext() const {
+
+ return m_sslctx;
+}
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
diff --git a/vmime-master/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp b/vmime-master/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp
new file mode 100644
index 0000000..518216b
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp
@@ -0,0 +1,109 @@
+//
+// 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_NET_TLS_TLSSESSION_OPENSSL_HPP_INCLUDED
+#define VMIME_NET_TLS_TLSSESSION_OPENSSL_HPP_INCLUDED
+
+
+#ifndef VMIME_BUILDING_DOC
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/tls/TLSSession.hpp"
+#include "vmime/net/tls/TLSSocket.hpp"
+#include "vmime/net/tls/TLSProperties.hpp"
+
+
+#include <openssl/ssl.h>
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+class TLSSession_OpenSSL : public TLSSession {
+
+ friend class TLSSocket_OpenSSL;
+
+public:
+
+ TLSSession_OpenSSL(
+ const shared_ptr <security::cert::certificateVerifier>& cv,
+ const shared_ptr <TLSProperties>& props
+ );
+
+ ~TLSSession_OpenSSL();
+
+
+ shared_ptr <TLSSocket> getSocket(const shared_ptr <socket>& sok);
+
+ shared_ptr <security::cert::certificateVerifier> getCertificateVerifier();
+
+
+ /** Set the private key to use if server requires a client certificate.
+ *
+ * @param keyfile path to the private key in PEM format
+ */
+ void usePrivateKeyFile(const vmime::string& keyfile);
+
+ /** Supply the certificate chain to present if requested by server.
+ *
+ * @param chainFile File in PEM format holding certificate chain
+ */
+ void useCertificateChainFile(const vmime::string& chainFile);
+
+ /** Get a pointer to the SSL_CTX used for this session.
+ *
+ * @return the SSL_CTX used for all connections created with this session
+ */
+ SSL_CTX* getContext() const;
+
+private:
+
+ TLSSession_OpenSSL(const TLSSession_OpenSSL&);
+
+ SSL_CTX* m_sslctx;
+
+ shared_ptr <security::cert::certificateVerifier> m_certVerifier;
+ shared_ptr <TLSProperties> m_props;
+};
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+#endif // VMIME_BUILDING_DOC
+
+#endif // VMIME_NET_TLS_TLSSESSION_OPENSSL_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp b/vmime-master/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp
new file mode 100644
index 0000000..978f0ca
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp
@@ -0,0 +1,761 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp"
+#include "vmime/net/tls/openssl/TLSSession_OpenSSL.hpp"
+#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp"
+
+#include "vmime/platform.hpp"
+
+#include "vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include <vector>
+#include <cstring>
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+static OpenSSLInitializer::autoInitializer openSSLInitializer;
+
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
+// static
+BIO_METHOD TLSSocket_OpenSSL::sm_customBIOMethod = {
+ 100 | BIO_TYPE_SOURCE_SINK,
+ "vmime::socket glue",
+ TLSSocket_OpenSSL::bio_write,
+ TLSSocket_OpenSSL::bio_read,
+ TLSSocket_OpenSSL::bio_puts,
+ NULL, // gets
+ TLSSocket_OpenSSL::bio_ctrl,
+ TLSSocket_OpenSSL::bio_create,
+ TLSSocket_OpenSSL::bio_destroy,
+ 0
+};
+
+#define BIO_set_init(b, val) b->init = val
+#define BIO_set_data(b, val) b->ptr = val
+#define BIO_set_num(b, val) b->num = val
+#define BIO_set_flags(b, val) b->flags = val
+#define BIO_set_shutdown(b, val) b->shutdown = val
+#define BIO_get_init(b) b->init
+#define BIO_get_data(b) b->ptr
+#define BIO_get_shutdown(b) b->shutdown
+
+#else
+
+#define BIO_set_num(b, val)
+
+#endif
+
+
+
+// static
+shared_ptr <TLSSocket> TLSSocket::wrap(
+ const shared_ptr <TLSSession>& session,
+ const shared_ptr <socket>& sok
+) {
+
+ return make_shared <TLSSocket_OpenSSL>(dynamicCast <TLSSession_OpenSSL>(session), sok);
+}
+
+
+TLSSocket_OpenSSL::TLSSocket_OpenSSL(
+ const shared_ptr <TLSSession_OpenSSL>& session,
+ const shared_ptr <socket>& sok
+)
+ : m_session(session),
+ m_wrapped(sok),
+ m_connected(false),
+ m_ssl(0),
+ m_status(0),
+ m_ex() {
+
+}
+
+
+TLSSocket_OpenSSL::~TLSSocket_OpenSSL() {
+
+ try {
+ disconnect();
+ } catch (...) {
+ // Don't throw in destructor
+ }
+}
+
+
+void TLSSocket_OpenSSL::createSSLHandle() {
+
+ if (m_wrapped->isConnected()) {
+ string peerName = getPeerName();
+
+ if (peerName.empty()) {
+ throw exceptions::tls_exception("Unknown host name, will not be able to set SNI");
+ }
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
+ BIO* sockBio = BIO_new(&sm_customBIOMethod);
+ sockBio->ptr = this;
+ sockBio->init = 1;
+
+#else
+
+ BIO_METHOD* bioMeth = BIO_meth_new(BIO_TYPE_SOURCE_SINK | BIO_get_new_index(), "vmime::socket glue");
+
+ if (!bioMeth) {
+ BIO_meth_free(bioMeth);
+ throw exceptions::tls_exception("BIO_meth_new() failed");
+ }
+
+ BIO_meth_set_write(bioMeth, TLSSocket_OpenSSL::bio_write);
+ BIO_meth_set_read(bioMeth, TLSSocket_OpenSSL::bio_read);
+ BIO_meth_set_puts(bioMeth, TLSSocket_OpenSSL::bio_puts);
+ BIO_meth_set_ctrl(bioMeth, TLSSocket_OpenSSL::bio_ctrl);
+ BIO_meth_set_create(bioMeth, TLSSocket_OpenSSL::bio_create);
+ BIO_meth_set_destroy(bioMeth, TLSSocket_OpenSSL::bio_destroy);
+
+ BIO* sockBio = BIO_new(bioMeth);
+ BIO_set_data(sockBio, this);
+ BIO_set_init(sockBio, 1);
+
+#endif
+
+ if (!sockBio) {
+ throw exceptions::tls_exception("BIO_new() failed");
+ }
+
+ m_ssl = SSL_new(m_session->getContext());
+
+ if (!m_ssl) {
+ BIO_free(sockBio);
+ throw exceptions::tls_exception("Cannot create SSL object");
+ }
+
+ SSL_set_bio(m_ssl, sockBio, sockBio);
+ SSL_set_tlsext_host_name(m_ssl, peerName.c_str());
+ SSL_set_connect_state(m_ssl);
+ SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY | SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+
+ } else {
+
+ throw exceptions::tls_exception("Unconnected socket error");
+ }
+}
+
+
+void TLSSocket_OpenSSL::connect(const string& address, const port_t port) {
+
+ try {
+
+ m_wrapped->connect(address, port);
+
+ createSSLHandle();
+
+ handshake();
+
+ } catch (...) {
+
+ disconnect();
+ throw;
+ }
+}
+
+
+void TLSSocket_OpenSSL::disconnect() {
+
+ if (m_ssl) {
+
+ // Don't shut down the socket more than once.
+ int shutdownState = SSL_get_shutdown(m_ssl);
+ bool shutdownSent = (shutdownState & SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN;
+
+ if (!shutdownSent) {
+ SSL_shutdown(m_ssl);
+ }
+
+ SSL_free(m_ssl);
+ m_ssl = 0;
+ }
+
+ if (m_connected) {
+ m_connected = false;
+ m_wrapped->disconnect();
+ }
+}
+
+
+bool TLSSocket_OpenSSL::isConnected() const {
+
+ return m_wrapped->isConnected() && m_connected;
+}
+
+
+size_t TLSSocket_OpenSSL::getBlockSize() const {
+
+ return 16384; // 16 KB
+}
+
+
+const string TLSSocket_OpenSSL::getPeerName() const {
+
+ return m_wrapped->getPeerName();
+}
+
+
+const string TLSSocket_OpenSSL::getPeerAddress() const {
+
+ return m_wrapped->getPeerAddress();
+}
+
+
+shared_ptr <timeoutHandler> TLSSocket_OpenSSL::getTimeoutHandler() {
+
+ return m_wrapped->getTimeoutHandler();
+}
+
+
+void TLSSocket_OpenSSL::setTracer(const shared_ptr <net::tracer>& tracer) {
+
+ m_wrapped->setTracer(tracer);
+}
+
+
+shared_ptr <net::tracer> TLSSocket_OpenSSL::getTracer() {
+
+ return m_wrapped->getTracer();
+}
+
+
+bool TLSSocket_OpenSSL::waitForRead(const int msecs) {
+
+ return m_wrapped->waitForRead(msecs);
+}
+
+
+bool TLSSocket_OpenSSL::waitForWrite(const int msecs) {
+
+ return m_wrapped->waitForWrite(msecs);
+}
+
+
+void TLSSocket_OpenSSL::receive(string& buffer) {
+
+ const size_t size = receiveRaw(m_buffer, sizeof(m_buffer));
+
+ if (size != 0) {
+ buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size);
+ } else {
+ buffer.clear();
+ }
+}
+
+
+void TLSSocket_OpenSSL::send(const string& buffer) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(buffer.data()), buffer.length());
+}
+
+
+void TLSSocket_OpenSSL::send(const char* str) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(str), ::strlen(str));
+}
+
+
+size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) {
+
+ if (!m_ssl) {
+ throw exceptions::socket_not_connected_exception();
+ }
+
+ m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ);
+
+ ERR_clear_error();
+ int rc = SSL_read(m_ssl, buffer, static_cast <int>(count));
+
+ if (m_ex.get()) {
+ internalThrow();
+ }
+
+ if (rc <= 0) {
+
+ int error = SSL_get_error(m_ssl, rc);
+
+ if (error == SSL_ERROR_WANT_WRITE) {
+ m_status |= STATUS_WANT_WRITE;
+ return 0;
+ } else if (error == SSL_ERROR_WANT_READ) {
+ m_status |= STATUS_WANT_READ;
+ return 0;
+ }
+
+ handleError(rc);
+ }
+
+ return rc;
+}
+
+
+void TLSSocket_OpenSSL::sendRaw(const byte_t* buffer, const size_t count) {
+
+ if (!m_ssl) {
+ throw exceptions::socket_not_connected_exception();
+ }
+
+ m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ);
+
+ for (size_t size = count ; size > 0 ; ) {
+
+ ERR_clear_error();
+ int rc = SSL_write(m_ssl, buffer, static_cast <int>(size));
+
+ if (rc <= 0) {
+
+ int error = SSL_get_error(m_ssl, rc);
+
+ if (error == SSL_ERROR_WANT_READ) {
+ m_wrapped->waitForRead();
+ continue;
+ } else if (error == SSL_ERROR_WANT_WRITE) {
+ m_wrapped->waitForWrite();
+ continue;
+ }
+
+ handleError(rc);
+
+ } else {
+
+ buffer += rc;
+ size -= rc;
+ }
+ }
+}
+
+
+size_t TLSSocket_OpenSSL::sendRawNonBlocking(const byte_t* buffer, const size_t count) {
+
+ if (!m_ssl) {
+ throw exceptions::socket_not_connected_exception();
+ }
+
+ m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ);
+
+ ERR_clear_error();
+ int rc = SSL_write(m_ssl, buffer, static_cast <int>(count));
+
+ if (m_ex.get()) {
+ internalThrow();
+ }
+
+ if (rc <= 0) {
+
+ int error = SSL_get_error(m_ssl, rc);
+
+ if (error == SSL_ERROR_WANT_WRITE) {
+ m_status |= STATUS_WANT_WRITE;
+ return 0;
+ } else if (error == SSL_ERROR_WANT_READ) {
+ m_status |= STATUS_WANT_READ;
+ return 0;
+ }
+
+ handleError(rc);
+ }
+
+ return rc;
+}
+
+
+void TLSSocket_OpenSSL::handshake() {
+
+ shared_ptr <timeoutHandler> toHandler = m_wrapped->getTimeoutHandler();
+
+ if (toHandler) {
+ toHandler->resetTimeOut();
+ }
+
+ if (getTracer()) {
+ getTracer()->traceSend("Beginning SSL/TLS handshake");
+ }
+
+ // Start handshaking process
+ if (!m_ssl) {
+ createSSLHandle();
+ }
+
+ try {
+
+ int rc;
+
+ ERR_clear_error();
+
+ while ((rc = SSL_do_handshake(m_ssl)) <= 0) {
+
+ const int err = SSL_get_error(m_ssl, rc);
+
+ if (err == SSL_ERROR_WANT_READ) {
+ m_wrapped->waitForRead();
+ } else if (err == SSL_ERROR_WANT_WRITE) {
+ m_wrapped->waitForWrite();
+ } else {
+ handleError(rc);
+ }
+
+ // Check whether the time-out delay is elapsed
+ if (toHandler && toHandler->isTimeOut()) {
+
+ if (!toHandler->handleTimeOut()) {
+ throw exceptions::operation_timed_out();
+ }
+
+ toHandler->resetTimeOut();
+ }
+
+ ERR_clear_error();
+ }
+
+ } catch (...) {
+
+ throw;
+ }
+
+ // Verify server's certificate(s)
+ shared_ptr <security::cert::certificateChain> certs = getPeerCertificates();
+
+ if (!certs) {
+ throw exceptions::tls_exception("No peer certificate.");
+ }
+
+ m_session->getCertificateVerifier()->verify(certs, getPeerName());
+
+ m_connected = true;
+}
+
+
+shared_ptr <security::cert::certificateChain> TLSSocket_OpenSSL::getPeerCertificates() {
+
+ if (getTracer()) {
+ getTracer()->traceSend("Getting peer certificates");
+ }
+
+ STACK_OF(X509)* chain = SSL_get_peer_cert_chain(m_ssl);
+
+ if (chain == NULL) {
+ return null;
+ }
+
+ int certCount = sk_X509_num(chain);
+
+ if (certCount == 0) {
+ return null;
+ }
+
+ bool error = false;
+ std::vector <shared_ptr <security::cert::certificate> > certs;
+
+ for (int i = 0; i < certCount && !error; i++) {
+
+ shared_ptr <vmime::security::cert::X509Certificate> cert =
+ vmime::security::cert::X509Certificate_OpenSSL::importInternal(sk_X509_value(chain, i));
+
+ if (cert) {
+ certs.push_back(cert);
+ } else {
+ error = true;
+ }
+ }
+
+ if (error) {
+ return null;
+ }
+
+ return make_shared <security::cert::certificateChain>(certs);
+}
+
+
+void TLSSocket_OpenSSL::internalThrow() {
+
+ if (m_ex.get()) {
+ throw *m_ex;
+ }
+}
+
+
+void TLSSocket_OpenSSL::handleError(int rc) {
+
+ if (rc > 0) {
+ return;
+ }
+
+ internalThrow();
+
+ int sslError = SSL_get_error(m_ssl, rc);
+ long lastError = ERR_get_error();
+
+ switch (sslError) {
+
+ case SSL_ERROR_ZERO_RETURN:
+
+ disconnect();
+ return;
+
+ case SSL_ERROR_SYSCALL: {
+
+ if (lastError == 0) {
+
+ if (rc == 0) {
+
+ throw exceptions::tls_exception("SSL connection unexpectedly closed");
+
+ } else {
+
+ std::ostringstream oss;
+ oss << "The BIO reported an error: " << rc;
+ oss.flush();
+ throw exceptions::tls_exception(oss.str());
+ }
+ }
+
+ break;
+ }
+
+ case SSL_ERROR_WANT_READ:
+
+ BIO_set_retry_read(SSL_get_rbio(m_ssl));
+ break;
+
+ case SSL_ERROR_WANT_WRITE:
+
+ BIO_set_retry_write(SSL_get_wbio(m_ssl));
+ break;
+
+ // This happens only for BIOs of type BIO_s_connect() or BIO_s_accept()
+ case SSL_ERROR_WANT_CONNECT:
+ case SSL_ERROR_WANT_ACCEPT:
+ // SSL_CTX_set_client_cert_cb related, not used
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ case SSL_ERROR_SSL:
+ default:
+
+ if (lastError == 0) {
+
+ throw exceptions::tls_exception("Unexpected SSL IO error");
+
+ } else {
+
+ char buffer[256];
+ ERR_error_string_n(lastError, buffer, sizeof(buffer));
+ vmime::string msg(buffer);
+ throw exceptions::tls_exception(msg);
+ }
+
+ break;
+ }
+}
+
+
+unsigned int TLSSocket_OpenSSL::getStatus() const {
+
+ return m_status;
+}
+
+
+// Implementation of custom BIO methods
+
+
+// static
+int TLSSocket_OpenSSL::bio_write(BIO* bio, const char* buf, int len) {
+
+ BIO_clear_retry_flags(bio);
+
+ if (buf == NULL || len <= 0) {
+ return -1;
+ }
+
+ TLSSocket_OpenSSL *sok = reinterpret_cast <TLSSocket_OpenSSL*>(BIO_get_data(bio));
+
+ if (!BIO_get_init(bio) || !sok) {
+ return -1;
+ }
+
+ try {
+
+ const size_t n = sok->m_wrapped->sendRawNonBlocking(
+ reinterpret_cast <const byte_t*>(buf), len
+ );
+
+ if (n == 0 && sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) {
+ BIO_set_retry_write(bio);
+ return -1;
+ }
+
+ return static_cast <int>(n);
+
+ } catch (exception& e) {
+
+ // Workaround for passing C++ exceptions from C BIO functions
+ sok->m_ex.reset(e.clone());
+ return -1;
+ }
+}
+
+
+// static
+int TLSSocket_OpenSSL::bio_read(BIO* bio, char* buf, int len) {
+
+ BIO_clear_retry_flags(bio);
+
+ if (buf == NULL || len <= 0) {
+ return -1;
+ }
+
+ TLSSocket_OpenSSL *sok = reinterpret_cast <TLSSocket_OpenSSL*>(BIO_get_data(bio));
+
+ if (!BIO_get_init(bio) || !sok) {
+ return -1;
+ }
+
+ try {
+
+ const size_t n = sok->m_wrapped->receiveRaw(
+ reinterpret_cast <byte_t*>(buf), len
+ );
+
+ if (n == 0 || sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) {
+ BIO_set_retry_read(bio);
+ return -1;
+ }
+
+ return static_cast <int>(n);
+
+ } catch (exception& e) {
+
+ // Workaround for passing C++ exceptions from C BIO functions
+ sok->m_ex.reset(e.clone());
+ return -1;
+ }
+}
+
+
+// static
+int TLSSocket_OpenSSL::bio_puts(BIO* bio, const char* str) {
+
+ return bio_write(bio, str, static_cast <int>(strlen(str)));
+}
+
+
+// static
+long TLSSocket_OpenSSL::bio_ctrl(BIO* bio, int cmd, long num, void* /* ptr */) {
+
+ long ret = 1;
+
+ switch (cmd) {
+
+ case BIO_CTRL_INFO:
+
+ ret = 0;
+ break;
+
+ case BIO_CTRL_GET_CLOSE:
+
+ ret = BIO_get_shutdown(bio);
+ break;
+
+ case BIO_CTRL_SET_CLOSE:
+
+ BIO_set_shutdown(bio, static_cast <int>(num));
+ break;
+
+ case BIO_CTRL_PENDING:
+ case BIO_CTRL_WPENDING:
+
+ ret = 0;
+ break;
+
+ case BIO_CTRL_DUP:
+ case BIO_CTRL_FLUSH:
+
+ ret = 1;
+ break;
+
+ default:
+
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+
+// static
+int TLSSocket_OpenSSL::bio_create(BIO* bio) {
+
+ BIO_set_init(bio, 0);
+ BIO_set_num(bio, 0);
+ BIO_set_data(bio, NULL);
+ BIO_set_flags(bio, 0);
+
+ return 1;
+}
+
+
+// static
+int TLSSocket_OpenSSL::bio_destroy(BIO* bio) {
+
+ if (!bio) {
+ return 0;
+ }
+
+ if (BIO_get_shutdown(bio)) {
+ BIO_set_data(bio, NULL);
+ BIO_set_init(bio, 0);
+ BIO_set_flags(bio, 0);
+ }
+
+ return 1;
+}
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
diff --git a/vmime-master/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp b/vmime-master/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp
new file mode 100644
index 0000000..e30df68
--- /dev/null
+++ b/vmime-master/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp
@@ -0,0 +1,142 @@
+//
+// 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_NET_TLS_TLSSOCKET_OPENSSL_HPP_INCLUDED
+#define VMIME_NET_TLS_TLSSOCKET_OPENSSL_HPP_INCLUDED
+
+
+#ifndef VMIME_BUILDING_DOC
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+
+#include "vmime/net/tls/TLSSocket.hpp"
+
+#include <memory>
+
+#include <openssl/ssl.h>
+
+
+namespace vmime {
+namespace net {
+namespace tls {
+
+
+class TLSSession;
+class TLSSession_OpenSSL;
+
+
+class TLSSocket_OpenSSL : public TLSSocket {
+
+public:
+
+ TLSSocket_OpenSSL(
+ const shared_ptr <TLSSession_OpenSSL>& session,
+ const shared_ptr <socket>& sok
+ );
+
+ ~TLSSocket_OpenSSL();
+
+
+ void handshake();
+
+ shared_ptr <security::cert::certificateChain> getPeerCertificates();
+
+ // Implementation of 'socket'
+ void connect(const string& address, const port_t port);
+ void disconnect();
+ bool isConnected() const;
+
+ bool waitForRead(const int msecs = 30000);
+ bool waitForWrite(const int msecs = 30000);
+
+ void receive(string& buffer);
+ size_t receiveRaw(byte_t* buffer, const size_t count);
+
+ void send(const string& buffer);
+ void send(const char* str);
+ void sendRaw(const byte_t* buffer, const size_t count);
+ size_t sendRawNonBlocking(const byte_t* buffer, const size_t count);
+
+ size_t getBlockSize() const;
+
+ unsigned int getStatus() const;
+
+ const string getPeerName() const;
+ const string getPeerAddress() const;
+
+ shared_ptr <timeoutHandler> getTimeoutHandler();
+
+ void setTracer(const shared_ptr <net::tracer>& tracer);
+ shared_ptr <net::tracer> getTracer();
+
+private:
+
+ static BIO_METHOD sm_customBIOMethod;
+
+ static int bio_write(BIO* bio, const char* buf, int len);
+ static int bio_read(BIO* bio, char* buf, int len);
+ static int bio_puts(BIO* bio, const char* str);
+ static int bio_gets(BIO* bio, char* buf, int len);
+ static long bio_ctrl(BIO* bio, int cmd, long num, void* ptr);
+ static int bio_create(BIO* bio);
+ static int bio_destroy(BIO* bio);
+
+ void createSSLHandle();
+
+ void internalThrow();
+ void handleError(int rc);
+
+
+ shared_ptr <TLSSession_OpenSSL> m_session;
+
+ shared_ptr <socket> m_wrapped;
+
+ bool m_connected;
+
+ byte_t m_buffer[65536];
+
+ SSL* m_ssl;
+
+ unsigned int m_status;
+
+ // Last exception thrown from C BIO functions
+ scoped_ptr <exception> m_ex;
+};
+
+
+} // tls
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+#endif // VMIME_BUILDING_DOC
+
+#endif // VMIME_NET_TLS_TLSSOCKET_OPENSSL_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/net/tracer.cpp b/vmime-master/src/vmime/net/tracer.cpp
new file mode 100644
index 0000000..66afb36
--- /dev/null
+++ b/vmime-master/src/vmime/net/tracer.cpp
@@ -0,0 +1,74 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "tracer.hpp"
+
+
+#include <sstream>
+
+
+namespace vmime {
+namespace net {
+
+
+void tracer::traceReceiveBytes(const size_t count, const string& state) {
+
+ std::ostringstream oss;
+ oss << "{...";
+
+ if (!state.empty()) {
+ oss << state << ": ";
+ }
+
+ oss << count << " bytes of data...}";
+
+ traceReceive(oss.str());
+}
+
+
+void tracer::traceSendBytes(const size_t count, const string& state) {
+
+ std::ostringstream oss;
+ oss << "{...";
+
+ if (!state.empty()) {
+ oss << state << ": ";
+ }
+
+ oss << count << " bytes of data...}";
+
+ traceSend(oss.str());
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
diff --git a/vmime-master/src/vmime/net/tracer.hpp b/vmime-master/src/vmime/net/tracer.hpp
new file mode 100644
index 0000000..7472463
--- /dev/null
+++ b/vmime-master/src/vmime/net/tracer.hpp
@@ -0,0 +1,110 @@
+//
+// 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_NET_TRACER_HPP_INCLUDED
+#define VMIME_NET_TRACER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/base.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+class service;
+
+
+/** Base class for an object used to trace network communication
+ * between the client and the server.
+ */
+class VMIME_EXPORT tracer : public object {
+
+public:
+
+ virtual ~tracer() {
+
+ }
+
+ /** Trace raw bytes which have been received.
+ *
+ * @param count number of bytes
+ * @param state protocol state (eg. "SASL exchange"), or empty
+ */
+ virtual void traceReceiveBytes(const size_t count, const string& state = "");
+
+ /** Trace raw bytes which have been sent.
+ *
+ * @param count number of bytes
+ * @param state protocol state (eg. "SASL exchange"), or empty
+ */
+ virtual void traceSendBytes(const size_t count, const string& state = "");
+
+ /** Trace a command line which has been sent.
+ *
+ * @param line command line
+ */
+ virtual void traceSend(const string& line) = 0;
+
+ /** Trace a response line which has been received.
+ *
+ * @param line response line
+ */
+ virtual void traceReceive(const string& line) = 0;
+};
+
+
+/** A class to create 'tracer' objects.
+ */
+class VMIME_EXPORT tracerFactory : public object {
+
+public:
+
+ virtual ~tracerFactory() {
+
+ }
+
+ /** Creates a tracer for the specified service.
+ *
+ * @param serv messaging service
+ * @param connectionId an identifier for the connection to distinguate between
+ * different connections used by a service
+ * @return a new tracer
+ */
+ virtual shared_ptr <tracer> create(const shared_ptr <service>& serv, const int connectionId) = 0;
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_TRACER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/net/transport.cpp b/vmime-master/src/vmime/net/transport.cpp
new file mode 100644
index 0000000..0991302
--- /dev/null
+++ b/vmime-master/src/vmime/net/transport.cpp
@@ -0,0 +1,265 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/transport.hpp"
+
+#include "vmime/utility/stream.hpp"
+#include "vmime/mailboxList.hpp"
+#include "vmime/message.hpp"
+#include "vmime/dateTime.hpp"
+#include "vmime/messageId.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+
+
+namespace vmime {
+namespace net {
+
+
+transport::transport(
+ const shared_ptr <session>& sess,
+ const serviceInfos& infos,
+ const shared_ptr <security::authenticator>& auth
+)
+ : service(sess, infos, auth) {
+
+}
+
+
+shared_ptr <headerField> transport::processHeaderField(const shared_ptr <headerField>& field) {
+
+ if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::BCC)) {
+
+ // Remove Bcc headers from the message, as required by the RFC.
+ // Some SMTP server automatically strip this header (Postfix, qmail),
+ // and others have an option for this (Exim).
+ return null;
+
+ } else if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::RETURN_PATH)) {
+
+ // RFC-2821: Return-Path header is added by the final transport system
+ // that delivers the message to its recipient. Then, it should not be
+ // transmitted to MSA.
+ return null;
+
+ } else if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::ORIGINAL_RECIPIENT)) {
+
+ // RFC-2298: Delivering MTA may add the Original-Recipient header and
+ // discard existing one; so, no need to send it.
+ return null;
+ }
+
+ // Leave the header field as is
+ return field;
+}
+
+
+void transport::processHeader(const shared_ptr <header>& header) {
+
+ if (header->getFieldCount() == 0) {
+ return;
+ }
+
+ // Remove/replace fields
+ for (size_t idx = header->getFieldCount() ; idx != 0 ; --idx) {
+
+ shared_ptr <headerField> field = header->getFieldAt(idx - 1);
+ shared_ptr <headerField> newField = processHeaderField(field);
+
+ if (newField == NULL) {
+ header->removeField(field);
+ } else if (newField != field) {
+ header->replaceField(field, newField);
+ }
+ }
+
+ // Add missing header fields
+ // -- Date
+ if (!header->hasField(fields::DATE)) {
+ header->Date()->setValue(datetime::now());
+ }
+
+ // -- Mime-Version
+ if (!header->hasField(fields::MIME_VERSION)) {
+ header->MimeVersion()->setValue(string(SUPPORTED_MIME_VERSION));
+ }
+
+ // -- Message-Id
+ if (!header->hasField(fields::MESSAGE_ID)) {
+ header->MessageId()->setValue(messageId::generateId());
+ }
+}
+
+
+static void extractMailboxes(
+ mailboxList& recipients,
+ const addressList& list
+) {
+
+ for (size_t i = 0 ; i < list.getAddressCount() ; ++i) {
+
+ shared_ptr <mailbox> mbox = dynamicCast <mailbox>(list.getAddressAt(i)->clone());
+
+ if (mbox) {
+ recipients.appendMailbox(mbox);
+ }
+ }
+}
+
+
+void transport::send(
+ const shared_ptr <vmime::message>& msg,
+ utility::progressListener* progress,
+ const dsnAttributes& dsnAttrs
+) {
+
+ // Extract expeditor
+ shared_ptr <mailbox> fromMbox =
+ msg->getHeader()->findFieldValue <mailbox>(fields::FROM);
+
+ if (!fromMbox) {
+ throw exceptions::no_expeditor();
+ }
+
+ mailbox expeditor = *fromMbox;
+
+ // Extract sender
+ shared_ptr <mailbox> senderMbox =
+ msg->getHeader()->findFieldValue <mailbox>(fields::SENDER);
+
+ mailbox sender;
+
+ if (!senderMbox) {
+ sender = expeditor;
+ } else {
+ sender = *senderMbox;
+ }
+
+ // Extract recipients
+ mailboxList recipients;
+
+ // -- "To" field
+ shared_ptr <addressList> addresses =
+ msg->getHeader()->findFieldValue <addressList>(fields::TO);
+
+ if (addresses) {
+ extractMailboxes(recipients, *addresses);
+ }
+
+ // -- "Cc" field
+ addresses = msg->getHeader()->findFieldValue <addressList>(fields::CC);
+
+ if (addresses) {
+ extractMailboxes(recipients, *addresses);
+ }
+
+ // -- "Bcc" field
+ addresses = msg->getHeader()->findFieldValue <addressList>(fields::BCC);
+
+ if (addresses) {
+ extractMailboxes(recipients, *addresses);
+ }
+
+ // Process message header by removing fields that should be removed
+ // before transmitting the message to MSA, and adding missing fields
+ // which are required/recommended by the RFCs.
+ shared_ptr <header> hdr = vmime::clone(msg->getHeader());
+ processHeader(hdr);
+
+ // To avoid cloning message body (too much overhead), use processed
+ // header during the time we are generating the message to a stream.
+ // Revert it back to original header after.
+ struct XChangeMsgHeader {
+
+ XChangeMsgHeader(
+ const shared_ptr <vmime::message>& _msg,
+ const shared_ptr <vmime::header>& _hdr
+ )
+ : msg(_msg),
+ hdr(msg->getHeader()) {
+
+ // Set new header
+ msg->setHeader(_hdr);
+ }
+
+ ~XChangeMsgHeader() {
+
+ // Revert original header
+ msg->setHeader(hdr);
+ }
+
+ private:
+
+ shared_ptr <vmime::message> msg;
+ shared_ptr <vmime::header> hdr;
+
+ } headerExchanger(msg, hdr);
+
+ send(msg, expeditor, recipients, progress, sender, dsnAttrs);
+}
+
+
+void transport::send(
+ const shared_ptr <vmime::message>& msg,
+ const mailbox& expeditor,
+ const mailboxList& recipients,
+ utility::progressListener* progress,
+ const mailbox& sender,
+ const dsnAttributes& dsnAttrs
+) {
+
+ // Generate the message, "stream" it and delegate the sending
+ // to the generic send() function.
+ std::ostringstream oss;
+ utility::outputStreamAdapter ossAdapter(oss);
+
+ msg->generate(ossAdapter);
+
+ const string& str(oss.str());
+
+ utility::inputStreamStringAdapter isAdapter(str);
+
+ send(expeditor, recipients, isAdapter, str.length(), progress, sender,
+ dsnAttrs);
+}
+
+
+transport::Type transport::getType() const {
+
+ return TYPE_TRANSPORT;
+}
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
diff --git a/vmime-master/src/vmime/net/transport.hpp b/vmime-master/src/vmime/net/transport.hpp
new file mode 100644
index 0000000..daa4717
--- /dev/null
+++ b/vmime-master/src/vmime/net/transport.hpp
@@ -0,0 +1,152 @@
+//
+// 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_NET_TRANSPORT_HPP_INCLUDED
+#define VMIME_NET_TRANSPORT_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/dsnAttributes.hpp"
+#include "vmime/net/service.hpp"
+#include "vmime/utility/stream.hpp"
+
+#include "vmime/mailboxList.hpp"
+
+
+namespace vmime {
+
+class header;
+class headerField;
+class message;
+class mailbox;
+class mailboxList;
+
+namespace net {
+
+
+/** A transport service.
+ * Encapsulate protocols that can send messages.
+ */
+class VMIME_EXPORT transport : public service {
+
+protected:
+
+ transport(
+ const shared_ptr <session>& sess,
+ const serviceInfos& infos,
+ const shared_ptr <security::authenticator>& auth
+ );
+
+public:
+
+ /** Send a message over this transport service.
+ * The default implementation simply generates the whole message into
+ * a string buffer and "streams" it via a inputStreamStringAdapter.
+ *
+ * @param msg message to send
+ * @param progress progress listener, or NULL if not used
+ * @param dsnAttributes attributes for Delivery Status Notification (if needed)
+ */
+ virtual void send(
+ const shared_ptr <vmime::message>& msg,
+ utility::progressListener* progress = NULL,
+ const dsnAttributes& dsnAttrs = dsnAttributes()
+ );
+
+ /** Send a message over this transport service.
+ *
+ * @param expeditor expeditor mailbox
+ * @param recipients list of recipient mailboxes
+ * @param is input stream providing message data (header + body)
+ * @param size size of the message data
+ * @param progress progress listener, or NULL if not used
+ * @param sender envelope sender (if empty, expeditor will be used)
+ * @param dsnAttributes attributes for Delivery Status Notification (if needed)
+ */
+ virtual void send(
+ const mailbox& expeditor,
+ const mailboxList& recipients,
+ utility::inputStream& is,
+ const size_t size,
+ utility::progressListener* progress = NULL,
+ const mailbox& sender = mailbox(),
+ const dsnAttributes& dsnAttrs = dsnAttributes()
+ ) = 0;
+
+ /** Send a message over this transport service.
+ * The default implementation simply generates the whole message into
+ * a string buffer and "streams" it via a inputStreamStringAdapter.
+ *
+ * @param msg message to send
+ * @param expeditor expeditor mailbox
+ * @param recipients list of recipient mailboxes
+ * @param progress progress listener, or NULL if not used
+ * @param sender envelope sender (if empty, expeditor will be used)
+ * @param dsnAttributes attributes for Delivery Status Notification (if needed)
+ */
+ virtual void send(
+ const shared_ptr <vmime::message>& msg,
+ const mailbox& expeditor,
+ const mailboxList& recipients,
+ utility::progressListener* progress = NULL,
+ const mailbox& sender = mailbox(),
+ const dsnAttributes& dsnAttrs = dsnAttributes()
+ );
+
+
+ Type getType() const;
+
+protected:
+
+ /** Called by processHeader().
+ * Decides what to do with the specified header field.
+ *
+ * @return NULL if the header should be removed, a reference to a new headerField
+ * if the field is to be replaced, or a reference to the same headerField
+ * that was passed if the field should be left as is
+ */
+ shared_ptr <headerField> processHeaderField(const shared_ptr <headerField>& field);
+
+ /** Prepares the header before transmitting the message.
+ * Removes headers that should not be present (eg. "Bcc", "Return-Path"),
+ * or adds missing headers that are required/recommended by the RFCs.
+ * The header is modified inline.
+ *
+ * @param header headers to process
+ */
+ void processHeader(const shared_ptr <header>& header);
+};
+
+
+} // net
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_NET_TRANSPORT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/object.cpp b/vmime-master/src/vmime/object.cpp
new file mode 100644
index 0000000..f61b2ac
--- /dev/null
+++ b/vmime-master/src/vmime/object.cpp
@@ -0,0 +1,52 @@
+//
+// 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.
+//
+
+#include "vmime/types.hpp"
+#include "vmime/object.hpp"
+
+
+namespace vmime {
+
+
+object::object() {
+
+}
+
+
+object::object(const object&) {
+
+}
+
+
+object& object::operator=(const object&) {
+
+ return *this;
+}
+
+
+object::~object() {
+
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/object.hpp b/vmime-master/src/vmime/object.hpp
new file mode 100644
index 0000000..5869d38
--- /dev/null
+++ b/vmime-master/src/vmime/object.hpp
@@ -0,0 +1,52 @@
+//
+// 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_OBJECT_HPP_INCLUDED
+#define VMIME_OBJECT_HPP_INCLUDED
+
+
+#include "vmime/types.hpp"
+
+
+namespace vmime {
+
+
+/** Base object for all objects in the library.
+ */
+class VMIME_EXPORT object {
+
+protected:
+
+ object();
+ object(const object&);
+
+ object& operator=(const object&);
+
+ virtual ~object();
+};
+
+
+} // vmime
+
+
+#endif // VMIME_OBJECT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/parameter.cpp b/vmime-master/src/vmime/parameter.cpp
new file mode 100644
index 0000000..41b37a4
--- /dev/null
+++ b/vmime-master/src/vmime/parameter.cpp
@@ -0,0 +1,665 @@
+//
+// 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.
+//
+
+#include "vmime/parameter.hpp"
+#include "vmime/parserHelpers.hpp"
+
+#include "vmime/text.hpp"
+#include "vmime/encoding.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+#include "vmime/utility/outputStreamStringAdapter.hpp"
+
+
+namespace vmime {
+
+
+parameter::parameter(const string& name)
+ : m_name(name),
+ m_value(make_shared <word>()) {
+
+}
+
+
+parameter::parameter(const string& name, const word& value)
+ : m_name(name),
+ m_value(make_shared <word>(value)) {
+
+}
+
+
+parameter::parameter(const string& name, const string& value)
+ : m_name(name),
+ m_value(make_shared <word>(value)) {
+
+}
+
+
+parameter::parameter(const parameter&)
+ : component() {
+
+}
+
+
+shared_ptr <component> parameter::clone() const {
+
+ shared_ptr <parameter> p = make_shared <parameter>(m_name);
+ p->copyFrom(*this);
+
+ return (p);
+}
+
+
+void parameter::copyFrom(const component& other) {
+
+ const parameter& param = dynamic_cast <const parameter&>(other);
+
+ m_name = param.m_name;
+ m_value->copyFrom(*param.m_value);
+}
+
+
+parameter& parameter::operator=(const parameter& other) {
+
+ copyFrom(other);
+ return (*this);
+}
+
+
+const string& parameter::getName() const {
+
+ return m_name;
+}
+
+
+const word& parameter::getValue() const {
+
+ return *m_value;
+}
+
+
+void parameter::setValue(const component& value) {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter vos(oss);
+
+ value.generate(vos);
+
+ setValue(word(oss.str(), vmime::charsets::US_ASCII));
+}
+
+
+void parameter::setValue(const word& value) {
+
+ *m_value = value;
+}
+
+
+void parameter::parseImpl(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ m_value->setBuffer(string(buffer.begin() + position, buffer.begin() + end));
+
+ if (ctx.getInternationalizedEmailSupport()) {
+ m_value->setCharset(charset(charsets::UTF_8));
+ } else {
+ m_value->setCharset(charset(charsets::US_ASCII));
+ }
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void parameter::parse(
+ const parsingContext& ctx,
+ const std::vector <valueChunk>& chunks
+) {
+
+ bool foundCharsetChunk = false;
+
+ charset ch(charsets::US_ASCII);
+ string lang;
+
+ std::ostringstream value;
+ value.imbue(std::locale::classic());
+
+ for (std::vector <valueChunk>::size_type i = 0 ; i < chunks.size() ; ++i) {
+
+ const valueChunk& chunk = chunks[i];
+
+ // Decode following data
+ if (chunk.encoded) {
+
+ const size_t len = chunk.data.length();
+ size_t pos = 0;
+
+ // If this is the first encoded chunk, extract charset
+ // and language information
+ if (!foundCharsetChunk) {
+
+ // Eg. "us-ascii'en'This%20is%20even%20more%20"
+ size_t q = chunk.data.find_first_of('\'');
+
+ if (q != string::npos) {
+
+ const string chs = chunk.data.substr(0, q);
+
+ if (!chs.empty()) {
+ ch = charset(chs);
+ }
+
+ ++q;
+ pos = q;
+ }
+
+ q = chunk.data.find_first_of('\'', pos);
+
+ if (q != string::npos) {
+
+ // Extract language
+ lang = chunk.data.substr(pos, q - pos);
+
+ ++q;
+ pos = q;
+ }
+
+ foundCharsetChunk = true;
+ }
+
+ for (size_t i = pos ; i < len ; ++i) {
+
+ const char c = chunk.data[i];
+
+ if (c == '%' && i + 2 < len) {
+
+ unsigned int v = 0;
+
+ // First char
+ switch (chunk.data[i + 1]) {
+
+ case 'a': case 'A': v += 10; break;
+ case 'b': case 'B': v += 11; break;
+ case 'c': case 'C': v += 12; break;
+ case 'd': case 'D': v += 13; break;
+ case 'e': case 'E': v += 14; break;
+ case 'f': case 'F': v += 15; break;
+ default: // assume 0-9
+
+ v += (chunk.data[i + 1] - '0');
+ break;
+ }
+
+ v *= 16;
+
+ // Second char
+ switch (chunk.data[i + 2]) {
+
+ case 'a': case 'A': v += 10; break;
+ case 'b': case 'B': v += 11; break;
+ case 'c': case 'C': v += 12; break;
+ case 'd': case 'D': v += 13; break;
+ case 'e': case 'E': v += 14; break;
+ case 'f': case 'F': v += 15; break;
+ default: // assume 0-9
+
+ v += (chunk.data[i + 2] - '0');
+ break;
+ }
+
+ value << static_cast <char>(v);
+
+ i += 2; // skip next 2 chars
+
+ } else {
+
+ value << c;
+ }
+ }
+
+ // Simply copy data, as it is not encoded
+ } else {
+
+ // This syntax is non-standard (expressly prohibited
+ // by RFC-2047), but is used by Mozilla:
+ //
+ // Content-Type: image/png;
+ // name="=?us-ascii?Q?Logo_VMime=2Epng?="
+
+ // Using 'vmime::text' to parse the data is safe even
+ // if the data is not encoded, because it can recover
+ // from parsing errors.
+ vmime::text t;
+ t.parse(ctx, chunk.data);
+
+ if (t.getWordCount() != 0) {
+
+ value << t.getWholeBuffer();
+
+ if (!foundCharsetChunk) {
+
+ // This is still wrong. Each word can have it's own charset, and can
+ // be mixed (eg. iso-8859-1 and iso-2022-jp), but very unlikely. Real
+ // fix is to have parameters store a vmime::text instead of a
+ // vmime::word in m_value. But that changes the interface.
+ for (size_t i = 0 ; i < t.getWordCount() ; ++i) {
+
+ if (t.getWordAt(i)->getCharset() != ch && ch == charsets::US_ASCII) {
+
+ ch = t.getWordAt(i)->getCharset();
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ m_value->setBuffer(value.str());
+ m_value->setCharset(ch);
+ m_value->setLanguage(lang);
+}
+
+
+void parameter::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ const string& name = m_name;
+ const string& value = m_value->getBuffer();
+
+ // For compatibility with implementations that do not understand RFC-2231,
+ // we may also generate a normal "7bit/us-ascii" parameter
+ generationContext::EncodedParameterValueModes
+ genMode = ctx.getEncodedParameterValueMode();
+
+#if VMIME_ALWAYS_GENERATE_7BIT_PARAMETER
+ genMode = generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047;
+#endif
+
+ // [By Eugene A. Shatokhin]
+ // Note that if both the normal "7bit/us-ascii" value and the extended
+ // value are present, the latter can be ignored by mail processing systems.
+ // This may lead to annoying problems, for example, with strange names of
+ // attachments with all but 7-bit ascii characters removed, etc. To avoid
+ // this, I would suggest not to create "7bit/us-ascii" value if the extended
+ // value is to be generated.
+
+ // A stream for a temporary storage
+ string sevenBitBuffer;
+ utility::outputStreamStringAdapter sevenBitStream(sevenBitBuffer);
+
+ size_t pos = curLinePos;
+
+ if (pos + name.length() + 10 + value.length() > ctx.getMaxLineLength()) {
+
+ sevenBitStream << NEW_LINE_SEQUENCE;
+ pos = NEW_LINE_SEQUENCE_LENGTH;
+ }
+
+ bool needQuoting = false;
+ bool needQuotedPrintable = false;
+ size_t valueLength = 0;
+
+ // Use worst-case length name.length()+2 for 'name=' part of line
+ for (size_t i = 0 ; (i < value.length()) && (pos + name.length() + 2 + valueLength < ctx.getMaxLineLength() - 4) ; ++i, ++valueLength) {
+
+ switch (value[i]) {
+
+ // Characters that need to be quoted _and_ escaped
+ case '"':
+ case '\\':
+ // Other characters that need quoting
+ case ' ':
+ case '\t':
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '@':
+ case ',':
+ case ';':
+ case ':':
+ case '/':
+ case '[':
+ case ']':
+ case '?':
+ case '=':
+
+ needQuoting = true;
+ break;
+
+ default:
+
+ if (!parserHelpers::isAscii(value[i])) {
+ needQuotedPrintable = true;
+ needQuoting = true;
+ }
+
+ break;
+ }
+ }
+
+ const bool cutValue = (valueLength != value.length()); // has the value been cut?
+
+ if (needQuoting) {
+
+ sevenBitStream << name << "=\"";
+ pos += name.length() + 2;
+
+ } else {
+
+ sevenBitStream << name << "=";
+ pos += name.length() + 1;
+ }
+
+ // Check whether there is a recommended encoding for this charset.
+ // If so, the whole buffer will be encoded. Else, the number of
+ // 7-bit (ASCII) bytes in the input will be used to determine if
+ // we need to encode the whole buffer.
+ encoding recommendedEnc;
+ const bool alwaysEncode = m_value->getCharset().getRecommendedEncoding(recommendedEnc);
+ bool extended = alwaysEncode;
+
+ if ((needQuotedPrintable || cutValue || !m_value->getLanguage().empty()) &&
+ genMode != generationContext::PARAMETER_VALUE_NO_ENCODING) {
+
+ // Send the name in quoted-printable, so outlook express et.al.
+ // will understand the real filename
+ size_t oldLen = sevenBitBuffer.length();
+ m_value->generate(sevenBitStream);
+ pos += sevenBitBuffer.length() - oldLen;
+ extended = true; // also send with RFC-2231 encoding
+
+ } else {
+
+ // Do not chop off this value, but just add the complete name as one header line.
+ for (size_t i = 0, n = value.length(), curValueLength = 0 ;
+ i < n && curValueLength < valueLength ; ++i) {
+
+ const char_t c = value[i];
+
+ if (/* needQuoting && */ (c == '"' || c == '\\')) { // 'needQuoting' is implicit
+
+ sevenBitStream << '\\' << value[i]; // escape 'x' with '\x'
+ pos += 2;
+
+ } else if (parserHelpers::isAscii(c)) {
+
+ sevenBitStream << value[i];
+ ++pos;
+ ++curValueLength;
+
+ } else {
+
+ extended = true;
+ }
+ }
+
+ } // !needQuotedPrintable
+
+ if (needQuoting) {
+
+ sevenBitStream << '"';
+ ++pos;
+ }
+
+ if (genMode == generationContext::PARAMETER_VALUE_RFC2047_ONLY ||
+ genMode == generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047) {
+
+ os << sevenBitBuffer;
+ }
+
+ // Also generate an extended parameter if the value contains 8-bit characters
+ // or is too long for a single line
+ if ((extended || cutValue) &&
+ genMode != generationContext::PARAMETER_VALUE_NO_ENCODING &&
+ genMode != generationContext::PARAMETER_VALUE_RFC2047_ONLY) {
+
+
+ if (genMode == generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047) {
+
+ os << ';';
+ ++pos;
+
+ } else {
+
+ // The data output to 'sevenBitBuffer' will be discarded in this case
+ pos = curLinePos;
+ }
+
+ /* RFC-2231
+ * ========
+ *
+ * Content-Type: message/external-body; access-type=URL;
+ * URL*0="ftp://";
+ * URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar"
+ *
+ * Content-Type: application/x-stuff;
+ * title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A
+ *
+ * Content-Type: application/x-stuff;
+ * title*0*=us-ascii'en'This%20is%20even%20more%20
+ * title*1*=%2A%2A%2Afun%2A%2A%2A%20
+ * title*2="isn't it!"
+ */
+
+ // Check whether there is enough space for the first section:
+ // parameter name, section identifier, charset and separators
+ // + at least 5 characters for the value
+ const size_t firstSectionLength =
+ name.length() + 4 /* *0*= */ + 2 /* '' */
+ + m_value->getCharset().getName().length();
+
+ if (pos + firstSectionLength + 5 >= ctx.getMaxLineLength()) {
+
+ os << NEW_LINE_SEQUENCE;
+ pos = NEW_LINE_SEQUENCE_LENGTH;
+ }
+
+ // Split text into multiple sections that fit on one line
+ int sectionCount = 0;
+ std::vector <string> sectionText;
+
+ string currentSection;
+ size_t currentSectionLength = firstSectionLength;
+
+ for (size_t i = 0 ; i < value.length() ; ++i) {
+
+ // Check whether we should start a new line (taking into
+ // account the next character will be encoded = worst case)
+ if (currentSectionLength + 3 >= ctx.getMaxLineLength()) {
+
+ sectionText.push_back(currentSection);
+ sectionCount++;
+
+ currentSection.clear();
+ currentSectionLength = NEW_LINE_SEQUENCE_LENGTH + name.length() + 6;
+ }
+
+ // Output next character
+ const char_t c = value[i];
+ bool encode = false;
+
+ switch (c) {
+
+ // special characters
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ case '%':
+ case '"':
+ case ';':
+ case ',':
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '@':
+ case ':':
+ case '/':
+ case '[':
+ case ']':
+ case '?':
+ case '=':
+
+ encode = true;
+ break;
+
+ default:
+
+ encode = (!parserHelpers::isPrint(c) ||
+ !parserHelpers::isAscii(c) ||
+ alwaysEncode);
+
+ break;
+ }
+
+ if (encode) { // need encoding
+
+ const int h1 = static_cast <unsigned char>(c) / 16;
+ const int h2 = static_cast <unsigned char>(c) % 16;
+
+ currentSection += '%';
+ currentSection += "0123456789ABCDEF"[h1];
+ currentSection += "0123456789ABCDEF"[h2];
+
+ pos += 3;
+ currentSectionLength += 3;
+
+ } else {
+
+ currentSection += value[i];
+
+ ++pos;
+ ++currentSectionLength;
+ }
+ }
+
+ if (!currentSection.empty()) {
+
+ sectionText.push_back(currentSection);
+ sectionCount++;
+ }
+
+ // Output sections
+ for (int sectionNumber = 0 ; sectionNumber < sectionCount ; ++sectionNumber) {
+
+ os << name;
+
+ if (sectionCount != 1) { // no section specifier when only a single one
+
+ os << '*';
+ os << sectionNumber;
+ }
+
+ os << "*=";
+
+ if (sectionNumber == 0) {
+
+ os << m_value->getCharset().getName();
+ os << '\'' << /* No language */ '\'';
+ }
+
+ os << sectionText[sectionNumber];
+
+ if (sectionNumber + 1 < sectionCount) {
+
+ os << ';';
+ os << NEW_LINE_SEQUENCE;
+ pos = NEW_LINE_SEQUENCE_LENGTH;
+ }
+ }
+
+ } else if (!(genMode == generationContext::PARAMETER_VALUE_RFC2047_ONLY ||
+ genMode == generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047)) {
+
+ // The value does not contain 8-bit characters and
+ // is short enough for a single line.
+ // "7bit/us-ascii" will suffice in this case.
+
+ // Output what has been stored in temporary buffer so far
+ os << sevenBitBuffer;
+ }
+
+ if (newLinePos) {
+ *newLinePos = pos;
+ }
+}
+
+
+size_t parameter::getGeneratedSize(const generationContext& ctx) {
+
+ const string& name = m_name;
+ const string& value = m_value->getBuffer();
+
+ const size_t bytesNeedingEncoding =
+ value.length() - utility::stringUtils::countASCIIchars(value.begin(), value.end());
+
+ const size_t valueLength = value.length();
+
+ // Compute generated length in the very worst case
+
+ // Non-encoded parameter + value (worst case: quoting + QP)
+ size_t len = name.length() + 1 /* = */ + 2 /* "" */ + 7 /* =?...?Q?...?= */
+ + m_value->getCharset().getName().length() + valueLength + bytesNeedingEncoding * 2 + 1 /* ; */;
+
+ // Encoded parameter + value
+ const size_t maxEncodedValueLengthOnLine =
+ ctx.getMaxLineLength() - 2 /* CRLF */ - NEW_LINE_SEQUENCE_LENGTH
+ - name.length() - 5 /* *00*= */ - 1 /* ; */;
+
+ const size_t encodedValueLength = (valueLength + bytesNeedingEncoding * 2)
+ + m_value->getCharset().getName().length() + m_value->getLanguage().length() + 2 /* 2 x ' */;
+
+ const size_t numberOfSections = 1 /* worst case: generation starts at the end of a line */
+ + std::max(size_t(1), encodedValueLength / maxEncodedValueLengthOnLine);
+
+ len += numberOfSections * (name.length() + 5 /* *00*= */ + 1 /* ; */ + 2 /* CRLF */ + NEW_LINE_SEQUENCE_LENGTH) + encodedValueLength;
+
+ return len;
+
+}
+
+
+const std::vector <shared_ptr <component> > parameter::getChildComponents() {
+
+ std::vector <shared_ptr <component> > list;
+
+ list.push_back(m_value);
+
+ return list;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/parameter.hpp b/vmime-master/src/vmime/parameter.hpp
new file mode 100644
index 0000000..f965bad
--- /dev/null
+++ b/vmime-master/src/vmime/parameter.hpp
@@ -0,0 +1,176 @@
+//
+// 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_PARAMETER_HPP_INCLUDED
+#define VMIME_PARAMETER_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/component.hpp"
+#include "vmime/word.hpp"
+
+
+namespace vmime {
+
+
+class VMIME_EXPORT parameter : public component {
+
+ friend class parameterizedHeaderField;
+
+private:
+
+ parameter(const parameter&);
+
+public:
+
+ /** Construct a parameter with no value.
+ * Charset is set to the current locale charset.
+ *
+ * @param name parameter name
+ */
+ parameter(const string& name);
+
+ /** Construct a parameter given a name and a value.
+ *
+ * @param name parameter name
+ * @param value parameter value
+ */
+ parameter(const string& name, const word& value);
+
+ /** Construct a parameter given a name and a string value
+ * expressed in the current locale charset.
+ *
+ * @param name parameter name
+ * @param value parameter value
+ */
+ parameter(const string& name, const string& value);
+
+
+#ifndef VMIME_BUILDING_DOC
+
+ /** A single section of a multi-section parameter,
+ * as defined in RFC-2231/3. This is used when
+ * calling parse() on the parameter.
+ */
+ struct valueChunk {
+ bool encoded;
+ string data;
+ };
+
+#endif // VMIME_BUILDING_DOC
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ parameter& operator=(const parameter& other);
+
+ size_t getGeneratedSize(const generationContext& ctx);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+ /** Return the name of this parameter.
+ *
+ * @return name of this parameter
+ */
+ const string& getName() const;
+
+ /** Return the raw value of this parameter.
+ *
+ * @return read-only value
+ */
+ const word& getValue() const;
+
+ /** Return the value of this object in the specified type.
+ * For example, the following code:
+ *
+ * <pre>
+ * getParameter("creation-date")->getValueAs <vmime::dateTime>()
+ * </pre>
+ *
+ * is equivalent to:
+ *
+ * <pre>
+ * shared_ptr <vmime::word> rawValue = getParameter("creation-date");
+ *
+ * vmime::dateTime theDate;
+ * theDate.parse(rawValue->getBuffer());
+ * </pre>
+ *
+ * @param T type to which convert the value
+ * @return value
+ */
+ template <typename T>
+ const T getValueAs() const {
+
+ T ret;
+ ret.parse(m_value->getBuffer());
+
+ return ret;
+ }
+
+ /** Set the value of this parameter.
+ *
+ * @param value new value
+ */
+ void setValue(const component& value);
+
+ /** Set the raw value of this parameter.
+ *
+ * @param value new value
+ */
+ void setValue(const word& value);
+
+
+protected:
+
+ void parseImpl(
+ const 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;
+
+private:
+
+ void parse(
+ const parsingContext& ctx,
+ const std::vector <valueChunk>& chunks
+ );
+
+
+ string m_name;
+ shared_ptr <word> m_value;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_PARAMETER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/parameterizedHeaderField.cpp b/vmime-master/src/vmime/parameterizedHeaderField.cpp
new file mode 100644
index 0000000..6815fad
--- /dev/null
+++ b/vmime-master/src/vmime/parameterizedHeaderField.cpp
@@ -0,0 +1,634 @@
+//
+// 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.
+//
+
+#include "vmime/parameterizedHeaderField.hpp"
+#include "vmime/text.hpp"
+#include "vmime/parserHelpers.hpp"
+
+
+namespace vmime {
+
+
+parameterizedHeaderField::parameterizedHeaderField() {
+
+}
+
+
+parameterizedHeaderField::~parameterizedHeaderField() {
+
+ removeAllParameters();
+}
+
+
+/*
+ This class handles field contents of the following form:
+ Field: VALUE; PARAM1="VALUE1"; PARAM2="VALUE2"...
+
+ eg. RFC-1521
+
+ content := "Content-Type" ":" type "/" subtype *(";" parameter)
+
+ parameter := attribute "=" value
+
+ attribute := token ; case-insensitive
+
+ value := token / quoted-string
+
+ token := 1*<any (ASCII) CHAR except SPACE, CTLs, or tspecials>
+
+ tspecials := "(" / ")" / "<" / ">" / "@"
+ / "," / ";" / ":" / "\" / <">
+ / "/" / "[" / "]" / "?" / "="
+ ; Must be in quoted-string,
+ ; to use within parameter values
+*/
+
+
+#ifndef VMIME_BUILDING_DOC
+
+struct paramInfo {
+
+ bool extended;
+ std::vector <parameter::valueChunk> value;
+ size_t start;
+ size_t end;
+};
+
+#endif // VMIME_BUILDING_DOC
+
+
+void parameterizedHeaderField::parseImpl(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ const char* const pend = buffer.data() + end;
+ const char* const pstart = buffer.data() + position;
+ const char* p = pstart;
+
+ // Skip non-significant whitespaces
+ size_t valueStart = position;
+
+ while (p < pend && parserHelpers::isSpace(*p)) {
+ ++p;
+ ++valueStart;
+ }
+
+ // Advance up to ';', if any
+ size_t valueLength = 0;
+
+ while (p < pend && *p != ';' && (!parserHelpers::isSpace(*p))) { // FIXME: support ";" inside quoted or RFC-2047-encoded text
+
+ ++p;
+ ++valueLength;
+ }
+
+ // Trim whitespaces at the end of the value
+ while (valueLength > 0 && parserHelpers::isSpace(buffer[valueStart + valueLength - 1])) {
+ --valueLength;
+ }
+
+ // Parse value
+ getValue()->parse(ctx, buffer, valueStart, valueStart + valueLength);
+
+ // Reset parameters
+ removeAllParameters();
+
+ // If there is one or more parameters following...
+ if (p < pend) {
+
+ std::map <string, paramInfo> params;
+
+ if (*p != ';') {
+
+ while (p < pend && *p != ';') { // FIXME: support ";" inside quoted or RFC-2047-encoded text
+ ++p;
+ }
+ }
+
+ while (*p == ';') {
+
+ // Skip ';'
+ ++p;
+
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ const size_t attrStart = position + (p - pstart);
+
+ while (p < pend && !(*p == ';' || *p == '=')) {
+ ++p;
+ }
+
+ if (p >= pend || *p == ';') {
+
+ // Hmmmm... we didn't found an '=' sign.
+ // This parameter may not be valid so try to advance
+ // to the next one, if there is one.
+ while (p < pend && *p != ';')
+ ++p;
+
+ } else {
+
+ // Extract the attribute name
+ size_t attrEnd = position + (p - pstart);
+
+ while (attrEnd != attrStart && parserHelpers::isSpace(buffer[attrEnd - 1])) {
+ --attrEnd;
+ }
+
+ // Skip '='
+ ++p;
+
+ // Skip white-spaces between '=' and the value
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ // Extract the value
+ string value;
+
+ // -- this is a quoted-string
+ if (*p == '"') {
+
+ // Skip '"'
+ ++p;
+
+ // Extract quoted-string
+ bool escape = false;
+ bool stop = false;
+
+ std::ostringstream ss;
+ size_t start = position + (p - pstart);
+
+ for ( ; p < pend && !stop ; ++p) {
+
+ if (escape) {
+
+ escape = false;
+ start = position + (p - pstart);
+
+ } else {
+
+ switch (*p) {
+
+ case '"': {
+
+ ss << string(
+ buffer.begin() + start,
+ buffer.begin() + position + (p - pstart)
+ );
+
+ stop = true;
+ break;
+ }
+ case '\\': {
+
+ ss << string(
+ buffer.begin() + start,
+ buffer.begin() + position + (p - pstart)
+ );
+
+ escape = true;
+ break;
+ }
+
+ }
+ }
+ }
+
+ if (!stop) {
+
+ ss << string(
+ buffer.begin() + start,
+ buffer.begin() + position + (p - pstart)
+ );
+ }
+
+ value = ss.str();
+
+ // -- the value is a simple token
+ } else {
+
+ const size_t valStart = position + (p - pstart);
+
+ while (p < pend && *p != ';') {
+ ++p;
+ }
+
+ size_t valEnd = position + (p - pstart);
+
+ while (valEnd != valStart && parserHelpers::isSpace(buffer[valEnd - 1])) {
+ --valEnd;
+ }
+
+ value = string(
+ buffer.begin() + valStart,
+ buffer.begin() + valEnd
+ );
+ }
+
+ // Don't allow ill-formed parameters
+ if (attrStart != attrEnd && value.length()) {
+
+ string name(buffer.begin() + attrStart, buffer.begin() + attrEnd);
+
+ // Check for RFC-2231 extended parameters
+ bool extended = false;
+ bool encoded = false;
+
+ if (name[name.length() - 1] == '*') {
+
+ name.erase(name.end() - 1, name.end());
+
+ extended = true;
+ encoded = true;
+ }
+
+ // Check for RFC-2231 multi-section parameters
+ const size_t star = name.find_last_of('*');
+
+ if (star != string::npos) {
+
+ bool allDigits = true;
+
+ for (size_t i = star + 1 ; allDigits && (i < name.length()) ; ++i) {
+ allDigits = parserHelpers::isDigit(name[i]);
+ }
+
+ if (allDigits) {
+ name.erase(name.begin() + star, name.end());
+ extended = true;
+ }
+
+ // NOTE: we ignore section number, and we suppose that
+ // the sequence is correct (ie. the sections appear
+ // in order: param*0, param*1...)
+ }
+
+ // Add/replace/modify the parameter
+ const std::map <string, paramInfo>::iterator it = params.find(name);
+
+ if (it != params.end()) {
+
+ paramInfo& info = (*it).second;
+
+ // An extended parameter replaces a normal one
+ if (!info.extended) {
+
+ info.extended = extended;
+ info.value.clear();
+ info.start = attrStart;
+ }
+
+ // Append a new section for a multi-section parameter
+ parameter::valueChunk chunk;
+ chunk.encoded = encoded;
+ chunk.data = value;
+
+ info.value.push_back(chunk);
+ info.end = position + (p - pstart);
+
+ } else {
+
+ parameter::valueChunk chunk;
+ chunk.encoded = encoded;
+ chunk.data = value;
+
+ paramInfo info;
+ info.extended = extended;
+ info.value.push_back(chunk);
+ info.start = attrStart;
+ info.end = position + (p - pstart);
+
+ // Insert a new parameter
+ params.insert(std::map <string, paramInfo>::value_type(name, info));
+ }
+ }
+
+ // Skip white-spaces after this parameter
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+ }
+
+ for (std::map <string, paramInfo>::const_iterator it = params.begin() ;
+ it != params.end() ; ++it) {
+
+ const paramInfo& info = (*it).second;
+
+ // Append this parameter to the list
+ shared_ptr <parameter> param = make_shared <parameter>((*it).first);
+
+ param->parse(ctx, info.value);
+ param->setParsedBounds(info.start, info.end);
+
+ appendParameter(param);
+ }
+ }
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void parameterizedHeaderField::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ size_t pos = curLinePos;
+
+ // Parent header field
+ headerField::generateImpl(ctx, os, pos, &pos);
+
+ // Parameters
+ for (std::vector <shared_ptr <parameter> >::const_iterator
+ it = m_params.begin() ; it != m_params.end() ; ++it) {
+
+ os << "; ";
+ pos += 2;
+
+ (*it)->generate(ctx, os, pos, &pos);
+ }
+
+ if (newLinePos) {
+ *newLinePos = pos;
+ }
+}
+
+
+size_t parameterizedHeaderField::getGeneratedSize(const generationContext& ctx)
+{
+ size_t size = headerField::getGeneratedSize(ctx);
+
+ for (std::vector <shared_ptr <parameter> >::const_iterator
+ it = m_params.begin() ; it != m_params.end() ; ++it) {
+
+ size += 2; // "; "
+ size += (*it)->getGeneratedSize(ctx);
+ }
+
+ return size;
+}
+
+
+void parameterizedHeaderField::copyFrom(const component& other) {
+
+ headerField::copyFrom(other);
+
+ const parameterizedHeaderField& source = dynamic_cast<const parameterizedHeaderField&>(other);
+
+ removeAllParameters();
+
+ for (std::vector <shared_ptr <parameter> >::const_iterator i = source.m_params.begin() ;
+ i != source.m_params.end() ; ++i) {
+
+ appendParameter(vmime::clone(*i));
+ }
+}
+
+
+parameterizedHeaderField& parameterizedHeaderField::operator=(const parameterizedHeaderField& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+bool parameterizedHeaderField::hasParameter(const string& paramName) const {
+
+ const string name = utility::stringUtils::toLower(paramName);
+
+ std::vector <shared_ptr <parameter> >::const_iterator pos = m_params.begin();
+ const std::vector <shared_ptr <parameter> >::const_iterator end = m_params.end();
+
+ for ( ; pos != end && utility::stringUtils::toLower((*pos)->getName()) != name ; ++pos) {}
+
+ return pos != end;
+}
+
+
+shared_ptr <parameter> parameterizedHeaderField::findParameter(const string& paramName) const {
+
+ const string name = utility::stringUtils::toLower(paramName);
+
+ // Find the first parameter that matches the specified name
+ std::vector <shared_ptr <parameter> >::const_iterator pos = m_params.begin();
+ const std::vector <shared_ptr <parameter> >::const_iterator end = m_params.end();
+
+ for ( ; pos != end && utility::stringUtils::toLower((*pos)->getName()) != name ; ++pos) {}
+
+ // No parameter with this name can be found
+ if (pos == end) {
+ return null;
+ }
+
+ // Else, return a reference to the existing parameter
+ return *pos;
+}
+
+
+shared_ptr <parameter> parameterizedHeaderField::getParameter(const string& paramName) {
+
+ const string name = utility::stringUtils::toLower(paramName);
+
+ // Find the first parameter that matches the specified name
+ std::vector <shared_ptr <parameter> >::const_iterator pos = m_params.begin();
+ const std::vector <shared_ptr <parameter> >::const_iterator end = m_params.end();
+
+ for ( ; pos != end && utility::stringUtils::toLower((*pos)->getName()) != name ; ++pos) {}
+
+ // If no parameter with this name can be found, create a new one
+ if (pos == end) {
+
+ shared_ptr <parameter> param = make_shared <parameter>(paramName);
+
+ appendParameter(param);
+
+ // Return a reference to the new parameter
+ return param;
+
+ // Else, return a reference to the existing parameter
+ } else {
+
+ return *pos;
+ }
+}
+
+
+void parameterizedHeaderField::appendParameter(const shared_ptr <parameter>& param) {
+
+ m_params.push_back(param);
+}
+
+
+void parameterizedHeaderField::insertParameterBefore(
+ const shared_ptr <parameter>& beforeParam,
+ const shared_ptr <parameter>& param
+) {
+
+ const std::vector <shared_ptr <parameter> >::iterator it =
+ std::find(m_params.begin(), m_params.end(), beforeParam);
+
+ if (it == m_params.end()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ m_params.insert(it, param);
+}
+
+
+void parameterizedHeaderField::insertParameterBefore(
+ const size_t pos,
+ const shared_ptr <parameter>& param
+) {
+
+ if (pos >= m_params.size()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ m_params.insert(m_params.begin() + pos, param);
+}
+
+
+void parameterizedHeaderField::insertParameterAfter(
+ const shared_ptr <parameter>& afterParam,
+ const shared_ptr <parameter>& param
+) {
+
+ const std::vector <shared_ptr <parameter> >::iterator it =
+ std::find(m_params.begin(), m_params.end(), afterParam);
+
+ if (it == m_params.end()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ m_params.insert(it + 1, param);
+}
+
+
+void parameterizedHeaderField::insertParameterAfter(
+ const size_t pos,
+ const shared_ptr <parameter>& param
+) {
+
+ if (pos >= m_params.size()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ m_params.insert(m_params.begin() + pos + 1, param);
+}
+
+
+void parameterizedHeaderField::removeParameter(const shared_ptr <parameter>& param) {
+
+ const std::vector <shared_ptr <parameter> >::iterator it =
+ std::find(m_params.begin(), m_params.end(), param);
+
+ if (it == m_params.end()) {
+ throw std::out_of_range("Invalid position");
+ }
+
+ m_params.erase(it);
+}
+
+
+void parameterizedHeaderField::removeParameter(const size_t pos) {
+
+ const std::vector <shared_ptr <parameter> >::iterator it = m_params.begin() + pos;
+
+ m_params.erase(it);
+}
+
+
+void parameterizedHeaderField::removeAllParameters() {
+
+ m_params.clear();
+}
+
+
+size_t parameterizedHeaderField::getParameterCount() const {
+
+ return m_params.size();
+}
+
+
+bool parameterizedHeaderField::isEmpty() const {
+
+ return m_params.empty();
+}
+
+
+const shared_ptr <parameter> parameterizedHeaderField::getParameterAt(const size_t pos) {
+
+ return m_params[pos];
+}
+
+
+const shared_ptr <const parameter> parameterizedHeaderField::getParameterAt(const size_t pos) const {
+
+ return m_params[pos];
+}
+
+
+const std::vector <shared_ptr <const parameter> > parameterizedHeaderField::getParameterList() const {
+
+ std::vector <shared_ptr <const parameter> > list;
+
+ list.reserve(m_params.size());
+
+ for (std::vector <shared_ptr <parameter> >::const_iterator it = m_params.begin() ;
+ it != m_params.end() ; ++it) {
+
+ list.push_back(*it);
+ }
+
+ return list;
+}
+
+
+const std::vector <shared_ptr <parameter> > parameterizedHeaderField::getParameterList() {
+
+ return m_params;
+}
+
+
+const std::vector <shared_ptr <component> > parameterizedHeaderField::getChildComponents() {
+
+ std::vector <shared_ptr <component> > list = headerField::getChildComponents();
+
+ for (std::vector <shared_ptr <parameter> >::iterator it = m_params.begin() ;
+ it != m_params.end() ; ++it) {
+
+ list.push_back(*it);
+ }
+
+ return list;
+}
+
+
+} // vmime
+
diff --git a/vmime-master/src/vmime/parameterizedHeaderField.hpp b/vmime-master/src/vmime/parameterizedHeaderField.hpp
new file mode 100644
index 0000000..d884f1f
--- /dev/null
+++ b/vmime-master/src/vmime/parameterizedHeaderField.hpp
@@ -0,0 +1,222 @@
+//
+// 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_PARAMETERIZEDHEADERFIELD_HPP_INCLUDED
+#define VMIME_PARAMETERIZEDHEADERFIELD_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/headerFieldFactory.hpp"
+#include "vmime/parameter.hpp"
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+
+
+/** A header field that can also contain parameters (name=value pairs).
+ * Parameters can be created using vmime::parameterFactory.
+ */
+class VMIME_EXPORT parameterizedHeaderField : public headerField {
+
+ friend class headerFieldFactory;
+
+protected:
+
+ // Protected constructor to prevent the user from creating
+ // new objects without using 'headerFieldFactory'
+ parameterizedHeaderField();
+
+public:
+
+ ~parameterizedHeaderField();
+
+ void copyFrom(const component& other);
+ parameterizedHeaderField& operator=(const parameterizedHeaderField& other);
+
+ /** Checks whether (at least) one parameter with this name exists.
+ * Parameter name is case-insensitive.
+ *
+ * @param paramName parameter name
+ * @return true if at least one parameter with the specified name
+ * exists, or false otherwise
+ */
+ bool hasParameter(const string& paramName) const;
+
+ /** Find the first parameter that matches the specified name. Parameter name
+ * is case-insensitive. If no parameter is found, NULL is returned.
+ *
+ * @param paramName parameter name
+ * @return first parameter with the specified name, or NULL if
+ * no parameter with this name exists
+ */
+ shared_ptr <parameter> findParameter(const string& paramName) const;
+
+ /** Find the first parameter that matches the specified name.
+ * Parameter name is case-insensitive.
+ * If no parameter is found, one will be created and inserted into
+ * the parameter list.
+ *
+ * @param paramName parameter name
+ * @return first parameter with the specified name or a new field
+ * if no parameter is found
+ */
+ shared_ptr <parameter> getParameter(const string& paramName);
+
+ /** Add a parameter at the end of the list.
+ *
+ * @param param parameter to append
+ */
+ void appendParameter(const shared_ptr <parameter>& param);
+
+ /** Insert a new parameter before the specified parameter.
+ *
+ * @param beforeParam parameter before which the new parameter will be inserted
+ * @param param parameter to insert
+ * @throw std::out_of_range if the parameter is not in the list
+ */
+ void insertParameterBefore(
+ const shared_ptr <parameter>& beforeParam,
+ const shared_ptr <parameter>& param
+ );
+
+ /** Insert a new parameter before the specified position.
+ *
+ * @param pos position at which to insert the new parameter (0 to insert at
+ * the beginning of the list)
+ * @param param parameter to insert
+ * @throw std::out_of_range if the position is out of range
+ */
+ void insertParameterBefore(
+ const size_t pos,
+ const shared_ptr <parameter>& param
+ );
+
+ /** Insert a new parameter after the specified parameter.
+ *
+ * @param afterParam parameter after which the new parameter will be inserted
+ * @param param parameter to insert
+ * @throw std::out_of_range if the parameter is not in the list
+ */
+ void insertParameterAfter(
+ const shared_ptr <parameter>& afterParam,
+ const shared_ptr <parameter>& param
+ );
+
+ /** Insert a new parameter after the specified position.
+ *
+ * @param pos position of the parameter before the new parameter
+ * @param param parameter to insert
+ * @throw std::out_of_range if the position is out of range
+ */
+ void insertParameterAfter(
+ const size_t pos,
+ const shared_ptr <parameter>& param
+ );
+
+ /** Remove the specified parameter from the list.
+ *
+ * @param param parameter to remove
+ * @throw std::out_of_range if the parameter is not in the list
+ */
+ void removeParameter(const shared_ptr <parameter>& param);
+
+ /** Remove the parameter at the specified position.
+ *
+ * @param pos position of the parameter to remove
+ */
+ void removeParameter(const size_t pos);
+
+ /** Remove all parameters from the list.
+ */
+ void removeAllParameters();
+
+ /** Return the number of parameters in the list.
+ *
+ * @return number of parameters
+ */
+ size_t getParameterCount() const;
+
+ /** Tests whether the list of parameters is empty.
+ *
+ * @return true if there is no parameter, false otherwise
+ */
+ bool isEmpty() const;
+
+ /** Return the parameter at the specified position.
+ *
+ * @param pos position
+ * @return parameter at position 'pos'
+ */
+ const shared_ptr <parameter> getParameterAt(const size_t pos);
+
+ /** Return the parameter at the specified position.
+ *
+ * @param pos position
+ * @return parameter at position 'pos'
+ */
+ const shared_ptr <const parameter> getParameterAt(const size_t pos) const;
+
+ /** Return the parameter list.
+ *
+ * @return list of parameters
+ */
+ const std::vector <shared_ptr <const parameter> > getParameterList() const;
+
+ /** Return the parameter list.
+ *
+ * @return list of parameters
+ */
+ const std::vector <shared_ptr <parameter> > getParameterList();
+
+ size_t getGeneratedSize(const generationContext& ctx);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+private:
+
+ std::vector <shared_ptr <parameter> > m_params;
+
+protected:
+
+ void parseImpl(
+ const 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;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_PARAMETERIZEDHEADERFIELD_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/parsedMessageAttachment.cpp b/vmime-master/src/vmime/parsedMessageAttachment.cpp
new file mode 100644
index 0000000..d50862b
--- /dev/null
+++ b/vmime-master/src/vmime/parsedMessageAttachment.cpp
@@ -0,0 +1,114 @@
+//
+// 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.
+//
+
+#include "vmime/parsedMessageAttachment.hpp"
+
+#include "vmime/stringContentHandler.hpp"
+#include "vmime/contentDisposition.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+
+namespace vmime {
+
+
+parsedMessageAttachment::parsedMessageAttachment(const shared_ptr <message>& msg)
+ : m_msg(msg) {
+
+}
+
+
+const mediaType parsedMessageAttachment::getType() const {
+
+ return mediaType(mediaTypes::MESSAGE, mediaTypes::MESSAGE_RFC822);
+}
+
+
+const text parsedMessageAttachment::getDescription() const {
+
+ return text();
+}
+
+
+const word parsedMessageAttachment::getName() const {
+
+ return word();
+}
+
+
+const shared_ptr <const contentHandler> parsedMessageAttachment::getData() const {
+
+ if (!m_data) {
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter os(oss);
+
+ m_msg->generate(os);
+
+ m_data = make_shared <stringContentHandler>(oss.str());
+ }
+
+ return m_data;
+}
+
+
+const encoding parsedMessageAttachment::getEncoding() const {
+
+ return encoding(encodingTypes::EIGHT_BIT); // not important
+}
+
+
+shared_ptr <const object> parsedMessageAttachment::getPart() const {
+
+ return null;
+}
+
+
+shared_ptr <const header> parsedMessageAttachment::getHeader() const {
+
+ return null;
+}
+
+
+shared_ptr <message> parsedMessageAttachment::getMessage() const {
+
+ return m_msg;
+}
+
+
+void parsedMessageAttachment::generateIn(const shared_ptr <bodyPart>& parent) const {
+
+ // Create and append a new part for this attachment
+ shared_ptr <bodyPart> part = make_shared <bodyPart>();
+ parent->getBody()->appendPart(part);
+
+ // Set header fields
+ part->getHeader()->ContentType()->setValue(getType());
+ part->getHeader()->ContentDisposition()->setValue(contentDisposition(contentDispositionTypes::ATTACHMENT));
+
+ // Set contents
+ part->getBody()->setContents(getData());
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/parsedMessageAttachment.hpp b/vmime-master/src/vmime/parsedMessageAttachment.hpp
new file mode 100644
index 0000000..2a5358e
--- /dev/null
+++ b/vmime-master/src/vmime/parsedMessageAttachment.hpp
@@ -0,0 +1,76 @@
+//
+// 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_PARSEDMESSAGEATTACHMENT_HPP_INCLUDED
+#define VMIME_PARSEDMESSAGEATTACHMENT_HPP_INCLUDED
+
+
+#ifndef VMIME_BUILDING_DOC // implementation detail
+
+
+#include "vmime/messageAttachment.hpp"
+
+
+namespace vmime {
+
+
+/** A message attachment that can be generated into a message.
+ */
+class VMIME_EXPORT parsedMessageAttachment : public messageAttachment {
+
+public:
+
+ parsedMessageAttachment(const shared_ptr <message>& msg);
+
+ const mediaType getType() const;
+ const text getDescription() const;
+ const word getName() const;
+
+ const shared_ptr <const contentHandler> getData() const;
+
+ const encoding getEncoding() const;
+
+ shared_ptr <const object> getPart() const;
+
+ shared_ptr <const header> getHeader() const;
+
+ shared_ptr <message> getMessage() const;
+
+protected:
+
+ void generateIn(const shared_ptr <bodyPart>& parent) const;
+
+private:
+
+ shared_ptr <message> m_msg;
+ mutable shared_ptr <contentHandler> m_data;
+};
+
+
+} // vmime
+
+
+#endif // !VMIME_BUILDING_DOC
+
+
+#endif // VMIME_PARSEDMESSAGEATTACHMENT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/parserHelpers.hpp b/vmime-master/src/vmime/parserHelpers.hpp
new file mode 100644
index 0000000..cba43c6
--- /dev/null
+++ b/vmime-master/src/vmime/parserHelpers.hpp
@@ -0,0 +1,140 @@
+//
+// 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_PARSERHELPERS_HPP_INCLUDED
+#define VMIME_PARSERHELPERS_HPP_INCLUDED
+
+
+#include "vmime/types.hpp"
+#include "vmime/utility/stringUtils.hpp"
+
+#include <algorithm>
+
+
+
+namespace vmime {
+
+
+class parserHelpers {
+
+public:
+
+ static bool isSpace(const char_t c) {
+
+ return c == ' ' || c == '\t' || c == '\n' || c == '\r';
+ }
+
+ static bool isSpaceOrTab(const char_t c) {
+
+ return c == ' ' || c == '\t';
+ }
+
+ static bool isDigit(const char_t c) {
+
+ return c >= '0' && c <= '9';
+ }
+
+ static bool isAlpha(const char_t c) {
+
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+ }
+
+
+ static char_t toLower(const char_t c) {
+
+ if (c >= 'A' && c <= 'Z') {
+ return ('a' + (c - 'A'));
+ } else {
+ return c;
+ }
+ }
+
+
+ // Checks whether a character is in the 7-bit US-ASCII charset
+
+ static bool isAscii(const char_t c) {
+
+ const unsigned int x = static_cast <unsigned int>(c);
+ return x <= 127;
+ }
+
+
+ // Checks whether a character has a visual representation
+
+ static bool isPrint(const char_t c) {
+
+ const unsigned int x = static_cast <unsigned int>(c);
+ return x >= 0x20 && x <= 0x7E;
+ }
+
+
+ /** Finds the next EOL sequence in the specified buffer.
+ * An EOL sequence may be a CR+LF sequence, or a LF sequence.
+ *
+ * @param buffer search buffer
+ * @param currentPos start searching from this position
+ * @param end stop searching at this position
+ * @param eol will receive the position after the EOL sequence
+ * @return true if an EOL sequence has been found, or false if
+ * no EOL sequence was found before the end of the buffer
+ */
+ static bool findEOL(
+ const string& buffer,
+ const size_t currentPos,
+ const size_t end,
+ size_t* eol
+ ) {
+
+ size_t pos = currentPos;
+
+ if (pos == end) {
+ return false;
+ }
+
+ while (pos < end) {
+
+ if (buffer[pos] == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') {
+
+ *eol = pos + 2;
+ return true;
+
+ } else if (buffer[pos] == '\n') {
+
+ *eol = pos + 1;
+ return true;
+ }
+
+ ++pos;
+ }
+
+ *eol = end;
+
+ return true;
+ }
+};
+
+
+} // vmime
+
+
+#endif // VMIME_PARSERHELPERS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/parsingContext.cpp b/vmime-master/src/vmime/parsingContext.cpp
new file mode 100644
index 0000000..0975e3d
--- /dev/null
+++ b/vmime-master/src/vmime/parsingContext.cpp
@@ -0,0 +1,64 @@
+//
+// 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.
+//
+
+#include "vmime/parsingContext.hpp"
+
+
+namespace vmime {
+
+
+parsingContext::parsingContext()
+ : m_headerParseErrorRecovery(vmime::headerParseRecoveryMethod::SKIP_LINE) {
+
+}
+
+
+parsingContext::parsingContext(const parsingContext& ctx)
+ : context(ctx),
+ m_headerParseErrorRecovery(vmime::headerParseRecoveryMethod::SKIP_LINE) {
+
+}
+
+
+parsingContext& parsingContext::getDefaultContext() {
+
+ static parsingContext ctx;
+ return ctx;
+}
+
+
+headerParseRecoveryMethod::headerLineError parsingContext::getHeaderParseErrorRecoveryMethod() const {
+
+ return m_headerParseErrorRecovery;
+}
+
+
+void parsingContext::setHeaderParseErrorRecoveryMethod(
+ const headerParseRecoveryMethod::headerLineError recoveryMethod
+) {
+
+ m_headerParseErrorRecovery = recoveryMethod;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/parsingContext.hpp b/vmime-master/src/vmime/parsingContext.hpp
new file mode 100644
index 0000000..d13d94e
--- /dev/null
+++ b/vmime-master/src/vmime/parsingContext.hpp
@@ -0,0 +1,82 @@
+//
+// 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_PARSINGCONTEXT_HPP_INCLUDED
+#define VMIME_PARSINGCONTEXT_HPP_INCLUDED
+
+
+#include "vmime/context.hpp"
+
+
+namespace vmime {
+
+/** Provides runtime configurable options to provide flexibility in header parsing
+ */
+struct headerParseRecoveryMethod {
+
+ enum headerLineError {
+ SKIP_LINE = 0,
+ /* APPEND_TO_PREVIOUS_LINE = 1, */
+ ASSUME_END_OF_HEADERS = 2
+ };
+};
+
+/** Holds configuration parameters used for parsing messages.
+ */
+class VMIME_EXPORT parsingContext : public context {
+
+public:
+
+ parsingContext();
+ parsingContext(const parsingContext& ctx);
+
+ /** Returns the default context used for parsing messages.
+ *
+ * @return a reference to the default parsing context
+ */
+ static parsingContext& getDefaultContext();
+
+ /** Sets the recovery method when parsing a header encounters an error
+ * such as a failed fold or missing new line.
+ *
+ * @param recoveryMethod is one of vmime::headerParseRecoveryMethod.
+ * Defaults to vmime::headerParseRecoveryMethod::SKIP_LINE.
+ */
+ void setHeaderParseErrorRecoveryMethod(const headerParseRecoveryMethod::headerLineError recoveryMethod);
+
+ /** Return the recovery method when parsing a header encounters an error.
+ *
+ * @return is an enum from vmime::headerParseRecoveryMethod
+ */
+ headerParseRecoveryMethod::headerLineError getHeaderParseErrorRecoveryMethod() const;
+
+protected:
+
+ headerParseRecoveryMethod::headerLineError m_headerParseErrorRecovery;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_PARSINGCONTEXT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/path.cpp b/vmime-master/src/vmime/path.cpp
new file mode 100644
index 0000000..f57d128
--- /dev/null
+++ b/vmime-master/src/vmime/path.cpp
@@ -0,0 +1,206 @@
+//
+// 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.
+//
+
+#include "vmime/path.hpp"
+#include "vmime/parserHelpers.hpp"
+
+
+namespace vmime {
+
+
+path::path() {
+
+}
+
+
+path::path(const string& localPart, const string& domain)
+ : m_localPart(localPart),
+ m_domain(domain) {
+
+}
+
+
+path::path(const path& p)
+ : headerFieldValue(),
+ m_localPart(p.m_localPart),
+ m_domain(p.m_domain) {
+
+}
+
+
+const string& path::getLocalPart() const {
+
+ return m_localPart;
+}
+
+
+void path::setLocalPart(const string& localPart) {
+
+ m_localPart = localPart;
+}
+
+
+const string& path::getDomain() const {
+
+ return m_domain;
+}
+
+
+void path::setDomain(const string& domain) {
+
+ m_domain = domain;
+}
+
+
+bool path::operator==(const path& p) const {
+
+ return m_localPart == p.m_localPart &&
+ m_domain == p.m_domain;
+}
+
+
+bool path::operator!=(const path& p) const {
+
+ return m_localPart != p.m_localPart ||
+ m_domain != p.m_domain;
+}
+
+
+void path::copyFrom(const component& other) {
+
+ const path& p = dynamic_cast <const path&>(other);
+
+ m_localPart = p.m_localPart;
+ m_domain = p.m_domain;
+}
+
+
+shared_ptr <component> path::clone() const {
+
+ return make_shared <path>(*this);
+}
+
+
+path& path::operator=(const path& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+const std::vector <shared_ptr <component> > path::getChildComponents() {
+
+ return std::vector <shared_ptr <component> >();
+}
+
+
+void path::parseImpl(
+ const parsingContext& /* ctx */,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ size_t pos = position;
+
+ while (pos < end && parserHelpers::isSpace(buffer[pos])) {
+ ++pos;
+ }
+
+ string addrSpec;
+
+ if (pos < end && buffer[pos] == '<') {
+
+ // Skip '<'
+ ++pos;
+
+ while (pos < end && parserHelpers::isSpace(buffer[pos])) {
+ ++pos;
+ }
+
+ const size_t addrStart = pos;
+
+ while (pos < end && buffer[pos] != '>') {
+ ++pos;
+ }
+
+ size_t addrEnd = pos;
+
+ while (addrEnd > addrStart && parserHelpers::isSpace(buffer[addrEnd - 1])) {
+ addrEnd--;
+ }
+
+ addrSpec = string(buffer.begin() + addrStart, buffer.begin() + addrEnd);
+
+ } else {
+
+ addrSpec = string(buffer.begin() + position, buffer.begin() + end);
+ }
+
+ const size_t at = addrSpec.find_first_of('@');
+
+ if (at != string::npos) {
+
+ m_localPart = string(addrSpec.begin(), addrSpec.begin() + at);
+ m_domain = string(addrSpec.begin() + at + 1, addrSpec.end());
+
+ } else {
+
+ m_localPart.clear();
+ m_domain = addrSpec;
+ }
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void path::generateImpl(
+ const generationContext& /* ctx */,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ if (m_localPart.empty() && m_domain.empty()) {
+
+ os << "<>";
+
+ if (newLinePos) {
+ *newLinePos = curLinePos + 2;
+ }
+
+ } else {
+
+ os << "<" << m_localPart << "@" << m_domain << ">";
+
+ if (newLinePos) {
+ *newLinePos = curLinePos + m_localPart.length() + m_domain.length() + 3;
+ }
+ }
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/path.hpp b/vmime-master/src/vmime/path.hpp
new file mode 100644
index 0000000..d63ee67
--- /dev/null
+++ b/vmime-master/src/vmime/path.hpp
@@ -0,0 +1,106 @@
+//
+// 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_PATH_HPP_INCLUDED
+#define VMIME_PATH_HPP_INCLUDED
+
+
+#include "vmime/headerFieldValue.hpp"
+
+
+namespace vmime {
+
+
+/** A path: a local part + '@' + a domain.
+ */
+class VMIME_EXPORT path : public headerFieldValue {
+
+public:
+
+ path();
+ path(const string& localPart, const string& domain);
+ path(const path& p);
+
+ /** Return the local part of the address.
+ *
+ * @return local part of the address
+ */
+ const string& getLocalPart() const;
+
+ /** Set the local part of the address.
+ *
+ * @param localPart local part of the address
+ */
+ void setLocalPart(const string& localPart);
+
+ /** Return the domain of the address.
+ *
+ * @return domain of the address
+ */
+ const string& getDomain() const;
+
+ /** Set the domain of the address.
+ *
+ * @param domain domain of the address
+ */
+ void setDomain(const string& domain);
+
+ // Comparison
+ bool operator==(const path& p) const;
+ bool operator!=(const path& p) const;
+
+ // Assignment
+ void copyFrom(const component& other);
+ shared_ptr <component> clone() const;
+ path& operator=(const path& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+protected:
+
+ string m_localPart;
+ string m_domain;
+
+
+ // Component parsing & assembling
+ void parseImpl(
+ const 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;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_PATH_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/plainTextPart.cpp b/vmime-master/src/vmime/plainTextPart.cpp
new file mode 100644
index 0000000..859a67c
--- /dev/null
+++ b/vmime-master/src/vmime/plainTextPart.cpp
@@ -0,0 +1,121 @@
+//
+// 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.
+//
+
+#include "vmime/plainTextPart.hpp"
+#include "vmime/header.hpp"
+#include "vmime/exception.hpp"
+
+#include "vmime/contentTypeField.hpp"
+
+#include "vmime/emptyContentHandler.hpp"
+
+
+namespace vmime {
+
+
+plainTextPart::plainTextPart()
+ : m_text(make_shared <emptyContentHandler>()) {
+
+}
+
+
+plainTextPart::~plainTextPart() {
+
+}
+
+
+const mediaType plainTextPart::getType() const {
+
+ return mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN);
+}
+
+
+size_t plainTextPart::getPartCount() const {
+
+ return 1;
+}
+
+
+void plainTextPart::generateIn(
+ const shared_ptr <bodyPart>& /* message */,
+ const shared_ptr <bodyPart>& parent
+) const {
+
+ // Create a new part
+ shared_ptr <bodyPart> part = make_shared <bodyPart>();
+ parent->getBody()->appendPart(part);
+
+ // Set contents
+ part->getBody()->setContents(
+ m_text,
+ mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN),
+ m_charset,
+ encoding::decide(m_text, m_charset, encoding::USAGE_TEXT)
+ );
+}
+
+
+void plainTextPart::parse(
+ const shared_ptr <const bodyPart>& /* message */,
+ const shared_ptr <const bodyPart>& /* parent */,
+ const shared_ptr <const bodyPart>& textPart
+) {
+
+ m_text = vmime::clone(textPart->getBody()->getContents());
+
+ shared_ptr <const contentTypeField> ctf =
+ textPart->getHeader()->findField <contentTypeField>(fields::CONTENT_TYPE);
+
+ if (ctf && ctf->hasCharset()) {
+ m_charset = ctf->getCharset();
+ } else {
+ m_charset = charset();
+ }
+}
+
+
+const charset& plainTextPart::getCharset() const {
+
+ return m_charset;
+}
+
+
+void plainTextPart::setCharset(const charset& ch) {
+
+ m_charset = ch;
+}
+
+
+const shared_ptr <const contentHandler> plainTextPart::getText() const{
+
+ return m_text;
+}
+
+
+void plainTextPart::setText(const shared_ptr <contentHandler>& text) {
+
+ m_text = vmime::clone(text);
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/plainTextPart.hpp b/vmime-master/src/vmime/plainTextPart.hpp
new file mode 100644
index 0000000..8a0249e
--- /dev/null
+++ b/vmime-master/src/vmime/plainTextPart.hpp
@@ -0,0 +1,74 @@
+//
+// 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_PLAINTEXTPART_HPP_INCLUDED
+#define VMIME_PLAINTEXTPART_HPP_INCLUDED
+
+
+#include "vmime/textPart.hpp"
+
+
+namespace vmime {
+
+
+/** Text part of type 'text/plain'.
+ */
+class VMIME_EXPORT plainTextPart : public textPart {
+
+public:
+
+ plainTextPart();
+ ~plainTextPart();
+
+ const mediaType getType() const;
+
+ const charset& getCharset() const;
+ void setCharset(const charset& ch);
+
+ const shared_ptr <const contentHandler> getText() const;
+ void setText(const shared_ptr <contentHandler>& text);
+
+ size_t getPartCount() const;
+
+ void generateIn(
+ const shared_ptr <bodyPart>& message,
+ const shared_ptr <bodyPart>& parent
+ ) const;
+
+ void parse(
+ const shared_ptr <const bodyPart>& message,
+ const shared_ptr <const bodyPart>& parent,
+ const shared_ptr <const bodyPart>& textPart
+ );
+
+private:
+
+ shared_ptr <contentHandler> m_text;
+ charset m_charset;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_PLAINTEXTPART_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platform.cpp b/vmime-master/src/vmime/platform.cpp
new file mode 100644
index 0000000..f2f1e97
--- /dev/null
+++ b/vmime-master/src/vmime/platform.cpp
@@ -0,0 +1,77 @@
+//
+// 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.
+//
+
+#include "vmime/platform.hpp"
+#include "vmime/config.hpp"
+
+#include "vmime/platforms/posix/posixHandler.hpp"
+#include "vmime/platforms/windows/windowsHandler.hpp"
+
+
+namespace vmime {
+
+
+shared_ptr <platform::handler> platform::sm_handler;
+
+
+platform::handler::~handler() {
+
+}
+
+
+// static
+shared_ptr <platform::handler> platform::getDefaultHandler() {
+
+#if VMIME_PLATFORM_IS_WINDOWS
+ return make_shared <platforms::windows::windowsHandler>();
+#elif VMIME_PLATFORM_IS_POSIX
+ return make_shared <platforms::posix::posixHandler>();
+#else
+ return null;
+#endif
+
+}
+
+
+// static
+shared_ptr <platform::handler> platform::getHandler() {
+
+ // If a custom platform handler is installed, return it
+ if (sm_handler) {
+ return sm_handler;
+ }
+
+ // Else, use the default handler for this platform
+ shared_ptr <handler> defaultHandler = getDefaultHandler();
+
+ if (defaultHandler) {
+ sm_handler = defaultHandler;
+ return sm_handler;
+ }
+
+ // Oops... no platform handler!
+ throw exceptions::no_platform_handler();
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/platform.hpp b/vmime-master/src/vmime/platform.hpp
new file mode 100644
index 0000000..03a7b23
--- /dev/null
+++ b/vmime-master/src/vmime/platform.hpp
@@ -0,0 +1,158 @@
+//
+// 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_PLATFORM_HPP_INCLUDED
+#define VMIME_PLATFORM_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+#include "vmime/dateTime.hpp"
+#include "vmime/exception.hpp"
+#include "vmime/charset.hpp"
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ #include "vmime/net/socket.hpp"
+ #include "vmime/net/timeoutHandler.hpp"
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ #include "vmime/utility/file.hpp"
+ #include "vmime/utility/childProcess.hpp"
+#endif
+
+#include "vmime/utility/sync/criticalSection.hpp"
+
+
+namespace vmime {
+
+
+/** Allow setting or getting the current platform handler.
+ */
+class VMIME_EXPORT platform {
+
+public:
+
+ /** Takes care of all platform-dependent operations. It offers an interface to
+ * access platform-dependent objects: sockets, date/time, file system, etc.
+ */
+ class VMIME_EXPORT handler : public object {
+
+ public:
+
+ virtual ~handler();
+
+ /** Return the current UNIX time (Epoch time): the number of
+ * seconds elapsed since Jan, 1st 1970 00:00.
+ *
+ * @return UNIX Epoch time
+ */
+ virtual unsigned long getUnixTime() const = 0;
+
+ /** Return the current date and time, in the local time zone.
+ *
+ * @return current date and time
+ */
+ virtual const datetime getCurrentLocalTime() const = 0;
+
+ /** Return the host name of the system.
+ * Used when generating message ids.
+ *
+ * @return host name
+ */
+ virtual const string getHostName() const = 0;
+
+ /** Return the current process identifier.
+ * Used when generating random strings (part boundaries or message ids).
+ *
+ * @return current process id
+ */
+ virtual unsigned int getProcessId() const = 0;
+
+ /** Return an unique identifier for the current thread.
+ * Used for multi-threading synchronization.
+ *
+ * @return current thread id
+ */
+ virtual unsigned int getThreadId() const = 0;
+
+ /** Return the charset used on the system.
+ *
+ * @return local charset
+ */
+ virtual const charset getLocalCharset() const = 0;
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ /** Return a pointer to the default socket factory for
+ * this platform.
+ *
+ * @return socket factory
+ */
+ virtual shared_ptr <net::socketFactory> getSocketFactory() = 0;
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ /** Return a pointer to a factory that creates file-system objects.
+ *
+ * @return file-system factory
+ */
+ virtual shared_ptr <utility::fileSystemFactory> getFileSystemFactory() = 0;
+
+ /** Return a pointer to a factory that creates child process objects,
+ * which are used to spawn processes (run executable files).
+ *
+ * @return child process factory
+ */
+ virtual shared_ptr <utility::childProcessFactory> getChildProcessFactory() = 0;
+#endif
+
+ /** Fills a buffer with cryptographically random bytes.
+ *
+ * @param buffer buffer to fill in with random bytes
+ * @param count number of random bytes to write in buffer
+ */
+ virtual void generateRandomBytes(unsigned char* buffer, const unsigned int count) = 0;
+
+ /** Creates and initializes a critical section.
+ */
+ virtual shared_ptr <utility::sync::criticalSection> createCriticalSection() = 0;
+ };
+
+
+ template <class TYPE>
+ static void setHandler() {
+ sm_handler = vmime::make_shared <TYPE>();
+ }
+
+ static shared_ptr <handler> getDefaultHandler();
+ static shared_ptr <handler> getHandler();
+
+private:
+
+ static shared_ptr <handler> sm_handler;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_PLATFORM_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/posix/posixChildProcess.cpp b/vmime-master/src/vmime/platforms/posix/posixChildProcess.cpp
new file mode 100644
index 0000000..4a9fef3
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixChildProcess.cpp
@@ -0,0 +1,410 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/platforms/posix/posixChildProcess.hpp"
+#include "vmime/platforms/posix/posixFile.hpp"
+
+#include "vmime/exception.hpp"
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+// posixChildProcessFactory
+
+shared_ptr <utility::childProcess> posixChildProcessFactory::create(const utility::file::path& path) const {
+
+ return make_shared <posixChildProcess>(path);
+}
+
+
+
+#ifndef VMIME_BUILDING_DOC
+
+
+// getPosixSignalMessage
+// Returns the name of a POSIX signal.
+
+static const string getPosixSignalMessage(const int num) {
+
+ switch (num) {
+ case SIGHUP: return "SIGHUP";
+ case SIGINT: return "SIGINT";
+ case SIGQUIT: return "SIGQUIT";
+ case SIGILL: return "SIGILL";
+ case SIGABRT: return "SIGABRT";
+ case SIGFPE: return "SIGFPE";
+ case SIGKILL: return "SIGKILL";
+ case SIGSEGV: return "SIGSEGV";
+ case SIGPIPE: return "SIGPIPE";
+ case SIGALRM: return "SIGALRM";
+ case SIGTERM: return "SIGTERM";
+ case SIGUSR1: return "SIGUSR1";
+ case SIGUSR2: return "SIGUSR2";
+ case SIGCHLD: return "SIGCHLD";
+ case SIGCONT: return "SIGCONT";
+ case SIGSTOP: return "SIGSTOP";
+ case SIGTSTP: return "SIGTSTP";
+ case SIGTTIN: return "SIGTTIN";
+ case SIGTTOU: return "SIGTTOU";
+ }
+
+ return "(unknown)";
+}
+
+
+// getPosixErrorMessage
+// Returns a message corresponding to an error code.
+
+static const string getPosixErrorMessage(const int num) {
+
+#ifdef strerror_r
+ char res[256];
+ res[0] = '\0';
+
+ strerror_r(num, res, sizeof(res));
+
+ return string(res);
+#else
+ return string(strerror(num));
+#endif
+
+}
+
+
+// Output stream adapter for POSIX pipe
+
+class outputStreamPosixPipeAdapter : public utility::outputStream {
+
+public:
+
+ outputStreamPosixPipeAdapter(const int desc)
+ : m_desc(desc) {
+
+ }
+
+ void flush() {
+
+ ::fsync(m_desc);
+ }
+
+protected:
+
+ void writeImpl(const byte_t* const data, const size_t count) {
+
+ if (::write(m_desc, data, count) == -1) {
+ const string errorMsg = getPosixErrorMessage(errno);
+ throw exceptions::system_error(errorMsg);
+ }
+ }
+
+private:
+
+ const int m_desc;
+};
+
+
+// Input stream adapter for POSIX pipe
+
+class inputStreamPosixPipeAdapter : public utility::inputStream {
+
+public:
+
+ inputStreamPosixPipeAdapter(const int desc)
+ : m_desc(desc) {
+ }
+
+ bool eof() const {
+
+ return m_eof;
+ }
+
+ void reset() {
+
+ // Do nothing: unsupported
+ }
+
+ size_t skip(const size_t count) {
+
+ // TODO: not tested
+ byte_t buffer[4096];
+
+ ssize_t bytesSkipped = 0;
+ ssize_t bytesRead = 0;
+
+ while ((bytesRead = ::read(m_desc, buffer,
+ std::min(sizeof(buffer), count - bytesSkipped))) != 0) {
+
+ if (bytesRead == -1) {
+ const string errorMsg = getPosixErrorMessage(errno);
+ throw exceptions::system_error(errorMsg);
+ }
+
+ bytesSkipped += bytesRead;
+ }
+
+ return static_cast <size_t>(bytesSkipped);
+ }
+
+ size_t read(byte_t* const data, const size_t count) {
+
+ ssize_t bytesRead = 0;
+
+ if ((bytesRead = ::read(m_desc, data, count)) == -1) {
+ const string errorMsg = getPosixErrorMessage(errno);
+ throw exceptions::system_error(errorMsg);
+ }
+
+ m_eof = (bytesRead == 0);
+
+ return static_cast <size_t>(bytesRead);
+ }
+
+private:
+
+ const int m_desc;
+
+ bool m_eof;
+};
+
+
+#endif // VMIME_BUILDING_DOC
+
+
+
+// posixChildProcess
+
+posixChildProcess::posixChildProcess(const utility::file::path& path)
+ : m_processPath(path),
+ m_started(false),
+ m_stdIn(null),
+ m_stdOut(null),
+ m_pid(0),
+ m_argArray(NULL) {
+
+ m_pipe[0] = 0;
+ m_pipe[1] = 0;
+
+ sigemptyset(&m_oldProcMask);
+}
+
+
+posixChildProcess::~posixChildProcess() {
+
+ if (m_started) {
+ sigprocmask(SIG_SETMASK, &m_oldProcMask, NULL);
+ }
+
+ if (m_pipe[0] != 0) {
+ close(m_pipe[0]);
+ }
+
+ if (m_pipe[1] != 0) {
+ close(m_pipe[1]);
+ }
+
+ delete [] m_argArray;
+}
+
+
+// The following code is highly inspired and adapted from the 'sendmail'
+// provider module in Evolution data server code.
+//
+// Original authors: Dan Winship <danw@ximian.com>
+// Copyright 2000 Ximian, Inc. (www.ximian.com)
+
+void posixChildProcess::start(const std::vector <string>& args, const int flags) {
+
+ if (m_started) {
+ return;
+ }
+
+ // Construct C-style argument array
+ const char** argv = new const char*[args.size() + 2];
+
+ m_argVector = args; // for c_str() pointer to remain valid
+ m_argArray = argv; // to free later
+
+ argv[0] = m_processPath.getLastComponent().getBuffer().c_str();
+ argv[args.size() + 1] = NULL;
+
+ for (unsigned int i = 0 ; i < m_argVector.size() ; ++i) {
+ argv[i + 1] = m_argVector[i].c_str();
+ }
+
+ // Create a pipe to communicate with the child process
+ int fd[2];
+
+ if (pipe(fd) == -1) {
+ throw exceptions::system_error(getPosixErrorMessage(errno));
+ }
+
+ m_pipe[0] = fd[0];
+ m_pipe[1] = fd[1];
+
+ // Block SIGCHLD so the calling application doesn't notice
+ // process exiting before we do
+ sigset_t mask;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &mask, &m_oldProcMask);
+
+ // Spawn process
+ const pid_t pid = fork();
+
+ if (pid == -1) { // error
+
+ const string errorMsg = getPosixErrorMessage(errno);
+
+ sigprocmask(SIG_SETMASK, &m_oldProcMask, NULL);
+
+ close(fd[0]);
+ close(fd[1]);
+
+ throw exceptions::system_error(errorMsg);
+
+ } else if (pid == 0) { // child process
+
+ if (flags & FLAG_REDIRECT_STDIN) {
+ dup2(fd[0], STDIN_FILENO);
+ } else {
+ close(fd[0]);
+ }
+
+ if (flags & FLAG_REDIRECT_STDOUT) {
+ dup2(fd[1], STDOUT_FILENO);
+ } else {
+ close(fd[1]);
+ }
+
+ posixFileSystemFactory* pfsf = new posixFileSystemFactory();
+
+ const string path = pfsf->pathToString(m_processPath);
+
+ delete pfsf;
+
+ execv(path.c_str(), const_cast <char**>(argv));
+ _exit(255);
+ }
+
+ if (flags & FLAG_REDIRECT_STDIN) {
+
+ m_stdIn = make_shared <outputStreamPosixPipeAdapter>(m_pipe[1]);
+
+ } else {
+
+ close(m_pipe[1]);
+ m_pipe[1] = 0;
+ }
+
+ if (flags & FLAG_REDIRECT_STDOUT) {
+
+ m_stdOut = make_shared <inputStreamPosixPipeAdapter>(m_pipe[0]);
+
+ } else {
+
+ close(m_pipe[0]);
+ m_pipe[0] = 0;
+ }
+
+ m_pid = pid;
+ m_started = true;
+}
+
+
+shared_ptr <utility::outputStream> posixChildProcess::getStdIn() {
+
+ return m_stdIn;
+}
+
+
+shared_ptr <utility::inputStream> posixChildProcess::getStdOut() {
+
+ return m_stdOut;
+}
+
+
+void posixChildProcess::waitForFinish() {
+
+ // Close stdin pipe
+ if (m_pipe[1] != 0) {
+ close(m_pipe[1]);
+ m_pipe[1] = 0;
+ }
+
+ int wstat;
+
+ while (waitpid(m_pid, &wstat, 0) == -1 && errno == EINTR) {
+ ;
+ }
+
+ if (!WIFEXITED(wstat)) {
+
+ throw exceptions::system_error("Process exited with signal "
+ + getPosixSignalMessage(WTERMSIG(wstat)));
+
+ } else if (WEXITSTATUS(wstat) != 0) {
+
+ if (WEXITSTATUS(wstat) == 255) {
+
+ scoped_ptr <posixFileSystemFactory> pfsf(new posixFileSystemFactory());
+
+ throw exceptions::system_error("Could not execute '"
+ + pfsf->pathToString(m_processPath) + "'");
+
+ } else {
+
+ std::ostringstream oss;
+ oss.imbue(std::locale::classic());
+
+ oss << "Process exited with status " << WEXITSTATUS(wstat);
+
+ throw exceptions::system_error(oss.str());
+ }
+ }
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
diff --git a/vmime-master/src/vmime/platforms/posix/posixChildProcess.hpp b/vmime-master/src/vmime/platforms/posix/posixChildProcess.hpp
new file mode 100644
index 0000000..b831e8b
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixChildProcess.hpp
@@ -0,0 +1,92 @@
+//
+// 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_PLATFORMS_POSIX_POSIXCHILDPROCESS_HPP_INCLUDED
+#define VMIME_PLATFORMS_POSIX_POSIXCHILDPROCESS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/utility/childProcess.hpp"
+
+#include <sys/types.h>
+#include <signal.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+class posixChildProcess : public utility::childProcess {
+
+public:
+
+ posixChildProcess(const utility::file::path& path);
+ ~posixChildProcess();
+
+ void start(const std::vector <string>& args, const int flags = 0);
+
+ shared_ptr <utility::outputStream> getStdIn();
+ shared_ptr <utility::inputStream> getStdOut();
+
+ void waitForFinish();
+
+private:
+
+ utility::file::path m_processPath;
+ bool m_started;
+
+ shared_ptr <utility::outputStream> m_stdIn;
+ shared_ptr <utility::inputStream> m_stdOut;
+
+ sigset_t m_oldProcMask;
+ pid_t m_pid;
+ int m_pipe[2];
+
+ std::vector <string> m_argVector;
+ const char** m_argArray;
+};
+
+
+class posixChildProcessFactory : public utility::childProcessFactory {
+
+public:
+
+ shared_ptr <utility::childProcess> create(const utility::file::path& path) const;
+};
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
+#endif // VMIME_PLATFORMS_POSIX_POSIXCHILDPROCESS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/platforms/posix/posixCriticalSection.cpp b/vmime-master/src/vmime/platforms/posix/posixCriticalSection.cpp
new file mode 100644
index 0000000..2f25cfa
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixCriticalSection.cpp
@@ -0,0 +1,67 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX
+
+
+#include "vmime/platforms/posix/posixCriticalSection.hpp"
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+posixCriticalSection::posixCriticalSection() {
+
+ pthread_mutex_init(&m_cs, NULL);
+}
+
+
+posixCriticalSection::~posixCriticalSection() {
+
+ pthread_mutex_destroy(&m_cs);
+}
+
+
+void posixCriticalSection::lock() {
+
+ pthread_mutex_lock(&m_cs);
+}
+
+
+void posixCriticalSection::unlock() {
+
+ pthread_mutex_unlock(&m_cs);
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX
diff --git a/vmime-master/src/vmime/platforms/posix/posixCriticalSection.hpp b/vmime-master/src/vmime/platforms/posix/posixCriticalSection.hpp
new file mode 100644
index 0000000..9a4bed5
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixCriticalSection.hpp
@@ -0,0 +1,69 @@
+//
+// 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_PLATFORMS_POSIX_CRITICALSECTION_HPP_INCLUDED
+#define VMIME_PLATFORMS_POSIX_CRITICALSECTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX
+
+
+#include "vmime/utility/sync/criticalSection.hpp"
+
+
+#include <unistd.h>
+#include <pthread.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+class posixCriticalSection : public utility::sync::criticalSection {
+
+public:
+
+ posixCriticalSection();
+ ~posixCriticalSection();
+
+ void lock();
+ void unlock();
+
+private:
+
+ pthread_mutex_t m_cs;
+};
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX
+
+#endif // VMIME_PLATFORMS_POSIX_CRITICALSECTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/posix/posixFile.cpp b/vmime-master/src/vmime/platforms/posix/posixFile.cpp
new file mode 100644
index 0000000..9773b3a
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixFile.cpp
@@ -0,0 +1,715 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/platforms/posix/posixFile.hpp"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+//
+// posixFileIterator
+//
+
+posixFileIterator::posixFileIterator(
+ const vmime::utility::file::path& path,
+ const vmime::string& nativePath
+)
+ : m_path(path),
+ m_nativePath(nativePath),
+ m_dir(NULL),
+ m_dirEntry(NULL) {
+
+ if ((m_dir = ::opendir(m_nativePath.c_str())) == NULL) {
+ posixFileSystemFactory::reportError(path, errno);
+ }
+
+ getNextElement();
+}
+
+
+posixFileIterator::~posixFileIterator() {
+
+ if (m_dir) {
+
+ if (::closedir(m_dir) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+ }
+}
+
+
+bool posixFileIterator::hasMoreElements() const {
+
+ return (m_dirEntry != NULL);
+}
+
+
+shared_ptr <vmime::utility::file> posixFileIterator::nextElement() {
+
+ shared_ptr <posixFile> file = make_shared <posixFile>(
+ m_path / vmime::utility::file::path::component(m_dirEntry->d_name)
+ );
+
+ getNextElement();
+
+ return file;
+}
+
+
+void posixFileIterator::getNextElement() {
+
+ errno = 0;
+
+ while ((m_dirEntry = ::readdir(m_dir)) != NULL) {
+
+ const char* name = m_dirEntry->d_name;
+ const size_t len = ::strlen(name);
+
+ if (!(len == 1 && name[0] == '.') &&
+ !(len == 2 && name[0] == '.' && name[1] == '.')) {
+
+ break;
+ }
+ }
+
+ if (errno) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+}
+
+
+
+//
+// posixFileWriterOutputStream
+//
+
+posixFileWriterOutputStream::posixFileWriterOutputStream(
+ const vmime::utility::file::path& path,
+ const int fd
+)
+ : m_path(path),
+ m_fd(fd) {
+
+}
+
+
+posixFileWriterOutputStream::~posixFileWriterOutputStream() {
+
+ ::close(m_fd);
+}
+
+
+void posixFileWriterOutputStream::writeImpl(
+ const byte_t* const data,
+ const size_t count
+) {
+
+ const byte_t* array = data;
+ size_t size = count;
+
+ while (1) {
+
+ ssize_t ret = ::write(m_fd, array, size);
+
+ if (ret == -1) {
+
+ if (errno == EINTR) {
+ continue;
+ }
+
+ posixFileSystemFactory::reportError(m_path, errno);
+ break;
+
+ } else if (size_t(ret) < size) {
+
+ array += ret;
+ size -= ret;
+ }
+
+ break;
+ }
+}
+
+
+void posixFileWriterOutputStream::flush() {
+
+ if (::fsync(m_fd) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+}
+
+
+
+//
+// posixFileReaderInputStream
+//
+
+posixFileReaderInputStream::posixFileReaderInputStream(
+ const vmime::utility::file::path& path,
+ const int fd
+)
+ : m_path(path),
+ m_fd(fd),
+ m_eof(false) {
+
+}
+
+
+posixFileReaderInputStream::~posixFileReaderInputStream() {
+
+ if (::close(m_fd) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+}
+
+
+bool posixFileReaderInputStream::eof() const {
+
+ return m_eof;
+}
+
+
+void posixFileReaderInputStream::reset() {
+
+ if (::lseek(m_fd, 0, SEEK_SET) == off_t(-1)) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ m_eof = false;
+}
+
+
+size_t posixFileReaderInputStream::read(
+ byte_t* const data,
+ const size_t count
+) {
+
+ ssize_t c = 0;
+
+ if ((c = ::read(m_fd, data, count)) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ if (c == 0 && count != 0) {
+ m_eof = true;
+ }
+
+ return static_cast <size_t>(c);
+}
+
+
+size_t posixFileReaderInputStream::skip(const size_t count) {
+
+ const off_t curPos = ::lseek(m_fd, 0, SEEK_CUR);
+
+ if (curPos == off_t(-1)) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ const off_t newPos = ::lseek(m_fd, count, SEEK_CUR);
+
+ if (newPos == off_t(-1)) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ return static_cast <size_t>(newPos - curPos);
+}
+
+
+size_t posixFileReaderInputStream::getPosition() const {
+
+ const off_t curPos = ::lseek(m_fd, 0, SEEK_CUR);
+
+ if (curPos == off_t(-1)) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ return static_cast <size_t>(curPos);
+}
+
+
+void posixFileReaderInputStream::seek(const size_t pos) {
+
+ const off_t newPos = ::lseek(m_fd, pos, SEEK_SET);
+
+ if (newPos == off_t(-1)) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+}
+
+
+
+//
+// posixFileWriter
+//
+
+posixFileWriter::posixFileWriter(
+ const vmime::utility::file::path& path,
+ const vmime::string& nativePath
+)
+ : m_path(path),
+ m_nativePath(nativePath) {
+
+}
+
+
+shared_ptr <vmime::utility::outputStream> posixFileWriter::getOutputStream() {
+
+ int fd = 0;
+
+ if ((fd = ::open(m_nativePath.c_str(), O_WRONLY, 0660)) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ return make_shared <posixFileWriterOutputStream>(m_path, fd);
+}
+
+
+
+//
+// posixFileReader
+//
+
+posixFileReader::posixFileReader(
+ const vmime::utility::file::path& path,
+ const vmime::string& nativePath
+)
+ : m_path(path),
+ m_nativePath(nativePath) {
+
+}
+
+
+shared_ptr <vmime::utility::inputStream> posixFileReader::getInputStream() {
+
+ int fd = 0;
+
+ if ((fd = ::open(m_nativePath.c_str(), O_RDONLY, 0640)) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ return make_shared <posixFileReaderInputStream>(m_path, fd);
+}
+
+
+
+//
+// posixFile
+//
+
+posixFile::posixFile(const vmime::utility::file::path& path)
+ : m_path(path),
+ m_nativePath(posixFileSystemFactory::pathToStringImpl(path)) {
+
+}
+
+
+void posixFile::createFile() {
+
+ int fd = 0;
+
+ if ((fd = ::open(m_nativePath.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660)) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ if (::fsync(fd) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ if (::close(fd) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+}
+
+
+void posixFile::createDirectory(const bool createAll) {
+
+ createDirectoryImpl(m_path, m_path, createAll);
+}
+
+
+bool posixFile::isFile() const {
+
+ struct stat buf;
+
+ if (::stat(m_nativePath.c_str(), &buf) == -1) {
+
+ if (errno == ENOENT) {
+ return false;
+ }
+
+ posixFileSystemFactory::reportError(m_path, errno);
+ return false;
+ }
+
+ return S_ISREG(buf.st_mode);
+}
+
+
+bool posixFile::isDirectory() const {
+
+ struct stat buf;
+
+ if (::stat(m_nativePath.c_str(), &buf) == -1) {
+
+ if (errno == ENOENT) {
+ return false;
+ }
+
+ posixFileSystemFactory::reportError(m_path, errno);
+ return false;
+ }
+
+ return S_ISDIR(buf.st_mode);
+}
+
+
+bool posixFile::canRead() const {
+
+ struct stat buf;
+
+ if (::stat(m_nativePath.c_str(), &buf) == -1) {
+
+ if (errno == ENOENT) {
+ return false;
+ }
+
+ posixFileSystemFactory::reportError(m_path, errno);
+ return false;
+ }
+
+ return S_ISREG(buf.st_mode)
+ && ::access(m_nativePath.c_str(), R_OK | F_OK) == 0;
+}
+
+
+bool posixFile::canWrite() const {
+
+ struct stat buf;
+
+ if (::stat(m_nativePath.c_str(), &buf) == -1) {
+
+ if (errno == ENOENT) {
+ return false;
+ }
+
+ posixFileSystemFactory::reportError(m_path, errno);
+ return false;
+ }
+
+ return S_ISREG(buf.st_mode)
+ && ::access(m_nativePath.c_str(), W_OK | F_OK) == 0;
+}
+
+
+posixFile::length_type posixFile::getLength() {
+
+ struct stat buf;
+
+ if (::stat(m_nativePath.c_str(), &buf) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ return static_cast <length_type>(buf.st_size);
+}
+
+
+const posixFile::path& posixFile::getFullPath() const {
+
+ return m_path;
+}
+
+
+bool posixFile::exists() const {
+
+ struct stat buf;
+ return ::stat(m_nativePath.c_str(), &buf) == 0;
+}
+
+
+shared_ptr <vmime::utility::file> posixFile::getParent() const {
+
+ if (m_path.isEmpty()) {
+ return null;
+ } else {
+ return make_shared <posixFile>(m_path.getParent());
+ }
+}
+
+
+void posixFile::rename(const path& newName) {
+
+ const vmime::string newNativePath = posixFileSystemFactory::pathToStringImpl(newName);
+
+ posixFile dest(newName);
+
+ if (isDirectory()) {
+ dest.createDirectory();
+ } else {
+ dest.createFile();
+ }
+
+ if (::rename(m_nativePath.c_str(), newNativePath.c_str()) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ m_path = newName;
+ m_nativePath = newNativePath;
+}
+
+
+void posixFile::remove() {
+
+ struct stat buf;
+
+ if (::stat(m_nativePath.c_str(), &buf) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ if (S_ISDIR(buf.st_mode)) {
+
+ if (::rmdir(m_nativePath.c_str()) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+
+ } else if (S_ISREG(buf.st_mode)) {
+
+ if (::unlink(m_nativePath.c_str()) == -1) {
+ posixFileSystemFactory::reportError(m_path, errno);
+ }
+ }
+}
+
+
+shared_ptr <vmime::utility::fileWriter> posixFile::getFileWriter() {
+
+ return make_shared <posixFileWriter>(m_path, m_nativePath);
+}
+
+
+shared_ptr <vmime::utility::fileReader> posixFile::getFileReader() {
+
+ return make_shared <posixFileReader>(m_path, m_nativePath);
+}
+
+
+shared_ptr <vmime::utility::fileIterator> posixFile::getFiles() const {
+
+ if (!isDirectory()) {
+ throw vmime::exceptions::not_a_directory(m_path);
+ }
+
+ return make_shared <posixFileIterator>(m_path, m_nativePath);
+}
+
+
+void posixFile::createDirectoryImpl(
+ const vmime::utility::file::path& fullPath,
+ const vmime::utility::file::path& path,
+ const bool recursive
+) {
+
+ const vmime::string nativePath = posixFileSystemFactory::pathToStringImpl(path);
+ struct stat buf;
+
+ if (::stat(nativePath.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode)) {
+ return;
+ }
+
+ if (!path.isEmpty() && recursive) {
+ createDirectoryImpl(fullPath, path.getParent(), true);
+ }
+
+ if (::mkdir(nativePath.c_str(), 0750) == -1) {
+ posixFileSystemFactory::reportError(fullPath, errno);
+ }
+}
+
+
+
+//
+// posixFileSystemFactory
+//
+
+shared_ptr <vmime::utility::file> posixFileSystemFactory::create(
+ const vmime::utility::file::path& path
+) const {
+
+ return make_shared <posixFile>(path);
+}
+
+
+const vmime::utility::file::path posixFileSystemFactory::stringToPath(
+ const vmime::string& str
+) const {
+
+ return stringToPathImpl(str);
+}
+
+
+const vmime::string posixFileSystemFactory::pathToString(
+ const vmime::utility::file::path& path
+) const {
+
+ return pathToStringImpl(path);
+}
+
+
+const vmime::utility::file::path posixFileSystemFactory::stringToPathImpl(
+ const vmime::string& str
+) {
+
+ vmime::size_t offset = 0;
+ vmime::size_t prev = 0;
+
+ vmime::utility::file::path path;
+
+ while ((offset = str.find_first_of("/", offset)) != vmime::string::npos) {
+
+ if (offset != prev) {
+
+ path.appendComponent(
+ vmime::utility::file::path::component(
+ vmime::string(str.begin() + prev, str.begin() + offset)
+ )
+ );
+ }
+
+ prev = offset + 1;
+ offset++;
+ }
+
+ if (prev < str.length()) {
+
+ path.appendComponent(
+ vmime::utility::file::path::component(
+ vmime::string(str.begin() + prev, str.end())
+ )
+ );
+ }
+
+ return path;
+}
+
+
+const vmime::string posixFileSystemFactory::pathToStringImpl(const vmime::utility::file::path& path) {
+
+ vmime::string native = "/";
+
+ for (size_t i = 0 ; i < path.getSize() ; ++i) {
+
+ if (i > 0) {
+ native += "/";
+ }
+
+ native += path[i].getBuffer();
+ }
+
+ return native;
+}
+
+
+bool posixFileSystemFactory::isValidPathComponent(
+ const vmime::utility::file::path::component& comp
+) const {
+
+ return comp.getBuffer().find_first_of("/*") == vmime::string::npos;
+}
+
+
+bool posixFileSystemFactory::isValidPath(const vmime::utility::file::path& path) const {
+
+ for (size_t i = 0 ; i < path.getSize() ; ++i) {
+
+ if (!isValidPathComponent(path[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+void posixFileSystemFactory::reportError(const vmime::utility::path& path, const int err) {
+
+ vmime::string desc;
+
+ switch (err) {
+ case EEXIST: desc = "EEXIST: file already exists."; break;
+ case EISDIR: desc = "EISDIR: path refers to a directory."; break;
+ case EACCES: desc = "EACCES: permission denied"; break;
+ case ENAMETOOLONG: desc = "ENAMETOOLONG: path too long."; break;
+ case ENOENT: desc = "ENOENT: a directory in the path does not exist."; break;
+ case ENOTDIR: desc = "ENOTDIR: path is not a directory."; break;
+ case EROFS: desc = "EROFS: read-only filesystem."; break;
+ case ELOOP: desc = "ELOOP: too many symbolic links."; break;
+ case ENOSPC: desc = "ENOSPC: no space left on device."; break;
+ case ENOMEM: desc = "ENOMEM: insufficient kernel memory."; break;
+ case EMFILE: desc = "ENFILE: limit on number of files open by the process has been reached."; break;
+ case ENFILE: desc = "ENFILE: limit on number of files open on the system has been reached."; break;
+#ifndef AIX
+ case ENOTEMPTY: desc = "ENOTEMPTY: directory is not empty."; break;
+#endif
+
+ default:
+
+ std::ostringstream oss;
+ oss << ::strerror(err) << ".";
+
+ desc = oss.str();
+ break;
+ }
+
+ throw vmime::exceptions::filesystem_exception(desc, path);
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
diff --git a/vmime-master/src/vmime/platforms/posix/posixFile.hpp b/vmime-master/src/vmime/platforms/posix/posixFile.hpp
new file mode 100644
index 0000000..d1fda9e
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixFile.hpp
@@ -0,0 +1,224 @@
+//
+// 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_PLATFORMS_POSIX_FILE_HPP_INCLUDED
+#define VMIME_PLATFORMS_POSIX_FILE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/utility/file.hpp"
+#include "vmime/utility/seekableInputStream.hpp"
+
+
+#include <dirent.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+class posixFileWriterOutputStream : public vmime::utility::outputStream {
+
+public:
+
+ posixFileWriterOutputStream(const vmime::utility::file::path& path, const int fd);
+ ~posixFileWriterOutputStream();
+
+ void flush();
+
+protected:
+
+ void writeImpl(const byte_t* const data, const size_t count);
+
+private:
+
+ const vmime::utility::file::path m_path;
+ const int m_fd;
+};
+
+
+
+class posixFileReaderInputStream : public vmime::utility::seekableInputStream {
+
+public:
+
+ posixFileReaderInputStream(const vmime::utility::file::path& path, const int fd);
+ ~posixFileReaderInputStream();
+
+ bool eof() const;
+
+ void reset();
+
+ size_t read(byte_t* const data, const size_t count);
+
+ size_t skip(const size_t count);
+
+ size_t getPosition() const;
+ void seek(const size_t pos);
+
+private:
+
+ const vmime::utility::file::path m_path;
+ const int m_fd;
+
+ bool m_eof;
+};
+
+
+
+class posixFileWriter : public vmime::utility::fileWriter {
+
+public:
+
+ posixFileWriter(const vmime::utility::file::path& path, const vmime::string& nativePath);
+
+ shared_ptr <vmime::utility::outputStream> getOutputStream();
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+};
+
+
+
+class posixFileReader : public vmime::utility::fileReader {
+
+public:
+
+ posixFileReader(const vmime::utility::file::path& path, const vmime::string& nativePath);
+
+ shared_ptr <vmime::utility::inputStream> getInputStream();
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+};
+
+
+
+class posixFileIterator : public vmime::utility::fileIterator {
+
+public:
+
+ posixFileIterator(const vmime::utility::file::path& path, const vmime::string& nativePath);
+ ~posixFileIterator();
+
+ bool hasMoreElements() const;
+ shared_ptr <vmime::utility::file> nextElement();
+
+private:
+
+ void getNextElement();
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+
+ DIR* m_dir;
+ struct dirent* m_dirEntry;
+};
+
+
+
+class posixFile : public vmime::utility::file {
+
+public:
+
+ posixFile(const vmime::utility::file::path& path);
+
+ void createFile();
+ void createDirectory(const bool createAll = false);
+
+ bool isFile() const;
+ bool isDirectory() const;
+
+ bool canRead() const;
+ bool canWrite() const;
+
+ length_type getLength();
+
+ const path& getFullPath() const;
+
+ bool exists() const;
+
+ shared_ptr <vmime::utility::file> getParent() const;
+
+ void rename(const path& newName);
+
+ void remove();
+
+ shared_ptr <vmime::utility::fileWriter> getFileWriter();
+ shared_ptr <vmime::utility::fileReader> getFileReader();
+
+ shared_ptr <vmime::utility::fileIterator> getFiles() const;
+
+private:
+
+ static void createDirectoryImpl(
+ const vmime::utility::file::path& fullPath,
+ const vmime::utility::file::path& path,
+ const bool recursive = false
+ );
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+};
+
+
+
+class posixFileSystemFactory : public vmime::utility::fileSystemFactory {
+
+public:
+
+ shared_ptr <vmime::utility::file> create(const vmime::utility::file::path& path) const;
+
+ const vmime::utility::file::path stringToPath(const vmime::string& str) const;
+ const vmime::string pathToString(const vmime::utility::file::path& path) const;
+
+ static const vmime::utility::file::path stringToPathImpl(const vmime::string& str);
+ static const vmime::string pathToStringImpl(const vmime::utility::file::path& path);
+
+ bool isValidPathComponent(const vmime::utility::file::path::component& comp) const;
+ bool isValidPath(const vmime::utility::file::path& path) const;
+
+ static void reportError(const vmime::utility::path& path, const int err);
+};
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_FILESYSTEM_FEATURES
+
+#endif // VMIME_PLATFORMS_POSIX_FILE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/posix/posixHandler.cpp b/vmime-master/src/vmime/platforms/posix/posixHandler.cpp
new file mode 100644
index 0000000..eecdbea
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixHandler.cpp
@@ -0,0 +1,292 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX
+
+
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+#include "vmime/platforms/posix/posixCriticalSection.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#if VMIME_HAVE_SYSCALL
+# include <sys/syscall.h>
+#endif
+
+#include <netdb.h>
+
+#include <string.h>
+#include <cassert>
+#include <cstdlib>
+
+
+/*
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ #include <sched.h>
+#endif // _POSIX_PRIORITY_SCHEDULING
+*/
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+posixHandler::posixHandler() {
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ m_socketFactory = make_shared <posixSocketFactory>();
+#endif
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ m_fileSysFactory = make_shared <posixFileSystemFactory>();
+ m_childProcFactory = make_shared <posixChildProcessFactory>();
+#endif
+
+}
+
+
+posixHandler::~posixHandler() {
+
+}
+
+
+unsigned long posixHandler::getUnixTime() const {
+
+ return static_cast <unsigned long>(::time(NULL));
+}
+
+
+const vmime::datetime posixHandler::getCurrentLocalTime() const {
+
+ const time_t t(::time(NULL));
+
+ // Get the local time
+#if VMIME_HAVE_LOCALTIME_R
+ tm local;
+ ::localtime_r(&t, &local);
+#else
+ tm local = *::localtime(&t); // WARNING: this is not thread-safe!
+#endif
+
+ // Get the UTC time
+#if VMIME_HAVE_GMTIME_R
+ tm gmt;
+ ::gmtime_r(&t, &gmt);
+#else
+ tm gmt = *::gmtime(&t); // WARNING: this is not thread-safe!
+#endif
+
+ // "A negative value for tm_isdst causes mktime() to attempt
+ // to determine whether Daylight Saving Time is in effect
+ // for the specified time."
+ local.tm_isdst = -1;
+ gmt.tm_isdst = -1;
+
+ // Calculate the difference (in seconds)
+ const time_t diff = ::mktime(&local) - ::mktime(&gmt);
+
+ // Return the date
+ return vmime::datetime(
+ local.tm_year + 1900, local.tm_mon + 1, local.tm_mday,
+ local.tm_hour, local.tm_min, local.tm_sec, static_cast <int>(diff / 60)
+ );
+}
+
+
+const vmime::charset posixHandler::getLocalCharset() const {
+
+ // Note: nl_langinfo() might be affected by calls to setlocale()
+ // in a multithread environment. There is not MT-safe alternative
+ // to nl_langinfo().
+ auto codeset = ::nl_langinfo(CODESET);
+
+ if (codeset) {
+ return vmime::charset(codeset);
+ }
+
+ return vmime::charset();
+}
+
+
+static inline bool isAcceptableHostname(const vmime::string& str) {
+
+ // At least, try to find something better than "localhost"
+ if (utility::stringUtils::isStringEqualNoCase(str, "localhost", 9) ||
+ utility::stringUtils::isStringEqualNoCase(str, "localhost.localdomain", 21)) {
+
+ return false;
+ }
+
+ // Anything else will be OK, as long as it is a valid hostname
+ return utility::stringUtils::isValidHostname(str);
+}
+
+
+const vmime::string posixHandler::getHostName() const {
+ char hostname[256];
+
+ ::gethostname(hostname, sizeof(hostname));
+ hostname[sizeof(hostname)-1] = '\0';
+
+ // Try to get official canonical name of this host
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC; // either IPV4 or IPV6
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_CANONNAME;
+
+ struct addrinfo* info;
+
+ if (getaddrinfo(hostname, "http", &hints, &info) == 0) {
+ // First, try to get a Fully-Qualified Domain Name (FQDN)
+ for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) {
+
+ if (p->ai_canonname) {
+
+ const string hn(p->ai_canonname);
+
+ if (utility::stringUtils::isValidFQDN(hn)) {
+ freeaddrinfo(info);
+ return hn;
+ }
+ }
+ }
+
+ // Then, try to find an acceptable host name
+ for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) {
+
+ if (p->ai_canonname) {
+
+ const string hn(p->ai_canonname);
+
+ if (isAcceptableHostname(hn)) {
+ freeaddrinfo(info);
+ return hn;
+ }
+ }
+ }
+
+ freeaddrinfo(info);
+ }
+
+ if (::strlen(hostname) == 0 || !isAcceptableHostname(hostname)) {
+ ::strcpy(hostname, "localhost.localdomain");
+ }
+
+ return hostname;
+}
+
+
+unsigned int posixHandler::getProcessId() const {
+
+ return ::getpid();
+}
+
+
+unsigned int posixHandler::getThreadId() const {
+
+#if VMIME_HAVE_GETTID
+ return static_cast <unsigned int>(::gettid());
+#elif VMIME_HAVE_SYSCALL && VMIME_HAVE_SYSCALL_GETTID
+ return static_cast <unsigned int>(::syscall(SYS_gettid));
+#elif VMIME_HAVE_GETTHRID // OpenBSD
+ return static_cast <unsigned int>(::getthrid());
+#else
+ #error We have no implementation of getThreadId() for this platform!
+#endif
+
+}
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+shared_ptr <vmime::net::socketFactory> posixHandler::getSocketFactory() {
+
+ return m_socketFactory;
+}
+
+#endif
+
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+
+shared_ptr <vmime::utility::fileSystemFactory> posixHandler::getFileSystemFactory() {
+
+ return m_fileSysFactory;
+}
+
+
+shared_ptr <vmime::utility::childProcessFactory> posixHandler::getChildProcessFactory() {
+
+ return m_childProcFactory;
+}
+
+#endif
+
+
+void posixHandler::generateRandomBytes(unsigned char* buffer, const unsigned int count) {
+
+ int fd = open("/dev/urandom", O_RDONLY);
+
+ if (fd != -1) {
+
+ read(fd, buffer, count);
+ close(fd);
+
+ } else { // fallback
+
+ for (unsigned int i = 0 ; i < count ; ++i) {
+ buffer[i] = static_cast <unsigned char>(rand() % 255);
+ }
+ }
+}
+
+
+shared_ptr <utility::sync::criticalSection> posixHandler::createCriticalSection() {
+
+ return make_shared <posixCriticalSection>();
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX
diff --git a/vmime-master/src/vmime/platforms/posix/posixHandler.hpp b/vmime-master/src/vmime/platforms/posix/posixHandler.hpp
new file mode 100644
index 0000000..30417f1
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixHandler.hpp
@@ -0,0 +1,103 @@
+//
+// 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_PLATFORMS_POSIX_HANDLER_HPP_INCLUDED
+#define VMIME_PLATFORMS_POSIX_HANDLER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX
+
+
+#include "vmime/platform.hpp"
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ #include "vmime/platforms/posix/posixSocket.hpp"
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ #include "vmime/platforms/posix/posixFile.hpp"
+ #include "vmime/platforms/posix/posixChildProcess.hpp"
+#endif
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+class VMIME_EXPORT posixHandler : public vmime::platform::handler {
+
+public:
+
+ posixHandler();
+ ~posixHandler();
+
+ unsigned long getUnixTime() const;
+
+ const vmime::datetime getCurrentLocalTime() const;
+
+ const vmime::charset getLocalCharset() const;
+
+ const vmime::string getHostName() const;
+
+ unsigned int getProcessId() const;
+ unsigned int getThreadId() const;
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ shared_ptr <vmime::net::socketFactory> getSocketFactory();
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ shared_ptr <vmime::utility::fileSystemFactory> getFileSystemFactory();
+
+ shared_ptr <vmime::utility::childProcessFactory> getChildProcessFactory();
+#endif
+
+ void generateRandomBytes(unsigned char* buffer, const unsigned int count);
+
+ shared_ptr <utility::sync::criticalSection> createCriticalSection();
+
+private:
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ shared_ptr <posixSocketFactory> m_socketFactory;
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ shared_ptr <posixFileSystemFactory> m_fileSysFactory;
+ shared_ptr <posixChildProcessFactory> m_childProcFactory;
+#endif
+};
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX
+
+#endif // VMIME_PLATFORMS_POSIX_HANDLER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/posix/posixSocket.cpp b/vmime-master/src/vmime/platforms/posix/posixSocket.cpp
new file mode 100644
index 0000000..aec6a83
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixSocket.cpp
@@ -0,0 +1,969 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/platforms/posix/posixSocket.hpp"
+#include "vmime/platforms/posix/posixHandler.hpp"
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE // for getaddrinfo_a() in <netdb.h>
+#endif
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <poll.h>
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include "vmime/exception.hpp"
+
+
+#if defined(EWOULDBLOCK)
+# define IS_EAGAIN(x) ((x) == EAGAIN || (x) == EWOULDBLOCK || (x) == EINTR || (x) == EINPROGRESS)
+#else
+# define IS_EAGAIN(x) ((x) == EAGAIN || (x) == EINTR || (x) == EINPROGRESS)
+#endif
+
+
+// Workaround for detection of strerror_r variants
+#if VMIME_HAVE_STRERROR_R
+
+namespace {
+
+char* vmime_strerror_r_result(int /* res */, char* buf) {
+
+ // XSI-compliant prototype:
+ // int strerror_r(int errnum, char *buf, size_t buflen);
+ return buf;
+}
+
+char* vmime_strerror_r_result(char* res, char* /* buf */) {
+
+ // GNU-specific prototype:
+ // char *strerror_r(int errnum, char *buf, size_t buflen);
+ return res;
+}
+
+}
+
+#endif // VMIME_HAVE_STRERROR_R
+
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+//
+// posixSocket
+//
+
+posixSocket::posixSocket(shared_ptr <vmime::net::timeoutHandler> th)
+ : m_timeoutHandler(th),
+ m_desc(-1),
+ m_status(0) {
+
+}
+
+
+posixSocket::~posixSocket() {
+
+ if (m_desc != -1) {
+ ::close(m_desc);
+ }
+}
+
+
+void posixSocket::connect(const vmime::string& address, const vmime::port_t port) {
+
+ // Close current connection, if any
+ if (m_desc != -1) {
+ ::close(m_desc);
+ m_desc = -1;
+ }
+
+ if (m_tracer) {
+
+ std::ostringstream trace;
+ trace << "Connecting to " << address << ", port " << port;
+
+ m_tracer->traceSend(trace.str());
+ }
+
+#if VMIME_HAVE_GETADDRINFO // use thread-safe and IPv6-aware getaddrinfo() if available
+
+ // Resolve address, if needed
+ m_serverAddress = address;
+
+ struct ::addrinfo* addrInfo = NULL; // resolved addresses
+ resolve(&addrInfo, address, port);
+
+ // Connect to host
+ int sock = -1;
+ int connectErrno = 0;
+
+ if (m_timeoutHandler != NULL) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ for (struct ::addrinfo* curAddrInfo = addrInfo ;
+ sock == -1 && curAddrInfo != NULL ;
+ curAddrInfo = curAddrInfo->ai_next, connectErrno = ETIMEDOUT) {
+
+ if (curAddrInfo->ai_family != AF_INET && curAddrInfo->ai_family != AF_INET6) {
+ continue;
+ }
+
+ sock = ::socket(curAddrInfo->ai_family, curAddrInfo->ai_socktype, curAddrInfo->ai_protocol);
+
+ if (sock < 0) {
+ connectErrno = errno;
+ continue; // try next
+ }
+
+#if VMIME_HAVE_SO_KEEPALIVE
+
+ // Enable TCP Keepalive
+ int keepAlive_optval = 1;
+ socklen_t keepAlive_optlen = sizeof(keepAlive_optval);
+
+ ::setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive_optval, keepAlive_optlen);
+
+#endif // VMIME_HAVE_SO_KEEPALIVE
+
+#if VMIME_HAVE_SO_NOSIGPIPE
+
+ // Return EPIPE instead of generating SIGPIPE
+ int nosigpipe_optval = 1;
+ socklen_t nosigpipe_optlen = sizeof(nosigpipe_optval);
+
+ ::setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe_optval, nosigpipe_optlen);
+
+#endif // VMIME_HAVE_SO_NOSIGPIPE
+
+
+ if (m_timeoutHandler) {
+
+ ::fcntl(sock, F_SETFL, ::fcntl(sock, F_GETFL) | O_NONBLOCK);
+
+ if (::connect(sock, curAddrInfo->ai_addr, curAddrInfo->ai_addrlen) < 0) {
+
+ switch (errno) {
+
+ case 0:
+ case EINPROGRESS:
+ case EINTR:
+#if defined(EAGAIN)
+ case EAGAIN:
+#endif // EAGAIN
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ case EWOULDBLOCK:
+#endif // EWOULDBLOCK
+
+ // Connection in progress
+ break;
+
+ default:
+
+ connectErrno = errno;
+ ::close(sock);
+ sock = -1;
+ continue; // try next
+ }
+
+ // Wait for socket to be connected.
+ bool connected = false;
+
+ const int pollTimeout = 1000; // poll() timeout (ms)
+ const int tryNextTimeout = 5000; // maximum time before trying next (ms)
+
+ timeval startTime = { 0, 0 };
+ gettimeofday(&startTime, /* timezone */ NULL);
+
+ do {
+
+ pollfd fds[1];
+ fds[0].fd = sock;
+ fds[0].events = POLLIN | POLLOUT;
+
+ const int ret = ::poll(fds, sizeof(fds) / sizeof(fds[0]), pollTimeout);
+
+ // Success
+ if (ret > 0) {
+
+ if (fds[0].revents & (POLLIN | POLLOUT)) {
+
+ int error = 0;
+ socklen_t len = sizeof(error);
+
+ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+
+ connectErrno = errno;
+
+ } else {
+
+ if (error != 0) {
+ connectErrno = error;
+ } else {
+ connected = true;
+ }
+ }
+ }
+
+ break;
+
+ // Error
+ } else if (ret < -1) {
+
+ if (errno != EAGAIN && errno != EINTR) {
+
+ // Cancel connection
+ connectErrno = errno;
+ break;
+ }
+ }
+
+ // Check for timeout
+ if (m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Cancel connection
+ connectErrno = ETIMEDOUT;
+ break;
+
+ } else {
+
+ // Reset timeout and keep waiting for connection
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ } else {
+
+ // Keep waiting for connection
+ }
+
+ timeval curTime = { 0, 0 };
+ gettimeofday(&curTime, /* timezone */ NULL);
+
+ if (curAddrInfo->ai_next != NULL &&
+ curTime.tv_usec - startTime.tv_usec >= tryNextTimeout * 1000) {
+
+ connectErrno = ETIMEDOUT;
+ break;
+ }
+
+ } while (true);
+
+ if (!connected) {
+
+ ::close(sock);
+ sock = -1;
+ continue; // try next
+ }
+
+ break;
+
+ } else {
+
+ // Connection successful
+ break;
+ }
+
+ } else {
+
+ if (::connect(sock, curAddrInfo->ai_addr, curAddrInfo->ai_addrlen) < 0) {
+
+ connectErrno = errno;
+ ::close(sock);
+ sock = -1;
+ continue; // try next
+ }
+ }
+ }
+
+ ::freeaddrinfo(addrInfo);
+
+ if (sock == -1) {
+
+ try {
+ throwSocketError(connectErrno);
+ } catch (exceptions::socket_exception& e) { // wrap
+ throw vmime::exceptions::connection_error("Error while connecting socket.", e);
+ }
+ }
+
+ m_desc = sock;
+
+#else // !VMIME_HAVE_GETADDRINFO
+
+ // Resolve address
+ ::sockaddr_in addr;
+
+ memset(&addr, 0, sizeof(addr));
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(static_cast <unsigned short>(port));
+ addr.sin_addr.s_addr = ::inet_addr(address.c_str());
+
+ if (addr.sin_addr.s_addr == static_cast <in_addr_t>(-1)) {
+
+ ::hostent* hostInfo = ::gethostbyname(address.c_str());
+
+ if (hostInfo == NULL) {
+ // Error: cannot resolve address
+ throw vmime::exceptions::connection_error("Cannot resolve address.");
+ }
+
+ ::memcpy(reinterpret_cast <char*>(&addr.sin_addr), hostInfo->h_addr, hostInfo->h_length);
+ }
+
+ m_serverAddress = address;
+
+ // Get a new socket
+ m_desc = ::socket(AF_INET, SOCK_STREAM, 0);
+
+ if (m_desc == -1) {
+
+ try {
+ throwSocketError(errno);
+ } catch (exceptions::socket_exception& e) { // wrap
+ throw vmime::exceptions::connection_error("Error while creating socket.", e);
+ }
+ }
+
+ // Start connection
+ if (::connect(m_desc, reinterpret_cast <sockaddr*>(&addr), sizeof(addr)) == -1) {
+
+ try {
+
+ throwSocketError(errno);
+
+ } catch (exceptions::socket_exception& e) { // wrap
+
+ ::close(m_desc);
+ m_desc = -1;
+
+ // Error
+ throw vmime::exceptions::connection_error("Error while connecting socket.", e);
+ }
+ }
+
+#endif // VMIME_HAVE_GETADDRINFO
+
+ ::fcntl(m_desc, F_SETFL, ::fcntl(m_desc, F_GETFL) | O_NONBLOCK);
+}
+
+
+void posixSocket::resolve(
+ struct ::addrinfo** addrInfo,
+ const vmime::string& address,
+ const vmime::port_t port
+) {
+
+ char portStr[16];
+ snprintf(portStr, sizeof(portStr), "%u", static_cast <unsigned int>(port));
+
+
+ struct ::addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+
+ hints.ai_flags = AI_CANONNAME | AI_NUMERICSERV;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+#if VMIME_HAVE_GETADDRINFO_A
+
+ // If getaddrinfo_a() is available, use asynchronous resolving to allow
+ // the timeout handler to cancel the operation
+
+ struct ::gaicb gaiRequest;
+ memset(&gaiRequest, 0, sizeof(gaiRequest));
+
+ gaiRequest.ar_name = address.c_str();
+ gaiRequest.ar_service = portStr;
+ gaiRequest.ar_request = &hints;
+
+ struct ::gaicb* gaiRequests = &gaiRequest;
+ int gaiError;
+
+ if ((gaiError = getaddrinfo_a(GAI_NOWAIT, &gaiRequests, 1, NULL)) != 0) {
+
+ throw vmime::exceptions::connection_error(
+ "getaddrinfo_a() failed: " + std::string(gai_strerror(gaiError))
+ );
+ }
+
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ while (true) {
+
+ struct timespec gaiTimeout;
+ gaiTimeout.tv_sec = 1; // query timeout handler every second
+ gaiTimeout.tv_nsec = 0;
+
+ gaiError = gai_suspend(&gaiRequests, 1, &gaiTimeout);
+
+ if (gaiError == 0 || gaiError == EAI_ALLDONE) {
+
+ const int ret = gai_error(&gaiRequest);
+
+ if (ret != 0) {
+
+ throw vmime::exceptions::connection_error(
+ "getaddrinfo_a() request failed: " + std::string(gai_strerror(ret))
+ );
+
+ } else {
+
+ *addrInfo = gaiRequest.ar_result;
+ break;
+ }
+
+ } else if (gaiError != EAI_AGAIN) {
+
+ if (gaiError == EAI_SYSTEM) {
+
+ const int ret = gai_error(&gaiRequest);
+
+ if (ret != EAI_INPROGRESS && errno != 0) {
+
+ try {
+ throwSocketError(errno);
+ } catch (exceptions::socket_exception& e) { // wrap
+ throw vmime::exceptions::connection_error("Error while connecting socket.", e);
+ }
+ }
+
+ } else {
+
+ throw vmime::exceptions::connection_error(
+ "gai_suspend() failed: " + std::string(gai_strerror(gaiError))
+ );
+ }
+ }
+
+ // Check for timeout
+ if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ throw exceptions::operation_timed_out();
+
+ } else {
+
+ // Reset timeout and keep waiting for connection
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+ }
+
+#else // !VMIME_HAVE_GETADDRINFO_A
+
+ if (::getaddrinfo(address.c_str(), portStr, &hints, addrInfo) != 0) {
+
+ // Error: cannot resolve address
+ throw vmime::exceptions::connection_error("Cannot resolve address.");
+ }
+
+#endif // VMIME_HAVE_GETADDRINFO_A
+
+}
+
+
+bool posixSocket::isConnected() const {
+
+ if (m_desc == -1) {
+ return false;
+ }
+
+ char buff;
+
+ return ::recv(m_desc, &buff, 1, MSG_PEEK) != 0;
+}
+
+
+void posixSocket::disconnect() {
+
+ if (m_desc != -1) {
+
+ if (m_tracer) {
+ m_tracer->traceSend("Disconnecting");
+ }
+
+ ::shutdown(m_desc, SHUT_RDWR);
+ ::close(m_desc);
+
+ m_desc = -1;
+ }
+}
+
+
+static bool isNumericAddress(const char* address) {
+
+#if VMIME_HAVE_GETADDRINFO
+
+ struct addrinfo hint, *info = NULL;
+ memset(&hint, 0, sizeof(hint));
+
+ hint.ai_family = AF_UNSPEC;
+ hint.ai_flags = AI_NUMERICHOST;
+
+ if (getaddrinfo(address, 0, &hint, &info) == 0) {
+
+ freeaddrinfo(info);
+ return true;
+
+ } else {
+
+ return false;
+ }
+
+#else
+
+ return inet_addr(address) != INADDR_NONE;
+
+#endif
+
+}
+
+
+const string posixSocket::getPeerAddress() const {
+
+ // Get address of connected peer
+ sockaddr peer;
+ socklen_t peerLen = sizeof(peer);
+
+ if (getpeername(m_desc, &peer, &peerLen) != 0) {
+ throwSocketError(errno);
+ }
+
+ // Convert to numerical presentation format
+ char buf[INET6_ADDRSTRLEN];
+
+ if (!inet_ntop(peer.sa_family, &(reinterpret_cast <struct sockaddr_in *>(&peer))->sin_addr, buf, sizeof(buf))) {
+ throwSocketError(errno);
+ }
+
+ return string(buf);
+}
+
+
+const string posixSocket::getPeerName() const {
+
+ // Get address of connected peer
+ sockaddr peer;
+ socklen_t peerLen = sizeof(peer);
+
+ if (getpeername(m_desc, &peer, &peerLen) != 0) {
+ throwSocketError(errno);
+ }
+
+ // If server address as specified when connecting is a numeric
+ // address, try to get a host name for it
+ if (isNumericAddress(m_serverAddress.c_str())) {
+
+#if VMIME_HAVE_GETNAMEINFO
+
+ char host[NI_MAXHOST + 1];
+ char service[NI_MAXSERV + 1];
+
+ if (getnameinfo(reinterpret_cast <sockaddr *>(&peer), peerLen,
+ host, sizeof(host), service, sizeof(service),
+ /* flags */ NI_NAMEREQD) == 0) {
+
+ return string(host);
+ }
+
+#else
+
+ struct hostent *hp;
+
+ if ((hp = gethostbyaddr(reinterpret_cast <const void *>(&peer),
+ sizeof(peer), peer.sa_family)) != NULL) {
+
+ return string(hp->h_name);
+ }
+
+#endif
+
+ }
+
+ return m_serverAddress;
+}
+
+
+size_t posixSocket::getBlockSize() const {
+
+ return 16384; // 16 KB
+}
+
+
+bool posixSocket::waitForData(const bool read, const bool write, const int msecs) {
+
+ for (int i = 0 ; i <= msecs / 10 ; ++i) {
+
+ // Check whether data is available
+ pollfd fds[1];
+ fds[0].fd = m_desc;
+ fds[0].events = 0;
+
+ if (read) {
+ fds[0].events |= POLLIN;
+ }
+
+ if (write) {
+ fds[0].events |= POLLOUT;
+ }
+
+ const int ret = ::poll(fds, sizeof(fds) / sizeof(fds[0]), 10 /* ms */);
+
+ if (ret < 0) {
+
+ if (errno != EAGAIN && errno != EINTR) {
+ throwSocketError(errno);
+ }
+
+ } else if (ret > 0) {
+
+ if (fds[0].revents & (POLLIN | POLLOUT)) {
+ return true;
+ }
+ }
+
+ // No data available at this time
+ // Check if we are timed out
+ if (m_timeoutHandler &&
+ m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Server did not react within timeout delay
+ throw exceptions::operation_timed_out();
+
+ } else {
+
+ // Reset timeout
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+ }
+
+ return false; // time out
+}
+
+
+bool posixSocket::waitForRead(const int msecs) {
+
+ return waitForData(/* read */ true, /* write */ false, msecs);
+}
+
+
+bool posixSocket::waitForWrite(const int msecs) {
+
+ return waitForData(/* read */ false, /* write */ true, msecs);
+}
+
+
+void posixSocket::receive(vmime::string& buffer) {
+
+ const size_t size = receiveRaw(m_buffer, sizeof(m_buffer));
+ buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size);
+}
+
+
+size_t posixSocket::receiveRaw(byte_t* buffer, const size_t count) {
+
+ m_status &= ~STATUS_WOULDBLOCK;
+
+ // Check whether data is available
+ if (!waitForRead(50 /* msecs */)) {
+
+ m_status |= STATUS_WOULDBLOCK;
+
+ // Continue waiting for data
+ return 0;
+ }
+
+ // Read available data
+ ssize_t ret = ::recv(m_desc, buffer, count, 0);
+
+ if (ret < 0) {
+
+ if (!IS_EAGAIN(errno)) {
+ throwSocketError(errno);
+ }
+
+ // Check if we are timed out
+ if (m_timeoutHandler &&
+ m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Server did not react within timeout delay
+ throwSocketError(errno);
+
+ } else {
+
+ // Reset timeout
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+
+ m_status |= STATUS_WOULDBLOCK;
+
+ // No data available at this time
+ return 0;
+
+ } else if (ret == 0) {
+
+ // Host shutdown
+ throwSocketError(ENOTCONN);
+
+ } else {
+
+ // Data received, reset timeout
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+
+ return ret;
+}
+
+
+void posixSocket::send(const vmime::string& buffer) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(buffer.data()), buffer.length());
+}
+
+
+void posixSocket::send(const char* str) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(str), ::strlen(str));
+}
+
+
+void posixSocket::sendRaw(const byte_t* buffer, const size_t count) {
+
+ m_status &= ~STATUS_WOULDBLOCK;
+
+ size_t size = count;
+
+ while (size > 0) {
+
+#if VMIME_HAVE_MSG_NOSIGNAL
+ const ssize_t ret = ::send(m_desc, buffer, size, MSG_NOSIGNAL);
+#else
+ const ssize_t ret = ::send(m_desc, buffer, size, 0);
+#endif
+
+ if (ret <= 0) {
+
+ if (ret < 0 && !IS_EAGAIN(errno)) {
+ throwSocketError(errno);
+ }
+
+ waitForWrite(50 /* msecs */);
+
+ } else {
+
+ buffer += ret;
+ size -= ret;
+ }
+ }
+
+ // Reset timeout
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+}
+
+
+size_t posixSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) {
+
+ m_status &= ~STATUS_WOULDBLOCK;
+
+#if VMIME_HAVE_MSG_NOSIGNAL
+ const ssize_t ret = ::send(m_desc, buffer, count, MSG_NOSIGNAL);
+#else
+ const ssize_t ret = ::send(m_desc, buffer, count, 0);
+#endif
+
+ if (ret <= 0) {
+
+ if (ret < 0 && !IS_EAGAIN(errno)) {
+ throwSocketError(errno);
+ }
+
+ // Check if we are timed out
+ if (m_timeoutHandler &&
+ m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Could not send data within timeout delay
+ throw exceptions::operation_timed_out();
+
+ } else {
+
+ // Reset timeout
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+
+ m_status |= STATUS_WOULDBLOCK;
+
+ // No data can be written at this time
+ return 0;
+ }
+
+ // Reset timeout
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ return ret;
+}
+
+
+void posixSocket::throwSocketError(const int err) {
+
+ const char* msg = NULL;
+
+ switch (err) {
+
+ case EACCES: msg = "EACCES: permission denied"; break;
+ case EAFNOSUPPORT: msg = "EAFNOSUPPORT: address family not supported"; break;
+ case EMFILE: msg = "EMFILE: process file table overflow"; break;
+ case ENFILE: msg = "ENFILE: system limit reached"; break;
+ case EPROTONOSUPPORT: msg = "EPROTONOSUPPORT: protocol not supported"; break;
+ case EAGAIN: msg = "EGAIN: blocking operation"; break;
+ case EBADF: msg = "EBADF: invalid descriptor"; break;
+ case ECONNRESET: msg = "ECONNRESET: connection reset by peer"; break;
+ case EFAULT: msg = "EFAULT: bad user space address"; break;
+ case EINTR: msg = "EINTR: signal occurred before transmission"; break;
+ case EINVAL: msg = "EINVAL: invalid argument"; break;
+ case EMSGSIZE: msg = "EMSGSIZE: message cannot be sent atomically"; break;
+ case ENOBUFS: msg = "ENOBUFS: output queue is full"; break;
+ case ENOMEM: msg = "ENOMEM: out of memory"; break;
+ case EPIPE: msg = "EPIPE: broken pipe"; break;
+ case ENOTCONN: msg = "ENOTCONN: not connected"; break;
+ case ECONNREFUSED: msg = "ECONNREFUSED: connection refused"; break;
+ }
+
+ if (msg) {
+
+ throw exceptions::socket_exception(msg);
+
+ } else {
+
+ // Use strerror() to get string describing error number
+
+#if VMIME_HAVE_STRERROR_R
+
+ char errbuf[512];
+
+ throw exceptions::socket_exception(
+ vmime_strerror_r_result(
+ strerror_r(err, errbuf, sizeof(errbuf)),
+ errbuf
+ )
+ );
+
+#else // !VMIME_HAVE_STRERROR_R
+
+ const std::string strmsg(strerror(err));
+ throw exceptions::socket_exception(strmsg);
+
+#endif // VMIME_HAVE_STRERROR_R
+
+ }
+}
+
+
+unsigned int posixSocket::getStatus() const {
+
+ return m_status;
+}
+
+
+shared_ptr <net::timeoutHandler> posixSocket::getTimeoutHandler() {
+
+ return m_timeoutHandler;
+}
+
+
+void posixSocket::setTracer(const shared_ptr <net::tracer>& tracer) {
+
+ m_tracer = tracer;
+}
+
+
+shared_ptr <net::tracer> posixSocket::getTracer() {
+
+ return m_tracer;
+}
+
+
+
+//
+// posixSocketFactory
+//
+
+shared_ptr <vmime::net::socket> posixSocketFactory::create() {
+
+ shared_ptr <vmime::net::timeoutHandler> th;
+ return make_shared <posixSocket>(th);
+}
+
+
+shared_ptr <vmime::net::socket> posixSocketFactory::create(const shared_ptr <vmime::net::timeoutHandler>& th) {
+
+ return make_shared <posixSocket>(th);
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES
diff --git a/vmime-master/src/vmime/platforms/posix/posixSocket.hpp b/vmime-master/src/vmime/platforms/posix/posixSocket.hpp
new file mode 100644
index 0000000..7d732b7
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/posix/posixSocket.hpp
@@ -0,0 +1,118 @@
+//
+// 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_PLATFORMS_POSIX_SOCKET_HPP_INCLUDED
+#define VMIME_PLATFORMS_POSIX_SOCKET_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/net/socket.hpp"
+
+
+struct addrinfo;
+
+
+namespace vmime {
+namespace platforms {
+namespace posix {
+
+
+class posixSocket : public vmime::net::socket {
+
+public:
+
+ posixSocket(shared_ptr <vmime::net::timeoutHandler> th);
+ ~posixSocket();
+
+ void connect(const vmime::string& address, const vmime::port_t port);
+ bool isConnected() const;
+ void disconnect();
+
+ bool waitForRead(const int msecs = 30000);
+ bool waitForWrite(const int msecs = 30000);
+
+ void receive(vmime::string& buffer);
+ size_t receiveRaw(byte_t* buffer, const size_t count);
+
+ void send(const vmime::string& buffer);
+ void send(const char* str);
+ void sendRaw(const byte_t* buffer, const size_t count);
+ size_t sendRawNonBlocking(const byte_t* buffer, const size_t count);
+
+ size_t getBlockSize() const;
+
+ unsigned int getStatus() const;
+
+ const string getPeerName() const;
+ const string getPeerAddress() const;
+
+ shared_ptr <net::timeoutHandler> getTimeoutHandler();
+
+ void setTracer(const shared_ptr <net::tracer>& tracer);
+ shared_ptr <net::tracer> getTracer();
+
+protected:
+
+ void resolve(struct ::addrinfo** addrInfo, const vmime::string& address, const vmime::port_t port);
+
+ bool waitForData(const bool read, const bool write, const int msecs);
+
+ static void throwSocketError(const int err);
+
+private:
+
+ shared_ptr <vmime::net::timeoutHandler> m_timeoutHandler;
+ shared_ptr <net::tracer> m_tracer;
+
+ byte_t m_buffer[65536];
+ int m_desc;
+
+ unsigned int m_status;
+
+ string m_serverAddress;
+};
+
+
+
+class posixSocketFactory : public vmime::net::socketFactory {
+
+public:
+
+ shared_ptr <vmime::net::socket> create();
+ shared_ptr <vmime::net::socket> create(const shared_ptr <vmime::net::timeoutHandler>& th);
+};
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_PLATFORMS_POSIX_SOCKET_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/windows/windowsCodepages.hpp b/vmime-master/src/vmime/platforms/windows/windowsCodepages.hpp
new file mode 100644
index 0000000..1457c59
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsCodepages.hpp
@@ -0,0 +1,197 @@
+//
+// 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_PLATFORMS_WINDOWS_CODEPAGES_HPP_INCLUDED
+#define VMIME_PLATFORMS_WINDOWS_CODEPAGES_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS
+
+
+#include <string.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+struct windowsCodepages {
+
+ static int getByName(const char* s8_Name) {
+
+ if (stricmp(s8_Name, "ASMO-708") == 0) return 708;
+ if (stricmp(s8_Name, "big5") == 0) return 950;
+ if (stricmp(s8_Name, "cp1025") == 0) return 21025;
+ if (stricmp(s8_Name, "cp866") == 0) return 866;
+ if (stricmp(s8_Name, "cp875") == 0) return 875;
+ if (stricmp(s8_Name, "DOS-720") == 0) return 720;
+ if (stricmp(s8_Name, "DOS-862") == 0) return 862;
+ if (stricmp(s8_Name, "EUC-CN") == 0) return 51936;
+ if (stricmp(s8_Name, "euc-jp") == 0) return 51932;
+ if (stricmp(s8_Name, "EUC-JP") == 0) return 20932;
+ if (stricmp(s8_Name, "euc-kr") == 0) return 51949;
+ if (stricmp(s8_Name, "GB18030") == 0) return 54936;
+ if (stricmp(s8_Name, "GBK") == 0) return 54936;
+ if (stricmp(s8_Name, "gb2312") == 0) return 936;
+ if (stricmp(s8_Name, "hz-gb-2312") == 0) return 52936;
+ if (stricmp(s8_Name, "IBM00858") == 0) return 858;
+ if (stricmp(s8_Name, "IBM00924") == 0) return 20924;
+ if (stricmp(s8_Name, "IBM01047") == 0) return 1047;
+ if (stricmp(s8_Name, "IBM01140") == 0) return 1140;
+ if (stricmp(s8_Name, "IBM01141") == 0) return 1141;
+ if (stricmp(s8_Name, "IBM01142") == 0) return 1142;
+ if (stricmp(s8_Name, "IBM01143") == 0) return 1143;
+ if (stricmp(s8_Name, "IBM01144") == 0) return 1144;
+ if (stricmp(s8_Name, "IBM01145") == 0) return 1145;
+ if (stricmp(s8_Name, "IBM01146") == 0) return 1146;
+ if (stricmp(s8_Name, "IBM01147") == 0) return 1147;
+ if (stricmp(s8_Name, "IBM01148") == 0) return 1148;
+ if (stricmp(s8_Name, "IBM01149") == 0) return 1149;
+ if (stricmp(s8_Name, "IBM037") == 0) return 37;
+ if (stricmp(s8_Name, "IBM1026") == 0) return 1026;
+ if (stricmp(s8_Name, "IBM273") == 0) return 20273;
+ if (stricmp(s8_Name, "IBM277") == 0) return 20277;
+ if (stricmp(s8_Name, "IBM278") == 0) return 20278;
+ if (stricmp(s8_Name, "IBM280") == 0) return 20280;
+ if (stricmp(s8_Name, "IBM284") == 0) return 20284;
+ if (stricmp(s8_Name, "IBM285") == 0) return 20285;
+ if (stricmp(s8_Name, "IBM290") == 0) return 20290;
+ if (stricmp(s8_Name, "IBM297") == 0) return 20297;
+ if (stricmp(s8_Name, "IBM420") == 0) return 20420;
+ if (stricmp(s8_Name, "IBM423") == 0) return 20423;
+ if (stricmp(s8_Name, "IBM424") == 0) return 20424;
+ if (stricmp(s8_Name, "IBM437") == 0) return 437;
+ if (stricmp(s8_Name, "IBM500") == 0) return 500;
+ if (stricmp(s8_Name, "ibm737") == 0) return 737;
+ if (stricmp(s8_Name, "ibm775") == 0) return 775;
+ if (stricmp(s8_Name, "ibm850") == 0) return 850;
+ if (stricmp(s8_Name, "ibm852") == 0) return 852;
+ if (stricmp(s8_Name, "IBM855") == 0) return 855;
+ if (stricmp(s8_Name, "ibm857") == 0) return 857;
+ if (stricmp(s8_Name, "IBM860") == 0) return 860;
+ if (stricmp(s8_Name, "ibm861") == 0) return 861;
+ if (stricmp(s8_Name, "IBM863") == 0) return 863;
+ if (stricmp(s8_Name, "IBM864") == 0) return 864;
+ if (stricmp(s8_Name, "IBM865") == 0) return 865;
+ if (stricmp(s8_Name, "ibm869") == 0) return 869;
+ if (stricmp(s8_Name, "IBM870") == 0) return 870;
+ if (stricmp(s8_Name, "IBM871") == 0) return 20871;
+ if (stricmp(s8_Name, "IBM880") == 0) return 20880;
+ if (stricmp(s8_Name, "IBM905") == 0) return 20905;
+ if (stricmp(s8_Name, "IBM-Thai") == 0) return 20838;
+ if (stricmp(s8_Name, "iso-2022-jp") == 0) return 50222;
+ if (stricmp(s8_Name, "iso-2022-kr") == 0) return 50225;
+ if (stricmp(s8_Name, "iso-8859-1") == 0) return 28591;
+ if (stricmp(s8_Name, "iso-8859-13") == 0) return 28603;
+ if (stricmp(s8_Name, "iso-8859-15") == 0) return 28605;
+ if (stricmp(s8_Name, "iso-8859-2") == 0) return 28592;
+ if (stricmp(s8_Name, "iso-8859-3") == 0) return 28593;
+ if (stricmp(s8_Name, "iso-8859-4") == 0) return 28594;
+ if (stricmp(s8_Name, "iso-8859-5") == 0) return 28595;
+ if (stricmp(s8_Name, "iso-8859-6") == 0) return 28596;
+ if (stricmp(s8_Name, "iso-8859-7") == 0) return 28597;
+ if (stricmp(s8_Name, "iso-8859-8") == 0) return 28598;
+ if (stricmp(s8_Name, "iso-8859-8-i") == 0) return 38598;
+ if (stricmp(s8_Name, "iso-8859-9") == 0) return 28599;
+ if (stricmp(s8_Name, "Johab") == 0) return 1361;
+ if (stricmp(s8_Name, "koi8-r") == 0) return 20866;
+ if (stricmp(s8_Name, "koi8-u") == 0) return 21866;
+ if (stricmp(s8_Name, "ks_c_5601-1987") == 0) return 949;
+ if (stricmp(s8_Name, "macintosh") == 0) return 10000;
+ if (stricmp(s8_Name, "unicodeFFFE") == 0) return 1201;
+ if (stricmp(s8_Name, "us-ascii") == 0) return 20127;
+ if (stricmp(s8_Name, "utf-16") == 0) return 1200;
+ if (stricmp(s8_Name, "utf-32") == 0) return 12000;
+ if (stricmp(s8_Name, "utf-32BE") == 0) return 12001;
+ if (stricmp(s8_Name, "utf-7") == 0) return 65000;
+ if (stricmp(s8_Name, "utf-8") == 0) return 65001;
+ if (stricmp(s8_Name, "windows-1250") == 0) return 1250;
+ if (stricmp(s8_Name, "windows-1251") == 0) return 1251;
+ if (stricmp(s8_Name, "Windows-1252") == 0) return 1252;
+ if (stricmp(s8_Name, "windows-1253") == 0) return 1253;
+ if (stricmp(s8_Name, "windows-1254") == 0) return 1254;
+ if (stricmp(s8_Name, "windows-1255") == 0) return 1255;
+ if (stricmp(s8_Name, "windows-1256") == 0) return 1256;
+ if (stricmp(s8_Name, "windows-1257") == 0) return 1257;
+ if (stricmp(s8_Name, "windows-1258") == 0) return 1258;
+ if (stricmp(s8_Name, "windows-874") == 0) return 874;
+ if (stricmp(s8_Name, "x-Chinese-CNS") == 0) return 20000;
+ if (stricmp(s8_Name, "x-Chinese-Eten") == 0) return 20002;
+ if (stricmp(s8_Name, "x-cp20001") == 0) return 20001;
+ if (stricmp(s8_Name, "x-cp20003") == 0) return 20003;
+ if (stricmp(s8_Name, "x-cp20004") == 0) return 20004;
+ if (stricmp(s8_Name, "x-cp20005") == 0) return 20005;
+ if (stricmp(s8_Name, "x-cp20261") == 0) return 20261;
+ if (stricmp(s8_Name, "x-cp20269") == 0) return 20269;
+ if (stricmp(s8_Name, "x-cp20936") == 0) return 20936;
+ if (stricmp(s8_Name, "x-cp20949") == 0) return 20949;
+ if (stricmp(s8_Name, "x-cp50227") == 0) return 50227;
+ if (stricmp(s8_Name, "x-EBCDIC-KoreanExtended") == 0) return 20833;
+ if (stricmp(s8_Name, "x-Europa") == 0) return 29001;
+ if (stricmp(s8_Name, "x-IA5") == 0) return 20105;
+ if (stricmp(s8_Name, "x-IA5-German") == 0) return 20106;
+ if (stricmp(s8_Name, "x-IA5-Norwegian") == 0) return 20108;
+ if (stricmp(s8_Name, "x-IA5-Swedish") == 0) return 20107;
+ if (stricmp(s8_Name, "x-iscii-as") == 0) return 57006;
+ if (stricmp(s8_Name, "x-iscii-be") == 0) return 57003;
+ if (stricmp(s8_Name, "x-iscii-de") == 0) return 57002;
+ if (stricmp(s8_Name, "x-iscii-gu") == 0) return 57010;
+ if (stricmp(s8_Name, "x-iscii-ka") == 0) return 57008;
+ if (stricmp(s8_Name, "x-iscii-ma") == 0) return 57009;
+ if (stricmp(s8_Name, "x-iscii-or") == 0) return 57007;
+ if (stricmp(s8_Name, "x-iscii-pa") == 0) return 57011;
+ if (stricmp(s8_Name, "x-iscii-ta") == 0) return 57004;
+ if (stricmp(s8_Name, "x-iscii-te") == 0) return 57005;
+ if (stricmp(s8_Name, "x-mac-arabic") == 0) return 10004;
+ if (stricmp(s8_Name, "x-mac-ce") == 0) return 10029;
+ if (stricmp(s8_Name, "x-mac-chinesesimp") == 0) return 10008;
+ if (stricmp(s8_Name, "x-mac-chinesetrad") == 0) return 10002;
+ if (stricmp(s8_Name, "x-mac-croatian") == 0) return 10082;
+ if (stricmp(s8_Name, "x-mac-cyrillic") == 0) return 10007;
+ if (stricmp(s8_Name, "x-mac-greek") == 0) return 10006;
+ if (stricmp(s8_Name, "x-mac-hebrew") == 0) return 10005;
+ if (stricmp(s8_Name, "x-mac-icelandic") == 0) return 10079;
+ if (stricmp(s8_Name, "x-mac-japanese") == 0) return 10001;
+ if (stricmp(s8_Name, "x-mac-korean") == 0) return 10003;
+ if (stricmp(s8_Name, "x-mac-romanian") == 0) return 10010;
+ if (stricmp(s8_Name, "x-mac-thai") == 0) return 10021;
+ if (stricmp(s8_Name, "x-mac-turkish") == 0) return 10081;
+ if (stricmp(s8_Name, "x-mac-ukrainian") == 0) return 10017;
+
+ throw exception(std::string("Unknown charset: ") + s8_Name);
+ }
+};
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS
+
+#endif // VMIME_PLATFORMS_WINDOWS_CODEPAGES_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/windows/windowsCriticalSection.cpp b/vmime-master/src/vmime/platforms/windows/windowsCriticalSection.cpp
new file mode 100644
index 0000000..c0a0bec
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsCriticalSection.cpp
@@ -0,0 +1,67 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS
+
+
+#include "vmime/platforms/windows/windowsCriticalSection.hpp"
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+windowsCriticalSection::windowsCriticalSection() {
+
+ InitializeCriticalSectionAndSpinCount(&m_cs, 0x400);
+}
+
+
+windowsCriticalSection::~windowsCriticalSection() {
+
+ DeleteCriticalSection(&m_cs);
+}
+
+
+void windowsCriticalSection::lock() {
+
+ EnterCriticalSection(&m_cs);
+}
+
+
+void windowsCriticalSection::unlock() {
+
+ LeaveCriticalSection(&m_cs);
+}
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS
diff --git a/vmime-master/src/vmime/platforms/windows/windowsCriticalSection.hpp b/vmime-master/src/vmime/platforms/windows/windowsCriticalSection.hpp
new file mode 100644
index 0000000..ffe8294
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsCriticalSection.hpp
@@ -0,0 +1,68 @@
+//
+// 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_PLATFORMS_WINDOWS_CRITICALSECTION_HPP_INCLUDED
+#define VMIME_PLATFORMS_WINDOWS_CRITICALSECTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS
+
+
+#include "vmime/utility/sync/criticalSection.hpp"
+
+
+#include <windows.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+class windowsCriticalSection : public utility::sync::criticalSection {
+
+public:
+
+ windowsCriticalSection();
+ ~windowsCriticalSection();
+
+ void lock();
+ void unlock();
+
+private:
+
+ CRITICAL_SECTION m_cs;
+};
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS
+
+#endif // VMIME_PLATFORMS_WINDOWS_CRITICALSECTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/windows/windowsFile.cpp b/vmime-master/src/vmime/platforms/windows/windowsFile.cpp
new file mode 100644
index 0000000..774731c
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsFile.cpp
@@ -0,0 +1,712 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/platforms/windows/windowsFile.hpp"
+
+#include <windows.h>
+#include <string.h>
+
+#include "vmime/exception.hpp"
+#include "vmime/utility/stringUtils.hpp"
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+shared_ptr <vmime::utility::file> windowsFileSystemFactory::create(
+ const vmime::utility::file::path& path
+) const {
+
+ return make_shared <windowsFile>(path);
+}
+
+
+const vmime::utility::file::path windowsFileSystemFactory::stringToPath(
+ const vmime::string& str
+) const {
+
+ return stringToPathImpl(str);
+}
+
+
+const vmime::string windowsFileSystemFactory::pathToString(
+ const vmime::utility::file::path& path
+) const {
+
+ return pathToStringImpl(path);
+}
+
+
+const vmime::utility::file::path windowsFileSystemFactory::stringToPathImpl(
+ const vmime::string& str
+) {
+
+ vmime::size_t offset = 0;
+ vmime::size_t prev = 0;
+
+ vmime::utility::file::path path;
+
+ while ((offset = str.find_first_of("\\", offset)) != vmime::string::npos) {
+
+ if (offset != prev) {
+
+ path.appendComponent(
+ vmime::utility::file::path::component(
+ vmime::string(str.begin() + prev, str.begin() + offset)
+ )
+ );
+ }
+
+ prev = offset + 1;
+ offset++;
+ }
+
+ if (prev < str.length()) {
+
+ path.appendComponent(
+ vmime::utility::file::path::component(
+ vmime::string(str.begin() + prev, str.end())
+ )
+ );
+ }
+
+ return path;
+}
+
+
+const vmime::string windowsFileSystemFactory::pathToStringImpl(
+ const vmime::utility::file::path& path
+) {
+
+ vmime::string native = "";
+
+ for (int i = 0 ; i < path.getSize() ; ++i) {
+
+ if (i > 0) {
+ native += "\\";
+ }
+
+ native += path[i].getBuffer();
+ }
+
+ return native;
+}
+
+
+bool windowsFileSystemFactory::isValidPathComponent(
+ const vmime::utility::file::path::component& comp
+) const {
+
+ return isValidPathComponent(comp, false);
+}
+
+
+bool windowsFileSystemFactory::isValidPathComponent(
+ const vmime::utility::file::path::component& comp,
+ bool firstComponent
+) const {
+
+ const string& buffer = comp.getBuffer();
+
+ // If first component, check if component is a drive
+ if (firstComponent && (buffer.length() == 2) && (buffer[1] == ':')) {
+
+ char drive = tolower(buffer[0]);
+
+ if ((drive >= 'a') && (drive <= 'z')) {
+ return true;
+ }
+ }
+
+ // Check for invalid characters
+ for (size_t i = 0 ; i < buffer.length() ; ++i) {
+
+ const unsigned char c = buffer[i];
+
+ switch (c) {
+
+ // Reserved characters
+ case '<': case '>': case ':':
+ case '"': case '/': case '\\':
+ case '|': case '$': case '*':
+
+ return false;
+
+ default:
+
+ if (c <= 31) {
+ return false;
+ }
+ }
+ }
+
+ string upperBuffer = vmime::utility::stringUtils::toUpper(buffer);
+
+ // Check for reserved names
+ if (upperBuffer.length() == 3) {
+
+ if (upperBuffer == "CON" || buffer == "PRN" || buffer == "AUX" || buffer == "NUL") {
+ return false;
+ }
+
+ } else if (upperBuffer.length() == 4) {
+
+ if ((upperBuffer.substr(0, 3) == "COM") && // COM0 to COM9
+ (upperBuffer[3] >= '0') && (upperBuffer[3] <= '9')) {
+
+ return false;
+
+ } else if ((upperBuffer.substr(0, 3) == "LPT") && // LPT0 to LPT9
+ (upperBuffer[3] >= '0') && (upperBuffer[3] <= '9')) {
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+bool windowsFileSystemFactory::isValidPath(const vmime::utility::file::path& path) const {
+
+ for (int i = 0 ; i < path.getSize() ; ++i) {
+
+ if (!isValidPathComponent(path[i], (i == 0))) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+void windowsFileSystemFactory::reportError(const vmime::utility::path& path, const int err) {
+
+ vmime::string desc;
+
+ LPVOID lpMsgBuf;
+
+ if (FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ err,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL)) {
+
+ desc = (char*) lpMsgBuf;
+ LocalFree(lpMsgBuf);
+ }
+
+ throw vmime::exceptions::filesystem_exception(desc, path);
+}
+
+
+
+
+windowsFile::windowsFile(const vmime::utility::file::path& path)
+ : m_path(path),
+ m_nativePath(windowsFileSystemFactory::pathToStringImpl(path)) {
+
+}
+
+
+void windowsFile::createFile() {
+
+ HANDLE hFile = CreateFile(
+ m_nativePath.c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+
+ CloseHandle(hFile);
+}
+
+
+void windowsFile::createDirectory(const bool createAll) {
+
+ createDirectoryImpl(m_path, m_path, createAll);
+}
+
+
+bool windowsFile::isFile() const {
+
+ DWORD dwFileAttribute = GetFileAttributes(m_nativePath.c_str());
+
+ if (dwFileAttribute == INVALID_FILE_ATTRIBUTES) {
+ return false;
+ }
+
+ return (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY) == 0;
+}
+
+
+bool windowsFile::isDirectory() const {
+
+ DWORD dwFileAttribute = GetFileAttributes(m_nativePath.c_str());
+
+ if (dwFileAttribute == INVALID_FILE_ATTRIBUTES) {
+ return false;
+ }
+
+ return (dwFileAttribute & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
+}
+
+
+bool windowsFile::canRead() const {
+
+ HANDLE hFile = CreateFile(
+ m_nativePath.c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ CloseHandle(hFile);
+
+ return true;
+}
+
+
+bool windowsFile::canWrite() const {
+
+ HANDLE hFile = CreateFile(
+ m_nativePath.c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ CloseHandle(hFile);
+
+ return true;
+}
+
+
+windowsFile::length_type windowsFile::getLength() {
+
+ HANDLE hFile = CreateFile(
+ m_nativePath.c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+
+ DWORD dwSize = GetFileSize(hFile, NULL);
+
+ CloseHandle(hFile);
+
+ return dwSize;
+}
+
+
+const vmime::utility::path& windowsFile::getFullPath() const {
+
+ return m_path;
+}
+
+
+bool windowsFile::exists() const {
+
+ WIN32_FIND_DATA findData;
+ HANDLE hFind = FindFirstFile(m_nativePath.c_str(), &findData);
+
+ if (hFind != INVALID_HANDLE_VALUE) {
+ FindClose(hFind);
+ return true;
+ }
+
+ return false;
+}
+
+
+shared_ptr <vmime::utility::file> windowsFile::getParent() const {
+
+ if (m_path.isEmpty()) {
+ return null;
+ } else {
+ return make_shared <windowsFile>(m_path.getParent());
+ }
+}
+
+
+void windowsFile::rename(const path& newName) {
+
+ const vmime::string newNativeName = windowsFileSystemFactory::pathToStringImpl(newName);
+
+ if (MoveFile(m_nativePath.c_str(), newNativeName.c_str())) {
+
+ m_path = newName;
+ m_nativePath = newNativeName;
+
+ } else {
+
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+}
+
+
+void windowsFile::remove() {
+
+ if (!DeleteFile(m_nativePath.c_str())) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+}
+
+
+shared_ptr <vmime::utility::fileWriter> windowsFile::getFileWriter() {
+
+ return make_shared <windowsFileWriter>(m_path, m_nativePath);
+}
+
+
+shared_ptr <vmime::utility::fileReader> windowsFile::getFileReader() {
+
+ return make_shared <windowsFileReader>(m_path, m_nativePath);
+}
+
+
+shared_ptr <vmime::utility::fileIterator> windowsFile::getFiles() const {
+
+ return make_shared <windowsFileIterator>(m_path, m_nativePath);
+}
+
+
+void windowsFile::createDirectoryImpl(
+ const vmime::utility::file::path& fullPath,
+ const vmime::utility::file::path& path,
+ const bool recursive
+) {
+
+ const vmime::string nativePath = windowsFileSystemFactory::pathToStringImpl(path);
+
+ windowsFile tmp(path);
+
+ if (tmp.isDirectory()) {
+ return;
+ }
+
+ if (!path.isEmpty() && recursive) {
+ createDirectoryImpl(fullPath, path.getParent(), true);
+ }
+
+ if (!CreateDirectory(nativePath.c_str(), NULL)) {
+ windowsFileSystemFactory::reportError(fullPath, GetLastError());
+ }
+}
+
+
+
+windowsFileIterator::windowsFileIterator(
+ const vmime::utility::file::path& path,
+ const vmime::string& nativePath
+)
+ : m_path(path),
+ m_nativePath(nativePath),
+ m_moreElements(false),
+ m_hFind(INVALID_HANDLE_VALUE) {
+
+ findFirst();
+}
+
+
+windowsFileIterator::~windowsFileIterator() {
+
+ if (m_hFind != INVALID_HANDLE_VALUE) {
+ FindClose(m_hFind);
+ }
+}
+
+
+bool windowsFileIterator::hasMoreElements() const {
+
+ return m_moreElements;
+}
+
+
+shared_ptr <vmime::utility::file> windowsFileIterator::nextElement() {
+
+ shared_ptr <vmime::utility::file> pFile = make_shared <windowsFile>(
+ m_path / vmime::utility::file::path::component(m_findData.cFileName)
+ );
+
+ findNext();
+
+ return pFile;
+}
+
+
+void windowsFileIterator::findFirst() {
+
+ m_hFind = FindFirstFile(m_nativePath.c_str(), &m_findData);
+
+ if (m_hFind == INVALID_HANDLE_VALUE) {
+ m_moreElements = false;
+ return;
+ }
+
+ m_moreElements = true;
+
+ if (isCurrentOrParentDir()) {
+ findNext();
+ }
+}
+
+
+void windowsFileIterator::findNext() {
+
+ do {
+
+ if (!FindNextFile(m_hFind, &m_findData)) {
+ m_moreElements = false;
+ return;
+ }
+
+ } while (isCurrentOrParentDir());
+}
+
+
+bool windowsFileIterator::isCurrentOrParentDir() const {
+
+ vmime::string s(m_findData.cFileName);
+
+ if ((s == ".") || (s == "..")) {
+ return true;
+ }
+
+ return false;
+}
+
+
+
+windowsFileReader::windowsFileReader(
+ const vmime::utility::file::path& path,
+ const vmime::string& nativePath
+)
+ : m_path(path),
+ m_nativePath(nativePath) {
+
+}
+
+
+shared_ptr <vmime::utility::inputStream> windowsFileReader::getInputStream() {
+
+ HANDLE hFile = CreateFile(
+ m_nativePath.c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+
+ return make_shared <windowsFileReaderInputStream>(m_path, hFile);
+}
+
+
+windowsFileReaderInputStream::windowsFileReaderInputStream(
+ const vmime::utility::file::path& path,
+ HANDLE hFile
+)
+ : m_path(path),
+ m_hFile(hFile) {
+
+}
+
+windowsFileReaderInputStream::~windowsFileReaderInputStream() {
+
+ CloseHandle(m_hFile);
+}
+
+
+bool windowsFileReaderInputStream::eof() const {
+
+ DWORD dwSize = GetFileSize(m_hFile, NULL);
+ DWORD dwPosition = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT);
+
+ return dwSize == dwPosition;
+}
+
+
+void windowsFileReaderInputStream::reset() {
+
+ SetFilePointer(m_hFile, 0, NULL, FILE_BEGIN);
+}
+
+
+size_t windowsFileReaderInputStream::read(byte_t* const data, const size_t count) {
+
+ DWORD dwBytesRead;
+
+ if (!ReadFile(m_hFile, (LPVOID) data, (DWORD) count, &dwBytesRead, NULL)) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+
+ return dwBytesRead;
+}
+
+
+size_t windowsFileReaderInputStream::skip(const size_t count) {
+
+ DWORD dwCurPos = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT);
+ DWORD dwNewPos = SetFilePointer(m_hFile, (LONG) count, NULL, FILE_CURRENT);
+
+ return dwNewPos - dwCurPos;
+}
+
+
+size_t windowsFileReaderInputStream::getPosition() const {
+
+ DWORD dwCurPos = SetFilePointer(m_hFile, 0, NULL, FILE_CURRENT);
+
+ if (dwCurPos == INVALID_SET_FILE_POINTER) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+
+ return static_cast <size_t>(dwCurPos);
+}
+
+void windowsFileReaderInputStream::seek(const size_t pos) {
+
+ DWORD dwNewPos = SetFilePointer(m_hFile, (LONG) pos, NULL, FILE_BEGIN);
+
+ if (dwNewPos == INVALID_SET_FILE_POINTER) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+}
+
+
+
+windowsFileWriter::windowsFileWriter(
+ const vmime::utility::file::path& path,
+ const vmime::string& nativePath
+)
+ : m_path(path),
+ m_nativePath(nativePath) {
+
+}
+
+shared_ptr <vmime::utility::outputStream> windowsFileWriter::getOutputStream() {
+
+ HANDLE hFile = CreateFile(
+ m_nativePath.c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (hFile == INVALID_HANDLE_VALUE) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+
+ return make_shared <windowsFileWriterOutputStream>(m_path, hFile);
+}
+
+
+windowsFileWriterOutputStream::windowsFileWriterOutputStream(
+ const vmime::utility::file::path& path,
+ HANDLE hFile
+)
+ : m_path(path),
+ m_hFile(hFile) {
+
+}
+
+
+windowsFileWriterOutputStream::~windowsFileWriterOutputStream() {
+
+ CloseHandle(m_hFile);
+}
+
+
+void windowsFileWriterOutputStream::writeImpl(const byte_t* const data, const size_t count) {
+
+ DWORD dwBytesWritten;
+
+ if (!WriteFile(m_hFile, data, (DWORD) count, &dwBytesWritten, NULL)) {
+ windowsFileSystemFactory::reportError(m_path, GetLastError());
+ }
+}
+
+
+void windowsFileWriterOutputStream::flush() {
+
+ // TODO
+}
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_FILESYSTEM_FEATURES
+
diff --git a/vmime-master/src/vmime/platforms/windows/windowsFile.hpp b/vmime-master/src/vmime/platforms/windows/windowsFile.hpp
new file mode 100644
index 0000000..dc4b5ed
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsFile.hpp
@@ -0,0 +1,225 @@
+//
+// 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_PLATFORMS_WINDOWS_FILE_HPP_INCLUDED
+#define VMIME_PLATFORMS_WINDOWS_FILE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#include "vmime/utility/file.hpp"
+#include "vmime/utility/seekableInputStream.hpp"
+
+#include <windows.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+class windowsFileSystemFactory : public vmime::utility::fileSystemFactory {
+
+public:
+
+ shared_ptr <vmime::utility::file> create(const vmime::utility::file::path& path) const;
+
+ const vmime::utility::file::path stringToPath(const vmime::string& str) const;
+ const vmime::string pathToString(const vmime::utility::file::path& path) const;
+
+ static const vmime::utility::file::path stringToPathImpl(const vmime::string& str);
+ static const vmime::string pathToStringImpl(const vmime::utility::file::path& path);
+
+ bool isValidPathComponent(const vmime::utility::file::path::component& comp) const;
+ bool isValidPathComponent(const vmime::utility::file::path::component& comp,
+ bool firstComponent) const;
+ bool isValidPath(const vmime::utility::file::path& path) const;
+
+ static void reportError(const vmime::utility::path& path, const int err);
+};
+
+
+class windowsFile : public vmime::utility::file {
+
+public:
+
+ windowsFile(const vmime::utility::file::path& path);
+
+ void createFile();
+ void createDirectory(const bool createAll = false);
+
+ bool isFile() const;
+ bool isDirectory() const;
+
+ bool canRead() const;
+ bool canWrite() const;
+
+ length_type getLength();
+
+ const path& getFullPath() const;
+
+ bool exists() const;
+
+ shared_ptr <file> getParent() const;
+
+ void rename(const path& newName);
+ void remove();
+
+ shared_ptr <vmime::utility::fileWriter> getFileWriter();
+
+ shared_ptr <vmime::utility::fileReader> getFileReader();
+
+ shared_ptr <vmime::utility::fileIterator> getFiles() const;
+
+private:
+
+ static void createDirectoryImpl(
+ const vmime::utility::file::path& fullPath,
+ const vmime::utility::file::path& path,
+ const bool recursive = false
+ );
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+};
+
+
+class windowsFileIterator : public vmime::utility::fileIterator {
+
+public:
+
+ windowsFileIterator(const vmime::utility::file::path& path, const vmime::string& nativePath);
+ ~windowsFileIterator();
+
+ bool hasMoreElements() const;
+ shared_ptr <vmime::utility::file> nextElement();
+
+private:
+
+ void findFirst();
+ void findNext();
+ bool isCurrentOrParentDir() const;
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+ WIN32_FIND_DATA m_findData;
+ bool m_moreElements;
+ HANDLE m_hFind;
+};
+
+
+class windowsFileReader : public vmime::utility::fileReader {
+
+public:
+
+ windowsFileReader(const vmime::utility::file::path& path, const vmime::string& nativePath);
+
+public:
+
+ shared_ptr <vmime::utility::inputStream> getInputStream();
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+};
+
+
+class windowsFileReaderInputStream : public vmime::utility::inputStream {
+
+public:
+
+ windowsFileReaderInputStream(const vmime::utility::file::path& path, HANDLE hFile);
+ ~windowsFileReaderInputStream();
+
+public:
+
+ bool eof() const;
+ void reset();
+ size_t read(byte_t* const data, const size_t count);
+ size_t skip(const size_t count);
+ size_t getPosition() const;
+ void seek(const size_t pos);
+
+private:
+
+ const vmime::utility::file::path m_path;
+ HANDLE m_hFile;
+};
+
+
+class windowsFileWriter : public vmime::utility::fileWriter {
+
+public:
+
+ windowsFileWriter(const vmime::utility::file::path& path, const vmime::string& nativePath);
+
+public:
+
+ shared_ptr <vmime::utility::outputStream> getOutputStream();
+
+private:
+
+ vmime::utility::file::path m_path;
+ vmime::string m_nativePath;
+};
+
+
+class windowsFileWriterOutputStream : public vmime::utility::outputStream {
+
+public:
+
+ windowsFileWriterOutputStream(const vmime::utility::file::path& path, HANDLE hFile);
+ ~windowsFileWriterOutputStream();
+
+public:
+
+ void flush();
+
+protected:
+
+ void writeImpl(const byte_t* const data, const size_t count);
+
+private:
+
+ const vmime::utility::file::path m_path;
+ HANDLE m_hFile;
+};
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_FILESYSTEM_FEATURES
+
+#endif // VMIME_PLATFORMS_WINDOWS_FILE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/windows/windowsHandler.cpp b/vmime-master/src/vmime/platforms/windows/windowsHandler.cpp
new file mode 100644
index 0000000..551f672
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsHandler.cpp
@@ -0,0 +1,315 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS
+
+
+#include "vmime/platforms/windows/windowsHandler.hpp"
+
+#include "vmime/platforms/windows/windowsCriticalSection.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include <time.h>
+#include <locale.h>
+#include <process.h>
+#include <winsock2.h> // for WSAStartup()
+#include <windows.h> // for winnls.h
+#include <ws2tcpip.h>
+#include <wincrypt.h>
+
+#if VMIME_HAVE_MLANG
+# include <mlang.h>
+#endif
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+windowsHandler::windowsHandler() {
+
+ WSAData wsaData;
+ WSAStartup(MAKEWORD(1, 1), &wsaData);
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ m_socketFactory = make_shared <windowsSocketFactory>();
+#endif
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ m_fileSysFactory = make_shared <windowsFileSystemFactory>();
+#endif
+
+}
+
+
+windowsHandler::~windowsHandler() {
+
+ WSACleanup();
+}
+
+
+unsigned long windowsHandler::getUnixTime() const {
+
+ return static_cast <unsigned long>(::time(NULL));
+}
+
+
+const vmime::datetime windowsHandler::getCurrentLocalTime() const {
+
+ const time_t t(::time(NULL));
+
+ // Get the local time
+#if VMIME_HAVE_LOCALTIME_S
+ tm local;
+ ::localtime_s(&local, &t);
+#elif VMIME_HAVE_LOCALTIME_R
+ tm local;
+ ::localtime_r(&t, &local);
+#else
+ tm local = *::localtime(&t); // WARNING: this is not thread-safe!
+#endif
+
+ // Get the UTC time
+#if VMIME_HAVE_GMTIME_S
+ tm gmt;
+ ::gmtime_s(&gmt, &t);
+#elif VMIME_HAVE_GMTIME_R
+ tm gmt;
+ ::gmtime_r(&t, &gmt);
+#else
+ tm gmt = *::gmtime(&t); // WARNING: this is not thread-safe!
+#endif
+
+ // "A negative value for tm_isdst causes mktime() to attempt
+ // to determine whether Daylight Saving Time is in effect
+ // for the specified time."
+ local.tm_isdst = -1;
+ gmt.tm_isdst = -1;
+
+ // Calculate the difference (in seconds)
+ const int diff = (const int)(::mktime(&local) - ::mktime(&gmt));
+
+ // Return the date
+ return vmime::datetime(
+ local.tm_year + 1900, local.tm_mon + 1, local.tm_mday,
+ local.tm_hour, local.tm_min, local.tm_sec, diff / 60 // minutes needed
+ );
+}
+
+
+const vmime::charset windowsHandler::getLocalCharset() const {
+
+#if VMIME_HAVE_MLANG
+
+ char szCharset[256];
+
+ CoInitialize(NULL);
+ {
+ IMultiLanguage* pMultiLanguage;
+
+ CoCreateInstance(
+ CLSID_CMultiLanguage,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IMultiLanguage,
+ (void**) &pMultiLanguage
+ );
+
+ UINT codePage = GetACP();
+ MIMECPINFO cpInfo;
+ pMultiLanguage->GetCodePageInfo(codePage, &cpInfo);
+
+ int nLengthW = lstrlenW(cpInfo.wszBodyCharset) + 1;
+
+ WideCharToMultiByte(
+ codePage, 0, cpInfo.wszBodyCharset, nLengthW,
+ szCharset, sizeof(szCharset), NULL, NULL
+ );
+
+ pMultiLanguage->Release();
+ }
+ CoUninitialize();
+
+ return vmime::charset(szCharset);
+
+#else // VMIME_HAVE_MLANG
+
+ vmime::string ch = vmime::charsets::ISO8859_1; // default
+
+ switch (GetACP()) {
+
+ case 437: ch = vmime::charsets::CP_437; break;
+ case 737: ch = vmime::charsets::CP_737; break;
+ case 775: ch = vmime::charsets::CP_775; break;
+ case 850: ch = vmime::charsets::CP_850; break;
+ case 852: ch = vmime::charsets::CP_852; break;
+ case 853: ch = vmime::charsets::CP_853; break;
+ case 855: ch = vmime::charsets::CP_855; break;
+ case 857: ch = vmime::charsets::CP_857; break;
+ case 858: ch = vmime::charsets::CP_858; break;
+ case 860: ch = vmime::charsets::CP_860; break;
+ case 861: ch = vmime::charsets::CP_861; break;
+ case 862: ch = vmime::charsets::CP_862; break;
+ case 863: ch = vmime::charsets::CP_863; break;
+ case 864: ch = vmime::charsets::CP_864; break;
+ case 865: ch = vmime::charsets::CP_865; break;
+ case 866: ch = vmime::charsets::CP_866; break;
+ case 869: ch = vmime::charsets::CP_869; break;
+ case 874: ch = vmime::charsets::CP_874; break;
+
+ case 1125: ch = vmime::charsets::CP_1125; break;
+ case 1250: ch = vmime::charsets::CP_1250; break;
+ case 1251: ch = vmime::charsets::CP_1251; break;
+ case 1252: ch = vmime::charsets::CP_1252; break;
+ case 1253: ch = vmime::charsets::CP_1253; break;
+ case 1254: ch = vmime::charsets::CP_1254; break;
+ case 1255: ch = vmime::charsets::CP_1255; break;
+ case 1256: ch = vmime::charsets::CP_1256; break;
+ case 1257: ch = vmime::charsets::CP_1257; break;
+
+ case 28591: ch = vmime::charsets::ISO8859_1; break;
+ case 28592: ch = vmime::charsets::ISO8859_2; break;
+ case 28593: ch = vmime::charsets::ISO8859_3; break;
+ case 28594: ch = vmime::charsets::ISO8859_4; break;
+ case 28595: ch = vmime::charsets::ISO8859_5; break;
+ case 28596: ch = vmime::charsets::ISO8859_6; break;
+ case 28597: ch = vmime::charsets::ISO8859_7; break;
+ case 28598: ch = vmime::charsets::ISO8859_8; break;
+ case 28599: ch = vmime::charsets::ISO8859_9; break;
+ case 28605: ch = vmime::charsets::ISO8859_15; break;
+
+ case 65000: ch = vmime::charsets::UTF_7; break;
+ case 65001: ch = vmime::charsets::UTF_8; break;
+ }
+
+ return vmime::charset(ch);
+
+#endif
+
+}
+
+
+const vmime::string windowsHandler::getHostName() const {
+
+ char hostname[1024];
+ DWORD hostnameLen;
+
+ // First, try to get a Fully-Qualified Domain Name (FQDN)
+ for (int cnf = ComputerNameDnsHostname ; cnf <= ComputerNameDnsFullyQualified ; ++cnf) {
+
+ hostnameLen = sizeof(hostname);
+
+ if (GetComputerNameEx((COMPUTER_NAME_FORMAT) cnf, hostname, &hostnameLen)) {
+
+ const vmime::string hostnameStr(hostname);
+
+ if (utility::stringUtils::isValidFQDN(hostnameStr)) {
+ return hostnameStr;
+ }
+ }
+ }
+
+ // Anything else will be OK, as long as it is a valid hostname
+ for (int cnf = 0 ; cnf < ComputerNameMax ; ++cnf) {
+
+ hostnameLen = sizeof(hostname);
+
+ if (GetComputerNameEx((COMPUTER_NAME_FORMAT) cnf, hostname, &hostnameLen)) {
+
+ const vmime::string hostnameStr(hostname);
+
+ if (utility::stringUtils::isValidHostname(hostnameStr)) {
+ return hostnameStr;
+ }
+ }
+ }
+
+ return "localhost.localdomain";
+}
+
+
+unsigned int windowsHandler::getProcessId() const {
+
+ return static_cast <unsigned int>(::GetCurrentProcessId());
+}
+
+
+unsigned int windowsHandler::getThreadId() const {
+
+ return static_cast <unsigned int>(::GetCurrentThreadId());
+}
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+shared_ptr <vmime::net::socketFactory> windowsHandler::getSocketFactory() {
+
+ return m_socketFactory;
+}
+
+#endif
+
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+
+shared_ptr <vmime::utility::fileSystemFactory> windowsHandler::getFileSystemFactory() {
+
+ return m_fileSysFactory;
+}
+
+
+shared_ptr <vmime::utility::childProcessFactory> windowsHandler::getChildProcessFactory() {
+
+ // TODO: Not implemented
+ return null;
+}
+
+#endif
+
+
+void windowsHandler::generateRandomBytes(unsigned char* buffer, const unsigned int count) {
+
+ HCRYPTPROV cryptProvider = 0;
+ CryptAcquireContext(&cryptProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
+ CryptGenRandom(cryptProvider, static_cast <unsigned long>(count), static_cast <unsigned char*>(buffer));
+ CryptReleaseContext(cryptProvider, 0);
+}
+
+
+shared_ptr <utility::sync::criticalSection> windowsHandler::createCriticalSection() {
+
+ return make_shared <windowsCriticalSection>();
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS
+
diff --git a/vmime-master/src/vmime/platforms/windows/windowsHandler.hpp b/vmime-master/src/vmime/platforms/windows/windowsHandler.hpp
new file mode 100644
index 0000000..9dda256
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsHandler.hpp
@@ -0,0 +1,101 @@
+//
+// 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_PLATFORMS_WINDOWS_HANDLER_HPP_INCLUDED
+#define VMIME_PLATFORMS_WINDOWS_HANDLER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS
+
+
+#include "vmime/platform.hpp"
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ #include "vmime/platforms/windows/windowsSocket.hpp"
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ #include "vmime/platforms/windows/windowsFile.hpp"
+#endif
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+class VMIME_EXPORT windowsHandler : public vmime::platform::handler {
+
+public:
+
+ windowsHandler();
+ ~windowsHandler();
+
+ unsigned long getUnixTime() const;
+
+ const vmime::datetime getCurrentLocalTime() const;
+
+ const vmime::charset getLocalCharset() const;
+
+ const vmime::string getHostName() const;
+
+ unsigned int getProcessId() const;
+ unsigned int getThreadId() const;
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ shared_ptr <vmime::net::socketFactory> getSocketFactory();
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ shared_ptr <vmime::utility::fileSystemFactory> getFileSystemFactory();
+
+ shared_ptr <vmime::utility::childProcessFactory> getChildProcessFactory();
+#endif
+
+ void generateRandomBytes(unsigned char* buffer, const unsigned int count);
+
+ shared_ptr <utility::sync::criticalSection> createCriticalSection();
+
+private:
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+ shared_ptr <windowsSocketFactory> m_socketFactory;
+#endif
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+ shared_ptr <windowsFileSystemFactory> m_fileSysFactory;
+#endif
+};
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS
+
+#endif // VMIME_PLATFORMS_WINDOWS_HANDLER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/platforms/windows/windowsSocket.cpp b/vmime-master/src/vmime/platforms/windows/windowsSocket.cpp
new file mode 100644
index 0000000..3a93c53
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsSocket.cpp
@@ -0,0 +1,547 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES
+
+
+#pragma warning(disable: 4267)
+
+#include "vmime/platforms/windows/windowsSocket.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+#include "vmime/exception.hpp"
+
+#include <ws2tcpip.h>
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+//
+// windowsSocket
+//
+
+windowsSocket::windowsSocket(shared_ptr <vmime::net::timeoutHandler> th)
+ : m_timeoutHandler(th),
+ m_desc(INVALID_SOCKET),
+ m_status(0) {
+
+ WSAData wsaData;
+ WSAStartup(MAKEWORD(1, 1), &wsaData);
+}
+
+
+windowsSocket::~windowsSocket() {
+
+ if (m_desc != INVALID_SOCKET) {
+ ::closesocket(m_desc);
+ }
+
+ WSACleanup();
+}
+
+
+void windowsSocket::connect(const vmime::string& address, const vmime::port_t port) {
+
+ // Close current connection, if any
+ if (m_desc != INVALID_SOCKET) {
+ ::closesocket(m_desc);
+ m_desc = INVALID_SOCKET;
+ }
+
+ // Resolve address
+ ::sockaddr_in addr;
+
+ memset(&addr, 0, sizeof(addr));
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(static_cast <unsigned short>(port));
+ addr.sin_addr.s_addr = ::inet_addr(address.c_str());
+
+ if (m_tracer) {
+
+ std::ostringstream trace;
+ trace << "Connecting to " << address << ", port " << port;
+
+ m_tracer->traceSend(trace.str());
+ }
+
+ if (addr.sin_addr.s_addr == static_cast <int>(-1)) {
+
+ ::hostent* hostInfo = ::gethostbyname(address.c_str());
+
+ if (!hostInfo) {
+ // Error: cannot resolve address
+ throw vmime::exceptions::connection_error("Cannot resolve address.");
+ }
+
+ memcpy(reinterpret_cast <char*>(&addr.sin_addr), hostInfo->h_addr, hostInfo->h_length);
+ }
+
+ m_serverAddress = address;
+
+ // Get a new socket
+ m_desc = ::socket(AF_INET, SOCK_STREAM, 0);
+
+ if (m_desc == INVALID_SOCKET) {
+
+ try {
+
+ int err = WSAGetLastError();
+ throwSocketError(err);
+
+ } catch (exceptions::socket_exception& e) {
+
+ throw vmime::exceptions::connection_error("Error while creating socket.", e);
+ }
+ }
+
+ // Start connection
+ if (::connect(m_desc, reinterpret_cast <sockaddr*>(&addr), sizeof(addr)) == -1) {
+
+ try {
+
+ int err = WSAGetLastError();
+ throwSocketError(err);
+
+ } catch (exceptions::socket_exception& e) {
+
+ ::closesocket(m_desc);
+ m_desc = INVALID_SOCKET;
+
+ // Error
+ throw vmime::exceptions::connection_error("Error while connecting socket.", e);
+ }
+ }
+
+ // Set socket to non-blocking
+ unsigned long non_blocking = 1;
+ ::ioctlsocket(m_desc, FIONBIO, &non_blocking);
+}
+
+
+bool windowsSocket::isConnected() const {
+
+ if (m_desc == INVALID_SOCKET) {
+ return false;
+ }
+
+ char buff;
+
+ return ::recv(m_desc, &buff, 1, MSG_PEEK) != 0;
+}
+
+
+void windowsSocket::disconnect() {
+
+ if (m_desc != INVALID_SOCKET) {
+
+ if (m_tracer) {
+ m_tracer->traceSend("Disconnecting");
+ }
+
+ ::shutdown(m_desc, SD_BOTH);
+ ::closesocket(m_desc);
+
+ m_desc = INVALID_SOCKET;
+ }
+}
+
+
+static bool isNumericAddress(const char* address) {
+
+ struct addrinfo hint, *info = NULL;
+ memset(&hint, 0, sizeof(hint));
+
+ hint.ai_family = AF_UNSPEC;
+ hint.ai_flags = AI_NUMERICHOST;
+
+ if (getaddrinfo(address, 0, &hint, &info) == 0) {
+
+ freeaddrinfo(info);
+ return true;
+
+ } else {
+
+ return false;
+ }
+}
+
+
+const string windowsSocket::getPeerAddress() const {
+
+ // Get address of connected peer
+ sockaddr peer;
+ socklen_t peerLen = sizeof(peer);
+
+ getpeername(m_desc, reinterpret_cast <sockaddr*>(&peer), &peerLen);
+
+ // Convert to numerical presentation format
+ char host[NI_MAXHOST + 1];
+ char service[NI_MAXSERV + 1];
+
+ if (getnameinfo(reinterpret_cast <sockaddr *>(&peer), peerLen,
+ host, sizeof(host), service, sizeof(service),
+ /* flags */ NI_NUMERICHOST) == 0) {
+
+ return string(host);
+ }
+
+ return ""; // should not happen
+}
+
+
+const string windowsSocket::getPeerName() const {
+
+ // Get address of connected peer
+ sockaddr peer;
+ socklen_t peerLen = sizeof(peer);
+
+ getpeername(m_desc, reinterpret_cast <sockaddr*>(&peer), &peerLen);
+
+ // If server address as specified when connecting is a numeric
+ // address, try to get a host name for it
+ if (isNumericAddress(m_serverAddress.c_str())) {
+
+ char host[NI_MAXHOST + 1];
+ char service[NI_MAXSERV + 1];
+
+ if (getnameinfo(reinterpret_cast <sockaddr *>(&peer), peerLen,
+ host, sizeof(host), service, sizeof(service),
+ /* flags */ NI_NAMEREQD) == 0) {
+
+ return string(host);
+ }
+ }
+
+ return m_serverAddress;
+}
+
+
+size_t windowsSocket::getBlockSize() const {
+
+ return 16384; // 16 KB
+}
+
+
+void windowsSocket::receive(vmime::string& buffer) {
+
+ const size_t size = receiveRaw(m_buffer, sizeof(m_buffer));
+ buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size);
+}
+
+
+size_t windowsSocket::receiveRaw(byte_t* buffer, const size_t count) {
+
+ m_status &= ~STATUS_WOULDBLOCK;
+
+ // Check whether data is available
+ if (!waitForRead(50 /* msecs */)) {
+
+ // No data available at this time
+ // Check if we are timed out
+ if (m_timeoutHandler &&
+ m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Server did not react within timeout delay
+ throwSocketError(WSAETIMEDOUT);
+
+ } else {
+
+ // Reset timeout
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+
+ // Continue waiting for data
+ return 0;
+ }
+
+ // Read available data
+ int ret = ::recv(m_desc, reinterpret_cast <char*>(buffer), count, 0);
+
+ if (ret == SOCKET_ERROR) {
+
+ int err = WSAGetLastError();
+
+ if (err != WSAEWOULDBLOCK) {
+ throwSocketError(err);
+ }
+
+ m_status |= STATUS_WOULDBLOCK;
+
+ // Error or no data
+ return 0;
+
+ } else if (ret == 0) {
+
+ // Host shutdown
+ throwSocketError(WSAENOTCONN);
+
+ } else {
+
+ // Data received, reset timeout
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ return ret;
+ }
+}
+
+
+void windowsSocket::send(const vmime::string& buffer) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(buffer.data()), buffer.length());
+}
+
+
+void windowsSocket::send(const char* str) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(str), strlen(str));
+}
+
+
+void windowsSocket::sendRaw(const byte_t* buffer, const size_t count) {
+
+ m_status &= ~STATUS_WOULDBLOCK;
+
+ size_t size = count;
+
+ while (size > 0) {
+
+ const int ret = ::send(m_desc, reinterpret_cast <const char*>(buffer), size, 0);
+
+ if (ret == SOCKET_ERROR) {
+
+ int err = WSAGetLastError();
+
+ if (err != WSAEWOULDBLOCK) {
+ throwSocketError(err);
+ }
+
+ waitForWrite(50 /* msecs */);
+
+ } else {
+
+ buffer += ret;
+ size -= ret;
+ }
+ }
+
+ // Reset timeout
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+}
+
+
+size_t windowsSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) {
+
+ m_status &= ~STATUS_WOULDBLOCK;
+
+ const int ret = ::send(m_desc, reinterpret_cast <const char*>(buffer), count, 0);
+
+ if (ret == SOCKET_ERROR) {
+
+ int err = WSAGetLastError();
+
+ if (err == WSAEWOULDBLOCK) {
+
+ // Check if we are timed out
+ if (m_timeoutHandler &&
+ m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Could not send data within timeout delay
+ throwSocketError(err);
+
+ } else {
+
+ // Reset timeout
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+
+ m_status |= STATUS_WOULDBLOCK;
+
+ // No data can be written at this time
+ return 0;
+
+ } else {
+
+ throwSocketError(err);
+ }
+ }
+
+ // Reset timeout
+ if (m_timeoutHandler) {
+ m_timeoutHandler->resetTimeOut();
+ }
+
+ return ret;
+}
+
+
+unsigned int windowsSocket::getStatus() const {
+
+ return m_status;
+}
+
+
+void windowsSocket::throwSocketError(const int err) {
+
+ std::ostringstream oss;
+ string msg;
+
+ LPTSTR str;
+
+ if (::FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, err, 0, (LPTSTR) &str, 0, NULL) == 0) {
+
+ // Failed getting message
+ oss << "Unknown socket error (code " << err << ")";
+
+ } else {
+
+ oss << str;
+ ::LocalFree(str);
+ }
+
+ msg = oss.str();
+
+ throw exceptions::socket_exception(msg);
+}
+
+
+bool windowsSocket::waitForData(const bool read, const bool write, const int msecs) {
+
+ for (int i = 0 ; i <= msecs / 10 ; ++i) {
+
+ // Check whether data is available
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(m_desc, &fds);
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000; // 10 ms
+
+ int ret = ::select(m_desc + 1, read ? &fds : NULL, write ? &fds : NULL, NULL, &tv);
+
+ if (ret == SOCKET_ERROR) {
+
+ int err = WSAGetLastError();
+ throwSocketError(err);
+
+ } else if (ret > 0) {
+
+ return true;
+ }
+
+ // No data available at this time
+ // Check if we are timed out
+ if (m_timeoutHandler &&
+ m_timeoutHandler->isTimeOut()) {
+
+ if (!m_timeoutHandler->handleTimeOut()) {
+
+ // Server did not react within timeout delay
+ throw exceptions::operation_timed_out();
+
+ } else {
+
+ // Reset timeout
+ m_timeoutHandler->resetTimeOut();
+ }
+ }
+ }
+
+ return false; // time out
+}
+
+
+bool windowsSocket::waitForRead(const int msecs) {
+
+ return waitForData(/* read */ true, /* write */ false, msecs);
+}
+
+
+bool windowsSocket::waitForWrite(const int msecs) {
+
+ return waitForData(/* read */ false, /* write */ true, msecs);
+}
+
+
+shared_ptr <net::timeoutHandler> windowsSocket::getTimeoutHandler() {
+
+ return m_timeoutHandler;
+}
+
+
+void windowsSocket::setTracer(const shared_ptr <net::tracer>& tracer) {
+
+ m_tracer = tracer;
+}
+
+
+shared_ptr <net::tracer> windowsSocket::getTracer() {
+
+ return m_tracer;
+}
+
+
+
+//
+// posixSocketFactory
+//
+
+shared_ptr <vmime::net::socket> windowsSocketFactory::create() {
+
+ shared_ptr <vmime::net::timeoutHandler> th;
+ return make_shared <windowsSocket>(th);
+}
+
+
+shared_ptr <vmime::net::socket> windowsSocketFactory::create(const shared_ptr <vmime::net::timeoutHandler>& th) {
+
+ return make_shared <windowsSocket>(th);
+}
+
+
+} // posix
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES
+
diff --git a/vmime-master/src/vmime/platforms/windows/windowsSocket.hpp b/vmime-master/src/vmime/platforms/windows/windowsSocket.hpp
new file mode 100644
index 0000000..ddb82da
--- /dev/null
+++ b/vmime-master/src/vmime/platforms/windows/windowsSocket.hpp
@@ -0,0 +1,117 @@
+//
+// 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_PLATFORMS_WINDOWS_SOCKET_HPP_INCLUDED
+#define VMIME_PLATFORMS_WINDOWS_SOCKET_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include <winsock2.h>
+#include "vmime/net/socket.hpp"
+
+
+namespace vmime {
+namespace platforms {
+namespace windows {
+
+
+class windowsSocket : public vmime::net::socket {
+
+public:
+
+ windowsSocket();
+ windowsSocket(shared_ptr <vmime::net::timeoutHandler> th);
+ ~windowsSocket();
+
+public:
+
+ void connect(const vmime::string& address, const vmime::port_t port);
+ bool isConnected() const;
+ void disconnect();
+
+ bool waitForRead(const int msecs = 30000);
+ bool waitForWrite(const int msecs = 30000);
+
+ void receive(vmime::string& buffer);
+ size_t receiveRaw(byte_t* buffer, const size_t count);
+
+ void send(const vmime::string& buffer);
+ void send(const char* str);
+ void sendRaw(const byte_t* buffer, const size_t count);
+ size_t sendRawNonBlocking(const byte_t* buffer, const size_t count);
+
+ size_t getBlockSize() const;
+
+ unsigned int getStatus() const;
+
+ const string getPeerName() const;
+ const string getPeerAddress() const;
+
+ shared_ptr <net::timeoutHandler> getTimeoutHandler();
+ shared_ptr <net::tracer> m_tracer;
+
+ void setTracer(const shared_ptr <net::tracer>& tracer);
+ shared_ptr <net::tracer> getTracer();
+
+protected:
+
+ void throwSocketError(const int err);
+
+ bool waitForData(const bool read, const bool write, const int msecs);
+
+private:
+
+ shared_ptr <vmime::net::timeoutHandler> m_timeoutHandler;
+
+ byte_t m_buffer[65536];
+ SOCKET m_desc;
+
+ unsigned int m_status;
+
+ string m_serverAddress;
+};
+
+
+
+class windowsSocketFactory : public vmime::net::socketFactory {
+
+public:
+
+ shared_ptr <vmime::net::socket> create();
+ shared_ptr <vmime::net::socket> create(const shared_ptr <vmime::net::timeoutHandler>& th);
+};
+
+
+} // windows
+} // platforms
+} // vmime
+
+
+#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_PLATFORMS_WINDOWS_SOCKET_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/propertySet.cpp b/vmime-master/src/vmime/propertySet.cpp
new file mode 100644
index 0000000..e0d4848
--- /dev/null
+++ b/vmime-master/src/vmime/propertySet.cpp
@@ -0,0 +1,399 @@
+//
+// 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.
+//
+
+#include "vmime/propertySet.hpp"
+#include "vmime/parserHelpers.hpp"
+
+
+namespace vmime {
+
+
+propertySet::propertySet() {
+
+}
+
+
+propertySet::propertySet(const string& props) {
+
+ parse(props);
+}
+
+
+propertySet::propertySet(const propertySet& set)
+ : object() {
+
+ for (std::list <shared_ptr <property> >::const_iterator it = set.m_props.begin() ;
+ it != set.m_props.end() ; ++it) {
+
+ m_props.push_back(make_shared <property>(**it));
+ }
+}
+
+
+propertySet::~propertySet() {
+
+ removeAllProperties();
+}
+
+
+propertySet& propertySet::operator=(const propertySet& set) {
+
+ removeAllProperties();
+
+ for (std::list <shared_ptr <property> >::const_iterator it = set.m_props.begin() ;
+ it != set.m_props.end() ; ++it) {
+
+ m_props.push_back(make_shared <property>(**it));
+ }
+
+ return *this;
+}
+
+
+void propertySet::setFromString(const string& props) {
+
+ parse(props);
+}
+
+
+void propertySet::removeAllProperties() {
+
+ m_props.clear();
+}
+
+
+void propertySet::removeProperty(const string& name) {
+
+ std::list <shared_ptr <property> >::iterator it =
+ std::find_if(m_props.begin(), m_props.end(), propFinder(name));
+
+ if (it != m_props.end()) {
+ m_props.erase(it);
+ }
+}
+
+
+void propertySet::parse(const string& props) {
+
+ const string::const_iterator end = props.end();
+ string::const_iterator pos = props.begin();
+
+ for ( ; pos != end ; ) {
+
+ // Skip white-spaces
+ for ( ; pos != end && parserHelpers::isSpace(*pos) ; ++pos) {}
+
+ if (pos != end) {
+
+ if (*pos == ';') {
+ ++pos;
+ continue;
+ }
+
+ // Extract the property name
+ const string::const_iterator optStart = pos;
+
+ for ( ; pos != end && *pos != '=' ; ++pos) {}
+
+ string::const_iterator optEnd = pos;
+
+ for ( ; optEnd != optStart && parserHelpers::isSpace(*(optEnd - 1)) ; --optEnd) {}
+
+ const string option(optStart, optEnd);
+ string value = "1";
+
+ if (pos != end) {
+
+ ++pos; // skip '='
+
+ // Extract the value
+ for ( ; pos != end && parserHelpers::isSpace(*pos) ; ++pos) {}
+
+ if (pos != end) {
+
+ // A quoted-string
+ if (*pos == '"' || *pos == '\'') {
+
+ value.reserve(50);
+
+ const char quoteChar = *pos;
+ bool theEnd = false;
+ bool escape = false;
+
+ for ( ; (pos != end) && !theEnd ; ++pos) {
+
+ if (escape) {
+
+ value += *pos;
+ escape = false;
+
+ } else {
+
+ if (*pos == '\\') {
+ escape = true;
+ } else if (*pos == quoteChar) {
+ theEnd = true;
+ } else {
+ value += *pos;
+ }
+ }
+ }
+
+ if (pos != end) {
+ ++pos;
+ }
+
+ // Simple value
+ } else {
+
+ const string::const_iterator valStart = pos;
+
+ for ( ; pos != end && !parserHelpers::isSpace(*pos) ; ++pos) {}
+
+ value = string(valStart, pos);
+ }
+
+ // Advance to the next ';'
+ for ( ; pos != end && (*pos != ';') ; ++pos) {}
+
+ if (pos != end) {
+ ++pos; // skip ';'
+ }
+ }
+ }
+
+ m_props.push_back(make_shared <property>(option, value));
+ }
+ }
+}
+
+
+shared_ptr <propertySet::property> propertySet::find(const string& name) const {
+
+ std::list <shared_ptr <property> >::const_iterator it =
+ std::find_if(m_props.begin(), m_props.end(), propFinder(name));
+
+ return it != m_props.end() ? *it : null;
+}
+
+
+shared_ptr <propertySet::property> propertySet::findOrCreate(const string& name) {
+
+ std::list <shared_ptr <property> >::const_iterator it =
+ std::find_if(m_props.begin(), m_props.end(), propFinder(name));
+
+ if (it != m_props.end()) {
+
+ return *it;
+
+ } else {
+
+ shared_ptr <property> prop = make_shared <property>(name, "");
+ m_props.push_back(prop);
+ return prop;
+ }
+}
+
+
+propertySet::propertyProxy propertySet::operator[](const string& name) {
+
+ return propertyProxy(name, this);
+}
+
+
+const propertySet::constPropertyProxy propertySet::operator[](const string& name) const {
+
+ return constPropertyProxy(name, this);
+}
+
+
+bool propertySet::hasProperty(const string& name) const {
+
+ return find(name) != NULL;
+}
+
+
+const std::vector <shared_ptr <const propertySet::property> > propertySet::getPropertyList() const {
+
+ std::vector <shared_ptr <const property> > res;
+
+ for (list_type::const_iterator it = m_props.begin() ; it != m_props.end() ; ++it) {
+ res.push_back(*it);
+ }
+
+ return res;
+}
+
+
+const std::vector <shared_ptr <propertySet::property> > propertySet::getPropertyList() {
+
+ std::vector <shared_ptr <property> > res;
+
+ for (list_type::const_iterator it = m_props.begin() ; it != m_props.end() ; ++it) {
+ res.push_back(*it);
+ }
+
+ return res;
+}
+
+
+//
+// propertySet::property
+//
+
+propertySet::property::property(const string& name, const string& value)
+ : m_name(name),
+ m_value(value) {
+
+}
+
+
+propertySet::property::property(const string& name)
+ : m_name(name) {
+
+}
+
+
+propertySet::property::property(const property& prop)
+ : object(),
+ m_name(prop.m_name),
+ m_value(prop.m_value) {
+
+}
+
+
+const string& propertySet::property::getName() const {
+
+ return m_name;
+}
+
+
+#ifndef _MSC_VER
+
+
+const string& propertySet::property::getValue() const {
+
+ return m_value;
+}
+
+
+void propertySet::property::setValue(const string& value) {
+
+ m_value = value;
+}
+
+
+#endif // !_MSC_VER
+
+
+#ifndef VMIME_INLINE_TEMPLATE_SPECIALIZATION
+
+template <>
+void propertySet::property::setValue(const string& value) {
+
+ m_value = value;
+}
+
+
+template <>
+void propertySet::property::setValue(const bool& value) {
+
+ m_value = value ? "true" : "false";
+}
+
+
+template <>
+string propertySet::property::getValue() const {
+
+ return m_value;
+}
+
+
+template <>
+bool propertySet::property::getValue() const {
+
+ if (utility::stringUtils::toLower(m_value) == "true") {
+
+ return true;
+
+ } else {
+
+ int val = 0;
+
+ std::istringstream iss(m_value);
+ iss.imbue(std::locale::classic()); // no formatting
+
+ iss >> val;
+
+ return !iss.fail() && val != 0;
+ }
+}
+
+
+
+
+template <>
+string propertySet::valueFromString(const string& value) {
+
+ return value;
+}
+
+
+template <>
+string propertySet::valueToString(const string& value) {
+
+ return value;
+}
+
+
+template <>
+bool propertySet::valueFromString(const string& value) {
+
+ if (utility::stringUtils::toLower(value) == "true") {
+
+ return true;
+
+ } else {
+
+ int val = 0;
+
+ std::istringstream iss(value);
+ iss.imbue(std::locale::classic()); // no formatting
+
+ iss >> val;
+
+ return !iss.fail() && val != 0;
+ }
+}
+
+
+template <>
+string propertySet::valueToString(const bool& value) {
+
+ return value ? "true" : "false";
+}
+
+#endif // VMIME_INLINE_TEMPLATE_SPECIALIZATION
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/propertySet.hpp b/vmime-master/src/vmime/propertySet.hpp
new file mode 100644
index 0000000..20eb9de
--- /dev/null
+++ b/vmime-master/src/vmime/propertySet.hpp
@@ -0,0 +1,461 @@
+//
+// 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_PROPERTY_HPP_INCLUDED
+#define VMIME_PROPERTY_HPP_INCLUDED
+
+#include <list>
+#include <functional>
+#include <algorithm>
+#include <sstream>
+
+#include "vmime/base.hpp"
+#include "vmime/exception.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+
+namespace vmime {
+
+
+/** Manage a list of (name,value) pairs.
+ */
+class VMIME_EXPORT propertySet : public object {
+
+public:
+
+ /** A property holds a (name,value) pair.
+ */
+ class property : public object {
+
+ public:
+
+ property(const string& name, const string& value);
+ property(const string& name);
+ property(const property& prop);
+
+ /** Return the name of the property.
+ *
+ * @return property name
+ */
+ const string& getName() const;
+
+#ifndef _MSC_VER
+
+ // Visual Studio errors on linking with these 2 functions,
+ // whereas GCC and CLang need them.
+
+ /** Return the value of the property as a string.
+ *
+ * @return current value of the property
+ */
+ const string& getValue() const;
+
+ /** Set the value of the property as a string.
+ *
+ * @param value new value for property
+ */
+ void setValue(const string& value);
+
+#endif // !_MSC_VER
+
+ /** Set the value of the property as a generic type.
+ *
+ * @param value new value for property
+ */
+ template <class TYPE> void setValue(const TYPE& value) {
+
+ std::ostringstream oss;
+ oss.imbue(std::locale::classic()); // no formatting
+
+ oss << value;
+
+ m_value = oss.str();
+ }
+
+ /** Get the value of the property as a generic type.
+ *
+ * @throw exceptions::invalid_property_type if the specified
+ * type is incompatible with the string value (cannot be
+ * converted using std::istringstream)
+ * @return current value of the property
+ */
+ template <class TYPE> TYPE getValue() const {
+
+ TYPE val = TYPE();
+
+ std::istringstream iss(m_value);
+ iss.imbue(std::locale::classic()); // no formatting
+
+ iss >> val;
+
+ if (iss.fail()) {
+ throw exceptions::invalid_property_type();
+ }
+
+ return (val);
+ }
+
+
+#ifdef VMIME_INLINE_TEMPLATE_SPECIALIZATION
+
+ template <>
+ void propertySet::property::setValue(const string& value) {
+
+ m_value = value;
+ }
+
+ template <>
+ void propertySet::property::setValue(const bool& value) {
+
+ m_value = value ? "true" : "false";
+ }
+
+ template <>
+ string propertySet::property::getValue() const {
+
+ return (m_value);
+ }
+
+ template <>
+ bool propertySet::property::getValue() const {
+
+ if (utility::stringUtils::toLower(m_value) == "true") {
+
+ return true;
+
+ } else {
+
+ int val = 0;
+
+ std::istringstream iss(m_value);
+ iss.imbue(std::locale::classic()); // no formatting
+
+ iss >> val;
+
+ return !iss.fail() && val != 0;
+ }
+ }
+
+#endif // VMIME_INLINE_TEMPLATE_SPECIALIZATION
+
+ private:
+
+ const string m_name;
+ string m_value;
+ };
+
+protected:
+
+ class propertyProxy {
+
+ public:
+
+ propertyProxy(const string& name, propertySet* set)
+ : m_name(name),
+ m_set(set) {
+
+ }
+
+ template <class TYPE>
+ propertyProxy& operator=(const TYPE& value) {
+
+ m_set->setProperty(m_name, value);
+ return *this;
+ }
+
+ template <class TYPE>
+ void setValue(const TYPE& value) {
+
+ m_set->setProperty(m_name, value);
+ }
+
+ template <class TYPE>
+ const TYPE getValue() const {
+
+ return m_set->getProperty <TYPE>(m_name);
+ }
+
+ operator string() const {
+
+ return m_set->getProperty <string>(m_name);
+ }
+
+ private:
+
+ const string m_name;
+ propertySet* m_set;
+ };
+
+ class constPropertyProxy {
+
+ public:
+
+ constPropertyProxy(const string& name, const propertySet* set)
+ : m_name(name),
+ m_set(set) {
+
+ }
+
+ template <class TYPE>
+ const TYPE getValue() const {
+
+ return m_set->getProperty <TYPE>(m_name);
+ }
+
+ operator string() const {
+
+ return m_set->getProperty <string>(m_name);
+ }
+
+ private:
+
+ const string m_name;
+ const propertySet* m_set;
+ };
+
+public:
+
+ propertySet();
+ propertySet(const string& props);
+ propertySet(const propertySet& set);
+
+ ~propertySet();
+
+ propertySet& operator=(const propertySet& set);
+
+ /** Parse a string and extract one or more properties.
+ * The string format is: name[=value](;name[=value])*.
+ *
+ * @param props string representing a list of properties
+ */
+ void setFromString(const string& props);
+
+ /** Remove all properties from the list.
+ */
+ void removeAllProperties();
+
+ /** Remove the specified property.
+ *
+ * @param name name of the property to remove
+ */
+ void removeProperty(const string& name);
+
+ /** Test whether the specified property is set.
+ *
+ * @param name name of the property to test
+ * @return true if the property is set (has a value),
+ * false otherwise
+ */
+ bool hasProperty(const string& name) const;
+
+ /** Get the value of the specified property.
+ *
+ * @throw exceptions::no_such_property if the property does not exist
+ * @param name property name
+ * @return value of the specified property
+ */
+ template <class TYPE>
+ const TYPE getProperty(const string& name) const {
+
+ const shared_ptr <property> prop = find(name);
+ if (!prop) throw exceptions::no_such_property(name);
+
+ return (prop->template getValue <TYPE>());
+ }
+
+ /** Get the value of the specified property.
+ * A default value can be returned if the property is not set.
+ *
+ * @param name property name
+ * @param defaultValue value to return if the specified property
+ * does not exist
+ * @return value of the specified property or default value
+ * if if does not exist
+ */
+ template <class TYPE>
+ const TYPE getProperty(const string& name, const TYPE defaultValue) const {
+
+ const shared_ptr <property> prop = find(name);
+ return prop ? prop->template getValue <TYPE>() : defaultValue;
+ }
+
+ /** Change the value of the specified property or create
+ * a new property set to the specified a value.
+ *
+ * @param name property name
+ * @param value property value
+ */
+ template <class TYPE>
+ void setProperty(const string& name, const TYPE& value) {
+ findOrCreate(name)->setValue(value);
+ }
+
+ /** Return a proxy object to access the specified property
+ * suitable for reading or writing. If the property does not
+ * exist and the value is changed, a new property will
+ * be created.
+ *
+ * @param name property name
+ * @return proxy object for the specified property
+ */
+ propertyProxy operator[](const string& name);
+
+ /** Return a proxy object to access the specified property
+ * suitable for reading only.
+ *
+ * @throw exceptions::no_such_property if the property does not exist
+ * @return read-only proxy object for the specified property
+ */
+ const constPropertyProxy operator[](const string& name) const;
+
+private:
+
+ void parse(const string& props);
+
+
+ class propFinder : public std::unary_function <shared_ptr <property>, bool> {
+
+ public:
+
+ propFinder(const string& name) : m_name(utility::stringUtils::toLower(name)) { }
+
+ bool operator()(const shared_ptr <property>& p) const {
+
+ return (utility::stringUtils::toLower(p->getName()) == m_name);
+ }
+
+ private:
+
+ const string m_name;
+ };
+
+ shared_ptr <property> find(const string& name) const;
+ shared_ptr <property> findOrCreate(const string& name);
+
+ typedef std::list <shared_ptr <property> > list_type;
+ list_type m_props;
+
+public:
+
+ template <typename TYPE>
+ static TYPE valueFromString(const string& value) {
+
+ TYPE v = TYPE();
+
+ std::istringstream iss(value);
+ iss.imbue(std::locale::classic()); // no formatting
+
+ iss >> v;
+
+ return v;
+ }
+
+ template <typename TYPE>
+ static string valueToString(const TYPE& value) {
+
+ std::ostringstream oss(value);
+ oss.imbue(std::locale::classic()); // no formatting
+
+ oss << value;
+
+ return oss.str();
+ }
+
+#ifdef VMIME_INLINE_TEMPLATE_SPECIALIZATION
+
+ template <>
+ static string valueFromString(const string& value) {
+
+ return value;
+ }
+
+ template <>
+ static string valueToString(const string& value) {
+
+ return value;
+ }
+
+ template <>
+ static bool valueFromString(const string& value) {
+
+ if (utility::stringUtils::toLower(value) == "true") {
+
+ return true;
+
+ } else {
+
+ int val = 0;
+
+ std::istringstream iss(value);
+ iss.imbue(std::locale::classic()); // no formatting
+
+ iss >> val;
+
+ return !iss.fail() && val != 0;
+ }
+ }
+
+ template <>
+ static string valueToString(const bool& value) {
+
+ return value ? "true" : "false";
+ }
+
+#endif // VMIME_INLINE_TEMPLATE_SPECIALIZATION
+
+ /** Return the property list.
+ *
+ * @return list of properties
+ */
+ const std::vector <shared_ptr <const property> > getPropertyList() const;
+
+ /** Return the property list.
+ *
+ * @return list of properties
+ */
+ const std::vector <shared_ptr <property> > getPropertyList();
+};
+
+
+#ifndef VMIME_INLINE_TEMPLATE_SPECIALIZATION
+
+template <> VMIME_EXPORT void propertySet::property::setValue <string>(const string& value);
+template <> VMIME_EXPORT void propertySet::property::setValue(const bool& value);
+
+template <> VMIME_EXPORT string propertySet::property::getValue() const;
+template <> VMIME_EXPORT bool propertySet::property::getValue() const;
+
+template <> VMIME_EXPORT string propertySet::valueFromString(const string& value);
+template <> VMIME_EXPORT string propertySet::valueToString(const string& value);
+
+template <> VMIME_EXPORT bool propertySet::valueFromString(const string& value);
+template <> VMIME_EXPORT string propertySet::valueToString(const bool& value);
+
+#endif // VMIME_INLINE_TEMPLATE_SPECIALIZATION
+
+
+} // vmime
+
+
+#endif // VMIME_PROPERTY_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/relay.cpp b/vmime-master/src/vmime/relay.cpp
new file mode 100644
index 0000000..b0a6b60
--- /dev/null
+++ b/vmime-master/src/vmime/relay.cpp
@@ -0,0 +1,363 @@
+//
+// 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.
+//
+
+#include "vmime/relay.hpp"
+#include "vmime/text.hpp"
+#include "vmime/parserHelpers.hpp"
+#include "vmime/utility/outputStreamAdapter.hpp"
+
+#include <sstream>
+
+
+namespace vmime {
+
+
+relay::relay() {
+
+}
+
+
+relay::relay(const relay& r)
+ : headerFieldValue() {
+
+ copyFrom(r);
+}
+
+
+/*
+
+ RFC #2822:
+
+ received = "Received" ":" ; one per relay
+ ["from" domain] ; sending host
+ ["by" domain] ; receiving host
+ ["via" atom] ; physical path
+ *("with" atom) ; link/mail protocol
+ ["id" msg-id] ; receiver msg id
+ ["for" addr-spec] ; initial form
+*/
+
+void relay::parseImpl(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ const char* const pend = buffer.data() + end;
+ const char* const pstart = buffer.data() + position;
+ const char* p = pend - 1;
+
+ // Find the beginning of the date part
+ while (p >= pstart && *p != ';') {
+ --p;
+ }
+
+ if (p >= pstart) {
+
+ // Parse the date/time part
+ m_date.parse(ctx, buffer, position + (p - pstart) + 1, end);
+
+ // Parse the components
+ std::istringstream iss(
+ string(buffer.begin() + position, buffer.begin() + position + (p - pstart))
+ );
+
+ iss.imbue(std::locale::classic());
+
+ string word;
+ std::vector <string> previous;
+
+ enum Parts {
+ Part_None,
+ Part_From, // The "from" part
+ Part_By, // The "by" part
+ Part_Via, // The "via" part
+ Part_With, // One "with" part
+ Part_Id, // The "id" part
+ Part_For, // The "for" part
+ Part_End
+ };
+
+ Parts part = Part_None;
+ bool cont = true;
+ bool inComment = false;
+
+ while (cont) {
+
+ Parts newPart = Part_None;
+
+ if ((cont = !(iss >> word).fail())) {
+
+ // A little hack for handling comments
+ if (inComment) {
+
+ size_t par = word.find(')');
+
+ if (par != string::npos) {
+
+ previous.push_back(string(word.begin(), word.begin() + par + 1));
+ word.erase(word.begin(), word.begin() + par + 1);
+ inComment = false;
+ }
+ }
+
+ bool keyword = false;
+
+ if (!inComment) {
+
+ if (utility::stringUtils::isStringEqualNoCase(word, "from", 4)) {
+
+ newPart = Part_From;
+ keyword = true;
+
+ } else if (utility::stringUtils::isStringEqualNoCase(word, "by", 2)) {
+
+ newPart = Part_By;
+ keyword = true;
+
+ } else if (utility::stringUtils::isStringEqualNoCase(word, "via", 2)) {
+
+ newPart = Part_Via;
+ keyword = true;
+
+ } else if (utility::stringUtils::isStringEqualNoCase(word, "with", 2)) {
+
+ newPart = Part_With;
+ keyword = true;
+
+ } else if (utility::stringUtils::isStringEqualNoCase(word, "id", 2)) {
+
+ newPart = Part_Id;
+ keyword = true;
+
+ } else if (utility::stringUtils::isStringEqualNoCase(word, "for", 2)) {
+
+ newPart = Part_For;
+ keyword = true;
+ }
+ }
+
+ if (!keyword) {
+
+ if (word.find('(') != string::npos) {
+ inComment = true;
+ }
+
+ previous.push_back(word);
+ }
+ }
+
+ if (!cont || newPart != Part_None) {
+
+ if (part != Part_None) {
+
+ std::ostringstream value;
+
+ for (std::vector <string>::const_iterator
+ it = previous.begin() ; it != previous.end() ; ++it) {
+
+ if (it != previous.begin()) value << " ";
+ value << *it;
+ }
+
+ switch (part) {
+ case Part_From: m_from = value.str(); break;
+ case Part_By: m_by = value.str(); break;
+ case Part_Via: m_via = value.str(); break;
+ case Part_With: m_with.push_back(value.str()); break;
+ case Part_Id: m_id = value.str(); break;
+ case Part_For: m_for = value.str(); break;
+ default: break; // Should never happen...
+ }
+ }
+
+ previous.clear();
+ part = newPart;
+ }
+ }
+ }
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void relay::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ std::ostringstream oss;
+ int count = 0;
+
+ if (m_from.length()) oss << (count++ > 0 ? " " : "") << "from " << m_from;
+ if (m_by.length()) oss << (count++ > 0 ? " " : "") << "by " << m_by;
+ if (m_via.length()) oss << (count++ > 0 ? " " : "") << "via " << m_via;
+
+ for (std::vector <string>::const_iterator
+ it = m_with.begin() ; it != m_with.end() ; ++it) {
+
+ oss << (count++ > 0 ? " " : "") << "with " << *it;
+ }
+
+ if (m_id.length()) oss << (count++ > 0 ? " " : "") << "id " << m_id;
+ if (m_for.length()) oss << (count++ > 0 ? " " : "") << "for " << m_for;
+
+ oss << "; ";
+
+ vmime::utility::outputStreamAdapter dos(oss);
+ m_date.generate(ctx, dos, 0, NULL);
+
+ text(oss.str()).encodeAndFold(ctx, os, curLinePos, newLinePos, text::FORCE_NO_ENCODING);
+}
+
+
+void relay::copyFrom(const component& other) {
+
+ const relay& r = dynamic_cast <const relay&>(other);
+
+ m_from = r.m_from;
+ m_via = r.m_via;
+ m_by = r.m_by;
+ m_id = r.m_id;
+ m_for = r.m_for;
+
+ m_with.resize(r.m_with.size());
+ std::copy(r.m_with.begin(), r.m_with.end(), m_with.begin());
+
+ m_date = r.m_date;
+}
+
+
+relay& relay::operator=(const relay& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+shared_ptr <component> relay::clone() const {
+
+ return make_shared <relay>(*this);
+}
+
+
+const string& relay::getFrom() const {
+
+ return m_from;
+}
+
+
+void relay::setFrom(const string& from) {
+
+ m_from = from;
+}
+
+
+const string& relay::getVia() const {
+
+ return m_via;
+}
+
+
+void relay::setVia(const string& via) {
+
+ m_via = via;
+}
+
+
+const string& relay::getBy() const {
+
+ return m_by;
+}
+
+
+void relay::setBy(const string& by) {
+
+ m_by = by;
+}
+
+
+const string& relay::getId() const {
+
+ return m_id;
+}
+
+
+void relay::setId(const string& id) {
+
+ m_id = id;
+}
+
+
+const string& relay::getFor() const {
+
+ return m_for;
+}
+
+
+void relay::setFor(const string& for_) {
+
+ m_for = for_;
+}
+
+
+const datetime& relay::getDate() const {
+
+ return m_date;
+}
+
+
+void relay::setDate(const datetime& date) {
+
+ m_date = date;
+}
+
+
+const std::vector <string>& relay::getWithList() const {
+
+ return m_with;
+}
+
+
+std::vector <string>& relay::getWithList() {
+
+ return m_with;
+}
+
+
+const std::vector <shared_ptr <component> > relay::getChildComponents() {
+
+ // TODO: should fields inherit from 'component'? (using typeAdapter)
+ return std::vector <shared_ptr <component> >();
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/relay.hpp b/vmime-master/src/vmime/relay.hpp
new file mode 100644
index 0000000..f467602
--- /dev/null
+++ b/vmime-master/src/vmime/relay.hpp
@@ -0,0 +1,108 @@
+//
+// 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_RELAY_HPP_INCLUDED
+#define VMIME_RELAY_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/headerFieldValue.hpp"
+
+#include "vmime/dateTime.hpp"
+
+
+namespace vmime {
+
+
+/** Trace information about a relay (basic type).
+ */
+class VMIME_EXPORT relay : public headerFieldValue {
+
+public:
+
+ relay();
+ relay(const relay& r);
+
+public:
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ relay& operator=(const relay& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+ const string& getFrom() const;
+ void setFrom(const string& from);
+
+ const string& getVia() const;
+ void setVia(const string& via);
+
+ const string& getBy() const;
+ void setBy(const string& by);
+
+ const string& getId() const;
+ void setId(const string& id);
+
+ const string& getFor() const;
+ void setFor(const string& for_);
+
+ const datetime& getDate() const;
+ void setDate(const datetime& date);
+
+ const std::vector <string>& getWithList() const;
+ std::vector <string>& getWithList();
+
+private:
+
+ string m_from;
+ string m_via;
+ string m_by;
+ string m_id;
+ string m_for;
+ std::vector <string> m_with;
+
+ datetime m_date;
+
+protected:
+
+ void parseImpl(
+ const 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;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_RELAY_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/authenticator.hpp b/vmime-master/src/vmime/security/authenticator.hpp
new file mode 100644
index 0000000..03bca73
--- /dev/null
+++ b/vmime-master/src/vmime/security/authenticator.hpp
@@ -0,0 +1,136 @@
+//
+// 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_SECURITY_AUTHENTICATOR_HPP_INCLUDED
+#define VMIME_SECURITY_AUTHENTICATOR_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/types.hpp"
+
+
+// Forward declarations
+namespace vmime {
+namespace net {
+
+class service;
+
+} // net
+} // vmime
+
+
+namespace vmime {
+namespace security {
+
+
+/** Provides required information for user authentication. The same
+ * information can be requested multiple time (eg. in IMAP, there is a
+ * new connection started each time a folder is open), so the object is
+ * responsible for caching the information to avoid useless interactions
+ * with the user.
+ *
+ * Usually, you should not inherit from this class, but instead from the
+ * more convenient defaultAuthenticator class.
+ *
+ * WARNING: an authenticator should be used with one and ONLY ONE messaging
+ * service at a time.
+ */
+class VMIME_EXPORT authenticator : public object {
+
+public:
+
+ /** Return the authentication identity (usually, this
+ * is the username).
+ *
+ * @return username
+ * @throw exceptions::no_auth_information if the information
+ * could not be provided
+ */
+ virtual const string getUsername() const = 0;
+
+ /** Return the password of the authentication identity.
+ *
+ * @return password
+ * @throw exceptions::no_auth_information if the information
+ * could not be provided
+ */
+ virtual const string getPassword() const = 0;
+
+ /** Return the optional access token for authentication. This is
+ * used for example with XOAuth2 SASL authentication.
+ *
+ * @return access token
+ * @throw exceptions::no_auth_information if the information
+ * could not be provided
+ */
+ virtual const string getAccessToken() const = 0;
+
+ /** Return the local host name of the machine.
+ *
+ * @return hostname
+ * @throw exceptions::no_auth_information if the information
+ * could not be provided
+ */
+ virtual const string getHostname() const = 0;
+
+ /** Return the anonymous token (usually, this is the user's
+ * email address).
+ *
+ * @return anonymous token
+ * @throw exceptions::no_auth_information if the information
+ * could not be provided
+ */
+ virtual const string getAnonymousToken() const = 0;
+
+ /** Return the registered service name of the application
+ * service (eg: "imap"). This can be used by GSSAPI or DIGEST-MD5
+ * mechanisms with SASL.
+ *
+ * @return service name
+ * @throw exceptions::no_auth_information if the information
+ * could not be provided
+ */
+ virtual const string getServiceName() const = 0;
+
+ /** Called by the messaging service to allow this authenticator to
+ * know which service is currently using it. This is called just
+ * before the service starts the authentication process.
+ *
+ * @param serv messaging service instance
+ */
+ virtual void setService(const shared_ptr <net::service>& serv) = 0;
+};
+
+
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_SECURITY_AUTHENTICATOR_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/cert/X509Certificate.cpp b/vmime-master/src/vmime/security/cert/X509Certificate.cpp
new file mode 100644
index 0000000..128fac1
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/X509Certificate.cpp
@@ -0,0 +1,72 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/X509Certificate.hpp"
+
+#include "vmime/security/cert/certificateNotYetValidException.hpp"
+#include "vmime/security/cert/certificateExpiredException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+X509Certificate::~X509Certificate() {
+
+}
+
+
+void X509Certificate::checkValidity() {
+
+ const datetime now = datetime::now();
+
+ if (now < getActivationDate()) {
+
+ certificateNotYetValidException ex;
+ ex.setCertificate(dynamicCast <certificate>(shared_from_this()));
+
+ throw ex;
+
+ } else if (now > getExpirationDate()) {
+
+ certificateExpiredException ex;
+ ex.setCertificate(dynamicCast <certificate>(shared_from_this()));
+
+ throw ex;
+ }
+}
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
diff --git a/vmime-master/src/vmime/security/cert/X509Certificate.hpp b/vmime-master/src/vmime/security/cert/X509Certificate.hpp
new file mode 100644
index 0000000..5434b45
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/X509Certificate.hpp
@@ -0,0 +1,197 @@
+//
+// 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_SECURITY_CERT_X509CERTIFICATE_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_X509CERTIFICATE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificate.hpp"
+
+#include "vmime/utility/stream.hpp"
+
+#include "vmime/base.hpp"
+#include "vmime/types.hpp"
+#include "vmime/dateTime.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+/** Identity certificate based on X.509 standard.
+ */
+class VMIME_EXPORT X509Certificate : public certificate {
+
+public:
+
+ ~X509Certificate();
+
+ /** Supported encodings for X.509 certificates. */
+ enum Format {
+ FORMAT_DER, /**< DER encoding */
+ FORMAT_PEM /**< PEM encoding */
+ };
+
+ /** Supported digest algorithms (used for fingerprint). */
+ enum DigestAlgorithm {
+ DIGEST_MD5, /**< MD5 digest */
+ DIGEST_SHA1 /**< SHA1 digest */
+ };
+
+
+ /** Imports a DER or PEM encoded X.509 certificate.
+ *
+ * @param is input stream to read data from
+ * @return a X.509 certificate, or NULL if the given data does not
+ * represent a valid certificate
+ */
+ static shared_ptr <X509Certificate> import(utility::inputStream& is);
+
+ /** Imports a DER or PEM encoded X.509 certificate.
+ *
+ * @param data points to raw data
+ * @param length size of data
+ * @return a X.509 certificate, or NULL if the given data does not
+ * represent a valid certificate
+ */
+ static shared_ptr <X509Certificate> import(const byte_t* data, const size_t length);
+
+ /** Import sveral DER or PEM encoded X.509 certificates.
+ *
+ * @param is input stream to read data from
+ * @param certs the resulting list of certificates
+ */
+ static void import(
+ utility::inputStream& is,
+ std::vector <shared_ptr <X509Certificate> >& certs
+ );
+
+ /** Import several DER or PEM encoded X.509 certificates.
+ *
+ * @param data points to raw data
+ * @param length size of data
+ * @param certs the resulting list of certificates
+ */
+ static void import(
+ const byte_t* data,
+ const size_t length,
+ std::vector <shared_ptr <X509Certificate> >& certs
+ );
+
+ /** Exports this X.509 certificate to the specified format.
+ *
+ * @param os output stream into which write data
+ * @param format output format
+ */
+ virtual void write(utility::outputStream& os, const Format format) const = 0;
+
+ /** Returns the X.509 certificate's serial number. This is obtained
+ * by the X.509 Certificate 'serialNumber' field. Serial is not
+ * always a 32 or 64bit number. Some CAs use large serial numbers,
+ * thus it may be wise to handle it as something opaque.
+ *
+ * @return serial number of this certificate
+ */
+ virtual const byteArray getSerialNumber() const = 0;
+
+ /** Returns the distinguished name of the issuer of this certificate.
+ * Eg. "C=US,O=VeriSign\, Inc.,OU=Class 1 Public Primary Certification Authority"
+ *
+ * @return distinguished name of the certificate issuer, as a string
+ */
+ virtual const string getIssuerString() const = 0;
+
+ /** Checks if this certificate has the given issuer.
+ *
+ * @param issuer certificate of a possible issuer
+ * @return true if this certificate was issued by the given issuer,
+ * false otherwise
+ */
+ virtual bool checkIssuer(const shared_ptr <const X509Certificate>& issuer) const = 0;
+
+ /** Verifies this certificate against a given trusted one.
+ *
+ * @param caCert a certificate that is considered to be trusted one
+ * @return true if the verification succeeded, false otherwise
+ */
+ virtual bool verify(const shared_ptr <const X509Certificate>& caCert) const = 0;
+
+ /** Verify certificate's subject name against the given hostname.
+ *
+ * @param hostname DNS name of the server
+ * @param nonMatchingNames if not NULL, will contain the names that do
+ * not match the identities in the certificate
+ * @return true if the match is successful, false otherwise
+ */
+ virtual bool verifyHostName(
+ const string& hostname,
+ std::vector <std::string>* nonMatchingNames = NULL
+ ) const = 0;
+
+ /** Gets the expiration date of this certificate. This is the date
+ * at which this certificate will not be valid anymore.
+ *
+ * @return expiration date of this certificate
+ */
+ virtual const datetime getExpirationDate() const = 0;
+
+ /** Gets the activation date of this certificate. This is the date
+ * at which this certificate will be valid.
+ *
+ * @return activation date of this certificate
+ */
+ virtual const datetime getActivationDate() const = 0;
+
+ /** Returns the fingerprint of this certificate.
+ *
+ * @return the fingerprint of this certificate
+ */
+ virtual const byteArray getFingerprint(const DigestAlgorithm algo) const = 0;
+
+ /** Checks that the certificate is currently valid. For the certificate
+ * to be valid, the current date and time must be in the validity period
+ * specified in the certificate.
+ *
+ * @throw certificateExpiredException if the certificate has expired
+ * @throw certificateNotYetValidException if the certificate is not yet valid
+ */
+ virtual void checkValidity();
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+#endif // VMIME_SECURITY_CERT_X509CERTIFICATE_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/security/cert/certificate.hpp b/vmime-master/src/vmime/security/cert/certificate.hpp
new file mode 100644
index 0000000..ed0f175
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificate.hpp
@@ -0,0 +1,84 @@
+//
+// 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_SECURITY_CERT_CERTIFICATE_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_CERTIFICATE_HPP_INCLUDED
+
+
+#include "vmime/types.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+/** Identity certificate for a peer.
+ */
+class VMIME_EXPORT certificate : public object, public enable_shared_from_this <certificate> {
+
+public:
+
+ /** Returns the encoded form of this certificate (for example,
+ * X.509 certificates are encoded as ASN.1 DER).
+ *
+ * @return the encoded form of this certificate
+ */
+ virtual const byteArray getEncoded() const = 0;
+
+ /** Return the type of this certificate.
+ *
+ * @return the type of this certificate
+ */
+ virtual const string getType() const = 0;
+
+ /** Return the version of this certificate.
+ *
+ * @return the version of this certificate
+ */
+ virtual int getVersion() const = 0;
+
+ /** Checks if two certificates are the same.
+ *
+ * @param other certificate to compare with
+ * @return true if the two certificates are the same,
+ * false otherwise
+ */
+ virtual bool equals(const shared_ptr <const certificate>& other) const = 0;
+
+ /** Returns a pointer to internal binary data for this certificate.
+ * The actual type of data depends on the library used for TLS support.
+ *
+ * @return pointer to underlying data
+ */
+ virtual void* getInternalData() = 0;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_SECURITY_CERT_CERTIFICATE_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/security/cert/certificateChain.cpp b/vmime-master/src/vmime/security/cert/certificateChain.cpp
new file mode 100644
index 0000000..c506913
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateChain.cpp
@@ -0,0 +1,53 @@
+//
+// 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.
+//
+
+#include "vmime/security/cert/certificateChain.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+certificateChain::certificateChain(const std::vector <shared_ptr <certificate> >& certs)
+ : m_certs(certs) {
+
+}
+
+
+size_t certificateChain::getCount() const {
+
+ return m_certs.size();
+}
+
+
+const shared_ptr <certificate>& certificateChain::getAt(const size_t index) {
+
+ return m_certs[index];
+}
+
+
+} // cert
+} // security
+} // vmime
+
diff --git a/vmime-master/src/vmime/security/cert/certificateChain.hpp b/vmime-master/src/vmime/security/cert/certificateChain.hpp
new file mode 100644
index 0000000..f8c363e
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateChain.hpp
@@ -0,0 +1,79 @@
+//
+// 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_SECURITY_CERT_CERTIFICATECHAIN_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_CERTIFICATECHAIN_HPP_INCLUDED
+
+
+#include "vmime/types.hpp"
+
+#include "vmime/security/cert/certificate.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+/** An ordered list of certificates, from the subject certificate to
+ * the issuer certificate.
+ */
+class VMIME_EXPORT certificateChain : public object {
+
+public:
+
+ /** Construct a new certificateChain object given an ordered list
+ * of certificates.
+ *
+ * @param certs chain of certificates
+ */
+ certificateChain(const std::vector <shared_ptr <certificate> >& certs);
+
+ /** Return the number of certificates in the chain.
+ *
+ * @return number of certificates in the chain
+ */
+ size_t getCount() const;
+
+ /** Return the certificate at the specified position. 0 is the
+ * subject certificate, 1 is the issuer's certificate, 2 is
+ * the issuer's issuer, etc.
+ *
+ * @param index position at which to retrieve certificate
+ * @return certificate at the specified position
+ */
+ const shared_ptr <certificate>& getAt(const size_t index);
+
+protected:
+
+ std::vector <shared_ptr <certificate> > m_certs;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_SECURITY_CERT_CERTIFICATECHAIN_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/security/cert/certificateException.cpp b/vmime-master/src/vmime/security/cert/certificateException.cpp
new file mode 100644
index 0000000..51a4f03
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateException.cpp
@@ -0,0 +1,84 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificateException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+certificateException::certificateException()
+ : exception("A problem occurred with a certificate.") {
+
+}
+
+
+certificateException::certificateException(const std::string& what)
+ : exception(what) {
+
+}
+
+
+certificateException::~certificateException() throw() {
+
+}
+
+
+exception* certificateException::clone() const {
+
+ return new certificateException(what());
+}
+
+
+void certificateException::setCertificate(const shared_ptr <certificate>& cert) {
+
+ m_cert = cert;
+}
+
+
+shared_ptr <certificate> certificateException::getCertificate() {
+
+ return m_cert;
+}
+
+
+shared_ptr <const certificate> certificateException::getCertificate() const {
+
+ return m_cert;
+}
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
diff --git a/vmime-master/src/vmime/security/cert/certificateException.hpp b/vmime-master/src/vmime/security/cert/certificateException.hpp
new file mode 100644
index 0000000..9dd5443
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateException.hpp
@@ -0,0 +1,95 @@
+//
+// 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_SECURITY_CERT_CERTIFICATEEXCEPTION_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_CERTIFICATEEXCEPTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificate.hpp"
+
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+/** Thrown to indicate a problem with a certificate or certificate verification.
+ */
+class VMIME_EXPORT certificateException : public exception {
+
+public:
+
+ /** Constructs a certificateException with no detail message.
+ */
+ certificateException();
+
+ /** Constructs a certificateException with a detail message.
+ *
+ * @param what a message that describes this exception
+ */
+ certificateException(const std::string& what);
+
+ ~certificateException() throw();
+
+ exception* clone() const;
+
+ /** Sets the certificate on which the problem occured.
+ *
+ * @param cert certificate
+ */
+ void setCertificate(const shared_ptr <certificate>& cert);
+
+ /** Returns the certificate on which the problem occured.
+ *
+ * @return certificate
+ */
+ shared_ptr <certificate> getCertificate();
+
+ /** Returns the certificate on which the problem occured.
+ *
+ * @return certificate
+ */
+ shared_ptr <const certificate> getCertificate() const;
+
+private:
+
+ shared_ptr <certificate> m_cert;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+#endif // VMIME_SECURITY_CERT_CERTIFICATEEXCEPTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/cert/certificateExpiredException.cpp b/vmime-master/src/vmime/security/cert/certificateExpiredException.cpp
new file mode 100644
index 0000000..1aa248e
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateExpiredException.cpp
@@ -0,0 +1,55 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificateExpiredException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+certificateExpiredException::certificateExpiredException()
+ : certificateException("The certificate has expired.") {
+
+}
+
+
+exception* certificateExpiredException::clone() const
+{
+ return new certificateExpiredException();
+}
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
diff --git a/vmime-master/src/vmime/security/cert/certificateExpiredException.hpp b/vmime-master/src/vmime/security/cert/certificateExpiredException.hpp
new file mode 100644
index 0000000..4db0a1e
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateExpiredException.hpp
@@ -0,0 +1,65 @@
+//
+// 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_SECURITY_CERT_CERTIFICATEEXPIREDEXCEPTION_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_CERTIFICATEEXPIREDEXCEPTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificate.hpp"
+#include "vmime/security/cert/certificateException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+/** Thrown when the current date and time is after the validity period
+ * specified in the certificate.
+ */
+class VMIME_EXPORT certificateExpiredException : public certificateException {
+
+public:
+
+ /** Constructs a certificateExpiredException with no detail message.
+ */
+ certificateExpiredException();
+
+ exception* clone() const;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+#endif // VMIME_SECURITY_CERT_CERTIFICATEEXPIREDEXCEPTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.cpp b/vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.cpp
new file mode 100644
index 0000000..adf5049
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.cpp
@@ -0,0 +1,55 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificateIssuerVerificationException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+certificateIssuerVerificationException::certificateIssuerVerificationException()
+ : certificateException("Certificate subject/issuer verification failed.") {
+
+}
+
+
+exception* certificateIssuerVerificationException::clone() const {
+
+ return new certificateIssuerVerificationException();
+}
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
diff --git a/vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.hpp b/vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.hpp
new file mode 100644
index 0000000..e22bd92
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.hpp
@@ -0,0 +1,65 @@
+//
+// 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_SECURITY_CERT_CERTIFICATEISSUERVERIFICATIONEXCEPTION_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_CERTIFICATEISSUERVERIFICATIONEXCEPTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificate.hpp"
+#include "vmime/security/cert/certificateException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+/** Thrown when a certificate in a certificate chain cannot be verified
+ * against the next certificate in the chain (the issuer).
+ */
+class VMIME_EXPORT certificateIssuerVerificationException : public certificateException {
+
+public:
+
+ /** Constructs a certificateIssuerVerificationException with no detail message.
+ */
+ certificateIssuerVerificationException();
+
+ exception* clone() const;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+#endif // VMIME_SECURITY_CERT_CERTIFICATEISSUERVERIFICATIONEXCEPTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/cert/certificateNotTrustedException.cpp b/vmime-master/src/vmime/security/cert/certificateNotTrustedException.cpp
new file mode 100644
index 0000000..a5ebb99
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateNotTrustedException.cpp
@@ -0,0 +1,55 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificateNotTrustedException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+certificateNotTrustedException::certificateNotTrustedException()
+ : certificateException("Cannot verify certificate against trusted certificates.") {
+
+}
+
+
+exception* certificateNotTrustedException::clone() const {
+
+ return new certificateNotTrustedException();
+}
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
diff --git a/vmime-master/src/vmime/security/cert/certificateNotTrustedException.hpp b/vmime-master/src/vmime/security/cert/certificateNotTrustedException.hpp
new file mode 100644
index 0000000..8cdb2f0
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateNotTrustedException.hpp
@@ -0,0 +1,65 @@
+//
+// 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_SECURITY_CERT_CERTIFICATENOTTRUSTEDEXCEPTION_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_CERTIFICATENOTTRUSTEDEXCEPTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificate.hpp"
+#include "vmime/security/cert/certificateException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+/** Thrown when a certificate cannot be verified against root and/or
+ * trusted certificates.
+ */
+class VMIME_EXPORT certificateNotTrustedException : public certificateException {
+
+public:
+
+ /** Constructs a certificateNotTrustedException with no detail message.
+ */
+ certificateNotTrustedException();
+
+ exception* clone() const;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+#endif // VMIME_SECURITY_CERT_CERTIFICATENOTTRUSTEDEXCEPTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/cert/certificateNotYetValidException.cpp b/vmime-master/src/vmime/security/cert/certificateNotYetValidException.cpp
new file mode 100644
index 0000000..ed8ca79
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateNotYetValidException.cpp
@@ -0,0 +1,55 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificateNotYetValidException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+certificateNotYetValidException::certificateNotYetValidException()
+ : certificateException("The certificate is not yet valid.") {
+
+}
+
+
+exception* certificateNotYetValidException::clone() const {
+
+ return new certificateNotYetValidException();
+}
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
diff --git a/vmime-master/src/vmime/security/cert/certificateNotYetValidException.hpp b/vmime-master/src/vmime/security/cert/certificateNotYetValidException.hpp
new file mode 100644
index 0000000..8f321eb
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateNotYetValidException.hpp
@@ -0,0 +1,65 @@
+//
+// 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_SECURITY_CERT_CERTIFICATENOTYETVALIDEXCEPTION_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_CERTIFICATENOTYETVALIDEXCEPTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificate.hpp"
+#include "vmime/security/cert/certificateException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+/** Thrown when the current date and time is before the validity period
+ * specified in the certificate.
+ */
+class VMIME_EXPORT certificateNotYetValidException : public certificateException {
+
+public:
+
+ /** Constructs a certificateNotYetValidException with no detail message.
+ */
+ certificateNotYetValidException();
+
+ exception* clone() const;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+#endif // VMIME_SECURITY_CERT_CERTIFICATENOTYETVALIDEXCEPTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/cert/certificateVerifier.hpp b/vmime-master/src/vmime/security/cert/certificateVerifier.hpp
new file mode 100644
index 0000000..7e2913a
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/certificateVerifier.hpp
@@ -0,0 +1,76 @@
+//
+// 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_SECURITY_CERT_CERTIFICATEVERIFIER_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_CERTIFICATEVERIFIER_HPP_INCLUDED
+
+
+#include "vmime/types.hpp"
+
+#include "vmime/security/cert/certificateChain.hpp"
+
+#include "vmime/security/cert/unsupportedCertificateTypeException.hpp"
+#include "vmime/security/cert/certificateIssuerVerificationException.hpp"
+#include "vmime/security/cert/certificateNotTrustedException.hpp"
+#include "vmime/security/cert/serverIdentityException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+/** Verify that a certificate path issued by a server can be trusted.
+ */
+class VMIME_EXPORT certificateVerifier : public object {
+
+public:
+
+ /** Verify that the specified certificate chain is trusted.
+ *
+ * @param chain certificate chain
+ * @param hostname server hostname
+ * @throw unsupportedCertificateTypeException if a certificate in the
+ * chain is of unsupported format
+ * @throw certificateExpiredException if a certificate in the chain
+ * has expired
+ * @throw certificateNotYetValidException if a certificate in the chain
+ * is not yet valid
+ * @throw certificateNotTrustedException if a certificate in the chain
+ * cannot be verified against root and/or trusted certificates
+ * @throw certificateIssuerVerificationException if a certificate in the
+ * chain cannot be verified against the next certificate (issuer)
+ * @throw serverIdentityException if the subject name of the certificate
+ * does not match the hostname of the server
+ */
+ virtual void verify(const shared_ptr <certificateChain>& chain, const string& hostname) = 0;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_SECURITY_CERT_CERTIFICATEVERIFIER_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/security/cert/defaultCertificateVerifier.cpp b/vmime-master/src/vmime/security/cert/defaultCertificateVerifier.cpp
new file mode 100644
index 0000000..a67052e
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/defaultCertificateVerifier.cpp
@@ -0,0 +1,191 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/defaultCertificateVerifier.hpp"
+
+#include "vmime/security/cert/X509Certificate.hpp"
+
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+defaultCertificateVerifier::defaultCertificateVerifier() {
+
+}
+
+
+defaultCertificateVerifier::~defaultCertificateVerifier() {
+
+}
+
+
+defaultCertificateVerifier::defaultCertificateVerifier(const defaultCertificateVerifier&)
+ : certificateVerifier() {
+
+ // Not used
+}
+
+
+void defaultCertificateVerifier::verify(
+ const shared_ptr <certificateChain>& chain,
+ const string& hostname
+) {
+
+ if (chain->getCount() == 0) {
+ return;
+ }
+
+ const string type = chain->getAt(0)->getType();
+
+ if (type == "X.509") {
+ verifyX509(chain, hostname);
+ } else {
+ throw unsupportedCertificateTypeException(type);
+ }
+}
+
+
+void defaultCertificateVerifier::verifyX509(
+ const shared_ptr <certificateChain>& chain,
+ const string& hostname
+) {
+
+ // For every certificate in the chain, verify that the certificate
+ // has been issued by the next certificate in the chain
+ if (chain->getCount() >= 2) {
+
+ for (size_t i = 0 ; i < chain->getCount() - 1 ; ++i) {
+
+ shared_ptr <X509Certificate> cert =
+ dynamicCast <X509Certificate>(chain->getAt(i));
+
+ shared_ptr <X509Certificate> next =
+ dynamicCast <X509Certificate>(chain->getAt(i + 1));
+
+ if (!cert->checkIssuer(next)) {
+
+ certificateIssuerVerificationException ex;
+ ex.setCertificate(cert);
+
+ throw ex;
+ }
+ }
+ }
+
+ // For every certificate in the chain, verify that the certificate
+ // is valid at the current time
+ for (size_t i = 0 ; i < chain->getCount() ; ++i) {
+
+ shared_ptr <X509Certificate> cert =
+ dynamicCast <X509Certificate>(chain->getAt(i));
+
+ cert->checkValidity();
+ }
+
+ // Check whether the certificate can be trusted
+
+ // -- First, verify that the the last certificate in the chain was
+ // -- issued by a third-party that we trust
+ shared_ptr <X509Certificate> lastCert =
+ dynamicCast <X509Certificate>(chain->getAt(chain->getCount() - 1));
+
+ bool trusted = false;
+
+ for (size_t i = 0 ; !trusted && i < m_x509RootCAs.size() ; ++i) {
+
+ shared_ptr <X509Certificate> rootCa = m_x509RootCAs[i];
+
+ // printf("rootCAs size is %d, i is %d\n", m_x509RootCAs.size(), i);
+ // printf("will cal verify with %p\n", rootCa.get());
+ if (lastCert->verify(rootCa)) {
+ trusted = true;
+ }
+ // printf("called verify");
+ }
+
+ // -- Next, if the issuer certificate cannot be verified against
+ // -- root CAs, compare the subject's certificate against the
+ // -- trusted certificates
+ shared_ptr <X509Certificate> firstCert =
+ dynamicCast <X509Certificate>(chain->getAt(0));
+
+ for (size_t i = 0 ; !trusted && i < m_x509TrustedCerts.size() ; ++i) {
+
+ shared_ptr <X509Certificate> cert = m_x509TrustedCerts[i];
+
+ if (firstCert->equals(cert)) {
+ trusted = true;
+ }
+ }
+
+ if (!trusted) {
+
+ certificateNotTrustedException ex;
+ ex.setCertificate(firstCert);
+
+ throw ex;
+ }
+
+ // Ensure the first certificate's subject name matches server hostname
+ if (!firstCert->verifyHostName(hostname)) {
+
+ serverIdentityException ex;
+ ex.setCertificate(firstCert);
+
+ throw ex;
+ }
+}
+
+
+void defaultCertificateVerifier::setX509RootCAs(
+ const std::vector <shared_ptr <X509Certificate> >& caCerts
+) {
+
+ m_x509RootCAs = caCerts;
+}
+
+
+void defaultCertificateVerifier::setX509TrustedCerts(
+ const std::vector <shared_ptr <X509Certificate> >& trustedCerts
+) {
+
+ m_x509TrustedCerts = trustedCerts;
+}
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
diff --git a/vmime-master/src/vmime/security/cert/defaultCertificateVerifier.hpp b/vmime-master/src/vmime/security/cert/defaultCertificateVerifier.hpp
new file mode 100644
index 0000000..4aa4445
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/defaultCertificateVerifier.hpp
@@ -0,0 +1,98 @@
+//
+// 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_SECURITY_CERT_DEFAULTCERTIFICATEVERIFIER_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_DEFAULTCERTIFICATEVERIFIER_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificateVerifier.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+class X509Certificate;
+
+
+/** Default implementation for certificate verification.
+ */
+class VMIME_EXPORT defaultCertificateVerifier : public certificateVerifier {
+
+private:
+
+ defaultCertificateVerifier(const defaultCertificateVerifier&);
+
+public:
+
+ defaultCertificateVerifier();
+ ~defaultCertificateVerifier();
+
+ /** Sets a list of X.509 certificates that are trusted.
+ *
+ * @param trustedCerts list of trusted certificates
+ */
+ void setX509TrustedCerts(const std::vector <shared_ptr <X509Certificate> >& trustedCerts);
+
+ /** Sets the X.509 root CAs used for certificate verification.
+ *
+ * @param caCerts list of root CAs
+ */
+ void setX509RootCAs(const std::vector <shared_ptr <X509Certificate> >& caCerts);
+
+
+ // Implementation of 'certificateVerifier'
+ void verify(const shared_ptr <certificateChain>& chain, const string& hostname);
+
+private:
+
+ /** Verify a chain of X.509 certificates.
+ *
+ * @param chain list of X.509 certificates
+ * @param hostname server hostname
+ */
+ void verifyX509(const shared_ptr <certificateChain>& chain, const string& hostname);
+
+
+ std::vector <shared_ptr <X509Certificate> > m_x509RootCAs;
+ std::vector <shared_ptr <X509Certificate> > m_x509TrustedCerts;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#endif // VMIME_SECURITY_CERT_DEFAULTCERTIFICATEVERIFIER_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp b/vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp
new file mode 100644
index 0000000..3dfa1c6
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp
@@ -0,0 +1,395 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#include <ctime>
+
+#include "vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp"
+
+#include "vmime/utility/outputStreamByteArrayAdapter.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+#ifndef VMIME_BUILDING_DOC
+
+struct GnuTLSX509CertificateInternalData {
+
+ GnuTLSX509CertificateInternalData() {
+
+ gnutls_x509_crt_init(&cert);
+ }
+
+ ~GnuTLSX509CertificateInternalData() {
+
+ gnutls_x509_crt_deinit(cert);
+ }
+
+ void swap(gnutls_x509_crt_t to) {
+ gnutls_x509_crt_deinit(cert);
+ cert = to;
+ }
+
+
+ gnutls_x509_crt_t cert;
+};
+
+#endif // VMIME_BUILDING_DOC
+
+
+X509Certificate_GnuTLS::X509Certificate_GnuTLS()
+ : m_data(new GnuTLSX509CertificateInternalData) {
+
+}
+
+
+X509Certificate_GnuTLS::X509Certificate_GnuTLS(const X509Certificate&)
+ : X509Certificate(), m_data(NULL) {
+
+ // Not used
+}
+
+
+X509Certificate_GnuTLS::~X509Certificate_GnuTLS() {
+
+ delete m_data;
+}
+
+
+void* X509Certificate_GnuTLS::getInternalData() {
+
+ return &m_data->cert;
+}
+
+
+// static
+shared_ptr <X509Certificate> X509Certificate::import(
+ utility::inputStream& is
+) {
+
+ byteArray bytes;
+ byte_t chunk[4096];
+
+ while (!is.eof()) {
+ const size_t len = is.read(chunk, sizeof(chunk));
+ bytes.insert(bytes.end(), chunk, chunk + len);
+ }
+
+ return import(&bytes[0], bytes.size());
+}
+
+
+// static
+shared_ptr <X509Certificate> X509Certificate::import(
+ const byte_t* data,
+ const size_t length
+) {
+
+ gnutls_datum_t buffer;
+ buffer.data = const_cast <byte_t*>(data);
+ buffer.size = static_cast <unsigned int>(length);
+
+ // Try DER format
+ shared_ptr <X509Certificate_GnuTLS> derCert = make_shared <X509Certificate_GnuTLS>();
+
+ if (gnutls_x509_crt_import(derCert->m_data->cert, &buffer, GNUTLS_X509_FMT_DER) >= 0) {
+ return derCert;
+ }
+
+ // Try PEM format
+ shared_ptr <X509Certificate_GnuTLS> pemCert = make_shared <X509Certificate_GnuTLS>();
+
+ if (gnutls_x509_crt_import(pemCert->m_data->cert, &buffer, GNUTLS_X509_FMT_PEM) >= 0) {
+ return pemCert;
+ }
+
+ return null;
+}
+
+
+// static
+void X509Certificate::import(
+ utility::inputStream& is,
+ std::vector <shared_ptr <X509Certificate> >& certs
+) {
+
+ byteArray bytes;
+ byte_t chunk[4096];
+
+ while (!is.eof()) {
+ const size_t len = is.read(chunk, sizeof(chunk));
+ bytes.insert(bytes.end(), chunk, chunk + len);
+ }
+
+ import(&bytes[0], bytes.size(), certs);
+}
+
+
+// static
+void X509Certificate::import(
+ const byte_t* data,
+ const size_t length,
+ std::vector <shared_ptr <X509Certificate> >& certs
+) {
+
+ gnutls_datum_t buffer;
+ buffer.data = const_cast <byte_t*>(data);
+ buffer.size = static_cast <unsigned int>(length);
+
+ unsigned int size = 1024;
+ gnutls_x509_crt_t x509[1024];
+
+ // Try DER format
+ if (gnutls_x509_crt_list_import(x509, &size, &buffer, GNUTLS_X509_FMT_DER, 0) < 0) {
+
+ // Try PEM format
+ if (gnutls_x509_crt_list_import(x509, &size, &buffer, GNUTLS_X509_FMT_PEM, 0) < 0) {
+ return;
+ }
+ }
+
+ for (unsigned int i = 0 ; i < size ; i += 1) {
+
+ auto c = make_shared <X509Certificate_GnuTLS>();
+ c->m_data->swap(x509[i]);
+ certs.push_back(c);
+ }
+}
+
+
+void X509Certificate_GnuTLS::write(
+ utility::outputStream& os,
+ const Format format
+) const {
+
+ size_t dataSize = 0;
+ gnutls_x509_crt_fmt_t fmt = GNUTLS_X509_FMT_DER;
+
+ switch (format) {
+ case FORMAT_DER: fmt = GNUTLS_X509_FMT_DER; break;
+ case FORMAT_PEM: fmt = GNUTLS_X509_FMT_PEM; break;
+ }
+
+ gnutls_x509_crt_export(m_data->cert, fmt, NULL, &dataSize);
+
+ std::vector <byte_t> data(dataSize);
+
+ gnutls_x509_crt_export(m_data->cert, fmt, &data[0], &dataSize);
+
+ os.write(reinterpret_cast <byte_t*>(&data[0]), dataSize);
+}
+
+
+const byteArray X509Certificate_GnuTLS::getSerialNumber() const {
+
+ char serial[64];
+ size_t serialSize = sizeof(serial);
+
+ gnutls_x509_crt_get_serial(m_data->cert, serial, &serialSize);
+
+ return byteArray(serial, serial + serialSize);
+}
+
+
+bool X509Certificate_GnuTLS::checkIssuer(const shared_ptr <const X509Certificate>& issuer_) const {
+
+ shared_ptr <const X509Certificate_GnuTLS> issuer =
+ dynamicCast <const X509Certificate_GnuTLS>(issuer_);
+
+ return gnutls_x509_crt_check_issuer(m_data->cert, issuer->m_data->cert) >= 1;
+}
+
+
+bool X509Certificate_GnuTLS::verify(const shared_ptr <const X509Certificate>& caCert_) const {
+
+ shared_ptr <const X509Certificate_GnuTLS> caCert =
+ dynamicCast <const X509Certificate_GnuTLS>(caCert_);
+
+ unsigned int verify = 0;
+
+ const int res = gnutls_x509_crt_verify(
+ m_data->cert, &(caCert->m_data->cert), 1,
+ GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT,
+ &verify
+ );
+
+ return res == 0 && verify == 0;
+}
+
+
+bool X509Certificate_GnuTLS::verifyHostName(
+ const string& hostname,
+ std::vector <std::string>* nonMatchingNames
+) const {
+
+ if (gnutls_x509_crt_check_hostname(m_data->cert, hostname.c_str()) != 0) {
+ return true;
+ }
+
+ if (nonMatchingNames) {
+
+ const int MAX_CN = 256;
+ const char* OID_X520_COMMON_NAME = "2.5.4.3";
+
+ char dnsName[MAX_CN];
+ size_t dnsNameLength;
+
+ dnsNameLength = sizeof(dnsName);
+
+ if (gnutls_x509_crt_get_dn_by_oid(m_data->cert, OID_X520_COMMON_NAME, 0, 0, dnsName, &dnsNameLength) >= 0) {
+ nonMatchingNames->push_back(dnsName);
+ }
+
+ for (int i = 0, ret = 0 ; ret >= 0 ; ++i) {
+
+ dnsNameLength = sizeof(dnsName);
+ ret = gnutls_x509_crt_get_subject_alt_name(m_data->cert, i, dnsName, &dnsNameLength, NULL);
+
+ if (ret == GNUTLS_SAN_DNSNAME) {
+ nonMatchingNames->push_back(dnsName);
+ }
+ }
+ }
+
+ return false;
+}
+
+
+const datetime X509Certificate_GnuTLS::getActivationDate() const {
+
+ const time_t t = gnutls_x509_crt_get_activation_time(m_data->cert);
+ return datetime(t);
+}
+
+
+const datetime X509Certificate_GnuTLS::getExpirationDate() const {
+
+ const time_t t = gnutls_x509_crt_get_expiration_time(m_data->cert);
+ return datetime(t);
+}
+
+
+const byteArray X509Certificate_GnuTLS::getFingerprint(const DigestAlgorithm algo) const {
+
+ gnutls_digest_algorithm_t galgo;
+
+ switch (algo) {
+
+ case DIGEST_MD5:
+
+ galgo = GNUTLS_DIG_MD5;
+ break;
+
+ default:
+ case DIGEST_SHA1:
+
+ galgo = GNUTLS_DIG_SHA;
+ break;
+ }
+
+ size_t bufferSize = 0;
+ gnutls_x509_crt_get_fingerprint(m_data->cert, galgo, NULL, &bufferSize);
+
+ std::vector <byte_t> buffer(bufferSize);
+
+ if (gnutls_x509_crt_get_fingerprint(m_data->cert, galgo, &buffer[0], &bufferSize) == 0) {
+
+ byteArray res;
+ res.insert(res.end(), &buffer[0], &buffer[0] + bufferSize);
+
+ return res;
+ }
+
+ return byteArray();
+}
+
+
+const byteArray X509Certificate_GnuTLS::getEncoded() const {
+
+ byteArray bytes;
+ utility::outputStreamByteArrayAdapter os(bytes);
+
+ write(os, FORMAT_DER);
+
+ return bytes;
+}
+
+
+const string X509Certificate_GnuTLS::getIssuerString() const {
+
+ char buffer[4096];
+ size_t bufferSize = sizeof(buffer);
+
+ if (gnutls_x509_crt_get_issuer_dn(m_data->cert, buffer, &bufferSize) != GNUTLS_E_SUCCESS) {
+ return "";
+ }
+
+ return buffer;
+}
+
+
+const string X509Certificate_GnuTLS::getType() const {
+
+ return "X.509";
+}
+
+
+int X509Certificate_GnuTLS::getVersion() const {
+
+ return gnutls_x509_crt_get_version(m_data->cert);
+}
+
+
+bool X509Certificate_GnuTLS::equals(const shared_ptr <const certificate>& other) const {
+
+ shared_ptr <const X509Certificate_GnuTLS> otherX509 =
+ dynamicCast <const X509Certificate_GnuTLS>(other);
+
+ if (!otherX509) {
+ return false;
+ }
+
+ const byteArray fp1 = getFingerprint(DIGEST_MD5);
+ const byteArray fp2 = otherX509->getFingerprint(DIGEST_MD5);
+
+ return fp1 == fp2;
+}
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
diff --git a/vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp b/vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp
new file mode 100644
index 0000000..c7c6c48
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp
@@ -0,0 +1,96 @@
+//
+// 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_SECURITY_CERT_X509CERTIFICATE_GNUTLS_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_X509CERTIFICATE_GNUTLS_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+
+#include "vmime/security/cert/X509Certificate.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+class X509Certificate_GnuTLS : public X509Certificate {
+
+ friend class X509Certificate;
+
+ X509Certificate_GnuTLS(const X509Certificate&);
+
+public:
+
+ X509Certificate_GnuTLS();
+
+ ~X509Certificate_GnuTLS();
+
+
+ void write(utility::outputStream& os, const Format format) const;
+
+ const byteArray getSerialNumber() const;
+
+ const string getIssuerString() const;
+ bool checkIssuer(const shared_ptr <const X509Certificate>& issuer) const;
+
+ bool verify(const shared_ptr <const X509Certificate>& caCert) const;
+
+ bool verifyHostName(
+ const string& hostname,
+ std::vector <std::string>* nonMatchingNames = NULL
+ ) const;
+
+ const datetime getExpirationDate() const;
+ const datetime getActivationDate() const;
+
+ const byteArray getFingerprint(const DigestAlgorithm algo) const;
+
+
+ // Implementation of 'certificate'
+ const byteArray getEncoded() const;
+ const string getType() const;
+ int getVersion() const;
+ bool equals(const shared_ptr <const certificate>& other) const;
+ void* getInternalData();
+
+private:
+
+ struct GnuTLSX509CertificateInternalData* m_data;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS
+
+#endif // VMIME_SECURITY_CERT_X509CERTIFICATE_GNUTLS_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp b/vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp
new file mode 100644
index 0000000..5488801
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp
@@ -0,0 +1,655 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+
+#include <cstdio>
+#include <ctime>
+#include <map>
+#include <algorithm>
+
+#include "vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp"
+
+#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp"
+
+#include "vmime/utility/outputStreamByteArrayAdapter.hpp"
+
+#include "vmime/security/cert/certificateException.hpp"
+#include "vmime/security/cert/unsupportedCertificateTypeException.hpp"
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/conf.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+
+
+#ifdef _WIN32
+# define strcasecmp _stricmp
+# define strncasecmp _strnicmp
+#endif
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+static net::tls::OpenSSLInitializer::autoInitializer openSSLInitializer;
+
+
+#ifndef VMIME_BUILDING_DOC
+
+class monthMap {
+
+public:
+
+ monthMap() {
+
+ m_monthMap["jan"] = vmime::datetime::JAN;
+ m_monthMap["feb"] = vmime::datetime::FEB;
+ m_monthMap["mar"] = vmime::datetime::MAR;
+ m_monthMap["apr"] = vmime::datetime::APR;
+ m_monthMap["may"] = vmime::datetime::MAY;
+ m_monthMap["jun"] = vmime::datetime::JUN;
+ m_monthMap["jul"] = vmime::datetime::JUL;
+ m_monthMap["aug"] = vmime::datetime::AUG;
+ m_monthMap["sep"] = vmime::datetime::SEP;
+ m_monthMap["oct"] = vmime::datetime::OCT;
+ m_monthMap["nov"] = vmime::datetime::NOV;
+ m_monthMap["dec"] = vmime::datetime::DEC;
+ }
+
+ int getMonth(vmime::string mstr) {
+
+ std::transform(mstr.begin(), mstr.end(), mstr.begin(), ::tolower);
+
+ std::map <vmime::string, vmime::datetime::Months>::const_iterator
+ c_it = m_monthMap.find(mstr);
+
+ if (c_it != m_monthMap.end()) {
+ return c_it->second;
+ }
+
+ return -1;
+ }
+
+private:
+
+ std::map<vmime::string, vmime::datetime::Months> m_monthMap;
+};
+
+static monthMap sg_monthMap;
+
+
+
+struct OpenSSLX509CertificateInternalData {
+
+ OpenSSLX509CertificateInternalData() {
+
+ cert = 0;
+ }
+
+ ~OpenSSLX509CertificateInternalData() {
+
+ if (cert) {
+ X509_free(cert);
+ }
+ }
+
+ X509* cert;
+};
+
+
+// Workaround for i2v() taking either a const or a non-const 'method' on some platforms
+STACK_OF(CONF_VALUE)* call_i2v(const X509V3_EXT_METHOD* m, void* p1, STACK_OF(CONF_VALUE)* p2) {
+
+ return m->i2v(m, p1, p2);
+}
+
+
+STACK_OF(CONF_VALUE)* call_i2v(X509V3_EXT_METHOD* m, void* p1, STACK_OF(CONF_VALUE)* p2) {
+
+ return m->i2v(m, p1, p2);
+}
+
+
+#endif // VMIME_BUILDING_DOC
+
+
+X509Certificate_OpenSSL::X509Certificate_OpenSSL()
+ : m_data(new OpenSSLX509CertificateInternalData) {
+
+}
+
+
+X509Certificate_OpenSSL::X509Certificate_OpenSSL(X509* cert)
+ : m_data(new OpenSSLX509CertificateInternalData) {
+
+ m_data->cert = X509_dup(cert);
+}
+
+
+X509Certificate_OpenSSL::X509Certificate_OpenSSL(const X509Certificate_OpenSSL&)
+ : X509Certificate(), m_data(NULL) {
+
+ // Not used
+}
+
+
+X509Certificate_OpenSSL::~X509Certificate_OpenSSL() {
+
+ delete m_data;
+}
+
+
+void* X509Certificate_OpenSSL::getInternalData() {
+
+ return &m_data->cert;
+}
+
+
+// static
+shared_ptr <X509Certificate> X509Certificate_OpenSSL::importInternal(X509* cert) {
+
+ if (cert) {
+ return make_shared <X509Certificate_OpenSSL>(reinterpret_cast <X509 *>(cert));
+ }
+
+ return null;
+}
+
+
+// static
+shared_ptr <X509Certificate> X509Certificate::import(utility::inputStream& is) {
+
+ byteArray bytes;
+ byte_t chunk[4096];
+
+ while (!is.eof()) {
+ const size_t len = is.read(chunk, sizeof(chunk));
+ bytes.insert(bytes.end(), chunk, chunk + len);
+ }
+
+ return import(&bytes[0], bytes.size());
+}
+
+
+// static
+shared_ptr <X509Certificate> X509Certificate::import(
+ const byte_t* data,
+ const size_t length
+) {
+
+ shared_ptr <X509Certificate_OpenSSL> cert = make_shared <X509Certificate_OpenSSL>();
+
+ BIO* membio = BIO_new_mem_buf(const_cast <byte_t*>(data), static_cast <int>(length));
+
+ if (!(cert->m_data->cert = d2i_X509_bio(membio, NULL))
+ /*!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0)*/) {
+ BIO_vfree(membio);
+ return null;
+ }
+
+ BIO_vfree(membio);
+
+ return cert;
+}
+
+
+// static
+void X509Certificate::import(
+ utility::inputStream& is,
+ std::vector <shared_ptr <X509Certificate> >& certs
+) {
+
+ byteArray bytes;
+ byte_t chunk[4096];
+
+ while (!is.eof()) {
+ const size_t len = is.read(chunk, sizeof(chunk));
+ bytes.insert(bytes.end(), chunk, chunk + len);
+ }
+
+ import(&bytes[0], bytes.size(), certs);
+}
+
+
+// static
+void X509Certificate::import(
+ const byte_t* data,
+ const size_t length,
+ std::vector <shared_ptr <X509Certificate> >& certs
+) {
+
+ BIO* membio = BIO_new_mem_buf(const_cast <byte_t*>(data), static_cast <int>(length));
+ shared_ptr <X509Certificate_OpenSSL> cert = null;
+
+ while (true) {
+
+ cert = make_shared <X509Certificate_OpenSSL>();
+
+ if (!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0)) {
+ break;
+ }
+
+ certs.push_back(cert);
+ }
+
+ BIO_vfree(membio);
+}
+
+
+void X509Certificate_OpenSSL::write(
+ utility::outputStream& os,
+ const Format format
+) const {
+
+ BIO* membio = 0;
+ long dataSize = 0;
+ unsigned char* out = 0;
+
+ if (format == FORMAT_DER) {
+
+ if ((dataSize = i2d_X509(m_data->cert, &out)) < 0) {
+ goto err;
+ }
+
+ os.write(reinterpret_cast <byte_t*>(out), dataSize);
+ os.flush();
+ OPENSSL_free(out);
+
+ } else if (format == FORMAT_PEM) {
+
+ membio = BIO_new(BIO_s_mem());
+ BIO_set_close(membio, BIO_CLOSE);
+
+ if (!PEM_write_bio_X509(membio, m_data->cert)) {
+ goto pem_err;
+ }
+
+ dataSize = BIO_get_mem_data(membio, &out);
+ os.write(reinterpret_cast <byte_t*>(out), dataSize);
+ os.flush();
+ BIO_vfree(membio);
+
+ } else {
+
+ throw unsupportedCertificateTypeException("Unknown format");
+ }
+
+ return; // #### Early Return ####
+
+pem_err:
+ {
+ if (membio) {
+ BIO_vfree(membio);
+ }
+ }
+
+err:
+ {
+ char errstr[256];
+ long ec = ERR_get_error();
+ ERR_error_string(ec, errstr);
+ throw certificateException("OpenSSLX509Certificate_OpenSSL::write exception - " + string(errstr));
+ }
+}
+
+
+const byteArray X509Certificate_OpenSSL::getSerialNumber() const {
+
+ ASN1_INTEGER *serial = X509_get_serialNumber(m_data->cert);
+ BIGNUM *bnser = ASN1_INTEGER_to_BN(serial, NULL);
+ int n = BN_num_bytes(bnser);
+ byte_t* outbuf = new byte_t[n];
+ BN_bn2bin(bnser, outbuf);
+ byteArray ser(outbuf, outbuf + n);
+ delete [] outbuf;
+ BN_free(bnser);
+ return ser;
+}
+
+
+bool X509Certificate_OpenSSL::checkIssuer(const shared_ptr <const X509Certificate>& cert_) const {
+
+ shared_ptr <const X509Certificate_OpenSSL> cert =
+ dynamicCast <const X509Certificate_OpenSSL>(cert_);
+
+ // Get issuer for this cert
+ BIO *out;
+ unsigned char *issuer;
+
+ out = BIO_new(BIO_s_mem());
+ X509_NAME_print_ex(out, X509_get_issuer_name(m_data->cert), 0, XN_FLAG_RFC2253);
+ long n = BIO_get_mem_data(out, &issuer);
+ vmime::string thisIssuerName((char*)issuer, n);
+ BIO_free(out);
+
+ // Get subject of issuer
+ unsigned char *subject;
+ out = BIO_new(BIO_s_mem());
+ X509_NAME_print_ex(out, X509_get_subject_name(cert->m_data->cert), 0, XN_FLAG_RFC2253);
+ n = BIO_get_mem_data(out, &subject);
+ vmime::string subjOfIssuer((char*)subject, n);
+ BIO_free(out);
+
+ return subjOfIssuer == thisIssuerName;
+}
+
+
+bool X509Certificate_OpenSSL::verify(const shared_ptr <const X509Certificate>& caCert_) const {
+
+ shared_ptr <const X509Certificate_OpenSSL> caCert =
+ dynamicCast <const X509Certificate_OpenSSL>(caCert_);
+
+// printf("ptr before cast is %p\n", caCert_.get());
+// printf("ptr is %p\n", caCert.get());
+
+ bool verified = false;
+ bool error = true;
+
+ X509_STORE *store = X509_STORE_new();
+
+ if (store) {
+
+ X509_STORE_CTX *verifyCtx = X509_STORE_CTX_new();
+
+ if (verifyCtx) {
+
+ if (X509_STORE_add_cert(store, caCert->m_data->cert)) {
+
+ X509_STORE_CTX_init(verifyCtx, store, m_data->cert, NULL);
+
+ int ret = X509_verify_cert(verifyCtx);
+
+ if (ret == 1) {
+
+ verified = true;
+ error = false;
+
+ } else if (ret == 0) {
+
+ verified = false;
+ error = false;
+ }
+
+ //X509_verify_cert_error_string(vrfy_ctx->error)
+
+ X509_STORE_CTX_free(verifyCtx);
+ }
+ }
+
+ X509_STORE_free(store);
+ }
+
+ return verified && !error;
+}
+
+
+// static
+bool X509Certificate_OpenSSL::cnMatch(const char* cnBuf, const char* host) {
+
+ // Right-to-left match, looking for a '*' wildcard
+ const bool hasWildcard = (strlen(cnBuf) > 1 && cnBuf[0] == '*' && cnBuf[1] == '.');
+ const char* cnBufReverseEndPtr = (cnBuf + (hasWildcard ? 2 : 0));
+ const char* hostPtr = host + strlen(host);
+ const char* cnPtr = cnBuf + strlen(cnBuf);
+
+ bool matches = true;
+
+ while (matches && --hostPtr >= host && --cnPtr >= cnBufReverseEndPtr) {
+ matches = (toupper(*hostPtr) == toupper(*cnPtr));
+ }
+
+ return matches;
+}
+
+
+bool X509Certificate_OpenSSL::verifyHostName(
+ const string& hostname,
+ std::vector <std::string>* nonMatchingNames
+) const {
+
+ // First, check subject common name against hostname
+ char CNBuffer[1024];
+ CNBuffer[sizeof(CNBuffer) - 1] = '\0';
+
+ X509_NAME* xname = X509_get_subject_name(m_data->cert);
+
+ if (X509_NAME_get_text_by_NID(xname, NID_commonName, CNBuffer, sizeof(CNBuffer)) != -1) {
+
+ if (cnMatch(CNBuffer, hostname.c_str())) {
+ return true;
+ }
+
+ if (nonMatchingNames) {
+ nonMatchingNames->push_back(CNBuffer);
+ }
+ }
+
+ // Now, look in subject alternative names
+ bool verify = false;
+
+ STACK_OF(GENERAL_NAME)* altNames = static_cast <GENERAL_NAMES*>
+ (X509_get_ext_d2i(m_data->cert, NID_subject_alt_name, NULL, NULL));
+
+ if (altNames == NULL) {
+ return false;
+ }
+
+ // Check each name within the extension
+ for (int i = 0, n = sk_GENERAL_NAME_num(altNames) ; i < n ; ++i) {
+
+ const GENERAL_NAME* currentName = sk_GENERAL_NAME_value(altNames, i);
+
+ if (currentName->type == GEN_DNS) {
+
+ // Current name is a DNS name, let's check it
+ char *DNSName = (char *) ASN1_STRING_data(currentName->d.dNSName);
+
+ // Make sure there isn't an embedded NUL character in the DNS name
+ if (ASN1_STRING_length(currentName->d.dNSName) != strlen(DNSName)) {
+ // Malformed certificate
+ break;
+ }
+
+ if (cnMatch(DNSName, hostname.c_str())) {
+ verify = true;
+ break;
+ }
+
+ if (nonMatchingNames) {
+ nonMatchingNames->push_back(DNSName);
+ }
+ }
+ }
+
+ sk_GENERAL_NAME_pop_free(altNames, GENERAL_NAME_free);
+
+ return verify;
+}
+
+
+const datetime X509Certificate_OpenSSL::convertX509Date(void* time) const {
+
+ char* buffer;
+ BIO* out = BIO_new(BIO_s_mem());
+ BIO_set_close(out, BIO_CLOSE);
+
+ ASN1_TIME* asn1_time = reinterpret_cast<ASN1_TIME*>(time);
+ ASN1_TIME_print(out, asn1_time);
+
+ const long sz = BIO_get_mem_data(out, &buffer);
+ char* dest = new char[sz + 1];
+ dest[sz] = 0;
+ memcpy(dest, buffer, sz);
+ vmime::string t(dest);
+
+ BIO_free(out);
+ delete [] dest;
+
+ if (t.size() > 0) {
+
+ char month[4] = {0};
+ char zone[4] = {0};
+ int day, hour, minute, second, year;
+ int nrconv = sscanf(t.c_str(), "%s %2d %02d:%02d:%02d %d%s", month, &day, &hour, &minute, &second,&year,zone);
+
+ if (nrconv >= 6) {
+ return datetime(year, sg_monthMap.getMonth(vmime::string(month)), day, hour, minute, second);
+ }
+ }
+
+ // let datetime try and parse it
+ return datetime(t);
+}
+
+
+const datetime X509Certificate_OpenSSL::getActivationDate() const {
+
+ return convertX509Date(X509_get_notBefore(m_data->cert));
+}
+
+
+const datetime X509Certificate_OpenSSL::getExpirationDate() const {
+
+ return convertX509Date(X509_get_notAfter(m_data->cert));
+}
+
+
+const byteArray X509Certificate_OpenSSL::getFingerprint(const DigestAlgorithm algo) const {
+
+ BIO *out;
+ int j;
+ unsigned int n;
+ const EVP_MD *digest;
+ unsigned char * fingerprint;
+ unsigned char md[EVP_MAX_MD_SIZE];
+
+ switch (algo) {
+
+ case DIGEST_MD5:
+
+ digest = EVP_md5();
+ break;
+
+ default:
+ case DIGEST_SHA1:
+
+ digest = EVP_sha1();
+ break;
+ }
+
+ out = BIO_new(BIO_s_mem());
+ BIO_set_close(out, BIO_CLOSE);
+
+ if (X509_digest(m_data->cert, digest, md, &n)) {
+
+ for (j = 0 ; j < (int) n ; j++) {
+ BIO_printf(out, "%02X", md[j]);
+ if (j + 1 != (int) n) BIO_printf(out, ":");
+ }
+ }
+
+ const long resultLen = BIO_get_mem_data(out, &fingerprint);
+ unsigned char* result = new unsigned char[resultLen];
+ memcpy(result, fingerprint, resultLen);
+ BIO_free(out);
+
+ byteArray res;
+ res.insert(res.end(), &result[0], &result[0] + resultLen);
+
+ delete [] result;
+
+ return res;
+}
+
+
+const byteArray X509Certificate_OpenSSL::getEncoded() const {
+
+ byteArray bytes;
+ utility::outputStreamByteArrayAdapter os(bytes);
+
+ write(os, FORMAT_DER);
+
+ return bytes;
+}
+
+
+const string X509Certificate_OpenSSL::getIssuerString() const {
+
+ // Get issuer for this cert
+ BIO* out = BIO_new(BIO_s_mem());
+ X509_NAME_print_ex(out, X509_get_issuer_name(m_data->cert), 0, XN_FLAG_RFC2253);
+
+ unsigned char* issuer;
+ const long n = BIO_get_mem_data(out, &issuer);
+
+ vmime::string name(reinterpret_cast <char*>(issuer), n);
+ BIO_free(out);
+
+ return name;
+}
+
+
+const string X509Certificate_OpenSSL::getType() const {
+
+ return "X.509";
+}
+
+
+int X509Certificate_OpenSSL::getVersion() const {
+
+ return (int) X509_get_version(m_data->cert);
+}
+
+
+bool X509Certificate_OpenSSL::equals(const shared_ptr <const certificate>& other) const {
+
+ shared_ptr <const X509Certificate_OpenSSL> otherX509 =
+ dynamicCast <const X509Certificate_OpenSSL>(other);
+
+ if (!otherX509) {
+ return false;
+ }
+
+ const byteArray fp1 = getFingerprint(DIGEST_MD5);
+ const byteArray fp2 = otherX509->getFingerprint(DIGEST_MD5);
+
+ return fp1 == fp2;
+}
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
diff --git a/vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp b/vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp
new file mode 100644
index 0000000..c0ebf3c
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp
@@ -0,0 +1,119 @@
+//
+// 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_SECURITY_CERT_X509CERTIFICATE_OPENSSL_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_X509CERTIFICATE_OPENSSL_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+
+#include "vmime/security/cert/X509Certificate.hpp"
+
+#include <openssl/x509.h>
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+class X509Certificate_OpenSSL : public X509Certificate {
+
+ friend class X509Certificate;
+
+ X509Certificate_OpenSSL(const X509Certificate_OpenSSL&);
+
+public:
+
+ X509Certificate_OpenSSL();
+ X509Certificate_OpenSSL(X509* cert);
+
+ ~X509Certificate_OpenSSL();
+
+
+ void write(utility::outputStream& os, const Format format) const;
+
+ const byteArray getSerialNumber() const;
+
+ const string getIssuerString() const;
+ bool checkIssuer(const shared_ptr <const X509Certificate>& issuer) const;
+
+ bool verify(const shared_ptr <const X509Certificate>& caCert) const;
+
+ bool verifyHostName(
+ const string& hostname,
+ std::vector <std::string>* nonMatchingNames = NULL
+ ) const;
+
+ const datetime getExpirationDate() const;
+ const datetime getActivationDate() const;
+
+ const byteArray getFingerprint(const DigestAlgorithm algo) const;
+
+
+ static shared_ptr <X509Certificate> importInternal(X509* cert);
+
+
+ // Implementation of 'certificate'
+ const byteArray getEncoded() const;
+ const string getType() const;
+ int getVersion() const;
+ bool equals(const shared_ptr <const certificate>& other) const;
+ void* getInternalData();
+
+private:
+
+ /** Internal utility function to test whether a hostname matches
+ * the specified X509 Common Name (wildcard is supported).
+ *
+ * @param cnBuf pointer to buffer holding Common Name
+ * @param host pointer to buffer holding host name
+ * @return true if the hostname matches the Common Name, or
+ * false otherwise
+ */
+ static bool cnMatch(const char* cnBuf, const char* host);
+
+ /** Internal utility function to convert ASN1_TIME
+ * structs to vmime::datetime
+ *
+ * @param pointer to ASN1_TIME struct to convert
+ */
+ const datetime convertX509Date(void* time) const;
+
+ struct OpenSSLX509CertificateInternalData* m_data;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL
+
+#endif // VMIME_SECURITY_CERT_X509CERTIFICATE_OPENSSL_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/security/cert/serverIdentityException.cpp b/vmime-master/src/vmime/security/cert/serverIdentityException.cpp
new file mode 100644
index 0000000..fcbe571
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/serverIdentityException.cpp
@@ -0,0 +1,55 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/serverIdentityException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+serverIdentityException::serverIdentityException()
+ : certificateException("Server identity cannot be verified.") {
+
+}
+
+
+exception* serverIdentityException::clone() const {
+
+ return new serverIdentityException();
+}
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
diff --git a/vmime-master/src/vmime/security/cert/serverIdentityException.hpp b/vmime-master/src/vmime/security/cert/serverIdentityException.hpp
new file mode 100644
index 0000000..358553e
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/serverIdentityException.hpp
@@ -0,0 +1,65 @@
+//
+// 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_SECURITY_CERT_SERVERIDENTITYEXCEPTION_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_SERVERIDENTITYEXCEPTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificate.hpp"
+#include "vmime/security/cert/certificateException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+/** Thrown when the subject name of a certificate does not match
+ * the hostname of the server.
+ */
+class VMIME_EXPORT serverIdentityException : public certificateException {
+
+public:
+
+ /** Constructs a serverIdentityException with no detail message.
+ */
+ serverIdentityException();
+
+ exception* clone() const;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+#endif // VMIME_SECURITY_CERT_SERVERIDENTITYEXCEPTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.cpp b/vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.cpp
new file mode 100644
index 0000000..5765651
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.cpp
@@ -0,0 +1,61 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/unsupportedCertificateTypeException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+unsupportedCertificateTypeException::unsupportedCertificateTypeException(const string& type)
+ : certificateException(string("Unsupported certificate type: '") + type + "'."),
+ m_type(type) {
+
+}
+
+
+unsupportedCertificateTypeException::~unsupportedCertificateTypeException() throw() {
+
+}
+
+
+exception* unsupportedCertificateTypeException::clone() const {
+
+ return new unsupportedCertificateTypeException(m_type);
+}
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
diff --git a/vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.hpp b/vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.hpp
new file mode 100644
index 0000000..725035f
--- /dev/null
+++ b/vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.hpp
@@ -0,0 +1,72 @@
+//
+// 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_SECURITY_CERT_UNSUPPORTEDCERTIFICATETYPEEXCEPTION_HPP_INCLUDED
+#define VMIME_SECURITY_CERT_UNSUPPORTEDCERTIFICATETYPEEXCEPTION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+
+#include "vmime/security/cert/certificate.hpp"
+#include "vmime/security/cert/certificateException.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+/** Thrown when a certificate is of unsupported format.
+ */
+class VMIME_EXPORT unsupportedCertificateTypeException : public certificateException {
+
+public:
+
+ /** Constructs a unsupportedCertificateTypeException.
+ *
+ * @param type certificate type
+ */
+ unsupportedCertificateTypeException(const string& type);
+
+ ~unsupportedCertificateTypeException() throw();
+
+ exception* clone() const;
+
+private:
+
+ string m_type;
+};
+
+
+} // cert
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
+#endif // VMIME_SECURITY_CERT_UNSUPPORTEDCERTIFICATETYPEEXCEPTION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/defaultAuthenticator.cpp b/vmime-master/src/vmime/security/defaultAuthenticator.cpp
new file mode 100644
index 0000000..86c29d3
--- /dev/null
+++ b/vmime-master/src/vmime/security/defaultAuthenticator.cpp
@@ -0,0 +1,130 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+#include "vmime/security/defaultAuthenticator.hpp"
+
+#include "vmime/net/service.hpp"
+
+#include "vmime/platform.hpp"
+
+
+namespace vmime {
+namespace security {
+
+
+defaultAuthenticator::defaultAuthenticator() {
+
+}
+
+
+defaultAuthenticator::~defaultAuthenticator() {
+
+}
+
+
+const string defaultAuthenticator::getUsername() const {
+
+ shared_ptr <const net::service> service = m_service.lock();
+
+ const string prefix = service->getInfos().getPropertyPrefix();
+ const propertySet& props = service->getSession()->getProperties();
+
+ if (props.hasProperty(prefix + net::serviceInfos::property::AUTH_USERNAME.getName())) {
+ return props[prefix + net::serviceInfos::property::AUTH_USERNAME.getName()];
+ }
+
+ throw exceptions::no_auth_information();
+}
+
+
+const string defaultAuthenticator::getPassword() const {
+
+ shared_ptr <const net::service> service = m_service.lock();
+
+ const string prefix = service->getInfos().getPropertyPrefix();
+ const propertySet& props = service->getSession()->getProperties();
+
+ if (props.hasProperty(prefix + net::serviceInfos::property::AUTH_PASSWORD.getName())) {
+ return props[prefix + net::serviceInfos::property::AUTH_PASSWORD.getName()];
+ }
+
+ throw exceptions::no_auth_information();
+}
+
+
+const string defaultAuthenticator::getAccessToken() const {
+
+ shared_ptr <const net::service> service = m_service.lock();
+
+ const string prefix = service->getInfos().getPropertyPrefix();
+ const propertySet& props = service->getSession()->getProperties();
+
+ if (props.hasProperty(prefix + net::serviceInfos::property::AUTH_ACCESS_TOKEN.getName())) {
+ return props[prefix + net::serviceInfos::property::AUTH_ACCESS_TOKEN.getName()];
+ }
+
+ throw exceptions::no_auth_information();
+}
+
+
+const string defaultAuthenticator::getHostname() const {
+
+ return platform::getHandler()->getHostName();
+}
+
+
+const string defaultAuthenticator::getAnonymousToken() const {
+
+ return "anonymous@" + platform::getHandler()->getHostName();
+}
+
+
+const string defaultAuthenticator::getServiceName() const {
+
+ // Information cannot be provided
+ throw exceptions::no_auth_information();
+}
+
+
+void defaultAuthenticator::setService(const shared_ptr <net::service>& serv) {
+
+ m_service = serv;
+}
+
+
+weak_ptr <net::service> defaultAuthenticator::getService() const {
+
+ return m_service;
+}
+
+
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
diff --git a/vmime-master/src/vmime/security/defaultAuthenticator.hpp b/vmime-master/src/vmime/security/defaultAuthenticator.hpp
new file mode 100644
index 0000000..e053f9e
--- /dev/null
+++ b/vmime-master/src/vmime/security/defaultAuthenticator.hpp
@@ -0,0 +1,73 @@
+//
+// 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_SECURITY_DEFAULTAUTHENTICATOR_HPP_INCLUDED
+#define VMIME_SECURITY_DEFAULTAUTHENTICATOR_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#include "vmime/security/authenticator.hpp"
+
+
+namespace vmime {
+namespace security {
+
+
+/** An authenticator that can provide some basic information by
+ * reading in the messaging session properties.
+ */
+class VMIME_EXPORT defaultAuthenticator : public authenticator {
+
+public:
+
+ defaultAuthenticator();
+ ~defaultAuthenticator();
+
+ const string getUsername() const;
+ const string getPassword() const;
+ const string getHostname() const;
+ const string getAnonymousToken() const;
+ const string getServiceName() const;
+ const string getAccessToken() const;
+
+ void setService(const shared_ptr <net::service>& serv);
+ weak_ptr <net::service> getService() const;
+
+private:
+
+ weak_ptr <net::service> m_service;
+};
+
+
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES
+
+#endif // VMIME_SECURITY_DEFAULTAUTHENTICATOR_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/digest/md5/md5MessageDigest.cpp b/vmime-master/src/vmime/security/digest/md5/md5MessageDigest.cpp
new file mode 100644
index 0000000..9a07b57
--- /dev/null
+++ b/vmime-master/src/vmime/security/digest/md5/md5MessageDigest.cpp
@@ -0,0 +1,349 @@
+//
+// 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.
+//
+//
+// Derived from cryptoapi implementation, originally based on the
+// public domain implementation written by Colin Plumb in 1993.
+//
+// Copyright (C) Cryptoapi developers.
+//
+// Algorithm Copyright:
+//
+// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+// rights reserved.
+//
+// License to copy and use this software is granted provided that it
+// is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+// Algorithm" in all material mentioning or referencing this software
+// or this function.
+//
+// License is also granted to make and use derivative works provided
+// that such works are identified as "derived from the RSA Data
+// Security, Inc. MD5 Message-Digest Algorithm" in all material
+// mentioning or referencing the derived work.
+//
+// RSA Data Security, Inc. makes no representations concerning either
+// the merchantability of this software or the suitability of this
+// software forany particular purpose. It is provided "as is"
+// without express or implied warranty of any kind.
+// These notices must be retained in any copies of any part of this
+// documentation and/or software.
+
+#include "vmime/security/digest/md5/md5MessageDigest.hpp"
+
+#include <cstring>
+
+
+namespace vmime {
+namespace security {
+namespace digest {
+namespace md5 {
+
+
+md5MessageDigest::md5MessageDigest() {
+
+ init();
+}
+
+
+void md5MessageDigest::reset() {
+
+ init();
+}
+
+
+void md5MessageDigest::init() {
+
+ m_hash[0] = 0x67452301;
+ m_hash[1] = 0xefcdab89;
+ m_hash[2] = 0x98badcfe;
+ m_hash[3] = 0x10325476;
+
+ m_byteCount = 0;
+ m_finalized = false;
+}
+
+
+static void copyUint8Array(vmime_uint8* dest, const vmime_uint8* src, size_t count) {
+
+ for ( ; count >= 4 ; count -= 4, dest += 4, src += 4) {
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest[2] = src[2];
+ dest[3] = src[3];
+ }
+
+ for ( ; count ; --count, ++dest, ++src) {
+ dest[0] = src[0];
+ }
+}
+
+
+static inline vmime_uint32 swapUint32(const vmime_uint32 D) {
+
+ return ((D << 24) | ((D << 8) & 0x00FF0000) | ((D >> 8) & 0x0000FF00) | (D >> 24));
+}
+
+
+static inline void swapUint32Array(vmime_uint32* buf, size_t words) {
+
+ for ( ; words >= 4 ; words -= 4, buf += 4) {
+ buf[0] = swapUint32(buf[0]);
+ buf[1] = swapUint32(buf[1]);
+ buf[2] = swapUint32(buf[2]);
+ buf[3] = swapUint32(buf[3]);
+ }
+
+ for ( ; words ; --words, ++buf) {
+ buf[0] = swapUint32(buf[0]);
+ }
+}
+
+
+void md5MessageDigest::update(const byte_t b) {
+
+ update(&b, 1);
+}
+
+
+void md5MessageDigest::update(const string& s) {
+
+ update(reinterpret_cast <const byte_t*>(s.data()), s.length());
+}
+
+
+void md5MessageDigest::update(const byte_t* data, const size_t offset, const size_t len) {
+
+ update(data + offset, len);
+}
+
+
+void md5MessageDigest::update(const byte_t* data, const size_t length) {
+
+ const size_t avail = 64 - (m_byteCount & 0x3f);
+ size_t len = length;
+
+ m_byteCount += len;
+
+ if (avail > len) {
+ copyUint8Array(m_block.b8 + (64 - avail), data, len);
+ return;
+ }
+
+ copyUint8Array(m_block.b8 + (64 - avail), data, avail);
+ transformHelper();
+
+ data += avail;
+ len -= avail;
+
+ while (len >= 64) {
+
+ copyUint8Array(m_block.b8, data, 64);
+ transformHelper();
+
+ data += 64;
+ len -= 64;
+ }
+
+ copyUint8Array(m_block.b8, data, len);
+}
+
+
+void md5MessageDigest::finalize(const string& s) {
+
+ update(s);
+ finalize();
+}
+
+
+void md5MessageDigest::finalize(const byte_t* buffer, const size_t len) {
+
+ update(buffer, len);
+ finalize();
+}
+
+
+void md5MessageDigest::finalize(
+ const byte_t* buffer,
+ const size_t offset,
+ const size_t len
+) {
+
+ update(buffer, offset, len);
+ finalize();
+}
+
+
+void md5MessageDigest::finalize() {
+
+ const long offset = m_byteCount & 0x3f;
+
+ vmime_uint8* p = m_block.b8 + offset;
+ long padding = 56 - (offset + 1);
+
+ *p++ = 0x80;
+
+ if (padding < 0) {
+
+ memset(p, 0x00, padding + 8);
+ transformHelper();
+ p = m_block.b8;
+ padding = 56;
+ }
+
+ memset(p, 0, padding);
+
+ m_block.b32[14] = static_cast <vmime_uint32>(m_byteCount << 3);
+ m_block.b32[15] = static_cast <vmime_uint32>(m_byteCount >> 29);
+
+#if VMIME_BYTE_ORDER_BIG_ENDIAN
+ swapUint32Array(m_block.b32, (64 - 8) / 4);
+#endif
+
+ transform();
+
+#if VMIME_BYTE_ORDER_BIG_ENDIAN
+ swapUint32Array(m_hash, 4);
+#endif
+
+ m_finalized = true;
+}
+
+
+void md5MessageDigest::transformHelper() {
+
+#if VMIME_BYTE_ORDER_BIG_ENDIAN
+ swapUint32Array(m_block.b32, 64 / 4);
+#endif
+ transform();
+}
+
+
+void md5MessageDigest::transform() {
+
+ const vmime_uint32* const in = m_block.b32;
+
+ vmime_uint32 a = m_hash[0];
+ vmime_uint32 b = m_hash[1];
+ vmime_uint32 c = m_hash[2];
+ vmime_uint32 d = m_hash[3];
+
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, in, s) \
+ (w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ m_hash[0] += a;
+ m_hash[1] += b;
+ m_hash[2] += c;
+ m_hash[3] += d;
+}
+
+
+size_t md5MessageDigest::getDigestLength() const {
+
+ return 16;
+}
+
+
+const byte_t* md5MessageDigest::getDigest() const {
+
+ return reinterpret_cast <const byte_t*>(m_hash);
+}
+
+
+} // md5
+} // digest
+} // security
+} // vmime
+
diff --git a/vmime-master/src/vmime/security/digest/md5/md5MessageDigest.hpp b/vmime-master/src/vmime/security/digest/md5/md5MessageDigest.hpp
new file mode 100644
index 0000000..bdb730a
--- /dev/null
+++ b/vmime-master/src/vmime/security/digest/md5/md5MessageDigest.hpp
@@ -0,0 +1,85 @@
+//
+// 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_SECURITY_DIGEST_MD5_MD5MESSAGEDIGEST_HPP_INCLUDED
+#define VMIME_SECURITY_DIGEST_MD5_MD5MESSAGEDIGEST_HPP_INCLUDED
+
+
+#include "vmime/security/digest/messageDigest.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace digest {
+namespace md5 {
+
+
+class md5MessageDigest : public messageDigest {
+
+public:
+
+ md5MessageDigest();
+
+ void update(const byte_t b);
+ void update(const string& s);
+ void update(const byte_t* buffer, const size_t len);
+ void update(const byte_t* buffer, const size_t offset, const size_t len);
+
+ void finalize();
+ void finalize(const string& s);
+ void finalize(const byte_t* buffer, const size_t len);
+ void finalize(const byte_t* buffer, const size_t offset, const size_t len);
+
+ size_t getDigestLength() const;
+ const byte_t* getDigest() const;
+
+ void reset();
+
+protected:
+
+ void init();
+ void transformHelper();
+ void transform();
+
+ vmime_uint32 m_hash[4];
+
+ union BlockType {
+ vmime_uint32 b32[16];
+ vmime_uint8 b8[64];
+ };
+
+ size_t m_byteCount;
+ BlockType m_block;
+
+ bool m_finalized;
+};
+
+
+} // md5
+} // digest
+} // security
+} // vmime
+
+
+#endif // VMIME_SECURITY_DIGEST_MD5_MD5MESSAGEDIGEST_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/security/digest/messageDigest.cpp b/vmime-master/src/vmime/security/digest/messageDigest.cpp
new file mode 100644
index 0000000..d7e394f
--- /dev/null
+++ b/vmime-master/src/vmime/security/digest/messageDigest.cpp
@@ -0,0 +1,56 @@
+//
+// 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.
+//
+
+#include "vmime/security/digest/messageDigest.hpp"
+
+#include <sstream>
+
+
+namespace vmime {
+namespace security {
+namespace digest {
+
+
+const string messageDigest::getHexDigest() const {
+
+ const byte_t* hash = getDigest();
+ const size_t len = getDigestLength();
+
+ static const unsigned char hex[] = "0123456789abcdef";
+
+ std::ostringstream oss;
+ oss.imbue(std::locale::classic());
+
+ for (size_t i = 0 ; i < len ; ++i) {
+ oss << hex[(hash[i] & 0xf0) >> 4];
+ oss << hex[(hash[i] & 0x0f)];
+ }
+
+ return oss.str();
+}
+
+
+} // digest
+} // security
+} // vmime
+
diff --git a/vmime-master/src/vmime/security/digest/messageDigest.hpp b/vmime-master/src/vmime/security/digest/messageDigest.hpp
new file mode 100644
index 0000000..0413810
--- /dev/null
+++ b/vmime-master/src/vmime/security/digest/messageDigest.hpp
@@ -0,0 +1,142 @@
+//
+// 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_SECURITY_DIGEST_MESSAGEDIGEST_HPP_INCLUDED
+#define VMIME_SECURITY_DIGEST_MESSAGEDIGEST_HPP_INCLUDED
+
+
+#include "vmime/object.hpp"
+#include "vmime/types.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace digest {
+
+
+/** Computes message digests using standard algorithms,
+ * such as MD5 or SHA.
+ */
+class VMIME_EXPORT messageDigest : public object {
+
+public:
+
+ /** Updates the digest using the specified string.
+ *
+ * @param s the string with which to update the digest.
+ */
+ virtual void update(const string& s) = 0;
+
+ /** Updates the digest using the specified byte.
+ *
+ * @param b the byte with which to update the digest.
+ */
+ virtual void update(const byte_t b) = 0;
+
+ /** Updates the digest using the specified array of bytes.
+ *
+ * @param buffer array of bytes
+ * @param len number of bytes to use in the buffer
+ */
+ virtual void update(const byte_t* buffer, const size_t len) = 0;
+
+ /** Updates the digest using the specified array of bytes,
+ * starting at the specified offset.
+ *
+ * @param buffer array of bytes
+ * @param offset offset to start from in the array of bytes
+ * @param len number of bytes to use, starting at offset
+ */
+ virtual void update(
+ const byte_t* buffer,
+ const size_t offset,
+ const size_t len
+ ) = 0;
+
+ /** Completes the hash computation by performing final operations
+ * such as padding.
+ */
+ virtual void finalize() = 0;
+
+ /** Completes the hash computation by performing final operations
+ * such as padding. This is equivalent to calling update() and
+ * then finalize().
+ */
+ virtual void finalize(const string& s) = 0;
+
+ /** Completes the hash computation by performing final operations
+ * such as padding. This is equivalent to calling update() and
+ * then finalize().
+ */
+ virtual void finalize(
+ const byte_t* buffer,
+ const size_t len
+ ) = 0;
+
+ /** Completes the hash computation by performing final operations
+ * such as padding. This is equivalent to calling update() and
+ * then finalize().
+ */
+ virtual void finalize(
+ const byte_t* buffer,
+ const size_t offset,
+ const size_t len
+ ) = 0;
+
+ /** Returns the length of the hash.
+ * This is the length of the array returned by getDigest().
+ *
+ * @return length of computed hash
+ */
+ virtual size_t getDigestLength() const = 0;
+
+ /** Returns the hash, as computed by the algorithm.
+ * You must call finalize() before using this function, or the
+ * hash will not be correct.
+ * To get the size of the returned array, call getDigestLength().
+ *
+ * @return computed hash
+ */
+ virtual const byte_t* getDigest() const = 0;
+
+ /** Returns the hash as an hexadecimal string.
+ * You must call finalize() before using this function, or the
+ * hash will not be correct.
+ *
+ * @return computed hash, in hexadecimal format
+ */
+ virtual const string getHexDigest() const;
+
+ /** Resets the algorithm to its initial state, so that you can
+ * compute a new hash using the same object.
+ */
+ virtual void reset() = 0;
+};
+
+
+} // digest
+} // security
+} // vmime
+
+
+#endif // VMIME_SECURITY_DIGEST_MESSAGEDIGEST_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/digest/messageDigestFactory.cpp b/vmime-master/src/vmime/security/digest/messageDigestFactory.cpp
new file mode 100644
index 0000000..2e49968
--- /dev/null
+++ b/vmime-master/src/vmime/security/digest/messageDigestFactory.cpp
@@ -0,0 +1,81 @@
+//
+// 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.
+//
+
+#include "vmime/security/digest/messageDigestFactory.hpp"
+#include "vmime/exception.hpp"
+
+#include "vmime/security/digest/md5/md5MessageDigest.hpp"
+#include "vmime/security/digest/sha1/sha1MessageDigest.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace digest {
+
+
+messageDigestFactory::messageDigestFactory() {
+
+ registerAlgorithm <md5::md5MessageDigest>("md5");
+ registerAlgorithm <sha1::sha1MessageDigest>("sha1");
+}
+
+
+messageDigestFactory::~messageDigestFactory() {
+
+}
+
+
+messageDigestFactory* messageDigestFactory::getInstance() {
+
+ static messageDigestFactory instance;
+ return &instance;
+}
+
+
+shared_ptr <messageDigest> messageDigestFactory::create(const string& name) {
+
+ const MapType::const_iterator it = m_algos.find(utility::stringUtils::toLower(name));
+
+ if (it != m_algos.end()) {
+ return (*it).second->create();
+ }
+
+ throw exceptions::no_digest_algorithm_available(name);
+}
+
+
+const std::vector <string> messageDigestFactory::getSupportedAlgorithms() const {
+
+ std::vector <string> res;
+
+ for (MapType::const_iterator it = m_algos.begin() ; it != m_algos.end() ; ++it) {
+ res.push_back((*it).first);
+ }
+
+ return res;
+}
+
+
+} // digest
+} // security
+} // vmime
diff --git a/vmime-master/src/vmime/security/digest/messageDigestFactory.hpp b/vmime-master/src/vmime/security/digest/messageDigestFactory.hpp
new file mode 100644
index 0000000..56a0cfe
--- /dev/null
+++ b/vmime-master/src/vmime/security/digest/messageDigestFactory.hpp
@@ -0,0 +1,110 @@
+//
+// 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_SECURITY_DIGEST_MESSAGEDIGESTFACTORY_HPP_INCLUDED
+#define VMIME_SECURITY_DIGEST_MESSAGEDIGESTFACTORY_HPP_INCLUDED
+
+
+#include "vmime/types.hpp"
+#include "vmime/security/digest/messageDigest.hpp"
+#include "vmime/utility/stringUtils.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace digest {
+
+
+/** Creates instances of message digest algorithms.
+ */
+
+class VMIME_EXPORT messageDigestFactory {
+
+private:
+
+ messageDigestFactory();
+ ~messageDigestFactory();
+
+public:
+
+ static messageDigestFactory* getInstance();
+
+private:
+
+ struct digestAlgorithmFactory : public object {
+
+ virtual shared_ptr <messageDigest> create() const = 0;
+ };
+
+ template <class E>
+ struct digestAlgorithmFactoryImpl : public digestAlgorithmFactory {
+
+ shared_ptr <messageDigest> create() const {
+ return vmime::make_shared <E>();
+ }
+ };
+
+
+ typedef std::map <string, shared_ptr <digestAlgorithmFactory> > MapType;
+ MapType m_algos;
+
+public:
+
+ /** Register a new digest algorithm by its name.
+ *
+ * @param name algorithm name
+ */
+ template <class E>
+ void registerAlgorithm(const string& name) {
+
+ m_algos.insert(
+ MapType::value_type(
+ utility::stringUtils::toLower(name),
+ vmime::make_shared <digestAlgorithmFactoryImpl <E> >()
+ )
+ );
+ }
+
+ /** Create a new algorithm instance from its name.
+ *
+ * @param name algorithm name (eg. "md5")
+ * @return a new algorithm instance for the specified name
+ * @throw exceptions::no_digest_algorithm_available if no algorithm is
+ * registered with this name
+ */
+ shared_ptr <messageDigest> create(const string& name);
+
+ /** Return a list of supported digest algorithms.
+ *
+ * @return list of supported digest algorithms
+ */
+ const std::vector <string> getSupportedAlgorithms() const;
+};
+
+
+} // digest
+} // security
+} // vmime
+
+
+#endif // VMIME_SECURITY_DIGEST_MESSAGEDIGESTFACTORY_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/digest/sha1/sha1MessageDigest.cpp b/vmime-master/src/vmime/security/digest/sha1/sha1MessageDigest.cpp
new file mode 100644
index 0000000..c098f14
--- /dev/null
+++ b/vmime-master/src/vmime/security/digest/sha1/sha1MessageDigest.cpp
@@ -0,0 +1,276 @@
+//
+// 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.
+//
+//
+// This is an implementation by Steve Reid <steve@edmweb.com>
+// 100% public domain.
+
+#include "vmime/security/digest/sha1/sha1MessageDigest.hpp"
+
+#include <cstring>
+#include <cassert>
+
+
+namespace vmime {
+namespace security {
+namespace digest {
+namespace sha1 {
+
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+// blk0() and blk() perform the initial expand.
+// I got the idea of expanding during the round function from SSLeay
+#if VMIME_BYTE_ORDER_LITTLE_ENDIAN
+ #define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \
+ | (rol(block->l[i], 8) & 0x00FF00FF))
+#else
+ #define blk0(i) block->l[i]
+#endif
+
+#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] \
+ ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
+
+// (R0+R1), R2, R3, R4 are the different operations used in SHA1
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+sha1MessageDigest::sha1MessageDigest() {
+
+ init();
+}
+
+
+void sha1MessageDigest::reset() {
+
+ init();
+}
+
+
+void sha1MessageDigest::init() {
+
+ m_state[0] = 0x67452301;
+ m_state[1] = 0xefcdab89;
+ m_state[2] = 0x98badcfe;
+ m_state[3] = 0x10325476;
+ m_state[4] = 0xc3d2e1f0;
+
+ m_count[0] = 0;
+ m_count[1] = 0;
+}
+
+
+void sha1MessageDigest::update(const byte_t b) {
+
+ update(&b, 1);
+}
+
+
+void sha1MessageDigest::update(const string& s) {
+
+ update(reinterpret_cast <const byte_t*>(s.data()), s.length());
+}
+
+
+void sha1MessageDigest::update(const byte_t* buffer, const size_t offset, const size_t len) {
+
+ update(buffer + offset, len);
+}
+
+
+void sha1MessageDigest::update(const byte_t* buffer, const size_t len) {
+
+ unsigned int i, j;
+
+ j = (m_count[0] >> 3) & 63;
+
+ if ((m_count[0] += static_cast <unsigned int>(len << 3)) < static_cast <unsigned int>(len << 3)) {
+ m_count[1]++;
+ }
+
+ m_count[1] += static_cast <unsigned int>(len >> 29);
+
+ if ((j + len) > 63) {
+
+ memcpy(&m_buffer[j], buffer, (i = 64 - j));
+
+ transform(m_state, m_buffer);
+
+ for ( ; i + 63 < len ; i += 64) {
+ transform(m_state, &buffer[i]);
+ }
+
+ j = 0;
+
+ } else {
+
+ i = 0;
+ }
+
+ std::memcpy(&m_buffer[j], &buffer[i], len - i);
+}
+
+
+void sha1MessageDigest::finalize() {
+
+ unsigned int i, j;
+ unsigned char finalcount[8];
+
+ for (i = 0 ; i < 8 ; i++) {
+
+ finalcount[i] = static_cast <unsigned char>(
+ (m_count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255 // Endian independent
+ );
+ }
+
+ update(reinterpret_cast <const byte_t*>("\200"), 1);
+
+ while ((m_count[0] & 504) != 448) {
+ update(reinterpret_cast <const byte_t*>("\0"), 1);
+ }
+
+ update(finalcount, 8); // Should cause a transform()
+
+ for (i = 0 ; i < 20 ; i++) {
+
+ m_digest[i] = static_cast <unsigned char>(
+ (m_state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255
+ );
+ }
+
+ // Wipe variables
+ i = j = 0;
+
+ std::memset(m_buffer, 0, 64);
+ std::memset(m_state, 0, 5 * sizeof(unsigned int));
+ std::memset(m_count, 0, 2 * sizeof(unsigned int));
+ std::memset(&finalcount, 0, 8);
+}
+
+
+void sha1MessageDigest::finalize(const string& s) {
+
+ finalize(reinterpret_cast <const byte_t*>(s.data()), s.length());
+}
+
+
+void sha1MessageDigest::finalize(const byte_t* buffer, const size_t len) {
+
+ update(buffer, len);
+ finalize();
+}
+
+
+void sha1MessageDigest::finalize(
+ const byte_t* buffer,
+ const size_t offset,
+ const size_t len
+) {
+
+ finalize(buffer + offset, len);
+}
+
+
+/** Hash a single 512-bit block.
+ * This is the core of the algorithm.
+ */
+void sha1MessageDigest::transform(
+ unsigned int state[5],
+ const unsigned char buffer[64]
+) {
+
+ unsigned int a, b, c, d, e;
+
+ typedef union {
+ unsigned char c[64];
+ unsigned int l[16];
+ } CHAR64LONG16;
+
+ assert(sizeof(unsigned int) == 4);
+
+ CHAR64LONG16* block;
+ static unsigned char workspace[64];
+
+ block = reinterpret_cast <CHAR64LONG16*>(workspace);
+ memcpy(block, buffer, 64);
+
+ // Copy context->state[] to working vars
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+ // 4 rounds of 20 operations each. Loop unrolled.
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+ // Add the working vars back into context.state[]
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ // Wipe variables
+ a = b = c = d = e = 0;
+}
+
+
+size_t sha1MessageDigest::getDigestLength() const {
+
+ return 20;
+}
+
+
+const byte_t* sha1MessageDigest::getDigest() const {
+
+ return m_digest;
+}
+
+
+} // sha1
+} // digest
+} // security
+} // vmime
diff --git a/vmime-master/src/vmime/security/digest/sha1/sha1MessageDigest.hpp b/vmime-master/src/vmime/security/digest/sha1/sha1MessageDigest.hpp
new file mode 100644
index 0000000..1906236
--- /dev/null
+++ b/vmime-master/src/vmime/security/digest/sha1/sha1MessageDigest.hpp
@@ -0,0 +1,79 @@
+//
+// 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_SECURITY_DIGEST_SHA1_SHA1MESSAGEDIGEST_HPP_INCLUDED
+#define VMIME_SECURITY_DIGEST_SHA1_SHA1MESSAGEDIGEST_HPP_INCLUDED
+
+
+#include "vmime/security/digest/messageDigest.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace digest {
+namespace sha1 {
+
+
+class sha1MessageDigest : public messageDigest {
+
+public:
+
+ sha1MessageDigest();
+
+ void update(const byte_t b);
+ void update(const string& s);
+ void update(const byte_t* buffer, const size_t len);
+ void update(const byte_t* buffer, const size_t offset, const size_t len);
+
+ void finalize();
+ void finalize(const string& s);
+ void finalize(const byte_t* buffer, const size_t len);
+ void finalize(const byte_t* buffer, const size_t offset, const size_t len);
+
+ size_t getDigestLength() const;
+ const byte_t* getDigest() const;
+
+ void reset();
+
+protected:
+
+ void init();
+
+ static void transform(unsigned int state[5], const byte_t buffer[64]);
+
+ unsigned int m_state[5];
+ unsigned int m_count[2];
+ byte_t m_buffer[64];
+
+ byte_t m_digest[20];
+};
+
+
+} // sha1
+} // digest
+} // security
+} // vmime
+
+
+#endif // VMIME_SECURITY_DIGEST_SHA1_SHA1MESSAGEDIGEST_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/security/sasl/SASLAuthenticator.hpp b/vmime-master/src/vmime/security/sasl/SASLAuthenticator.hpp
new file mode 100644
index 0000000..a75bfa0
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/SASLAuthenticator.hpp
@@ -0,0 +1,96 @@
+//
+// 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_SECURITY_SASL_SASLAUTHENTICATOR_HPP_INCLUDED
+#define VMIME_SECURITY_SASL_SASLAUTHENTICATOR_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/types.hpp"
+
+#include "vmime/security/authenticator.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+class SASLMechanism;
+class SASLSession;
+
+
+/** SASL-aware authenticator.
+ *
+ * Usually, you should not inherit from this class, but instead from the
+ * more convenient defaultSASLAuthenticator class.
+ */
+class VMIME_EXPORT SASLAuthenticator : public authenticator {
+
+public:
+
+ /** This method is called to allow the client to choose the
+ * authentication mechanisms that will be used. By default,
+ * the most secure mechanisms are chosen.
+ *
+ * @param available available mechanisms
+ * @param suggested suggested mechanism (or NULL if the system
+ * could not suggest a mechanism)
+ * @return ordered list of mechanism to use among the available
+ * mechanisms (from the first to try to the last)
+ */
+ virtual const std::vector <shared_ptr <SASLMechanism> > getAcceptableMechanisms(
+ const std::vector <shared_ptr <SASLMechanism> >& available,
+ const shared_ptr <SASLMechanism>& suggested
+ ) const = 0;
+
+ /** Set the SASL session which is using this authenticator.
+ *
+ * @param sess SASL session
+ */
+ virtual void setSASLSession(const shared_ptr <SASLSession>& sess) = 0;
+
+ /** Set the SASL mechanism which has been selected for the
+ * SASL authentication process. This may be called several times
+ * if the multiple mechanisms are tried by the service which
+ * use this authentication.
+ *
+ * @param mech SASL mechanism
+ */
+ virtual void setSASLMechanism(const shared_ptr <SASLMechanism>& mech) = 0;
+};
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+#endif // VMIME_SECURITY_SASL_SASLAUTHENTICATOR_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/sasl/SASLContext.cpp b/vmime-master/src/vmime/security/sasl/SASLContext.cpp
new file mode 100644
index 0000000..2174541
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/SASLContext.cpp
@@ -0,0 +1,221 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include <sstream>
+
+#include <gsasl.h>
+
+#include "vmime/security/sasl/SASLContext.hpp"
+#include "vmime/security/sasl/SASLMechanism.hpp"
+
+#include "vmime/base.hpp"
+
+#include "vmime/utility/encoder/encoderFactory.hpp"
+
+#include "vmime/utility/stream.hpp"
+#include "vmime/utility/outputStreamStringAdapter.hpp"
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+#include "vmime/utility/inputStreamByteBufferAdapter.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+SASLContext::SASLContext() {
+
+ if (gsasl_init(&m_gsaslContext) != GSASL_OK) {
+ throw std::bad_alloc();
+ }
+}
+
+
+SASLContext::~SASLContext() {
+
+ gsasl_done(m_gsaslContext);
+}
+
+
+// static
+shared_ptr <SASLContext> SASLContext::create() {
+
+ return shared_ptr <SASLContext>(new SASLContext());
+}
+
+
+shared_ptr <SASLSession> SASLContext::createSession(
+ const string& serviceName,
+ const shared_ptr <authenticator>& auth,
+ const shared_ptr <SASLMechanism>& mech
+) {
+
+ return SASLSession::create
+ (serviceName, dynamicCast <SASLContext>(shared_from_this()), auth, mech);
+}
+
+
+shared_ptr <SASLMechanism> SASLContext::createMechanism(const string& name) {
+
+ return SASLMechanismFactory::getInstance()->create(
+ dynamicCast <SASLContext>(shared_from_this()), name
+ );
+}
+
+
+shared_ptr <SASLMechanism> SASLContext::suggestMechanism(
+ const std::vector <shared_ptr <SASLMechanism> >& mechs
+) {
+
+ if (mechs.empty()) {
+ return null;
+ }
+
+ std::ostringstream oss;
+
+ for (unsigned int i = 0 ; i < mechs.size() ; ++i) {
+ oss << mechs[i]->getName() << " ";
+ }
+
+ const string mechList = oss.str();
+ const char* suggested = gsasl_client_suggest_mechanism(m_gsaslContext, mechList.c_str());
+
+ if (suggested) {
+
+ for (unsigned int i = 0 ; i < mechs.size() ; ++i) {
+
+ if (mechs[i]->getName() == suggested) {
+ return mechs[i];
+ }
+ }
+ }
+
+ return null;
+}
+
+
+void SASLContext::decodeB64(const string& input, byte_t** output, size_t* outputLen) {
+
+ string res;
+
+ utility::inputStreamStringAdapter is(input);
+ utility::outputStreamStringAdapter os(res);
+
+ shared_ptr <utility::encoder::encoder> dec =
+ utility::encoder::encoderFactory::getInstance()->create("base64");
+
+ dec->decode(is, os);
+
+ byte_t* out = new byte_t[res.length()];
+
+ std::copy(res.begin(), res.end(), out);
+
+ *output = out;
+ *outputLen = res.length();
+}
+
+
+const string SASLContext::encodeB64(const byte_t* input, const size_t inputLen) {
+
+ string res;
+
+ utility::inputStreamByteBufferAdapter is(input, inputLen);
+ utility::outputStreamStringAdapter os(res);
+
+ shared_ptr <utility::encoder::encoder> enc =
+ utility::encoder::encoderFactory::getInstance()->create("base64");
+
+ enc->encode(is, os);
+
+ return res;
+}
+
+
+const string SASLContext::getErrorMessage(const string& fname, const int code) {
+
+ string msg = fname + "() returned ";
+
+#define ERROR(x) \
+ case x: msg += #x; break;
+
+ switch (code)
+ {
+ ERROR(GSASL_NEEDS_MORE)
+ ERROR(GSASL_UNKNOWN_MECHANISM)
+ ERROR(GSASL_MECHANISM_CALLED_TOO_MANY_TIMES)
+ ERROR(GSASL_MALLOC_ERROR)
+ ERROR(GSASL_BASE64_ERROR)
+ ERROR(GSASL_CRYPTO_ERROR)
+ ERROR(GSASL_SASLPREP_ERROR)
+ ERROR(GSASL_MECHANISM_PARSE_ERROR)
+ ERROR(GSASL_AUTHENTICATION_ERROR)
+ ERROR(GSASL_INTEGRITY_ERROR)
+ ERROR(GSASL_NO_CLIENT_CODE)
+ ERROR(GSASL_NO_SERVER_CODE)
+ ERROR(GSASL_NO_CALLBACK)
+ ERROR(GSASL_NO_ANONYMOUS_TOKEN)
+ ERROR(GSASL_NO_AUTHID)
+ ERROR(GSASL_NO_AUTHZID)
+ ERROR(GSASL_NO_PASSWORD)
+ ERROR(GSASL_NO_PASSCODE)
+ ERROR(GSASL_NO_PIN)
+ ERROR(GSASL_NO_SERVICE)
+ ERROR(GSASL_NO_HOSTNAME)
+ ERROR(GSASL_GSSAPI_RELEASE_BUFFER_ERROR)
+ ERROR(GSASL_GSSAPI_IMPORT_NAME_ERROR)
+ ERROR(GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR)
+ ERROR(GSASL_GSSAPI_ACCEPT_SEC_CONTEXT_ERROR)
+ ERROR(GSASL_GSSAPI_UNWRAP_ERROR)
+ ERROR(GSASL_GSSAPI_WRAP_ERROR)
+ ERROR(GSASL_GSSAPI_ACQUIRE_CRED_ERROR)
+ ERROR(GSASL_GSSAPI_DISPLAY_NAME_ERROR)
+ ERROR(GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR)
+ ERROR(GSASL_KERBEROS_V5_INIT_ERROR)
+ ERROR(GSASL_KERBEROS_V5_INTERNAL_ERROR)
+ ERROR(GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE)
+ ERROR(GSASL_SECURID_SERVER_NEED_NEW_PIN)
+
+ default:
+
+ msg += "unknown error";
+ break;
+ }
+
+#undef ERROR
+
+ return msg;
+}
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
diff --git a/vmime-master/src/vmime/security/sasl/SASLContext.hpp b/vmime-master/src/vmime/security/sasl/SASLContext.hpp
new file mode 100644
index 0000000..93d80ff
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/SASLContext.hpp
@@ -0,0 +1,136 @@
+//
+// 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_SECURITY_SASL_SASLCONTEXT_HPP_INCLUDED
+#define VMIME_SECURITY_SASL_SASLCONTEXT_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/types.hpp"
+
+#include "vmime/security/sasl/SASLSession.hpp"
+#include "vmime/security/sasl/SASLMechanismFactory.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+/** An SASL client context.
+ */
+class VMIME_EXPORT SASLContext : public object, public enable_shared_from_this <SASLContext> {
+
+ friend class SASLSession;
+ friend class builtinSASLMechanism;
+
+public:
+
+ ~SASLContext();
+
+ /** Construct and initialize a new SASL context.
+ *
+ * @return pointer to a new SASL context
+ */
+ static shared_ptr <SASLContext> create();
+
+ /** Create and initialize a new SASL session.
+ *
+ * @param serviceName name of the service which will use the session
+ * @param auth authenticator object to use during the session
+ * @param mech SASL mechanism
+ * @return a new SASL session
+ */
+ shared_ptr <SASLSession> createSession(
+ const string& serviceName,
+ const shared_ptr <authenticator>& auth,
+ const shared_ptr <SASLMechanism>& mech
+ );
+
+ /** Create an instance of an SASL mechanism.
+ *
+ * @param name mechanism name
+ * @return a new instance of the specified SASL mechanism
+ * @throw exceptions::no_such_mechanism if no mechanism is
+ * registered for the specified name
+ */
+ shared_ptr <SASLMechanism> createMechanism(const string& name);
+
+ /** Suggests an SASL mechanism among a set of mechanisms
+ * supported by the server.
+ *
+ * @param mechs list of mechanisms
+ * @return suggested mechanism (usually the safest mechanism
+ * supported by both the client and the server)
+ */
+ shared_ptr <SASLMechanism> suggestMechanism(
+ const std::vector <shared_ptr <SASLMechanism> >& mechs
+ );
+
+ /** Helper function for decoding Base64-encoded challenge.
+ *
+ * @param input input buffer
+ * @param output output buffer
+ * @param outputLen length of output buffer
+ */
+ void decodeB64(const string& input, byte_t** output, size_t* outputLen);
+
+ /** Helper function for encoding challenge in Base64.
+ *
+ * @param input input buffer
+ * @param inputLen length of input buffer
+ * @return Base64-encoded challenge
+ */
+ const string encodeB64(const byte_t* input, const size_t inputLen);
+
+private:
+
+ SASLContext();
+ SASLContext(SASLContext&);
+
+
+ static const string getErrorMessage(const string& fname, const int code);
+
+
+#ifdef GSASL_VERSION
+ Gsasl* m_gsaslContext;
+#else
+ void* m_gsaslContext;
+#endif // GSASL_VERSION
+
+};
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+#endif // VMIME_SECURITY_SASL_SASLCONTEXT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/sasl/SASLMechanism.hpp b/vmime-master/src/vmime/security/sasl/SASLMechanism.hpp
new file mode 100644
index 0000000..a6e056d
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/SASLMechanism.hpp
@@ -0,0 +1,153 @@
+//
+// 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_SECURITY_SASL_SASLMECHANISM_HPP_INCLUDED
+#define VMIME_SECURITY_SASL_SASLMECHANISM_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/types.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+class SASLSession;
+
+
+/** An SASL mechanism.
+ */
+class VMIME_EXPORT SASLMechanism : public object {
+
+public:
+
+ /** Return the name of this mechanism.
+ *
+ * @return mechanism name
+ */
+ virtual const string getName() const = 0;
+
+ /** Perform one step of SASL authentication. Accept data from the
+ * server (challenge), process it and return data to be returned
+ * in response to the server.
+ *
+ * If the challenge is empty (challengeLen == 0), the initial
+ * response is returned, if this mechanism has one.
+ *
+ * @param sess SASL session
+ * @param challenge challenge sent from the server
+ * @param challengeLen length of challenge
+ * @param response response to send to the server (allocated by
+ * this function, free with delete[])
+ * @param responseLen length of response buffer
+ * @return true if authentication terminated successfully, or
+ * false if the authentication process should continue
+ * @throw exceptions::sasl_exception if an error occurred during
+ * authentication (in this case, the values in 'response' and
+ * 'responseLen' are undetermined)
+ */
+ virtual bool step(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* challenge,
+ const size_t challengeLen,
+ byte_t** response,
+ size_t* responseLen
+ ) = 0;
+
+ /** Check whether authentication has completed. If false, more
+ * calls to evaluateChallenge() are needed to complete the
+ * authentication process).
+ *
+ * @return true if the authentication has finished, or false
+ * otherwise
+ */
+ virtual bool isComplete() const = 0;
+
+ /** Determine if this mechanism has an optional initial response.
+ * If true, caller should call step() with an empty challenge to
+ * get the initial response.
+ *
+ * @return true if this mechanism has an initial response, or
+ * false otherwise
+ */
+ virtual bool hasInitialResponse() const = 0;
+
+ /** Encode data according to negotiated SASL mechanism. This
+ * might mean that data is integrity or privacy protected.
+ *
+ * @param sess SASL session
+ * @param input input buffer
+ * @param inputLen length of input buffer
+ * @param output output buffer (allocated bu the function,
+ * free with delete[])
+ * @param outputLen length of output buffer
+ * @throw exceptions::sasl_exception if an error occurred during
+ * the encoding of data (in this case, the values in 'output' and
+ * 'outputLen' are undetermined)
+ */
+ virtual void encode(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* input,
+ const size_t inputLen,
+ byte_t** output,
+ size_t* outputLen
+ ) = 0;
+
+ /** Decode data according to negotiated SASL mechanism. This
+ * might mean that data is integrity or privacy protected.
+ *
+ * @param sess SASL session
+ * @param input input buffer
+ * @param inputLen length of input buffer
+ * @param output output buffer (allocated bu the function,
+ * free with delete[])
+ * @param outputLen length of output buffer
+ * @throw exceptions::sasl_exception if an error occurred during
+ * the encoding of data (in this case, the values in 'output' and
+ * 'outputLen' are undetermined)
+ */
+ virtual void decode(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* input,
+ const size_t inputLen,
+ byte_t** output,
+ size_t* outputLen
+ ) = 0;
+};
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+#endif // VMIME_SECURITY_SASL_SASLMECHANISM_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/sasl/SASLMechanismFactory.cpp b/vmime-master/src/vmime/security/sasl/SASLMechanismFactory.cpp
new file mode 100644
index 0000000..a2fbedb
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/SASLMechanismFactory.cpp
@@ -0,0 +1,149 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include <stdexcept>
+#include <new>
+
+#include <gsasl.h>
+
+#include "vmime/security/sasl/SASLMechanismFactory.hpp"
+#include "vmime/security/sasl/builtinSASLMechanism.hpp"
+#include "vmime/security/sasl/SASLContext.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include "vmime/base.hpp"
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+SASLMechanismFactory::SASLMechanismFactory() {
+
+ if (gsasl_init(&m_gsaslContext) != GSASL_OK) {
+ throw std::bad_alloc();
+ }
+}
+
+
+SASLMechanismFactory::~SASLMechanismFactory() {
+
+ gsasl_done(m_gsaslContext);
+}
+
+
+// static
+SASLMechanismFactory* SASLMechanismFactory::getInstance() {
+
+ static SASLMechanismFactory instance;
+ return &instance;
+}
+
+
+shared_ptr <SASLMechanism> SASLMechanismFactory::create(
+ const shared_ptr <SASLContext>& ctx,
+ const string& name_
+) {
+
+ const string name(utility::stringUtils::toUpper(name_));
+
+ // Check for registered mechanisms
+ MapType::iterator it = m_mechs.find(name);
+
+ if (it != m_mechs.end()) {
+ return (*it).second->create(ctx, name);
+ }
+
+ // Check for built-in mechanisms
+ if (isBuiltinMechanism(name)) {
+ return make_shared <builtinSASLMechanism>(ctx, name);
+ }
+
+ throw exceptions::no_such_mechanism(name);
+ return null;
+}
+
+
+const std::vector <string> SASLMechanismFactory::getSupportedMechanisms() const {
+
+ std::vector <string> list;
+
+ // Registered mechanisms
+ for (MapType::const_iterator it = m_mechs.begin() ;
+ it != m_mechs.end() ; ++it) {
+
+ list.push_back((*it).first);
+ }
+
+ // Built-in mechanisms
+ char* out = 0;
+
+ if (gsasl_client_mechlist(m_gsaslContext, &out) == GSASL_OK) {
+
+ // 'out' contains SASL mechanism names, separated by spaces
+ for (char *start = out, *p = out ; ; ++p) {
+
+ if (*p == ' ' || !*p) {
+
+ list.push_back(string(start, p));
+ start = p + 1;
+
+ // End of string
+ if (!*p) break;
+ }
+ }
+
+ gsasl_free(out);
+ }
+
+ return list;
+}
+
+
+bool SASLMechanismFactory::isMechanismSupported(const string& name) const {
+
+ return isBuiltinMechanism(name) || m_mechs.find(name) != m_mechs.end();
+}
+
+
+bool SASLMechanismFactory::isBuiltinMechanism(const string& name) const {
+
+ return gsasl_client_support_p(m_gsaslContext, name.c_str()) != 0;
+}
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
diff --git a/vmime-master/src/vmime/security/sasl/SASLMechanismFactory.hpp b/vmime-master/src/vmime/security/sasl/SASLMechanismFactory.hpp
new file mode 100644
index 0000000..af76c96
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/SASLMechanismFactory.hpp
@@ -0,0 +1,155 @@
+//
+// 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_SECURITY_SASL_SASLMECHANISMFACTORY_HPP_INCLUDED
+#define VMIME_SECURITY_SASL_SASLMECHANISMFACTORY_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/types.hpp"
+#include "vmime/base.hpp"
+
+#include "vmime/security/sasl/SASLMechanism.hpp"
+
+#include <map>
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+class SASLContext;
+
+
+/** Constructs SASL mechanism objects.
+ */
+class VMIME_EXPORT SASLMechanismFactory : public object {
+
+private:
+
+ SASLMechanismFactory();
+ ~SASLMechanismFactory();
+
+
+ struct registeredMechanism : public object {
+
+ virtual shared_ptr <SASLMechanism> create(
+ const shared_ptr <SASLContext>& ctx, const string& name
+ ) = 0;
+ };
+
+ template <typename T>
+ struct registeredMechanismImpl : public registeredMechanism {
+
+ shared_ptr <SASLMechanism> create(
+ const shared_ptr <SASLContext>& ctx,
+ const string& name
+ ) {
+
+ return vmime::make_shared <T>(ctx, name);
+ }
+ };
+
+ typedef std::map <string, shared_ptr <registeredMechanism> > MapType;
+ MapType m_mechs;
+
+public:
+
+ static SASLMechanismFactory* getInstance();
+
+ /** Register a mechanism into this factory, so that subsequent
+ * calls to create return a valid object for this mechanism.
+ *
+ * @param name mechanism name
+ */
+ template <typename MECH_CLASS>
+ void registerMechanism(const string& name) {
+
+ m_mechs.insert(
+ MapType::value_type(
+ name,
+ vmime::make_shared <registeredMechanismImpl <MECH_CLASS> >()
+ )
+ );
+ }
+
+ /** Create a mechanism object given its name.
+ *
+ * @param ctx SASL context
+ * @param name mechanism name
+ * @return a new mechanism object
+ * @throw exceptions::no_such_mechanism if no mechanism is
+ * registered for the specified name
+ */
+ shared_ptr <SASLMechanism> create(const shared_ptr <SASLContext>& ctx, const string& name);
+
+ /** Return a list of supported mechanisms. This includes mechanisms
+ * registered using registerMechanism() as well as the ones that
+ * are built-in.
+ *
+ * @return list of supported mechanisms
+ */
+ const std::vector <string> getSupportedMechanisms() const;
+
+ /** Test whether an authentication mechanism is supported.
+ *
+ * @param name mechanism name
+ * @return true if the specified mechanism is supported,
+ * false otherwise
+ */
+ bool isMechanismSupported(const string& name) const;
+
+ /** Test whether an authentication mechanism is directly supported
+ * by the underlying SASL library.
+ *
+ * @param name mechanism name
+ * @return true if the specified mechanism is built-in,
+ * or false otherwise
+ */
+ bool isBuiltinMechanism(const string& name) const;
+
+private:
+
+#ifdef GSASL_VERSION
+ Gsasl* m_gsaslContext;
+#else
+ void* m_gsaslContext;
+#endif // GSASL_VERSION
+
+};
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+#endif // VMIME_SECURITY_SASL_SASLMECHANISMFACTORY_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/sasl/SASLSession.cpp b/vmime-master/src/vmime/security/sasl/SASLSession.cpp
new file mode 100644
index 0000000..7498b46
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/SASLSession.cpp
@@ -0,0 +1,221 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include <sstream>
+
+#include <gsasl.h>
+
+#include "vmime/security/sasl/SASLSession.hpp"
+
+#include "vmime/security/sasl/SASLContext.hpp"
+#include "vmime/security/sasl/SASLSocket.hpp"
+#include "vmime/security/sasl/SASLAuthenticator.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+SASLSession::SASLSession(
+ const string& serviceName,
+ const shared_ptr <SASLContext>& ctx,
+ const shared_ptr <authenticator>& auth,
+ const shared_ptr <SASLMechanism>& mech
+)
+ : m_serviceName(serviceName),
+ m_context(ctx),
+ m_auth(auth),
+ m_mech(mech),
+ m_gsaslContext(0),
+ m_gsaslSession(0) {
+
+ if (gsasl_init(&m_gsaslContext) != GSASL_OK) {
+ throw std::bad_alloc();
+ }
+
+ gsasl_client_start(m_gsaslContext, mech->getName().c_str(), &m_gsaslSession);
+
+ gsasl_callback_set(m_gsaslContext, gsaslCallback);
+ gsasl_callback_hook_set(m_gsaslContext, this);
+}
+
+
+SASLSession::~SASLSession() {
+
+ gsasl_finish(m_gsaslSession);
+ m_gsaslSession = NULL;
+
+ gsasl_done(m_gsaslContext);
+ m_gsaslContext = NULL;
+}
+
+
+// static
+shared_ptr <SASLSession> SASLSession::create(
+ const string& serviceName,
+ const shared_ptr <SASLContext>& ctx,
+ const shared_ptr <authenticator>& auth,
+ const shared_ptr <SASLMechanism>& mech
+) {
+
+ return shared_ptr <SASLSession>(new SASLSession(serviceName, ctx, auth, mech));
+}
+
+
+void SASLSession::init() {
+
+ shared_ptr <SASLAuthenticator> saslAuth = dynamicCast <SASLAuthenticator>(m_auth);
+
+ if (saslAuth) {
+ saslAuth->setSASLMechanism(m_mech);
+ saslAuth->setSASLSession(dynamicCast <SASLSession>(shared_from_this()));
+ }
+}
+
+
+shared_ptr <authenticator> SASLSession::getAuthenticator() {
+
+ return m_auth;
+}
+
+
+shared_ptr <SASLMechanism> SASLSession::getMechanism() {
+
+ return m_mech;
+}
+
+
+shared_ptr <SASLContext> SASLSession::getContext() {
+
+ return m_context;
+}
+
+
+bool SASLSession::evaluateChallenge(
+ const byte_t* challenge,
+ const size_t challengeLen,
+ byte_t** response,
+ size_t* responseLen
+) {
+
+ return m_mech->step(
+ dynamicCast <SASLSession>(shared_from_this()),
+ challenge, challengeLen, response, responseLen
+ );
+}
+
+
+shared_ptr <net::socket> SASLSession::getSecuredSocket(const shared_ptr <net::socket>& sok) {
+
+ return make_shared <SASLSocket>(dynamicCast <SASLSession>(shared_from_this()), sok);
+}
+
+
+const string SASLSession::getServiceName() const {
+
+ return m_serviceName;
+}
+
+
+// static
+int SASLSession::gsaslCallback(
+ Gsasl* ctx,
+ Gsasl_session* sctx,
+ Gsasl_property prop
+) {
+
+ SASLSession* sess = reinterpret_cast <SASLSession*>(gsasl_callback_hook_get(ctx));
+
+ if (!sess) {
+ return GSASL_AUTHENTICATION_ERROR;
+ }
+
+ shared_ptr <authenticator> auth = sess->getAuthenticator();
+
+ try {
+
+ string res;
+
+ switch (prop) {
+
+ case GSASL_AUTHID:
+
+ res = auth->getUsername();
+ break;
+
+ case GSASL_PASSWORD:
+
+ res = auth->getPassword();
+ break;
+
+ case GSASL_ANONYMOUS_TOKEN:
+
+ res = auth->getAnonymousToken();
+ break;
+
+ case GSASL_HOSTNAME:
+
+ res = auth->getHostname();
+ break;
+
+ case GSASL_SERVICE:
+
+ res = auth->getServiceName();
+ break;
+
+ case GSASL_AUTHZID:
+ case GSASL_GSSAPI_DISPLAY_NAME:
+ case GSASL_PASSCODE:
+ case GSASL_SUGGESTED_PIN:
+ case GSASL_PIN:
+ case GSASL_REALM:
+
+ default:
+
+ return GSASL_NO_CALLBACK;
+ }
+
+ gsasl_property_set(sctx, prop, res.c_str());
+
+ return GSASL_OK;
+
+ } catch (...) {
+
+ return GSASL_NO_CALLBACK;
+ }
+}
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
diff --git a/vmime-master/src/vmime/security/sasl/SASLSession.hpp b/vmime-master/src/vmime/security/sasl/SASLSession.hpp
new file mode 100644
index 0000000..7fc7225
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/SASLSession.hpp
@@ -0,0 +1,180 @@
+//
+// 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_SECURITY_SASL_SASLSESSION_HPP_INCLUDED
+#define VMIME_SECURITY_SASL_SASLSESSION_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/socket.hpp"
+
+#include "vmime/security/sasl/SASLAuthenticator.hpp"
+#include "vmime/security/sasl/SASLMechanism.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+class SASLContext;
+
+
+/** An SASL client session.
+ */
+class VMIME_EXPORT SASLSession : public object, public enable_shared_from_this <SASLSession> {
+
+ friend class builtinSASLMechanism;
+ friend class SASLSocket;
+
+public:
+
+ ~SASLSession();
+
+ /** Construct a new SASL session.
+ *
+ * @param serviceName name of the service using this session
+ * @param ctx SASL context
+ * @param auth authenticator to use for this session
+ * @param mech SASL mechanism
+ */
+ static shared_ptr <SASLSession> create(
+ const string& serviceName,
+ const shared_ptr <SASLContext>& ctx,
+ const shared_ptr <authenticator>& auth,
+ const shared_ptr <SASLMechanism>& mech
+ );
+
+ /** Initialize this SASL session. This must be called before
+ * calling any other method on this object (except accessors).
+ */
+ void init();
+
+ /** Return the authenticator used for this session. This is the
+ * authenticator which has been previously set with a call to
+ * setAuthenticator().
+ *
+ * @return authenticator object
+ */
+ shared_ptr <authenticator> getAuthenticator();
+
+ /** Return the mechanism used for this session.
+ *
+ * @return SASL mechanism
+ */
+ shared_ptr <SASLMechanism> getMechanism();
+
+ /** Return the SASL context.
+ *
+ * @return SASL context
+ */
+ shared_ptr <SASLContext> getContext();
+
+ /** Perform one step of SASL authentication. Accept data from the
+ * server (challenge), process it and return data to be returned
+ * in response to the server.
+ *
+ * If the challenge is empty (challengeLen == 0), the initial
+ * response is returned, if the mechanism has one.
+ *
+ * @param challenge challenge sent from the server
+ * @param challengeLen length of challenge
+ * @param response response to send to the server (allocated by
+ * this function, free with delete[])
+ * @param responseLen length of response buffer
+ * @return true if authentication terminated successfully, or
+ * false if the authentication process should continue
+ * @throw exceptions::sasl_exception if an error occurred during
+ * authentication (in this case, the values in 'response' and
+ * 'responseLen' are undetermined)
+ */
+ bool evaluateChallenge(
+ const byte_t* challenge,
+ const size_t challengeLen,
+ byte_t** response,
+ size_t* responseLen
+ );
+
+ /** Return a socket in which transmitted data is integrity
+ * and/or privacy protected, depending on the QOP (Quality of
+ * Protection) negotiated during the SASL authentication.
+ *
+ * @param sok socket to wrap
+ * @return secured socket
+ */
+ shared_ptr <net::socket> getSecuredSocket(const shared_ptr <net::socket>& sok);
+
+ /** Return the name of the service which is using this
+ * SASL session (eg. "imap"). This value should be returned
+ * by the authenticator when INFO_SERVICE is requested.
+ *
+ * @return service name
+ */
+ const string getServiceName() const;
+
+private:
+
+ SASLSession(
+ const string& serviceName,
+ const shared_ptr <SASLContext>& ctx,
+ const shared_ptr <authenticator>& auth,
+ const shared_ptr <SASLMechanism>& mech
+ );
+
+
+ const string m_serviceName;
+
+ shared_ptr <SASLContext> m_context;
+ shared_ptr <authenticator> m_auth;
+ shared_ptr <SASLMechanism> m_mech;
+
+#ifdef GSASL_VERSION
+ Gsasl* m_gsaslContext;
+ Gsasl_session* m_gsaslSession;
+
+ static int gsaslCallback(Gsasl* ctx, Gsasl_session* sctx, Gsasl_property prop);
+#else
+ void* m_gsaslContext;
+ void* m_gsaslSession;
+
+ static int gsaslCallback(void* ctx, void* sctx, int prop);
+#endif // GSASL_VERSION
+
+};
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+#endif // VMIME_SECURITY_SASL_SASLSESSION_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/sasl/SASLSocket.cpp b/vmime-master/src/vmime/security/sasl/SASLSocket.cpp
new file mode 100644
index 0000000..0dbafd8
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/SASLSocket.cpp
@@ -0,0 +1,273 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/security/sasl/SASLSocket.hpp"
+#include "vmime/security/sasl/SASLSession.hpp"
+
+#include "vmime/utility/stringUtils.hpp"
+
+#include "vmime/exception.hpp"
+
+#include <algorithm>
+#include <cstring>
+
+#include <gsasl.h>
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+
+SASLSocket::SASLSocket(
+ const shared_ptr <SASLSession>& sess,
+ const shared_ptr <net::socket>& wrapped
+)
+ : m_session(sess),
+ m_wrapped(wrapped),
+ m_pendingBuffer(0),
+ m_pendingPos(0),
+ m_pendingLen(0) {
+
+}
+
+
+SASLSocket::~SASLSocket() {
+
+ if (m_pendingBuffer) {
+ delete [] m_pendingBuffer;
+ }
+}
+
+
+void SASLSocket::connect(const string& address, const port_t port) {
+
+ m_wrapped->connect(address, port);
+}
+
+
+void SASLSocket::disconnect() {
+
+ m_wrapped->disconnect();
+}
+
+
+bool SASLSocket::isConnected() const {
+
+ return m_wrapped->isConnected();
+}
+
+
+size_t SASLSocket::getBlockSize() const {
+
+ return m_wrapped->getBlockSize();
+}
+
+
+const string SASLSocket::getPeerName() const {
+
+ return m_wrapped->getPeerName();
+}
+
+
+const string SASLSocket::getPeerAddress() const {
+
+ return m_wrapped->getPeerAddress();
+}
+
+
+shared_ptr <net::timeoutHandler> SASLSocket::getTimeoutHandler() {
+
+ return m_wrapped->getTimeoutHandler();
+}
+
+
+void SASLSocket::setTracer(const shared_ptr <net::tracer>& tracer) {
+
+ m_wrapped->setTracer(tracer);
+}
+
+
+shared_ptr <net::tracer> SASLSocket::getTracer() {
+
+ return m_wrapped->getTracer();
+}
+
+
+bool SASLSocket::waitForRead(const int msecs) {
+
+ return m_wrapped->waitForRead(msecs);
+}
+
+
+bool SASLSocket::waitForWrite(const int msecs) {
+
+ return m_wrapped->waitForWrite(msecs);
+}
+
+
+void SASLSocket::receive(string& buffer) {
+
+ const size_t n = receiveRaw(m_recvBuffer, sizeof(m_recvBuffer));
+
+ buffer = utility::stringUtils::makeStringFromBytes(m_recvBuffer, n);
+}
+
+
+size_t SASLSocket::receiveRaw(byte_t* buffer, const size_t count) {
+
+ if (m_pendingLen != 0) {
+
+ const size_t copyLen =
+ (count >= m_pendingLen ? m_pendingLen : count);
+
+ std::copy(
+ m_pendingBuffer + m_pendingPos,
+ m_pendingBuffer + m_pendingPos + copyLen,
+ buffer
+ );
+
+ m_pendingLen -= copyLen;
+ m_pendingPos += copyLen;
+
+ if (m_pendingLen == 0) {
+
+ delete [] m_pendingBuffer;
+
+ m_pendingBuffer = 0;
+ m_pendingPos = 0;
+ m_pendingLen = 0;
+ }
+
+ return copyLen;
+ }
+
+ const size_t n = m_wrapped->receiveRaw(buffer, count);
+
+ byte_t* output = 0;
+ size_t outputLen = 0;
+
+ m_session->getMechanism()->decode(m_session, buffer, n, &output, &outputLen);
+
+ // If we can not copy all decoded data into the output buffer, put
+ // remaining data into a pending buffer for next calls to receive()
+ if (outputLen > count) {
+
+ std::copy(output, output + count, buffer);
+
+ m_pendingBuffer = output;
+ m_pendingLen = outputLen;
+ m_pendingPos = count;
+
+ return count;
+
+ } else {
+
+ std::copy(output, output + outputLen, buffer);
+
+ delete [] output;
+
+ return outputLen;
+ }
+}
+
+
+void SASLSocket::send(const string& buffer) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(buffer.data()), buffer.length());
+}
+
+
+void SASLSocket::send(const char* str) {
+
+ sendRaw(reinterpret_cast <const byte_t*>(str), strlen(str));
+}
+
+
+void SASLSocket::sendRaw(const byte_t* buffer, const size_t count) {
+
+ byte_t* output = 0;
+ size_t outputLen = 0;
+
+ m_session->getMechanism()->encode(
+ m_session, buffer, count, &output, &outputLen
+ );
+
+ try {
+
+ m_wrapped->sendRaw(output, outputLen);
+
+ } catch (...) {
+
+ delete [] output;
+ throw;
+ }
+
+ delete [] output;
+}
+
+
+size_t SASLSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count) {
+
+ byte_t* output = 0;
+ size_t outputLen = 0;
+
+ m_session->getMechanism()->encode(m_session, buffer, count, &output, &outputLen);
+
+ size_t bytesSent = 0;
+
+ try {
+
+ bytesSent = m_wrapped->sendRawNonBlocking(output, outputLen);
+
+ } catch (...) {
+
+ delete [] output;
+ throw;
+ }
+
+ delete [] output;
+
+ return bytesSent;
+}
+
+
+unsigned int SASLSocket::getStatus() const {
+
+ return m_wrapped->getStatus();
+}
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
diff --git a/vmime-master/src/vmime/security/sasl/SASLSocket.hpp b/vmime-master/src/vmime/security/sasl/SASLSocket.hpp
new file mode 100644
index 0000000..ac0e89e
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/SASLSocket.hpp
@@ -0,0 +1,108 @@
+//
+// 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_SECURITY_SASL_SASLSOCKET_HPP_INCLUDED
+#define VMIME_SECURITY_SASL_SASLSOCKET_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/types.hpp"
+
+#include "vmime/net/socket.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+class SASLSession;
+
+
+/** A socket which provides data integrity and/or privacy protection.
+ */
+class VMIME_EXPORT SASLSocket : public net::socket {
+
+public:
+
+ SASLSocket(
+ const shared_ptr <SASLSession>& sess,
+ const shared_ptr <net::socket>& wrapped
+ );
+
+ ~SASLSocket();
+
+ void connect(const string& address, const port_t port);
+ void disconnect();
+
+ bool isConnected() const;
+
+ bool waitForRead(const int msecs = 30000);
+ bool waitForWrite(const int msecs = 30000);
+
+ void receive(string& buffer);
+ size_t receiveRaw(byte_t* buffer, const size_t count);
+
+ void send(const string& buffer);
+ void send(const char* str);
+ void sendRaw(const byte_t* buffer, const size_t count);
+ size_t sendRawNonBlocking(const byte_t* buffer, const size_t count);
+
+ size_t getBlockSize() const;
+
+ unsigned int getStatus() const;
+
+ const string getPeerName() const;
+ const string getPeerAddress() const;
+
+ shared_ptr <net::timeoutHandler> getTimeoutHandler();
+
+ void setTracer(const shared_ptr <net::tracer>& tracer);
+ shared_ptr <net::tracer> getTracer();
+
+private:
+
+ shared_ptr <SASLSession> m_session;
+ shared_ptr <net::socket> m_wrapped;
+
+ byte_t* m_pendingBuffer;
+ size_t m_pendingPos;
+ size_t m_pendingLen;
+
+ byte_t m_recvBuffer[65536];
+};
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+#endif // VMIME_SECURITY_SASL_SASLSOCKET_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/sasl/XOAuth2SASLAuthenticator.cpp b/vmime-master/src/vmime/security/sasl/XOAuth2SASLAuthenticator.cpp
new file mode 100644
index 0000000..ecc715a
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/XOAuth2SASLAuthenticator.cpp
@@ -0,0 +1,99 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/security/sasl/XOAuth2SASLAuthenticator.hpp"
+
+#include "vmime/security/sasl/SASLMechanism.hpp"
+#include "vmime/security/sasl/SASLSession.hpp"
+#include "vmime/security/sasl/SASLContext.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+XOAuth2SASLAuthenticator::XOAuth2SASLAuthenticator(const Mode mode)
+ : m_mode(mode) {
+
+}
+
+
+XOAuth2SASLAuthenticator::~XOAuth2SASLAuthenticator() {
+
+}
+
+
+const std::vector <shared_ptr <SASLMechanism> >
+ XOAuth2SASLAuthenticator::getAcceptableMechanisms(
+ const std::vector <shared_ptr <SASLMechanism> >& available,
+ const shared_ptr <SASLMechanism>& suggested
+ ) const {
+
+ if (m_mode == MODE_EXCLUSIVE) {
+
+ std::vector <shared_ptr <SASLMechanism> > mechs;
+
+ for (size_t i = available.size() ; i != 0 ; --i) {
+
+ shared_ptr <SASLMechanism> mech = available[i - 1];
+
+ if ("XOAUTH2" == mech->getName()) {
+ // Only allow XOAuth2
+ mechs.push_back(mech);
+ }
+ }
+
+ return mechs;
+
+ } else {
+
+ shared_ptr <SASLMechanism> newSuggested(suggested);
+
+ for (size_t i = available.size() ; i != 0 ; --i) {
+
+ shared_ptr <SASLMechanism> mech = available[i - 1];
+
+ if ("XOAUTH2" == mech->getName()) {
+ // Suggest using XOAuth2
+ newSuggested = mech;
+ }
+ }
+
+ return defaultSASLAuthenticator::getAcceptableMechanisms(available, newSuggested);
+ }
+}
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
diff --git a/vmime-master/src/vmime/security/sasl/XOAuth2SASLAuthenticator.hpp b/vmime-master/src/vmime/security/sasl/XOAuth2SASLAuthenticator.hpp
new file mode 100644
index 0000000..e4d3d83
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/XOAuth2SASLAuthenticator.hpp
@@ -0,0 +1,77 @@
+//
+// 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_SECURITY_SASL_XOAUTH2SASLAUTHENTICATOR_HPP_INCLUDED
+#define VMIME_SECURITY_SASL_XOAUTH2SASLAUTHENTICATOR_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/security/sasl/defaultSASLAuthenticator.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+/** An authenticator that is capable of providing information
+ * for XOAuth2 authentication mechanisms (username and access token).
+ * This authenticator force using the XOAUTH2 mechanism.
+ */
+class VMIME_EXPORT XOAuth2SASLAuthenticator : public defaultSASLAuthenticator {
+
+public:
+
+ enum Mode {
+ MODE_SUGGEST, /**< Try XOAUTH2 before other mechanisms. */
+ MODE_EXCLUSIVE /**< Use XOAUTH2 and nothing else. */
+ };
+
+
+ XOAuth2SASLAuthenticator(const Mode mode);
+ ~XOAuth2SASLAuthenticator();
+
+ const std::vector <shared_ptr <SASLMechanism> > getAcceptableMechanisms(
+ const std::vector <shared_ptr <SASLMechanism> >& available,
+ const shared_ptr <SASLMechanism>& suggested
+ ) const;
+
+private:
+
+ Mode m_mode;
+};
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+#endif // VMIME_SECURITY_SASL_XOAUTH2SASLAUTHENTICATOR_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/sasl/XOAuth2SASLMechanism.cpp b/vmime-master/src/vmime/security/sasl/XOAuth2SASLMechanism.cpp
new file mode 100644
index 0000000..e5ecd4b
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/XOAuth2SASLMechanism.cpp
@@ -0,0 +1,155 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/security/sasl/XOAuth2SASLMechanism.hpp"
+
+#include "vmime/security/sasl/SASLContext.hpp"
+#include "vmime/security/sasl/SASLSession.hpp"
+
+#include "vmime/exception.hpp"
+
+#include <sstream>
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+XOAuth2SASLMechanism::XOAuth2SASLMechanism(
+ const shared_ptr <SASLContext>& ctx,
+ const string& /* name */
+)
+ : m_context(ctx),
+ m_complete(false) {
+
+}
+
+
+XOAuth2SASLMechanism::~XOAuth2SASLMechanism() {
+
+}
+
+
+const string XOAuth2SASLMechanism::getName() const {
+
+ return "XOAUTH2";
+}
+
+
+bool XOAuth2SASLMechanism::step(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* /* challenge */,
+ const size_t /* challengeLen */,
+ byte_t** response,
+ size_t* responseLen
+) {
+
+ // Build initial response
+ //
+ // The SASL XOAUTH2 initial client response has the following format:
+ // base64("user=" {User} "^Aauth=Bearer " {Access Token} "^A^A")
+
+ const std::string user(sess->getAuthenticator()->getUsername());
+ const std::string accessToken(sess->getAuthenticator()->getAccessToken());
+
+ std::ostringstream initRespBytes;
+ initRespBytes.write("user=", 5);
+ initRespBytes.write(user.c_str(), user.length());
+ initRespBytes.write("\x01", 1);
+ initRespBytes.write("auth=Bearer ", 12);
+ initRespBytes.write(accessToken.c_str(), accessToken.length());
+ initRespBytes.write("\x01\x01", 2);
+
+ const std::string initResp = initRespBytes.str();
+
+ // Set initial response
+ byte_t* res = new byte_t[initResp.length()];
+ std::copy(initResp.c_str(), initResp.c_str() + initResp.length(), res);
+
+ *response = res;
+ *responseLen = initResp.length();
+ m_complete = true;
+
+ return true;
+}
+
+
+bool XOAuth2SASLMechanism::isComplete() const {
+
+ return m_complete;
+}
+
+
+bool XOAuth2SASLMechanism::hasInitialResponse() const {
+
+ return true;
+}
+
+
+void XOAuth2SASLMechanism::encode(
+ const shared_ptr <SASLSession>& /* sess */,
+ const byte_t* input,
+ const size_t inputLen,
+ byte_t** output,
+ size_t* outputLen
+) {
+
+ // No encoding performed, just copy input bytes
+ byte_t* res = new byte_t[inputLen];
+ std::copy(input, input + inputLen, res);
+
+ *outputLen = inputLen;
+ *output = res;
+}
+
+
+void XOAuth2SASLMechanism::decode(
+ const shared_ptr <SASLSession>& /* sess */,
+ const byte_t* input,
+ const size_t inputLen,
+ byte_t** output,
+ size_t* outputLen
+) {
+
+ // No decoding performed, just copy input bytes
+ byte_t* res = new byte_t[inputLen];
+ std::copy(input, input + inputLen, res);
+
+ *outputLen = inputLen;
+ *output = res;
+}
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
diff --git a/vmime-master/src/vmime/security/sasl/XOAuth2SASLMechanism.hpp b/vmime-master/src/vmime/security/sasl/XOAuth2SASLMechanism.hpp
new file mode 100644
index 0000000..eacbb0a
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/XOAuth2SASLMechanism.hpp
@@ -0,0 +1,102 @@
+//
+// 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_SECURITY_SASL_XOAUTH2SASLMECHANISM_HPP_INCLUDED
+#define VMIME_SECURITY_SASL_XOAUTH2SASLMECHANISM_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/security/sasl/SASLMechanism.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+class SASLContext;
+
+
+/** SASL XOAUTH2 mechanism, used by GMail.
+ */
+class VMIME_EXPORT XOAuth2SASLMechanism : public SASLMechanism {
+
+public:
+
+ XOAuth2SASLMechanism(const shared_ptr <SASLContext>& ctx, const string& name);
+ ~XOAuth2SASLMechanism();
+
+
+ const string getName() const;
+
+ bool step(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* challenge,
+ const size_t challengeLen,
+ byte_t** response,
+ size_t* responseLen
+ );
+
+ bool isComplete() const;
+
+ bool hasInitialResponse() const;
+
+ void encode(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* input,
+ const size_t inputLen,
+ byte_t** output,
+ size_t* outputLen
+ );
+
+ void decode(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* input,
+ const size_t inputLen,
+ byte_t** output,
+ size_t* outputLen
+ );
+
+private:
+
+ /** SASL context */
+ shared_ptr <SASLContext> m_context;
+
+ /** Authentication process status. */
+ bool m_complete;
+};
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+#endif // VMIME_SECURITY_SASL_XOAUTH2SASLMECHANISM_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/sasl/builtinSASLMechanism.cpp b/vmime-master/src/vmime/security/sasl/builtinSASLMechanism.cpp
new file mode 100644
index 0000000..846e2cc
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/builtinSASLMechanism.cpp
@@ -0,0 +1,221 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include <gsasl.h>
+
+#include "vmime/security/sasl/builtinSASLMechanism.hpp"
+
+#include "vmime/security/sasl/SASLContext.hpp"
+#include "vmime/security/sasl/SASLSession.hpp"
+
+#include "vmime/exception.hpp"
+
+#include <stdexcept>
+#include <new>
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+builtinSASLMechanism::builtinSASLMechanism(
+ const shared_ptr <SASLContext>& ctx,
+ const string& name
+)
+ : m_context(ctx),
+ m_name(name),
+ m_complete(false) {
+
+}
+
+
+builtinSASLMechanism::~builtinSASLMechanism() {
+
+}
+
+
+const string builtinSASLMechanism::getName() const {
+
+ return m_name;
+}
+
+
+bool builtinSASLMechanism::step(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* challenge,
+ const size_t challengeLen,
+ byte_t** response,
+ size_t* responseLen
+) {
+
+ char* output = 0;
+ size_t outputLen = 0;
+
+ const int result = gsasl_step(
+ sess->m_gsaslSession,
+ reinterpret_cast <const char*>(challenge), challengeLen,
+ &output, &outputLen
+ );
+
+ if (result == GSASL_OK || result == GSASL_NEEDS_MORE) {
+
+ byte_t* res = new byte_t[outputLen];
+
+ for (size_t i = 0 ; i < outputLen ; ++i) {
+ res[i] = output[i];
+ }
+
+ *response = res;
+ *responseLen = outputLen;
+
+ gsasl_free(output);
+
+ } else {
+
+ *response = 0;
+ *responseLen = 0;
+ }
+
+ if (result == GSASL_OK) {
+
+ // Authentication process completed
+ m_complete = true;
+ return true;
+
+ } else if (result == GSASL_NEEDS_MORE) {
+
+ // Continue authentication process
+ return false;
+
+ } else if (result == GSASL_MALLOC_ERROR) {
+
+ throw std::bad_alloc();
+
+ } else {
+
+ throw exceptions::sasl_exception(
+ "Error when processing challenge: "
+ + SASLContext::getErrorMessage("gsasl_step", result)
+ );
+ }
+}
+
+
+bool builtinSASLMechanism::isComplete() const {
+
+ return m_complete;
+}
+
+
+bool builtinSASLMechanism::hasInitialResponse() const {
+
+ // It seems GNU SASL does not support initial response
+ return false;
+}
+
+
+void builtinSASLMechanism::encode(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* input,
+ const size_t inputLen,
+ byte_t** output,
+ size_t* outputLen
+) {
+
+ char* coutput = 0;
+ size_t coutputLen = 0;
+
+ if (gsasl_encode(sess->m_gsaslSession, reinterpret_cast <const char*>(input), inputLen,
+ &coutput, &coutputLen) != GSASL_OK) {
+
+ throw exceptions::sasl_exception("Encoding error.");
+ }
+
+ try {
+
+ byte_t* res = new byte_t[coutputLen];
+
+ std::copy(coutput, coutput + coutputLen, res);
+
+ *output = res;
+ *outputLen = static_cast <int>(coutputLen);
+
+ } catch (...) {
+
+ gsasl_free(coutput);
+ throw;
+ }
+
+ gsasl_free(coutput);
+}
+
+
+void builtinSASLMechanism::decode(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* input,
+ const size_t inputLen,
+ byte_t** output,
+ size_t* outputLen
+) {
+
+ char* coutput = 0;
+ size_t coutputLen = 0;
+
+ try {
+
+ if (gsasl_decode(sess->m_gsaslSession, reinterpret_cast <const char*>(input), inputLen,
+ &coutput, &coutputLen) != GSASL_OK) {
+
+ throw exceptions::sasl_exception("Decoding error.");
+ }
+
+ byte_t* res = new byte_t[coutputLen];
+
+ std::copy(coutput, coutput + coutputLen, res);
+
+ *output = res;
+ *outputLen = static_cast <int>(coutputLen);
+
+ } catch (...) {
+
+ gsasl_free(coutput);
+ throw;
+ }
+
+ gsasl_free(coutput);
+}
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
diff --git a/vmime-master/src/vmime/security/sasl/builtinSASLMechanism.hpp b/vmime-master/src/vmime/security/sasl/builtinSASLMechanism.hpp
new file mode 100644
index 0000000..2e412d6
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/builtinSASLMechanism.hpp
@@ -0,0 +1,105 @@
+//
+// 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_SECURITY_SASL_BUILTINSASLMECHANISM_HPP_INCLUDED
+#define VMIME_SECURITY_SASL_BUILTINSASLMECHANISM_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/security/sasl/SASLMechanism.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+class SASLContext;
+
+
+/** A built-in authentication mechanism that relies on
+ * the GNU SASL library.
+ */
+class VMIME_EXPORT builtinSASLMechanism : public SASLMechanism {
+
+public:
+
+ builtinSASLMechanism(const shared_ptr <SASLContext>& ctx, const string& name);
+ ~builtinSASLMechanism();
+
+
+ const string getName() const;
+
+ bool step(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* challenge,
+ const size_t challengeLen,
+ byte_t** response, size_t* responseLen
+ );
+
+ bool isComplete() const;
+
+ bool hasInitialResponse() const;
+
+ void encode(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* input,
+ const size_t inputLen,
+ byte_t** output,
+ size_t* outputLen
+ );
+
+ void decode(
+ const shared_ptr <SASLSession>& sess,
+ const byte_t* input,
+ const size_t inputLen,
+ byte_t** output,
+ size_t* outputLen
+ );
+
+private:
+
+ /** SASL context */
+ shared_ptr <SASLContext> m_context;
+
+ /** Mechanism name */
+ const string m_name;
+
+ /** Authentication process status. */
+ bool m_complete;
+};
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+#endif // VMIME_SECURITY_SASL_BUILTINSASLMECHANISM_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/security/sasl/defaultSASLAuthenticator.cpp b/vmime-master/src/vmime/security/sasl/defaultSASLAuthenticator.cpp
new file mode 100644
index 0000000..ebd7e68
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/defaultSASLAuthenticator.cpp
@@ -0,0 +1,159 @@
+//
+// 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.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/security/sasl/defaultSASLAuthenticator.hpp"
+
+#include "vmime/security/sasl/SASLMechanism.hpp"
+#include "vmime/security/sasl/SASLSession.hpp"
+#include "vmime/security/sasl/SASLContext.hpp"
+
+#include "vmime/net/service.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+defaultSASLAuthenticator::defaultSASLAuthenticator() {
+
+}
+
+
+defaultSASLAuthenticator::~defaultSASLAuthenticator() {
+
+}
+
+
+const std::vector <shared_ptr <SASLMechanism> > defaultSASLAuthenticator::getAcceptableMechanisms(
+ const std::vector <shared_ptr <SASLMechanism> >& available,
+ const shared_ptr <SASLMechanism>& suggested
+) const {
+
+ if (suggested) {
+
+ std::vector <shared_ptr <SASLMechanism> > res;
+
+ res.push_back(suggested);
+
+ for (unsigned int i = 0 ; i < available.size() ; ++i) {
+
+ if (available[i]->getName() != suggested->getName()) {
+ res.push_back(available[i]);
+ }
+ }
+
+ return res;
+
+ } else {
+
+ return available;
+ }
+}
+
+
+const string defaultSASLAuthenticator::getUsername() const {
+
+ return m_default.getUsername();
+}
+
+
+const string defaultSASLAuthenticator::getPassword() const {
+
+ return m_default.getPassword();
+}
+
+
+const string defaultSASLAuthenticator::getAccessToken() const {
+
+ return m_default.getAccessToken();
+}
+
+
+const string defaultSASLAuthenticator::getHostname() const {
+
+ return m_default.getHostname();
+}
+
+
+const string defaultSASLAuthenticator::getAnonymousToken() const {
+
+ return m_default.getAnonymousToken();
+}
+
+
+const string defaultSASLAuthenticator::getServiceName() const {
+
+ return m_saslSession.lock()->getServiceName();
+}
+
+
+void defaultSASLAuthenticator::setService(const shared_ptr <net::service>& serv) {
+
+ m_service = serv;
+ m_default.setService(serv);
+}
+
+
+weak_ptr <net::service> defaultSASLAuthenticator::getService() const {
+
+ return m_service;
+}
+
+
+void defaultSASLAuthenticator::setSASLSession(const shared_ptr <SASLSession>& sess) {
+
+ m_saslSession = sess;
+}
+
+
+shared_ptr <SASLSession> defaultSASLAuthenticator::getSASLSession() const {
+
+ return m_saslSession.lock();
+}
+
+
+void defaultSASLAuthenticator::setSASLMechanism(const shared_ptr <SASLMechanism>& mech) {
+
+ m_saslMech = mech;
+}
+
+
+shared_ptr <SASLMechanism> defaultSASLAuthenticator::getSASLMechanism() const {
+
+ return m_saslMech;
+}
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
diff --git a/vmime-master/src/vmime/security/sasl/defaultSASLAuthenticator.hpp b/vmime-master/src/vmime/security/sasl/defaultSASLAuthenticator.hpp
new file mode 100644
index 0000000..368e9ef
--- /dev/null
+++ b/vmime-master/src/vmime/security/sasl/defaultSASLAuthenticator.hpp
@@ -0,0 +1,91 @@
+//
+// 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_SECURITY_SASL_DEFAULTSASLAUTHENTICATOR_HPP_INCLUDED
+#define VMIME_SECURITY_SASL_DEFAULTSASLAUTHENTICATOR_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+
+#include "vmime/security/sasl/SASLAuthenticator.hpp"
+#include "vmime/security/defaultAuthenticator.hpp"
+
+
+namespace vmime {
+namespace security {
+namespace sasl {
+
+
+/** An authenticator that is capable of providing information
+ * for simple authentication mechanisms (username and password).
+ */
+class VMIME_EXPORT defaultSASLAuthenticator : public SASLAuthenticator {
+
+public:
+
+ defaultSASLAuthenticator();
+ ~defaultSASLAuthenticator();
+
+ const std::vector <shared_ptr <SASLMechanism> > getAcceptableMechanisms(
+ const std::vector <shared_ptr <SASLMechanism> >& available,
+ const shared_ptr <SASLMechanism>& suggested
+ ) const;
+
+ const string getUsername() const;
+ const string getPassword() const;
+ const string getHostname() const;
+ const string getAnonymousToken() const;
+ const string getServiceName() const;
+ const string getAccessToken() const;
+
+ void setService(const shared_ptr <net::service>& serv);
+ weak_ptr <net::service> getService() const;
+
+ void setSASLSession(const shared_ptr <SASLSession>& sess);
+ shared_ptr <SASLSession> getSASLSession() const;
+
+ void setSASLMechanism(const shared_ptr <SASLMechanism>& mech);
+ shared_ptr <SASLMechanism> getSASLMechanism() const;
+
+private:
+
+ defaultAuthenticator m_default;
+
+ weak_ptr <net::service> m_service;
+ weak_ptr <SASLSession> m_saslSession;
+ shared_ptr <SASLMechanism> m_saslMech;
+};
+
+
+} // sasl
+} // security
+} // vmime
+
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT
+
+#endif // VMIME_SECURITY_SASL_DEFAULTSASLAUTHENTICATOR_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/streamContentHandler.cpp b/vmime-master/src/vmime/streamContentHandler.cpp
new file mode 100644
index 0000000..e35bcd7
--- /dev/null
+++ b/vmime-master/src/vmime/streamContentHandler.cpp
@@ -0,0 +1,257 @@
+//
+// 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.
+//
+
+#include "vmime/streamContentHandler.hpp"
+
+#include "vmime/utility/outputStreamAdapter.hpp"
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+#include "vmime/utility/seekableInputStream.hpp"
+#include "vmime/utility/streamUtils.hpp"
+
+
+namespace vmime {
+
+
+streamContentHandler::streamContentHandler()
+ : m_encoding(NO_ENCODING),
+ m_stream(null),
+ m_length(0) {
+
+}
+
+
+streamContentHandler::streamContentHandler(
+ const shared_ptr <utility::inputStream>& is,
+ const size_t length,
+ const vmime::encoding& enc
+) {
+
+ setData(is, length, enc);
+}
+
+
+streamContentHandler::~streamContentHandler() {
+
+}
+
+
+streamContentHandler::streamContentHandler(const streamContentHandler& cts)
+ : contentHandler(),
+ m_contentType(cts.m_contentType),
+ m_encoding(cts.m_encoding),
+ m_stream(cts.m_stream),
+ m_length(cts.m_length) {
+
+}
+
+
+shared_ptr <contentHandler> streamContentHandler::clone() const {
+
+ return make_shared <streamContentHandler>(*this);
+}
+
+
+streamContentHandler& streamContentHandler::operator=(const streamContentHandler& cts) {
+
+ m_contentType = cts.m_contentType;
+ m_encoding = cts.m_encoding;
+
+ m_stream = cts.m_stream;
+ m_length = cts.m_length;
+
+ return *this;
+}
+
+
+void streamContentHandler::setData(
+ const shared_ptr <utility::inputStream>& is,
+ const size_t length,
+ const vmime::encoding& enc
+) {
+
+ m_encoding = enc;
+ m_length = length;
+ m_stream = is;
+}
+
+
+void streamContentHandler::generate(
+ utility::outputStream& os,
+ const vmime::encoding& enc,
+ const size_t maxLineLength
+) const {
+
+ if (!m_stream) {
+ return;
+ }
+
+ // Managed data is already encoded
+ if (isEncoded()) {
+
+ // The data is already encoded but the encoding specified for
+ // the generation is different from the current one. We need
+ // to re-encode data: decode from input buffer to temporary
+ // buffer, and then re-encode to output stream...
+ if (m_encoding != enc) {
+
+ shared_ptr <utility::encoder::encoder> theDecoder = m_encoding.getEncoder();
+ shared_ptr <utility::encoder::encoder> theEncoder = enc.getEncoder();
+
+ theEncoder->getProperties()["maxlinelength"] = maxLineLength;
+ theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT);
+
+ m_stream->reset(); // may not work...
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter tempOut(oss);
+
+ theDecoder->decode(*m_stream, tempOut);
+
+ string str = oss.str();
+ utility::inputStreamStringAdapter tempIn(str);
+
+ theEncoder->encode(tempIn, os);
+
+ // No encoding to perform
+ } else {
+
+ m_stream->reset(); // may not work...
+
+ utility::bufferedStreamCopy(*m_stream, os);
+ }
+
+ // Need to encode data before
+ } else {
+
+ shared_ptr <utility::encoder::encoder> theEncoder = enc.getEncoder();
+ theEncoder->getProperties()["maxlinelength"] = maxLineLength;
+ theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT);
+
+ m_stream->reset(); // may not work...
+
+ theEncoder->encode(*m_stream, os);
+ }
+}
+
+
+void streamContentHandler::extract(
+ utility::outputStream& os,
+ utility::progressListener* progress
+) const {
+
+ if (!m_stream) {
+ return;
+ }
+
+ // No decoding to perform
+ if (!isEncoded()) {
+
+ m_stream->reset(); // may not work...
+
+ if (progress) {
+ utility::bufferedStreamCopy(*m_stream, os, getLength(), progress);
+ } else {
+ utility::bufferedStreamCopy(*m_stream, os);
+ }
+
+ // Need to decode data
+ } else {
+
+ shared_ptr <utility::encoder::encoder> theDecoder = m_encoding.getEncoder();
+
+ m_stream->reset(); // may not work...
+
+ utility::progressListenerSizeAdapter plsa(progress, getLength());
+
+ theDecoder->decode(*m_stream, os, &plsa);
+ }
+}
+
+
+void streamContentHandler::extractRaw(
+ utility::outputStream& os,
+ utility::progressListener* progress
+) const {
+
+ if (!m_stream) {
+ return;
+ }
+
+ m_stream->reset(); // may not work...
+
+ if (progress) {
+ utility::bufferedStreamCopy(*m_stream, os, getLength(), progress);
+ } else {
+ utility::bufferedStreamCopy(*m_stream, os);
+ }
+}
+
+
+size_t streamContentHandler::getLength() const {
+
+ return m_length;
+}
+
+
+bool streamContentHandler::isEmpty() const {
+
+ return m_length == 0 || !m_stream;
+}
+
+
+bool streamContentHandler::isEncoded() const {
+
+ return m_encoding != NO_ENCODING;
+}
+
+
+const vmime::encoding& streamContentHandler::getEncoding() const {
+
+ return m_encoding;
+}
+
+
+bool streamContentHandler::isBuffered() const {
+
+ if (dynamicCast <utility::seekableInputStream>(m_stream)) {
+ return true;
+ }
+
+ // FIXME: some streams can be resetted
+ return false;
+}
+
+
+void streamContentHandler::setContentTypeHint(const mediaType& type) {
+
+ m_contentType = type;
+}
+
+
+const mediaType streamContentHandler::getContentTypeHint() const {
+
+ return m_contentType;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/streamContentHandler.hpp b/vmime-master/src/vmime/streamContentHandler.hpp
new file mode 100644
index 0000000..6964a1c
--- /dev/null
+++ b/vmime-master/src/vmime/streamContentHandler.hpp
@@ -0,0 +1,126 @@
+//
+// 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_STREAMCONTENTHANDLER_HPP_INCLUDED
+#define VMIME_STREAMCONTENTHANDLER_HPP_INCLUDED
+
+
+#include "vmime/contentHandler.hpp"
+
+
+namespace vmime {
+
+
+/** A content handler which obtains its data from a stream.
+ */
+class VMIME_EXPORT streamContentHandler : public contentHandler {
+
+public:
+
+ /** Creates a new empty content handler. No data can be extracted until
+ * an input stream is set using setData() function.
+ *
+ * @return a reference to a new content handler
+ */
+ streamContentHandler();
+
+ /** Creates a new content handler using an input stream.
+ *
+ * @param is input stream from which data will be obtained
+ * @param length expected stream length. May be zero, but it is highly
+ * recommended to set this parameter to take part of some optimizations
+ * and features (eg. SMTP CHUNKING/SIZE extension).
+ * @param enc set to anything other than NO_ENCODING if the data obtained
+ * from the stream is already encoded with the specified encoding
+ *
+ * @return a reference to a new content handler
+ */
+ streamContentHandler(
+ const shared_ptr <utility::inputStream>& is,
+ const size_t length,
+ const vmime::encoding& enc = NO_ENCODING
+ );
+
+ ~streamContentHandler();
+
+ streamContentHandler(const streamContentHandler& cts);
+ streamContentHandler& operator=(const streamContentHandler& cts);
+
+ shared_ptr <contentHandler> clone() const;
+
+ /** Sets the data managed by this content handler.
+ *
+ * @param is input stream from which data will be obtained
+ * @param length expected stream length. May be zero, but it is highly
+ * recommended to set this parameter to take part of some optimizations
+ * and features (eg. SMTP CHUNKING/SIZE extension).
+ * @param enc set to anything other than NO_ENCODING if the data obtained
+ * from the stream is already encoded with the specified encoding
+ */
+ void setData(
+ const shared_ptr <utility::inputStream>& is,
+ const size_t length,
+ const vmime::encoding& enc = NO_ENCODING
+ );
+
+
+ void generate(
+ utility::outputStream& os,
+ const vmime::encoding& enc,
+ const size_t maxLineLength = lineLengthLimits::infinite
+ ) const;
+
+ void extract(utility::outputStream& os, utility::progressListener* progress = NULL) const;
+ void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const;
+
+ size_t getLength() const;
+
+ bool isEncoded() const;
+
+ const vmime::encoding& getEncoding() const;
+
+ bool isEmpty() const;
+
+ bool isBuffered() const;
+
+ void setContentTypeHint(const mediaType& type);
+ const mediaType getContentTypeHint() const;
+
+private:
+
+ mediaType m_contentType;
+
+ // Equals to NO_ENCODING if data is not encoded, otherwise this
+ // specifies the encoding that have been used to encode the data.
+ vmime::encoding m_encoding;
+
+ // Actual data
+ mutable shared_ptr <utility::inputStream> m_stream;
+ size_t m_length;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_STREAMCONTENTHANDLER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/stringContentHandler.cpp b/vmime-master/src/vmime/stringContentHandler.cpp
new file mode 100644
index 0000000..f7fadf7
--- /dev/null
+++ b/vmime-master/src/vmime/stringContentHandler.cpp
@@ -0,0 +1,228 @@
+//
+// 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.
+//
+
+#include "vmime/stringContentHandler.hpp"
+
+#include "vmime/utility/inputStreamStringAdapter.hpp"
+#include "vmime/utility/outputStreamAdapter.hpp"
+#include "vmime/utility/streamUtils.hpp"
+
+
+namespace vmime {
+
+
+stringContentHandler::stringContentHandler() {
+
+}
+
+
+stringContentHandler::stringContentHandler(
+ const string& buffer,
+ const vmime::encoding& enc
+)
+ : m_encoding(enc),
+ m_string(buffer) {
+
+}
+
+
+stringContentHandler::stringContentHandler(
+ const stringContentHandler& cts
+)
+ : contentHandler(),
+ m_contentType(cts.m_contentType),
+ m_encoding(cts.m_encoding),
+ m_string(cts.m_string) {
+
+}
+
+
+stringContentHandler::~stringContentHandler() {
+
+}
+
+
+shared_ptr <contentHandler> stringContentHandler::clone() const {
+
+ return make_shared <stringContentHandler>(*this);
+}
+
+
+stringContentHandler& stringContentHandler::operator=(const stringContentHandler& cts) {
+
+ m_contentType = cts.m_contentType;
+ m_encoding = cts.m_encoding;
+ m_string = cts.m_string;
+
+ return *this;
+}
+
+
+void stringContentHandler::setData(const string& buffer, const vmime::encoding& enc) {
+
+ m_encoding = enc;
+ m_string = buffer;
+}
+
+
+stringContentHandler& stringContentHandler::operator=(const string& buffer) {
+
+ setData(buffer, NO_ENCODING);
+ return *this;
+}
+
+
+void stringContentHandler::generate(
+ utility::outputStream& os,
+ const vmime::encoding& enc,
+ const size_t maxLineLength
+) const {
+
+ // Managed data is already encoded
+ if (isEncoded()) {
+
+ // The data is already encoded but the encoding specified for
+ // the generation is different from the current one. We need
+ // to re-encode data: decode from input buffer to temporary
+ // buffer, and then re-encode to output stream...
+ if (m_encoding != enc) {
+
+ shared_ptr <utility::encoder::encoder> theDecoder = m_encoding.getEncoder();
+ shared_ptr <utility::encoder::encoder> theEncoder = enc.getEncoder();
+
+ theEncoder->getProperties()["maxlinelength"] = maxLineLength;
+ theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT);
+
+ utility::inputStreamStringAdapter in(m_string);
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter tempOut(oss);
+
+ theDecoder->decode(in, tempOut);
+
+ string str = oss.str();
+ utility::inputStreamStringAdapter tempIn(str);
+
+ theEncoder->encode(tempIn, os);
+
+ // No encoding to perform
+ } else {
+
+ os.write(m_string.data(), m_string.length());
+ }
+
+ // Need to encode data before
+ } else {
+
+ shared_ptr <utility::encoder::encoder> theEncoder = enc.getEncoder();
+ theEncoder->getProperties()["maxlinelength"] = maxLineLength;
+ theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT);
+
+ utility::inputStreamStringAdapter in(m_string);
+
+ theEncoder->encode(in, os);
+ }
+}
+
+
+void stringContentHandler::extract(
+ utility::outputStream& os,
+ utility::progressListener* progress
+) const {
+
+ // No decoding to perform
+ if (!isEncoded()) {
+
+ utility::inputStreamStringAdapter in(m_string);
+ utility::progressListenerSizeAdapter plsa(progress, getLength());
+
+ utility::bufferedStreamCopy(in, os, m_string.length(), progress);
+
+ // Need to decode data
+ } else {
+
+ shared_ptr <utility::encoder::encoder> theDecoder = m_encoding.getEncoder();
+
+ utility::inputStreamStringAdapter in(m_string);
+ utility::progressListenerSizeAdapter plsa(progress, getLength());
+
+ theDecoder->decode(in, os, &plsa);
+ }
+}
+
+
+void stringContentHandler::extractRaw(
+ utility::outputStream& os,
+ utility::progressListener* progress
+) const {
+
+ utility::inputStreamStringAdapter in(m_string);
+ utility::progressListenerSizeAdapter plsa(progress, getLength());
+
+ utility::bufferedStreamCopy(in, os, m_string.length(), progress);
+}
+
+
+size_t stringContentHandler::getLength() const {
+
+ return m_string.length();
+}
+
+
+bool stringContentHandler::isEmpty() const {
+
+ return m_string.length() == 0;
+}
+
+
+bool stringContentHandler::isEncoded() const {
+
+ return m_encoding != NO_ENCODING;
+}
+
+
+const vmime::encoding& stringContentHandler::getEncoding() const {
+
+ return m_encoding;
+}
+
+
+bool stringContentHandler::isBuffered() const {
+
+ return true;
+}
+
+
+void stringContentHandler::setContentTypeHint(const mediaType& type) {
+
+ m_contentType = type;
+}
+
+
+const mediaType stringContentHandler::getContentTypeHint() const {
+
+ return m_contentType;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/stringContentHandler.hpp b/vmime-master/src/vmime/stringContentHandler.hpp
new file mode 100644
index 0000000..c9a7331
--- /dev/null
+++ b/vmime-master/src/vmime/stringContentHandler.hpp
@@ -0,0 +1,107 @@
+//
+// 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_STRINGCONTENTHANDLER_HPP_INCLUDED
+#define VMIME_STRINGCONTENTHANDLER_HPP_INCLUDED
+
+
+#include "vmime/contentHandler.hpp"
+
+
+namespace vmime {
+
+
+class VMIME_EXPORT stringContentHandler : public contentHandler
+{
+public:
+
+ stringContentHandler();
+
+ stringContentHandler(
+ const string& buffer,
+ const vmime::encoding& enc = NO_ENCODING
+ );
+
+ ~stringContentHandler();
+
+ stringContentHandler(const stringContentHandler& cts);
+ stringContentHandler& operator=(const stringContentHandler& cts);
+
+ shared_ptr <contentHandler> clone() const;
+
+ /** Set data contained in this object.
+ *
+ * @param buffer buffer containing data
+ * @param enc set to anything other than NO_ENCODING if the data managed by
+ * this content handler is already encoded with the specified encoding (so, no
+ * encoding/decoding will be performed on generate()/extract()). Note that the
+ * data may be re-encoded (that is, decoded and encoded) if the encoding passed
+ * to generate() is different from this one.
+ */
+ void setData(
+ const string& buffer,
+ const vmime::encoding& enc = NO_ENCODING
+ );
+
+
+ stringContentHandler& operator=(const string& buffer);
+
+ void generate(
+ utility::outputStream& os,
+ const vmime::encoding& enc,
+ const size_t maxLineLength = lineLengthLimits::infinite
+ ) const;
+
+ void extract(utility::outputStream& os, utility::progressListener* progress = NULL) const;
+ void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const;
+
+ size_t getLength() const;
+
+ bool isEncoded() const;
+
+ const vmime::encoding& getEncoding() const;
+
+ bool isEmpty() const;
+
+ bool isBuffered() const;
+
+ void setContentTypeHint(const mediaType& type);
+ const mediaType getContentTypeHint() const;
+
+private:
+
+ mediaType m_contentType;
+
+ // Equals to NO_ENCODING if data is not encoded, otherwise this
+ // specifies the encoding that have been used to encode the data.
+ vmime::encoding m_encoding;
+
+ // The actual data
+ string m_string;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_STRINGCONTENTHANDLER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/text.cpp b/vmime-master/src/vmime/text.cpp
new file mode 100644
index 0000000..86ba44f
--- /dev/null
+++ b/vmime-master/src/vmime/text.cpp
@@ -0,0 +1,536 @@
+//
+// 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.
+//
+
+#include "vmime/text.hpp"
+
+#include "vmime/parserHelpers.hpp"
+#include "vmime/encoding.hpp"
+
+
+namespace vmime {
+
+
+text::text() {
+
+}
+
+
+text::text(const text& t)
+ : headerFieldValue() {
+
+ copyFrom(t);
+}
+
+
+text::text(const string& t, const charset& ch) {
+
+ createFromString(t, ch);
+}
+
+
+text::text(const string& t) {
+
+ createFromString(t, charset::getLocalCharset());
+}
+
+
+text::text(const word& w) {
+
+ appendWord(make_shared <word>(w));
+}
+
+
+text::~text() {
+
+ removeAllWords();
+}
+
+
+void text::parseImpl(
+ const parsingContext& ctx,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ removeAllWords();
+
+ size_t newPos;
+
+ const std::vector <shared_ptr <word> > words =
+ word::parseMultiple(ctx, buffer, position, end, &newPos);
+
+ copy_vector(words, m_words);
+
+ setParsedBounds(position, newPos);
+
+ if (newPosition) {
+ *newPosition = newPos;
+ }
+}
+
+
+void text::generateImpl(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ encodeAndFold(ctx, os, curLinePos, newLinePos, 0);
+}
+
+
+void text::copyFrom(const component& other) {
+
+ const text& t = dynamic_cast <const text&>(other);
+
+ removeAllWords();
+
+ for (std::vector <shared_ptr <word> >::const_iterator i = t.m_words.begin() ;
+ i != t.m_words.end() ; ++i) {
+
+ m_words.push_back(make_shared <word>(**i));
+ }
+}
+
+
+text& text::operator=(const component& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+text& text::operator=(const text& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+bool text::operator==(const text& t) const {
+
+ if (getWordCount() == t.getWordCount()) {
+
+ bool equal = true;
+
+ std::vector <shared_ptr <word> >::const_iterator i = m_words.begin();
+ std::vector <shared_ptr <word> >::const_iterator j = t.m_words.begin();
+
+ for ( ; equal && i != m_words.end() ; ++i, ++j) {
+ equal = (**i == **j);
+ }
+
+ return equal;
+ }
+
+ return false;
+}
+
+
+bool text::operator!=(const text& t) const {
+
+ return !(*this == t);
+}
+
+
+const string text::getConvertedText(
+ const charset& dest,
+ const charsetConverterOptions& opts
+) const {
+
+ string out;
+
+ for (std::vector <shared_ptr <word> >::const_iterator i = m_words.begin() ;
+ i != m_words.end() ; ++i) {
+
+ out += (*i)->getConvertedText(dest, opts);
+ }
+
+ return out;
+}
+
+
+void text::appendWord(const shared_ptr <word>& w) {
+
+ m_words.push_back(w);
+}
+
+
+void text::insertWordBefore(const size_t pos, const shared_ptr <word>& w) {
+
+ m_words.insert(m_words.begin() + pos, w);
+}
+
+
+void text::insertWordAfter(const size_t pos, const shared_ptr <word>& w) {
+
+ m_words.insert(m_words.begin() + pos + 1, w);
+}
+
+
+void text::removeWord(const size_t pos) {
+
+ const std::vector <shared_ptr <word> >::iterator it = m_words.begin() + pos;
+
+ m_words.erase(it);
+}
+
+
+void text::removeAllWords() {
+
+ m_words.clear();
+}
+
+
+size_t text::getWordCount() const {
+
+ return m_words.size();
+}
+
+
+bool text::isEmpty() const {
+
+ return m_words.empty();
+}
+
+
+const shared_ptr <word> text::getWordAt(const size_t pos) {
+
+ return m_words[pos];
+}
+
+
+const shared_ptr <const word> text::getWordAt(const size_t pos) const {
+
+ return m_words[pos];
+}
+
+
+const std::vector <shared_ptr <const word> > text::getWordList() const {
+
+ std::vector <shared_ptr <const word> > list;
+
+ list.reserve(m_words.size());
+
+ for (std::vector <shared_ptr <word> >::const_iterator it = m_words.begin() ;
+ it != m_words.end() ; ++it) {
+
+ list.push_back(*it);
+ }
+
+ return list;
+}
+
+
+const std::vector <shared_ptr <word> > text::getWordList() {
+
+ return m_words;
+}
+
+
+shared_ptr <component> text::clone() const {
+
+ return make_shared <text>(*this);
+}
+
+
+shared_ptr <text> text::newFromString(const string& in, const charset& ch) {
+
+ shared_ptr <text> t = make_shared <text>();
+
+ t->createFromString(in, ch);
+
+ return t;
+}
+
+
+void text::createFromString(const string& in, const charset& ch) {
+
+ size_t asciiCount = 0;
+ size_t asciiPercent = 0;
+
+ removeAllWords();
+
+ // Check whether there is a recommended encoding for this charset.
+ // If so, the whole buffer will be encoded. Else, the number of
+ // 7-bit (ASCII) bytes in the input will be used to determine if
+ // we need to encode the whole buffer.
+ encoding recommendedEnc;
+ const bool alwaysEncode = ch.getRecommendedEncoding(recommendedEnc);
+
+ if (!alwaysEncode) {
+ asciiCount = utility::stringUtils::countASCIIchars(in.begin(), in.end());
+ asciiPercent = (in.length() == 0 ? 100 : (100 * asciiCount) / in.length());
+ }
+
+ // If there are "too much" non-ASCII chars, encode everything
+ if (alwaysEncode || asciiPercent < 60) { // less than 60% ASCII chars
+
+ appendWord(make_shared <word>(in, ch));
+
+ // Else, only encode words which need it
+ } else {
+
+ bool is8bit = false; // is the current word 8-bit?
+ bool prevIs8bit = false; // is previous word 8-bit?
+ unsigned int count = 0; // total number of words
+
+ for (size_t end = in.size(), pos = 0, start = 0 ; ; ) {
+
+ if (pos == end || parserHelpers::isSpace(in[pos])) {
+
+ const string chunk(in.begin() + start, in.begin() + pos);
+
+ if (pos != end) {
+ ++pos;
+ }
+
+ if (is8bit) {
+
+ if (count && prevIs8bit) {
+
+ // No need to create a new encoded word, just append
+ // the current word to the previous one.
+ shared_ptr <word> w = getWordAt(getWordCount() - 1);
+ w->getBuffer() += " " + chunk;
+
+ } else {
+
+ if (count) {
+ shared_ptr <word> w = getWordAt(getWordCount() - 1);
+ w->getBuffer() += ' ';
+ }
+
+ appendWord(make_shared <word>(chunk, ch));
+
+ prevIs8bit = true;
+ ++count;
+ }
+
+ } else {
+
+ if (count && !prevIs8bit) {
+
+ shared_ptr <word> w = getWordAt(getWordCount() - 1);
+ w->getBuffer() += " " + chunk;
+
+ } else {
+
+ appendWord(make_shared <word>(chunk, charset(charsets::US_ASCII)));
+
+ prevIs8bit = false;
+ ++count;
+ }
+ }
+
+ if (pos == end) {
+ break;
+ }
+
+ is8bit = false;
+ start = pos;
+
+ } else if (!parserHelpers::isAscii(in[pos])) {
+
+ is8bit = true;
+ ++pos;
+
+ } else {
+
+ ++pos;
+ }
+ }
+ }
+}
+
+
+void text::encodeAndFold(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t firstLineOffset,
+ size_t* lastLineLength,
+ const int flags
+) const {
+
+ size_t curLineLength = firstLineOffset;
+ word::generatorState state;
+
+ for (size_t wi = 0 ; wi < getWordCount() ; ++wi) {
+
+ getWordAt(wi)->generate(
+ ctx, os, curLineLength,
+ &curLineLength, flags, &state
+ );
+ }
+
+ if (lastLineLength) {
+ *lastLineLength = curLineLength;
+ }
+}
+
+
+shared_ptr <text> text::decodeAndUnfold(const string& in) {
+
+ shared_ptr <text> t = make_shared <text>();
+
+ decodeAndUnfold(parsingContext::getDefaultContext(), in, t.get());
+
+ return t;
+}
+
+
+shared_ptr <text> text::decodeAndUnfold(const parsingContext& ctx, const string& in) {
+
+ shared_ptr <text> t = make_shared <text>();
+
+ decodeAndUnfold(ctx, in, t.get());
+
+ return t;
+}
+
+
+text* text::decodeAndUnfold(const string& in, text* generateInExisting) {
+
+ return decodeAndUnfold(parsingContext::getDefaultContext(), in, generateInExisting);
+}
+
+
+text* text::decodeAndUnfold(const parsingContext& ctx, const string& in, text* generateInExisting) {
+
+ text* out = generateInExisting ? generateInExisting : new text();
+
+ out->removeAllWords();
+
+ std::vector <shared_ptr <word> > words = word::parseMultiple(ctx, in, 0, in.length(), NULL);
+ fixBrokenWords(words);
+
+ copy_vector(words, out->m_words);
+
+ return out;
+}
+
+
+// static
+void text::fixBrokenWords(std::vector <shared_ptr <word> >& words) {
+
+ if (words.size() < 2) {
+ return;
+ }
+
+ // Fix words which encode a non-integral number of characters.
+ // This is not RFC-compliant, but we should be able to recover from it.
+ for (size_t i = 0, n = words.size() ; i < n - 1 ; ++i) {
+
+ shared_ptr <word> w1 = words[i];
+
+ // Check whether the word is valid
+ bool valid = false;
+
+ try {
+
+ valid = w1->getCharset().isValidText(w1->getBuffer(), NULL);
+
+ } catch (vmime::exceptions::charset_conv_error& e) {
+
+ // Unknown charset or unexpected conversion error: assume word is valid
+ valid = true;
+ }
+
+ // If the current word is not valid, try to grab some bytes
+ // from the next words, to see whether it becomes valid.
+ if (!valid) {
+
+ string buffer(w1->getBuffer());
+ size_t mergeWords = 1; // number of adjacent words to merge
+
+ for (size_t j = i + 1 ; j < n ; ++j) {
+
+ shared_ptr <word> nextWord = words[j];
+
+ if (nextWord->getCharset() != w1->getCharset()) {
+ break;
+ }
+
+ buffer += nextWord->getBuffer();
+ ++mergeWords;
+ }
+
+ if (mergeWords == 1) {
+ // No adjacent word with same charset found
+ continue;
+ }
+
+ string::size_type firstInvalidByte;
+ valid = w1->getCharset().isValidText(buffer, &firstInvalidByte);
+
+ // Current word with additional bytes from the next words
+ // is now valid: adjust buffers of words.
+ w1->setBuffer(string(buffer.begin(), buffer.begin() + firstInvalidByte));
+ words[i + 1]->setBuffer(string(buffer.begin() + firstInvalidByte, buffer.end()));
+
+ // Remove unused words
+ for (size_t j = 0 ; j < mergeWords - 2 ; ++j) {
+
+ words.erase(words.begin() + i + 2);
+ --n;
+ }
+
+ // If the next word is now empty, remove it
+ if (words[i + 1]->getBuffer().empty()) {
+
+ words.erase(words.begin() + i + 1);
+ --n;
+ }
+ }
+ }
+}
+
+
+const std::vector <shared_ptr <component> > text::getChildComponents() {
+
+ std::vector <shared_ptr <component> > list;
+
+ copy_vector(m_words, list);
+
+ return list;
+}
+
+
+const string text::getWholeBuffer() const {
+
+ string res;
+
+ for (std::vector <shared_ptr <word> >::const_iterator it = m_words.begin() ;
+ it != m_words.end() ; ++it) {
+
+ res += (*it)->getBuffer();
+ }
+
+ return res;
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/text.hpp b/vmime-master/src/vmime/text.hpp
new file mode 100644
index 0000000..143f527
--- /dev/null
+++ b/vmime-master/src/vmime/text.hpp
@@ -0,0 +1,291 @@
+//
+// 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_TEXT_HPP_INCLUDED
+#define VMIME_TEXT_HPP_INCLUDED
+
+
+#include "vmime/headerFieldValue.hpp"
+#include "vmime/base.hpp"
+#include "vmime/word.hpp"
+
+
+namespace vmime {
+
+
+/** List of encoded-words, as defined in RFC-2047 (basic type).
+ */
+class VMIME_EXPORT text : public headerFieldValue {
+
+public:
+
+ text();
+ text(const text& t);
+ text(const string& t, const charset& ch);
+ explicit text(const string& t);
+ explicit text(const word& w);
+ ~text();
+
+public:
+
+ bool operator==(const text& t) const;
+ bool operator!=(const text& t) const;
+
+ shared_ptr <component> clone() const;
+ void copyFrom(const component& other);
+ text& operator=(const component& other);
+ text& operator=(const text& other);
+
+ const std::vector <shared_ptr <component> > getChildComponents();
+
+ /** Add a word at the end of the list.
+ *
+ * @param w word to append
+ */
+ void appendWord(const shared_ptr <word>& w);
+
+ /** Insert a new word before the specified position.
+ *
+ * @param pos position at which to insert the new word (0 to insert at
+ * the beginning of the list)
+ * @param w word to insert
+ */
+ void insertWordBefore(const size_t pos, const shared_ptr <word>& w);
+
+ /** Insert a new word after the specified position.
+ *
+ * @param pos position of the word before the new word
+ * @param w word to insert
+ */
+ void insertWordAfter(const size_t pos, const shared_ptr <word>& w);
+
+ /** Remove the word at the specified position.
+ *
+ * @param pos position of the word to remove
+ */
+ void removeWord(const size_t pos);
+
+ /** Remove all words from the list.
+ */
+ void removeAllWords();
+
+ /** Return the number of words in the list.
+ *
+ * @return number of words
+ */
+ size_t getWordCount() const;
+
+ /** Tests whether the list of words is empty.
+ *
+ * @return true if there is no word, false otherwise
+ */
+ bool isEmpty() const;
+
+ /** Return the word at the specified position.
+ *
+ * @param pos position
+ * @return word at position 'pos'
+ */
+ const shared_ptr <word> getWordAt(const size_t pos);
+
+ /** Return the word at the specified position.
+ *
+ * @param pos position
+ * @return word at position 'pos'
+ */
+ const shared_ptr <const word> getWordAt(const size_t pos) const;
+
+ /** Return the word list.
+ *
+ * @return list of words
+ */
+ const std::vector <shared_ptr <const word> > getWordList() const;
+
+ /** Return the word list.
+ *
+ * @return list of words
+ */
+ const std::vector <shared_ptr <word> > getWordList();
+
+
+ /** Return the text converted into the specified charset.
+ * The encoded-words are decoded and then converted in the
+ * specified destination charset.
+ *
+ * @param dest output charset
+ * @param opts options for charset conversion
+ * @return text decoded in the specified charset
+ */
+ const string getConvertedText(
+ const charset& dest,
+ const charsetConverterOptions& opts = charsetConverterOptions()
+ ) const;
+
+ /** Return the unconverted (raw) data of all words. This is the
+ * concatenation of the results returned by getBuffer() on
+ * the contained words.
+ *
+ * @return raw data
+ */
+ const string getWholeBuffer() const;
+
+ /** This function can be used to make several encoded words from a text.
+ * All the characters in the text must be in the same specified charset.
+ *
+ * <p>Eg: giving:</p>
+ * <pre> &lt;iso-8859-1> "Linux dans un t'el'ephone mobile"
+ * ("=?iso-8859-1?Q?Linux_dans_un_t=E9l=E9phone_mobile?=")
+ * </pre><p>it will return:</p>
+ * <pre> &lt;us-ascii> "Linux dans un "
+ * &lt;iso-8859-1> "t'el'ephone "
+ * &lt;us-ascii> "mobile"
+ * ("Linux dans un =?iso-8859-1?Q?t=E9l=E9phone_?= mobile")
+ * </pre>
+ *
+ * @param in input string
+ * @param ch input charset
+ * @return new text object
+ */
+ static shared_ptr <text> newFromString(const string& in, const charset& ch);
+
+ /** This function can be used to make several encoded words from a text.
+ * All the characters in the text must be in the same specified charset.
+ *
+ * <p>Eg: giving:</p>
+ * <pre> &lt;iso-8859-1> "Linux dans un t'el'ephone mobile"
+ * ("=?iso-8859-1?Q?Linux_dans_un_t=E9l=E9phone_mobile?=")
+ * </pre><p>it will return:</p>
+ * <pre> &lt;us-ascii> "Linux dans un "
+ * &lt;iso-8859-1> "t'el'ephone "
+ * &lt;us-ascii> "mobile"
+ * ("Linux dans un =?iso-8859-1?Q?t=E9l=E9phone_?= mobile")
+ * </pre>
+ *
+ * @param in input string
+ * @param ch input charset
+ */
+ void createFromString(const string& in, const charset& ch);
+
+ /** Flags used by "encodeAndFold" function.
+ */
+ enum EncodeAndFoldFlags {
+
+ // NOTE: If both "FORCE_NO_ENCODING" and "FORCE_ENCODING" are
+ // specified, "FORCE_NO_ENCODING" is used by default.
+
+ FORCE_NO_ENCODING = (1 << 0), /**< Just fold lines, don't encode them. */
+ FORCE_ENCODING = (1 << 1), /**< Encode lines even if they are plain ASCII text. */
+ NO_NEW_LINE_SEQUENCE = (1 << 2), /**< Use CRLF instead of new-line sequence (CRLF + TAB). */
+ QUOTE_IF_POSSIBLE = (1 << 3), /**< Use quoting instead of encoding when possible (even if FORCE_ENCODING is specified). */
+ QUOTE_IF_NEEDED = (1 << 4) /**< Use quoting instead of encoding if needed (eg. whitespaces and/or special chars). */
+ };
+
+ /** Encode and fold text in respect to RFC-2047.
+ *
+ * @param ctx generation context
+ * @param os output stream
+ * @param firstLineOffset the first line length (may be useful if the current output line is not empty)
+ * @param lastLineLength will receive the length of the last line written
+ * @param flags encoding flags (see EncodeAndFoldFlags)
+ */
+ void encodeAndFold(
+ const generationContext& ctx,
+ utility::outputStream& os,
+ const size_t firstLineOffset,
+ size_t* lastLineLength,
+ const int flags
+ ) const;
+
+ /** Decode and unfold text (RFC-2047), using the default parsing context.
+ *
+ * @param in input string
+ * @return new text object
+ */
+ static shared_ptr <text> decodeAndUnfold(const string& in);
+
+ /** Decode and unfold text (RFC-2047).
+ *
+ * @param ctx parsingContext
+ * @param in input string
+ * @return new text object
+ */
+ static shared_ptr <text> decodeAndUnfold(const parsingContext& ctx, const string& in);
+
+ /** Decode and unfold text (RFC-2047), using the default parsing context.
+ *
+ * @param in input string
+ * @param generateInExisting if not NULL, the resulting text will be generated
+ * in the specified object instead of a new created object (in this case, the
+ * function returns the same pointer). Can be used to avoid copying the
+ * resulting object into an existing object.
+ * @return new text object or existing object if generateInExisting != NULL
+ */
+ static text* decodeAndUnfold(const string& in, text* generateInExisting);
+
+ /** Decode and unfold text (RFC-2047).
+ *
+ * @param ctx parsing context
+ * @param in input string
+ * @param generateInExisting if not NULL, the resulting text will be generated
+ * in the specified object instead of a new created object (in this case, the
+ * function returns the same pointer). Can be used to avoid copying the
+ * resulting object into an existing object.
+ * @return new text object or existing object if generateInExisting != NULL
+ */
+ static text* decodeAndUnfold(
+ const parsingContext& ctx,
+ const string& in,
+ text* generateInExisting
+ );
+
+protected:
+
+ static void fixBrokenWords(std::vector <shared_ptr <word> >& words);
+
+
+ // Component parsing & assembling
+ void parseImpl(
+ const 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;
+
+private:
+
+ std::vector <shared_ptr <word> > m_words;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_TEXT_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/textPart.hpp b/vmime-master/src/vmime/textPart.hpp
new file mode 100644
index 0000000..e34a169
--- /dev/null
+++ b/vmime-master/src/vmime/textPart.hpp
@@ -0,0 +1,117 @@
+//
+// 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_TEXTPART_HPP_INCLUDED
+#define VMIME_TEXTPART_HPP_INCLUDED
+
+
+#include "vmime/bodyPart.hpp"
+
+#include "vmime/mediaType.hpp"
+#include "vmime/charset.hpp"
+#include "vmime/contentHandler.hpp"
+
+
+namespace vmime {
+
+
+/** Generic text part.
+ */
+class VMIME_EXPORT textPart : public object {
+
+ friend class textPartFactory;
+ friend class messageBuilder; // for generateIn, getPartCount
+ friend class messageParser; // for parse
+
+public:
+
+ virtual ~textPart() { }
+
+ /** Return the type of text part (eg: "text/html").
+ *
+ * @return type of text part
+ */
+ virtual const mediaType getType() const = 0;
+
+ /** Return the charset used to encode text in the
+ * text part.
+ *
+ * @return text charset
+ */
+ virtual const charset& getCharset() const = 0;
+
+ /** Set the charset used to encode text in the
+ * text part.
+ *
+ * @param ch text charset
+ */
+ virtual void setCharset(const charset& ch) = 0;
+
+ /** Return the text contained in the part.
+ *
+ * @return text of the part
+ */
+ virtual const shared_ptr <const contentHandler> getText() const = 0;
+
+ /** Set the text contained in the part.
+ *
+ * @param text text of the part
+ */
+ virtual void setText(const shared_ptr <contentHandler>& text) = 0;
+
+ /** Return the actual body parts this text part is composed of.
+ * For example, HTML parts are composed of two parts: one "text/html"
+ * part, and the plain text part "text/plain".
+ *
+ * @return number of body parts
+ */
+ virtual size_t getPartCount() const = 0;
+
+ /** Generate the text part(s) into the specified message.
+ *
+ * @param message the message
+ * @param parent body part into which generate this part
+ */
+ virtual void generateIn(
+ const shared_ptr <bodyPart>& message,
+ const shared_ptr <bodyPart>& parent
+ ) const = 0;
+
+ /** Parse the text part(s) from the specified message.
+ *
+ * @param message message containing the text part
+ * @param parent part containing the text part
+ * @param textPart actual text part
+ */
+ virtual void parse(
+ const shared_ptr <const bodyPart>& message,
+ const shared_ptr <const bodyPart>& parent,
+ const shared_ptr <const bodyPart>& textPart
+ ) = 0;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_TEXTPART_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/textPartFactory.cpp b/vmime-master/src/vmime/textPartFactory.cpp
new file mode 100644
index 0000000..2c58888
--- /dev/null
+++ b/vmime-master/src/vmime/textPartFactory.cpp
@@ -0,0 +1,68 @@
+//
+// 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.
+//
+
+#include "vmime/textPartFactory.hpp"
+#include "vmime/exception.hpp"
+
+
+#include "vmime/plainTextPart.hpp"
+#include "vmime/htmlTextPart.hpp"
+
+
+namespace vmime {
+
+
+textPartFactory::textPartFactory() {
+
+ registerType <plainTextPart>(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN));
+ registerType <htmlTextPart>(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML));
+}
+
+
+textPartFactory::~textPartFactory() {
+
+}
+
+
+textPartFactory* textPartFactory::getInstance() {
+
+ static textPartFactory instance;
+ return &instance;
+}
+
+
+shared_ptr <textPart> textPartFactory::create(const mediaType& type)
+{
+ for (MapType::const_iterator it = m_map.begin() ;
+ it != m_map.end() ; ++it) {
+
+ if ((*it).first == type) {
+ return ((*it).second)();
+ }
+ }
+
+ throw exceptions::no_factory_available("No 'textPart' class registered for media type '" + type.generate() + "'.");
+}
+
+
+} // vmime
diff --git a/vmime-master/src/vmime/textPartFactory.hpp b/vmime-master/src/vmime/textPartFactory.hpp
new file mode 100644
index 0000000..322c616
--- /dev/null
+++ b/vmime-master/src/vmime/textPartFactory.hpp
@@ -0,0 +1,77 @@
+//
+// 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_TEXTPARTFACTORY_HPP_INCLUDED
+#define VMIME_TEXTPARTFACTORY_HPP_INCLUDED
+
+
+#include "vmime/textPart.hpp"
+#include "vmime/mediaType.hpp"
+
+
+namespace vmime {
+
+
+class VMIME_EXPORT textPartFactory {
+
+protected:
+
+ textPartFactory();
+ ~textPartFactory();
+
+ typedef shared_ptr <textPart> (*AllocFunc)(void);
+ typedef std::vector <std::pair <mediaType, AllocFunc> > MapType;
+
+ MapType m_map;
+
+#ifndef VMIME_BUILDING_DOC
+ template <class TYPE>
+ class registerer {
+ public:
+
+ static shared_ptr <textPart> creator() {
+
+ // Allocate a new object
+ return vmime::make_shared <TYPE>();
+ }
+ };
+#endif // VMIME_BUILDING_DOC
+
+public:
+
+ static textPartFactory* getInstance();
+
+ template <class T>
+ void registerType(const mediaType& type) {
+
+ m_map.push_back(MapType::value_type(type, &registerer<T>::creator));
+ }
+
+ shared_ptr <textPart> create(const mediaType& type);
+};
+
+
+} // vmime
+
+
+#endif // VMIME_TEXTPARTFACTORY_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/types.hpp b/vmime-master/src/vmime/types.hpp
new file mode 100644
index 0000000..3527883
--- /dev/null
+++ b/vmime-master/src/vmime/types.hpp
@@ -0,0 +1,87 @@
+//
+// 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_TYPES_HPP_INCLUDED
+#define VMIME_TYPES_HPP_INCLUDED
+
+
+#include <limits>
+#include <string>
+#include <vector>
+#include <stdexcept>
+#include <cstddef>
+#include <utility>
+#include <memory>
+
+#include "vmime/config.hpp"
+
+
+#ifndef VMIME_BUILDING_DOC
+
+namespace vmime {
+
+ using std::shared_ptr;
+ using std::weak_ptr;
+ using std::make_shared;
+ using std::enable_shared_from_this;
+ using std::dynamic_pointer_cast;
+ using std::const_pointer_cast;
+
+ /** Custom deleter to be used with shared_ptr.
+ * This does not actually delete the pointer, and is used
+ * only for the singleton classes allocated on the stack.
+ */
+ template <typename T>
+ struct noop_shared_ptr_deleter {
+ void operator()(T*) const {}
+ };
+
+ template <typename T> using scoped_ptr = std::unique_ptr <T>;
+}
+
+#endif // VMIME_BUILDING_DOC
+
+
+namespace vmime {
+
+ typedef std::string string;
+
+ typedef unsigned short port_t;
+
+ typedef int char_t;
+
+ typedef vmime_uint8 byte_t;
+ typedef std::vector <byte_t> byteArray;
+
+ typedef std::size_t size_t;
+
+ // For compatibility with versions <= 0.7.1 (deprecated)
+ namespace net { }
+ namespace messaging = net;
+}
+
+
+#include "vmime/object.hpp"
+
+
+#endif // VMIME_TYPES_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/childProcess.hpp b/vmime-master/src/vmime/utility/childProcess.hpp
new file mode 100644
index 0000000..b72ab85
--- /dev/null
+++ b/vmime-master/src/vmime/utility/childProcess.hpp
@@ -0,0 +1,103 @@
+//
+// 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_UTILITY_CHILDPROCESS_HPP_INCLUDED
+#define VMIME_UTILITY_CHILDPROCESS_HPP_INCLUDED
+
+
+#include "vmime/utility/stream.hpp"
+#include "vmime/utility/file.hpp"
+
+#include <vector>
+
+
+namespace vmime {
+namespace utility {
+
+
+/** Spawn a process and redirect its standard input
+ * and/or standard output.
+ */
+class VMIME_EXPORT childProcess : public object {
+
+public:
+
+ virtual ~childProcess() { }
+
+ /** Flags used with start(). */
+ enum Flags {
+ FLAG_REDIRECT_STDIN = (1 << 0),
+ FLAG_REDIRECT_STDOUT = (1 << 1)
+ };
+
+ /** Start the child process.
+ *
+ * @param args list of arguments
+ * @param flags one or more childProcess::Flags
+ * @throws exceptions::system_error if the an error occurs
+ * before the process can be started
+ */
+ virtual void start(const std::vector <string>& args, const int flags = 0) = 0;
+
+ /** Return a wrapper to the child process standard input.
+ *
+ * @return output stream wrapper for child's stdin
+ */
+ virtual shared_ptr <utility::outputStream> getStdIn() = 0;
+
+ /** Return a wrapper to the child process standard output.
+ *
+ * @return input stream wrapper for child's stdout
+ */
+ virtual shared_ptr <utility::inputStream> getStdOut() = 0;
+
+ /** Wait for the process to finish.
+ *
+ * @throws exceptions::system_error if the process does
+ * not exit normally
+ */
+ virtual void waitForFinish() = 0;
+};
+
+
+/** Create 'childProcess' objects.
+ */
+class childProcessFactory : public object {
+
+public:
+
+ virtual ~childProcessFactory() { }
+
+ /** Create a new child process.
+ *
+ * @param path full path of the process executable file
+ */
+ virtual shared_ptr <childProcess> create(const utility::file::path& path) const = 0;
+};
+
+
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_CHILDPROCESS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/datetimeUtils.cpp b/vmime-master/src/vmime/utility/datetimeUtils.cpp
new file mode 100644
index 0000000..b1a6c55
--- /dev/null
+++ b/vmime-master/src/vmime/utility/datetimeUtils.cpp
@@ -0,0 +1,317 @@
+//
+// 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.
+//
+
+#include "vmime/utility/datetimeUtils.hpp"
+
+#include <stdexcept>
+
+
+namespace vmime {
+namespace utility {
+
+
+#ifndef VMIME_BUILDING_DOC
+
+static inline void nextMonth(datetime& d) {
+
+ if (d.getMonth() >= 12) {
+ d.setMonth(1);
+ d.setYear(d.getYear() + 1);
+ } else {
+ d.setMonth(d.getMonth() + 1);
+ }
+}
+
+
+static inline void prevMonth(datetime& d) {
+
+ if (d.getMonth() <= 1) {
+ d.setYear(d.getYear() - 1);
+ d.setMonth(12);
+ } else {
+ d.setMonth(d.getMonth() - 1);
+ }
+}
+
+
+static inline void nextDay(datetime& d) {
+
+ if (d.getDay() >= datetimeUtils::getDaysInMonth(d.getYear(), d.getMonth())) {
+ d.setDay(1);
+ nextMonth(d);
+ } else {
+ d.setDay(d.getDay() + 1);
+ }
+}
+
+
+static inline void prevDay(datetime& d) {
+
+ if (d.getDay() <= 1) {
+ prevMonth(d);
+ d.setDay(datetimeUtils::getDaysInMonth(d.getYear(), d.getMonth()));
+ } else {
+ d.setDay(d.getDay() - 1);
+ }
+}
+
+
+static inline void nextHour(datetime& d) {
+
+ if (d.getHour() >= 23) {
+ d.setHour(0);
+ nextDay(d);
+ } else {
+ d.setHour(d.getHour() + 1);
+ }
+}
+
+
+static inline void prevHour(datetime& d) {
+
+ if (d.getHour() <= 0) {
+ d.setHour(23);
+ prevDay(d);
+ } else {
+ d.setHour(d.getHour() - 1);
+ }
+}
+
+
+static inline void addHoursAndMinutes(datetime& d, const int h, const int m) {
+
+ d.setMinute(d.getMinute() + m);
+
+ if (d.getMinute() >= 60) {
+ d.setMinute(d.getMinute() - 60);
+ nextHour(d);
+ }
+
+ d.setHour(d.getHour() + h);
+
+ if (d.getHour() >= 24) {
+ d.setHour(d.getHour() - 24);
+ nextDay(d);
+ }
+}
+
+
+static inline void substractHoursAndMinutes(datetime& d, const int h, const int m) {
+
+ if (m > d.getMinute()) {
+ d.setMinute(60 - (m - d.getMinute()));
+ prevHour(d);
+ } else {
+ d.setMinute(d.getMinute() - m);
+ }
+
+ if (h > d.getHour()) {
+ d.setHour(24 - (h - d.getHour()));
+ prevDay(d);
+ } else {
+ d.setHour(d.getHour() - h);
+ }
+}
+
+#endif // VMIME_BUILDING_DOC
+
+
+const datetime datetimeUtils::toUniversalTime(const datetime& date) {
+
+ if (date.getZone() == datetime::GMT) {
+ return date; // no conversion needed
+ }
+
+ datetime nd(date);
+ nd.setZone(datetime::GMT);
+
+ const int z = date.getZone();
+ const int h = (z < 0) ? (-z / 60) : (z / 60);
+ const int m = (z < 0) ? (-z - h * 60) : (z - h * 60);
+
+ if (z < 0) { // GMT-hhmm: add hours and minutes to date
+ addHoursAndMinutes(nd, h, m);
+ } else { // GMT+hhmm: substract hours and minutes from date
+ substractHoursAndMinutes(nd, h, m);
+ }
+
+ return nd;
+}
+
+
+const datetime datetimeUtils::toLocalTime(const datetime& date, const int zone) {
+
+ datetime utcDate(date);
+
+ if (utcDate.getZone() != datetime::GMT) {
+ utcDate = toUniversalTime(date); // convert to UT before
+ }
+
+ datetime nd(utcDate);
+ nd.setZone(zone);
+
+ const int h = (zone < 0) ? (-zone / 60) : (zone / 60);
+ const int m = (zone < 0) ? (-zone - h * 60) : (zone - h * 60);
+
+ if (zone < 0) { // GMT+hhmm: substract hours and minutes from date
+ substractHoursAndMinutes(nd, h, m);
+ } else { // GMT-hhmm: add hours and minutes to date
+ addHoursAndMinutes(nd, h, m);
+ }
+
+ return nd;
+}
+
+
+bool datetimeUtils::isLeapYear(const int year) {
+
+ // From RFC 3339 - Appendix C. Leap Years:
+ return ((year % 4) == 0 && (year % 100 != 0 || year % 400 == 0));
+}
+
+
+int datetimeUtils::getDaysInMonth(const int year, const int month) {
+
+ static const int daysInMonth[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ static const int daysInMonthLeapYear[12] = {
+ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+
+ if (month < 1 || month > 12) {
+ throw std::out_of_range("Invalid month number");
+ }
+
+ return isLeapYear(year) ? daysInMonthLeapYear[month - 1] : daysInMonth[month - 1];
+}
+
+
+int datetimeUtils::getDayOfWeek(const int year, const int month, const int day) {
+
+ int y = year;
+ int m = month;
+
+ if (month < 1 || month > 12) {
+ throw std::out_of_range("Invalid month number");
+ } else if (day < 1 || day > getDaysInMonth(year, month)) {
+ throw std::out_of_range("Invalid day number");
+ }
+
+ // From RFC-3339 - Appendix B. Day of the Week
+
+ // Adjust months so February is the last one
+ m -= 2;
+
+ if (m < 1) {
+ m += 12;
+ --y;
+ }
+
+ // Split by century
+ const int cent = y / 100;
+ y %= 100;
+
+ return ((26 * m - 2) / 10 + day + y + (y >> 2) + (cent >> 2) + 5 * cent) % 7;
+}
+
+
+int datetimeUtils::getWeekOfYear(const int year, const int month, const int day, const bool iso) {
+
+ // Algorithm from http://personal.ecu.edu/mccartyr/ISOwdALG.txt
+
+ const bool leapYear = ((year % 4) == 0 && (year % 100) != 0) || (year % 400) == 0;
+ const bool leapYear_1 = (((year - 1) % 4) == 0 && ((year - 1) % 100) != 0) || ((year - 1) % 400) == 0;
+
+ // 4. Find the DayOfYearNumber for Y M D
+ static const int DAY_OF_YEAR_NUMBER_MAP[12] = {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+ };
+
+ int DayOfYearNumber = day + DAY_OF_YEAR_NUMBER_MAP[month - 1];
+
+ if (leapYear && month > 2) {
+ DayOfYearNumber += 1;
+ }
+
+ // 5. Find the Jan1Weekday for Y (Monday=1, Sunday=7)
+ const int YY = (year - 1) % 100;
+ const int C = (year - 1) - YY;
+ const int G = YY + YY / 4;
+ const int Jan1Weekday = 1 + (((((C / 100) % 4) * 5) + G) % 7);
+
+ // 6. Find the Weekday for Y M D
+ const int H = DayOfYearNumber + (Jan1Weekday - 1);
+ const int Weekday = 1 + ((H - 1) % 7);
+
+ // 7. Find if Y M D falls in YearNumber Y-1, WeekNumber 52 or 53
+ int YearNumber = 0, WeekNumber = 0;
+
+ if (DayOfYearNumber <= (8 - Jan1Weekday) && Jan1Weekday > 4) {
+
+ YearNumber = year - 1;
+
+ if (Jan1Weekday == 5 || (Jan1Weekday == 6 && leapYear_1)) {
+ WeekNumber = 53;
+ } else {
+ WeekNumber = 52;
+ }
+
+ } else {
+
+ YearNumber = year;
+ }
+
+ // 8. Find if Y M D falls in YearNumber Y+1, WeekNumber 1
+ if (YearNumber == year) {
+
+ const int I = (leapYear ? 366 : 365);
+
+ if ((I - DayOfYearNumber) < (4 - Weekday)) {
+ YearNumber = year + 1;
+ WeekNumber = 1;
+ }
+ }
+
+ // 9. Find if Y M D falls in YearNumber Y, WeekNumber 1 through 53
+ if (YearNumber == year) {
+
+ const int J = DayOfYearNumber + (7 - Weekday) + (Jan1Weekday - 1);
+
+ WeekNumber = J / 7;
+
+ if (Jan1Weekday > 4) {
+ WeekNumber -= 1;
+ }
+ }
+
+ if (!iso && (WeekNumber == 1 && month == 12)) {
+ WeekNumber = 53;
+ }
+
+ return WeekNumber;
+}
+
+
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/datetimeUtils.hpp b/vmime-master/src/vmime/utility/datetimeUtils.hpp
new file mode 100644
index 0000000..b762a6e
--- /dev/null
+++ b/vmime-master/src/vmime/utility/datetimeUtils.hpp
@@ -0,0 +1,98 @@
+//
+// 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_DATETIMEUTILS_HPP_INCLUDED
+#define VMIME_DATETIMEUTILS_HPP_INCLUDED
+
+
+#include "vmime/dateTime.hpp"
+
+
+namespace vmime {
+namespace utility {
+
+
+/** Miscellaneous functions related to date/time.
+ */
+class VMIME_EXPORT datetimeUtils {
+
+public:
+
+ /** Test whether the specified year is a leap year.
+ *
+ * @param year year in 4-digit format
+ * @return true if year is a leap year, false otherwise
+ */
+ static bool isLeapYear(const int year);
+
+ /** Return the number of days in the specified month.
+ *
+ * @param year year in 4-digit format (this is needed to check
+ * for leap years)
+ * @param month month, January is 1, December is 12 (see datetime::Months enum)
+ * @return the number of days in the month
+ */
+ static int getDaysInMonth(const int year, const int month);
+
+ /** Convert the specified date/time to UT (GMT).
+ *
+ * @param date date/time to convert
+ * @return GMT date/time
+ */
+ static const datetime toUniversalTime(const datetime& date);
+
+ /** Convert the specified date/time to the specified time zone.
+ *
+ * @param date date/time to convert
+ * @param zone local zone to convert to (see datetime::TimeZones enum)
+ * @return local time and date
+ */
+ static const datetime toLocalTime(const datetime& date, const int zone);
+
+ /** Return the day of the week from the specified date.
+ *
+ * @param year year in 4-digit format
+ * @param month month (1-12), January is 1, December is 12 (see datetime::Months enum)
+ * @param day month day (1-31)
+ * @return the day of the week, Sunday is 0, Monday is 1 (see datetime::DaysOfWeek enum)
+ */
+ static int getDayOfWeek(const int year, const int month, const int day);
+
+ /** Return the week number in the year (ISO 8601).
+ *
+ * @param year year in 4-digit format
+ * @param month month (1-12), January is 1, December is 12 (see datetime::Months enum)
+ * @param day month day (1-31)
+ * @param iso if TRUE, use ISO week-numbering year (default is to use calendar year).
+ * For more information, read here: http://en.wikipedia.org/wiki/ISO_8601#Week_dates
+ * @return the week number (1 is the first week of the year)
+ */
+ static int getWeekOfYear(const int year, const int month, const int day, const bool iso = false);
+};
+
+
+} // utility
+} // vmime
+
+
+#endif // VMIME_DATETIMEUTILS_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/encoder/b64Encoder.cpp b/vmime-master/src/vmime/utility/encoder/b64Encoder.cpp
new file mode 100644
index 0000000..ef4e581
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/b64Encoder.cpp
@@ -0,0 +1,350 @@
+//
+// 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.
+//
+
+#include "vmime/utility/encoder/b64Encoder.hpp"
+#include "vmime/parserHelpers.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+b64Encoder::b64Encoder() {
+
+}
+
+
+const std::vector <string> b64Encoder::getAvailableProperties() const {
+
+ std::vector <string> list(encoder::getAvailableProperties());
+
+ list.push_back("maxlinelength");
+
+ return list;
+}
+
+
+// 7-bits alphabet used to encode binary data
+const unsigned char b64Encoder::sm_alphabet[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+
+const unsigned char b64Encoder::sm_decodeMap[256] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0x00 - 0x0f
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0x10 - 0x1f
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3e,0xff,0xff,0xff,0x3f, // 0x20 - 0x2f
+ 0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0xff,0xff,0xff,0x3d,0xff,0xff, // 0x30 - 0x3f
+ 0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, // 0x40 - 0x4f
+ 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0xff,0xff,0xff,0xff,0xff, // 0x50 - 0x5f
+ 0xff,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28, // 0x60 - 0x6f
+ 0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0xff,0xff,0xff,0xff, // 0x70 - 0x7f
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0x80 - 0x8f
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0x90 - 0x9f
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0xa0 - 0xaf
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0xb0 - 0xbf
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0xc0 - 0xcf
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0xd0 - 0xdf
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0xe0 - 0xef
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, // 0xf0 - 0xff
+};
+
+#ifndef VMIME_BUILDING_DOC
+ #define B64_WRITE(s, x, l) s.write(reinterpret_cast <byte_t*>(x), l)
+#endif // VMIME_BUILDING_DOC
+
+
+
+size_t b64Encoder::encode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress
+) {
+
+ in.reset(); // may not work...
+
+ const size_t propMaxLineLength =
+ getProperties().getProperty <size_t>("maxlinelength", static_cast <size_t>(-1));
+
+ const bool cutLines = (propMaxLineLength != static_cast <size_t>(-1));
+ const size_t maxLineLength = std::min(propMaxLineLength, static_cast <size_t>(76));
+
+ // Process data
+ byte_t buffer[65536];
+ size_t bufferLength = 0;
+ size_t bufferPos = 0;
+
+ byte_t bytes[3];
+ byte_t output[4];
+
+ size_t total = 0;
+ size_t inTotal = 0;
+
+ size_t curCol = 0;
+
+ if (progress) {
+ progress->start(0);
+ }
+
+ while (bufferPos < bufferLength || !in.eof()) {
+
+ if (bufferPos >= bufferLength) {
+
+ bufferLength = in.read(buffer, sizeof(buffer));
+ bufferPos = 0;
+
+ if (bufferLength == 0) {
+ break;
+ }
+ }
+
+ // Get 3 bytes of data
+ int count = 0;
+
+ while (count < 3 && bufferPos < bufferLength) {
+ bytes[count++] = buffer[bufferPos++];
+ }
+
+ while (count < 3) {
+
+ // There may be more data in the next chunk...
+ if (bufferPos >= bufferLength) {
+
+ bufferLength = in.read(buffer, sizeof(buffer));
+ bufferPos = 0;
+
+ if (bufferLength == 0) {
+ break;
+ }
+ }
+
+ while (count < 3 && bufferPos < bufferLength) {
+ bytes[count++] = buffer[bufferPos++];
+ }
+ }
+
+ // Encode data
+ switch (count) {
+
+ case 1:
+
+ output[0] = sm_alphabet[(bytes[0] & 0xFC) >> 2];
+ output[1] = sm_alphabet[(bytes[0] & 0x03) << 4];
+ output[2] = sm_alphabet[64]; // padding
+ output[3] = sm_alphabet[64]; // padding
+
+ break;
+
+ case 2:
+
+ output[0] = sm_alphabet[(bytes[0] & 0xFC) >> 2];
+ output[1] = sm_alphabet[((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xF0) >> 4)];
+ output[2] = sm_alphabet[(bytes[1] & 0x0F) << 2];
+ output[3] = sm_alphabet[64]; // padding
+
+ break;
+
+ default:
+ case 3:
+
+ output[0] = sm_alphabet[(bytes[0] & 0xFC) >> 2];
+ output[1] = sm_alphabet[((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xF0) >> 4)];
+ output[2] = sm_alphabet[((bytes[1] & 0x0F) << 2) | ((bytes[2] & 0xC0) >> 6)];
+ output[3] = sm_alphabet[(bytes[2] & 0x3F)];
+
+ break;
+ }
+
+ // Write encoded data to output stream
+ B64_WRITE(out, output, 4);
+
+ inTotal += count;
+ total += 4;
+ curCol += 4;
+
+ if (cutLines && curCol + 2 /* \r\n */ + 4 /* next bytes */ >= maxLineLength) {
+ out.write("\r\n", 2);
+ curCol = 0;
+ }
+
+ if (progress) {
+ progress->progress(inTotal, inTotal);
+ }
+ }
+
+ if (progress) {
+ progress->stop(inTotal);
+ }
+
+ return total;
+}
+
+
+size_t b64Encoder::decode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress
+) {
+
+ in.reset(); // may not work...
+
+ // Process the data
+ byte_t buffer[16384];
+ size_t bufferLength = 0;
+ size_t bufferPos = 0;
+
+ size_t total = 0;
+ size_t inTotal = 0;
+
+ byte_t bytes[4];
+ byte_t output[3];
+
+ if (progress) {
+ progress->start(0);
+ }
+
+ while (bufferPos < bufferLength || !in.eof()) {
+
+ bytes[0] = '=';
+ bytes[1] = '=';
+ bytes[2] = '=';
+ bytes[3] = '=';
+
+ // Need to get more data?
+ if (bufferPos >= bufferLength) {
+
+ bufferLength = in.read(buffer, sizeof(buffer));
+ bufferPos = 0;
+
+ // No more data
+ if (bufferLength == 0) {
+ break;
+ }
+ }
+
+ // 4 bytes of input provide 3 bytes of output, so
+ // get the next 4 bytes from the input stream.
+ int count = 0;
+
+ while (count < 4 && bufferPos < bufferLength) {
+
+ const byte_t c = buffer[bufferPos++];
+
+ if (!parserHelpers::isSpace(c)) {
+ bytes[count++] = c;
+ }
+ }
+
+ if (count != 4) {
+
+ while (count < 4 && !in.eof()) {
+
+ // Data continues on the next chunk
+ bufferLength = in.read(buffer, sizeof(buffer));
+ bufferPos = 0;
+
+ while (count < 4 && bufferPos < bufferLength) {
+
+ const byte_t c = buffer[bufferPos++];
+
+ if (!parserHelpers::isSpace(c)) {
+ bytes[count++] = c;
+ }
+ }
+ }
+ }
+
+ if (count != 4) { // input length is not a multiple of 4 bytes
+ break;
+ }
+
+ // Decode the bytes
+ byte_t c1 = bytes[0];
+ byte_t c2 = bytes[1];
+
+ if (c1 == '=' || c2 == '=') { // end
+ break;
+ }
+
+ output[0] = static_cast <byte_t>((sm_decodeMap[c1] << 2) | ((sm_decodeMap[c2] & 0x30) >> 4));
+
+ c1 = bytes[2];
+
+ if (c1 == '=') { // end
+ B64_WRITE(out, output, 1);
+ total += 1;
+ break;
+ }
+
+ output[1] = static_cast <byte_t>(((sm_decodeMap[c2] & 0xf) << 4) | ((sm_decodeMap[c1] & 0x3c) >> 2));
+
+ c2 = bytes[3];
+
+ if (c2 == '=') { // end
+ B64_WRITE(out, output, 2);
+ total += 2;
+ break;
+ }
+
+ output[2] = static_cast <byte_t>(((sm_decodeMap[c1] & 0x03) << 6) | sm_decodeMap[c2]);
+
+ B64_WRITE(out, output, 3);
+ total += 3;
+ inTotal += count;
+
+ if (progress) {
+ progress->progress(inTotal, inTotal);
+ }
+ }
+
+ if (progress) {
+ progress->stop(inTotal);
+ }
+
+ return total;
+}
+
+
+size_t b64Encoder::getEncodedSize(const size_t n) const {
+
+ const size_t propMaxLineLength =
+ getProperties().getProperty <size_t>("maxlinelength", static_cast <size_t>(-1));
+
+ const bool cutLines = (propMaxLineLength != static_cast <size_t>(-1));
+ const size_t maxLineLength = std::min(propMaxLineLength, static_cast <size_t>(76));
+
+ return (n * 4) / 3 // 3 bytes of input provide 4 bytes of output
+ + (cutLines ? (n / maxLineLength) * 2 : 0) // CRLF (2 bytes) for each line.
+ + 4; // padding
+}
+
+
+size_t b64Encoder::getDecodedSize(const size_t n) const {
+
+ // 4 bytes of input provide 3 bytes of output
+ return (n * 3) / 4;
+}
+
+
+} // encoder
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/encoder/b64Encoder.hpp b/vmime-master/src/vmime/utility/encoder/b64Encoder.hpp
new file mode 100644
index 0000000..c5be2c3
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/b64Encoder.hpp
@@ -0,0 +1,73 @@
+//
+// 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_UTILITY_ENCODER_B64ENCODER_HPP_INCLUDED
+#define VMIME_UTILITY_ENCODER_B64ENCODER_HPP_INCLUDED
+
+
+#include "vmime/utility/encoder/encoder.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+/** Base64 encoder.
+ */
+class VMIME_EXPORT b64Encoder : public encoder {
+
+public:
+
+ b64Encoder();
+
+ size_t encode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress = NULL
+ );
+
+ size_t decode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress = NULL
+ );
+
+ const std::vector <string> getAvailableProperties() const;
+
+ size_t getEncodedSize(const size_t n) const;
+ size_t getDecodedSize(const size_t n) const;
+
+protected:
+
+ static const unsigned char sm_alphabet[];
+ static const unsigned char sm_decodeMap[256];
+};
+
+
+} // encoder
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_ENCODER_B64ENCODER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/encoder/binaryEncoder.cpp b/vmime-master/src/vmime/utility/encoder/binaryEncoder.cpp
new file mode 100644
index 0000000..b30bb7b
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/binaryEncoder.cpp
@@ -0,0 +1,39 @@
+//
+// 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.
+//
+
+#include "vmime/utility/encoder/binaryEncoder.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+binaryEncoder::binaryEncoder() {
+
+}
+
+
+} // encoder
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/encoder/binaryEncoder.hpp b/vmime-master/src/vmime/utility/encoder/binaryEncoder.hpp
new file mode 100644
index 0000000..331014e
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/binaryEncoder.hpp
@@ -0,0 +1,51 @@
+//
+// 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_UTILITY_ENCODER_BINARYENCODER_HPP_INCLUDED
+#define VMIME_UTILITY_ENCODER_BINARYENCODER_HPP_INCLUDED
+
+
+#include "vmime/utility/encoder/noopEncoder.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+/** Binary encoder.
+ */
+class VMIME_EXPORT binaryEncoder : public noopEncoder {
+
+public:
+
+ binaryEncoder();
+};
+
+
+} // encoder
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_ENCODER_BINARYENCODER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/encoder/eightBitEncoder.cpp b/vmime-master/src/vmime/utility/encoder/eightBitEncoder.cpp
new file mode 100644
index 0000000..a966931
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/eightBitEncoder.cpp
@@ -0,0 +1,39 @@
+//
+// 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.
+//
+
+#include "vmime/utility/encoder/eightBitEncoder.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+eightBitEncoder::eightBitEncoder() {
+
+}
+
+
+} // encoder
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/encoder/eightBitEncoder.hpp b/vmime-master/src/vmime/utility/encoder/eightBitEncoder.hpp
new file mode 100644
index 0000000..c400f51
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/eightBitEncoder.hpp
@@ -0,0 +1,51 @@
+//
+// 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_UTILITY_ENCODER_EIGHTBITENCODER_HPP_INCLUDED
+#define VMIME_UTILITY_ENCODER_EIGHTBITENCODER_HPP_INCLUDED
+
+
+#include "vmime/utility/encoder/noopEncoder.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+/** 8-bit encoder.
+ */
+class VMIME_EXPORT eightBitEncoder : public noopEncoder {
+
+public:
+
+ eightBitEncoder();
+};
+
+
+} // encoder
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_ENCODER_EIGHTBITENCODER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/encoder/encoder.cpp b/vmime-master/src/vmime/utility/encoder/encoder.cpp
new file mode 100644
index 0000000..634adf0
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/encoder.cpp
@@ -0,0 +1,76 @@
+//
+// 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.
+//
+
+#include "vmime/utility/encoder/encoder.hpp"
+#include "vmime/exception.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+encoder::encoder() {
+
+}
+
+
+encoder::~encoder() {
+
+}
+
+
+const propertySet& encoder::getProperties() const {
+
+ return m_props;
+}
+
+
+propertySet& encoder::getProperties() {
+
+ return m_props;
+}
+
+
+const propertySet& encoder::getResults() const {
+
+ return m_results;
+}
+
+
+propertySet& encoder::getResults() {
+
+ return m_results;
+}
+
+
+const std::vector <string> encoder::getAvailableProperties() const {
+
+ std::vector <string> list;
+ return list;
+}
+
+
+} // encoder
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/encoder/encoder.hpp b/vmime-master/src/vmime/utility/encoder/encoder.hpp
new file mode 100644
index 0000000..134e813
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/encoder.hpp
@@ -0,0 +1,135 @@
+//
+// 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_UTILITY_ENCODER_ENCODER_HPP_INCLUDED
+#define VMIME_UTILITY_ENCODER_ENCODER_HPP_INCLUDED
+
+
+#include "vmime/base.hpp"
+#include "vmime/propertySet.hpp"
+#include "vmime/exception.hpp"
+#include "vmime/utility/progressListener.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+/** Encode/decode data in different encodings.
+ */
+class VMIME_EXPORT encoder : public object {
+
+public:
+
+ encoder();
+ virtual ~encoder();
+
+ /** Encode data.
+ *
+ * @param in input data (decoded)
+ * @param out output stream for encoded data
+ * @param progress progress listener, or NULL if you do not
+ * want to receive progress notifications
+ * @return number of bytes written into output stream
+ */
+ virtual size_t encode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress = NULL
+ ) = 0;
+
+ /** Decode data.
+ *
+ * @param in input data (encoded)
+ * @param out output stream for decoded data
+ * @param progress progress listener, or NULL if you do not
+ * want to receive progress notifications
+ * @return number of bytes written into output stream
+ */
+ virtual size_t decode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress = NULL
+ ) = 0;
+
+ /** Return the properties of the encoder.
+ *
+ * @return properties of the encoder
+ */
+ const propertySet& getProperties() const;
+
+ /** Return the properties of the encoder.
+ *
+ * @return properties of the encoder
+ */
+ propertySet& getProperties();
+
+ /** Return a list of property names that can be set for
+ * this encoder.
+ *
+ * @return list of property names
+ */
+ virtual const std::vector <string> getAvailableProperties() const;
+
+ /** Return the results returned by this encoder.
+ *
+ * @return results returned by the encoder
+ */
+ const propertySet& getResults() const;
+
+ /** Return the encoded size for the specified input (decoded) size.
+ * If the size is not exact, it may be an estimate which should always
+ * be larger than the actual encoded size.
+ *
+ * @param n count of input (decoded) bytes
+ * @return count of output (encoded) bytes
+ */
+ virtual size_t getEncodedSize(const size_t n) const = 0;
+
+ /** Return the encoded size for the specified input (encoded) size.
+ * If the size is not exact, it may be an estimate which should always
+ * be larger than the actual decoded size.
+ *
+ * @param n count of input (encoded) bytes
+ * @return count of output (decoded) bytes
+ */
+ virtual size_t getDecodedSize(const size_t n) const = 0;
+
+protected:
+
+ propertySet& getResults();
+
+private:
+
+ propertySet m_props;
+ propertySet m_results;
+};
+
+
+} // encoder
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_ENCODER_ENCODER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/encoder/encoderFactory.cpp b/vmime-master/src/vmime/utility/encoder/encoderFactory.cpp
new file mode 100644
index 0000000..df655ae
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/encoderFactory.cpp
@@ -0,0 +1,149 @@
+//
+// 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.
+//
+
+#include "vmime/utility/encoder/encoderFactory.hpp"
+#include "vmime/exception.hpp"
+
+#include "vmime/utility/encoder/b64Encoder.hpp"
+#include "vmime/utility/encoder/qpEncoder.hpp"
+#include "vmime/utility/encoder/uuEncoder.hpp"
+#include "vmime/utility/encoder/binaryEncoder.hpp"
+#include "vmime/utility/encoder/sevenBitEncoder.hpp"
+#include "vmime/utility/encoder/eightBitEncoder.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+encoderFactory::encoderFactory() {
+
+ // Register some default encoders
+ registerName <b64Encoder>("base64");
+ registerName <qpEncoder>("quoted-printable");
+ registerName <uuEncoder>("uuencode");
+ registerName <uuEncoder>("x-uuencode");
+ registerName <sevenBitEncoder>("7bit");
+ registerName <eightBitEncoder>("8bit");
+ registerName <binaryEncoder>("binary");
+
+ // Also register some non-standard encoding names
+ registerName <sevenBitEncoder>("7-bit");
+ registerName <eightBitEncoder>("8-bit");
+ registerName <eightBitEncoder>("8bits");
+
+ // Finally, register some bogus encoding names, for compatibility
+ registerName <qpEncoder>("bmoted-printable");
+}
+
+
+encoderFactory::~encoderFactory() {
+
+}
+
+
+shared_ptr <encoderFactory> encoderFactory::getInstance() {
+
+ static encoderFactory instance;
+ return shared_ptr <encoderFactory>(&instance, noop_shared_ptr_deleter <encoderFactory>());
+}
+
+
+shared_ptr <encoder> encoderFactory::create(const string& name) {
+
+ try {
+
+ return (getEncoderByName(name)->create());
+
+ } catch (exceptions::no_encoder_available &) {
+
+ if (m_defaultEncoder) {
+ return m_defaultEncoder;
+ }
+
+ throw;
+ }
+}
+
+
+const shared_ptr <const encoderFactory::registeredEncoder>
+ encoderFactory::getEncoderByName(const string& name) const {
+
+ const string lcName(utility::stringUtils::toLower(name));
+
+ for (std::vector <shared_ptr <registeredEncoder> >::const_iterator it = m_encoders.begin() ;
+ it != m_encoders.end() ; ++it) {
+
+ if ((*it)->getName() == lcName) {
+ return (*it);
+ }
+ }
+
+ throw exceptions::no_encoder_available(name);
+}
+
+
+size_t encoderFactory::getEncoderCount() const {
+
+ return m_encoders.size();
+}
+
+
+const shared_ptr <const encoderFactory::registeredEncoder>
+ encoderFactory::getEncoderAt(const size_t pos) const {
+
+ return m_encoders[pos];
+}
+
+
+const std::vector <shared_ptr <const encoderFactory::registeredEncoder> >
+ encoderFactory::getEncoderList() const {
+
+ std::vector <shared_ptr <const registeredEncoder> > res;
+
+ for (std::vector <shared_ptr <registeredEncoder> >::const_iterator it = m_encoders.begin() ;
+ it != m_encoders.end() ; ++it) {
+
+ res.push_back(*it);
+ }
+
+ return res;
+}
+
+
+void encoderFactory::setDefaultEncoder(const shared_ptr <encoder>& enc) {
+
+ m_defaultEncoder = enc;
+}
+
+
+shared_ptr <encoder> encoderFactory::getDefaultEncoder() const {
+
+ return m_defaultEncoder;
+}
+
+
+} // encoder
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/encoder/encoderFactory.hpp b/vmime-master/src/vmime/utility/encoder/encoderFactory.hpp
new file mode 100644
index 0000000..e475f8e
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/encoderFactory.hpp
@@ -0,0 +1,164 @@
+//
+// 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_UTILITY_ENCODER_ENCODERFACTORY_HPP_INCLUDED
+#define VMIME_UTILITY_ENCODER_ENCODERFACTORY_HPP_INCLUDED
+
+
+#include "vmime/utility/encoder/encoder.hpp"
+#include "vmime/utility/stringUtils.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+/** A factory to create 'encoder' objects for the specified encoding.
+ */
+class VMIME_EXPORT encoderFactory
+{
+private:
+
+ encoderFactory();
+ ~encoderFactory();
+
+public:
+
+ static shared_ptr <encoderFactory> getInstance();
+
+ /** Information about a registered encoder. */
+ class VMIME_EXPORT registeredEncoder : public object {
+
+ protected:
+
+ virtual ~registeredEncoder() { }
+
+ public:
+
+ virtual shared_ptr <encoder> create() const = 0;
+
+ virtual const string& getName() const = 0;
+ };
+
+private:
+
+ template <class E>
+ class registeredEncoderImpl : public registeredEncoder {
+
+ public:
+
+ registeredEncoderImpl(const string& name) : m_name(name) { }
+
+ shared_ptr <encoder> create() const {
+
+ return vmime::make_shared <E>();
+ }
+
+ const string& getName() const {
+
+ return m_name;
+ }
+
+ private:
+
+ const string m_name;
+ };
+
+
+ std::vector <shared_ptr <registeredEncoder> > m_encoders;
+ shared_ptr <encoder> m_defaultEncoder;
+
+public:
+
+ /** Register a new encoder by its encoding name.
+ *
+ * @param name encoding name
+ */
+ template <class E>
+ void registerName(const string& name) {
+
+ m_encoders.push_back(
+ vmime::make_shared <registeredEncoderImpl <E> >(utility::stringUtils::toLower(name))
+ );
+ }
+
+ /** Create a new encoder instance from an encoding name.
+ *
+ * @param name encoding name (eg. "base64")
+ * @return a new encoder instance for the specified encoding
+ * @throw exceptions::no_encoder_available if no encoder is registered
+ * for this encoding
+ */
+ shared_ptr <encoder> create(const string& name);
+
+ /** Return information about a registered encoder.
+ *
+ * @param name encoding name
+ * @return information about this encoder
+ * @throw exceptions::no_encoder_available if no encoder is registered
+ * for this encoding
+ */
+ const shared_ptr <const registeredEncoder> getEncoderByName(const string& name) const;
+
+ /** Return the number of registered encoders.
+ *
+ * @return number of registered encoders
+ */
+ size_t getEncoderCount() const;
+
+ /** Return the registered encoder at the specified position.
+ *
+ * @param pos position of the registered encoder to return
+ * @return registered encoder at the specified position
+ */
+ const shared_ptr <const registeredEncoder> getEncoderAt(const size_t pos) const;
+
+ /** Return a list of all registered encoders.
+ *
+ * @return list of registered encoders
+ */
+ const std::vector <shared_ptr <const registeredEncoder> > getEncoderList() const;
+
+ /** Set the default encoder to use when no other encoder
+ * is registered for an encoding (fallback).
+ *
+ * @param enc default encoder
+ */
+ void setDefaultEncoder(const shared_ptr <encoder>& enc);
+
+ /** Return the default encoder to use when no other encoder
+ * is registered for an encoding (fallback).
+ *
+ * @return default encoder
+ */
+ shared_ptr <encoder> getDefaultEncoder() const;
+};
+
+
+} // encoder
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_ENCODER_ENCODERFACTORY_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/encoder/noopEncoder.cpp b/vmime-master/src/vmime/utility/encoder/noopEncoder.cpp
new file mode 100644
index 0000000..30cc6c1
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/noopEncoder.cpp
@@ -0,0 +1,94 @@
+//
+// 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.
+//
+
+#include "vmime/utility/encoder/noopEncoder.hpp"
+
+#include "vmime/utility/streamUtils.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+noopEncoder::noopEncoder() {
+
+}
+
+
+size_t noopEncoder::encode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress
+) {
+
+ in.reset(); // may not work...
+
+ // No encoding performed
+ size_t res = 0;
+
+ if (progress)
+ res = utility::bufferedStreamCopy(in, out, 0, progress);
+ else
+ res = utility::bufferedStreamCopy(in, out);
+
+ return res;
+}
+
+
+size_t noopEncoder::decode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress
+) {
+
+ in.reset(); // may not work...
+
+ // No decoding performed
+ size_t res = 0;
+
+ if (progress) {
+ res = utility::bufferedStreamCopy(in, out, 0, progress);
+ } else {
+ res = utility::bufferedStreamCopy(in, out);
+ }
+
+ return res;
+}
+
+
+size_t noopEncoder::getEncodedSize(const size_t n) const {
+
+ return n;
+}
+
+
+size_t noopEncoder::getDecodedSize(const size_t n) const {
+
+ return n;
+}
+
+
+} // encoder
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/encoder/noopEncoder.hpp b/vmime-master/src/vmime/utility/encoder/noopEncoder.hpp
new file mode 100644
index 0000000..91944de
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/noopEncoder.hpp
@@ -0,0 +1,66 @@
+//
+// 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_UTILITY_ENCODER_NOOPENCODER_HPP_INCLUDED
+#define VMIME_UTILITY_ENCODER_NOOPENCODER_HPP_INCLUDED
+
+
+#include "vmime/utility/encoder/encoder.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+/** Default, no-op encoder (simple copy, no encoding/decoding is performed).
+ */
+class VMIME_EXPORT noopEncoder : public encoder {
+
+public:
+
+ noopEncoder();
+
+ size_t encode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress = NULL
+ );
+
+ size_t decode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress = NULL
+ );
+
+ size_t getEncodedSize(const size_t n) const;
+ size_t getDecodedSize(const size_t n) const;
+};
+
+
+} // encoder
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_ENCODER_NOOPENCODER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/encoder/qpEncoder.cpp b/vmime-master/src/vmime/utility/encoder/qpEncoder.cpp
new file mode 100644
index 0000000..4aeb640
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/qpEncoder.cpp
@@ -0,0 +1,568 @@
+//
+// 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.
+//
+
+#include "vmime/utility/encoder/qpEncoder.hpp"
+#include "vmime/parserHelpers.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+qpEncoder::qpEncoder() {
+
+}
+
+
+const std::vector <string> qpEncoder::getAvailableProperties() const {
+
+ std::vector <string> list(encoder::getAvailableProperties());
+
+ list.push_back("maxlinelength");
+
+ list.push_back("text"); // if set, '\r' and '\n' are not hex-encoded.
+ // WARNING! You should not use this for binary data!
+
+ list.push_back("rfc2047"); // for header fields encoding (RFC #2047)
+
+ return list;
+}
+
+
+
+// Hex-encoding table
+const unsigned char qpEncoder::sm_hexDigits[] = "0123456789ABCDEF";
+
+
+// RFC-2047 encoding table: we always encode RFC-2047 using the restricted
+// charset, that is the one used for 'phrase' in From/To/Cc/... headers.
+//
+// " The set of characters that may be used in a "Q"-encoded 'encoded-word'
+// is restricted to: <upper and lower case ASCII letters, decimal digits,
+// "!", "*", "+", "-", "/", "=", and "_" (underscore, ASCII 95.)>. "
+//
+// Two special cases:
+// - encode space (32) as underscore (95)
+// - encode underscore as hex (=5F)
+//
+// This is a quick lookup table:
+// '1' means "encode", '0' means "no encoding"
+//
+const vmime_uint8 qpEncoder::sm_RFC2047EncodeTable[] = {
+ /* 0 NUL */ 1, /* 1 SOH */ 1, /* 2 STX */ 1, /* 3 ETX */ 1, /* 4 EOT */ 1, /* 5 ENQ */ 1,
+ /* 6 ACK */ 1, /* 7 BEL */ 1, /* 8 BS */ 1, /* 9 TAB */ 1, /* 10 LF */ 1, /* 11 VT */ 1,
+ /* 12 FF */ 1, /* 13 CR */ 1, /* 14 SO */ 1, /* 15 SI */ 1, /* 16 DLE */ 1, /* 17 DC1 */ 1,
+ /* 18 DC2 */ 1, /* 19 DC3 */ 1, /* 20 DC4 */ 1, /* 21 NAK */ 1, /* 22 SYN */ 1, /* 23 ETB */ 1,
+ /* 24 CAN */ 1, /* 25 EM */ 1, /* 26 SUB */ 1, /* 27 ESC */ 1, /* 28 FS */ 1, /* 29 GS */ 1,
+ /* 30 RS */ 1, /* 31 US */ 1, /* 32 SPACE*/ 1, /* 33 ! */ 0, /* 34 " */ 1, /* 35 # */ 1,
+ /* 36 $ */ 1, /* 37 % */ 1, /* 38 & */ 1, /* 39 ' */ 1, /* 40 ( */ 1, /* 41 ) */ 1,
+ /* 42 * */ 0, /* 43 + */ 0, /* 44 , */ 1, /* 45 - */ 0, /* 46 . */ 1, /* 47 / */ 0,
+ /* 48 0 */ 0, /* 49 1 */ 0, /* 50 2 */ 0, /* 51 3 */ 0, /* 52 4 */ 0, /* 53 5 */ 0,
+ /* 54 6 */ 0, /* 55 7 */ 0, /* 56 8 */ 0, /* 57 9 */ 0, /* 58 : */ 1, /* 59 ; */ 1,
+ /* 60 < */ 1, /* 61 = */ 1, /* 62 > */ 1, /* 63 ? */ 1, /* 64 @ */ 1, /* 65 A */ 0,
+ /* 66 B */ 0, /* 67 C */ 0, /* 68 D */ 0, /* 69 E */ 0, /* 70 F */ 0, /* 71 G */ 0,
+ /* 72 H */ 0, /* 73 I */ 0, /* 74 J */ 0, /* 75 K */ 0, /* 76 L */ 0, /* 77 M */ 0,
+ /* 78 N */ 0, /* 79 O */ 0, /* 80 P */ 0, /* 81 Q */ 0, /* 82 R */ 0, /* 83 S */ 0,
+ /* 84 T */ 0, /* 85 U */ 0, /* 86 V */ 0, /* 87 W */ 0, /* 88 X */ 0, /* 89 Y */ 0,
+ /* 90 Z */ 0, /* 91 [ */ 1, /* 92 " */ 1, /* 93 ] */ 1, /* 94 ^ */ 1, /* 95 _ */ 1,
+ /* 96 ` */ 1, /* 97 a */ 0, /* 98 b */ 0, /* 99 c */ 0, /* 100 d */ 0, /* 101 e */ 0,
+ /* 102 f */ 0, /* 103 g */ 0, /* 104 h */ 0, /* 105 i */ 0, /* 106 j */ 0, /* 107 k */ 0,
+ /* 108 l */ 0, /* 109 m */ 0, /* 110 n */ 0, /* 111 o */ 0, /* 112 p */ 0, /* 113 q */ 0,
+ /* 114 r */ 0, /* 115 s */ 0, /* 116 t */ 0, /* 117 u */ 0, /* 118 v */ 0, /* 119 w */ 0,
+ /* 120 x */ 0, /* 121 y */ 0, /* 122 z */ 0, /* 123 { */ 1, /* 124 | */ 1, /* 125 } */ 1,
+ /* 126 ~ */ 1, /* 127 DEL */ 1
+};
+
+
+// Hex-decoding table
+const vmime_uint8 qpEncoder::sm_hexDecodeTable[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+
+// static
+bool qpEncoder::RFC2047_isEncodingNeededForChar(const byte_t c) {
+
+ return c >= 128 || sm_RFC2047EncodeTable[c] != 0;
+}
+
+
+// static
+int qpEncoder::RFC2047_getEncodedLength(const byte_t c) {
+
+ if (c >= 128 || sm_RFC2047EncodeTable[c] != 0) {
+
+ if (c == 32) { // space
+
+ // Encoded as "_"
+ return 1;
+
+ } else {
+
+ // Hex encoding
+ return 3;
+ }
+
+ } else {
+
+ return 1; // no encoding
+ }
+}
+
+
+#ifndef VMIME_BUILDING_DOC
+
+#define QP_ENCODE_HEX(x) \
+ outBuffer[outBufferPos] = '='; \
+ outBuffer[outBufferPos + 1] = sm_hexDigits[x >> 4]; \
+ outBuffer[outBufferPos + 2] = sm_hexDigits[x & 0xF]; \
+ outBufferPos += 3; \
+ curCol += 3
+
+#define QP_WRITE(s, x, l) s.write(reinterpret_cast <byte_t*>(x), l)
+
+#endif // VMIME_BUILDING_DOC
+
+
+size_t qpEncoder::encode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress
+) {
+
+ in.reset(); // may not work...
+
+ const size_t propMaxLineLength =
+ getProperties().getProperty <size_t>("maxlinelength", static_cast <size_t>(-1));
+
+ const bool rfc2047 = getProperties().getProperty <bool>("rfc2047", false);
+ const bool text = getProperties().getProperty <bool>("text", false); // binary mode by default
+
+ const bool cutLines = (propMaxLineLength != static_cast <size_t>(-1));
+ const size_t maxLineLength = std::min(propMaxLineLength, static_cast <size_t>(74));
+
+ // Process the data
+ byte_t buffer[16384];
+ size_t bufferLength = 0;
+ size_t bufferPos = 0;
+
+ size_t curCol = 0;
+
+ byte_t outBuffer[16384];
+ size_t outBufferPos = 0;
+
+ size_t total = 0;
+ size_t inTotal = 0;
+
+ if (progress) {
+ progress->start(0);
+ }
+
+ while (bufferPos < bufferLength || !in.eof()) {
+
+ // Flush current output buffer
+ if (outBufferPos + 6 >= static_cast <int>(sizeof(outBuffer))) {
+
+ QP_WRITE(out, outBuffer, outBufferPos);
+
+ total += outBufferPos;
+ outBufferPos = 0;
+ }
+
+ // Need to get more data?
+ if (bufferPos >= bufferLength) {
+
+ bufferLength = in.read(buffer, sizeof(buffer));
+ bufferPos = 0;
+
+ // No more data
+ if (bufferLength == 0) {
+ break;
+ }
+ }
+
+ // Get the next char and encode it
+ const byte_t c = buffer[bufferPos++];
+
+ if (rfc2047) {
+
+ if (c >= 128 || sm_RFC2047EncodeTable[c] != 0) {
+
+ if (c == 32) { // space
+
+ // RFC-2047, Page 5, 4.2. The "Q" encoding:
+ // << The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be
+ // represented as "_" (underscore, ASCII 95.). >>
+ outBuffer[outBufferPos++] = '_';
+ ++curCol;
+
+ } else {
+
+ // Other characters: '=' + hexadecimal encoding
+ QP_ENCODE_HEX(c);
+ }
+
+ } else {
+
+ // No encoding
+ outBuffer[outBufferPos++] = c;
+ ++curCol;
+ }
+
+ } else {
+
+ switch (c) {
+
+ case 46: { // .
+
+ if (curCol == 0) {
+ // If a '.' appears at the beginning of a line, we encode it to
+ // to avoid problems with SMTP servers... ("\r\n.\r\n" means the
+ // end of data transmission).
+ QP_ENCODE_HEX('.');
+ continue;
+ }
+
+ outBuffer[outBufferPos++] = '.';
+ ++curCol;
+ break;
+ }
+ case 32: { // space
+
+ // Need to get more data?
+ if (bufferPos >= bufferLength) {
+ bufferLength = in.read(buffer, sizeof(buffer));
+ bufferPos = 0;
+ }
+
+ // Spaces cannot appear at the end of a line. So, encode the space.
+ if (bufferPos >= bufferLength ||
+ (buffer[bufferPos] == '\r' || buffer[bufferPos] == '\n')) {
+
+ QP_ENCODE_HEX(' ');
+
+ } else {
+
+ outBuffer[outBufferPos++] = ' ';
+ ++curCol;
+ }
+
+ break;
+ }
+ case 9: { // TAB
+
+ QP_ENCODE_HEX(c);
+ break;
+ }
+ case 13: // CR
+ case 10: { // LF
+
+ // RFC-2045/6.7(4)
+
+ // Text data
+ if (text && !rfc2047) {
+
+ outBuffer[outBufferPos++] = c;
+ ++curCol;
+
+ if (c == 10) {
+ curCol = 0; // reset current line length
+ }
+
+ // Binary data
+ } else {
+
+ QP_ENCODE_HEX(c);
+ }
+
+ break;
+ }
+ case 61: { // =
+
+ QP_ENCODE_HEX('=');
+ break;
+ }
+ /*
+ Rule #2: (Literal representation) Octets with decimal values of 33
+ through 60 inclusive, and 62 through 126, inclusive, MAY be
+ represented as the ASCII characters which correspond to those
+ octets (EXCLAMATION POINT through LESS THAN, and GREATER THAN
+ through TILDE, respectively).
+ */
+ default:
+
+ //if ((c >= 33 && c <= 60) || (c >= 62 && c <= 126))
+ if (c >= 33 && c <= 126 && c != 61 && c != 63) {
+
+ outBuffer[outBufferPos++] = c;
+ ++curCol;
+
+ // Other characters: '=' + hexadecimal encoding
+ } else {
+
+ QP_ENCODE_HEX(c);
+ }
+
+ break;
+
+ } // switch (c)
+
+ // Soft line break : "=\r\n"
+ if (cutLines && curCol >= maxLineLength - 1) {
+
+ outBuffer[outBufferPos] = '=';
+ outBuffer[outBufferPos + 1] = '\r';
+ outBuffer[outBufferPos + 2] = '\n';
+
+ outBufferPos += 3;
+ curCol = 0;
+ }
+
+ } // !rfc2047
+
+ ++inTotal;
+
+ if (progress) {
+ progress->progress(inTotal, inTotal);
+ }
+ }
+
+ // Flush remaining output buffer
+ if (outBufferPos != 0) {
+ QP_WRITE(out, outBuffer, outBufferPos);
+ total += outBufferPos;
+ }
+
+ if (progress) {
+ progress->stop(inTotal);
+ }
+
+ return total;
+}
+
+
+size_t qpEncoder::decode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress
+) {
+
+ in.reset(); // may not work...
+
+ // Process the data
+ const bool rfc2047 = getProperties().getProperty <bool>("rfc2047", false);
+
+ byte_t buffer[16384];
+ size_t bufferLength = 0;
+ size_t bufferPos = 0;
+
+ byte_t outBuffer[16384];
+ size_t outBufferPos = 0;
+
+ size_t total = 0;
+ size_t inTotal = 0;
+
+ while (bufferPos < bufferLength || !in.eof()) {
+
+ // Flush current output buffer
+ if (outBufferPos >= sizeof(outBuffer)) {
+
+ QP_WRITE(out, outBuffer, outBufferPos);
+
+ total += outBufferPos;
+ outBufferPos = 0;
+ }
+
+ // Need to get more data?
+ if (bufferPos >= bufferLength) {
+
+ bufferLength = in.read(buffer, sizeof(buffer));
+ bufferPos = 0;
+
+ // No more data
+ if (bufferLength == 0) {
+ break;
+ }
+ }
+
+ // Decode the next sequence (hex-encoded byte or printable character)
+ byte_t c = buffer[bufferPos++];
+
+ ++inTotal;
+
+ switch (c) {
+
+ case '=': {
+
+ if (bufferPos >= bufferLength) {
+ bufferLength = in.read(buffer, sizeof(buffer));
+ bufferPos = 0;
+ }
+
+ if (bufferPos < bufferLength) {
+
+ c = buffer[bufferPos++];
+
+ ++inTotal;
+
+ switch (c) {
+
+ // Ignore soft line break ("=\r\n" or "=\n")
+ case '\r':
+
+ // Read one byte more
+ if (bufferPos >= bufferLength) {
+ bufferLength = in.read(buffer, sizeof(buffer));
+ bufferPos = 0;
+ }
+
+ if (bufferPos < bufferLength) {
+ ++bufferPos;
+ ++inTotal;
+ }
+
+ break;
+
+ case '\n':
+
+ break;
+
+ // Hex-encoded char
+ default:
+ {
+ // We need another byte...
+ if (bufferPos >= bufferLength) {
+ bufferLength = in.read(buffer, sizeof(buffer));
+ bufferPos = 0;
+ }
+
+ if (bufferPos < bufferLength) {
+
+ const byte_t next = buffer[bufferPos++];
+
+ ++inTotal;
+
+ const byte_t value = static_cast <byte_t>(
+ sm_hexDecodeTable[c] * 16 + sm_hexDecodeTable[next]
+ );
+
+ outBuffer[outBufferPos++] = value;
+
+ } else {
+
+ // Premature end-of-data
+ }
+
+ break;
+ }
+
+ }
+
+ } else {
+
+ // Premature end-of-data
+ }
+
+ break;
+ }
+ case '_': {
+
+ if (rfc2047) {
+
+ // RFC-2047, Page 5, 4.2. The "Q" encoding:
+ // << Note that the "_" always represents hexadecimal 20, even if the SPACE
+ // character occupies a different code position in the character set in use. >>
+ outBuffer[outBufferPos++] = 0x20;
+ break;
+ }
+
+ outBuffer[outBufferPos++] = c;
+ break;
+ }
+ default: {
+
+ outBuffer[outBufferPos++] = c;
+ break;
+ }
+
+ }
+
+ if (progress) {
+ progress->progress(inTotal, inTotal);
+ }
+ }
+
+ // Flush remaining output buffer
+ if (outBufferPos != 0) {
+ QP_WRITE(out, outBuffer, outBufferPos);
+ total += outBufferPos;
+ }
+
+ if (progress) {
+ progress->stop(inTotal);
+ }
+
+ return total;
+}
+
+
+size_t qpEncoder::getEncodedSize(const size_t n) const {
+
+ const size_t propMaxLineLength =
+ getProperties().getProperty <size_t>("maxlinelength", static_cast <size_t>(-1));
+
+ const bool cutLines = (propMaxLineLength != static_cast <size_t>(-1));
+ const size_t maxLineLength = std::min(propMaxLineLength, static_cast <size_t>(74));
+
+ // Worst cast: 1 byte of input provide 3 bytes of output
+ // Count CRLF (2 bytes) for each line.
+ return n * 3 + (cutLines ? (n / maxLineLength) * 2 : 0);
+}
+
+
+size_t qpEncoder::getDecodedSize(const size_t n) const {
+
+ // Worst case: 1 byte of input equals 1 byte of output
+ return n;
+}
+
+
+} // encoder
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/encoder/qpEncoder.hpp b/vmime-master/src/vmime/utility/encoder/qpEncoder.hpp
new file mode 100644
index 0000000..21263a6
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/qpEncoder.hpp
@@ -0,0 +1,77 @@
+//
+// 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_UTILITY_ENCODER_QPENCODER_HPP_INCLUDED
+#define VMIME_UTILITY_ENCODER_QPENCODER_HPP_INCLUDED
+
+
+#include "vmime/utility/encoder/encoder.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+/** Quoted-printable encoder.
+ */
+class VMIME_EXPORT qpEncoder : public encoder {
+
+public:
+
+ qpEncoder();
+
+ size_t encode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress = NULL
+ );
+
+ size_t decode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress = NULL
+ );
+
+ const std::vector <string> getAvailableProperties() const;
+
+ static bool RFC2047_isEncodingNeededForChar(const unsigned char c);
+ static int RFC2047_getEncodedLength(const unsigned char c);
+
+ size_t getEncodedSize(const size_t n) const;
+ size_t getDecodedSize(const size_t n) const;
+
+protected:
+
+ static const unsigned char sm_hexDigits[17];
+ static const unsigned char sm_hexDecodeTable[256];
+ static const unsigned char sm_RFC2047EncodeTable[128];
+};
+
+
+} // encoder
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_ENCODER_QPENCODER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/encoder/sevenBitEncoder.cpp b/vmime-master/src/vmime/utility/encoder/sevenBitEncoder.cpp
new file mode 100644
index 0000000..999b11e
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/sevenBitEncoder.cpp
@@ -0,0 +1,39 @@
+//
+// 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.
+//
+
+#include "vmime/utility/encoder/sevenBitEncoder.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+sevenBitEncoder::sevenBitEncoder() {
+
+}
+
+
+} // encoder
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/encoder/sevenBitEncoder.hpp b/vmime-master/src/vmime/utility/encoder/sevenBitEncoder.hpp
new file mode 100644
index 0000000..37f84a6
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/sevenBitEncoder.hpp
@@ -0,0 +1,51 @@
+//
+// 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_UTILITY_ENCODER_SEVENBITENCODER_HPP_INCLUDED
+#define VMIME_UTILITY_ENCODER_SEVENBITENCODER_HPP_INCLUDED
+
+
+#include "vmime/utility/encoder/noopEncoder.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+/** 7-bit encoder.
+ */
+class VMIME_EXPORT sevenBitEncoder : public noopEncoder
+{
+public:
+
+ sevenBitEncoder();
+};
+
+
+} // encoder
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_ENCODER_SEVENBITENCODER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/encoder/uuEncoder.cpp b/vmime-master/src/vmime/utility/encoder/uuEncoder.cpp
new file mode 100644
index 0000000..24dcdc8
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/uuEncoder.cpp
@@ -0,0 +1,358 @@
+//
+// 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.
+//
+
+#include "vmime/utility/encoder/uuEncoder.hpp"
+#include "vmime/parserHelpers.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+uuEncoder::uuEncoder() {
+
+ getProperties()["mode"] = 644;
+ getProperties()["filename"] = "no_name";
+ getProperties()["maxlinelength"] = 46;
+}
+
+
+const std::vector <string> uuEncoder::getAvailableProperties() const {
+
+ std::vector <string> list(encoder::getAvailableProperties());
+
+ list.push_back("maxlinelength");
+
+ list.push_back("mode");
+ list.push_back("filename");
+
+ return list;
+}
+
+
+// This is the character encoding function to make a character printable
+static inline byte_t UUENCODE(const unsigned int c) {
+
+ return static_cast <byte_t>((c & 077) + ' ');
+}
+
+// Single character decoding
+static inline unsigned int UUDECODE(const unsigned int c) {
+
+ return (c - ' ') & 077;
+}
+
+
+size_t uuEncoder::encode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress
+) {
+
+ in.reset(); // may not work...
+
+ const string propFilename = getProperties().getProperty <string>("filename", "");
+ const string propMode = getProperties().getProperty <string>("mode", "644");
+
+ const size_t maxLineLength =
+ std::min(getProperties().getProperty <size_t>("maxlinelength", 46), static_cast <size_t>(46));
+
+ size_t total = 0;
+ size_t inTotal = 0;
+
+ // Output the prelude text ("begin [mode] [filename]")
+ out << "begin";
+
+ if (!propFilename.empty()) {
+ out << " " << propMode << " " << propFilename;
+ total += 2 + propMode.length() + propFilename.length();
+ }
+
+ out << "\r\n";
+ total += 7;
+
+ // Process the data
+ byte_t inBuffer[64];
+ byte_t outBuffer[64];
+
+ if (progress) {
+ progress->start(0);
+ }
+
+ while (!in.eof()) {
+
+ // Process up to 45 characters per line
+ std::fill(inBuffer, inBuffer + sizeof(inBuffer), 0);
+
+ const size_t inLength = in.read(inBuffer, maxLineLength - 1);
+
+ outBuffer[0] = UUENCODE(static_cast <unsigned int>(inLength)); // Line length
+
+ size_t j = 1;
+
+ for (size_t i = 0 ; i < inLength ; i += 3, j += 4) {
+
+ const byte_t c1 = inBuffer[i];
+ const byte_t c2 = inBuffer[i + 1];
+ const byte_t c3 = inBuffer[i + 2];
+
+ outBuffer[j] = UUENCODE(c1 >> 2);
+ outBuffer[j + 1] = UUENCODE(((c1 << 4) & 060) | ((c2 >> 4) & 017));
+ outBuffer[j + 2] = UUENCODE(((c2 << 2) & 074) | ((c3 >> 6) & 03));
+ outBuffer[j + 3] = UUENCODE(c3 & 077);
+ }
+
+ outBuffer[j] = '\r';
+ outBuffer[j + 1] = '\n';
+
+ out.write(outBuffer, j + 2);
+
+ total += j + 2;
+ inTotal += inLength;
+
+ if (progress) {
+ progress->progress(inTotal, inTotal);
+ }
+ }
+
+ out << "end\r\n";
+ total += 5;
+
+ if (progress) {
+ progress->stop(inTotal);
+ }
+
+ return total;
+}
+
+
+size_t uuEncoder::decode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress
+) {
+
+ in.reset(); // may not work...
+
+ // Process the data
+ byte_t inBuffer[64];
+ byte_t outBuffer[64];
+
+ size_t total = 0;
+ size_t inTotal = 0;
+
+ bool stop = false;
+
+ std::fill(inBuffer, inBuffer + sizeof(inBuffer), 0);
+
+ if (progress) {
+ progress->start(0);
+ }
+
+ while (!stop && !in.eof()) {
+
+ // Get the line length
+ byte_t lengthChar;
+
+ if (in.read(&lengthChar, 1) == 0) {
+ break;
+ }
+
+ const size_t outLength = UUDECODE(lengthChar);
+ const size_t inLength = std::min((outLength * 4) / 3, static_cast <size_t>(64));
+ size_t inPos = 0;
+
+ switch (lengthChar) {
+
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n': {
+
+ // Ignore
+ continue;
+ }
+ case 'b': {
+
+ // Read 5 characters more to check for begin ("begin ...\r\n" or "begin ...\n")
+ inPos = in.read(inBuffer, 5);
+
+ if (inPos == 5 &&
+ inBuffer[0] == 'e' &&
+ inBuffer[1] == 'g' &&
+ inBuffer[2] == 'i' &&
+ inBuffer[3] == 'n' &&
+ parserHelpers::isSpace(inBuffer[4])) {
+
+ inTotal += 5;
+
+ byte_t c = 0;
+
+ size_t count = 0;
+ byte_t buffer[512];
+
+ while (count < sizeof(buffer) - 1 && in.read(&c, 1) == 1) {
+
+ if (c == '\n') {
+ break;
+ }
+
+ buffer[count++] = c;
+ }
+
+ inTotal += count;
+
+ if (c != '\n') {
+
+ // OOPS! Weird line. Don't try to decode more...
+
+ if (progress) {
+ progress->stop(inTotal);
+ }
+
+ return total;
+ }
+
+ // Parse filename and mode
+ if (count > 0) {
+
+ buffer[count] = '\0';
+
+ byte_t* p = buffer;
+
+ while (*p && parserHelpers::isSpace(*p)) ++p;
+
+ byte_t* modeStart = buffer;
+
+ while (*p && !parserHelpers::isSpace(*p)) ++p;
+
+ getResults()["mode"] = string(modeStart, p);
+
+ while (*p && parserHelpers::isSpace(*p)) ++p;
+
+ byte_t* filenameStart = buffer;
+
+ while (*p && !(*p == '\r' || *p == '\n')) ++p;
+
+ getResults()["filename"] = string(filenameStart, p);
+
+ // No filename or mode specified
+ } else {
+
+ getResults()["filename"] = "untitled";
+ getResults()["mode"] = 644;
+ }
+
+ continue;
+ }
+
+ break;
+ }
+ case 'e': {
+
+ // Read 3 characters more to check for end ("end\r\n" or "end\n")
+ inPos = in.read(inBuffer, 3);
+
+ if (inPos == 3 &&
+ inBuffer[0] == 'n' &&
+ inBuffer[1] == 'd' &&
+ (inBuffer[2] == '\r' || inBuffer[2] == '\n')) {
+
+ stop = true;
+ inTotal += 3;
+ continue;
+ }
+
+ break;
+ }
+
+ }
+
+ // Read encoded data
+ if (in.read(inBuffer + inPos, inLength - inPos) != inLength - inPos) {
+ // Premature end of data
+ break;
+ }
+
+ inTotal += (inLength - inPos);
+
+ // Decode data
+ for (size_t i = 0, j = 0 ; i < inLength ; i += 4, j += 3) {
+
+ const byte_t c1 = inBuffer[i];
+ const byte_t c2 = inBuffer[i + 1];
+ const byte_t c3 = inBuffer[i + 2];
+ const byte_t c4 = inBuffer[i + 3];
+
+ const size_t n = std::min(inLength - i, static_cast <size_t>(3));
+
+ if (n >= 3) {
+ outBuffer[j + 2] = static_cast <byte_t>(UUDECODE(c3) << 6 | UUDECODE(c4));
+ }
+ if (n >= 2) {
+ outBuffer[j + 1] = static_cast <byte_t>(UUDECODE(c2) << 4 | UUDECODE(c3) >> 2);
+ }
+ if (n >= 1) {
+ outBuffer[j] = static_cast <byte_t>(UUDECODE(c1) << 2 | UUDECODE(c2) >> 4);
+ }
+
+ total += n;
+ }
+
+ out.write(outBuffer, outLength);
+
+ std::fill(inBuffer, inBuffer + sizeof(inBuffer), 0);
+
+ if (progress) {
+ progress->progress(inTotal, inTotal);
+ }
+ }
+
+ if (progress) {
+ progress->stop(inTotal);
+ }
+
+ return total;
+}
+
+
+size_t uuEncoder::getEncodedSize(const size_t n) const {
+
+ // 3 bytes of input provide 4 bytes of output.
+ // Count CRLF (2 bytes) for each line of 45 characters.
+ // Also reserve some space for header and footer.
+ return 200 + n * 3 + (n / 45) * 2;
+}
+
+
+size_t uuEncoder::getDecodedSize(const size_t n) const {
+
+ // 4 bytes of input provide 3 bytes of output
+ return (n * 3) / 4;
+}
+
+
+} // encoder
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/encoder/uuEncoder.hpp b/vmime-master/src/vmime/utility/encoder/uuEncoder.hpp
new file mode 100644
index 0000000..841cf66
--- /dev/null
+++ b/vmime-master/src/vmime/utility/encoder/uuEncoder.hpp
@@ -0,0 +1,68 @@
+//
+// 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_UTILITY_ENCODER_UUENCODER_HPP_INCLUDED
+#define VMIME_UTILITY_ENCODER_UUENCODER_HPP_INCLUDED
+
+
+#include "vmime/utility/encoder/encoder.hpp"
+
+
+namespace vmime {
+namespace utility {
+namespace encoder {
+
+
+/** UUEncode encoder.
+ */
+class VMIME_EXPORT uuEncoder : public encoder {
+
+public:
+
+ uuEncoder();
+
+ size_t encode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress = NULL
+ );
+
+ size_t decode(
+ utility::inputStream& in,
+ utility::outputStream& out,
+ utility::progressListener* progress = NULL
+ );
+
+ const std::vector <string> getAvailableProperties() const;
+
+ size_t getEncodedSize(const size_t n) const;
+ size_t getDecodedSize(const size_t n) const;
+};
+
+
+} // encoder
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_ENCODER_UUENCODER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/file.hpp b/vmime-master/src/vmime/utility/file.hpp
new file mode 100644
index 0000000..6e0605e
--- /dev/null
+++ b/vmime-master/src/vmime/utility/file.hpp
@@ -0,0 +1,264 @@
+//
+// 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_UTILITY_FILE_HPP_INCLUDED
+#define VMIME_UTILITY_FILE_HPP_INCLUDED
+
+
+#include "vmime/config.hpp"
+
+#include "vmime/utility/path.hpp"
+#include "vmime/utility/stream.hpp"
+
+
+#if VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+namespace vmime {
+namespace utility {
+
+
+class file;
+
+
+/** File list iterator (see file::getFiles).
+ */
+class VMIME_EXPORT fileIterator : public object {
+
+public:
+
+ virtual ~fileIterator() { }
+
+ /** Check whether the cursor has reach the end of the list.
+ *
+ * @return true if you can call nextElement(), or false
+ * if no more file is available
+ */
+ virtual bool hasMoreElements() const = 0;
+
+ /** Return the next file in the list.
+ *
+ * @return next file or NULL
+ */
+ virtual shared_ptr <file> nextElement() = 0;
+};
+
+
+/** Write to a file.
+ */
+class VMIME_EXPORT fileWriter : public object {
+
+public:
+
+ virtual ~fileWriter() { }
+
+ virtual shared_ptr <utility::outputStream> getOutputStream() = 0;
+};
+
+
+/** Read from a file.
+ */
+class VMIME_EXPORT fileReader : public object {
+
+public:
+
+ virtual ~fileReader() { }
+
+ virtual shared_ptr <utility::inputStream> getInputStream() = 0;
+};
+
+
+/** Abstract representation of a file or directory.
+ */
+class VMIME_EXPORT file : public object {
+
+public:
+
+ typedef utility::path path;
+ typedef unsigned long length_type;
+
+
+ virtual ~file() { }
+
+
+ /** Create the file pointed by this file object.
+ *
+ * @throw exceptions::filesystem_exception if an error occurs
+ */
+ virtual void createFile() = 0;
+
+ /** Create the directory pointed by this file object.
+ *
+ * @param createAll if set to true, recursively create all
+ * parent directories if they do not exist
+ * @throw exceptions::filesystem_exception if an error occurs
+ */
+ virtual void createDirectory(const bool createAll = false) = 0;
+
+ /** Test whether this is a file.
+ *
+ * @return true if this is a file, false otherwise
+ */
+ virtual bool isFile() const = 0;
+
+ /** Test whether this is a directory.
+ *
+ * @return true if this is a directory, false otherwise
+ */
+ virtual bool isDirectory() const = 0;
+
+ /** Test whether this file is readible.
+ *
+ * @return true if we can read this file, false otherwise
+ */
+ virtual bool canRead() const = 0;
+
+ /** Test whether this file is writeable.
+ *
+ * @return true if we can write to this file, false otherwise
+ */
+ virtual bool canWrite() const = 0;
+
+ /** Return the length of this file.
+ *
+ * @return file size (in bytes)
+ */
+ virtual length_type getLength() = 0;
+
+ /** Return the full path of this file/directory.
+ *
+ * @return full path of the file
+ */
+ virtual const path& getFullPath() const = 0;
+
+ /** Test whether this file/directory exists.
+ *
+ * @return true if the file exists, false otherwise
+ */
+ virtual bool exists() const = 0;
+
+ /** Return the parent directory of this file/directory.
+ *
+ * @return parent directory (or NULL if root)
+ */
+ virtual shared_ptr <file> getParent() const = 0;
+
+ /** Rename the file/directory.
+ *
+ * @param newName full path of the new file
+ * @throw exceptions::filesystem_exception if an error occurs
+ */
+ virtual void rename(const path& newName) = 0;
+
+ /** Deletes this file/directory.
+ * If this is a directory, it must be empty.
+ *
+ * @throw exceptions::filesystem_exception if an error occurs
+ */
+ virtual void remove() = 0;
+
+ /** Return an object capable of writing to this file.
+ *
+ * @return file writer object
+ */
+ virtual shared_ptr <fileWriter> getFileWriter() = 0;
+
+ /** Return an object capable of reading from this file.
+ *
+ * @return file reader object
+ */
+ virtual shared_ptr <fileReader> getFileReader() = 0;
+
+ /** Enumerate files contained in this directory.
+ *
+ * @return file iterator to enumerate files
+ * @throw exceptions::not_a_directory if this is not a directory,
+ * exceptions::filesystem_exception if another error occurs
+ */
+ virtual shared_ptr <fileIterator> getFiles() const = 0;
+
+protected:
+
+ file() { }
+
+private:
+
+ file(const file&) : object() { }
+};
+
+
+/** Constructs 'file' objects.
+ */
+class VMIME_EXPORT fileSystemFactory : public object {
+
+public:
+
+ virtual ~fileSystemFactory() { }
+
+ /** Create a new file object from the specified path.
+ *
+ * @param path full path (absolute) of the file
+ * @return new file object for the path
+ */
+ virtual shared_ptr <file> create(const file::path& path) const = 0;
+
+ /** Parse a path contained in a string.
+ *
+ * @param str string containing a path in a system-dependent representation
+ * @return path object (abstract representation)
+ */
+ virtual const file::path stringToPath(const string& str) const = 0;
+
+ /** Return the system-dependent string representation for the specified path.
+ *
+ * @param path abstract representation of the path
+ * @return string representation of the path
+ */
+ virtual const string pathToString(const file::path& path) const = 0;
+
+ /** Test whether the specified path component is syntactically
+ * valid (ie: does not contain any 'special' character).
+ *
+ * @param comp path component to test
+ * @return true if the component is valid, false otherwise
+ */
+ virtual bool isValidPathComponent(const file::path::component& comp) const = 0;
+
+ /** Test whether the specified path is syntactically valid
+ * (ie: components do not contain any 'special' character).
+ *
+ * @param path path to test
+ * @return true if the path is valid, false otherwise
+ */
+ virtual bool isValidPath(const file::path& path) const = 0;
+};
+
+
+} // utility
+} // vmime
+
+
+#endif // VMIME_HAVE_FILESYSTEM_FEATURES
+
+
+#endif // VMIME_UTILITY_FILE_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/filteredStream.cpp b/vmime-master/src/vmime/utility/filteredStream.cpp
new file mode 100644
index 0000000..d5ec17b
--- /dev/null
+++ b/vmime-master/src/vmime/utility/filteredStream.cpp
@@ -0,0 +1,402 @@
+//
+// 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.
+//
+
+#include "vmime/utility/filteredStream.hpp"
+
+#include <algorithm>
+
+
+namespace vmime {
+namespace utility {
+
+
+// filteredInputStream
+
+size_t filteredInputStream::getBlockSize() {
+
+ return std::min(inputStream::getBlockSize(), getPreviousInputStream().getBlockSize());
+}
+
+
+// filteredOutputStream
+
+size_t filteredOutputStream::getBlockSize() {
+
+ return std::min(outputStream::getBlockSize(), getNextOutputStream().getBlockSize());
+}
+
+
+// dotFilteredInputStream
+
+dotFilteredInputStream::dotFilteredInputStream(inputStream& is)
+ : m_stream(is),
+ m_previousChar2('\0'),
+ m_previousChar1('\0') {
+
+}
+
+
+inputStream& dotFilteredInputStream::getPreviousInputStream() {
+
+ return m_stream;
+}
+
+
+bool dotFilteredInputStream::eof() const {
+
+ return m_stream.eof();
+}
+
+
+void dotFilteredInputStream::reset() {
+
+ m_previousChar2 = '\0';
+ m_previousChar1 = '\0';
+
+ m_stream.reset();
+}
+
+
+size_t dotFilteredInputStream::read(byte_t* const data, const size_t count) {
+
+ const size_t read = m_stream.read(data, count);
+
+ const byte_t* readPtr = data;
+ byte_t* writePtr = data;
+
+ const byte_t* end = data + read;
+
+ size_t written = 0;
+
+ byte_t prevChar2 = m_previousChar2;
+ byte_t prevChar1 = m_previousChar1;
+
+ // Replace "\n.." with "\n."
+ while (readPtr < end) {
+
+ if (*readPtr == '.' && prevChar2 == '\n' && prevChar1 == '.') {
+
+ // Ignore last dot
+ prevChar2 = '\0';
+ prevChar1 = '.';
+
+ } else {
+
+ *writePtr = *readPtr;
+
+ ++writePtr;
+ ++written;
+
+ prevChar2 = prevChar1;
+ prevChar1 = *readPtr;
+ }
+
+ ++readPtr;
+ }
+
+ m_previousChar2 = prevChar2;
+ m_previousChar1 = prevChar1;
+
+ return written;
+}
+
+
+size_t dotFilteredInputStream::skip(const size_t /* count */) {
+
+ // Skipping bytes is not supported
+ return 0;
+}
+
+
+// dotFilteredOutputStream
+
+dotFilteredOutputStream::dotFilteredOutputStream(outputStream& os)
+ : m_stream(os),
+ m_previousChar('\0'),
+ m_start(true) {
+
+}
+
+
+outputStream& dotFilteredOutputStream::getNextOutputStream() {
+
+ return m_stream;
+}
+
+
+void dotFilteredOutputStream::writeImpl(const byte_t* const data, const size_t count) {
+
+ if (count == 0) {
+ return;
+ }
+
+ const byte_t* pos = data;
+ const byte_t* end = data + count;
+ const byte_t* start = data;
+
+ if (m_previousChar == '.') {
+
+ if (data[0] == '\n' || data[0] == '\r') {
+
+ m_stream.write(".", 1); // extra <DOT>
+ m_stream.write(data, 1);
+
+ pos = data + 1;
+ }
+ }
+
+ // Replace "\n." with "\n.."
+ while ((pos = std::find(pos, end, '.')) != end) {
+
+ const byte_t previousChar = (pos == data ? m_previousChar : *(pos - 1));
+
+ if (previousChar == '\n') {
+
+ m_stream.write(start, pos - start);
+ m_stream.write("..", 2);
+
+ start = pos + 1;
+
+ } else if (pos == data && m_start) { // <DOT><CR><LF> at the beginning of content
+
+ m_stream.write(start, pos - start);
+
+ if (pos + 1 < end && (*(pos + 1) == '\n' || *(pos + 1) == '\r')) {
+ m_stream.write("..", 2);
+ } else {
+ m_stream.write(".", 1);
+ }
+
+ start = pos + 1;
+ }
+
+ ++pos;
+ }
+
+ m_stream.write(start, end - start);
+ m_previousChar = data[count - 1];
+ m_start = false;
+}
+
+
+void dotFilteredOutputStream::flush() {
+
+ // Do nothing
+ m_stream.flush();
+}
+
+
+size_t dotFilteredOutputStream::getBlockSize() {
+
+ return m_stream.getBlockSize();
+}
+
+
+// CRLFToLFFilteredOutputStream
+
+CRLFToLFFilteredOutputStream::CRLFToLFFilteredOutputStream(outputStream& os)
+ : m_stream(os),
+ m_previousChar('\0') {
+
+}
+
+
+outputStream& CRLFToLFFilteredOutputStream::getNextOutputStream() {
+
+ return m_stream;
+}
+
+
+void CRLFToLFFilteredOutputStream::writeImpl(const byte_t* const data, const size_t count) {
+
+ if (count == 0) {
+ return;
+ }
+
+ const byte_t* pos = data;
+ const byte_t* end = data + count;
+ const byte_t* start = data;
+
+ // Warning: if the whole buffer finishes with '\r', this
+ // last character will not be written back if flush() is
+ // not called
+ if (m_previousChar == '\r') {
+
+ if (*pos != '\n') {
+ m_stream.write("\r", 1); // write back \r
+ m_previousChar = *pos;
+ }
+ }
+
+ // Replace "\r\n" (CRLF) with "\n" (LF)
+ while ((pos = std::find(pos, end, '\n')) != end) {
+
+ const byte_t previousChar = (pos == data ? m_previousChar : *(pos - 1));
+
+ if (previousChar == '\r') {
+
+ if (pos != start) {
+ m_stream.write(start, pos - 1 - start); // do not write \r
+ }
+
+ m_stream.write("\n", 1);
+
+ start = pos + 1;
+ }
+
+ ++pos;
+ }
+
+ if (data[count - 1] == '\r') {
+
+ m_stream.write(start, end - start - 1);
+ m_previousChar = '\r';
+
+ } else {
+
+ m_stream.write(start, end - start);
+ m_previousChar = data[count - 1];
+ }
+}
+
+
+void CRLFToLFFilteredOutputStream::flush() {
+
+ m_stream.flush();
+
+ // TODO
+}
+
+
+size_t CRLFToLFFilteredOutputStream::getBlockSize() {
+
+ return m_stream.getBlockSize();
+}
+
+
+// LFToCRLFFilteredOutputStream
+
+LFToCRLFFilteredOutputStream::LFToCRLFFilteredOutputStream(outputStream& os)
+ : m_stream(os),
+ m_previousChar('\0') {
+
+}
+
+
+outputStream& LFToCRLFFilteredOutputStream::getNextOutputStream() {
+
+ return m_stream;
+}
+
+
+void LFToCRLFFilteredOutputStream::writeImpl(const byte_t* const data, const size_t count)
+{
+ if (count == 0) {
+ return;
+ }
+
+ string buffer;
+ buffer.reserve(count);
+
+ const byte_t* pos = data;
+ const byte_t* end = data + count;
+
+ byte_t previousChar = m_previousChar;
+
+ while (pos < end) {
+
+ switch (*pos) {
+
+ case '\r':
+
+ buffer.append(1, '\r');
+ buffer.append(1, '\n');
+
+ break;
+
+ case '\n':
+
+ if (previousChar != '\r') {
+ buffer.append(1, '\r');
+ buffer.append(1, '\n');
+ }
+
+ break;
+
+ default:
+
+ buffer.append(1, *pos);
+ break;
+ }
+
+ previousChar = *pos;
+ ++pos;
+ }
+
+ m_stream.write(&buffer[0], buffer.length());
+
+ m_previousChar = previousChar;
+}
+
+
+void LFToCRLFFilteredOutputStream::flush() {
+
+ m_stream.flush();
+}
+
+
+size_t LFToCRLFFilteredOutputStream::getBlockSize() {
+
+ return m_stream.getBlockSize();
+}
+
+
+// stopSequenceFilteredInputStream <1>
+
+template <>
+size_t stopSequenceFilteredInputStream <1>::read(byte_t* const data, const size_t count) {
+
+ if (eof() || m_stream.eof()) {
+ m_eof = true;
+ return 0;
+ }
+
+ const size_t read = m_stream.read(data, count);
+ byte_t* end = data + read;
+
+ byte_t* pos = std::find(data, end, m_sequence[0]);
+
+ if (pos == end) {
+
+ return read;
+
+ } else {
+
+ m_found = 1;
+ return pos - data;
+ }
+}
+
+
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/filteredStream.hpp b/vmime-master/src/vmime/utility/filteredStream.hpp
new file mode 100644
index 0000000..2414c54
--- /dev/null
+++ b/vmime-master/src/vmime/utility/filteredStream.hpp
@@ -0,0 +1,405 @@
+//
+// 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_UTILITY_FILTEREDSTREAM_HPP_INCLUDED
+#define VMIME_UTILITY_FILTEREDSTREAM_HPP_INCLUDED
+
+
+#include <algorithm>
+
+#include "vmime/utility/inputStream.hpp"
+#include "vmime/utility/outputStream.hpp"
+
+
+namespace vmime {
+namespace utility {
+
+
+/** A stream whose input is filtered.
+ */
+class VMIME_EXPORT filteredInputStream : public inputStream {
+public:
+
+ virtual size_t getBlockSize();
+
+ /** Return a reference to the stream being filtered.
+ *
+ * @return stream being filtered
+ */
+ virtual inputStream& getPreviousInputStream() = 0;
+};
+
+
+/** A stream whose output is filtered.
+ */
+class VMIME_EXPORT filteredOutputStream : public outputStream {
+
+public:
+
+ virtual size_t getBlockSize();
+
+ /** Return a reference to the stream being filtered.
+ *
+ * @return destination stream for filtered data
+ */
+ virtual outputStream& getNextOutputStream() = 0;
+};
+
+
+/** A filtered input stream which replaces "\n.."
+ * sequences with "\n." sequences.
+ */
+class VMIME_EXPORT dotFilteredInputStream : public filteredInputStream {
+
+public:
+
+ /** Construct a new filter for the specified input stream.
+ *
+ * @param is stream from which to read data to be filtered
+ */
+ dotFilteredInputStream(inputStream& is);
+
+ inputStream& getPreviousInputStream();
+
+ bool eof() const;
+
+ void reset();
+
+ size_t read(byte_t* const data, const size_t count);
+
+ size_t skip(const size_t count);
+
+private:
+
+ inputStream& m_stream;
+
+ byte_t m_previousChar2; // (N - 1)th character of previous buffer
+ byte_t m_previousChar1; // (N)th (last) character of previous buffer
+};
+
+
+/** A filtered output stream which replaces "\n."
+ * sequences with "\n.." sequences.
+ */
+class VMIME_EXPORT dotFilteredOutputStream : public filteredOutputStream {
+
+public:
+
+ /** Construct a new filter for the specified output stream.
+ *
+ * @param os stream into which write filtered data
+ */
+ dotFilteredOutputStream(outputStream& os);
+
+ outputStream& getNextOutputStream();
+
+ void flush();
+
+ size_t getBlockSize();
+
+protected:
+
+ void writeImpl(const byte_t* const data, const size_t count);
+
+private:
+
+ outputStream& m_stream;
+ byte_t m_previousChar;
+ bool m_start;
+};
+
+
+/** A filtered output stream which replaces CRLF sequences
+ * with single LF characters.
+ */
+class VMIME_EXPORT CRLFToLFFilteredOutputStream : public filteredOutputStream {
+
+public:
+
+ /** Construct a new filter for the specified output stream.
+ *
+ * @param os stream into which write filtered data
+ */
+ CRLFToLFFilteredOutputStream(outputStream& os);
+
+ outputStream& getNextOutputStream();
+
+ void flush();
+
+ size_t getBlockSize();
+
+protected:
+
+ void writeImpl(const byte_t* const data, const size_t count);
+
+private:
+
+ outputStream& m_stream;
+ byte_t m_previousChar;
+};
+
+
+/** A filtered output stream which replaces CR or LF characters
+ * with CRLF sequences.
+ */
+class VMIME_EXPORT LFToCRLFFilteredOutputStream : public filteredOutputStream {
+
+public:
+
+ /** Construct a new filter for the specified output stream.
+ *
+ * @param os stream into which write filtered data
+ */
+ LFToCRLFFilteredOutputStream(outputStream& os);
+
+ outputStream& getNextOutputStream();
+
+ void flush();
+
+ size_t getBlockSize();
+
+protected:
+
+ void writeImpl(const byte_t* const data, const size_t count);
+
+private:
+
+ outputStream& m_stream;
+ byte_t m_previousChar;
+};
+
+
+/** A filtered input stream which stops when a specified sequence
+ * is found (eof() method will return 'true').
+ */
+template <int COUNT>
+class VMIME_EXPORT stopSequenceFilteredInputStream : public filteredInputStream {
+
+public:
+
+ /** Construct a new filter for the specified input stream.
+ *
+ * @param is stream from which to read data to be filtered
+ * @param sequence sequence on which to stop
+ */
+ stopSequenceFilteredInputStream(inputStream& is, const byte_t* sequence)
+ : m_stream(is),
+ m_sequence(sequence),
+ m_found(0),
+ m_eof(false) {
+
+ }
+
+ /** Construct a new filter for the specified input stream.
+ *
+ * @param is stream from which to read data to be filtered
+ * @param sequence sequence on which to stop
+ */
+ stopSequenceFilteredInputStream(inputStream& is, const char* sequence)
+ : m_stream(is),
+ m_sequence(reinterpret_cast <const byte_t*>(sequence)),
+ m_found(0),
+ m_eof(false) {
+
+ }
+
+ inputStream& getPreviousInputStream() {
+
+ return m_stream;
+ }
+
+ bool eof() const {
+
+ return m_found == COUNT || m_eof;
+ }
+
+ void reset() {
+
+ m_found = 0;
+ m_stream.reset();
+ }
+
+ size_t read(byte_t* const data, const size_t count) {
+
+ // Read buffer must be at least 'COUNT' size + 1 byte
+ if (eof() || count <= COUNT) {
+ return 0;
+ }
+
+ if (m_stream.eof()) {
+
+ if (m_found != 0) {
+
+ const size_t found = m_found;
+
+ for (size_t f = 0 ; f < found ; ++f) {
+ data[f] = m_sequence[f];
+ }
+
+ m_found = 0;
+ m_eof = true;
+
+ return found;
+
+ } else {
+
+ m_eof = true;
+ return 0;
+ }
+ }
+
+ size_t read = m_stream.read(data, count - COUNT);
+
+ byte_t* end = data + read;
+ byte_t* pos = data;
+
+ while (pos < end) {
+
+ // Very simple case, search for the whole sequence
+ if (m_found == 0) {
+
+ while (pos < end) {
+
+ pos = std::find(pos, end, m_sequence[0]);
+
+ if (pos == end) {
+ return read;
+ }
+
+ m_found = 1;
+ ++pos;
+
+ while (pos < end && m_found < COUNT && m_sequence[m_found] == *pos) {
+ ++m_found;
+ ++pos;
+ }
+
+ // Didn't found whole sequence
+ if (m_found != COUNT) {
+
+ // We reached the end of the buffer
+ if (pos == end) {
+
+ return read - m_found;
+
+ // Common prefix but not whole sequence
+ } else {
+
+ m_found = 0;
+ }
+
+ // Whole sequence found
+ } else {
+
+ // End of stream
+ return pos - data - m_found;
+ }
+ }
+
+ // More complex case: search for a sequence which has begun
+ // in a previous buffer
+ } else {
+
+ // Search for the end of the previously started sequence
+ while (pos < end && m_found < COUNT && m_sequence[m_found] == *pos) {
+ ++m_found;
+ ++pos;
+ }
+
+ if (m_found != COUNT) {
+
+ // End of buffer
+ if (pos == end) {
+
+ // No data: this buffer is a sub-sequence of the
+ // searched sequence
+ return 0;
+
+ // Common prefix
+ } else {
+
+ // We have to reinject the incomplete sequence into
+ // the stream data
+
+ // -- shift right data
+ const size_t n = pos - data;
+
+ byte_t* newEnd = data + read + m_found - n;
+ byte_t* oldEnd = data + read;
+
+ for (size_t i = 0 ; i < read - n ; ++i) {
+
+ --newEnd;
+ --oldEnd;
+
+ *newEnd = *oldEnd;
+ }
+
+ // -- copy the prefix just before data
+ for (size_t f = 0 ; f < m_found ; ++f) {
+ data[f] = m_sequence[f];
+ }
+
+ read += m_found - n;
+ end += m_found - n;
+
+ m_found = 0;
+ }
+
+ } else {
+
+ return 0; // no more data
+ }
+ }
+ }
+
+ return read;
+ }
+
+ size_t skip(const size_t /* count */) {
+
+ // Not supported
+ return 0;
+ }
+
+private:
+
+ inputStream& m_stream;
+
+ const byte_t* m_sequence;
+ size_t m_found;
+
+ bool m_eof;
+};
+
+
+template <>
+size_t stopSequenceFilteredInputStream <1>::read(byte_t* const data, const size_t count);
+
+
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_FILTEREDSTREAM_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/utility/inputStream.cpp b/vmime-master/src/vmime/utility/inputStream.cpp
new file mode 100644
index 0000000..916d8ba
--- /dev/null
+++ b/vmime-master/src/vmime/utility/inputStream.cpp
@@ -0,0 +1,33 @@
+//
+// 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.
+//
+
+#include "vmime/utility/inputStream.hpp"
+
+
+namespace vmime {
+namespace utility {
+
+
+} // utility
+} // vmime
+
diff --git a/vmime-master/src/vmime/utility/inputStream.hpp b/vmime-master/src/vmime/utility/inputStream.hpp
new file mode 100644
index 0000000..0e1c2df
--- /dev/null
+++ b/vmime-master/src/vmime/utility/inputStream.hpp
@@ -0,0 +1,75 @@
+//
+// 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_UTILITY_INPUTSTREAM_HPP_INCLUDED
+#define VMIME_UTILITY_INPUTSTREAM_HPP_INCLUDED
+
+
+#include "vmime/utility/stream.hpp"
+
+
+namespace vmime {
+namespace utility {
+
+
+/** Simple input stream.
+ */
+class VMIME_EXPORT inputStream : public stream {
+
+public:
+
+ /** Test for end of stream (no more data to read).
+ *
+ * @return true if we have reached the end of stream, false otherwise
+ */
+ virtual bool eof() const = 0;
+
+ /** Set the read pointer to the beginning of the stream.
+ *
+ * @warning WARNING: this may not work for all stream types.
+ */
+ virtual void reset() = 0;
+
+ /** Read data from the stream.
+ *
+ * @param data will receive the data read
+ * @param count maximum number of bytes to read
+ * @return number of bytes read
+ */
+ virtual size_t read(byte_t* const data, const size_t count) = 0;
+
+ /** Skip a number of bytes.
+ *
+ * @param count maximum number of bytes to ignore
+ * @return number of bytes skipped
+ */
+ virtual size_t skip(const size_t count) = 0;
+};
+
+
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_INPUTSTREAM_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/utility/inputStreamAdapter.cpp b/vmime-master/src/vmime/utility/inputStreamAdapter.cpp
new file mode 100644
index 0000000..28be103
--- /dev/null
+++ b/vmime-master/src/vmime/utility/inputStreamAdapter.cpp
@@ -0,0 +1,84 @@
+//
+// 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.
+//
+
+#include "vmime/utility/inputStreamAdapter.hpp"
+
+
+namespace vmime {
+namespace utility {
+
+
+inputStreamAdapter::inputStreamAdapter(std::istream& is)
+ : m_stream(is) {
+
+}
+
+
+bool inputStreamAdapter::eof() const {
+
+ return m_stream.eof();
+}
+
+
+void inputStreamAdapter::reset() {
+
+ m_stream.exceptions(std::ios_base::badbit);
+ m_stream.seekg(0, std::ios::beg);
+ m_stream.clear();
+}
+
+
+size_t inputStreamAdapter::read(byte_t* const data, const size_t count) {
+
+ m_stream.exceptions(std::ios_base::badbit);
+ m_stream.read(reinterpret_cast <char*>(data), count);
+
+ return m_stream.gcount();
+}
+
+
+size_t inputStreamAdapter::skip(const size_t count) {
+
+ m_stream.exceptions(std::ios_base::badbit);
+ m_stream.ignore(count);
+
+ return m_stream.gcount();
+}
+
+
+size_t inputStreamAdapter::getPosition() const {
+
+ return m_stream.tellg();
+}
+
+
+void inputStreamAdapter::seek(const size_t pos) {
+
+ m_stream.clear();
+ m_stream.seekg(pos, std::ios_base::beg);
+}
+
+
+} // utility
+} // vmime
+
diff --git a/vmime-master/src/vmime/utility/inputStreamAdapter.hpp b/vmime-master/src/vmime/utility/inputStreamAdapter.hpp
new file mode 100644
index 0000000..340765c
--- /dev/null
+++ b/vmime-master/src/vmime/utility/inputStreamAdapter.hpp
@@ -0,0 +1,65 @@
+//
+// 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_UTILITY_INPUTSTREAMADAPTER_HPP_INCLUDED
+#define VMIME_UTILITY_INPUTSTREAMADAPTER_HPP_INCLUDED
+
+
+#include "vmime/utility/seekableInputStream.hpp"
+
+#include <istream>
+
+
+namespace vmime {
+namespace utility {
+
+
+/** An adapter class for C++ standard input streams.
+ */
+class VMIME_EXPORT inputStreamAdapter : public seekableInputStream {
+
+public:
+
+ /** @param is input stream to wrap
+ */
+ inputStreamAdapter(std::istream& is);
+
+ bool eof() const;
+ void reset();
+ size_t read(byte_t* const data, const size_t count);
+ size_t skip(const size_t count);
+ size_t getPosition() const;
+ void seek(const size_t pos);
+
+private:
+
+ std::istream& m_stream;
+};
+
+
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_INPUTSTREAMADAPTER_HPP_INCLUDED
+
diff --git a/vmime-master/src/vmime/utility/inputStreamByteBufferAdapter.cpp b/vmime-master/src/vmime/utility/inputStreamByteBufferAdapter.cpp
new file mode 100644
index 0000000..927215c
--- /dev/null
+++ b/vmime-master/src/vmime/utility/inputStreamByteBufferAdapter.cpp
@@ -0,0 +1,104 @@
+//
+// 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.
+//
+
+#include "vmime/utility/inputStreamByteBufferAdapter.hpp"
+
+
+namespace vmime {
+namespace utility {
+
+
+inputStreamByteBufferAdapter::inputStreamByteBufferAdapter(const byte_t* buffer, const size_t length)
+ : m_buffer(buffer),
+ m_length(length),
+ m_pos(0) {
+
+}
+
+
+bool inputStreamByteBufferAdapter::eof() const {
+
+ return m_pos >= m_length;
+}
+
+
+void inputStreamByteBufferAdapter::reset() {
+
+ m_pos = 0;
+}
+
+
+size_t inputStreamByteBufferAdapter::read(byte_t* const data, const size_t count) {
+
+ const size_t remaining = m_length - m_pos;
+
+ if (remaining < count) {
+
+ std::copy(m_buffer + m_pos, m_buffer + m_pos + remaining, data);
+ m_pos += remaining;
+
+ return remaining;
+
+ } else {
+
+ std::copy(m_buffer + m_pos, m_buffer + m_pos + count, data);
+ m_pos += count;
+
+ return count;
+ }
+}
+
+
+size_t inputStreamByteBufferAdapter::skip(const size_t count) {
+
+ const size_t remaining = m_length - m_pos;
+
+ if (remaining < count) {
+
+ m_pos += remaining;
+ return remaining;
+
+ } else {
+
+ m_pos += count;
+ return count;
+ }
+}
+
+
+size_t inputStreamByteBufferAdapter::getPosition() const {
+
+ return m_pos;
+}
+
+
+void inputStreamByteBufferAdapter::seek(const size_t pos) {
+
+ if (pos <= m_length) {
+ m_pos = pos;
+ }
+}
+
+
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/inputStreamByteBufferAdapter.hpp b/vmime-master/src/vmime/utility/inputStreamByteBufferAdapter.hpp
new file mode 100644
index 0000000..c9094c7
--- /dev/null
+++ b/vmime-master/src/vmime/utility/inputStreamByteBufferAdapter.hpp
@@ -0,0 +1,63 @@
+//
+// 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_UTILITY_INPUTSTREAMBYTEBUFFERADAPTER_HPP_INCLUDED
+#define VMIME_UTILITY_INPUTSTREAMBYTEBUFFERADAPTER_HPP_INCLUDED
+
+
+#include "vmime/utility/seekableInputStream.hpp"
+
+
+namespace vmime {
+namespace utility {
+
+
+/** An adapter class for reading from an array of bytes.
+ */
+class VMIME_EXPORT inputStreamByteBufferAdapter : public seekableInputStream {
+
+public:
+
+ inputStreamByteBufferAdapter(const byte_t* buffer, size_t length);
+
+ bool eof() const;
+ void reset();
+ size_t read(byte_t* const data, const size_t count);
+ size_t skip(const size_t count);
+ size_t getPosition() const;
+ void seek(const size_t pos);
+
+private:
+
+ const byte_t* m_buffer;
+ const size_t m_length;
+
+ size_t m_pos;
+};
+
+
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_INPUTSTREAMBYTEBUFFERADAPTER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/inputStreamPointerAdapter.cpp b/vmime-master/src/vmime/utility/inputStreamPointerAdapter.cpp
new file mode 100644
index 0000000..3f468d4
--- /dev/null
+++ b/vmime-master/src/vmime/utility/inputStreamPointerAdapter.cpp
@@ -0,0 +1,48 @@
+//
+// 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.
+//
+
+#include "vmime/utility/inputStreamPointerAdapter.hpp"
+
+
+namespace vmime {
+namespace utility {
+
+
+inputStreamPointerAdapter::inputStreamPointerAdapter(std::istream* is, const bool own)
+ : inputStreamAdapter(*is),
+ m_stream(is),
+ m_own(own) {
+
+}
+
+
+inputStreamPointerAdapter::~inputStreamPointerAdapter() {
+
+ if (m_own) {
+ delete m_stream;
+ }
+}
+
+
+} // utility
+} // vmime
diff --git a/vmime-master/src/vmime/utility/inputStreamPointerAdapter.hpp b/vmime-master/src/vmime/utility/inputStreamPointerAdapter.hpp
new file mode 100644
index 0000000..e48f9ce
--- /dev/null
+++ b/vmime-master/src/vmime/utility/inputStreamPointerAdapter.hpp
@@ -0,0 +1,61 @@
+//
+// 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_UTILITY_INPUTSTREAMPOINTERADAPTER_HPP_INCLUDED
+#define VMIME_UTILITY_INPUTSTREAMPOINTERADAPTER_HPP_INCLUDED
+
+
+#include "vmime/utility/inputStreamAdapter.hpp"
+
+#include <istream>
+
+
+namespace vmime {
+namespace utility {
+
+
+/** An adapter class for pointer to C++ standard input stream.
+ */
+class VMIME_EXPORT inputStreamPointerAdapter : public inputStreamAdapter {
+
+public:
+
+ /** @param is input stream to wrap
+ * @param own if set to 'true', the pointer will be deleted when
+ * this object is destroyed
+ */
+ inputStreamPointerAdapter(std::istream* is, const bool own = true);
+ ~inputStreamPointerAdapter();
+
+private:
+
+ std::istream* m_stream;
+ const bool m_own;
+};
+
+
+} // utility
+} // vmime
+
+
+#endif // VMIME_UTILITY_INPUTSTREAMPOINTERADAPTER_HPP_INCLUDED
diff --git a/vmime-master/src/vmime/utility/inputStreamSocketAdapter.cpp b/vmime-master/src/vmime/utility/inputStreamSocketAdapter.cpp
new file mode 100644
index 0000000..515906b
--- /dev/null
+++ b/vmime-master/src/vmime/utility/inputStreamSocketAdapter.cpp