From 152c6bed75598a6ca5efb7914701157270155833 Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Sun, 29 Dec 2013 10:02:12 +0100 Subject: Merged source and header files in directory structure. Got rid of SConstruct build. --- .gitignore | 11 +- CMakeLists.txt | 23 +- SConstruct | 1124 ---- cmake/Utils.cmake | 4 +- examples/README | 12 - src/address.cpp | 216 - src/addressList.cpp | 305 -- src/attachmentHelper.cpp | 312 -- src/base.cpp | 161 - src/body.cpp | 1050 ---- src/bodyPart.cpp | 190 - src/bodyPartAttachment.cpp | 146 - src/charset.cpp | 210 - src/charsetConverter.cpp | 45 - src/charsetConverterOptions.cpp | 37 - src/charsetConverter_iconv.cpp | 475 -- src/charsetConverter_icu.cpp | 408 -- src/charsetConverter_idna.cpp | 168 - src/component.cpp | 244 - src/constants.cpp | 237 - src/contentDisposition.cpp | 133 - src/contentDispositionField.cpp | 158 - src/contentHandler.cpp | 40 - src/contentTypeField.cpp | 113 - src/context.cpp | 87 - src/dateTime.cpp | 894 ---- src/defaultAttachment.cpp | 146 - src/disposition.cpp | 329 -- src/emailAddress.cpp | 539 -- src/emptyContentHandler.cpp | 117 - src/encoding.cpp | 300 -- src/exception.cpp | 748 --- src/fileAttachment.cpp | 223 - src/fileContentHandler.cpp | 81 - src/generatedMessageAttachment.cpp | 107 - src/generationContext.cpp | 109 - src/header.cpp | 388 -- src/headerField.cpp | 381 -- src/headerFieldFactory.cpp | 151 - src/headerFieldValue.cpp | 44 - src/htmlTextPart.cpp | 510 -- src/mailbox.cpp | 510 -- src/mailboxField.cpp | 90 - src/mailboxGroup.cpp | 377 -- src/mailboxList.cpp | 230 - src/mdn/MDNHelper.cpp | 353 -- src/mdn/MDNInfos.cpp | 38 - src/mdn/receivedMDNInfos.cpp | 136 - src/mdn/sendableMDNInfos.cpp | 71 - src/mediaType.cpp | 187 - src/message.cpp | 48 - src/messageBuilder.cpp | 329 -- src/messageId.cpp | 300 -- src/messageIdSequence.cpp | 252 - src/messageParser.cpp | 322 -- src/misc/importanceHelper.cpp | 162 - src/net/builtinServices.inl | 76 - src/net/defaultConnectionInfos.cpp | 60 - src/net/events.cpp | 166 - src/net/fetchAttributes.cpp | 95 - src/net/folder.cpp | 127 - src/net/imap/IMAPConnection.cpp | 814 --- src/net/imap/IMAPFolder.cpp | 1511 ------ src/net/imap/IMAPFolderStatus.cpp | 307 -- src/net/imap/IMAPMessage.cpp | 649 --- src/net/imap/IMAPMessagePart.cpp | 161 - src/net/imap/IMAPMessagePartContentHandler.cpp | 216 - src/net/imap/IMAPMessageStructure.cpp | 94 - src/net/imap/IMAPSStore.cpp | 79 - src/net/imap/IMAPServiceInfos.cpp | 137 - src/net/imap/IMAPStore.cpp | 267 - src/net/imap/IMAPTag.cpp | 122 - src/net/imap/IMAPUtils.cpp | 758 --- src/net/maildir/format/courierMaildirFormat.cpp | 542 -- src/net/maildir/format/kmailMaildirFormat.cpp | 320 -- src/net/maildir/maildirFolder.cpp | 1254 ----- src/net/maildir/maildirFolderStatus.cpp | 88 - src/net/maildir/maildirFormat.cpp | 109 - src/net/maildir/maildirMessage.cpp | 369 -- src/net/maildir/maildirMessagePart.cpp | 155 - src/net/maildir/maildirMessageStructure.cpp | 98 - src/net/maildir/maildirServiceInfos.cpp | 77 - src/net/maildir/maildirStore.cpp | 272 - src/net/maildir/maildirUtils.cpp | 273 - src/net/message.cpp | 150 - src/net/messageSet.cpp | 369 -- src/net/pop3/POP3Command.cpp | 230 - src/net/pop3/POP3Connection.cpp | 675 --- src/net/pop3/POP3Folder.cpp | 729 --- src/net/pop3/POP3FolderStatus.cpp | 88 - src/net/pop3/POP3Message.cpp | 250 - src/net/pop3/POP3Response.cpp | 428 -- src/net/pop3/POP3SStore.cpp | 79 - src/net/pop3/POP3ServiceInfos.cpp | 143 - src/net/pop3/POP3Store.cpp | 240 - src/net/pop3/POP3Utils.cpp | 114 - src/net/sendmail/sendmailServiceInfos.cpp | 78 - src/net/sendmail/sendmailTransport.cpp | 230 - src/net/service.cpp | 152 - src/net/serviceFactory.cpp | 145 - src/net/serviceInfos.cpp | 167 - src/net/serviceRegistration.inl | 98 - src/net/session.cpp | 158 - src/net/smtp/SMTPChunkingOutputStreamAdapter.cpp | 145 - src/net/smtp/SMTPCommand.cpp | 214 - src/net/smtp/SMTPCommandSet.cpp | 144 - src/net/smtp/SMTPConnection.cpp | 618 --- src/net/smtp/SMTPExceptions.cpp | 151 - src/net/smtp/SMTPResponse.cpp | 334 -- src/net/smtp/SMTPSTransport.cpp | 79 - src/net/smtp/SMTPServiceInfos.cpp | 146 - src/net/smtp/SMTPTransport.cpp | 420 -- src/net/tls/TLSProperties.cpp | 44 - src/net/tls/TLSSecuredConnectionInfos.cpp | 72 - src/net/tls/TLSSession.cpp | 48 - src/net/tls/TLSSocket.cpp | 44 - src/net/tls/gnutls/TLSProperties_GnuTLS.cpp | 113 - src/net/tls/gnutls/TLSSession_GnuTLS.cpp | 300 -- src/net/tls/gnutls/TLSSocket_GnuTLS.cpp | 490 -- src/net/tls/openssl/OpenSSLInitializer.cpp | 142 - src/net/tls/openssl/TLSProperties_OpenSSL.cpp | 112 - src/net/tls/openssl/TLSSession_OpenSSL.cpp | 135 - src/net/tls/openssl/TLSSocket_OpenSSL.cpp | 601 --- src/net/transport.cpp | 236 - src/object.cpp | 53 - src/parameter.cpp | 603 --- src/parameterizedHeaderField.cpp | 580 -- src/parsedMessageAttachment.cpp | 116 - src/parsingContext.cpp | 49 - src/path.cpp | 190 - src/plainTextPart.cpp | 112 - src/platform.cpp | 79 - src/platforms/posix/posixChildProcess.cpp | 404 -- src/platforms/posix/posixCriticalSection.cpp | 67 - src/platforms/posix/posixFile.cpp | 628 --- src/platforms/posix/posixHandler.cpp | 322 -- src/platforms/posix/posixSocket.cpp | 680 --- src/platforms/windows/windowsCriticalSection.cpp | 67 - src/platforms/windows/windowsFile.cpp | 553 -- src/platforms/windows/windowsHandler.cpp | 329 -- src/platforms/windows/windowsSocket.cpp | 484 -- src/propertySet.cpp | 382 -- src/relay.cpp | 354 -- src/security/cert/X509Certificate.cpp | 48 - src/security/cert/certificateChain.cpp | 53 - src/security/cert/defaultCertificateVerifier.cpp | 178 - .../cert/gnutls/X509Certificate_GnuTLS.cpp | 290 - .../cert/openssl/X509Certificate_OpenSSL.cpp | 574 -- src/security/defaultAuthenticator.cpp | 115 - src/security/digest/md5/md5MessageDigest.cpp | 347 -- src/security/digest/messageDigest.cpp | 57 - src/security/digest/messageDigestFactory.cpp | 84 - src/security/digest/sha1/sha1MessageDigest.cpp | 271 - src/security/sasl/SASLContext.cpp | 208 - src/security/sasl/SASLMechanismFactory.cpp | 144 - src/security/sasl/SASLSession.cpp | 192 - src/security/sasl/SASLSocket.cpp | 236 - src/security/sasl/builtinSASLMechanism.cpp | 195 - src/security/sasl/defaultSASLAuthenticator.cpp | 153 - src/streamContentHandler.cpp | 234 - src/stringContentHandler.cpp | 236 - src/text.cpp | 435 -- src/textPartFactory.cpp | 69 - src/utility/datetimeUtils.cpp | 333 -- src/utility/encoder/b64Encoder.cpp | 330 -- src/utility/encoder/binaryEncoder.cpp | 39 - src/utility/encoder/eightBitEncoder.cpp | 39 - src/utility/encoder/encoder.cpp | 76 - src/utility/encoder/encoderFactory.cpp | 120 - src/utility/encoder/noopEncoder.cpp | 87 - src/utility/encoder/qpEncoder.cpp | 558 -- src/utility/encoder/sevenBitEncoder.cpp | 39 - src/utility/encoder/uuEncoder.cpp | 344 -- src/utility/filteredStream.cpp | 391 -- src/utility/inputStream.cpp | 33 - src/utility/inputStreamAdapter.cpp | 83 - src/utility/inputStreamByteBufferAdapter.cpp | 103 - src/utility/inputStreamPointerAdapter.cpp | 46 - src/utility/inputStreamSocketAdapter.cpp | 82 - src/utility/inputStreamStringAdapter.cpp | 107 - src/utility/inputStreamStringProxyAdapter.cpp | 102 - src/utility/outputStream.cpp | 45 - src/utility/outputStreamAdapter.cpp | 54 - src/utility/outputStreamByteArrayAdapter.cpp | 52 - src/utility/outputStreamSocketAdapter.cpp | 68 - src/utility/outputStreamStringAdapter.cpp | 54 - src/utility/parserInputStreamAdapter.cpp | 176 - src/utility/path.cpp | 266 - src/utility/progressListener.cpp | 79 - src/utility/random.cpp | 90 - src/utility/seekableInputStreamRegionAdapter.cpp | 106 - src/utility/stream.cpp | 40 - src/utility/streamUtils.cpp | 121 - src/utility/stringProxy.cpp | 151 - src/utility/stringUtils.cpp | 242 - src/utility/sync/criticalSection.cpp | 44 - src/utility/url.cpp | 406 -- src/utility/urlUtils.cpp | 133 - src/vmime/address.cpp | 216 + src/vmime/address.hpp | 87 + src/vmime/addressList.cpp | 305 ++ src/vmime/addressList.hpp | 192 + src/vmime/attachment.hpp | 118 + src/vmime/attachmentHelper.cpp | 312 ++ src/vmime/attachmentHelper.hpp | 121 + src/vmime/base.cpp | 161 + src/vmime/base.hpp | 258 + src/vmime/body.cpp | 1050 ++++ src/vmime/body.hpp | 344 ++ src/vmime/bodyPart.cpp | 190 + src/vmime/bodyPart.hpp | 155 + src/vmime/bodyPartAttachment.cpp | 146 + src/vmime/bodyPartAttachment.hpp | 78 + src/vmime/charset.cpp | 210 + src/vmime/charset.hpp | 148 + src/vmime/charsetConverter.cpp | 45 + src/vmime/charsetConverter.hpp | 119 + src/vmime/charsetConverterOptions.cpp | 37 + src/vmime/charsetConverterOptions.hpp | 53 + src/vmime/charsetConverter_iconv.cpp | 475 ++ src/vmime/charsetConverter_iconv.hpp | 135 + src/vmime/charsetConverter_icu.cpp | 408 ++ src/vmime/charsetConverter_icu.hpp | 126 + src/vmime/charsetConverter_idna.cpp | 168 + src/vmime/charsetConverter_idna.hpp | 70 + src/vmime/component.cpp | 244 + src/vmime/component.hpp | 257 + src/vmime/constants.cpp | 237 + src/vmime/constants.hpp | 256 + src/vmime/contentDisposition.cpp | 133 + src/vmime/contentDisposition.hpp | 99 + src/vmime/contentDispositionField.cpp | 158 + src/vmime/contentDispositionField.hpp | 148 + src/vmime/contentHandler.cpp | 40 + src/vmime/contentHandler.hpp | 139 + src/vmime/contentTypeField.cpp | 113 + src/vmime/contentTypeField.hpp | 114 + src/vmime/context.cpp | 87 + src/vmime/context.hpp | 122 + src/vmime/dateTime.cpp | 894 ++++ src/vmime/dateTime.hpp | 263 + src/vmime/defaultAttachment.cpp | 146 + src/vmime/defaultAttachment.hpp | 88 + src/vmime/disposition.cpp | 329 ++ src/vmime/disposition.hpp | 159 + src/vmime/emailAddress.cpp | 539 ++ src/vmime/emailAddress.hpp | 135 + src/vmime/emptyContentHandler.cpp | 117 + src/vmime/emptyContentHandler.hpp | 70 + src/vmime/encoding.cpp | 300 ++ src/vmime/encoding.hpp | 172 + src/vmime/exception.cpp | 748 +++ src/vmime/exception.hpp | 906 ++++ src/vmime/export.hpp | 36 + src/vmime/fileAttachment.cpp | 223 + src/vmime/fileAttachment.hpp | 197 + src/vmime/fileContentHandler.cpp | 81 + src/vmime/fileContentHandler.hpp | 93 + src/vmime/generatedMessageAttachment.cpp | 107 + src/vmime/generatedMessageAttachment.hpp | 79 + src/vmime/generationContext.cpp | 109 + src/vmime/generationContext.hpp | 106 + src/vmime/header.cpp | 388 ++ src/vmime/header.hpp | 346 ++ src/vmime/headerField.cpp | 381 ++ src/vmime/headerField.hpp | 190 + src/vmime/headerFieldFactory.cpp | 151 + src/vmime/headerFieldFactory.hpp | 152 + src/vmime/headerFieldValue.cpp | 44 + src/vmime/headerFieldValue.hpp | 52 + src/vmime/htmlTextPart.cpp | 510 ++ src/vmime/htmlTextPart.hpp | 237 + src/vmime/mailbox.cpp | 510 ++ src/vmime/mailbox.hpp | 123 + src/vmime/mailboxField.cpp | 90 + src/vmime/mailboxField.hpp | 68 + src/vmime/mailboxGroup.cpp | 377 ++ src/vmime/mailboxGroup.hpp | 194 + src/vmime/mailboxList.cpp | 230 + src/vmime/mailboxList.hpp | 184 + src/vmime/mdn/MDNHelper.cpp | 353 ++ src/vmime/mdn/MDNHelper.hpp | 139 + src/vmime/mdn/MDNInfos.cpp | 38 + src/vmime/mdn/MDNInfos.hpp | 58 + src/vmime/mdn/receivedMDNInfos.cpp | 136 + src/vmime/mdn/receivedMDNInfos.hpp | 94 + src/vmime/mdn/sendableMDNInfos.cpp | 71 + src/vmime/mdn/sendableMDNInfos.hpp | 73 + src/vmime/mediaType.cpp | 187 + src/vmime/mediaType.hpp | 119 + src/vmime/message.cpp | 48 + src/vmime/message.hpp | 62 + src/vmime/messageAttachment.hpp | 55 + src/vmime/messageBuilder.cpp | 329 ++ src/vmime/messageBuilder.hpp | 223 + src/vmime/messageId.cpp | 300 ++ src/vmime/messageId.hpp | 143 + src/vmime/messageIdSequence.cpp | 252 + src/vmime/messageIdSequence.hpp | 172 + src/vmime/messageParser.cpp | 322 ++ src/vmime/messageParser.hpp | 159 + src/vmime/misc/importanceHelper.cpp | 162 + src/vmime/misc/importanceHelper.hpp | 105 + src/vmime/net/builtinServices.inl | 76 + src/vmime/net/connectionInfos.hpp | 68 + src/vmime/net/defaultConnectionInfos.cpp | 60 + src/vmime/net/defaultConnectionInfos.hpp | 66 + src/vmime/net/events.cpp | 166 + src/vmime/net/events.hpp | 273 + src/vmime/net/fetchAttributes.cpp | 95 + src/vmime/net/fetchAttributes.hpp | 142 + src/vmime/net/folder.cpp | 127 + src/vmime/net/folder.hpp | 399 ++ src/vmime/net/folderStatus.hpp | 74 + src/vmime/net/imap/IMAPConnection.cpp | 814 +++ src/vmime/net/imap/IMAPConnection.hpp | 163 + src/vmime/net/imap/IMAPFolder.cpp | 1511 ++++++ src/vmime/net/imap/IMAPFolder.hpp | 204 + src/vmime/net/imap/IMAPFolderStatus.cpp | 307 ++ src/vmime/net/imap/IMAPFolderStatus.hpp | 124 + src/vmime/net/imap/IMAPMessage.cpp | 649 +++ src/vmime/net/imap/IMAPMessage.hpp | 191 + src/vmime/net/imap/IMAPMessagePart.cpp | 161 + src/vmime/net/imap/IMAPMessagePart.hpp | 92 + .../net/imap/IMAPMessagePartContentHandler.cpp | 216 + .../net/imap/IMAPMessagePartContentHandler.hpp | 87 + src/vmime/net/imap/IMAPMessageStructure.cpp | 94 + src/vmime/net/imap/IMAPMessageStructure.hpp | 75 + src/vmime/net/imap/IMAPParser.hpp | 5617 ++++++++++++++++++++ src/vmime/net/imap/IMAPSStore.cpp | 79 + src/vmime/net/imap/IMAPSStore.hpp | 71 + src/vmime/net/imap/IMAPServiceInfos.cpp | 137 + src/vmime/net/imap/IMAPServiceInfos.hpp | 91 + src/vmime/net/imap/IMAPStore.cpp | 267 + src/vmime/net/imap/IMAPStore.hpp | 120 + src/vmime/net/imap/IMAPTag.cpp | 122 + src/vmime/net/imap/IMAPTag.hpp | 79 + src/vmime/net/imap/IMAPUtils.cpp | 758 +++ src/vmime/net/imap/IMAPUtils.hpp | 129 + src/vmime/net/imap/imap.hpp | 35 + .../net/maildir/format/courierMaildirFormat.cpp | 542 ++ .../net/maildir/format/courierMaildirFormat.hpp | 121 + .../net/maildir/format/kmailMaildirFormat.cpp | 320 ++ .../net/maildir/format/kmailMaildirFormat.hpp | 109 + src/vmime/net/maildir/maildir.hpp | 34 + src/vmime/net/maildir/maildirFolder.cpp | 1254 +++++ src/vmime/net/maildir/maildirFolder.hpp | 190 + src/vmime/net/maildir/maildirFolderStatus.cpp | 88 + src/vmime/net/maildir/maildirFolderStatus.hpp | 76 + src/vmime/net/maildir/maildirFormat.cpp | 109 + src/vmime/net/maildir/maildirFormat.hpp | 195 + src/vmime/net/maildir/maildirMessage.cpp | 369 ++ src/vmime/net/maildir/maildirMessage.hpp | 116 + src/vmime/net/maildir/maildirMessagePart.cpp | 155 + src/vmime/net/maildir/maildirMessagePart.hpp | 99 + src/vmime/net/maildir/maildirMessageStructure.cpp | 98 + src/vmime/net/maildir/maildirMessageStructure.hpp | 76 + src/vmime/net/maildir/maildirServiceInfos.cpp | 77 + src/vmime/net/maildir/maildirServiceInfos.hpp | 71 + src/vmime/net/maildir/maildirStore.cpp | 272 + src/vmime/net/maildir/maildirStore.hpp | 120 + src/vmime/net/maildir/maildirUtils.cpp | 273 + src/vmime/net/maildir/maildirUtils.hpp | 151 + src/vmime/net/message.cpp | 150 + src/vmime/net/message.hpp | 355 ++ src/vmime/net/messageSet.cpp | 369 ++ src/vmime/net/messageSet.hpp | 335 ++ src/vmime/net/pop3/POP3Command.cpp | 230 + src/vmime/net/pop3/POP3Command.hpp | 113 + src/vmime/net/pop3/POP3Connection.cpp | 675 +++ src/vmime/net/pop3/POP3Connection.hpp | 125 + src/vmime/net/pop3/POP3Folder.cpp | 729 +++ src/vmime/net/pop3/POP3Folder.hpp | 157 + src/vmime/net/pop3/POP3FolderStatus.cpp | 88 + src/vmime/net/pop3/POP3FolderStatus.hpp | 76 + src/vmime/net/pop3/POP3Message.cpp | 250 + src/vmime/net/pop3/POP3Message.hpp | 121 + src/vmime/net/pop3/POP3Response.cpp | 428 ++ src/vmime/net/pop3/POP3Response.hpp | 182 + src/vmime/net/pop3/POP3SStore.cpp | 79 + src/vmime/net/pop3/POP3SStore.hpp | 71 + src/vmime/net/pop3/POP3ServiceInfos.cpp | 143 + src/vmime/net/pop3/POP3ServiceInfos.hpp | 93 + src/vmime/net/pop3/POP3Store.cpp | 240 + src/vmime/net/pop3/POP3Store.hpp | 116 + src/vmime/net/pop3/POP3Utils.cpp | 114 + src/vmime/net/pop3/POP3Utils.hpp | 86 + src/vmime/net/pop3/pop3.hpp | 35 + src/vmime/net/securedConnectionInfos.hpp | 55 + src/vmime/net/sendmail/sendmail.hpp | 31 + src/vmime/net/sendmail/sendmailServiceInfos.cpp | 78 + src/vmime/net/sendmail/sendmailServiceInfos.hpp | 71 + src/vmime/net/sendmail/sendmailTransport.cpp | 230 + src/vmime/net/sendmail/sendmailTransport.hpp | 103 + src/vmime/net/service.cpp | 152 + src/vmime/net/service.hpp | 233 + src/vmime/net/serviceFactory.cpp | 145 + src/vmime/net/serviceFactory.hpp | 165 + src/vmime/net/serviceInfos.cpp | 167 + src/vmime/net/serviceInfos.hpp | 246 + src/vmime/net/serviceRegistration.inl | 98 + src/vmime/net/session.cpp | 158 + src/vmime/net/session.hpp | 178 + .../net/smtp/SMTPChunkingOutputStreamAdapter.cpp | 145 + .../net/smtp/SMTPChunkingOutputStreamAdapter.hpp | 85 + src/vmime/net/smtp/SMTPCommand.cpp | 214 + src/vmime/net/smtp/SMTPCommand.hpp | 111 + src/vmime/net/smtp/SMTPCommandSet.cpp | 144 + src/vmime/net/smtp/SMTPCommandSet.hpp | 105 + src/vmime/net/smtp/SMTPConnection.cpp | 618 +++ src/vmime/net/smtp/SMTPConnection.hpp | 129 + src/vmime/net/smtp/SMTPExceptions.cpp | 151 + src/vmime/net/smtp/SMTPExceptions.hpp | 127 + src/vmime/net/smtp/SMTPResponse.cpp | 334 ++ src/vmime/net/smtp/SMTPResponse.hpp | 186 + src/vmime/net/smtp/SMTPSTransport.cpp | 79 + src/vmime/net/smtp/SMTPSTransport.hpp | 71 + src/vmime/net/smtp/SMTPServiceInfos.cpp | 146 + src/vmime/net/smtp/SMTPServiceInfos.hpp | 95 + src/vmime/net/smtp/SMTPTransport.cpp | 420 ++ src/vmime/net/smtp/SMTPTransport.hpp | 131 + src/vmime/net/smtp/smtp.hpp | 33 + src/vmime/net/socket.hpp | 184 + src/vmime/net/store.hpp | 114 + src/vmime/net/timeoutHandler.hpp | 89 + src/vmime/net/tls/TLSProperties.cpp | 44 + src/vmime/net/tls/TLSProperties.hpp | 105 + src/vmime/net/tls/TLSSecuredConnectionInfos.cpp | 72 + src/vmime/net/tls/TLSSecuredConnectionInfos.hpp | 84 + src/vmime/net/tls/TLSSession.cpp | 48 + src/vmime/net/tls/TLSSession.hpp | 93 + src/vmime/net/tls/TLSSocket.cpp | 44 + src/vmime/net/tls/TLSSocket.hpp | 88 + src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp | 113 + src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp | 68 + src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp | 300 ++ src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp | 91 + src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp | 490 ++ src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp | 120 + src/vmime/net/tls/openssl/OpenSSLInitializer.cpp | 142 + src/vmime/net/tls/openssl/OpenSSLInitializer.hpp | 111 + .../net/tls/openssl/TLSProperties_OpenSSL.cpp | 112 + .../net/tls/openssl/TLSProperties_OpenSSL.hpp | 68 + src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp | 135 + src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp | 108 + src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp | 601 +++ src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp | 132 + src/vmime/net/transport.cpp | 236 + src/vmime/net/transport.hpp | 137 + src/vmime/object.cpp | 53 + src/vmime/object.hpp | 55 + src/vmime/parameter.cpp | 603 +++ src/vmime/parameter.hpp | 153 + src/vmime/parameterizedHeaderField.cpp | 580 ++ src/vmime/parameterizedHeaderField.hpp | 208 + src/vmime/parsedMessageAttachment.cpp | 116 + src/vmime/parsedMessageAttachment.hpp | 78 + src/vmime/parserHelpers.hpp | 96 + src/vmime/parsingContext.cpp | 49 + src/vmime/parsingContext.hpp | 59 + src/vmime/path.cpp | 190 + src/vmime/path.hpp | 106 + src/vmime/plainTextPart.cpp | 112 + src/vmime/plainTextPart.hpp | 68 + src/vmime/platform.cpp | 79 + src/vmime/platform.hpp | 170 + src/vmime/platforms/posix/posixChildProcess.cpp | 404 ++ src/vmime/platforms/posix/posixChildProcess.hpp | 92 + src/vmime/platforms/posix/posixCriticalSection.cpp | 67 + src/vmime/platforms/posix/posixCriticalSection.hpp | 69 + src/vmime/platforms/posix/posixFile.cpp | 628 +++ src/vmime/platforms/posix/posixFile.hpp | 220 + src/vmime/platforms/posix/posixHandler.cpp | 322 ++ src/vmime/platforms/posix/posixHandler.hpp | 105 + src/vmime/platforms/posix/posixSocket.cpp | 680 +++ src/vmime/platforms/posix/posixSocket.hpp | 102 + .../platforms/windows/windowsCriticalSection.cpp | 67 + .../platforms/windows/windowsCriticalSection.hpp | 68 + src/vmime/platforms/windows/windowsFile.cpp | 553 ++ src/vmime/platforms/windows/windowsFile.hpp | 221 + src/vmime/platforms/windows/windowsHandler.cpp | 329 ++ src/vmime/platforms/windows/windowsHandler.hpp | 103 + src/vmime/platforms/windows/windowsSocket.cpp | 484 ++ src/vmime/platforms/windows/windowsSocket.hpp | 114 + src/vmime/propertySet.cpp | 382 ++ src/vmime/propertySet.hpp | 460 ++ src/vmime/relay.cpp | 354 ++ src/vmime/relay.hpp | 108 + src/vmime/security/authenticator.hpp | 128 + src/vmime/security/cert/X509Certificate.cpp | 48 + src/vmime/security/cert/X509Certificate.hpp | 156 + src/vmime/security/cert/certificate.hpp | 84 + src/vmime/security/cert/certificateChain.cpp | 53 + src/vmime/security/cert/certificateChain.hpp | 79 + src/vmime/security/cert/certificateVerifier.hpp | 62 + .../security/cert/defaultCertificateVerifier.cpp | 178 + .../security/cert/defaultCertificateVerifier.hpp | 89 + .../cert/gnutls/X509Certificate_GnuTLS.cpp | 290 + .../cert/gnutls/X509Certificate_GnuTLS.hpp | 92 + .../cert/openssl/X509Certificate_OpenSSL.cpp | 574 ++ .../cert/openssl/X509Certificate_OpenSSL.hpp | 115 + src/vmime/security/defaultAuthenticator.cpp | 115 + src/vmime/security/defaultAuthenticator.hpp | 73 + src/vmime/security/digest/md5/md5MessageDigest.cpp | 347 ++ src/vmime/security/digest/md5/md5MessageDigest.hpp | 86 + src/vmime/security/digest/messageDigest.cpp | 57 + src/vmime/security/digest/messageDigest.hpp | 138 + src/vmime/security/digest/messageDigestFactory.cpp | 84 + src/vmime/security/digest/messageDigestFactory.hpp | 112 + .../security/digest/sha1/sha1MessageDigest.cpp | 271 + .../security/digest/sha1/sha1MessageDigest.hpp | 79 + src/vmime/security/sasl/SASLAuthenticator.hpp | 96 + src/vmime/security/sasl/SASLContext.cpp | 208 + src/vmime/security/sasl/SASLContext.hpp | 128 + src/vmime/security/sasl/SASLMechanism.hpp | 131 + src/vmime/security/sasl/SASLMechanismFactory.cpp | 144 + src/vmime/security/sasl/SASLMechanismFactory.hpp | 143 + src/vmime/security/sasl/SASLSession.cpp | 192 + src/vmime/security/sasl/SASLSession.hpp | 162 + src/vmime/security/sasl/SASLSocket.cpp | 236 + src/vmime/security/sasl/SASLSocket.hpp | 97 + src/vmime/security/sasl/builtinSASLMechanism.cpp | 195 + src/vmime/security/sasl/builtinSASLMechanism.hpp | 93 + .../security/sasl/defaultSASLAuthenticator.cpp | 153 + .../security/sasl/defaultSASLAuthenticator.hpp | 90 + src/vmime/streamContentHandler.cpp | 234 + src/vmime/streamContentHandler.hpp | 122 + src/vmime/stringContentHandler.cpp | 236 + src/vmime/stringContentHandler.hpp | 101 + src/vmime/text.cpp | 435 ++ src/vmime/text.hpp | 277 + src/vmime/textPart.hpp | 112 + src/vmime/textPartFactory.cpp | 69 + src/vmime/textPartFactory.hpp | 79 + src/vmime/types.hpp | 115 + src/vmime/utility/childProcess.hpp | 107 + src/vmime/utility/datetimeUtils.cpp | 333 ++ src/vmime/utility/datetimeUtils.hpp | 99 + src/vmime/utility/encoder/b64Encoder.cpp | 330 ++ src/vmime/utility/encoder/b64Encoder.hpp | 65 + src/vmime/utility/encoder/binaryEncoder.cpp | 39 + src/vmime/utility/encoder/binaryEncoder.hpp | 52 + src/vmime/utility/encoder/eightBitEncoder.cpp | 39 + src/vmime/utility/encoder/eightBitEncoder.hpp | 52 + src/vmime/utility/encoder/encoder.cpp | 76 + src/vmime/utility/encoder/encoder.hpp | 128 + src/vmime/utility/encoder/encoderFactory.cpp | 120 + src/vmime/utility/encoder/encoderFactory.hpp | 148 + src/vmime/utility/encoder/noopEncoder.cpp | 87 + src/vmime/utility/encoder/noopEncoder.hpp | 58 + src/vmime/utility/encoder/qpEncoder.cpp | 558 ++ src/vmime/utility/encoder/qpEncoder.hpp | 69 + src/vmime/utility/encoder/sevenBitEncoder.cpp | 39 + src/vmime/utility/encoder/sevenBitEncoder.hpp | 52 + src/vmime/utility/encoder/uuEncoder.cpp | 344 ++ src/vmime/utility/encoder/uuEncoder.hpp | 60 + src/vmime/utility/file.hpp | 269 + src/vmime/utility/filteredStream.cpp | 391 ++ src/vmime/utility/filteredStream.hpp | 406 ++ src/vmime/utility/inputStream.cpp | 33 + src/vmime/utility/inputStream.hpp | 76 + src/vmime/utility/inputStreamAdapter.cpp | 83 + src/vmime/utility/inputStreamAdapter.hpp | 66 + src/vmime/utility/inputStreamByteBufferAdapter.cpp | 103 + src/vmime/utility/inputStreamByteBufferAdapter.hpp | 65 + src/vmime/utility/inputStreamPointerAdapter.cpp | 46 + src/vmime/utility/inputStreamPointerAdapter.hpp | 63 + src/vmime/utility/inputStreamSocketAdapter.cpp | 82 + src/vmime/utility/inputStreamSocketAdapter.hpp | 77 + src/vmime/utility/inputStreamStringAdapter.cpp | 107 + src/vmime/utility/inputStreamStringAdapter.hpp | 68 + .../utility/inputStreamStringProxyAdapter.cpp | 102 + .../utility/inputStreamStringProxyAdapter.hpp | 70 + src/vmime/utility/outputStream.cpp | 45 + src/vmime/utility/outputStream.hpp | 136 + src/vmime/utility/outputStreamAdapter.cpp | 54 + src/vmime/utility/outputStreamAdapter.hpp | 65 + src/vmime/utility/outputStreamByteArrayAdapter.cpp | 52 + src/vmime/utility/outputStreamByteArrayAdapter.hpp | 61 + src/vmime/utility/outputStreamSocketAdapter.cpp | 68 + src/vmime/utility/outputStreamSocketAdapter.hpp | 78 + src/vmime/utility/outputStreamStringAdapter.cpp | 54 + src/vmime/utility/outputStreamStringAdapter.hpp | 61 + src/vmime/utility/parserInputStreamAdapter.cpp | 176 + src/vmime/utility/parserInputStreamAdapter.hpp | 174 + src/vmime/utility/path.cpp | 266 + src/vmime/utility/path.hpp | 171 + src/vmime/utility/progressListener.cpp | 79 + src/vmime/utility/progressListener.hpp | 113 + src/vmime/utility/random.cpp | 90 + src/vmime/utility/random.hpp | 77 + src/vmime/utility/seekableInputStream.hpp | 64 + .../utility/seekableInputStreamRegionAdapter.cpp | 106 + .../utility/seekableInputStreamRegionAdapter.hpp | 72 + src/vmime/utility/stream.cpp | 40 + src/vmime/utility/stream.hpp | 62 + src/vmime/utility/streamUtils.cpp | 121 + src/vmime/utility/streamUtils.hpp | 79 + src/vmime/utility/stringProxy.cpp | 151 + src/vmime/utility/stringProxy.hpp | 92 + src/vmime/utility/stringUtils.cpp | 242 + src/vmime/utility/stringUtils.hpp | 214 + src/vmime/utility/sync/autoLock.hpp | 66 + src/vmime/utility/sync/criticalSection.cpp | 44 + src/vmime/utility/sync/criticalSection.hpp | 65 + src/vmime/utility/url.cpp | 406 ++ src/vmime/utility/url.hpp | 207 + src/vmime/utility/urlUtils.cpp | 133 + src/vmime/utility/urlUtils.hpp | 58 + src/vmime/vmime.hpp | 161 + src/vmime/word.cpp | 793 +++ src/vmime/word.hpp | 195 + src/vmime/wordEncoder.cpp | 287 + src/vmime/wordEncoder.hpp | 112 + src/word.cpp | 793 --- src/wordEncoder.cpp | 287 - test-outsourced-build.sh | 4 +- vmime/address.hpp | 87 - vmime/addressList.hpp | 192 - vmime/attachment.hpp | 118 - vmime/attachmentHelper.hpp | 121 - vmime/base.hpp | 258 - vmime/body.hpp | 344 -- vmime/bodyPart.hpp | 155 - vmime/bodyPartAttachment.hpp | 78 - vmime/charset.hpp | 148 - vmime/charsetConverter.hpp | 119 - vmime/charsetConverterOptions.hpp | 53 - vmime/charsetConverter_iconv.hpp | 135 - vmime/charsetConverter_icu.hpp | 126 - vmime/charsetConverter_idna.hpp | 70 - vmime/component.hpp | 257 - vmime/constants.hpp | 256 - vmime/contentDisposition.hpp | 99 - vmime/contentDispositionField.hpp | 148 - vmime/contentHandler.hpp | 139 - vmime/contentTypeField.hpp | 114 - vmime/context.hpp | 122 - vmime/dateTime.hpp | 263 - vmime/defaultAttachment.hpp | 88 - vmime/disposition.hpp | 159 - vmime/emailAddress.hpp | 135 - vmime/emptyContentHandler.hpp | 70 - vmime/encoding.hpp | 172 - vmime/exception.hpp | 906 ---- vmime/export.hpp | 36 - vmime/fileAttachment.hpp | 197 - vmime/fileContentHandler.hpp | 93 - vmime/generatedMessageAttachment.hpp | 79 - vmime/generationContext.hpp | 106 - vmime/header.hpp | 346 -- vmime/headerField.hpp | 190 - vmime/headerFieldFactory.hpp | 152 - vmime/headerFieldValue.hpp | 52 - vmime/htmlTextPart.hpp | 237 - vmime/mailbox.hpp | 123 - vmime/mailboxField.hpp | 68 - vmime/mailboxGroup.hpp | 194 - vmime/mailboxList.hpp | 184 - vmime/mdn/MDNHelper.hpp | 139 - vmime/mdn/MDNInfos.hpp | 58 - vmime/mdn/receivedMDNInfos.hpp | 94 - vmime/mdn/sendableMDNInfos.hpp | 73 - vmime/mediaType.hpp | 119 - vmime/message.hpp | 62 - vmime/messageAttachment.hpp | 55 - vmime/messageBuilder.hpp | 223 - vmime/messageId.hpp | 143 - vmime/messageIdSequence.hpp | 172 - vmime/messageParser.hpp | 159 - vmime/misc/importanceHelper.hpp | 105 - vmime/net/connectionInfos.hpp | 68 - vmime/net/defaultConnectionInfos.hpp | 66 - vmime/net/events.hpp | 273 - vmime/net/fetchAttributes.hpp | 142 - vmime/net/folder.hpp | 399 -- vmime/net/folderStatus.hpp | 74 - vmime/net/imap/IMAPConnection.hpp | 163 - vmime/net/imap/IMAPFolder.hpp | 204 - vmime/net/imap/IMAPFolderStatus.hpp | 124 - vmime/net/imap/IMAPMessage.hpp | 191 - vmime/net/imap/IMAPMessagePart.hpp | 92 - vmime/net/imap/IMAPMessagePartContentHandler.hpp | 87 - vmime/net/imap/IMAPMessageStructure.hpp | 75 - vmime/net/imap/IMAPParser.hpp | 5617 -------------------- vmime/net/imap/IMAPSStore.hpp | 71 - vmime/net/imap/IMAPServiceInfos.hpp | 91 - vmime/net/imap/IMAPStore.hpp | 120 - vmime/net/imap/IMAPTag.hpp | 79 - vmime/net/imap/IMAPUtils.hpp | 129 - vmime/net/imap/imap.hpp | 35 - vmime/net/maildir/format/courierMaildirFormat.hpp | 121 - vmime/net/maildir/format/kmailMaildirFormat.hpp | 109 - vmime/net/maildir/maildir.hpp | 34 - vmime/net/maildir/maildirFolder.hpp | 190 - vmime/net/maildir/maildirFolderStatus.hpp | 76 - vmime/net/maildir/maildirFormat.hpp | 195 - vmime/net/maildir/maildirMessage.hpp | 116 - vmime/net/maildir/maildirMessagePart.hpp | 99 - vmime/net/maildir/maildirMessageStructure.hpp | 76 - vmime/net/maildir/maildirServiceInfos.hpp | 71 - vmime/net/maildir/maildirStore.hpp | 120 - vmime/net/maildir/maildirUtils.hpp | 151 - vmime/net/message.hpp | 355 -- vmime/net/messageSet.hpp | 335 -- vmime/net/pop3/POP3Command.hpp | 113 - vmime/net/pop3/POP3Connection.hpp | 125 - vmime/net/pop3/POP3Folder.hpp | 157 - vmime/net/pop3/POP3FolderStatus.hpp | 76 - vmime/net/pop3/POP3Message.hpp | 121 - vmime/net/pop3/POP3Response.hpp | 182 - vmime/net/pop3/POP3SStore.hpp | 71 - vmime/net/pop3/POP3ServiceInfos.hpp | 93 - vmime/net/pop3/POP3Store.hpp | 116 - vmime/net/pop3/POP3Utils.hpp | 86 - vmime/net/pop3/pop3.hpp | 35 - vmime/net/securedConnectionInfos.hpp | 55 - vmime/net/sendmail/sendmail.hpp | 31 - vmime/net/sendmail/sendmailServiceInfos.hpp | 71 - vmime/net/sendmail/sendmailTransport.hpp | 103 - vmime/net/service.hpp | 233 - vmime/net/serviceFactory.hpp | 165 - vmime/net/serviceInfos.hpp | 246 - vmime/net/session.hpp | 178 - vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp | 85 - vmime/net/smtp/SMTPCommand.hpp | 111 - vmime/net/smtp/SMTPCommandSet.hpp | 105 - vmime/net/smtp/SMTPConnection.hpp | 129 - vmime/net/smtp/SMTPExceptions.hpp | 127 - vmime/net/smtp/SMTPResponse.hpp | 186 - vmime/net/smtp/SMTPSTransport.hpp | 71 - vmime/net/smtp/SMTPServiceInfos.hpp | 95 - vmime/net/smtp/SMTPTransport.hpp | 131 - vmime/net/smtp/smtp.hpp | 33 - vmime/net/socket.hpp | 184 - vmime/net/store.hpp | 114 - vmime/net/timeoutHandler.hpp | 89 - vmime/net/tls/TLSProperties.hpp | 105 - vmime/net/tls/TLSSecuredConnectionInfos.hpp | 84 - vmime/net/tls/TLSSession.hpp | 93 - vmime/net/tls/TLSSocket.hpp | 88 - vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp | 68 - vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp | 91 - vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp | 120 - vmime/net/tls/openssl/OpenSSLInitializer.hpp | 111 - vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp | 68 - vmime/net/tls/openssl/TLSSession_OpenSSL.hpp | 108 - vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp | 132 - vmime/net/transport.hpp | 137 - vmime/object.hpp | 55 - vmime/parameter.hpp | 153 - vmime/parameterizedHeaderField.hpp | 208 - vmime/parsedMessageAttachment.hpp | 78 - vmime/parserHelpers.hpp | 96 - vmime/parsingContext.hpp | 59 - vmime/path.hpp | 106 - vmime/plainTextPart.hpp | 68 - vmime/platform.hpp | 170 - vmime/platforms/posix/posixChildProcess.hpp | 92 - vmime/platforms/posix/posixCriticalSection.hpp | 69 - vmime/platforms/posix/posixFile.hpp | 220 - vmime/platforms/posix/posixHandler.hpp | 105 - vmime/platforms/posix/posixSocket.hpp | 102 - vmime/platforms/windows/windowsCriticalSection.hpp | 68 - vmime/platforms/windows/windowsFile.hpp | 221 - vmime/platforms/windows/windowsHandler.hpp | 103 - vmime/platforms/windows/windowsSocket.hpp | 114 - vmime/propertySet.hpp | 460 -- vmime/relay.hpp | 108 - vmime/security/authenticator.hpp | 128 - vmime/security/cert/X509Certificate.hpp | 156 - vmime/security/cert/certificate.hpp | 84 - vmime/security/cert/certificateChain.hpp | 79 - vmime/security/cert/certificateVerifier.hpp | 62 - vmime/security/cert/defaultCertificateVerifier.hpp | 89 - .../cert/gnutls/X509Certificate_GnuTLS.hpp | 92 - .../cert/openssl/X509Certificate_OpenSSL.hpp | 115 - vmime/security/defaultAuthenticator.hpp | 73 - vmime/security/digest/md5/md5MessageDigest.hpp | 86 - vmime/security/digest/messageDigest.hpp | 138 - vmime/security/digest/messageDigestFactory.hpp | 112 - vmime/security/digest/sha1/sha1MessageDigest.hpp | 79 - vmime/security/sasl/SASLAuthenticator.hpp | 96 - vmime/security/sasl/SASLContext.hpp | 128 - vmime/security/sasl/SASLMechanism.hpp | 131 - vmime/security/sasl/SASLMechanismFactory.hpp | 143 - vmime/security/sasl/SASLSession.hpp | 162 - vmime/security/sasl/SASLSocket.hpp | 97 - vmime/security/sasl/builtinSASLMechanism.hpp | 93 - vmime/security/sasl/defaultSASLAuthenticator.hpp | 90 - vmime/streamContentHandler.hpp | 122 - vmime/stringContentHandler.hpp | 101 - vmime/text.hpp | 277 - vmime/textPart.hpp | 112 - vmime/textPartFactory.hpp | 79 - vmime/types.hpp | 115 - vmime/utility/childProcess.hpp | 107 - vmime/utility/datetimeUtils.hpp | 99 - vmime/utility/encoder/b64Encoder.hpp | 65 - vmime/utility/encoder/binaryEncoder.hpp | 52 - vmime/utility/encoder/eightBitEncoder.hpp | 52 - vmime/utility/encoder/encoder.hpp | 128 - vmime/utility/encoder/encoderFactory.hpp | 148 - vmime/utility/encoder/noopEncoder.hpp | 58 - vmime/utility/encoder/qpEncoder.hpp | 69 - vmime/utility/encoder/sevenBitEncoder.hpp | 52 - vmime/utility/encoder/uuEncoder.hpp | 60 - vmime/utility/file.hpp | 269 - vmime/utility/filteredStream.hpp | 406 -- vmime/utility/inputStream.hpp | 76 - vmime/utility/inputStreamAdapter.hpp | 66 - vmime/utility/inputStreamByteBufferAdapter.hpp | 65 - vmime/utility/inputStreamPointerAdapter.hpp | 63 - vmime/utility/inputStreamSocketAdapter.hpp | 77 - vmime/utility/inputStreamStringAdapter.hpp | 68 - vmime/utility/inputStreamStringProxyAdapter.hpp | 70 - vmime/utility/outputStream.hpp | 136 - vmime/utility/outputStreamAdapter.hpp | 65 - vmime/utility/outputStreamByteArrayAdapter.hpp | 61 - vmime/utility/outputStreamSocketAdapter.hpp | 78 - vmime/utility/outputStreamStringAdapter.hpp | 61 - vmime/utility/parserInputStreamAdapter.hpp | 174 - vmime/utility/path.hpp | 171 - vmime/utility/progressListener.hpp | 113 - vmime/utility/random.hpp | 77 - vmime/utility/seekableInputStream.hpp | 64 - vmime/utility/seekableInputStreamRegionAdapter.hpp | 72 - vmime/utility/stream.hpp | 62 - vmime/utility/streamUtils.hpp | 79 - vmime/utility/stringProxy.hpp | 92 - vmime/utility/stringUtils.hpp | 214 - vmime/utility/sync/autoLock.hpp | 66 - vmime/utility/sync/criticalSection.hpp | 65 - vmime/utility/url.hpp | 207 - vmime/utility/urlUtils.hpp | 58 - vmime/vmime.hpp | 161 - vmime/word.hpp | 195 - vmime/wordEncoder.hpp | 112 - 838 files changed, 81411 insertions(+), 82551 deletions(-) delete mode 100644 SConstruct delete mode 100644 examples/README delete mode 100644 src/address.cpp delete mode 100644 src/addressList.cpp delete mode 100644 src/attachmentHelper.cpp delete mode 100644 src/base.cpp delete mode 100644 src/body.cpp delete mode 100644 src/bodyPart.cpp delete mode 100644 src/bodyPartAttachment.cpp delete mode 100644 src/charset.cpp delete mode 100644 src/charsetConverter.cpp delete mode 100644 src/charsetConverterOptions.cpp delete mode 100644 src/charsetConverter_iconv.cpp delete mode 100644 src/charsetConverter_icu.cpp delete mode 100644 src/charsetConverter_idna.cpp delete mode 100644 src/component.cpp delete mode 100644 src/constants.cpp delete mode 100644 src/contentDisposition.cpp delete mode 100644 src/contentDispositionField.cpp delete mode 100644 src/contentHandler.cpp delete mode 100644 src/contentTypeField.cpp delete mode 100644 src/context.cpp delete mode 100644 src/dateTime.cpp delete mode 100644 src/defaultAttachment.cpp delete mode 100644 src/disposition.cpp delete mode 100644 src/emailAddress.cpp delete mode 100644 src/emptyContentHandler.cpp delete mode 100644 src/encoding.cpp delete mode 100644 src/exception.cpp delete mode 100644 src/fileAttachment.cpp delete mode 100644 src/fileContentHandler.cpp delete mode 100644 src/generatedMessageAttachment.cpp delete mode 100644 src/generationContext.cpp delete mode 100644 src/header.cpp delete mode 100644 src/headerField.cpp delete mode 100644 src/headerFieldFactory.cpp delete mode 100644 src/headerFieldValue.cpp delete mode 100644 src/htmlTextPart.cpp delete mode 100644 src/mailbox.cpp delete mode 100644 src/mailboxField.cpp delete mode 100644 src/mailboxGroup.cpp delete mode 100644 src/mailboxList.cpp delete mode 100644 src/mdn/MDNHelper.cpp delete mode 100644 src/mdn/MDNInfos.cpp delete mode 100644 src/mdn/receivedMDNInfos.cpp delete mode 100644 src/mdn/sendableMDNInfos.cpp delete mode 100644 src/mediaType.cpp delete mode 100644 src/message.cpp delete mode 100644 src/messageBuilder.cpp delete mode 100644 src/messageId.cpp delete mode 100644 src/messageIdSequence.cpp delete mode 100644 src/messageParser.cpp delete mode 100644 src/misc/importanceHelper.cpp delete mode 100644 src/net/builtinServices.inl delete mode 100644 src/net/defaultConnectionInfos.cpp delete mode 100644 src/net/events.cpp delete mode 100644 src/net/fetchAttributes.cpp delete mode 100644 src/net/folder.cpp delete mode 100644 src/net/imap/IMAPConnection.cpp delete mode 100644 src/net/imap/IMAPFolder.cpp delete mode 100644 src/net/imap/IMAPFolderStatus.cpp delete mode 100644 src/net/imap/IMAPMessage.cpp delete mode 100644 src/net/imap/IMAPMessagePart.cpp delete mode 100644 src/net/imap/IMAPMessagePartContentHandler.cpp delete mode 100644 src/net/imap/IMAPMessageStructure.cpp delete mode 100644 src/net/imap/IMAPSStore.cpp delete mode 100644 src/net/imap/IMAPServiceInfos.cpp delete mode 100644 src/net/imap/IMAPStore.cpp delete mode 100644 src/net/imap/IMAPTag.cpp delete mode 100644 src/net/imap/IMAPUtils.cpp delete mode 100644 src/net/maildir/format/courierMaildirFormat.cpp delete mode 100644 src/net/maildir/format/kmailMaildirFormat.cpp delete mode 100644 src/net/maildir/maildirFolder.cpp delete mode 100644 src/net/maildir/maildirFolderStatus.cpp delete mode 100644 src/net/maildir/maildirFormat.cpp delete mode 100644 src/net/maildir/maildirMessage.cpp delete mode 100644 src/net/maildir/maildirMessagePart.cpp delete mode 100644 src/net/maildir/maildirMessageStructure.cpp delete mode 100644 src/net/maildir/maildirServiceInfos.cpp delete mode 100644 src/net/maildir/maildirStore.cpp delete mode 100644 src/net/maildir/maildirUtils.cpp delete mode 100644 src/net/message.cpp delete mode 100644 src/net/messageSet.cpp delete mode 100644 src/net/pop3/POP3Command.cpp delete mode 100644 src/net/pop3/POP3Connection.cpp delete mode 100644 src/net/pop3/POP3Folder.cpp delete mode 100644 src/net/pop3/POP3FolderStatus.cpp delete mode 100644 src/net/pop3/POP3Message.cpp delete mode 100644 src/net/pop3/POP3Response.cpp delete mode 100644 src/net/pop3/POP3SStore.cpp delete mode 100644 src/net/pop3/POP3ServiceInfos.cpp delete mode 100644 src/net/pop3/POP3Store.cpp delete mode 100644 src/net/pop3/POP3Utils.cpp delete mode 100644 src/net/sendmail/sendmailServiceInfos.cpp delete mode 100644 src/net/sendmail/sendmailTransport.cpp delete mode 100644 src/net/service.cpp delete mode 100644 src/net/serviceFactory.cpp delete mode 100644 src/net/serviceInfos.cpp delete mode 100644 src/net/serviceRegistration.inl delete mode 100644 src/net/session.cpp delete mode 100644 src/net/smtp/SMTPChunkingOutputStreamAdapter.cpp delete mode 100644 src/net/smtp/SMTPCommand.cpp delete mode 100644 src/net/smtp/SMTPCommandSet.cpp delete mode 100644 src/net/smtp/SMTPConnection.cpp delete mode 100644 src/net/smtp/SMTPExceptions.cpp delete mode 100644 src/net/smtp/SMTPResponse.cpp delete mode 100644 src/net/smtp/SMTPSTransport.cpp delete mode 100644 src/net/smtp/SMTPServiceInfos.cpp delete mode 100644 src/net/smtp/SMTPTransport.cpp delete mode 100644 src/net/tls/TLSProperties.cpp delete mode 100644 src/net/tls/TLSSecuredConnectionInfos.cpp delete mode 100644 src/net/tls/TLSSession.cpp delete mode 100644 src/net/tls/TLSSocket.cpp delete mode 100644 src/net/tls/gnutls/TLSProperties_GnuTLS.cpp delete mode 100644 src/net/tls/gnutls/TLSSession_GnuTLS.cpp delete mode 100644 src/net/tls/gnutls/TLSSocket_GnuTLS.cpp delete mode 100644 src/net/tls/openssl/OpenSSLInitializer.cpp delete mode 100644 src/net/tls/openssl/TLSProperties_OpenSSL.cpp delete mode 100644 src/net/tls/openssl/TLSSession_OpenSSL.cpp delete mode 100644 src/net/tls/openssl/TLSSocket_OpenSSL.cpp delete mode 100644 src/net/transport.cpp delete mode 100644 src/object.cpp delete mode 100644 src/parameter.cpp delete mode 100644 src/parameterizedHeaderField.cpp delete mode 100644 src/parsedMessageAttachment.cpp delete mode 100644 src/parsingContext.cpp delete mode 100644 src/path.cpp delete mode 100644 src/plainTextPart.cpp delete mode 100644 src/platform.cpp delete mode 100644 src/platforms/posix/posixChildProcess.cpp delete mode 100644 src/platforms/posix/posixCriticalSection.cpp delete mode 100644 src/platforms/posix/posixFile.cpp delete mode 100644 src/platforms/posix/posixHandler.cpp delete mode 100644 src/platforms/posix/posixSocket.cpp delete mode 100644 src/platforms/windows/windowsCriticalSection.cpp delete mode 100644 src/platforms/windows/windowsFile.cpp delete mode 100644 src/platforms/windows/windowsHandler.cpp delete mode 100644 src/platforms/windows/windowsSocket.cpp delete mode 100644 src/propertySet.cpp delete mode 100644 src/relay.cpp delete mode 100644 src/security/cert/X509Certificate.cpp delete mode 100644 src/security/cert/certificateChain.cpp delete mode 100644 src/security/cert/defaultCertificateVerifier.cpp delete mode 100644 src/security/cert/gnutls/X509Certificate_GnuTLS.cpp delete mode 100644 src/security/cert/openssl/X509Certificate_OpenSSL.cpp delete mode 100644 src/security/defaultAuthenticator.cpp delete mode 100644 src/security/digest/md5/md5MessageDigest.cpp delete mode 100644 src/security/digest/messageDigest.cpp delete mode 100644 src/security/digest/messageDigestFactory.cpp delete mode 100644 src/security/digest/sha1/sha1MessageDigest.cpp delete mode 100644 src/security/sasl/SASLContext.cpp delete mode 100644 src/security/sasl/SASLMechanismFactory.cpp delete mode 100644 src/security/sasl/SASLSession.cpp delete mode 100644 src/security/sasl/SASLSocket.cpp delete mode 100644 src/security/sasl/builtinSASLMechanism.cpp delete mode 100644 src/security/sasl/defaultSASLAuthenticator.cpp delete mode 100644 src/streamContentHandler.cpp delete mode 100644 src/stringContentHandler.cpp delete mode 100644 src/text.cpp delete mode 100644 src/textPartFactory.cpp delete mode 100644 src/utility/datetimeUtils.cpp delete mode 100644 src/utility/encoder/b64Encoder.cpp delete mode 100644 src/utility/encoder/binaryEncoder.cpp delete mode 100644 src/utility/encoder/eightBitEncoder.cpp delete mode 100644 src/utility/encoder/encoder.cpp delete mode 100644 src/utility/encoder/encoderFactory.cpp delete mode 100644 src/utility/encoder/noopEncoder.cpp delete mode 100644 src/utility/encoder/qpEncoder.cpp delete mode 100644 src/utility/encoder/sevenBitEncoder.cpp delete mode 100644 src/utility/encoder/uuEncoder.cpp delete mode 100644 src/utility/filteredStream.cpp delete mode 100644 src/utility/inputStream.cpp delete mode 100644 src/utility/inputStreamAdapter.cpp delete mode 100644 src/utility/inputStreamByteBufferAdapter.cpp delete mode 100644 src/utility/inputStreamPointerAdapter.cpp delete mode 100644 src/utility/inputStreamSocketAdapter.cpp delete mode 100644 src/utility/inputStreamStringAdapter.cpp delete mode 100644 src/utility/inputStreamStringProxyAdapter.cpp delete mode 100644 src/utility/outputStream.cpp delete mode 100644 src/utility/outputStreamAdapter.cpp delete mode 100644 src/utility/outputStreamByteArrayAdapter.cpp delete mode 100644 src/utility/outputStreamSocketAdapter.cpp delete mode 100644 src/utility/outputStreamStringAdapter.cpp delete mode 100644 src/utility/parserInputStreamAdapter.cpp delete mode 100644 src/utility/path.cpp delete mode 100644 src/utility/progressListener.cpp delete mode 100644 src/utility/random.cpp delete mode 100644 src/utility/seekableInputStreamRegionAdapter.cpp delete mode 100644 src/utility/stream.cpp delete mode 100644 src/utility/streamUtils.cpp delete mode 100644 src/utility/stringProxy.cpp delete mode 100644 src/utility/stringUtils.cpp delete mode 100644 src/utility/sync/criticalSection.cpp delete mode 100644 src/utility/url.cpp delete mode 100644 src/utility/urlUtils.cpp create mode 100644 src/vmime/address.cpp create mode 100644 src/vmime/address.hpp create mode 100644 src/vmime/addressList.cpp create mode 100644 src/vmime/addressList.hpp create mode 100644 src/vmime/attachment.hpp create mode 100644 src/vmime/attachmentHelper.cpp create mode 100644 src/vmime/attachmentHelper.hpp create mode 100644 src/vmime/base.cpp create mode 100644 src/vmime/base.hpp create mode 100644 src/vmime/body.cpp create mode 100644 src/vmime/body.hpp create mode 100644 src/vmime/bodyPart.cpp create mode 100644 src/vmime/bodyPart.hpp create mode 100644 src/vmime/bodyPartAttachment.cpp create mode 100644 src/vmime/bodyPartAttachment.hpp create mode 100644 src/vmime/charset.cpp create mode 100644 src/vmime/charset.hpp create mode 100644 src/vmime/charsetConverter.cpp create mode 100644 src/vmime/charsetConverter.hpp create mode 100644 src/vmime/charsetConverterOptions.cpp create mode 100644 src/vmime/charsetConverterOptions.hpp create mode 100644 src/vmime/charsetConverter_iconv.cpp create mode 100644 src/vmime/charsetConverter_iconv.hpp create mode 100644 src/vmime/charsetConverter_icu.cpp create mode 100644 src/vmime/charsetConverter_icu.hpp create mode 100644 src/vmime/charsetConverter_idna.cpp create mode 100644 src/vmime/charsetConverter_idna.hpp create mode 100644 src/vmime/component.cpp create mode 100644 src/vmime/component.hpp create mode 100644 src/vmime/constants.cpp create mode 100644 src/vmime/constants.hpp create mode 100644 src/vmime/contentDisposition.cpp create mode 100644 src/vmime/contentDisposition.hpp create mode 100644 src/vmime/contentDispositionField.cpp create mode 100644 src/vmime/contentDispositionField.hpp create mode 100644 src/vmime/contentHandler.cpp create mode 100644 src/vmime/contentHandler.hpp create mode 100644 src/vmime/contentTypeField.cpp create mode 100644 src/vmime/contentTypeField.hpp create mode 100644 src/vmime/context.cpp create mode 100644 src/vmime/context.hpp create mode 100644 src/vmime/dateTime.cpp create mode 100644 src/vmime/dateTime.hpp create mode 100644 src/vmime/defaultAttachment.cpp create mode 100644 src/vmime/defaultAttachment.hpp create mode 100644 src/vmime/disposition.cpp create mode 100644 src/vmime/disposition.hpp create mode 100644 src/vmime/emailAddress.cpp create mode 100644 src/vmime/emailAddress.hpp create mode 100644 src/vmime/emptyContentHandler.cpp create mode 100644 src/vmime/emptyContentHandler.hpp create mode 100644 src/vmime/encoding.cpp create mode 100644 src/vmime/encoding.hpp create mode 100644 src/vmime/exception.cpp create mode 100644 src/vmime/exception.hpp create mode 100644 src/vmime/export.hpp create mode 100644 src/vmime/fileAttachment.cpp create mode 100644 src/vmime/fileAttachment.hpp create mode 100644 src/vmime/fileContentHandler.cpp create mode 100644 src/vmime/fileContentHandler.hpp create mode 100644 src/vmime/generatedMessageAttachment.cpp create mode 100644 src/vmime/generatedMessageAttachment.hpp create mode 100644 src/vmime/generationContext.cpp create mode 100644 src/vmime/generationContext.hpp create mode 100644 src/vmime/header.cpp create mode 100644 src/vmime/header.hpp create mode 100644 src/vmime/headerField.cpp create mode 100644 src/vmime/headerField.hpp create mode 100644 src/vmime/headerFieldFactory.cpp create mode 100644 src/vmime/headerFieldFactory.hpp create mode 100644 src/vmime/headerFieldValue.cpp create mode 100644 src/vmime/headerFieldValue.hpp create mode 100644 src/vmime/htmlTextPart.cpp create mode 100644 src/vmime/htmlTextPart.hpp create mode 100644 src/vmime/mailbox.cpp create mode 100644 src/vmime/mailbox.hpp create mode 100644 src/vmime/mailboxField.cpp create mode 100644 src/vmime/mailboxField.hpp create mode 100644 src/vmime/mailboxGroup.cpp create mode 100644 src/vmime/mailboxGroup.hpp create mode 100644 src/vmime/mailboxList.cpp create mode 100644 src/vmime/mailboxList.hpp create mode 100644 src/vmime/mdn/MDNHelper.cpp create mode 100644 src/vmime/mdn/MDNHelper.hpp create mode 100644 src/vmime/mdn/MDNInfos.cpp create mode 100644 src/vmime/mdn/MDNInfos.hpp create mode 100644 src/vmime/mdn/receivedMDNInfos.cpp create mode 100644 src/vmime/mdn/receivedMDNInfos.hpp create mode 100644 src/vmime/mdn/sendableMDNInfos.cpp create mode 100644 src/vmime/mdn/sendableMDNInfos.hpp create mode 100644 src/vmime/mediaType.cpp create mode 100644 src/vmime/mediaType.hpp create mode 100644 src/vmime/message.cpp create mode 100644 src/vmime/message.hpp create mode 100644 src/vmime/messageAttachment.hpp create mode 100644 src/vmime/messageBuilder.cpp create mode 100644 src/vmime/messageBuilder.hpp create mode 100644 src/vmime/messageId.cpp create mode 100644 src/vmime/messageId.hpp create mode 100644 src/vmime/messageIdSequence.cpp create mode 100644 src/vmime/messageIdSequence.hpp create mode 100644 src/vmime/messageParser.cpp create mode 100644 src/vmime/messageParser.hpp create mode 100644 src/vmime/misc/importanceHelper.cpp create mode 100644 src/vmime/misc/importanceHelper.hpp create mode 100644 src/vmime/net/builtinServices.inl create mode 100644 src/vmime/net/connectionInfos.hpp create mode 100644 src/vmime/net/defaultConnectionInfos.cpp create mode 100644 src/vmime/net/defaultConnectionInfos.hpp create mode 100644 src/vmime/net/events.cpp create mode 100644 src/vmime/net/events.hpp create mode 100644 src/vmime/net/fetchAttributes.cpp create mode 100644 src/vmime/net/fetchAttributes.hpp create mode 100644 src/vmime/net/folder.cpp create mode 100644 src/vmime/net/folder.hpp create mode 100644 src/vmime/net/folderStatus.hpp create mode 100644 src/vmime/net/imap/IMAPConnection.cpp create mode 100644 src/vmime/net/imap/IMAPConnection.hpp create mode 100644 src/vmime/net/imap/IMAPFolder.cpp create mode 100644 src/vmime/net/imap/IMAPFolder.hpp create mode 100644 src/vmime/net/imap/IMAPFolderStatus.cpp create mode 100644 src/vmime/net/imap/IMAPFolderStatus.hpp create mode 100644 src/vmime/net/imap/IMAPMessage.cpp create mode 100644 src/vmime/net/imap/IMAPMessage.hpp create mode 100644 src/vmime/net/imap/IMAPMessagePart.cpp create mode 100644 src/vmime/net/imap/IMAPMessagePart.hpp create mode 100644 src/vmime/net/imap/IMAPMessagePartContentHandler.cpp create mode 100644 src/vmime/net/imap/IMAPMessagePartContentHandler.hpp create mode 100644 src/vmime/net/imap/IMAPMessageStructure.cpp create mode 100644 src/vmime/net/imap/IMAPMessageStructure.hpp create mode 100644 src/vmime/net/imap/IMAPParser.hpp create mode 100644 src/vmime/net/imap/IMAPSStore.cpp create mode 100644 src/vmime/net/imap/IMAPSStore.hpp create mode 100644 src/vmime/net/imap/IMAPServiceInfos.cpp create mode 100644 src/vmime/net/imap/IMAPServiceInfos.hpp create mode 100644 src/vmime/net/imap/IMAPStore.cpp create mode 100644 src/vmime/net/imap/IMAPStore.hpp create mode 100644 src/vmime/net/imap/IMAPTag.cpp create mode 100644 src/vmime/net/imap/IMAPTag.hpp create mode 100644 src/vmime/net/imap/IMAPUtils.cpp create mode 100644 src/vmime/net/imap/IMAPUtils.hpp create mode 100644 src/vmime/net/imap/imap.hpp create mode 100644 src/vmime/net/maildir/format/courierMaildirFormat.cpp create mode 100644 src/vmime/net/maildir/format/courierMaildirFormat.hpp create mode 100644 src/vmime/net/maildir/format/kmailMaildirFormat.cpp create mode 100644 src/vmime/net/maildir/format/kmailMaildirFormat.hpp create mode 100644 src/vmime/net/maildir/maildir.hpp create mode 100644 src/vmime/net/maildir/maildirFolder.cpp create mode 100644 src/vmime/net/maildir/maildirFolder.hpp create mode 100644 src/vmime/net/maildir/maildirFolderStatus.cpp create mode 100644 src/vmime/net/maildir/maildirFolderStatus.hpp create mode 100644 src/vmime/net/maildir/maildirFormat.cpp create mode 100644 src/vmime/net/maildir/maildirFormat.hpp create mode 100644 src/vmime/net/maildir/maildirMessage.cpp create mode 100644 src/vmime/net/maildir/maildirMessage.hpp create mode 100644 src/vmime/net/maildir/maildirMessagePart.cpp create mode 100644 src/vmime/net/maildir/maildirMessagePart.hpp create mode 100644 src/vmime/net/maildir/maildirMessageStructure.cpp create mode 100644 src/vmime/net/maildir/maildirMessageStructure.hpp create mode 100644 src/vmime/net/maildir/maildirServiceInfos.cpp create mode 100644 src/vmime/net/maildir/maildirServiceInfos.hpp create mode 100644 src/vmime/net/maildir/maildirStore.cpp create mode 100644 src/vmime/net/maildir/maildirStore.hpp create mode 100644 src/vmime/net/maildir/maildirUtils.cpp create mode 100644 src/vmime/net/maildir/maildirUtils.hpp create mode 100644 src/vmime/net/message.cpp create mode 100644 src/vmime/net/message.hpp create mode 100644 src/vmime/net/messageSet.cpp create mode 100644 src/vmime/net/messageSet.hpp create mode 100644 src/vmime/net/pop3/POP3Command.cpp create mode 100644 src/vmime/net/pop3/POP3Command.hpp create mode 100644 src/vmime/net/pop3/POP3Connection.cpp create mode 100644 src/vmime/net/pop3/POP3Connection.hpp create mode 100644 src/vmime/net/pop3/POP3Folder.cpp create mode 100644 src/vmime/net/pop3/POP3Folder.hpp create mode 100644 src/vmime/net/pop3/POP3FolderStatus.cpp create mode 100644 src/vmime/net/pop3/POP3FolderStatus.hpp create mode 100644 src/vmime/net/pop3/POP3Message.cpp create mode 100644 src/vmime/net/pop3/POP3Message.hpp create mode 100644 src/vmime/net/pop3/POP3Response.cpp create mode 100644 src/vmime/net/pop3/POP3Response.hpp create mode 100644 src/vmime/net/pop3/POP3SStore.cpp create mode 100644 src/vmime/net/pop3/POP3SStore.hpp create mode 100644 src/vmime/net/pop3/POP3ServiceInfos.cpp create mode 100644 src/vmime/net/pop3/POP3ServiceInfos.hpp create mode 100644 src/vmime/net/pop3/POP3Store.cpp create mode 100644 src/vmime/net/pop3/POP3Store.hpp create mode 100644 src/vmime/net/pop3/POP3Utils.cpp create mode 100644 src/vmime/net/pop3/POP3Utils.hpp create mode 100644 src/vmime/net/pop3/pop3.hpp create mode 100644 src/vmime/net/securedConnectionInfos.hpp create mode 100644 src/vmime/net/sendmail/sendmail.hpp create mode 100644 src/vmime/net/sendmail/sendmailServiceInfos.cpp create mode 100644 src/vmime/net/sendmail/sendmailServiceInfos.hpp create mode 100644 src/vmime/net/sendmail/sendmailTransport.cpp create mode 100644 src/vmime/net/sendmail/sendmailTransport.hpp create mode 100644 src/vmime/net/service.cpp create mode 100644 src/vmime/net/service.hpp create mode 100644 src/vmime/net/serviceFactory.cpp create mode 100644 src/vmime/net/serviceFactory.hpp create mode 100644 src/vmime/net/serviceInfos.cpp create mode 100644 src/vmime/net/serviceInfos.hpp create mode 100644 src/vmime/net/serviceRegistration.inl create mode 100644 src/vmime/net/session.cpp create mode 100644 src/vmime/net/session.hpp create mode 100644 src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp create mode 100644 src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp create mode 100644 src/vmime/net/smtp/SMTPCommand.cpp create mode 100644 src/vmime/net/smtp/SMTPCommand.hpp create mode 100644 src/vmime/net/smtp/SMTPCommandSet.cpp create mode 100644 src/vmime/net/smtp/SMTPCommandSet.hpp create mode 100644 src/vmime/net/smtp/SMTPConnection.cpp create mode 100644 src/vmime/net/smtp/SMTPConnection.hpp create mode 100644 src/vmime/net/smtp/SMTPExceptions.cpp create mode 100644 src/vmime/net/smtp/SMTPExceptions.hpp create mode 100644 src/vmime/net/smtp/SMTPResponse.cpp create mode 100644 src/vmime/net/smtp/SMTPResponse.hpp create mode 100644 src/vmime/net/smtp/SMTPSTransport.cpp create mode 100644 src/vmime/net/smtp/SMTPSTransport.hpp create mode 100644 src/vmime/net/smtp/SMTPServiceInfos.cpp create mode 100644 src/vmime/net/smtp/SMTPServiceInfos.hpp create mode 100644 src/vmime/net/smtp/SMTPTransport.cpp create mode 100644 src/vmime/net/smtp/SMTPTransport.hpp create mode 100644 src/vmime/net/smtp/smtp.hpp create mode 100644 src/vmime/net/socket.hpp create mode 100644 src/vmime/net/store.hpp create mode 100644 src/vmime/net/timeoutHandler.hpp create mode 100644 src/vmime/net/tls/TLSProperties.cpp create mode 100644 src/vmime/net/tls/TLSProperties.hpp create mode 100644 src/vmime/net/tls/TLSSecuredConnectionInfos.cpp create mode 100644 src/vmime/net/tls/TLSSecuredConnectionInfos.hpp create mode 100644 src/vmime/net/tls/TLSSession.cpp create mode 100644 src/vmime/net/tls/TLSSession.hpp create mode 100644 src/vmime/net/tls/TLSSocket.cpp create mode 100644 src/vmime/net/tls/TLSSocket.hpp create mode 100644 src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp create mode 100644 src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp create mode 100644 src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp create mode 100644 src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp create mode 100644 src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp create mode 100644 src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp create mode 100644 src/vmime/net/tls/openssl/OpenSSLInitializer.cpp create mode 100644 src/vmime/net/tls/openssl/OpenSSLInitializer.hpp create mode 100644 src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp create mode 100644 src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp create mode 100644 src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp create mode 100644 src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp create mode 100644 src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp create mode 100644 src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp create mode 100644 src/vmime/net/transport.cpp create mode 100644 src/vmime/net/transport.hpp create mode 100644 src/vmime/object.cpp create mode 100644 src/vmime/object.hpp create mode 100644 src/vmime/parameter.cpp create mode 100644 src/vmime/parameter.hpp create mode 100644 src/vmime/parameterizedHeaderField.cpp create mode 100644 src/vmime/parameterizedHeaderField.hpp create mode 100644 src/vmime/parsedMessageAttachment.cpp create mode 100644 src/vmime/parsedMessageAttachment.hpp create mode 100644 src/vmime/parserHelpers.hpp create mode 100644 src/vmime/parsingContext.cpp create mode 100644 src/vmime/parsingContext.hpp create mode 100644 src/vmime/path.cpp create mode 100644 src/vmime/path.hpp create mode 100644 src/vmime/plainTextPart.cpp create mode 100644 src/vmime/plainTextPart.hpp create mode 100644 src/vmime/platform.cpp create mode 100644 src/vmime/platform.hpp create mode 100644 src/vmime/platforms/posix/posixChildProcess.cpp create mode 100644 src/vmime/platforms/posix/posixChildProcess.hpp create mode 100644 src/vmime/platforms/posix/posixCriticalSection.cpp create mode 100644 src/vmime/platforms/posix/posixCriticalSection.hpp create mode 100644 src/vmime/platforms/posix/posixFile.cpp create mode 100644 src/vmime/platforms/posix/posixFile.hpp create mode 100644 src/vmime/platforms/posix/posixHandler.cpp create mode 100644 src/vmime/platforms/posix/posixHandler.hpp create mode 100644 src/vmime/platforms/posix/posixSocket.cpp create mode 100644 src/vmime/platforms/posix/posixSocket.hpp create mode 100644 src/vmime/platforms/windows/windowsCriticalSection.cpp create mode 100644 src/vmime/platforms/windows/windowsCriticalSection.hpp create mode 100644 src/vmime/platforms/windows/windowsFile.cpp create mode 100644 src/vmime/platforms/windows/windowsFile.hpp create mode 100644 src/vmime/platforms/windows/windowsHandler.cpp create mode 100644 src/vmime/platforms/windows/windowsHandler.hpp create mode 100644 src/vmime/platforms/windows/windowsSocket.cpp create mode 100644 src/vmime/platforms/windows/windowsSocket.hpp create mode 100644 src/vmime/propertySet.cpp create mode 100644 src/vmime/propertySet.hpp create mode 100644 src/vmime/relay.cpp create mode 100644 src/vmime/relay.hpp create mode 100644 src/vmime/security/authenticator.hpp create mode 100644 src/vmime/security/cert/X509Certificate.cpp create mode 100644 src/vmime/security/cert/X509Certificate.hpp create mode 100644 src/vmime/security/cert/certificate.hpp create mode 100644 src/vmime/security/cert/certificateChain.cpp create mode 100644 src/vmime/security/cert/certificateChain.hpp create mode 100644 src/vmime/security/cert/certificateVerifier.hpp create mode 100644 src/vmime/security/cert/defaultCertificateVerifier.cpp create mode 100644 src/vmime/security/cert/defaultCertificateVerifier.hpp create mode 100644 src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp create mode 100644 src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp create mode 100644 src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp create mode 100644 src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp create mode 100644 src/vmime/security/defaultAuthenticator.cpp create mode 100644 src/vmime/security/defaultAuthenticator.hpp create mode 100644 src/vmime/security/digest/md5/md5MessageDigest.cpp create mode 100644 src/vmime/security/digest/md5/md5MessageDigest.hpp create mode 100644 src/vmime/security/digest/messageDigest.cpp create mode 100644 src/vmime/security/digest/messageDigest.hpp create mode 100644 src/vmime/security/digest/messageDigestFactory.cpp create mode 100644 src/vmime/security/digest/messageDigestFactory.hpp create mode 100644 src/vmime/security/digest/sha1/sha1MessageDigest.cpp create mode 100644 src/vmime/security/digest/sha1/sha1MessageDigest.hpp create mode 100644 src/vmime/security/sasl/SASLAuthenticator.hpp create mode 100644 src/vmime/security/sasl/SASLContext.cpp create mode 100644 src/vmime/security/sasl/SASLContext.hpp create mode 100644 src/vmime/security/sasl/SASLMechanism.hpp create mode 100644 src/vmime/security/sasl/SASLMechanismFactory.cpp create mode 100644 src/vmime/security/sasl/SASLMechanismFactory.hpp create mode 100644 src/vmime/security/sasl/SASLSession.cpp create mode 100644 src/vmime/security/sasl/SASLSession.hpp create mode 100644 src/vmime/security/sasl/SASLSocket.cpp create mode 100644 src/vmime/security/sasl/SASLSocket.hpp create mode 100644 src/vmime/security/sasl/builtinSASLMechanism.cpp create mode 100644 src/vmime/security/sasl/builtinSASLMechanism.hpp create mode 100644 src/vmime/security/sasl/defaultSASLAuthenticator.cpp create mode 100644 src/vmime/security/sasl/defaultSASLAuthenticator.hpp create mode 100644 src/vmime/streamContentHandler.cpp create mode 100644 src/vmime/streamContentHandler.hpp create mode 100644 src/vmime/stringContentHandler.cpp create mode 100644 src/vmime/stringContentHandler.hpp create mode 100644 src/vmime/text.cpp create mode 100644 src/vmime/text.hpp create mode 100644 src/vmime/textPart.hpp create mode 100644 src/vmime/textPartFactory.cpp create mode 100644 src/vmime/textPartFactory.hpp create mode 100644 src/vmime/types.hpp create mode 100644 src/vmime/utility/childProcess.hpp create mode 100644 src/vmime/utility/datetimeUtils.cpp create mode 100644 src/vmime/utility/datetimeUtils.hpp create mode 100644 src/vmime/utility/encoder/b64Encoder.cpp create mode 100644 src/vmime/utility/encoder/b64Encoder.hpp create mode 100644 src/vmime/utility/encoder/binaryEncoder.cpp create mode 100644 src/vmime/utility/encoder/binaryEncoder.hpp create mode 100644 src/vmime/utility/encoder/eightBitEncoder.cpp create mode 100644 src/vmime/utility/encoder/eightBitEncoder.hpp create mode 100644 src/vmime/utility/encoder/encoder.cpp create mode 100644 src/vmime/utility/encoder/encoder.hpp create mode 100644 src/vmime/utility/encoder/encoderFactory.cpp create mode 100644 src/vmime/utility/encoder/encoderFactory.hpp create mode 100644 src/vmime/utility/encoder/noopEncoder.cpp create mode 100644 src/vmime/utility/encoder/noopEncoder.hpp create mode 100644 src/vmime/utility/encoder/qpEncoder.cpp create mode 100644 src/vmime/utility/encoder/qpEncoder.hpp create mode 100644 src/vmime/utility/encoder/sevenBitEncoder.cpp create mode 100644 src/vmime/utility/encoder/sevenBitEncoder.hpp create mode 100644 src/vmime/utility/encoder/uuEncoder.cpp create mode 100644 src/vmime/utility/encoder/uuEncoder.hpp create mode 100644 src/vmime/utility/file.hpp create mode 100644 src/vmime/utility/filteredStream.cpp create mode 100644 src/vmime/utility/filteredStream.hpp create mode 100644 src/vmime/utility/inputStream.cpp create mode 100644 src/vmime/utility/inputStream.hpp create mode 100644 src/vmime/utility/inputStreamAdapter.cpp create mode 100644 src/vmime/utility/inputStreamAdapter.hpp create mode 100644 src/vmime/utility/inputStreamByteBufferAdapter.cpp create mode 100644 src/vmime/utility/inputStreamByteBufferAdapter.hpp create mode 100644 src/vmime/utility/inputStreamPointerAdapter.cpp create mode 100644 src/vmime/utility/inputStreamPointerAdapter.hpp create mode 100644 src/vmime/utility/inputStreamSocketAdapter.cpp create mode 100644 src/vmime/utility/inputStreamSocketAdapter.hpp create mode 100644 src/vmime/utility/inputStreamStringAdapter.cpp create mode 100644 src/vmime/utility/inputStreamStringAdapter.hpp create mode 100644 src/vmime/utility/inputStreamStringProxyAdapter.cpp create mode 100644 src/vmime/utility/inputStreamStringProxyAdapter.hpp create mode 100644 src/vmime/utility/outputStream.cpp create mode 100644 src/vmime/utility/outputStream.hpp create mode 100644 src/vmime/utility/outputStreamAdapter.cpp create mode 100644 src/vmime/utility/outputStreamAdapter.hpp create mode 100644 src/vmime/utility/outputStreamByteArrayAdapter.cpp create mode 100644 src/vmime/utility/outputStreamByteArrayAdapter.hpp create mode 100644 src/vmime/utility/outputStreamSocketAdapter.cpp create mode 100644 src/vmime/utility/outputStreamSocketAdapter.hpp create mode 100644 src/vmime/utility/outputStreamStringAdapter.cpp create mode 100644 src/vmime/utility/outputStreamStringAdapter.hpp create mode 100644 src/vmime/utility/parserInputStreamAdapter.cpp create mode 100644 src/vmime/utility/parserInputStreamAdapter.hpp create mode 100644 src/vmime/utility/path.cpp create mode 100644 src/vmime/utility/path.hpp create mode 100644 src/vmime/utility/progressListener.cpp create mode 100644 src/vmime/utility/progressListener.hpp create mode 100644 src/vmime/utility/random.cpp create mode 100644 src/vmime/utility/random.hpp create mode 100644 src/vmime/utility/seekableInputStream.hpp create mode 100644 src/vmime/utility/seekableInputStreamRegionAdapter.cpp create mode 100644 src/vmime/utility/seekableInputStreamRegionAdapter.hpp create mode 100644 src/vmime/utility/stream.cpp create mode 100644 src/vmime/utility/stream.hpp create mode 100644 src/vmime/utility/streamUtils.cpp create mode 100644 src/vmime/utility/streamUtils.hpp create mode 100644 src/vmime/utility/stringProxy.cpp create mode 100644 src/vmime/utility/stringProxy.hpp create mode 100644 src/vmime/utility/stringUtils.cpp create mode 100644 src/vmime/utility/stringUtils.hpp create mode 100644 src/vmime/utility/sync/autoLock.hpp create mode 100644 src/vmime/utility/sync/criticalSection.cpp create mode 100644 src/vmime/utility/sync/criticalSection.hpp create mode 100644 src/vmime/utility/url.cpp create mode 100644 src/vmime/utility/url.hpp create mode 100644 src/vmime/utility/urlUtils.cpp create mode 100644 src/vmime/utility/urlUtils.hpp create mode 100644 src/vmime/vmime.hpp create mode 100644 src/vmime/word.cpp create mode 100644 src/vmime/word.hpp create mode 100644 src/vmime/wordEncoder.cpp create mode 100644 src/vmime/wordEncoder.hpp delete mode 100644 src/word.cpp delete mode 100644 src/wordEncoder.cpp delete mode 100644 vmime/address.hpp delete mode 100644 vmime/addressList.hpp delete mode 100644 vmime/attachment.hpp delete mode 100644 vmime/attachmentHelper.hpp delete mode 100644 vmime/base.hpp delete mode 100644 vmime/body.hpp delete mode 100644 vmime/bodyPart.hpp delete mode 100644 vmime/bodyPartAttachment.hpp delete mode 100644 vmime/charset.hpp delete mode 100644 vmime/charsetConverter.hpp delete mode 100644 vmime/charsetConverterOptions.hpp delete mode 100644 vmime/charsetConverter_iconv.hpp delete mode 100644 vmime/charsetConverter_icu.hpp delete mode 100644 vmime/charsetConverter_idna.hpp delete mode 100644 vmime/component.hpp delete mode 100644 vmime/constants.hpp delete mode 100644 vmime/contentDisposition.hpp delete mode 100644 vmime/contentDispositionField.hpp delete mode 100644 vmime/contentHandler.hpp delete mode 100644 vmime/contentTypeField.hpp delete mode 100644 vmime/context.hpp delete mode 100644 vmime/dateTime.hpp delete mode 100644 vmime/defaultAttachment.hpp delete mode 100644 vmime/disposition.hpp delete mode 100644 vmime/emailAddress.hpp delete mode 100644 vmime/emptyContentHandler.hpp delete mode 100644 vmime/encoding.hpp delete mode 100644 vmime/exception.hpp delete mode 100644 vmime/export.hpp delete mode 100644 vmime/fileAttachment.hpp delete mode 100644 vmime/fileContentHandler.hpp delete mode 100644 vmime/generatedMessageAttachment.hpp delete mode 100644 vmime/generationContext.hpp delete mode 100644 vmime/header.hpp delete mode 100644 vmime/headerField.hpp delete mode 100644 vmime/headerFieldFactory.hpp delete mode 100644 vmime/headerFieldValue.hpp delete mode 100644 vmime/htmlTextPart.hpp delete mode 100644 vmime/mailbox.hpp delete mode 100644 vmime/mailboxField.hpp delete mode 100644 vmime/mailboxGroup.hpp delete mode 100644 vmime/mailboxList.hpp delete mode 100644 vmime/mdn/MDNHelper.hpp delete mode 100644 vmime/mdn/MDNInfos.hpp delete mode 100644 vmime/mdn/receivedMDNInfos.hpp delete mode 100644 vmime/mdn/sendableMDNInfos.hpp delete mode 100644 vmime/mediaType.hpp delete mode 100644 vmime/message.hpp delete mode 100644 vmime/messageAttachment.hpp delete mode 100644 vmime/messageBuilder.hpp delete mode 100644 vmime/messageId.hpp delete mode 100644 vmime/messageIdSequence.hpp delete mode 100644 vmime/messageParser.hpp delete mode 100644 vmime/misc/importanceHelper.hpp delete mode 100644 vmime/net/connectionInfos.hpp delete mode 100644 vmime/net/defaultConnectionInfos.hpp delete mode 100644 vmime/net/events.hpp delete mode 100644 vmime/net/fetchAttributes.hpp delete mode 100644 vmime/net/folder.hpp delete mode 100644 vmime/net/folderStatus.hpp delete mode 100644 vmime/net/imap/IMAPConnection.hpp delete mode 100644 vmime/net/imap/IMAPFolder.hpp delete mode 100644 vmime/net/imap/IMAPFolderStatus.hpp delete mode 100644 vmime/net/imap/IMAPMessage.hpp delete mode 100644 vmime/net/imap/IMAPMessagePart.hpp delete mode 100644 vmime/net/imap/IMAPMessagePartContentHandler.hpp delete mode 100644 vmime/net/imap/IMAPMessageStructure.hpp delete mode 100644 vmime/net/imap/IMAPParser.hpp delete mode 100644 vmime/net/imap/IMAPSStore.hpp delete mode 100644 vmime/net/imap/IMAPServiceInfos.hpp delete mode 100644 vmime/net/imap/IMAPStore.hpp delete mode 100644 vmime/net/imap/IMAPTag.hpp delete mode 100644 vmime/net/imap/IMAPUtils.hpp delete mode 100644 vmime/net/imap/imap.hpp delete mode 100644 vmime/net/maildir/format/courierMaildirFormat.hpp delete mode 100644 vmime/net/maildir/format/kmailMaildirFormat.hpp delete mode 100644 vmime/net/maildir/maildir.hpp delete mode 100644 vmime/net/maildir/maildirFolder.hpp delete mode 100644 vmime/net/maildir/maildirFolderStatus.hpp delete mode 100644 vmime/net/maildir/maildirFormat.hpp delete mode 100644 vmime/net/maildir/maildirMessage.hpp delete mode 100644 vmime/net/maildir/maildirMessagePart.hpp delete mode 100644 vmime/net/maildir/maildirMessageStructure.hpp delete mode 100644 vmime/net/maildir/maildirServiceInfos.hpp delete mode 100644 vmime/net/maildir/maildirStore.hpp delete mode 100644 vmime/net/maildir/maildirUtils.hpp delete mode 100644 vmime/net/message.hpp delete mode 100644 vmime/net/messageSet.hpp delete mode 100644 vmime/net/pop3/POP3Command.hpp delete mode 100644 vmime/net/pop3/POP3Connection.hpp delete mode 100644 vmime/net/pop3/POP3Folder.hpp delete mode 100644 vmime/net/pop3/POP3FolderStatus.hpp delete mode 100644 vmime/net/pop3/POP3Message.hpp delete mode 100644 vmime/net/pop3/POP3Response.hpp delete mode 100644 vmime/net/pop3/POP3SStore.hpp delete mode 100644 vmime/net/pop3/POP3ServiceInfos.hpp delete mode 100644 vmime/net/pop3/POP3Store.hpp delete mode 100644 vmime/net/pop3/POP3Utils.hpp delete mode 100644 vmime/net/pop3/pop3.hpp delete mode 100644 vmime/net/securedConnectionInfos.hpp delete mode 100644 vmime/net/sendmail/sendmail.hpp delete mode 100644 vmime/net/sendmail/sendmailServiceInfos.hpp delete mode 100644 vmime/net/sendmail/sendmailTransport.hpp delete mode 100644 vmime/net/service.hpp delete mode 100644 vmime/net/serviceFactory.hpp delete mode 100644 vmime/net/serviceInfos.hpp delete mode 100644 vmime/net/session.hpp delete mode 100644 vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp delete mode 100644 vmime/net/smtp/SMTPCommand.hpp delete mode 100644 vmime/net/smtp/SMTPCommandSet.hpp delete mode 100644 vmime/net/smtp/SMTPConnection.hpp delete mode 100644 vmime/net/smtp/SMTPExceptions.hpp delete mode 100644 vmime/net/smtp/SMTPResponse.hpp delete mode 100644 vmime/net/smtp/SMTPSTransport.hpp delete mode 100644 vmime/net/smtp/SMTPServiceInfos.hpp delete mode 100644 vmime/net/smtp/SMTPTransport.hpp delete mode 100644 vmime/net/smtp/smtp.hpp delete mode 100644 vmime/net/socket.hpp delete mode 100644 vmime/net/store.hpp delete mode 100644 vmime/net/timeoutHandler.hpp delete mode 100644 vmime/net/tls/TLSProperties.hpp delete mode 100644 vmime/net/tls/TLSSecuredConnectionInfos.hpp delete mode 100644 vmime/net/tls/TLSSession.hpp delete mode 100644 vmime/net/tls/TLSSocket.hpp delete mode 100644 vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp delete mode 100644 vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp delete mode 100644 vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp delete mode 100644 vmime/net/tls/openssl/OpenSSLInitializer.hpp delete mode 100644 vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp delete mode 100644 vmime/net/tls/openssl/TLSSession_OpenSSL.hpp delete mode 100644 vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp delete mode 100644 vmime/net/transport.hpp delete mode 100644 vmime/object.hpp delete mode 100644 vmime/parameter.hpp delete mode 100644 vmime/parameterizedHeaderField.hpp delete mode 100644 vmime/parsedMessageAttachment.hpp delete mode 100644 vmime/parserHelpers.hpp delete mode 100644 vmime/parsingContext.hpp delete mode 100644 vmime/path.hpp delete mode 100644 vmime/plainTextPart.hpp delete mode 100644 vmime/platform.hpp delete mode 100644 vmime/platforms/posix/posixChildProcess.hpp delete mode 100644 vmime/platforms/posix/posixCriticalSection.hpp delete mode 100644 vmime/platforms/posix/posixFile.hpp delete mode 100644 vmime/platforms/posix/posixHandler.hpp delete mode 100644 vmime/platforms/posix/posixSocket.hpp delete mode 100644 vmime/platforms/windows/windowsCriticalSection.hpp delete mode 100644 vmime/platforms/windows/windowsFile.hpp delete mode 100644 vmime/platforms/windows/windowsHandler.hpp delete mode 100644 vmime/platforms/windows/windowsSocket.hpp delete mode 100644 vmime/propertySet.hpp delete mode 100644 vmime/relay.hpp delete mode 100644 vmime/security/authenticator.hpp delete mode 100644 vmime/security/cert/X509Certificate.hpp delete mode 100644 vmime/security/cert/certificate.hpp delete mode 100644 vmime/security/cert/certificateChain.hpp delete mode 100644 vmime/security/cert/certificateVerifier.hpp delete mode 100644 vmime/security/cert/defaultCertificateVerifier.hpp delete mode 100644 vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp delete mode 100644 vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp delete mode 100644 vmime/security/defaultAuthenticator.hpp delete mode 100644 vmime/security/digest/md5/md5MessageDigest.hpp delete mode 100644 vmime/security/digest/messageDigest.hpp delete mode 100644 vmime/security/digest/messageDigestFactory.hpp delete mode 100644 vmime/security/digest/sha1/sha1MessageDigest.hpp delete mode 100644 vmime/security/sasl/SASLAuthenticator.hpp delete mode 100644 vmime/security/sasl/SASLContext.hpp delete mode 100644 vmime/security/sasl/SASLMechanism.hpp delete mode 100644 vmime/security/sasl/SASLMechanismFactory.hpp delete mode 100644 vmime/security/sasl/SASLSession.hpp delete mode 100644 vmime/security/sasl/SASLSocket.hpp delete mode 100644 vmime/security/sasl/builtinSASLMechanism.hpp delete mode 100644 vmime/security/sasl/defaultSASLAuthenticator.hpp delete mode 100644 vmime/streamContentHandler.hpp delete mode 100644 vmime/stringContentHandler.hpp delete mode 100644 vmime/text.hpp delete mode 100644 vmime/textPart.hpp delete mode 100644 vmime/textPartFactory.hpp delete mode 100644 vmime/types.hpp delete mode 100644 vmime/utility/childProcess.hpp delete mode 100644 vmime/utility/datetimeUtils.hpp delete mode 100644 vmime/utility/encoder/b64Encoder.hpp delete mode 100644 vmime/utility/encoder/binaryEncoder.hpp delete mode 100644 vmime/utility/encoder/eightBitEncoder.hpp delete mode 100644 vmime/utility/encoder/encoder.hpp delete mode 100644 vmime/utility/encoder/encoderFactory.hpp delete mode 100644 vmime/utility/encoder/noopEncoder.hpp delete mode 100644 vmime/utility/encoder/qpEncoder.hpp delete mode 100644 vmime/utility/encoder/sevenBitEncoder.hpp delete mode 100644 vmime/utility/encoder/uuEncoder.hpp delete mode 100644 vmime/utility/file.hpp delete mode 100644 vmime/utility/filteredStream.hpp delete mode 100644 vmime/utility/inputStream.hpp delete mode 100644 vmime/utility/inputStreamAdapter.hpp delete mode 100644 vmime/utility/inputStreamByteBufferAdapter.hpp delete mode 100644 vmime/utility/inputStreamPointerAdapter.hpp delete mode 100644 vmime/utility/inputStreamSocketAdapter.hpp delete mode 100644 vmime/utility/inputStreamStringAdapter.hpp delete mode 100644 vmime/utility/inputStreamStringProxyAdapter.hpp delete mode 100644 vmime/utility/outputStream.hpp delete mode 100644 vmime/utility/outputStreamAdapter.hpp delete mode 100644 vmime/utility/outputStreamByteArrayAdapter.hpp delete mode 100644 vmime/utility/outputStreamSocketAdapter.hpp delete mode 100644 vmime/utility/outputStreamStringAdapter.hpp delete mode 100644 vmime/utility/parserInputStreamAdapter.hpp delete mode 100644 vmime/utility/path.hpp delete mode 100644 vmime/utility/progressListener.hpp delete mode 100644 vmime/utility/random.hpp delete mode 100644 vmime/utility/seekableInputStream.hpp delete mode 100644 vmime/utility/seekableInputStreamRegionAdapter.hpp delete mode 100644 vmime/utility/stream.hpp delete mode 100644 vmime/utility/streamUtils.hpp delete mode 100644 vmime/utility/stringProxy.hpp delete mode 100644 vmime/utility/stringUtils.hpp delete mode 100644 vmime/utility/sync/autoLock.hpp delete mode 100644 vmime/utility/sync/criticalSection.hpp delete mode 100644 vmime/utility/url.hpp delete mode 100644 vmime/utility/urlUtils.hpp delete mode 100644 vmime/vmime.hpp delete mode 100644 vmime/word.hpp delete mode 100644 vmime/wordEncoder.hpp diff --git a/.gitignore b/.gitignore index 8b955403..2262aac2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,11 +7,6 @@ # Doxygen-generated doc/html/* -# SConstruct -.sconsign.dblite -/options.cache -/run-tests - # CMake-generated / Build files CMakeFiles/ CMakeCache.txt @@ -24,9 +19,9 @@ cmake_install.cmake /install_manifest* /libvmime.a /vmime.pc -/vmime/config.hpp -/vmime/export-static.hpp -/vmime/export-shared.hpp +/src/vmime/config.hpp +/src/vmime/export-static.hpp +/src/vmime/export-shared.hpp /COPYING.txt build/ Makefile diff --git a/CMakeLists.txt b/CMakeLists.txt index c8a885a3..e20d00d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,19 +71,20 @@ SET(VMIME_LIBRARY_NAME vmime) FILE( GLOB_RECURSE VMIME_LIBRARY_SRC_FILES - src/* + ${CMAKE_CURRENT_SOURCE_DIR}/src/vmime/*.cpp ) FILE( GLOB_RECURSE VMIME_LIBRARY_INCLUDE_FILES - vmime/* + ${CMAKE_CURRENT_SOURCE_DIR}/src/vmime/*.hpp ) -LIST(APPEND VMIME_LIBRARY_GENERATED_INCLUDE_FILES "vmime/config.hpp") +LIST(APPEND VMIME_LIBRARY_GENERATED_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/vmime/config.hpp") INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} # for "contrib/" + ${CMAKE_CURRENT_SOURCE_DIR}/src # for "vmime/ ) INCLUDE(GenerateExportHeader) @@ -116,10 +117,10 @@ IF(VMIME_BUILD_SHARED_LIBRARY) COPY ${CMAKE_CURRENT_BINARY_DIR}/export-shared.hpp DESTINATION - ${PROJECT_SOURCE_DIR}/vmime + ${PROJECT_SOURCE_DIR}/src/vmime ) - LIST(APPEND VMIME_LIBRARY_GENERATED_INCLUDE_FILES "vmime/export-shared.hpp") + LIST(APPEND VMIME_LIBRARY_GENERATED_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/vmime/export-shared.hpp") SET_TARGET_PROPERTIES( ${VMIME_LIBRARY_NAME} @@ -161,10 +162,10 @@ IF(VMIME_BUILD_STATIC_LIBRARY) COPY ${CMAKE_CURRENT_BINARY_DIR}/export-static.hpp DESTINATION - ${PROJECT_SOURCE_DIR}/vmime + ${PROJECT_SOURCE_DIR}/src/vmime ) - LIST(APPEND VMIME_LIBRARY_GENERATED_INCLUDE_FILES "vmime/export-static.hpp") + LIST(APPEND VMIME_LIBRARY_GENERATED_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/vmime/export-static.hpp") SET_TARGET_PROPERTIES( ${VMIME_LIBRARY_NAME}-static @@ -244,8 +245,8 @@ IF(VMIME_BUILD_STATIC_LIBRARY) ENDIF() # Installation of header files -INSTALL_HEADERS_WITH_DIRECTORY(VMIME_LIBRARY_INCLUDE_FILES headers) -INSTALL_HEADERS_WITH_DIRECTORY(VMIME_LIBRARY_GENERATED_INCLUDE_FILES headers) +INSTALL_HEADERS_WITH_DIRECTORY(VMIME_LIBRARY_INCLUDE_FILES headers src/) +INSTALL_HEADERS_WITH_DIRECTORY(VMIME_LIBRARY_GENERATED_INCLUDE_FILES headers src/) #INSTALL( # FILES ${VMIME_LIBRARY_INCLUDE_FILES} @@ -1064,7 +1065,7 @@ ENDIF() # Set our configure file -CONFIGURE_FILE(cmake/config.hpp.cmake ${CMAKE_SOURCE_DIR}/vmime/config.hpp) +CONFIGURE_FILE(cmake/config.hpp.cmake ${CMAKE_SOURCE_DIR}/src/vmime/config.hpp) # PkgConfig post-configuration CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/vmime.pc.in ${CMAKE_BINARY_DIR}/vmime.pc @ONLY) diff --git a/SConstruct b/SConstruct deleted file mode 100644 index 88a42154..00000000 --- a/SConstruct +++ /dev/null @@ -1,1124 +0,0 @@ -# -# SConstruct file for VMime -# -# Deprecated: use only for development purpose. -# Use CMake for distribution/packaging. -# -# Process this file with 'scons' to build the project. -# For more information, please visit: http://www.scons.org/ . -# -# Usage: -# -# . scons build the library -# . scons -h see available configuration options -# . scons opt=value set a configuration option -# . scons doc build documentation for the project (Doxygen) -# - -import commands -import os -import sys -import re -import string - - -############# -# Version # -############# - -# Package information -packageName = 'libvmime' -packageGenericName = 'vmime' -packageRealName = 'VMime Library' -packageDescription = 'VMime C++ Mail Library (http://www.vmime.org)' -packageMaintainer = 'vincent@vmime.org' - -packageVersion = '0.0.0' -packageAPI = '0:0:0' - -packageVersionedGenericName = packageGenericName -packageVersionedName = packageName - - -################## -# Source files # -################## - -libvmime_sources = [ - # ============================== Parser ============================== - 'address.cpp', 'address.hpp', - 'addressList.cpp', 'addressList.hpp', - 'attachment.hpp', - 'attachmentHelper.cpp', 'attachmentHelper.hpp', - 'base.cpp', 'base.hpp', - 'body.cpp', 'body.hpp', - 'bodyPart.cpp', 'bodyPart.hpp', - 'bodyPartAttachment.cpp', 'bodyPartAttachment.hpp', - 'charset.cpp', 'charset.hpp', - 'charsetConverter.cpp', 'charsetConverter.hpp', - 'charsetConverter_iconv.cpp', 'charsetConverter_iconv.hpp', - 'charsetConverter_icu.cpp', 'charsetConverter_icu.hpp', - 'charsetConverter_idna.cpp', 'charsetConverter_idna.hpp', - 'charsetConverterOptions.cpp', 'charsetConverterOptions.hpp', - 'component.cpp', 'component.hpp', - 'constants.cpp', 'constants.hpp', - 'contentDisposition.cpp', 'contentDisposition.hpp', - 'contentDispositionField.cpp', 'contentDispositionField.hpp', - 'contentHandler.cpp', 'contentHandler.hpp', - 'contentTypeField.cpp', 'contentTypeField.hpp', - 'context.hpp', 'context.cpp', - 'dateTime.cpp', 'dateTime.hpp', - 'defaultAttachment.cpp', 'defaultAttachment.hpp', - 'disposition.cpp', 'disposition.hpp', - 'emailAddress.cpp', 'emailAddress.hpp', - 'emptyContentHandler.cpp', 'emptyContentHandler.hpp', - 'encoding.cpp', 'encoding.hpp', - 'exception.cpp', 'exception.hpp', - 'fileAttachment.cpp', 'fileAttachment.hpp', - 'fileContentHandler.cpp', 'fileContentHandler.hpp', - 'generatedMessageAttachment.hpp', 'generatedMessageAttachment.cpp', - 'generationContext.hpp', 'generationContext.cpp', - 'header.cpp', 'header.hpp', - 'headerFieldFactory.cpp', 'headerFieldFactory.hpp', - 'headerField.cpp', 'headerField.hpp', - 'headerFieldValue.cpp', 'headerFieldValue.hpp', - 'htmlTextPart.cpp', 'htmlTextPart.hpp', - 'mailbox.cpp', 'mailbox.hpp', - 'mailboxField.cpp', 'mailboxField.hpp', - 'mailboxGroup.cpp', 'mailboxGroup.hpp', - 'mailboxList.cpp', 'mailboxList.hpp', - 'mediaType.cpp', 'mediaType.hpp', - 'messageAttachment.hpp', - 'messageBuilder.cpp', 'messageBuilder.hpp', - 'message.cpp', 'message.hpp', - 'messageId.cpp', 'messageId.hpp', - 'messageIdSequence.cpp', 'messageIdSequence.hpp', - 'messageParser.cpp', 'messageParser.hpp', - 'object.cpp', 'object.hpp', - 'path.cpp', 'path.hpp', - 'parameter.cpp', 'parameter.hpp', - 'parameterizedHeaderField.cpp', 'parameterizedHeaderField.hpp', - 'parsedMessageAttachment.cpp', 'parsedMessageAttachment.hpp', - 'parserHelpers.hpp', - 'parsingContext.hpp', 'parsingContext.cpp', - 'plainTextPart.cpp', 'plainTextPart.hpp', - 'platform.cpp', 'platform.hpp', - 'propertySet.cpp', 'propertySet.hpp', - 'relay.cpp', 'relay.hpp', - 'stringContentHandler.cpp', 'stringContentHandler.hpp', - 'streamContentHandler.cpp', 'streamContentHandler.hpp', - 'text.cpp', 'text.hpp', - 'textPartFactory.cpp', 'textPartFactory.hpp', - 'textPart.hpp', - 'types.hpp', - 'word.cpp', 'word.hpp', - 'wordEncoder.cpp', 'wordEncoder.hpp', - 'vmime.hpp', - # ============================== Utility ============================= - 'utility/childProcess.hpp', - 'utility/file.hpp', - 'utility/datetimeUtils.cpp', 'utility/datetimeUtils.hpp', - 'utility/path.cpp', 'utility/path.hpp', - 'utility/progressListener.cpp', 'utility/progressListener.hpp', - 'utility/random.cpp', 'utility/random.hpp', - 'utility/stream.cpp', 'utility/stream.hpp', - 'utility/streamUtils.cpp', 'utility/streamUtils.hpp', - 'utility/filteredStream.cpp', 'utility/filteredStream.hpp', - 'utility/inputStream.cpp', 'utility/inputStream.hpp', - 'utility/inputStreamAdapter.cpp', 'utility/inputStreamAdapter.hpp', - 'utility/inputStreamByteBufferAdapter.cpp', 'utility/inputStreamByteBufferAdapter.hpp', - 'utility/inputStreamPointerAdapter.cpp', 'utility/inputStreamPointerAdapter.hpp', - 'utility/inputStreamSocketAdapter.cpp', 'utility/inputStreamSocketAdapter.hpp', - 'utility/inputStreamStringAdapter.cpp', 'utility/inputStreamStringAdapter.hpp', - 'utility/inputStreamStringProxyAdapter.cpp', 'utility/inputStreamStringProxyAdapter.hpp', - 'utility/seekableInputStream.hpp', - 'utility/seekableInputStreamRegionAdapter.cpp', 'utility/seekableInputStreamRegionAdapter.hpp', - 'utility/outputStream.cpp', 'utility/outputStream.hpp', - 'utility/outputStreamAdapter.cpp', 'utility/outputStreamAdapter.hpp', - 'utility/outputStreamByteArrayAdapter.cpp', 'utility/outputStreamByteArrayAdapter.hpp', - 'utility/outputStreamSocketAdapter.cpp', 'utility/outputStreamSocketAdapter.hpp', - 'utility/outputStreamStringAdapter.cpp', 'utility/outputStreamStringAdapter.hpp', - 'utility/parserInputStreamAdapter.cpp', 'utility/parserInputStreamAdapter.hpp', - 'utility/stringProxy.cpp', 'utility/stringProxy.hpp', - 'utility/stringUtils.cpp', 'utility/stringUtils.hpp', - 'utility/url.cpp', 'utility/url.hpp', - 'utility/urlUtils.cpp', 'utility/urlUtils.hpp', - 'utility/sync/autoLock.hpp', - 'utility/sync/criticalSection.cpp', 'utility/sync/criticalSection.hpp', - # -- encoder - 'utility/encoder/encoder.cpp', 'utility/encoder/encoder.hpp', - 'utility/encoder/sevenBitEncoder.cpp', 'utility/encoder/sevenBitEncoder.hpp', - 'utility/encoder/eightBitEncoder.cpp', 'utility/encoder/eightBitEncoder.hpp', - 'utility/encoder/b64Encoder.cpp', 'utility/encoder/b64Encoder.hpp', - 'utility/encoder/binaryEncoder.cpp', 'utility/encoder/binaryEncoder.hpp', - 'utility/encoder/noopEncoder.cpp', 'utility/encoder/noopEncoder.hpp', - 'utility/encoder/encoderFactory.cpp', 'utility/encoder/encoderFactory.hpp', - 'utility/encoder/qpEncoder.cpp', 'utility/encoder/qpEncoder.hpp', - 'utility/encoder/uuEncoder.cpp', 'utility/encoder/uuEncoder.hpp', - # =============================== MDN ================================ - 'mdn/MDNHelper.cpp', 'mdn/MDNHelper.hpp', - 'mdn/MDNInfos.cpp', 'mdn/MDNInfos.hpp', - 'mdn/receivedMDNInfos.cpp', 'mdn/receivedMDNInfos.hpp', - 'mdn/sendableMDNInfos.cpp', 'mdn/sendableMDNInfos.hpp', - # =============================== Misc =============================== - 'misc/importanceHelper.cpp', 'misc/importanceHelper.hpp', - # ============================= Security ============================= - 'security/authenticator.hpp', - 'security/defaultAuthenticator.cpp', 'security/defaultAuthenticator.hpp', - # -- digest - 'security/digest/messageDigest.cpp', 'security/digest/messageDigest.hpp', - 'security/digest/messageDigestFactory.cpp', 'security/digest/messageDigestFactory.hpp', - 'security/digest/md5/md5MessageDigest.cpp', 'security/digest/md5/md5MessageDigest.hpp', - 'security/digest/sha1/sha1MessageDigest.cpp', 'security/digest/sha1/sha1MessageDigest.hpp' -] - -libvmime_security_sasl_sources = [ - 'security/sasl/SASLContext.cpp', 'security/sasl/SASLContext.hpp', - 'security/sasl/SASLSession.cpp', 'security/sasl/SASLSession.hpp', - 'security/sasl/SASLMechanism.hpp', - 'security/sasl/SASLMechanismFactory.cpp', 'security/sasl/SASLMechanismFactory.hpp', - 'security/sasl/SASLSocket.cpp', 'security/sasl/SASLSocket.hpp', - 'security/sasl/SASLAuthenticator.hpp', - 'security/sasl/defaultSASLAuthenticator.cpp', 'security/sasl/defaultSASLAuthenticator.hpp', - 'security/sasl/builtinSASLMechanism.cpp', 'security/sasl/builtinSASLMechanism.hpp' -] - -libvmime_examples_sources = [ - 'examples/README', -# 'examples/Makefile.am', # not generated -# 'examples/Makefile.in', - 'examples/example1.cpp', - 'examples/example2.cpp', - 'examples/example3.cpp', - 'examples/example4.cpp', - 'examples/example5.cpp', - 'examples/example6.cpp', - 'examples/example7.cpp' -] - -libvmime_messaging_sources = [ - 'net/builtinServices.inl', - 'net/connectionInfos.hpp', - 'net/defaultConnectionInfos.cpp', 'net/defaultConnectionInfos.hpp', - 'net/events.cpp', 'net/events.hpp', - 'net/fetchAttributes.cpp', 'net/fetchAttributes.hpp', - 'net/folder.cpp', 'net/folder.hpp', - 'net/folderStatus.hpp', - 'net/message.cpp', 'net/message.hpp', - 'net/messageSet.cpp', 'net/messageSet.hpp', - 'net/securedConnectionInfos.hpp', - 'net/service.cpp', 'net/service.hpp', - 'net/serviceFactory.cpp', 'net/serviceFactory.hpp', - 'net/serviceInfos.cpp', 'net/serviceInfos.hpp', - 'net/serviceRegistration.inl', - 'net/session.cpp', 'net/session.hpp', - 'net/socket.hpp', - 'net/store.hpp', - 'net/timeoutHandler.hpp', - 'net/transport.cpp', 'net/transport.hpp' -] - -libvmime_net_tls_sources = [ - 'net/tls/TLSSession.cpp', 'net/tls/TLSSession.hpp', - 'net/tls/TLSSocket.cpp', 'net/tls/TLSSocket.hpp', - 'net/tls/TLSProperties.cpp', 'net/tls/TLSProperties.hpp', - 'net/tls/gnutls/TLSSession_GnuTLS.cpp', 'net/tls/gnutls/TLSSession_GnuTLS.hpp', - 'net/tls/gnutls/TLSSocket_GnuTLS.cpp', 'net/tls/gnutls/TLSSocket_GnuTLS.hpp', - 'net/tls/gnutls/TLSProperties_GnuTLS.cpp', 'net/tls/gnutls/TLSProperties_GnuTLS.hpp', - 'net/tls/openssl/TLSSession_OpenSSL.cpp', 'net/tls/openssl/TLSSession_OpenSSL.hpp', - 'net/tls/openssl/TLSSocket_OpenSSL.cpp', 'net/tls/openssl/TLSSocket_OpenSSL.hpp', - 'net/tls/openssl/TLSProperties_OpenSSL.cpp', 'net/tls/openssl/TLSProperties_OpenSSL.hpp', - 'net/tls/openssl/OpenSSLInitializer.cpp', 'net/tls/openssl/OpenSSLInitializer.hpp', - 'net/tls/TLSSecuredConnectionInfos.cpp', 'net/tls/TLSSecuredConnectionInfos.hpp', - 'security/cert/certificateChain.cpp', 'security/cert/certificateChain.hpp', - 'security/cert/certificateVerifier.hpp', - 'security/cert/defaultCertificateVerifier.cpp', 'security/cert/defaultCertificateVerifier.hpp', - 'security/cert/certificate.hpp', - 'security/cert/X509Certificate.cpp', 'security/cert/X509Certificate.hpp', - 'security/cert/gnutls/X509Certificate_GnuTLS.cpp', 'security/cert/gnutls/X509Certificate_GnuTLS.hpp', - 'security/cert/openssl/X509Certificate_OpenSSL.cpp', 'security/cert/openssl/X509Certificate_OpenSSL.hpp' -] - -libvmime_messaging_proto_sources = [ - [ - 'pop3', - [ - 'net/pop3/POP3Command.cpp', 'net/pop3/POP3Command.hpp', - 'net/pop3/POP3Connection.cpp', 'net/pop3/POP3Connection.hpp', - 'net/pop3/POP3ServiceInfos.cpp', 'net/pop3/POP3ServiceInfos.hpp', - 'net/pop3/POP3Store.cpp', 'net/pop3/POP3Store.hpp', - 'net/pop3/POP3SStore.cpp', 'net/pop3/POP3SStore.hpp', - 'net/pop3/POP3Folder.cpp', 'net/pop3/POP3Folder.hpp', - 'net/pop3/POP3FolderStatus.cpp', 'net/pop3/POP3FolderStatus.hpp', - 'net/pop3/POP3Message.cpp', 'net/pop3/POP3Message.hpp', - 'net/pop3/POP3Response.cpp', 'net/pop3/POP3Response.hpp', - 'net/pop3/POP3Utils.cpp', 'net/pop3/POP3Utils.hpp' - ] - ], - [ - 'smtp', - [ - 'net/smtp/SMTPChunkingOutputStreamAdapter.cpp', 'net/smtp/SMTPChunkingOutputStreamAdapter.hpp', - 'net/smtp/SMTPCommand.cpp', 'net/smtp/SMTPCommand.hpp', - 'net/smtp/SMTPCommandSet.cpp', 'net/smtp/SMTPCommandSet.hpp', - 'net/smtp/SMTPConnection.cpp', 'net/smtp/SMTPConnection.hpp', - 'net/smtp/SMTPExceptions.cpp', 'net/smtp/SMTPExceptions.hpp', - 'net/smtp/SMTPResponse.cpp', 'net/smtp/SMTPResponse.hpp', - 'net/smtp/SMTPServiceInfos.cpp', 'net/smtp/SMTPServiceInfos.hpp', - 'net/smtp/SMTPTransport.cpp', 'net/smtp/SMTPTransport.hpp', - 'net/smtp/SMTPSTransport.cpp', 'net/smtp/SMTPSTransport.hpp' - ] - ], - [ - 'imap', - [ - 'net/imap/IMAPServiceInfos.cpp', 'net/imap/IMAPServiceInfos.hpp', - 'net/imap/IMAPConnection.cpp', 'net/imap/IMAPConnection.hpp', - 'net/imap/IMAPStore.cpp', 'net/imap/IMAPStore.hpp', - 'net/imap/IMAPSStore.cpp', 'net/imap/IMAPSStore.hpp', - 'net/imap/IMAPFolder.cpp', 'net/imap/IMAPFolder.hpp', - 'net/imap/IMAPFolderStatus.cpp', 'net/imap/IMAPFolderStatus.hpp', - 'net/imap/IMAPMessage.cpp', 'net/imap/IMAPMessage.hpp', - 'net/imap/IMAPMessagePart.cpp', 'net/imap/IMAPMessagePart.hpp', - 'net/imap/IMAPMessagePartContentHandler.cpp', 'net/imap/IMAPMessagePartContentHandler.hpp', - 'net/imap/IMAPMessageStructure.cpp', 'net/imap/IMAPMessageStructure.hpp', - 'net/imap/IMAPTag.cpp', 'net/imap/IMAPTag.hpp', - 'net/imap/IMAPUtils.cpp', 'net/imap/IMAPUtils.hpp', - 'net/imap/IMAPParser.hpp', - ] - ], - [ - 'maildir', - [ - 'net/maildir/maildirServiceInfos.cpp', 'net/maildir/maildirServiceInfos.hpp', - 'net/maildir/maildirStore.cpp', 'net/maildir/maildirStore.hpp', - 'net/maildir/maildirFolder.cpp', 'net/maildir/maildirFolder.hpp', - 'net/maildir/maildirFolderStatus.cpp', 'net/maildir/maildirFolderStatus.hpp', - 'net/maildir/maildirMessage.cpp', 'net/maildir/maildirMessage.hpp', - 'net/maildir/maildirMessagePart.cpp', 'net/maildir/maildirMessagePart.hpp', - 'net/maildir/maildirMessageStructure.cpp', 'net/maildir/maildirMessageStructure.hpp', - 'net/maildir/maildirUtils.cpp', 'net/maildir/maildirUtils.hpp', - 'net/maildir/maildirFormat.cpp', 'net/maildir/maildirFormat.hpp', - 'net/maildir/format/kmailMaildirFormat.cpp', 'net/maildir/format/kmailMaildirFormat.hpp', - 'net/maildir/format/courierMaildirFormat.cpp', 'net/maildir/format/courierMaildirFormat.hpp' - ] - ], - [ - 'sendmail', - [ - 'net/sendmail/sendmailServiceInfos.cpp', 'net/sendmail/sendmailServiceInfos.hpp', - 'net/sendmail/sendmailTransport.cpp', 'net/sendmail/sendmailTransport.hpp' - ] - ] -] - -libvmime_platforms_sources = { - 'posix': - [ - 'platforms/posix/posixChildProcess.cpp', 'platforms/posix/posixChildProcess.hpp', - 'platforms/posix/posixCriticalSection.cpp', 'platforms/posix/posixCriticalSection.hpp', - 'platforms/posix/posixFile.cpp', 'platforms/posix/posixFile.hpp', - 'platforms/posix/posixHandler.cpp', 'platforms/posix/posixHandler.hpp', - 'platforms/posix/posixSocket.cpp', 'platforms/posix/posixSocket.hpp' - ], - 'windows': - [ - 'platforms/windows/windowsCriticalSection.cpp', 'platforms/windows/windowsCriticalSection.hpp', - 'platforms/windows/windowsFile.cpp', 'platforms/windows/windowsFile.hpp', - 'platforms/windows/windowsHandler.cpp', 'platforms/windows/windowsHandler.hpp', - 'platforms/windows/windowsSocket.cpp', 'platforms/windows/windowsSocket.hpp' - ] -} - -libvmime_extra = [ - 'AUTHORS', - 'ChangeLog', - 'COPYING', - 'HACKING', - 'INSTALL', - 'NEWS', - 'README', - 'README.msvc', - 'README.refcounting', - 'SConstruct', - 'vmime.doxygen' -] - -libvmime_tests = [ -# 'tests/Makefile.am', # not generated -# 'tests/Makefile.in', - - # parser -# 'tests/parser/Makefile.am', # not generated -# 'tests/parser/Makefile.in', - - # charset -# 'tests/charset/Makefile.am', # not generated -# 'tests/charset/Makefile.in', - 'tests/charset/main.cpp', - 'tests/charset/run-test.sh', - 'tests/charset/test-suites/gnu.in.utf-8', - 'tests/charset/test-suites/gnu.out.iso-8859-1', -] - -libvmimetest_common = [ - 'tests/testUtils.hpp', - 'tests/net/smtp/SMTPTransportTestUtils.hpp', - 'tests/utility/encoder/encoderTestUtils.hpp' -] - -libvmimetest_sources = [ - 'tests/testRunner.cpp', - 'tests/testUtils.cpp', - # ============================== Parser ============================== - 'tests/parser/attachmentHelperTest.cpp', - 'tests/parser/bodyPartTest.cpp', - 'tests/parser/bodyTest.cpp', - 'tests/parser/charsetTest.cpp', - 'tests/parser/charsetFilteredOutputStreamTest.cpp', - 'tests/parser/datetimeTest.cpp', - 'tests/parser/dispositionTest.cpp', - 'tests/parser/emailAddressTest.cpp', - 'tests/parser/emptyContentHandlerTest.cpp', - 'tests/parser/fileContentHandlerTest.cpp', - 'tests/parser/headerTest.cpp', - 'tests/parser/headerFieldTest.cpp', - 'tests/parser/htmlTextPartTest.cpp', - 'tests/parser/mailboxGroupTest.cpp', - 'tests/parser/mailboxListTest.cpp', - 'tests/parser/mailboxTest.cpp', - 'tests/parser/mediaTypeTest.cpp', - 'tests/parser/messageIdTest.cpp', - 'tests/parser/messageIdSequenceTest.cpp', - 'tests/parser/messageTest.cpp', - 'tests/parser/pathTest.cpp', - 'tests/parser/parameterTest.cpp', - 'tests/parser/streamContentHandlerTest.cpp', - 'tests/parser/stringContentHandlerTest.cpp', - 'tests/parser/textTest.cpp', - 'tests/parser/wordEncoderTest.cpp', - # ============================== Utility ============================= - 'tests/utility/datetimeUtilsTest.cpp', - 'tests/utility/filteredStreamTest.cpp', - 'tests/utility/stringProxyTest.cpp', - 'tests/utility/stringUtilsTest.cpp', - 'tests/utility/pathTest.cpp', - 'tests/utility/urlTest.cpp', - 'tests/utility/encoder/qpEncoderTest.cpp', - 'tests/utility/encoder/b64EncoderTest.cpp', - 'tests/utility/outputStreamStringAdapterTest.cpp', - 'tests/utility/outputStreamSocketAdapterTest.cpp', - 'tests/utility/outputStreamByteArrayAdapterTest.cpp', - 'tests/utility/seekableInputStreamRegionAdapterTest.cpp', - # =============================== Misc =============================== - 'tests/misc/importanceHelperTest.cpp', - # ============================= Security ============================= - 'tests/security/digest/md5Test.cpp', - 'tests/security/digest/sha1Test.cpp', - # =============================== Net ================================ - 'tests/net/messageSetTest.cpp', - 'tests/net/pop3/POP3CommandTest.cpp', - 'tests/net/pop3/POP3ResponseTest.cpp', - 'tests/net/pop3/POP3StoreTest.cpp', - 'tests/net/pop3/POP3UtilsTest.cpp', - 'tests/net/imap/IMAPTagTest.cpp', - 'tests/net/imap/IMAPParserTest.cpp', - 'tests/net/smtp/SMTPTransportTest.cpp', - 'tests/net/smtp/SMTPCommandTest.cpp', - 'tests/net/smtp/SMTPCommandSetTest.cpp', - 'tests/net/smtp/SMTPResponseTest.cpp', - 'tests/net/maildir/maildirStoreTest.cpp' -] - -libvmime_autotools = [ - 'm4/acx_pthread.m4', - 'm4/iconv.m4', - 'm4/lib-ld.m4', - 'm4/lib-link.m4', - 'm4/lib-prefix.m4', - 'm4/libgnutls.m4', - 'autotools/install-sh', -# 'autotools/mkinstalldirs', - 'autotools/missing', - 'autotools/config.guess', - 'autotools/config.sub', - 'autotools/ltmain.sh', -# 'autotools/depcomp', - 'bootstrap', # not generated - 'configure', - 'configure.in', - 'config.h.in', - 'Makefile.am', - 'Makefile.in', - 'src/Makefile.am', - 'src/Makefile.in', - 'vmime/Makefile.am', - 'vmime/Makefile.in' -] - -libvmime_all_sources = [] + libvmime_sources + libvmime_messaging_sources + libvmime_security_sasl_sources + libvmime_net_tls_sources - -for i in range(len(libvmime_all_sources)): - f = libvmime_all_sources[i] - if f[-4:] == '.hpp': - libvmime_all_sources[i] = 'vmime/' + f - else: - libvmime_all_sources[i] = 'src/' + f - -for p in libvmime_messaging_proto_sources: - for f in p[1]: - if f[-4:] == '.hpp': - libvmime_all_sources.append('vmime/' + f) - else: - libvmime_all_sources.append('src/' + f) - -for p in libvmime_platforms_sources: - for f in libvmime_platforms_sources[p]: - if f[-4:] == '.hpp': - libvmime_all_sources.append('vmime/' + f) - else: - libvmime_all_sources.append('src/' + f) - -libvmime_dist_files = libvmime_all_sources + libvmime_extra + libvmime_examples_sources - -libvmime_dist_files += libvmime_tests -libvmime_dist_files += libvmimetest_sources -libvmime_dist_files += libvmimetest_common -libvmime_dist_files += libvmime_autotools - - -################# -# Set options # -################# - -EnsureSConsVersion(0, 98, 1) - -SetOption('implicit_cache', 1) - -try: - Decider('MD5-timestamp') -except: - SourceSignatures('MD5') - TargetSignatures('build') - - -############# -# Options # -############# - -# Try to guess some default values -defaultSendmailPath = WhereIs("sendmail") - -if defaultSendmailPath == None: - defaultSendmailPath = '' - - -# Command line options -opts = Variables('options.cache') - -opts.AddVariables( - ( - 'prefix', - 'Installation prefix directory', - '/usr' - ), - EnumVariable( - 'debug', - 'Debug version (useful for developers only)', - 'yes', - allowed_values = ('yes', 'no'), - map = { }, - ignorecase = 1 - ), - EnumVariable( - 'with_messaging', - 'Messaging support (connection to mail store/transport servers)', - 'yes', - allowed_values = ('yes', 'no'), - map = { }, - ignorecase = 1 - ), - EnumVariable( - 'with_filesystem', - 'Enable file-system support (this is needed for "maildir" messaging support)', - 'yes', - allowed_values = ('yes', 'no'), - map = { }, - ignorecase = 1 - ), - ( - 'with_messaging_protocols', - 'Specifies which protocols to build into the library.\n' - + 'This option has no effect if "with_messaging" is not activated.\n' - + 'Separate protocols with spaces; string must be quoted with ".\n' - + 'Currently available protocols: pop3, smtp, imap, maildir, sendmail.', - '"pop3 smtp imap maildir sendmail"' - ), - ( - 'with_platforms', - 'Specifies which default platform handlers to build.\n' - + 'This provides support for each platform selected.\n' - + 'If no platform handler is available for your platform, you will have\n' - + 'to write your own...\n' - + 'Separate platforms with spaces; string must be quoted with ".\n' - + 'Currently available platform handlers: posix.', - '"posix"' - ), - EnumVariable( - 'with_sasl', - 'Enable SASL support (requires GNU SASL library)', - 'yes', - allowed_values = ('yes', 'no'), - map = { }, - ignorecase = 1 - ), - EnumVariable( - 'with_tls', - 'Enable TLS support (requires GNU TLS library)', - 'yes', - allowed_values = ('yes', 'no'), - map = { }, - ignorecase = 1 - ), - ( - 'sendmail_path', - 'Specifies the path to sendmail.', - defaultSendmailPath - ), - EnumVariable( - 'byte_order', - 'Byte order (Big Endian or Little Endian)', - sys.byteorder, - allowed_values = ('big', 'little'), - map = { }, - ignorecase = 1 - ), - EnumVariable( - 'pf_8bit_type', - 'The C-language 8-bit type for your platform', - 'char', - allowed_values = ('char', 'short', 'int', 'long'), - map = { }, - ignorecase = 1 - ), - EnumVariable( - 'pf_16bit_type', - 'The C-language 16-bit type for your platform', - 'short', - allowed_values = ('char', 'short', 'int', 'long'), - map = { }, - ignorecase = 1 - ), - EnumVariable( - 'pf_32bit_type', - 'The C-language 32-bit type for your platform', - 'int', - allowed_values = ('char', 'short', 'int', 'long'), - map = { }, - ignorecase = 1 - ), - EnumVariable( - 'pf_64bit_type', - 'The C-language 64-bit type for your platform', - 'long', - allowed_values = ('char', 'short', 'int', 'long', 'long long'), - map = { }, - ignorecase = 1 - ), - EnumVariable( - 'build_tests', - 'Build unit tests (run with "scons run-tests")', - 'no', - allowed_values = ('yes', 'no'), - map = { }, - ignorecase = 1 - ) -) - - - -############################### -# Configuration Environment # -############################### - -try: - env = Environment(variables = opts) -except TypeError: - env = Environment(options = opts) - -env.Append(ENV = os.environ) -env.Append(ENV = {'PATH' : os.environ['PATH']}) - -env.Append(CPPPATH = [ '.' ]) - -env.Append(CPPDEFINES = ['_REENTRANT=1']) - -env.Append(CPPDEFINES = ['VMIME_STATIC']) - -env.Append(CXXFLAGS = ['-W']) -env.Append(CXXFLAGS = ['-Wall']) -env.Append(CXXFLAGS = ['-ansi']) -env.Append(CXXFLAGS = ['-pedantic']) -env.Append(CXXFLAGS = ['-Wpointer-arith']) -env.Append(CXXFLAGS = ['-Wold-style-cast']) -env.Append(CXXFLAGS = ['-Wconversion']) -env.Append(CXXFLAGS = ['-Wcast-align']) -env.Append(CXXFLAGS = ['-Wno-long-long']) # OpenSSL -#env.Append(CXXFLAGS = ['-Wshadow']) - -env.Append(TARFLAGS = ['-c']) -env.Append(TARFLAGS = ['--bzip2']) - -if env['debug'] == 'yes': - env.Append(CXXFLAGS = ['-g']) - env.Append(CXXFLAGS = ['-O0']) -else: - env.Append(CXXFLAGS = ['-O2']) - #-fomit-frame-pointer -fmove-all-movables -fstrict-aliasing - -#env.Append(LIBS = ['additional-lib-here']) - -if env['with_sasl'] == 'yes': - libgsasl_pc = string.strip(os.popen("pkg-config --list-all | grep '^libgsasl[ ]' | cut -f 1 -d ' '").read()) - - if len(libgsasl_pc) == 0: - print "ERROR: GNU SASL development package is not installed\n" - Exit(1) - - env.ParseConfig('pkg-config --cflags --libs ' + libgsasl_pc) - -if env['with_tls'] == 'yes': - # GnuTLS - libgnutls_pc = string.strip(os.popen("pkg-config --list-all | grep '^libgnutls[ ]' | cut -f 1 -d ' '").read()) - - if len(libgnutls_pc) == 0: - libgnutls_pc = string.strip(os.popen("pkg-config --list-all | grep '^gnutls[ ]' | cut -f 1 -d ' '").read()) - - if len(libgnutls_pc) == 0: - print "ERROR: GNU TLS development package is not installed\n" - Exit(1) - - env.ParseConfig('pkg-config --cflags --libs ' + libgnutls_pc) - - # OpenSSL - libopenssl_pc = string.strip(os.popen("pkg-config --list-all | grep '^openssl[ ]' | cut -f 1 -d ' '").read()) - - if len(libopenssl_pc) == 0: - print "ERROR: OpenSSL development package is not installed\n" - Exit(1) - - env.ParseConfig('pkg-config --cflags --libs ' + libopenssl_pc) - -env.Append(CXXFLAGS = ['-pthread']) - -# Charset conversion library - -# -- iconv -if sys.platform == "mac" or sys.platform == "darwin": - env.Append(LIBS = ['iconv', 'gcrypt']) - -# -- ICU -env.Append(LIBS = ['icuuc', 'icudata', 'icui18n']) - -# Generate help text for command line options -Help(opts.GenerateHelpText(env)) - -# Cache current options -opts.Save('options.cache', env) - -# Documentation generation system -doxygenBuilder = Builder(action = 'doxygen $SOURCE') -env.Append(BUILDERS = { 'DoxygenDoc' : doxygenBuilder }) - - - -########################## -# Some initializations # -########################## - -# Messaging protocols -messaging_protocols = [ ] - -for proto in re.split('\W+', string.replace(env['with_messaging_protocols'], '"', '')): - proto = string.strip(proto) - if len(proto) >= 1: - messaging_protocols.append(proto) - -# Platforms -platforms = [ ] - -for platform in re.split('\W+', string.replace(env['with_platforms'], '"', '')): - platform = string.strip(platform) - if len(platform) >= 1: - platforms.append(platform) - - - -######################## -# Some sanity checks # -######################## - -def IsProtocolSupported(protoList, proto): - for supportedProto in protoList: - if string.upper(supportedProto) == string.upper(proto): - return 1 - return 0 - - -# File-system support must be activated when 'maildir' protocol is selected -if env['with_messaging'] == 'yes': - if IsProtocolSupported(messaging_protocols, 'maildir'): - if env['with_filesystem'] != 'yes': - print "ERROR: 'maildir' protocol requires file-system support!\n" - Exit(1) - -# Sendmail transport is only available on POSIX platforms -if os.name != 'posix': - if IsProtocolSupported(messaging_protocols, 'sendmail'): - print "WARNING: ignoring 'sendmail' support (only available on POSIX platforms)\n" - - newProtoList = [ ] - - for p in messaging_protocols: - if string.upper(p) != "SENDMAIL": - newProtoList.append(p) - - messaging_protocols = newProtoList - -# Check sendmail path -if IsProtocolSupported(messaging_protocols, 'sendmail'): - if env['sendmail_path'] == '': - print "ERROR: no path specified for 'sendmail'" - Exit(1) - - -########################### -# Configuration summary # -########################### - -print "" -print "+=================+" -print "| CONFIGURATION |" -print "+=================+" -print "" -print "Installation prefix : " + env['prefix'] -print "Debugging mode : " + env['debug'] -print "Messaging support : " + env['with_messaging'] -if env['with_messaging'] == 'yes': - print " * protocols : " + env['with_messaging_protocols'] -print "File-system support : " + env['with_filesystem'] -print "Platform handlers : " + env['with_platforms'] -print "SASL support : " + env['with_sasl'] -print "TLS/SSL support : " + env['with_tls'] - -if IsProtocolSupported(messaging_protocols, 'sendmail'): - print "Sendmail path : " + env['sendmail_path'] - -print "" - - -################################ -# Generate export-static.hpp # -################################ - -export_hpp = open('vmime/export-static.hpp', 'w') - -export_hpp.write(""" -#define VMIME_EXPORT -#define VMIME_NO_EXPORT - -#ifndef VMIME_DEPRECATED -# define VMIME_DEPRECATED __attribute__ ((__deprecated__)) -# define VMIME_DEPRECATED_EXPORT VMIME_EXPORT __attribute__ ((__deprecated__)) -# define VMIME_DEPRECATED_NO_EXPORT VMIME_NO_EXPORT __attribute__ ((__deprecated__)) -#endif -""") - -export_hpp.close() - - -######################### -# Generate config.hpp # -######################### - -config_hpp = open('vmime/config.hpp', 'w') - -config_hpp.write(""" -// -// This file was automatically generated by configuration script. -// - -#ifndef VMIME_CONFIG_HPP_INCLUDED -#define VMIME_CONFIG_HPP_INCLUDED - - -#include "vmime/export.hpp" - - -""") - -config_hpp.write('// Name of package\n') -config_hpp.write('#define VMIME_PACKAGE "' + packageName + '"\n') -config_hpp.write('\n') -config_hpp.write('// Version number of package\n') -config_hpp.write('#define VMIME_VERSION "' + packageVersion + '"\n') -config_hpp.write('#define VMIME_API "' + packageAPI + '"\n') -config_hpp.write('\n') -config_hpp.write('// Target OS and architecture\n') - -if os.name == 'posix': - config_hpp.write('#define VMIME_TARGET_ARCH "' + commands.getoutput('uname -m') + '"\n') - config_hpp.write('#define VMIME_TARGET_OS "' + commands.getoutput('uname -s') + '"\n') -else: - config_hpp.write('#define VMIME_TARGET_ARCH "" // Unknown\n') - config_hpp.write('#define VMIME_TARGET_OS "' + sys.platform + '/' + os.name + '"\n') - -config_hpp.write('\n') -config_hpp.write('// Set to 1 if debugging should be activated\n') - -if env['debug'] == 'yes': - config_hpp.write('#define VMIME_DEBUG 1\n') -else: - config_hpp.write('#define VMIME_DEBUG 0\n') - -config_hpp.write('\n') -config_hpp.write('// Byte order (set one or the other, but not both!)\n') - -if env['byte_order'] == 'big': - config_hpp.write('#define VMIME_BYTE_ORDER_BIG_ENDIAN 1\n') - config_hpp.write('#define VMIME_BYTE_ORDER_LITTLE_ENDIAN 0\n') -else: - config_hpp.write('#define VMIME_BYTE_ORDER_BIG_ENDIAN 0\n') - config_hpp.write('#define VMIME_BYTE_ORDER_LITTLE_ENDIAN 1\n') - -config_hpp.write('\n') -config_hpp.write('// Generic types\n') -config_hpp.write('// -- 8-bit\n') -config_hpp.write('typedef signed ' + env['pf_8bit_type'] + ' vmime_int8;\n') -config_hpp.write('typedef unsigned ' + env['pf_8bit_type'] + ' vmime_uint8;\n') -config_hpp.write('// -- 16-bit\n') -config_hpp.write('typedef signed ' + env['pf_16bit_type'] + ' vmime_int16;\n') -config_hpp.write('typedef unsigned ' + env['pf_16bit_type'] + ' vmime_uint16;\n') -config_hpp.write('// -- 32-bit\n') -config_hpp.write('typedef signed ' + env['pf_32bit_type'] + ' vmime_int32;\n') -config_hpp.write('typedef unsigned ' + env['pf_32bit_type'] + ' vmime_uint32;\n') -config_hpp.write('// -- 64-bit\n') -config_hpp.write('typedef signed ' + env['pf_64bit_type'] + ' vmime_int64;\n') -config_hpp.write('typedef unsigned ' + env['pf_64bit_type'] + ' vmime_uint64;\n') -config_hpp.write('\n') -config_hpp.write('#define VMIME_HAVE_SIZE_T 1\n') -config_hpp.write('\n') - -config_hpp.write('// Charset conversion support\n') -config_hpp.write('#define VMIME_CHARSETCONV_LIB_IS_ICONV 1\n') -config_hpp.write('#define VMIME_CHARSETCONV_LIB_IS_ICU 0\n') -config_hpp.write('\n') - -config_hpp.write('// Options\n') - -config_hpp.write('// -- File-system support\n') -if env['with_filesystem'] == 'yes': - config_hpp.write('#define VMIME_HAVE_FILESYSTEM_FEATURES 1\n') -else: - config_hpp.write('#define VMIME_HAVE_FILESYSTEM_FEATURES 0\n') - -config_hpp.write('// -- SASL support\n') -if env['with_sasl'] == 'yes': - config_hpp.write('#define VMIME_HAVE_SASL_SUPPORT 1\n') -else: - config_hpp.write('#define VMIME_HAVE_SASL_SUPPORT 0\n') - -config_hpp.write('// -- TLS/SSL support\n') -if env['with_tls'] == 'yes': - config_hpp.write('#define VMIME_HAVE_TLS_SUPPORT 1\n') - config_hpp.write('#define VMIME_TLS_SUPPORT_LIB_IS_GNUTLS 1\n') - config_hpp.write('#define VMIME_TLS_SUPPORT_LIB_IS_OPENSSL 0\n') - config_hpp.write('#define VMIME_HAVE_GNUTLS_PRIORITY_FUNCS 1\n') -else: - config_hpp.write('#define VMIME_HAVE_TLS_SUPPORT 0\n') - -config_hpp.write('// -- Messaging support\n') -if env['with_messaging'] == 'yes': - config_hpp.write('#define VMIME_HAVE_MESSAGING_FEATURES 1\n') - - config_hpp.write('// -- Messaging protocols\n') - - for proto in messaging_protocols: - config_hpp.write('#define VMIME_HAVE_MESSAGING_PROTO_' + string.upper(proto) + ' 1\n') - - for p in libvmime_messaging_proto_sources: - proto = p[0] - if not proto in messaging_protocols: - config_hpp.write('#define VMIME_HAVE_MESSAGING_PROTO_' + string.upper(proto) + ' 0\n') -else: - config_hpp.write('#define VMIME_HAVE_MESSAGING_FEATURES 0\n') - -config_hpp.write('// -- Platform-specific code\n') -for platform in platforms: - config_hpp.write('#define VMIME_PLATFORM_IS_' + string.upper(platform) + ' 1\n') - -for platform in libvmime_platforms_sources: - if not platform in platforms: - config_hpp.write('#define VMIME_PLATFORM_IS_' + string.upper(platform) + ' 0\n') - -config_hpp.write(""" -#define VMIME_HAVE_GETADDRINFO 1 -#define VMIME_HAVE_GETNAMEINFO 1 -#define VMIME_HAVE_PTHREAD 1 -#define VMIME_HAVE_GETTID 0 -#define VMIME_HAVE_SYSCALL 1 -#define VMIME_HAVE_SYSCALL_GETTID 1 -#define VMIME_HAVE_LOCALTIME_R 1 -#define VMIME_HAVE_LOCALTIME_S 0 -#define VMIME_HAVE_GMTIME_R 1 -#define VMIME_HAVE_GMTIME_S 0 -""") - -config_hpp.write('\n') -config_hpp.write('// Miscellaneous flags\n') - -if IsProtocolSupported(messaging_protocols, 'sendmail'): - config_hpp.write('#define VMIME_SENDMAIL_PATH "' + env['sendmail_path'] + '"\n') - -config_hpp.write(""" - -#endif // VMIME_CONFIG_HPP_INCLUDED -""") - -config_hpp.close() - - -################# -# Build rules # -################# - -# Build directory -if env['debug'] == 'yes': - BuildDir("#build/debug", 'src', duplicate = 0) - buildDirectory = 'build/debug/' -else: - BuildDir("#build/release", 'src', duplicate = 0) - buildDirectory = 'build/release/' - -# Create effective source files list - -# -- main library -libvmime_sel_sources = [] + libvmime_sources - -# -- messaging module -if env['with_messaging'] == 'yes': - # -- Add common files for messaging support - for file in libvmime_messaging_sources: - libvmime_sel_sources.append(file) - - # -- Add protocol specific source files - for proto in messaging_protocols: - for protosrc in libvmime_messaging_proto_sources: - if protosrc[0] == proto: - for file in protosrc[1]: - libvmime_sel_sources.append(file) - -# -- SASL support -if env['with_sasl'] == 'yes': - for file in libvmime_security_sasl_sources: - libvmime_sel_sources.append(file) - -# -- TLS support -if env['with_tls'] == 'yes': - for file in libvmime_net_tls_sources: - libvmime_sel_sources.append(file) - -# -- platform handlers -for platform in platforms: - files = libvmime_platforms_sources[platform] - - for file in files: - libvmime_sel_sources.append(file) - -# Split source files list into two lists: .CPP and .HPP -libvmime_sources_CPP = [ ] -libvmime_sources_HPP = [ ] - -libvmime_install_includes = [ ] - -for file in libvmime_sel_sources: - slash = string.rfind(file, '/') - dir = '' - - if slash != -1: - dir = file[0:slash] + '/' - - if file[-4:] == '.hpp': - libvmime_sources_HPP.append(buildDirectory + file) - libvmime_install_includes.append([dir, 'vmime/' + file, file]) - else: - if file[-4:] == '.cpp': - libvmime_sources_CPP.append(buildDirectory + file) - -# HACK: SCons does not allow '.' in target name, so we have to -# detect the suffix for library name and add it ourself -#libFoo = env.StaticLibrary(target = 'FOO', source = []) -#libNameSuffix = ''; -# -#if str(libFoo[0]).rfind('.') != -1: -# libNameSuffix = str(libFoo[0])[str(libFoo[0]).rfind('.'):] - -# Static library build -if env['debug'] == 'yes': - libVmime = env.StaticLibrary( - target = packageVersionedGenericName + '-debug', - source = libvmime_sources_CPP - ) -else: - libVmime = env.StaticLibrary( - target = packageVersionedGenericName, - source = libvmime_sources_CPP - ) - -Default(libVmime) - -# Tests -if env['build_tests'] == 'yes': - if env['debug'] == 'yes': - env = env.Clone() - env.Append(LIBS = ['cppunit', 'dl', packageVersionedGenericName + '-debug', 'pthread']) - env.Append(LIBPATH=['.']) - - if sys.platform == "mac" or sys.platform == "darwin": - env.Append(LIBS = ['iconv', 'gcrypt']) - - Default( - env.Program( - target = 'run-tests', - source = libvmimetest_sources - ) - ) - else: - print 'Debug mode must be enabled to build tests!' - Exit(1) - - -################### -# Documentation # -################### - -doxygenDocPath = '(doxygen-generated-files)' - -env.DoxygenDoc(doxygenDocPath, 'vmime.doxygen') -env.Alias('doc', doxygenDocPath) - - -################ -# Unit tests # -################ - -def runTests(target, source, env): - os.system("./run-tests") - return None - - -runTestsBuilder = Builder(action = runTests) -env.Append(BUILDERS = { 'RunTests' : runTestsBuilder }) - -env.Alias('run-tests', env.RunTests('foo', 'SConstruct')) - diff --git a/cmake/Utils.cmake b/cmake/Utils.cmake index 0abf5155..4782f67a 100644 --- a/cmake/Utils.cmake +++ b/cmake/Utils.cmake @@ -1,11 +1,11 @@ # Installing headers and preserving the directory structure # Found here: http://www.semipol.de/archives/251 -MACRO(INSTALL_HEADERS_WITH_DIRECTORY HEADER_LIST COMPONENT_NAME) +MACRO(INSTALL_HEADERS_WITH_DIRECTORY HEADER_LIST COMPONENT_NAME REMOVE_PREFIX) FOREACH(HEADER ${${HEADER_LIST}}) STRING(REGEX MATCH "(.*)[/\\]" DIR ${HEADER}) - STRING(REPLACE "${CMAKE_SOURCE_DIR}/" "" DIR ${DIR}) + STRING(REPLACE "${CMAKE_SOURCE_DIR}/${REMOVE_PREFIX}" "" DIR ${DIR}) INSTALL(FILES ${HEADER} DESTINATION include/${DIR} COMPONENT ${COMPONENT_NAME}) ENDFOREACH(HEADER) diff --git a/examples/README b/examples/README deleted file mode 100644 index 4f58b1fd..00000000 --- a/examples/README +++ /dev/null @@ -1,12 +0,0 @@ -========================================= -Instructions for compiling VMime examples -========================================= - -1) Configure, compile and install vmime library - -2) Compile the sample programs with: - $ g++ -o exampleX exampleX.cpp `pkg-config libvmime` - -3) For a more complete documentation, please visit: - http://www.vmime.org/documentation/ - diff --git a/src/address.cpp b/src/address.cpp deleted file mode 100644 index c6fa74f1..00000000 --- a/src/address.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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::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
parsedAddress; - - if (isGroup) - parsedAddress = make_shared (); - else - parsedAddress = make_shared (); - - parsedAddress->parse(ctx, buffer, start, pos, NULL); - parsedAddress->setParsedBounds(start, pos); - - return (parsedAddress); - } - - return null; -} - - -} // vmime diff --git a/src/addressList.cpp b/src/addressList.cpp deleted file mode 100644 index 5c7d34ac..00000000 --- a/src/addressList.cpp +++ /dev/null @@ -1,305 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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
parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, NULL); - - if (parsedAddress != NULL) - 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 >::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 (other); - - removeAllAddresses(); - - for (std::vector >::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
(other.getMailboxAt(i)->clone())); - - return (*this); -} - - -shared_ptr addressList::clone() const -{ - return make_shared (*this); -} - - -void addressList::appendAddress(shared_ptr
addr) -{ - m_list.push_back(addr); -} - - -void addressList::insertAddressBefore(shared_ptr
beforeAddress, shared_ptr
addr) -{ - const std::vector >::iterator it = std::find - (m_list.begin(), m_list.end(), beforeAddress); - - if (it == m_list.end()) - throw std::out_of_range("Invalid position"); - - m_list.insert(it, addr); -} - - -void addressList::insertAddressBefore(const size_t pos, shared_ptr
addr) -{ - if (pos >= m_list.size()) - throw std::out_of_range("Invalid position"); - - m_list.insert(m_list.begin() + pos, addr); -} - - -void addressList::insertAddressAfter(shared_ptr
afterAddress, shared_ptr
addr) -{ - const std::vector >::iterator it = std::find - (m_list.begin(), m_list.end(), afterAddress); - - if (it == m_list.end()) - throw std::out_of_range("Invalid position"); - - m_list.insert(it + 1, addr); -} - - -void addressList::insertAddressAfter(const size_t pos, shared_ptr
addr) -{ - if (pos >= m_list.size()) - throw std::out_of_range("Invalid position"); - - m_list.insert(m_list.begin() + pos + 1, addr); -} - - -void addressList::removeAddress(shared_ptr
addr) -{ - const std::vector >::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 >::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
addressList::getAddressAt(const size_t pos) -{ - return (m_list[pos]); -} - - -const shared_ptr addressList::getAddressAt(const size_t pos) const -{ - return (m_list[pos]); -} - - -const std::vector > addressList::getAddressList() const -{ - std::vector > list; - - list.reserve(m_list.size()); - - for (std::vector >::const_iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { - list.push_back(*it); - } - - return (list); -} - - -const std::vector > addressList::getAddressList() -{ - return (m_list); -} - - -const std::vector > addressList::getChildComponents() -{ - std::vector > list; - - copy_vector(m_list, list); - - return (list); -} - - -shared_ptr addressList::toMailboxList() const -{ - shared_ptr res = make_shared (); - - for (std::vector >::const_iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { - shared_ptr addr = *it; - - if (addr->isGroup()) - { - const std::vector > mailboxes = - dynamicCast (addr)->getMailboxList(); - - for (std::vector >::const_iterator jt = mailboxes.begin() ; - jt != mailboxes.end() ; ++jt) - { - res->appendMailbox(vmime::clone(*jt)); - } - } - else - { - res->appendMailbox(dynamicCast (addr->clone())); - } - } - - return res; -} - - -} // vmime diff --git a/src/attachmentHelper.cpp b/src/attachmentHelper.cpp deleted file mode 100644 index 152daeed..00000000 --- a/src/attachmentHelper.cpp +++ /dev/null @@ -1,312 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime -{ - - -// static -bool attachmentHelper::isBodyPartAnAttachment - (shared_ptr part, const unsigned int options) -{ - // First, try with "Content-Disposition" field. - // If not present, we will try with "Content-Type" field. - shared_ptr cdf = - part->getHeader()->findField (fields::CONTENT_DISPOSITION); - - if (cdf) - { - const contentDisposition disp = *cdf->getValue (); - - 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() == NULL) - return false; - - return true; - } - - return false; - } - } - - // Assume "attachment" if type is not "text/..." or "multipart/...". - mediaType type; - bool hasContentTypeName = false; - - shared_ptr ctf = - part->getHeader()->findField (fields::CONTENT_TYPE); - - if (ctf) - { - type = *ctf->getValue (); - - 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() == NULL) - 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 attachmentHelper::getBodyPartAttachment - (shared_ptr part, const unsigned int options) -{ - if (!isBodyPartAnAttachment(part, options)) - return null; - - mediaType type; - - shared_ptr ctf = - part->getHeader()->findField (fields::CONTENT_TYPE); - - if (ctf) - { - type = *ctf->getValue (); - } - 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 (part); - } - else - { - return make_shared (part); - } -} - - -// static -const std::vector > - attachmentHelper::findAttachmentsInMessage - (shared_ptr msg, const unsigned int options) -{ - return findAttachmentsInBodyPart(msg, options); -} - - -// static -const std::vector > - attachmentHelper::findAttachmentsInBodyPart - (shared_ptr part, const unsigned int options) -{ - std::vector > atts; - - // Test this part - if (isBodyPartAnAttachment(part, options)) - { - atts.push_back(getBodyPartAttachment(part, options)); - } - // Find in sub-parts - else - { - shared_ptr bdy = part->getBody(); - - for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) - { - std::vector > partAtts = - findAttachmentsInBodyPart(bdy->getPartAt(i), options); - - std::copy(partAtts.begin(), partAtts.end(), std::back_inserter(atts)); - } - } - - return atts; -} - - -// static -void attachmentHelper::addAttachment(shared_ptr msg, shared_ptr 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 part = findBodyPart(msg, mpMixed); - - if (part == NULL) // 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 container = make_shared (); - - 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 > 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 child = make_shared (); - - 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 ()); - - 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 attachmentHelper::findBodyPart - (shared_ptr part, const mediaType& type) -{ - if (part->getBody()->getContentType() == type) - return part; - - // Try in sub-parts - shared_ptr bdy = part->getBody(); - - for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) - { - shared_ptr found = - findBodyPart(bdy->getPartAt(i), type); - - if (found != NULL) - return found; - } - - return null; -} - - -// static -void attachmentHelper::addAttachment(shared_ptr msg, shared_ptr amsg) -{ - shared_ptr att = make_shared (amsg); - addAttachment(msg, att); -} - - -} // vmime - diff --git a/src/base.cpp b/src/base.cpp deleted file mode 100644 index 9f9a87be..00000000 --- a/src/base.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 ::max(); -} - - -const size_t npos = std::numeric_limits ::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). -// - -class initializer -{ -public: - - 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/src/body.cpp b/src/body.cpp deleted file mode 100644 index 8f5401cf..00000000 --- a/src/body.cpp +++ /dev/null @@ -1,1050 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 ()) -{ -} - - -body::~body() -{ -} - - -// static -size_t body::findNextBoundaryPosition - (shared_ptr parser, const string& boundary, - const size_t position, const size_t end, - size_t* boundaryStart, size_t* boundaryEnd) -{ - size_t pos = position; - - while (pos != npos && pos < end) - { - pos = parser->findNext(boundary, pos); - - if (pos == npos) - break; // not found - - if (pos != 0) - { - // Skip transport padding bytes (SPACE or HTAB), if any - size_t advance = 0; - - while (pos != 0) - { - parser->seek(pos - advance - 1); - - const byte_t c = parser->peekByte(); - - if (c == ' ' || c == '\t') - ++advance; - else - break; - } - - // Ensure the bytes before boundary are "[LF]--": boundary should be - // at the beginning of a line, and should start with "--" - if (pos - advance >= 3) - { - parser->seek(pos - advance - 3); - - if (parser->matchBytes("\n--", 3)) - { - parser->seek(pos + boundary.length()); - - const byte_t next = parser->peekByte(); - - // Boundary should be followed by a new line or a dash - if (next == '\r' || next == '\n' || next == '-') - { - // Get rid of the "[CR]" just before "[LF]--", if any - if (pos - advance >= 4) - { - parser->seek(pos - advance - 4); - - if (parser->peekByte() == '\r') - advance++; - } - - *boundaryStart = pos - advance - 3; - *boundaryEnd = pos + boundary.length(); - - return pos; - } - } - } - } - - // Boundary is a prefix of another, continue the search - pos++; - } - - return pos; -} - - -void body::parseImpl - (const parsingContext& /* ctx */, - shared_ptr 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 ctf = - m_part->getHeader()->findField (fields::CONTENT_TYPE); - - if (ctf) - { - const mediaType type = *ctf->getValue (); - - 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 #1521, Page 31: - // "...(If a boundary 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; - } - - if (index == 0) - { - if (partEnd > partStart) - { - vmime::text text; - text.parse(parser, partStart, partEnd); - - m_prologText = text.getWholeBuffer(); - } - else - { - m_prologText = ""; - } - } - else // index > 0 - { - shared_ptr 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(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 (); - - // Last part was not found: recover from missing boundary - if (!lastPart && pos == npos) - { - shared_ptr part = m_part->createChildPart(); - - try - { - part->parse(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(parser, partStart, end); - - m_epilogText = text.getWholeBuffer(); - } - } - // Treat the contents as 'simple' data - else - { - encoding enc; - - shared_ptr cef = - m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING); - - if (cef) - { - enc = *cef->getValue (); - } - else - { - // Defaults to "7bit" (RFC-1521) - enc = vmime::encoding(encodingTypes::SEVEN_BIT); - } - - // Extract the (encoded) contents - const size_t length = end - position; - - shared_ptr contentStream = - make_shared - (parser->getUnderlyingStream(), position, length); - - m_contents = make_shared (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 ctf = - m_part->getHeader()->findField (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 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 - { - shared_ptr srcEncoder = m_contents->getEncoding().getEncoder(); - shared_ptr 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 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 (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 (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 ctf = - dynamicCast (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 ctf = - m_part->getHeader()->findField (fields::CONTENT_TYPE); - - if (ctf) - { - return *ctf->getValue (); - } - else - { - // Defaults to "text/plain" (RFC-1521) - return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); - } -} - - -void body::setCharset(const charset& chset) -{ - shared_ptr ctf = - m_part->getHeader()->findField (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 ctf = - m_part->getHeader()->findField (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 cef = - m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING); - - if (cef) - { - return *cef->getValue (); - } - 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 >::iterator it = m_parts.begin() ; - it != m_parts.end() ; ++it) - { - shared_ptr childPart = *it; - parent->importChildPart(childPart); - } -} - - -bool body::isRootPart() const -{ - return (m_part == NULL || m_part->getParentPart() == NULL); -} - - -shared_ptr body::clone() const -{ - shared_ptr bdy = make_shared (); - - bdy->copyFrom(*this); - - return (bdy); -} - - -void body::copyFrom(const component& other) -{ - const body& bdy = dynamic_cast (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 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 body::getContents() const -{ - return (m_contents); -} - - -void body::setContents(shared_ptr contents) -{ - m_contents = contents; -} - - -void body::setContents(shared_ptr contents, const mediaType& type) -{ - m_contents = contents; - - setContentType(type); -} - - -void body::setContents(shared_ptr contents, const mediaType& type, const charset& chset) -{ - m_contents = contents; - - setContentType(type, chset); -} - - -void body::setContents(shared_ptr contents, const mediaType& type, - const charset& chset, const encoding& enc) -{ - m_contents = contents; - - setContentType(type, chset); - setEncoding(enc); -} - - -void body::initNewPart(shared_ptr 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 != NULL) - { - m_part->importChildPart(part); - - shared_ptr
hdr = m_part->getHeader(); - - // Check whether we have a boundary string - shared_ptr ctf = - hdr->findField (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 ()->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 (fields::CONTENT_TYPE); - - ctf->setValue(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED)); - ctf->setBoundary(generateRandomBoundaryString()); - } - } -} - - -void body::appendPart(shared_ptr part) -{ - initNewPart(part); - - m_parts.push_back(part); -} - - -void body::insertPartBefore(shared_ptr beforePart, shared_ptr part) -{ - initNewPart(part); - - const std::vector >::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, shared_ptr part) -{ - initNewPart(part); - - m_parts.insert(m_parts.begin() + pos, part); -} - - -void body::insertPartAfter(shared_ptr afterPart, shared_ptr part) -{ - initNewPart(part); - - const std::vector >::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, shared_ptr part) -{ - initNewPart(part); - - m_parts.insert(m_parts.begin() + pos + 1, part); -} - - -void body::removePart(shared_ptr part) -{ - const std::vector >::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 body::getPartAt(const size_t pos) -{ - return (m_parts[pos]); -} - - -const shared_ptr body::getPartAt(const size_t pos) const -{ - return (m_parts[pos]); -} - - -const std::vector > body::getPartList() const -{ - std::vector > list; - - list.reserve(m_parts.size()); - - for (std::vector >::const_iterator it = m_parts.begin() ; - it != m_parts.end() ; ++it) - { - list.push_back(*it); - } - - return (list); -} - - -const std::vector > body::getPartList() -{ - return (m_parts); -} - - -const std::vector > body::getChildComponents() -{ - std::vector > list; - - copy_vector(m_parts, list); - - return (list); -} - - -} // vmime diff --git a/src/bodyPart.cpp b/src/bodyPart.cpp deleted file mode 100644 index 12896f84..00000000 --- a/src/bodyPart.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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
()), - m_body(make_shared ()), - m_parent() -{ - m_body->setParentPart(this); -} - - -void bodyPart::parseImpl - (const parsingContext& ctx, shared_ptr 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 bodyPart::clone() const -{ - shared_ptr p = make_shared (); - - 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 (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 bodyPart::getHeader() const -{ - return (m_header); -} - - -shared_ptr
bodyPart::getHeader() -{ - return (m_header); -} - - -void bodyPart::setHeader(shared_ptr
h) -{ - m_header = h; -} - - -const shared_ptr bodyPart::getBody() const -{ - return (m_body); -} - - -shared_ptr bodyPart::getBody() -{ - return (m_body); -} - - -void bodyPart::setBody(shared_ptr b) -{ - bodyPart* oldPart = b->m_part; - - m_body = b; - m_body->setParentPart(this); - - // A body is associated to one and only one part - if (oldPart != NULL) - oldPart->setBody(make_shared ()); -} - - -bodyPart* bodyPart::getParentPart() -{ - return m_parent; -} - - -const bodyPart* bodyPart::getParentPart() const -{ - return m_parent; -} - - -shared_ptr bodyPart::createChildPart() -{ - shared_ptr part = make_shared (); - part->m_parent = this; - - return part; -} - - -void bodyPart::importChildPart(shared_ptr part) -{ - part->m_parent = this; -} - - -const std::vector > bodyPart::getChildComponents() -{ - std::vector > list; - - list.push_back(m_header); - list.push_back(m_body); - - return (list); -} - - -} // vmime - diff --git a/src/bodyPartAttachment.cpp b/src/bodyPartAttachment.cpp deleted file mode 100644 index 0684a896..00000000 --- a/src/bodyPartAttachment.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr part) - : m_part(part) -{ -} - - -const mediaType bodyPartAttachment::getType() const -{ - shared_ptr ctf = getContentType(); - - if (ctf) - { - return *ctf->getValue (); - } - 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 cdf = getContentDisposition(); - - if (cdf && cdf->hasFilename()) - { - name = cdf->getFilename(); - } - // Try the 'name' parameter of 'Content-Type' field - else - { - shared_ptr ctf = getContentType(); - - if (ctf) - { - shared_ptr prm = ctf->findParameter("name"); - - if (prm != NULL) - name = prm->getValue(); - } - } - - return name; -} - - -const text bodyPartAttachment::getDescription() const -{ - text description; - - shared_ptr cd = - getHeader()->findField(fields::CONTENT_DESCRIPTION); - - if (cd) - { - description = *cd->getValue (); - } - else - { - // No description available. - } - - return description; -} - - -const encoding bodyPartAttachment::getEncoding() const -{ - return m_part->getBody()->getEncoding(); -} - - -const shared_ptr bodyPartAttachment::getData() const -{ - return m_part->getBody()->getContents(); -} - - -shared_ptr bodyPartAttachment::getPart() const -{ - return m_part; -} - - -shared_ptr bodyPartAttachment::getHeader() const -{ - return m_part->getHeader(); -} - - -shared_ptr bodyPartAttachment::getContentDisposition() const -{ - return getHeader()->findField (fields::CONTENT_DISPOSITION); -} - - -shared_ptr bodyPartAttachment::getContentType() const -{ - return getHeader()->findField (fields::CONTENT_TYPE); -} - - -void bodyPartAttachment::generateIn(shared_ptr /* parent */) const -{ - // Not used -} - - -} // vmime - diff --git a/src/charset.cpp b/src/charset.cpp deleted file mode 100644 index 22bff301..00000000 --- a/src/charset.cpp +++ /dev/null @@ -1,210 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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 conv = charsetConverter::create(source, dest, opts); - conv->convert(in, out); -} - - -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 charset::clone() const -{ - return make_shared (m_name); -} - - -const string& charset::getName() const -{ - return (m_name); -} - - -void charset::copyFrom(const component& other) -{ - m_name = dynamic_cast (other).m_name; -} - - -const std::vector > charset::getChildComponents() -{ - return std::vector >(); -} - - - -// 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/src/charsetConverter.cpp b/src/charsetConverter.cpp deleted file mode 100644 index 87886823..00000000 --- a/src/charsetConverter.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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::create - (const charset& source, const charset& dest, - const charsetConverterOptions& opts) -{ - if (source == "idna" || dest == "idna") - return make_shared (source, dest, opts); - else - return createGenericConverter(source, dest, opts); -} - - -} // vmime diff --git a/src/charsetConverterOptions.cpp b/src/charsetConverterOptions.cpp deleted file mode 100644 index caeacd01..00000000 --- a/src/charsetConverterOptions.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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() - : invalidSequence("?") -{ -} - - -} // vmime diff --git a/src/charsetConverter_iconv.cpp b/src/charsetConverter_iconv.cpp deleted file mode 100644 index 75d7b170..00000000 --- a/src/charsetConverter_iconv.cpp +++ /dev/null @@ -1,475 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - #include - - // 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 (ptr)) { } - - operator const char**() { return m_ptr; } - operator char**() { return const_cast (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 (ptr)) { } - - operator char**() { return m_ptr; } - - private: - - char** m_ptr; - }; - -#endif // VMIME_BUILDING_DOC -} - - - -// Output replacement char when an invalid sequence is encountered -template -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 (-1)) - { - out.write(invalidCharOutBuffer, 16 - invalidCharOutLen); - } -} - - - -namespace vmime -{ - - -// static -shared_ptr charsetConverter::createGenericConverter - (const charset& source, const charset& dest, - const charsetConverterOptions& opts) -{ - return make_shared (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 (-1)) - { - iconv_t* p = new iconv_t; - *p= cd; - - m_desc = p; - } -} - - -charsetConverter_iconv::~charsetConverter_iconv() -{ - if (m_desc != NULL) - { - // Close iconv handle - iconv_close(*static_cast (m_desc)); - - delete static_cast (m_desc); - m_desc = NULL; - } -} - - -void charsetConverter_iconv::convert(utility::inputStream& in, utility::outputStream& out) -{ - if (m_desc == NULL) - throw exceptions::charset_conv_error("Cannot initialize converter."); - - const iconv_t cd = *static_cast (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 (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 (-1)) - { - // 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); - - // 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 (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 (inPtr), inBuffer + sizeof(inBuffer), inBuffer); - inPos = inLength; - - if (errno != E2BIG) - prevIsInvalid = true; - } - } - else - { - // Write successfully converted bytes - out.write(outBuffer, sizeof(outBuffer) - outLength); - - 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) -{ - if (m_source == m_dest) - { - // No conversion needed - out = in; - return; - } - - out.clear(); - - utility::inputStreamStringAdapter is(in); - utility::outputStreamStringAdapter os(out); - - convert(is, os); - - os.flush(); -} - - -shared_ptr charsetConverter_iconv::getFilteredOutputStream(utility::outputStream& os) -{ - return make_shared (m_source, m_dest, &os); -} - - - -// charsetFilteredOutputStream_iconv - -namespace utility { - - -charsetFilteredOutputStream_iconv::charsetFilteredOutputStream_iconv - (const charset& source, const charset& dest, outputStream* os) - : m_desc(NULL), m_sourceCharset(source), m_destCharset(dest), - m_stream(*os), m_unconvCount(0) -{ - // Get an iconv descriptor - const iconv_t cd = iconv_open(dest.getName().c_str(), source.getName().c_str()); - - if (cd != reinterpret_cast (-1)) - { - iconv_t* p = new iconv_t; - *p= cd; - - m_desc = p; - } -} - - -charsetFilteredOutputStream_iconv::~charsetFilteredOutputStream_iconv() -{ - if (m_desc != NULL) - { - // Close iconv handle - iconv_close(*static_cast (m_desc)); - - delete static_cast (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 == NULL) - throw exceptions::charset_conv_error("Cannot initialize converter."); - - const iconv_t cd = *static_cast (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)) - { - 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 (-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 (-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 == NULL) - throw exceptions::charset_conv_error("Cannot initialize converter."); - - const iconv_t cd = *static_cast (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 (-1)) - { - const size_t inputConverted = inLength0 - inLength; - - // Skip a "blocking" character - if (inputConverted == 0) - { - 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/src/charsetConverter_icu.cpp b/src/charsetConverter_icu.cpp deleted file mode 100644 index 3374d448..00000000 --- a/src/charsetConverter_icu.cpp +++ /dev/null @@ -1,408 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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" - - -extern "C" -{ -#ifndef VMIME_BUILDING_DOC - - #include - #include - -#endif // VMIME_BUILDING_DOC -} - - -#include - - -namespace vmime -{ - - -// static -shared_ptr charsetConverter::createGenericConverter - (const charset& source, const charset& dest, - const charsetConverterOptions& opts) -{ - return make_shared (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 (err != U_ZERO_ERROR) - { - throw exceptions::charset_conv_error - ("Cannot initialize ICU converter for source charset '" + source.getName() + "'."); - } - - m_to = ucnv_open(dest.getName().c_str(), &err); - - if (err != U_ZERO_ERROR) - { - throw exceptions::charset_conv_error - ("Cannot initialize ICU converter for destination charset '" + dest.getName() + "'."); - } -} - - -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) -{ - UErrorCode err = U_ZERO_ERROR; - - // From buffers - byte_t cpInBuffer[16]; // stream data put here - size_t outSize = ucnv_getMinCharSize(m_from) * sizeof(cpInBuffer) * sizeof(UChar); - UChar* uOutBuffer = new UChar[outSize]; // Unicode chars end up here - - // Auto delete Unicode char buffer - std::auto_ptr cleanup(uOutBuffer); - - // To buffers - // converted (char) data end up here - size_t cpOutBufferSz = ucnv_getMaxCharSize(m_to) * outSize; - char* cpOutBuffer = new char[cpOutBufferSz]; - std::auto_ptr cleanupOut(cpOutBuffer); - - // 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 setting replacement char."); - - // 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 (&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; - UChar* targetLimit = target + outSize; - - toErr = U_ZERO_ERROR; - ucnv_toUnicode(m_from, &target, targetLimit, - &source, sourceLimit, NULL, flush, &toErr); - - if (toErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(toErr)) - 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; - UChar* uSourceLimit = target; - UErrorCode fromErr; - - // Loop until converted chars are fully written - do - { - char* cpTarget = &cpOutBuffer[0]; - const char* cpTargetLimit = cpOutBuffer + cpOutBufferSz; - - fromErr = U_ZERO_ERROR; - - // Write converted bytes (Unicode) to destination codepage - ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit, - &uSource, uSourceLimit, NULL, flush, &fromErr); - - if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) - throw exceptions::charset_conv_error("[ICU] Error converting from Unicode to " + m_dest.getName()); - - // Write to destination stream - out.write(cpOutBuffer, (cpTarget - cpOutBuffer)); - - } while (fromErr == U_BUFFER_OVERFLOW_ERROR); - - } while (toErr == U_BUFFER_OVERFLOW_ERROR); - } -} - - -void charsetConverter_icu::convert(const string& in, string& out) -{ - if (m_source == m_dest) - { - // No conversion needed - out = in; - return; - } - - out.clear(); - - utility::inputStreamStringAdapter is(in); - utility::outputStreamStringAdapter os(out); - - convert(is, os); - - os.flush(); -} - - -shared_ptr charsetConverter_icu::getFilteredOutputStream(utility::outputStream& os) -{ - return make_shared (m_source, m_dest, &os); -} - - - -// charsetFilteredOutputStream_icu - -namespace utility { - - -charsetFilteredOutputStream_icu::charsetFilteredOutputStream_icu - (const charset& source, const charset& dest, outputStream* os) - : m_from(NULL), m_to(NULL), m_sourceCharset(source), m_destCharset(dest), m_stream(*os) -{ - UErrorCode err = U_ZERO_ERROR; - m_from = ucnv_open(source.getName().c_str(), &err); - - if (err != U_ZERO_ERROR) - { - throw exceptions::charset_conv_error - ("Cannot initialize ICU converter for source charset '" + source.getName() + "'."); - } - - m_to = ucnv_open(dest.getName().c_str(), &err); - - if (err != U_ZERO_ERROR) - { - throw exceptions::charset_conv_error - ("Cannot initialize ICU converter for destination charset '" + dest.getName() + "'."); - } - - // Set replacement chars for when converting from Unicode to codepage - icu::UnicodeString substString(vmime::charsetConverterOptions().invalidSequence.c_str()); - ucnv_setSubstString(m_to, substString.getTerminatedBuffer(), -1, &err); - - if (U_FAILURE(err)) - throw exceptions::charset_conv_error("[ICU] Error setting replacement char."); -} - - -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 == NULL || m_to == NULL) - throw exceptions::charset_conv_error("Cannot initialize converters."); - - // Allocate buffer for Unicode chars - size_t uniSize = ucnv_getMinCharSize(m_from) * count * sizeof(UChar); - UChar* uniBuffer = new UChar[uniSize]; - std::auto_ptr uniCleanup(uniBuffer); // auto delete Unicode buffer - - // Conversion loop - UErrorCode toErr = U_ZERO_ERROR; - - const char* uniSource = reinterpret_cast (data); - const char* uniSourceLimit = uniSource + count; - - do - { - // Convert from source charset to Unicode - UChar* uniTarget = uniBuffer; - UChar* uniTargetLimit = uniBuffer + 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) - { - throw exceptions::charset_conv_error - ("[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'."); - } - - const size_t uniLength = uniTarget - uniBuffer; - - // Allocate buffer for destination charset - size_t cpSize = ucnv_getMinCharSize(m_to) * uniLength; - char* cpBuffer = new char[cpSize]; - std::auto_ptr cpCleanup(cpBuffer); // auto delete CP buffer - - // Convert from Unicode to destination charset - UErrorCode fromErr = U_ZERO_ERROR; - - const UChar* cpSource = uniBuffer; - const UChar* cpSourceLimit = uniBuffer + uniLength; - - do - { - char* cpTarget = cpBuffer; - char* cpTargetLimit = cpBuffer + 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)) - { - throw exceptions::charset_conv_error - ("[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'."); - } - - const size_t cpLength = cpTarget - cpBuffer; - - // Write successfully converted bytes - m_stream.write(cpBuffer, cpLength); - - } while (fromErr == U_BUFFER_OVERFLOW_ERROR); - - } while (toErr == U_BUFFER_OVERFLOW_ERROR); -} - - -void charsetFilteredOutputStream_icu::flush() -{ - if (m_from == NULL || m_to == NULL) - throw exceptions::charset_conv_error("Cannot initialize converters."); - - // Allocate buffer for Unicode chars - size_t uniSize = ucnv_getMinCharSize(m_from) * 1024 * sizeof(UChar); - UChar* uniBuffer = new UChar[uniSize]; - std::auto_ptr uniCleanup(uniBuffer); // auto delete Unicode buffer - - // 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; - UChar* uniTargetLimit = uniBuffer + 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; - - // Allocate buffer for destination charset - size_t cpSize = ucnv_getMinCharSize(m_to) * uniLength; - char* cpBuffer = new char[cpSize]; - std::auto_ptr cpCleanup(cpBuffer); // auto delete CP buffer - - // Convert from Unicode to destination charset - UErrorCode fromErr = U_ZERO_ERROR; - - const UChar* cpSource = uniBuffer; - const UChar* cpSourceLimit = uniBuffer + uniLength; - - do - { - char* cpTarget = cpBuffer; - char* cpTargetLimit = cpBuffer + 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; - - // Write successfully converted bytes - m_stream.write(cpBuffer, 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/src/charsetConverter_idna.cpp b/src/charsetConverter_idna.cpp deleted file mode 100644 index aea6eca7..00000000 --- a/src/charsetConverter_idna.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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) -{ - // 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); - - out << outStr; -} - - -void charsetConverter_idna::convert(const string& in, string& out) -{ - if (m_source == m_dest) - { - // No conversion needed - out = in; - return; - } - - out.clear(); - - if (m_dest == "idna") - { - if (utility::stringUtils::is7bit(in)) - { - // 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 unichars; - unichars.reserve(inUTF8.length()); - - while (ch < end) - { - const utf8::uint32_t uc = utf8::unchecked::next(ch); - unichars.push_back(uc); - } - - std::vector output(inUTF8.length() * 2); - punycode_uint outputLen = output.size(); - - const punycode_status status = punycode_encode - (unichars.size(), &unichars[0], /* case_flags */ NULL, &outputLen, &output[0]); - - if (status == punycode_success) - { - out = string("xn--") + string(output.begin(), output.begin() + outputLen); - } - else - { - // TODO - } - } - else if (m_source == "idna") - { - if (in.length() < 5 || in.substr(0, 4) != "xn--") - { - // Not an IDNA string - out = in; - return; - } - - std::vector output(in.length() - 4); - punycode_uint outputLen = output.size(); - - const punycode_status status = punycode_decode - (in.length() - 4, &in[4], &outputLen, &output[0], /* case_flags */ NULL); - - if (status == punycode_success) - { - std::vector outUTF8Bytes(outputLen * 4); - char* p = &outUTF8Bytes[0]; - - for (std::vector ::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); - } - else - { - // TODO - } - } -} - - -shared_ptr charsetConverter_idna::getFilteredOutputStream(utility::outputStream& /* os */) -{ - return null; -} - - -} // vmime diff --git a/src/component.cpp b/src/component.cpp deleted file mode 100644 index 46ff4036..00000000 --- a/src/component.cpp +++ /dev/null @@ -1,244 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime -{ - - -component::component() - : m_parsedOffset(0), m_parsedLength(0) -{ -} - - -component::~component() -{ -} - - -void component::parse - (shared_ptr inputStream, const size_t length) -{ - parse(inputStream, 0, length, NULL); -} - - -void component::parse - (shared_ptr inputStream, const size_t position, - const size_t end, size_t* newPosition) -{ - parse(parsingContext::getDefaultContext(), inputStream, position, end, newPosition); -} - - -void component::parse - (const parsingContext& ctx, - shared_ptr inputStream, const size_t position, - const size_t end, size_t* newPosition) -{ - m_parsedOffset = m_parsedLength = 0; - - shared_ptr seekableStream = - dynamicCast (inputStream); - - if (seekableStream == NULL || 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 parser = - make_shared (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 > children = getChildComponents(); - - for (size_t i = 0, n = children.size() ; i < n ; ++i) - children[i]->offsetParsedBounds(offset); -} - - -void component::parseImpl - (const parsingContext& ctx, shared_ptr 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 != NULL) - *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 stream = - make_shared (buffer); - - shared_ptr parser = - make_shared (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 > children = getChildComponents(); - size_t totalSize = 0; - - for (std::vector >::iterator it = children.begin() ; it != children.end() ; ++it) - totalSize += (*it)->getGeneratedSize(ctx); - - return totalSize; -} - - -} // vmime - diff --git a/src/constants.cpp b/src/constants.cpp deleted file mode 100644 index 3b0a54c0..00000000 --- a/src/constants.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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"; -} - - -} // vmime diff --git a/src/contentDisposition.cpp b/src/contentDisposition.cpp deleted file mode 100644 index 3cf92e27..00000000 --- a/src/contentDisposition.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 contentDisposition::clone() const -{ - return make_shared (*this); -} - - -void contentDisposition::copyFrom(const component& other) -{ - const contentDisposition& d = dynamic_cast (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 > contentDisposition::getChildComponents() -{ - return std::vector >(); -} - - -} // vmime diff --git a/src/contentDispositionField.cpp b/src/contentDispositionField.cpp deleted file mode 100644 index 5a9c1212..00000000 --- a/src/contentDispositionField.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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&) - : headerField(), parameterizedHeaderField() -{ -} - - -bool contentDispositionField::hasCreationDate() const -{ - return findParameter("creation-date"); -} - - -const datetime contentDispositionField::getCreationDate() const -{ - shared_ptr param = findParameter("creation-date"); - - if (param) - return param->getValueAs (); - else - return datetime::now(); -} - - -void contentDispositionField::setCreationDate(const datetime& creationDate) -{ - getParameter("creation-date")->setValue(creationDate); -} - - -bool contentDispositionField::hasModificationDate() const -{ - return findParameter("modification-date"); -} - - -const datetime contentDispositionField::getModificationDate() const -{ - shared_ptr param = findParameter("modification-date"); - - if (param) - return param->getValueAs (); - else - return datetime::now(); -} - - -void contentDispositionField::setModificationDate(const datetime& modificationDate) -{ - getParameter("modification-date")->setValue(modificationDate); -} - - -bool contentDispositionField::hasReadDate() const -{ - return findParameter("read-date"); -} - - -const datetime contentDispositionField::getReadDate() const -{ - shared_ptr param = findParameter("read-date"); - - if (param) - return param->getValueAs (); - else - return datetime::now(); -} - - -void contentDispositionField::setReadDate(const datetime& readDate) -{ - getParameter("read-date")->setValue(readDate); -} - - -bool contentDispositionField::hasFilename() const -{ - return findParameter("filename"); -} - - -const word contentDispositionField::getFilename() const -{ - shared_ptr 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 findParameter("size"); -} - - -const string contentDispositionField::getSize() const -{ - shared_ptr 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/src/contentHandler.cpp b/src/contentHandler.cpp deleted file mode 100644 index 3afe4324..00000000 --- a/src/contentHandler.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/contentTypeField.cpp b/src/contentTypeField.cpp deleted file mode 100644 index 9f38294a..00000000 --- a/src/contentTypeField.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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&) - : headerField(), parameterizedHeaderField() -{ -} - - -bool contentTypeField::hasBoundary() const -{ - return findParameter("boundary"); -} - - -const string contentTypeField::getBoundary() const -{ - shared_ptr 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 findParameter("charset"); -} - - -const charset contentTypeField::getCharset() const -{ - shared_ptr param = findParameter("charset"); - - if (param) - return param->getValueAs (); - else - return charset(); -} - - -void contentTypeField::setCharset(const charset& ch) -{ - getParameter("charset")->setValue(ch); -} - - -bool contentTypeField::hasReportType() const -{ - return findParameter("report-type"); -} - - -const string contentTypeField::getReportType() const -{ - shared_ptr 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/src/context.cpp b/src/context.cpp deleted file mode 100644 index 07fe4875..00000000 --- a/src/context.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/dateTime.cpp b/src/dateTime.cpp deleted file mode 100644 index eca8e785..00000000 --- a/src/dateTime.cpp +++ /dev/null @@ -1,894 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#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 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 (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 datetime::clone() const -{ - return make_shared (*this); -} - - -const std::vector > datetime::getChildComponents() -{ - return std::vector >(); -} - - -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/src/defaultAttachment.cpp b/src/defaultAttachment.cpp deleted file mode 100644 index 8f8ad453..00000000 --- a/src/defaultAttachment.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr data, - const encoding& enc, const mediaType& type, const text& desc, const word& name) - : m_type(type), m_desc(desc), m_data(data), m_encoding(enc), m_name(name) -{ -} - - -defaultAttachment::defaultAttachment(shared_ptr 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(shared_ptr parent) const -{ - // Create and append a new part for this attachment - shared_ptr part = make_shared (); - parent->getBody()->appendPart(part); - - generatePart(part); -} - - -void defaultAttachment::generatePart(shared_ptr 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 (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 defaultAttachment::getData() const -{ - return m_data; -} - - -const encoding defaultAttachment::getEncoding() const -{ - return m_encoding; -} - - -shared_ptr defaultAttachment::getPart() const -{ - return null; -} - - -shared_ptr defaultAttachment::getHeader() const -{ - return null; -} - - -} // vmime diff --git a/src/disposition.cpp b/src/disposition.cpp deleted file mode 100644 index 352d3251..00000000 --- a/src/disposition.cpp +++ /dev/null @@ -1,329 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 disposition::clone() const -{ - shared_ptr disp = make_shared (); - - 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 (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 > disposition::getChildComponents() -{ - return std::vector >(); -} - - -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 ::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 ::const_iterator it = m_modifiers.begin() ; - it != m_modifiers.end() ; ++it) - { - if (*it == modifierLC) - return (true); - } - - return (false); -} - - -const std::vector 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 ::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/src/emailAddress.cpp b/src/emailAddress.cpp deleted file mode 100644 index e185b17b..00000000 --- a/src/emailAddress.cpp +++ /dev/null @@ -1,539 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -{ - - -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_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; - - 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; - - case State_LocalPartStart: - - if (c == '"') - { - state = State_LocalPartQuoted; - ++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_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_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(); - - m_localName = word(localPart.str(), vmime::charsets::UTF_8); - m_domainName = word(domainPart.str(), vmime::charsets::UTF_8); - } - - setParsedBounds(position, p - pend); - - if (newPosition) - *newPosition = p - pend; -} - - -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(); -} - - -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 (other); - - m_localName = source.m_localName; - m_domainName = source.m_domainName; -} - - -emailAddress& emailAddress::operator=(const emailAddress& other) -{ - copyFrom(other); - return (*this); -} - - -shared_ptr emailAddress::clone() const -{ - return make_shared (*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 > emailAddress::getChildComponents() -{ - return std::vector >(); -} - - -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 (m_localName)); - txt.appendWord(make_shared ("@", vmime::charsets::US_ASCII)); - txt.appendWord(make_shared (m_domainName)); - - return txt; -} - - -} // vmime diff --git a/src/emptyContentHandler.cpp b/src/emptyContentHandler.cpp deleted file mode 100644 index e0f191f3..00000000 --- a/src/emptyContentHandler.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 emptyContentHandler::clone() const -{ - return make_shared (); -} - - -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/src/encoding.cpp b/src/encoding.cpp deleted file mode 100644 index 26922395..00000000 --- a/src/encoding.cpp +++ /dev/null @@ -1,300 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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 encoding::getEncoder() const -{ - shared_ptr 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(), 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 - (shared_ptr 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(shared_ptr 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 encoding::clone() const -{ - return make_shared (*this); -} - - -void encoding::copyFrom(const component& other) -{ - const encoding& e = dynamic_cast (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 > encoding::getChildComponents() -{ - return std::vector >(); -} - - -} // vmime diff --git a/src/exception.cpp b/src/exception.cpp deleted file mode 100644 index 042ac4f4..00000000 --- a/src/exception.cpp +++ /dev/null @@ -1,748 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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() - : m_what(""), m_other(NULL) -{ -} - - -exception::exception(const string& what, const exception& other) - : m_what(what), m_other(&other != &NO_EXCEPTION ? other.clone() : NULL) -{ -} - - -exception::exception(const exception& e) - : std::exception(), m_what(e.what()), m_other(e.m_other == NULL ? NULL : e.m_other->clone()) -{ -} - - -exception::~exception() throw() -{ - delete (m_other); -} - - -const char* exception::what() const throw() -{ - return (m_what.c_str()); -} - - -const char* exception::what() throw() -{ - return (m_what.c_str()); -} - - -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"; } - - -// -// 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"; } - - -// -// 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"; } - - -// -// certificate_exception -// - -certificate_exception::~certificate_exception() throw() {} -certificate_exception::certificate_exception(const string& what, const exception& other) - : tls_exception(what, other) {} - -exception* certificate_exception::clone() const { return new certificate_exception(*this); } -const char* certificate_exception::name() const throw() { return "certificate_exception"; } - - -// -// certificate_verification_exception -// - -certificate_verification_exception::~certificate_verification_exception() throw() {} -certificate_verification_exception::certificate_verification_exception(const string& what, const exception& other) - : certificate_exception(what, other) {} - -exception* certificate_verification_exception::clone() const { return new certificate_verification_exception(*this); } -const char* certificate_verification_exception::name() const throw() { return "certificate_verification_exception"; } - - -// -// unsupported_certificate_type -// - -unsupported_certificate_type::~unsupported_certificate_type() throw() {} -unsupported_certificate_type::unsupported_certificate_type(const string& type, const exception& other) - : certificate_exception("Unsupported certificate type: '" + type + "'", other) {} - -exception* unsupported_certificate_type::clone() const { return new unsupported_certificate_type(*this); } -const char* unsupported_certificate_type::name() const throw() { return "unsupported_certificate_type"; } - - -#endif // VMIME_HAVE_TLS_SUPPORT - - -} // exceptions - - -} // vmime - diff --git a/src/fileAttachment.cpp b/src/fileAttachment.cpp deleted file mode 100644 index 25a97fcc..00000000 --- a/src/fileAttachment.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - -#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(shared_ptr 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(shared_ptr 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(shared_ptr 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 fsf = platform::getHandler()->getFileSystemFactory(); - utility::file::path path = fsf->stringToPath(filepath); - - shared_ptr file = fsf->create(path); - - if (!file->isFile()) - throw exceptions::open_file_error(); - - m_data = make_shared - (file->getFileReader()->getInputStream(), file->getLength()); - - m_fileInfo.setFilename(path.getLastComponent()); - m_fileInfo.setSize(file->getLength()); -} - - -void fileAttachment::setData(shared_ptr cts) -{ - m_data = cts; - - m_fileInfo.setSize(cts->getLength()); -} - - -void fileAttachment::generatePart(shared_ptr part) const -{ - defaultAttachment::generatePart(part); - - shared_ptr cdf = - dynamicCast (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 != NULL); } -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 != NULL); } -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 != NULL); } -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 != NULL); } -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 != NULL); } -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/src/fileContentHandler.cpp b/src/fileContentHandler.cpp deleted file mode 100644 index 53ec9f69..00000000 --- a/src/fileContentHandler.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/fileContentHandler.hpp" - - -namespace vmime -{ - - -fileContentHandler::fileContentHandler() - : streamContentHandler() -{ -} - - -fileContentHandler::fileContentHandler - (shared_ptr 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 fileContentHandler::clone() const -{ - return make_shared (*this); -} - - -void fileContentHandler::setData - (shared_ptr file, const vmime::encoding& enc) -{ - m_file = file; - m_encoding = enc; - - streamContentHandler::setData - (file->getFileReader()->getInputStream(), file->getLength(), enc); -} - - -} // vmime diff --git a/src/generatedMessageAttachment.cpp b/src/generatedMessageAttachment.cpp deleted file mode 100644 index 0473d247..00000000 --- a/src/generatedMessageAttachment.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr part) - : m_bpa(make_shared (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 generatedMessageAttachment::getData() const -{ - return m_bpa->getData(); -} - - -const encoding generatedMessageAttachment::getEncoding() const -{ - return m_bpa->getEncoding(); -} - - -shared_ptr generatedMessageAttachment::getPart() const -{ - return m_bpa->getPart(); -} - - -shared_ptr generatedMessageAttachment::getHeader() const -{ - return m_bpa->getHeader(); -} - - -shared_ptr generatedMessageAttachment::getMessage() const -{ - if (m_msg == NULL) - { - // Extract data - std::ostringstream oss; - utility::outputStreamAdapter os(oss); - - getData()->extract(os); - - // Parse message - m_msg = make_shared (); - m_msg->parse(oss.str()); - } - - return m_msg; -} - - -void generatedMessageAttachment::generateIn(shared_ptr /* parent */) const -{ - // Not used (see 'parsedMessageAttachment') -} - - -} // vmime - diff --git a/src/generationContext.cpp b/src/generationContext.cpp deleted file mode 100644 index e9662883..00000000 --- a/src/generationContext.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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("") -{ -} - - -generationContext::generationContext(const generationContext& ctx) - : context(ctx), - m_maxLineLength(ctx.m_maxLineLength), - m_prologText(ctx.m_prologText), - m_epilogText(ctx.m_epilogText) -{ -} - - -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; -} - - -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; -} - - -} // vmime diff --git a/src/header.cpp b/src/header.cpp deleted file mode 100644 index 34b5fa6e..00000000 --- a/src/header.cpp +++ /dev/null @@ -1,388 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - - -namespace vmime -{ - - -header::header() -{ -} - - -header::~header() -{ - removeAllFields(); -} - - -/* - - RFC #822: - 3.2. HEADER FIELD DEFINITIONS - -field = field-name ":" [ field-body ] CRLF - -field-name = 1* - -field-body = field-body-contents - [CRLF LWSP-char field-body] - -field-body-contents = - -*/ - -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 field = headerField::parseNext(ctx, buffer, pos, end, &pos); - if (field == NULL) 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 >::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 header::clone() const -{ - shared_ptr
hdr = make_shared
(); - - hdr->m_fields.reserve(m_fields.size()); - - for (std::vector >::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 (other); - - std::vector > fields; - - fields.reserve(h.m_fields.size()); - - for (std::vector >::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 >::const_iterator pos = - std::find_if(m_fields.begin(), m_fields.end(), - fieldHasName(utility::stringUtils::toLower(fieldName))); - - return (pos != m_fields.end()); -} - - -shared_ptr header::findField(const string& fieldName) const -{ - // Find the first field that matches the specified name - std::vector >::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 > header::findAllFields(const string& fieldName) -{ - std::vector > result; - std::back_insert_iterator > > back(result); - - std::remove_copy_if(m_fields.begin(), m_fields.end(), back, - fieldHasNotName(utility::stringUtils::toLower(fieldName))); - - return result; -} - - -shared_ptr header::getField(const string& fieldName) -{ - const string name = utility::stringUtils::toLower(fieldName); - - // Find the first field that matches the specified name - std::vector >::const_iterator pos = m_fields.begin(); - const std::vector >::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 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(shared_ptr field) -{ - m_fields.push_back(field); -} - - -void header::insertFieldBefore(shared_ptr beforeField, shared_ptr field) -{ - const std::vector >::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, shared_ptr field) -{ - m_fields.insert(m_fields.begin() + pos, field); -} - - -void header::insertFieldAfter(shared_ptr afterField, shared_ptr field) -{ - const std::vector >::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, shared_ptr field) -{ - m_fields.insert(m_fields.begin() + pos + 1, field); -} - - -void header::removeField(shared_ptr field) -{ - const std::vector >::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 >::iterator it = m_fields.begin() + pos; - - m_fields.erase(it); -} - - -void header::replaceField(shared_ptr field, shared_ptr newField) -{ - insertFieldBefore(field, newField); - removeField(field); -} - - -void header::removeAllFields() -{ - m_fields.clear(); -} - - -void header::removeAllFields(const string& fieldName) -{ - std::vector > 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 header::getFieldAt(const size_t pos) -{ - return (m_fields[pos]); -} - - -const shared_ptr header::getFieldAt(const size_t pos) const -{ - return (m_fields[pos]); -} - - -const std::vector > header::getFieldList() const -{ - std::vector > list; - - list.reserve(m_fields.size()); - - for (std::vector >::const_iterator it = m_fields.begin() ; - it != m_fields.end() ; ++it) - { - list.push_back(*it); - } - - return (list); -} - - -const std::vector > header::getFieldList() -{ - return (m_fields); -} - - -const std::vector > header::getChildComponents() -{ - std::vector > 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 & 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 & field) -{ - return utility::stringUtils::toLower(field->getName()) != m_name; -} - - -} // vmime diff --git a/src/headerField.cpp b/src/headerField.cpp deleted file mode 100644 index f4c6187e..00000000 --- a/src/headerField.cpp +++ /dev/null @@ -1,381 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 headerField::clone() const -{ - shared_ptr field = headerFieldFactory::getInstance()->create(m_name); - - field->copyFrom(*this); - - return (field); -} - - -void headerField::copyFrom(const component& other) -{ - const headerField& hf = dynamic_cast (other); - - m_value->copyFrom(*hf.m_value); -} - - -headerField& headerField::operator=(const headerField& other) -{ - copyFrom(other); - return (*this); -} - - -shared_ptr 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] != ':') - { - // 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; - } - else - { - // Extract the field name - const string name(buffer.begin() + nameStart, - buffer.begin() + nameEnd); - - // Skip ':' character - ++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; - - // Extract the field value - while (pos < end) - { - c = buffer[pos]; - - // Check for folded line - if (c == '\r' && pos + 2 < end && buffer[pos + 1] == '\n' && - (buffer[pos + 2] == ' ' || buffer[pos + 2] == '\t')) - { - pos += 3; - } - // Check for end of contents - if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') - { - contentsEnd = pos; - pos += 2; - break; - } - else if (c == '\n') - { - contentsEnd = pos; - ++pos; - break; - } - - while (pos < end) - { - c = buffer[pos]; - - // Check for end of line - if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') - { - contentsEnd = pos; - pos += 2; - break; - } - else if (c == '\n') - { - contentsEnd = pos; - ++pos; - break; - } - - ++pos; - } - - // Handle the case of folded lines - if (buffer[pos] == ' ' || buffer[pos] == '\t') - { - // This is a folding white-space: we keep it as is and - // we continue with contents parsing... - - // If the line contains only space characters, we assume it is - // the end of the headers. This is not strictly standard-compliant - // but, hey, we can't fail when parsing some malformed mails... - while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t')) - ++pos; - - if ((pos < end && buffer[pos] == '\n') || - (pos + 1 < end && buffer[pos] == '\r' && buffer[pos + 1] == '\n')) - { - break; - } - } - else - { - // End of this field - break; - } - } - - 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 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 > headerField::getChildComponents() -{ - std::vector > list; - - if (m_value) - list.push_back(m_value); - - return (list); -} - - -shared_ptr headerField::getValue() const -{ - return m_value; -} - - -shared_ptr headerField::getValue() -{ - return m_value; -} - - -void headerField::setValue(shared_ptr value) -{ - if (!headerFieldFactory::getInstance()->isValueTypeValid(*this, *value)) - throw exceptions::bad_field_value_type(getName()); - - if (value != NULL) - m_value = value; -} - - -void headerField::setValueConst(shared_ptr 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/src/headerFieldFactory.cpp b/src/headerFieldFactory.cpp deleted file mode 100644 index 5c60543e..00000000 --- a/src/headerFieldFactory.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 (vmime::fields::CONTENT_TYPE); - registerField (vmime::fields::CONTENT_TRANSFER_ENCODING); - registerField (vmime::fields::CONTENT_DISPOSITION); - - registerField (vmime::fields::FROM); - registerField (vmime::fields::SENDER); - registerField (vmime::fields::REPLY_TO); - registerField (vmime::fields::DELIVERED_TO); - - // Register standard field values - registerFieldValue (vmime::fields::FROM); - registerFieldValue (vmime::fields::TO); - registerFieldValue (vmime::fields::CC); - registerFieldValue (vmime::fields::BCC); - registerFieldValue (vmime::fields::SENDER); - registerFieldValue (vmime::fields::DATE); - registerFieldValue (vmime::fields::RECEIVED); - registerFieldValue (vmime::fields::SUBJECT); - registerFieldValue (vmime::fields::REPLY_TO); - registerFieldValue (vmime::fields::DELIVERED_TO); - registerFieldValue (vmime::fields::ORGANIZATION); - registerFieldValue (vmime::fields::USER_AGENT); - registerFieldValue (vmime::fields::RETURN_PATH); - registerFieldValue (vmime::fields::CONTENT_TYPE); - registerFieldValue (vmime::fields::CONTENT_TRANSFER_ENCODING); - registerFieldValue (vmime::fields::CONTENT_DESCRIPTION); - registerFieldValue (vmime::fields::MIME_VERSION); - registerFieldValue (vmime::fields::CONTENT_DISPOSITION); - registerFieldValue (vmime::fields::CONTENT_ID); - registerFieldValue (vmime::fields::MESSAGE_ID); - registerFieldValue (vmime::fields::CONTENT_LOCATION); - registerFieldValue (vmime::fields::IN_REPLY_TO); - registerFieldValue (vmime::fields::REFERENCES); - - registerFieldValue (vmime::fields::ORIGINAL_MESSAGE_ID); - registerFieldValue (vmime::fields::DISPOSITION); - registerFieldValue (vmime::fields::DISPOSITION_NOTIFICATION_TO); -} - - -headerFieldFactory::~headerFieldFactory() -{ -} - - -shared_ptr headerFieldFactory::getInstance() -{ - static headerFieldFactory instance; - return shared_ptr (&instance, noop_shared_ptr_deleter ()); -} - - -shared_ptr headerFieldFactory::create - (const string& name, const string& body) -{ - NameMap::const_iterator pos = m_nameMap.find(utility::stringUtils::toLower(name)); - shared_ptr field; - - if (pos != m_nameMap.end()) - field = ((*pos).second)(); - else - field = registerer ::creator(); - - field->setName(name); - field->setValue(createValue(name)); - - if (body != NULL_STRING) - field->parse(body); - - return field; -} - - -shared_ptr headerFieldFactory::createValue(const string& fieldName) -{ - ValueMap::const_iterator pos = m_valueMap.find - (utility::stringUtils::toLower(fieldName)); - - shared_ptr value; - - if (pos != m_valueMap.end()) - value = ((*pos).second.allocFunc)(); - else - value = registerer ::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/src/headerFieldValue.cpp b/src/headerFieldValue.cpp deleted file mode 100644 index a93e0061..00000000 --- a/src/headerFieldValue.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/htmlTextPart.cpp b/src/htmlTextPart.cpp deleted file mode 100644 index 44459336..00000000 --- a/src/htmlTextPart.cpp +++ /dev/null @@ -1,510 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 ()), - m_text(make_shared ()) -{ -} - - -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(shared_ptr /* message */, shared_ptr parent) const -{ - // Plain text - if (!m_plainText->isEmpty()) - { - // -- Create a new part - shared_ptr part = make_shared (); - 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 htmlPart = make_shared (); - - // -- 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 relPart = make_shared (); - 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 >::const_iterator it = m_objects.begin() ; - it != m_objects.end() ; ++it) - { - shared_ptr objPart = make_shared (); - relPart->getBody()->appendPart(objPart); - - string id = (*it)->getId(); - - if (id.substr(0, 4) == "CID:") - 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 >& cidParts, std::vector >& locParts) -{ - for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i) - { - shared_ptr 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 ctf = - part.getHeader()->findField(fields::CONTENT_TYPE); - - if (ctf) - { - type = *ctf->getValue (); - } - else - { - // No "Content-type" field: assume "application/octet-stream". - } - - m_objects.push_back(make_shared - (vmime::clone(part.getBody()->getContents()), - part.getBody()->getEncoding(), id, type, refType)); -} - - -void htmlTextPart::parse(shared_ptr message, shared_ptr parent, shared_ptr textPart) -{ - // Search for possible embedded objects in the _whole_ message. - std::vector > cidParts; - std::vector > 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 ctf = - textPart->getHeader()->findField (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 >::const_iterator p = cidParts.begin() ; p != cidParts.end() ; ++p) - { - const shared_ptr midField = - (*p)->getHeader()->findField(fields::CONTENT_ID); - - const messageId mid = *midField->getValue (); - - 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 >::const_iterator p = locParts.begin() ; p != locParts.end() ; ++p) - { - const shared_ptr locField = - (*p)->getHeader()->findField(fields::CONTENT_LOCATION); - - const text loc = *locField->getValue (); - 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 (); - } -} - - -bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& parent, const bodyPart& textPart) -{ - // We search for the nearest "multipart/alternative" part. - const shared_ptr ctf = - part.getHeader()->findField(fields::CONTENT_TYPE); - - if (ctf) - { - const mediaType type = *ctf->getValue (); - - if (type.getType() == mediaTypes::MULTIPART && - type.getSubType() == mediaTypes::MULTIPART_ALTERNATIVE) - { - shared_ptr foundPart; - - for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i) - { - const shared_ptr 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 p = part.getBody()->getPartAt(i); - - const shared_ptr ctf = - p->getHeader()->findField(fields::CONTENT_TYPE); - - if (ctf) - { - - const mediaType type = *ctf->getValue (); - - 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 htmlTextPart::getPlainText() const -{ - return m_plainText; -} - - -void htmlTextPart::setPlainText(shared_ptr plainText) -{ - m_plainText = plainText->clone(); -} - - -const shared_ptr htmlTextPart::getText() const -{ - return m_text; -} - - -void htmlTextPart::setText(shared_ptr text) -{ - m_text = text->clone(); -} - - -size_t htmlTextPart::getObjectCount() const -{ - return m_objects.size(); -} - - -shared_ptr htmlTextPart::getObjectAt(const size_t pos) const -{ - return m_objects[pos]; -} - - -shared_ptr htmlTextPart::findObject(const string& id) const -{ - for (std::vector >::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 >::const_iterator o = m_objects.begin() ; - o != m_objects.end() ; ++o) - { - if ((*o)->matchesId(id)) - return true; - } - - return false; -} - - -shared_ptr htmlTextPart::addObject - (shared_ptr data, const vmime::encoding& enc, const mediaType& type) -{ - const messageId mid(messageId::generateId()); - - shared_ptr obj = make_shared - (data, enc, mid.getId(), type, embeddedObject::REFERENCED_BY_ID); - - m_objects.push_back(obj); - - return obj; -} - - -shared_ptr htmlTextPart::addObject - (shared_ptr data, const mediaType& type) -{ - return addObject(data, encoding::decide(data), type); -} - - -shared_ptr htmlTextPart::addObject - (const string& data, const mediaType& type) -{ - shared_ptr cts = make_shared (data); - return addObject(cts, encoding::decide(cts), type); -} - - - -// -// htmlTextPart::embeddedObject -// - -htmlTextPart::embeddedObject::embeddedObject - (shared_ptr 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 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/src/mailbox.cpp b/src/mailbox.cpp deleted file mode 100644 index 7c6d5e3b..00000000 --- a/src/mailbox.cpp +++ /dev/null @@ -1,510 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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; - - // Ignore blank spaces at the beginning - while (p < pend && parserHelpers::isSpace(*p)) ++p; - - // Current state for parsing machine - enum States - { - State_None, - State_Name, - State_Address - }; - - States state = State_Name; // let's start with name, we will see later (*) - - // Temporary buffers for extracted name and address - string name; - string address; - bool hadBrackets = false; - - while (p < pend) - { - if (state == State_Name) - { - if (*p == '<') - { - state = State_Address; - continue; - } - - if (*p == '"') // Quoted string - { - ++p; - - bool escaped = false; - - while (p < pend) - { - if (escaped) - { - name += *p; - escaped = false; - } - else if (*p == '\\') - { - escaped = true; - } - else - { - if (*p == '"') - { - ++p; - break; - } - else - { - name += *p; - } - } - - ++p; - } - } - else - { - bool escaped = false; - int comment = 0; - - while (p < pend) - { - if (escaped) - { - if (!comment) name += *p; - 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 == '<') - { - // Erase any space between display name and
- string::iterator q = name.end(); - - while (q != name.begin() && parserHelpers::isSpace(*(q - 1))) - --q; - - name.erase(q, name.end()); - - break; - } - else if (/* parserHelpers::isSpace(*p) || */ *p == '@') - { - break; - } - else - { - name += *p; - } - - ++p; - } - } - - if (p < pend && *p == '@') - { - // (*) Actually, we were parsing the local-part of an address - // and not a display name... - address = name; - name.clear(); - - bool escaped = false; - int comment = 0; - - while (p < pend) - { - if (escaped) - { - if (!comment) address += *p; - 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 (parserHelpers::isSpace(*p)) - { - break; - } - else - { - address += *p; - } - - ++p; - } - - break; - } - else - { - while (p < pend && parserHelpers::isSpace(*p)) ++p; - state = State_None; - } - } - else if (state == State_Address) - { - // Skip '<' character - if (*p == '<') - ++p; - - bool escaped = false; - int comment = 0; - - while (p < pend) - { - if (escaped) - { - if (!comment) address += *p; - 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 == '<') - { - // 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! - name += address; - address.clear(); - } - else if (*p == '>') - { - hadBrackets = true; - break; - } - else if (!parserHelpers::isSpace(*p)) - { - address += *p; - } - - ++p; - } - - break; - } - else - { - while (p < pend && parserHelpers::isSpace(*p)) ++p; - - if (p < pend) - { - //if (*p == '<') - state = State_Address; - } - } - } - - // 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 " ; , < > ( ) @ / ? . = : - - // 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 '\r': - case '\n': - case '\t': - case ';': - case ',': - case '<': case '>': - case '(': case ')': - case '@': - case '/': - case '?': - case '.': - case '=': - case ':': - case '"': - - forceEncode = true; - break; - } - } - } - else - { - 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 (other); - - m_name = source.m_name; - m_email = source.m_email; -} - - -mailbox& mailbox::operator=(const mailbox& other) -{ - copyFrom(other); - return (*this); -} - - -shared_ptr mailbox::clone() const -{ - return make_shared (*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 > mailbox::getChildComponents() -{ - return std::vector >(); -} - - -} // vmime diff --git a/src/mailboxField.cpp b/src/mailboxField.cpp deleted file mode 100644 index 29fe9d33..00000000 --- a/src/mailboxField.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 mbox = make_shared (); - - // 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
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 group = dynamicCast (parsedAddress); - - if (!group->isEmpty()) - mbox = group->getMailboxAt(0); - } - else - { - // Parse only if it is a mailbox - mbox = dynamicCast (parsedAddress); - } - } - - mbox->setParsedBounds(position, end); - - setValue(mbox); - - setParsedBounds(position, end); - - if (newPosition) - *newPosition = end; -} - - -} // vmime - - -#endif // VMIME_BUILDING_DOC - diff --git a/src/mailboxGroup.cpp b/src/mailboxGroup.cpp deleted file mode 100644 index 5e8d6b1b..00000000 --- a/src/mailboxGroup.cpp +++ /dev/null @@ -1,377 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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
parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, &isLastAddressOfGroup); - - if (parsedAddress) - { - if (parsedAddress->isGroup()) - { - shared_ptr group = dynamicCast (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 (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 >::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 (other); - - m_name = source.m_name; - - removeAllMailboxes(); - - for (std::vector >::const_iterator it = source.m_list.begin() ; - it != source.m_list.end() ; ++it) - { - m_list.push_back(vmime::clone(*it)); - } -} - - -shared_ptr mailboxGroup::clone() const -{ - return make_shared (*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(shared_ptr mbox) -{ - m_list.push_back(mbox); -} - - -void mailboxGroup::insertMailboxBefore(shared_ptr beforeMailbox, shared_ptr mbox) -{ - const std::vector >::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, shared_ptr mbox) -{ - if (pos >= m_list.size()) - throw std::out_of_range("Invalid position"); - - m_list.insert(m_list.begin() + pos, mbox); -} - - -void mailboxGroup::insertMailboxAfter(shared_ptr afterMailbox, shared_ptr mbox) -{ - const std::vector >::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, shared_ptr 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(shared_ptr mbox) -{ - const std::vector >::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 >::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 mailboxGroup::getMailboxAt(const size_t pos) -{ - return (m_list[pos]); -} - - -const shared_ptr mailboxGroup::getMailboxAt(const size_t pos) const -{ - return (m_list[pos]); -} - - -const std::vector > mailboxGroup::getMailboxList() const -{ - std::vector > list; - - list.reserve(m_list.size()); - - for (std::vector >::const_iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { - list.push_back(*it); - } - - return (list); -} - - -const std::vector > mailboxGroup::getMailboxList() -{ - return (m_list); -} - - -const std::vector > mailboxGroup::getChildComponents() -{ - std::vector > list; - - copy_vector(m_list, list); - - return (list); - -} - - -} // vmime diff --git a/src/mailboxList.cpp b/src/mailboxList.cpp deleted file mode 100644 index b356a1e7..00000000 --- a/src/mailboxList.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr mbox) -{ - m_list.appendAddress(mbox); -} - - -void mailboxList::insertMailboxBefore(shared_ptr beforeMailbox, shared_ptr mbox) -{ - m_list.insertAddressBefore(beforeMailbox, mbox); -} - - -void mailboxList::insertMailboxBefore(const size_t pos, shared_ptr mbox) -{ - m_list.insertAddressBefore(pos, mbox); -} - - -void mailboxList::insertMailboxAfter(shared_ptr afterMailbox, shared_ptr mbox) -{ - m_list.insertAddressAfter(afterMailbox, mbox); -} - - -void mailboxList::insertMailboxAfter(const size_t pos, shared_ptr mbox) -{ - m_list.insertAddressAfter(pos, mbox); -} - - -void mailboxList::removeMailbox(shared_ptr 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 mailboxList::getMailboxAt(const size_t pos) -{ - return dynamicCast (m_list.getAddressAt(pos)); -} - - -const shared_ptr mailboxList::getMailboxAt(const size_t pos) const -{ - return dynamicCast (m_list.getAddressAt(pos)); -} - - -const std::vector > mailboxList::getMailboxList() const -{ - const std::vector > addrList = m_list.getAddressList(); - std::vector > res; - - for (std::vector >::const_iterator it = addrList.begin() ; - it != addrList.end() ; ++it) - { - const shared_ptr mbox = dynamicCast (*it); - - if (mbox != NULL) - res.push_back(mbox); - } - - return (res); -} - - -const std::vector > mailboxList::getMailboxList() -{ - const std::vector > addrList = m_list.getAddressList(); - std::vector > res; - - for (std::vector >::const_iterator it = addrList.begin() ; - it != addrList.end() ; ++it) - { - const shared_ptr mbox = dynamicCast (*it); - - if (mbox != NULL) - res.push_back(mbox); - } - - return (res); -} - - -shared_ptr mailboxList::clone() const -{ - return make_shared (*this); -} - - -void mailboxList::copyFrom(const component& other) -{ - const mailboxList& mboxList = dynamic_cast (other); - - m_list = mboxList.m_list; -} - - -mailboxList& mailboxList::operator=(const mailboxList& other) -{ - copyFrom(other); - return (*this); -} - - -const std::vector > 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
parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, NULL); - - if (parsedAddress != NULL) - { - if (parsedAddress->isGroup()) - { - shared_ptr group = dynamicCast (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 mailboxList::toAddressList() const -{ - return vmime::clone(m_list); -} - - -} // vmime - diff --git a/src/mdn/MDNHelper.cpp b/src/mdn/MDNHelper.cpp deleted file mode 100644 index 1205aef2..00000000 --- a/src/mdn/MDNHelper.cpp +++ /dev/null @@ -1,353 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr msg, const mailboxList& mailboxes) -{ - shared_ptr
hdr = msg->getHeader(); - - hdr->DispositionNotificationTo()->setValue(mailboxes); -} - - -void MDNHelper::attachMDNRequest(shared_ptr msg, const mailbox& mbox) -{ - mailboxList mboxList; - mboxList.appendMailbox(vmime::clone(mbox)); - - attachMDNRequest(msg, mboxList); -} - - -const std::vector MDNHelper::getPossibleMDNs(const shared_ptr msg) -{ - std::vector result; - - const shared_ptr hdr = msg->getHeader(); - - if (hdr->hasField(fields::DISPOSITION_NOTIFICATION_TO)) - { - const mailboxList& dnto = - *hdr->DispositionNotificationTo()->getValue (); - - 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 msg) -{ - const shared_ptr 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 (hdr->ContentType()); - - const mediaType type = *ctf.getValue (); - - 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 msg) -{ - if (!isMDN(msg)) - throw exceptions::invalid_argument(); - - return receivedMDNInfos(msg); -} - - -bool MDNHelper::needConfirmation(const shared_ptr msg) -{ - shared_ptr 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 (); - - 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 (); - - if (mbox.getEmail() != rp.getLocalPart() + "@" + rp.getDomain()) - return true; - } - - // User confirmation not needed - return false; -} - - -shared_ptr MDNHelper::buildMDN(const sendableMDNInfos& mdnInfos, - const string& text, - const charset& ch, - const mailbox& expeditor, - const disposition& dispo, - const string& reportingUA, - const std::vector & reportingUAProducts, - const std::map & fields) -{ - // Create a new message - shared_ptr msg = make_shared (); - - // Fill-in header fields - shared_ptr
hdr = msg->getHeader(); - - hdr->ContentType()->setValue(mediaType(vmime::mediaTypes::MULTIPART, - vmime::mediaTypes::MULTIPART_REPORT)); - dynamicCast (hdr->ContentType())->setReportType("disposition-notification"); - - hdr->Disposition()->setValue(dispo); - - addressList to; - to.appendAddress(make_shared (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 MDNHelper::createFirstMDNPart(const sendableMDNInfos& /* mdnInfos */, - const string& text, const charset& ch) -{ - shared_ptr part = make_shared (); - - // Header - shared_ptr
hdr = part->getHeader(); - - hdr->ContentType()->setValue(mediaType(vmime::mediaTypes::TEXT, - vmime::mediaTypes::TEXT_PLAIN)); - - dynamicCast (hdr->ContentType())->setCharset(ch); - - // Body - part->getBody()->setContents(make_shared (text)); - - return (part); -} - - -shared_ptr MDNHelper::createSecondMDNPart(const sendableMDNInfos& mdnInfos, - const disposition& dispo, - const string& reportingUA, - const std::vector & reportingUAProducts, - const std::map & additionalFields) -{ - shared_ptr part = make_shared (); - - // Header - shared_ptr
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 rua = headerFieldFactory::getInstance()-> - create(vmime::fields::REPORTING_UA); - - rua->setValue(ruaText); - - fields.appendField(rua); - } - - // -- Final-Recipient - shared_ptr 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 ::const_iterator it; - - if (additionalFields.size() > 0) - { - it = additionalFields.find(vmime::fields::ERROR); - if (it != additionalFields.end()) - { - shared_ptr error = headerFieldFactory::getInstance()-> - create(vmime::fields::ERROR); - error->setValue(it->second); - fields.appendField(error); - } - - it = additionalFields.find(vmime::fields::WARNING); - if (it != additionalFields.end()) - { - shared_ptr warn = headerFieldFactory::getInstance()-> - create(vmime::fields::WARNING); - warn->setValue(it->second); - fields.appendField(warn); - } - - it = additionalFields.find(vmime::fields::FAILURE); - if (it != additionalFields.end()) - { - shared_ptr 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 (oss.str())); - - return (part); -} - - -shared_ptr MDNHelper::createThirdMDNPart(const sendableMDNInfos& mdnInfos) -{ - shared_ptr part = make_shared (); - - // Header - shared_ptr
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 (oss.str())); - - return (part); -} - - -} // mdn -} // vmime diff --git a/src/mdn/MDNInfos.cpp b/src/mdn/MDNInfos.cpp deleted file mode 100644 index a70161b7..00000000 --- a/src/mdn/MDNInfos.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/mdn/receivedMDNInfos.cpp b/src/mdn/receivedMDNInfos.cpp deleted file mode 100644 index 53b2281e..00000000 --- a/src/mdn/receivedMDNInfos.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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 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 bdy = m_msg->getBody(); - - for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) - { - const shared_ptr part = bdy->getPartAt(i); - - if (!part->getHeader()->hasField(fields::CONTENT_TYPE)) - continue; - - const mediaType& type = *part->getHeader()->ContentType()->getValue (); - - // 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 omid = - fields.findFieldValue (fields::ORIGINAL_MESSAGE_ID); - - if (omid) - m_omid = *omid; - - shared_ptr disp = - fields.findFieldValue (fields::DISPOSITION); - - if (disp) - m_disp = *disp; - - shared_ptr contentMIC = - fields.findFieldValue ("Received-content-MIC"); - - if (contentMIC) - m_contentMIC = contentMIC->generate(); - } - } -} - - -} // mdn -} // vmime diff --git a/src/mdn/sendableMDNInfos.cpp b/src/mdn/sendableMDNInfos.cpp deleted file mode 100644 index c145c3b6..00000000 --- a/src/mdn/sendableMDNInfos.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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 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/src/mediaType.cpp b/src/mediaType.cpp deleted file mode 100644 index 60486da7..00000000 --- a/src/mediaType.cpp +++ /dev/null @@ -1,187 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 mediaType::clone() const -{ - return make_shared (m_type, m_subType); -} - - -void mediaType::copyFrom(const component& other) -{ - const mediaType& mt = dynamic_cast (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 > mediaType::getChildComponents() -{ - return std::vector >(); -} - - -} // vmime diff --git a/src/message.cpp b/src/message.cpp deleted file mode 100644 index 76735496..00000000 --- a/src/message.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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/src/messageBuilder.cpp b/src/messageBuilder.cpp deleted file mode 100644 index 64880483..00000000 --- a/src/messageBuilder.cpp +++ /dev/null @@ -1,329 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 messageBuilder::construct() const -{ - // Create a new message - shared_ptr msg = make_shared (); - - // 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 subPart = make_shared (); - 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 >::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 bodyCopy = vmime::clone(part.getBody()); - - // First, copy (and replace) the header fields - const std::vector > fields = part.getHeader()->getFieldList(); - - for (std::vector >::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(shared_ptr attach) -{ - appendAttachment(attach); -} - - -void messageBuilder::appendAttachment(shared_ptr attach) -{ - m_attach.push_back(attach); -} - - -void messageBuilder::constructTextPart(const mediaType& type) -{ - shared_ptr part; - - try - { - part = textPartFactory::getInstance()->create(type); - } - catch (exceptions::no_factory_available& e) - { - throw; - } - - m_textPart = part; -} - - -shared_ptr 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 messageBuilder::getAttachmentAt(const size_t pos) const -{ - return (m_attach[pos]); -} - - -shared_ptr messageBuilder::getAttachmentAt(const size_t pos) -{ - return (m_attach[pos]); -} - - -size_t messageBuilder::getAttachmentCount() const -{ - return (m_attach.size()); -} - - -const std::vector > messageBuilder::getAttachmentList() const -{ - std::vector > res; - - res.reserve(m_attach.size()); - - for (std::vector >::const_iterator it = m_attach.begin() ; - it != m_attach.end() ; ++it) - { - res.push_back(*it); - } - - return (res); -} - - -const std::vector > messageBuilder::getAttachmentList() -{ - return (m_attach); -} - - -} // vmime diff --git a/src/messageId.cpp b/src/messageId.cpp deleted file mode 100644 index edc4d1fb..00000000 --- a/src/messageId.cpp +++ /dev/null @@ -1,300 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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::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 mid = make_shared (); - mid->parse(ctx, buffer, begin, pos, NULL); - - if (newPosition != NULL) - *newPosition = pos; - - return (mid); - } - - if (newPosition != NULL) - *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 (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 messageId::clone() const -{ - return make_shared (*this); -} - - -void messageId::copyFrom(const component& other) -{ - const messageId& mid = dynamic_cast (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 > messageId::getChildComponents() -{ - return std::vector >(); -} - - -} // vmime diff --git a/src/messageIdSequence.cpp b/src/messageIdSequence.cpp deleted file mode 100644 index 23b12773..00000000 --- a/src/messageIdSequence.cpp +++ /dev/null @@ -1,252 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime -{ - - - - -messageIdSequence::messageIdSequence() -{ -} - - -messageIdSequence::~messageIdSequence() -{ - removeAllMessageIds(); -} - - -messageIdSequence::messageIdSequence(const messageIdSequence& midSeq) - : headerFieldValue() -{ - copyFrom(midSeq); -} - - -shared_ptr messageIdSequence::clone() const -{ - return make_shared (*this); -} - - -void messageIdSequence::copyFrom(const component& other) -{ - const messageIdSequence& midSeq = dynamic_cast (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 > messageIdSequence::getChildComponents() -{ - std::vector > 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 parsedMid = messageId::parseNext(ctx, buffer, pos, end, &pos); - - if (parsedMid != NULL) - 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 >::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(shared_ptr mid) -{ - m_list.push_back(mid); -} - - -void messageIdSequence::insertMessageIdBefore(shared_ptr beforeMid, shared_ptr mid) -{ - const std::vector >::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, shared_ptr mid) -{ - m_list.insert(m_list.begin() + pos, mid); -} - - -void messageIdSequence::insertMessageIdAfter(shared_ptr afterMid, shared_ptr mid) -{ - const std::vector >::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, shared_ptr mid) -{ - m_list.insert(m_list.begin() + pos + 1, mid); -} - - -void messageIdSequence::removeMessageId(shared_ptr mid) -{ - const std::vector >::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 >::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 messageIdSequence::getMessageIdAt(const size_t pos) -{ - return (m_list[pos]); -} - - -const shared_ptr messageIdSequence::getMessageIdAt(const size_t pos) const -{ - return (m_list[pos]); -} - - -const std::vector > messageIdSequence::getMessageIdList() const -{ - std::vector > list; - - list.reserve(m_list.size()); - - for (std::vector >::const_iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { - list.push_back(*it); - } - - return (list); -} - - -const std::vector > messageIdSequence::getMessageIdList() -{ - return (m_list); -} - - -} // vmime diff --git a/src/messageParser.cpp b/src/messageParser.cpp deleted file mode 100644 index 5fe219f3..00000000 --- a/src/messageParser.cpp +++ /dev/null @@ -1,322 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 msg = make_shared (); - msg->parse(buffer); - - parse(msg); -} - - -messageParser::messageParser(shared_ptr msg) -{ - parse(msg); -} - - -messageParser::~messageParser() -{ -} - - -void messageParser::parse(shared_ptr 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 fldValue = msg->getHeader()->findFieldValue (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 recv = msg->getHeader()->findField(fields::RECEIVED); - - if (recv) - { - m_date = recv->getValue ()->getDate(); - } - else - { - shared_ptr date = msg->getHeader()->findField(fields::DATE); - - if (date) - m_date = *date->getValue (); - else - m_date = datetime::now(); - } - - // Attachments - findAttachments(msg); - - // Text parts - findTextParts(msg, msg); -} - - -void messageParser::findAttachments(shared_ptr msg) -{ - m_attach = attachmentHelper::findAttachmentsInMessage(msg); -} - - -void messageParser::findTextParts(shared_ptr msg, shared_ptr 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 ctf = - msg->getHeader()->findField (fields::CONTENT_TYPE); - - if (ctf) - { - const mediaType ctfType = *ctf->getValue (); - - if (ctfType.getType() == mediaTypes::TEXT) - { - type = ctfType; - accept = true; - } - } - else - { - // No "Content-type" field: assume "text/plain". - accept = true; - } - - if (accept) - { - shared_ptr txtPart = textPartFactory::getInstance()->create(type); - txtPart->parse(msg, msg, msg); - - m_textParts.push_back(txtPart); - } - } - // Multipart message - else - { - findSubTextParts(msg, part); - } -} - - -bool messageParser::findSubTextParts(shared_ptr msg, shared_ptr 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 > textParts; - - for (size_t i = 0 ; i < part->getBody()->getPartCount() ; ++i) - { - const shared_ptr p = part->getBody()->getPartAt(i); - - shared_ptr ctf = - p->getHeader()->findField (fields::CONTENT_TYPE); - - if (ctf) - { - const mediaType type = *ctf->getValue (); - contentDisposition disp; // default should be inline - - if (type.getType() == mediaTypes::TEXT) - { - shared_ptr cdf = p->getHeader()-> - findField (fields::CONTENT_DISPOSITION); - - if (cdf) - { - disp = *cdf->getValue (); - } - 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 >::const_iterator p = textParts.begin() ; - p != textParts.end() ; ++p) - { - const contentTypeField& ctf = - *(*p)->getHeader()->findField (fields::CONTENT_TYPE); - - const mediaType type = *ctf.getValue (); - - try - { - shared_ptr 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 > messageParser::getAttachmentList() const -{ - return m_attach; -} - - -size_t messageParser::getAttachmentCount() const -{ - return (m_attach.size()); -} - - -const shared_ptr messageParser::getAttachmentAt(const size_t pos) const -{ - return (m_attach[pos]); -} - - -const std::vector > messageParser::getTextPartList() const -{ - std::vector > res; - - res.reserve(m_textParts.size()); - - for (std::vector >::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 messageParser::getTextPartAt(const size_t pos) const -{ - return (m_textParts[pos]); -} - - -} // vmime diff --git a/src/misc/importanceHelper.cpp b/src/misc/importanceHelper.cpp deleted file mode 100644 index b13f7466..00000000 --- a/src/misc/importanceHelper.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr msg) -{ - resetImportanceHeader(msg->getHeader()); -} - - -void importanceHelper::resetImportanceHeader(shared_ptr
hdr) -{ - shared_ptr fld; - - if ((fld = hdr->findField("X-Priority"))) - hdr->removeField(fld); - - if ((fld = hdr->findField("Importance"))) - hdr->removeField(fld); -} - - -importanceHelper::Importance importanceHelper::getImportance(shared_ptr msg) -{ - return getImportanceHeader(msg->getHeader()); -} - - -importanceHelper::Importance importanceHelper::getImportanceHeader(shared_ptr hdr) -{ - // Try "X-Priority" field - shared_ptr fld = hdr->findField("X-Priority"); - - if (fld) - { - const string value = fld->getValue ()->getWholeBuffer(); - - int n = IMPORTANCE_NORMAL; - - std::istringstream iss(value); - 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 ()->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(shared_ptr msg, const Importance i) -{ - setImportanceHeader(msg->getHeader(), i); -} - - -void importanceHelper::setImportanceHeader(shared_ptr
hdr, const Importance i) -{ - // "X-Priority:" Field - shared_ptr 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/src/net/builtinServices.inl b/src/net/builtinServices.inl deleted file mode 100644 index 9225ff30..00000000 --- a/src/net/builtinServices.inl +++ /dev/null @@ -1,76 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 "src/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/src/net/defaultConnectionInfos.cpp b/src/net/defaultConnectionInfos.cpp deleted file mode 100644 index 335e8f6f..00000000 --- a/src/net/defaultConnectionInfos.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/net/events.cpp b/src/net/events.cpp deleted file mode 100644 index a19e1738..00000000 --- a/src/net/events.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace net { -namespace events { - - -// -// event -// - -event::event() -{ -} - - -event::~event() -{ -} - - -// -// messageCountEvent -// - -const char* messageCountEvent::EVENT_CLASS = "messageCountEvent"; - - -messageCountEvent::messageCountEvent - (shared_ptr folder, const Types type, const std::vector & nums) - : m_folder(folder), m_type(type) -{ - m_nums.resize(nums.size()); - std::copy(nums.begin(), nums.end(), m_nums.begin()); -} - - -shared_ptr messageCountEvent::getFolder() const { return (m_folder); } -messageCountEvent::Types messageCountEvent::getType() const { return (m_type); } -const std::vector & messageCountEvent::getNumbers() const { return (m_nums); } - - -void messageCountEvent::dispatch(messageCountListener* listener) -{ - if (m_type == TYPE_ADDED) - listener->messagesAdded(dynamicCast (shared_from_this())); - else - listener->messagesRemoved(dynamicCast (shared_from_this())); -} - - -const char* messageCountEvent::getClass() const -{ - return EVENT_CLASS; -} - - -// -// messageChangedEvent -// - -const char* messageChangedEvent::EVENT_CLASS = "messageChangedEvent"; - - -messageChangedEvent::messageChangedEvent - (shared_ptr folder, const Types type, const std::vector & nums) - : m_folder(folder), m_type(type) -{ - m_nums.resize(nums.size()); - std::copy(nums.begin(), nums.end(), m_nums.begin()); -} - - -shared_ptr messageChangedEvent::getFolder() const { return (m_folder); } -messageChangedEvent::Types messageChangedEvent::getType() const { return (m_type); } -const std::vector & messageChangedEvent::getNumbers() const { return (m_nums); } - - -void messageChangedEvent::dispatch(messageChangedListener* listener) -{ - listener->messageChanged(dynamicCast (shared_from_this())); -} - - -const char* messageChangedEvent::getClass() const -{ - return EVENT_CLASS; -} - - -// -// folderEvent -// - -const char* folderEvent::EVENT_CLASS = "folderEvent"; - - -folderEvent::folderEvent - (shared_ptr 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 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 (shared_from_this())); break; - case TYPE_RENAMED: listener->folderRenamed(dynamicCast (shared_from_this())); break; - case TYPE_DELETED: listener->folderDeleted(dynamicCast (shared_from_this())); break; - } -} - - -const char* folderEvent::getClass() const -{ - return EVENT_CLASS; -} - - -} // events -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/fetchAttributes.cpp b/src/net/fetchAttributes.cpp deleted file mode 100644 index 85a41b8c..00000000 --- a/src/net/fetchAttributes.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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 fetchAttributes::getHeaderFields() const -{ - return m_headers; -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES diff --git a/src/net/folder.cpp b/src/net/folder.cpp deleted file mode 100644 index 1d6f3140..00000000 --- a/src/net/folder.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace net { - - -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(shared_ptr event) -{ - for (std::list ::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(shared_ptr event) -{ - for (std::list ::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(shared_ptr event) -{ - for (std::list ::iterator - it = m_folderListeners.begin() ; it != m_folderListeners.end() ; ++it) - { - event->dispatch(*it); - } -} - - -void folder::notifyEvent(shared_ptr event) -{ - if (event->getClass() == events::messageCountEvent::EVENT_CLASS) - { - notifyMessageCount(dynamicCast (event)); - } - else if (event->getClass() == events::messageChangedEvent::EVENT_CLASS) - { - notifyMessageChanged(dynamicCast (event)); - } - else if (event->getClass() == events::folderEvent::EVENT_CLASS) - { - notifyFolder(dynamicCast (event)); - } -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/imap/IMAPConnection.cpp b/src/net/imap/IMAPConnection.cpp deleted file mode 100644 index 234c2b6a..00000000 --- a/src/net/imap/IMAPConnection.cpp +++ /dev/null @@ -1,814 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/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 - - -// Helpers for service properties -#define GET_PROPERTY(type, prop) \ - (m_store.lock()->getInfos().getPropertyValue (getSession(), \ - dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) -#define HAS_PROPERTY(prop) \ - (m_store.lock()->getInfos().hasProperty(getSession(), \ - dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPConnection::IMAPConnection(shared_ptr store, shared_ptr 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) -{ -} - - -IMAPConnection::~IMAPConnection() -{ - try - { - if (isConnected()) - disconnect(); - else if (m_socket) - internalDisconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -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 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); - -#if VMIME_HAVE_TLS_SUPPORT - if (store->isIMAPS()) // dedicated port/IMAPS - { - shared_ptr tlsSession = tls::TLSSession::create - (store->getCertificateVerifier(), - store->getSession()->getTLSProperties()); - - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); - - m_socket = tlsSocket; - - m_secured = true; - m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); - } - else -#endif // VMIME_HAVE_TLS_SUPPORT - { - m_cntInfos = make_shared (address, port); - } - - m_socket->connect(address, port); - - - m_tag = make_shared (); - m_parser = make_shared (m_tag, m_socket, m_timeoutHandler); - - - setState(STATE_NON_AUTHENTICATED); - - - // Connection greeting - // - // eg: C: - // --- S: * OK mydomain.org IMAP4rev1 v12.256 server ready - - std::auto_ptr 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()); - } - -#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& e) - { - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) - { - // Can't fallback on normal authentication - internalDisconnect(); - throw e; - } - else - { - // Ignore, will try normal authentication - } - } - catch (exception& e) - { - internalDisconnect(); - throw e; - } - } -#endif // VMIME_HAVE_SASL_SUPPORT - - // Normal authentication - const string username = getAuthenticator()->getUsername(); - const string password = getAuthenticator()->getPassword(); - - send(true, "LOGIN " + IMAPUtils::quoteString(username) - + " " + IMAPUtils::quoteString(password), true); - - std::auto_ptr resp(m_parser->readResponse()); - - 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 (getAuthenticator())) - throw exceptions::authentication_error("No SASL authenticator available."); - - const std::vector capa = getCapabilities(); - std::vector 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 > mechList; - - shared_ptr saslContext = - make_shared (); - - 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 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 (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 mech = mechList[i]; - - shared_ptr saslSession = - saslContext->createSession("imap", getAuthenticator(), mech); - - saslSession->init(); - - send(true, "AUTHENTICATE " + mech->getName(), true); - - for (bool cont = true ; cont ; ) - { - std::auto_ptr resp(m_parser->readResponse()); - - 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 - { - std::vector - respDataList = resp->continue_req_or_response_data(); - - string response; - bool hasResponse = false; - - for (unsigned int i = 0 ; i < respDataList.size() ; ++i) - { - if (respDataList[i]->continue_req()) - { - response = respDataList[i]->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 - send(false, saslContext->encodeB64(resp, respLen), true); - - // 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 - send(false, "*", true); - } - 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 - { - send(true, "STARTTLS", true); - - std::auto_ptr resp(m_parser->readResponse()); - - 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 tlsSession = tls::TLSSession::create - (m_store.lock()->getCertificateVerifier(), - m_store.lock()->getSession()->getTLSProperties()); - - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); - - tlsSocket->handshake(m_timeoutHandler); - - m_socket = tlsSocket; - m_parser->setSocket(m_socket); - - m_secured = true; - m_cntInfos = make_shared - (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 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; -} - - -void IMAPConnection::invalidateCapabilities() -{ - m_capabilities.clear(); - m_capabilitiesFetched = false; -} - - -void IMAPConnection::fetchCapabilities() -{ - send(true, "CAPABILITY", true); - - std::auto_ptr resp(m_parser->readResponse()); - - 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) -{ - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - for (size_t i = 0 ; i < respDataList.size() ; ++i) - { - if (respDataList[i]->response_data() == NULL) - continue; - - const IMAPParser::capability_data* capaData = - respDataList[i]->response_data()->capability_data(); - - if (capaData == NULL) - continue; - - processCapabilityResponseData(capaData); - return true; - } - - return false; -} - - -void IMAPConnection::processCapabilityResponseData(const IMAPParser::capability_data* capaData) -{ - std::vector res; - - std::vector caps = capaData->capabilities(); - - for (unsigned int j = 0 ; j < caps.size() ; ++j) - { - if (caps[j]->auth_type()) - res.push_back("AUTH=" + caps[j]->auth_type()->name()); - else - res.push_back(utility::stringUtils::toUpper(caps[j]->atom()->value())); - } - - m_capabilities = res; - m_capabilitiesFetched = true; -} - - -shared_ptr 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 IMAPConnection::getConnectionInfos() const -{ - return m_cntInfos; -} - - -void IMAPConnection::disconnect() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - internalDisconnect(); -} - - -void IMAPConnection::internalDisconnect() -{ - if (isConnected()) - { - send(true, "LOGOUT", true); - - m_socket->disconnect(); - m_socket = null; - } - - m_timeoutHandler = null; - - m_state = STATE_LOGOUT; - - m_secured = false; - m_cntInfos = null; -} - - -void IMAPConnection::initHierarchySeparator() -{ - send(true, "LIST \"\" \"\"", true); - - std::auto_ptr resp(m_parser->readResponse()); - - 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 std::vector & 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() == NULL) - continue; - - const IMAPParser::mailbox_data* mailboxData = - static_cast - (respDataList[i]->response_data())->mailbox_data(); - - if (mailboxData == NULL || 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::send(bool tag, const string& what, bool end) -{ - if (tag && !m_firstTag) - ++(*m_tag); - -#if VMIME_DEBUG - std::ostringstream oss; - - if (tag) - { - oss << string(*m_tag); - oss << " "; - } - - oss << what; - - if (end) - oss << "\r\n"; - - m_socket->send(oss.str()); -#else - if (tag) - { - m_socket->send(*m_tag); - m_socket->send(" "); - } - - m_socket->send(what); - - if (end) - { - m_socket->send("\r\n"); - } -#endif - - if (tag) - m_firstTag = false; -} - - -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(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 IMAPConnection::getStore() const -{ - return m_store.lock(); -} - - -shared_ptr IMAPConnection::getStore() -{ - return m_store.lock(); -} - - -shared_ptr IMAPConnection::getSession() -{ - return m_store.lock()->getSession(); -} - - -shared_ptr IMAPConnection::getSocket() const -{ - return m_socket; -} - - -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/src/net/imap/IMAPFolder.cpp b/src/net/imap/IMAPFolder.cpp deleted file mode 100644 index fb98887c..00000000 --- a/src/net/imap/IMAPFolder.cpp +++ /dev/null @@ -1,1511 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/message.hpp" - -#include "vmime/exception.hpp" - -#include "vmime/utility/outputStreamAdapter.hpp" - -#include -#include - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPFolder::IMAPFolder(const folder::path& path, shared_ptr store, const int type, const int flags) - : 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_type(type), m_flags(flags) -{ - store->registerFolder(this); - - m_status = make_shared (); -} - - -IMAPFolder::~IMAPFolder() -{ - shared_ptr store = m_store.lock(); - - if (store) - { - if (m_open) - close(false); - - store->unregisterFolder(this); - } - else if (m_open) - { - m_connection = null; - onClose(); - } -} - - -int IMAPFolder::getMode() const -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - return (m_mode); -} - - -int IMAPFolder::getType() -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - // Root folder - if (m_path.isEmpty()) - { - return (TYPE_CONTAINS_FOLDERS); - } - else - { - if (m_type == TYPE_UNDEFINED) - testExistAndGetType(); - - return (m_type); - } -} - - -int IMAPFolder::getFlags() -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - // Root folder - if (m_path.isEmpty()) - { - return (FLAG_CHILDREN | FLAG_NO_OPEN); - } - else - { - if (m_flags == FLAG_UNDEFINED) - testExistAndGetType(); - - return (m_flags); - } -} - - -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 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 ::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 connection = - make_shared (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::ostringstream oss; - - if (mode == MODE_READ_ONLY) - oss << "EXAMINE "; - else - oss << "SELECT "; - - oss << IMAPUtils::quoteString(IMAPUtils::pathToString - (connection->hierarchySeparator(), getFullPath())); - - if (m_connection->hasCapability("CONDSTORE")) - oss << " (CONDSTORE)"; - - connection->send(true, oss.str(), true); - - // Read the response - std::auto_ptr 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"); - } - - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("SELECT", - resp->getErrorLog(), "invalid response"); - } - - const IMAPParser::response_data* responseData = (*it)->response_data(); - - // OK Untagged responses: UNSEEN, PERMANENTFLAGS, UIDVALIDITY (optional) - if (responseData->resp_cond_state()) - { - const IMAPParser::resp_text_code* code = - responseData->resp_cond_state()->resp_text()->resp_text_code(); - - if (code != NULL) - { - 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: - { - m_type = IMAPUtils::folderTypeFromFlags - (responseData->mailbox_data()->mailbox_flag_list()); - - m_flags = IMAPUtils::folderFlagsFromFlags - (responseData->mailbox_data()->mailbox_flag_list()); - - break; - } - - } - } - } - - processStatusUpdate(resp.get()); - - // Check for access mode (read-only or read-write) - const IMAPParser::resp_text_code* respTextCode = resp->response_done()-> - response_tagged()->resp_cond_state()->resp_text()->resp_text_code(); - - 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 store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - shared_ptr 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(); - - oldConnection->send(true, "CLOSE", true); - } - - // 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 (); - - onClose(); -} - - -void IMAPFolder::onClose() -{ - for (std::vector ::iterator it = m_messages.begin() ; - it != m_messages.end() ; ++it) - { - (*it)->onFolderClosed(); - } - - m_messages.clear(); -} - - -void IMAPFolder::create(const int type) -{ - shared_ptr 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 (type & TYPE_CONTAINS_FOLDERS) - mailbox += m_connection->hierarchySeparator(); - - std::ostringstream oss; - oss << "CREATE " << IMAPUtils::quoteString(mailbox); - - m_connection->send(true, oss.str(), true); - - - std::auto_ptr 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 event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_CREATED, m_path, m_path); - - notifyFolder(event); -} - - -void IMAPFolder::destroy() -{ - shared_ptr 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()); - - std::ostringstream oss; - oss << "DELETE " << IMAPUtils::quoteString(mailbox); - - m_connection->send(true, oss.str(), true); - - - std::auto_ptr 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 event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_DELETED, m_path, m_path); - - notifyFolder(event); -} - - -bool IMAPFolder::exists() -{ - shared_ptr store = m_store.lock(); - - if (!isOpen() && !store) - throw exceptions::illegal_state("Store disconnected"); - - return (testExistAndGetType() != TYPE_UNDEFINED); -} - - -int IMAPFolder::testExistAndGetType() -{ - m_type = TYPE_UNDEFINED; - - // 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 - - std::ostringstream oss; - oss << "LIST \"\" "; - oss << IMAPUtils::quoteString(IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath())); - - m_connection->send(true, oss.str(), true); - - - std::auto_ptr 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 - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("LIST", - resp->getErrorLog(), "invalid response"); - } - - const IMAPParser::mailbox_data* mailboxData = - (*it)->response_data()->mailbox_data(); - - // We are only interested in responses of type "LIST" - if (mailboxData != NULL && mailboxData->type() == IMAPParser::mailbox_data::LIST) - { - // Get the folder type/flags at the same time - m_type = IMAPUtils::folderTypeFromFlags - (mailboxData->mailbox_list()->mailbox_flag_list()); - - m_flags = IMAPUtils::folderFlagsFromFlags - (mailboxData->mailbox_list()->mailbox_flag_list()); - } - } - - return (m_type); -} - - -bool IMAPFolder::isOpen() const -{ - return (m_open); -} - - -shared_ptr IMAPFolder::getMessage(const int 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 (dynamicCast (shared_from_this()), num); -} - - -std::vector > IMAPFolder::getMessages(const messageSet& msgs) -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (msgs.isEmpty()) - return std::vector >(); - - std::vector > messages; - - if (msgs.isNumberSet()) - { - const std::vector numbers = IMAPUtils::messageSetToNumberList(msgs); - - shared_ptr thisFolder = dynamicCast (shared_from_this()); - - for (std::vector ::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) - messages.push_back(make_shared (thisFolder, *it)); - } - else if (msgs.isUIDSet()) - { - // 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 - - // Prepare command and arguments - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - - cmd << "UID FETCH " << IMAPUtils::messageSetToSequenceSet(msgs) << " UID"; - - // Send the request - m_connection->send(true, cmd.str(), true); - - // Get the response - std::auto_ptr 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 - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("UID FETCH ... UID", - resp->getErrorLog(), "invalid response"); - } - - const IMAPParser::message_data* messageData = - (*it)->response_data()->message_data(); - - // We are only interested in responses of type "FETCH" - if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) - continue; - - // Get Process fetch response for this message - const int msgNum = static_cast (messageData->number()); - message::uid msgUID; - - // Find UID in message attributes - const std::vector atts = messageData->msg_att()->items(); - - for (std::vector ::const_iterator - it = atts.begin() ; it != atts.end() ; ++it) - { - if ((*it)->type() == IMAPParser::msg_att_item::UID) - { - msgUID = (*it)->unique_id()->value(); - break; - } - } - - if (!msgUID.empty()) - { - shared_ptr thisFolder = dynamicCast (shared_from_this()); - messages.push_back(make_shared (thisFolder, msgNum, msgUID)); - } - } - } - - return messages; -} - - -int 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 IMAPFolder::getFolder(const folder::path::component& name) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - return make_shared (m_path / name, store); -} - - -std::vector > IMAPFolder::getFolders(const bool recursive) -{ - shared_ptr 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 - - std::ostringstream oss; - oss << "LIST "; - - const string pathString = IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath()); - - if (recursive) - { - oss << IMAPUtils::quoteString(pathString); - oss << " *"; - } - else - { - if (pathString.empty()) // don't add sep for root folder - oss << "\"\""; - else - oss << IMAPUtils::quoteString(pathString + m_connection->hierarchySeparator()); - - oss << " %"; - } - - m_connection->send(true, oss.str(), true); - - - std::auto_ptr 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"); - } - - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - - std::vector > v; - - for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("LIST", - resp->getErrorLog(), "invalid response"); - } - - const IMAPParser::mailbox_data* mailboxData = - (*it)->response_data()->mailbox_data(); - - if (mailboxData == NULL || mailboxData->type() != IMAPParser::mailbox_data::LIST) - continue; - - // Get folder path - const class IMAPParser::mailbox* 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 - const class IMAPParser::mailbox_flag_list* mailbox_flag_list = - mailboxData->mailbox_list()->mailbox_flag_list(); - - v.push_back(make_shared (path, store, - IMAPUtils::folderTypeFromFlags(mailbox_flag_list), - IMAPUtils::folderFlagsFromFlags(mailbox_flag_list))); - } - } - - return (v); -} - - -void IMAPFolder::fetchMessages(std::vector >& msg, const fetchAttributes& options, - utility::progressListener* progress) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - // Build message numbers list - std::vector list; - list.reserve(msg.size()); - - std::map > numberToMsg; - - for (std::vector >::iterator it = msg.begin() ; it != msg.end() ; ++it) - { - list.push_back((*it)->getNumber()); - numberToMsg[(*it)->getNumber()] = dynamicCast (*it); - } - - // Send the request - const string command = IMAPUtils::buildFetchRequest - (m_connection, messageSet::byNumber(list), options); - - m_connection->send(true, command, true); - - // Get the response - std::auto_ptr 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"); - } - - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - const size_t total = msg.size(); - size_t current = 0; - - if (progress) - progress->start(total); - - try - { - for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("FETCH", - resp->getErrorLog(), "invalid response"); - } - - const IMAPParser::message_data* messageData = - (*it)->response_data()->message_data(); - - // We are only interested in responses of type "FETCH" - if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) - continue; - - // Process fetch response for this message - const int num = static_cast (messageData->number()); - - std::map >::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(shared_ptr msg, const fetchAttributes& options) -{ - std::vector > msgs; - msgs.push_back(msg); - - fetchMessages(msgs, options, /* progress */ NULL); -} - - -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 IMAPFolder::getParent() -{ - if (m_path.isEmpty()) - return null; - else - return make_shared (m_path.getParent(), m_store.lock()); -} - - -shared_ptr IMAPFolder::getStore() const -{ - return m_store.lock(); -} - - -shared_ptr IMAPFolder::getStore() -{ - return m_store.lock(); -} - - -void IMAPFolder::registerMessage(IMAPMessage* msg) -{ - m_messages.push_back(msg); -} - - -void IMAPFolder::unregisterMessage(IMAPMessage* msg) -{ - std::vector ::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 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"); - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - if (msgs.isUIDSet()) - command << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs); - else - command << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs); - - command << " +FLAGS (\\Deleted)"; - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr 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) -{ - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - if (msgs.isUIDSet()) - command << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs); - else - command << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs); - - switch (mode) - { - case message::FLAG_MODE_ADD: command << " +FLAGS "; break; - case message::FLAG_MODE_REMOVE: command << " -FLAGS "; break; - default: - case message::FLAG_MODE_SET: command << " FLAGS "; break; - } - - const string flagList = IMAPUtils::messageFlagList(flags); - - if (!flagList.empty()) - { - command << flagList; - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr 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::addMessage(shared_ptr 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); - - addMessage(strAdapter, str.length(), flags, date, progress); -} - - -void IMAPFolder::addMessage(utility::inputStream& is, const size_t size, const int flags, - vmime::datetime* date, utility::progressListener* progress) -{ - shared_ptr 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"); - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - command << "APPEND " << IMAPUtils::quoteString(IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath())) << ' '; - - const string flagList = IMAPUtils::messageFlagList(flags); - - if (flags != message::FLAG_UNDEFINED && !flagList.empty()) - { - command << flagList; - command << ' '; - } - - if (date != NULL) - { - command << IMAPUtils::dateTime(*date); - command << ' '; - } - - command << '{' << size << '}'; - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr resp(m_connection->readResponse()); - - bool ok = false; - const std::vector & respList - = resp->continue_req_or_response_data(); - - for (std::vector ::const_iterator - 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"); - } - - // 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 (m_connection->getSocket()->getBlockSize())); - - std::vector vbuffer(blockSize); - byte_t* buffer = &vbuffer.front(); - - while (!is.eof()) - { - // Read some data from the input stream - const size_t read = is.read(buffer, sizeof(buffer)); - current += read; - - // Put read data into socket output stream - m_connection->sendRaw(buffer, read); - - // Notify progress - if (progress) - progress->progress(current, total); - } - - m_connection->send(false, "", true); - - if (progress) - progress->stop(total); - - // Get the response - std::auto_ptr 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(resp.get()); -} - - -void IMAPFolder::expunge() -{ - shared_ptr 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 - m_connection->send(true, "EXPUNGE", true); - - // Get the response - std::auto_ptr 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 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(); - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - command << "RENAME "; - command << IMAPUtils::quoteString(IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath())) << " "; - command << IMAPUtils::quoteString(IMAPUtils::pathToString - (m_connection->hierarchySeparator(), newPath)); - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr 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 event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); - - notifyFolder(event); - - // Notify sub-folders - for (std::list ::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 event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path); - - (*it)->notifyFolder(event); - } - } - - processStatusUpdate(resp.get()); -} - - -void IMAPFolder::copyMessages(const folder::path& dest, const messageSet& set) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - command << "COPY " << IMAPUtils::messageSetToSequenceSet(set) << " "; - command << IMAPUtils::quoteString(IMAPUtils::pathToString - (m_connection->hierarchySeparator(), dest)); - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr 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()); -} - - -void IMAPFolder::status(int& count, int& unseen) -{ - count = 0; - unseen = 0; - - shared_ptr status = getStatus(); - - count = status->getMessageCount(); - unseen = status->getUnseenCount(); -} - - -shared_ptr IMAPFolder::getStatus() -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - command << "STATUS "; - command << IMAPUtils::quoteString(IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath())); - command << " ("; - - command << "MESSAGES" << ' ' << "UNSEEN" << ' ' << "UIDNEXT" << ' ' << "UIDVALIDITY"; - - if (m_connection->hasCapability("CONDSTORE")) - command << ' ' << "HIGHESTMODSEQ"; - - command << ")"; - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr 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"); - } - - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() != NULL) - { - const IMAPParser::response_data* responseData = (*it)->response_data(); - - if (responseData->mailbox_data() && - responseData->mailbox_data()->type() == IMAPParser::mailbox_data::STATUS) - { - shared_ptr status = make_shared (); - 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 store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - m_connection->send(true, "NOOP", true); - - std::auto_ptr 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 IMAPFolder::getMessageNumbersStartingOnUID(const message::uid& uid) -{ - std::vector v; - - std::ostringstream command; - command.imbue(std::locale::classic()); - - command << "SEARCH UID " << uid << ":*"; - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr 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"); - } - - const std::vector & respDataList = resp->continue_req_or_response_data(); - - for (std::vector ::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("SEARCH", - resp->getErrorLog(), "invalid response"); - } - - const IMAPParser::mailbox_data* mailboxData = - (*it)->response_data()->mailbox_data(); - - // We are only interested in responses of type "SEARCH" - if (mailboxData == NULL || - mailboxData->type() != IMAPParser::mailbox_data::SEARCH) - { - continue; - } - - for (std::vector ::const_iterator - it = mailboxData->search_nz_number_list().begin() ; - it != mailboxData->search_nz_number_list().end(); - ++it) - { - v.push_back((*it)->value()); - } - } - - processStatusUpdate(resp.get()); - - return v; -} - - -void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) -{ - std::vector > events; - - shared_ptr 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()) - { - const IMAPParser::resp_text_code* code = - resp->response_done()->response_tagged() - ->resp_cond_state()->resp_text()->resp_text_code(); - - m_status->updateFromResponse(code); - } - - // Process untagged responses - for (std::vector ::const_iterator - 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()) - { - const IMAPParser::resp_text_code* code = - (*it)->response_data()->resp_cond_state()->resp_text()->resp_text_code(); - - m_status->updateFromResponse(code); - } - else if ((*it)->response_data() && (*it)->response_data()->mailbox_data()) - { - m_status->updateFromResponse((*it)->response_data()->mailbox_data()); - } - else if ((*it)->response_data() && (*it)->response_data()->message_data()) - { - const IMAPParser::message_data* msgData = (*it)->response_data()->message_data(); - const int msgNumber = msgData->number(); - - if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::FETCH) - { - // Message changed - for (std::vector ::iterator mit = - m_messages.begin() ; mit != m_messages.end() ; ++mit) - { - if ((*mit)->getNumber() == msgNumber) - (*mit)->processFetchResponse(/* options */ 0, msgData); - } - - events.push_back(make_shared - (dynamicCast (shared_from_this()), - events::messageChangedEvent::TYPE_FLAGS, - std::vector (1, msgNumber))); - } - else if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::EXPUNGE) - { - // A message has been expunged, renumber messages - for (std::vector ::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 - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_REMOVED, - std::vector (1, msgNumber))); - - expungedMessageCount++; - } - } - } - - // New messages arrived - if (m_status->getMessageCount() > oldStatus->getMessageCount() - expungedMessageCount) - { - std::vector newMessageNumbers; - - for (int msgNumber = oldStatus->getMessageCount() - expungedMessageCount ; - msgNumber <= m_status->getMessageCount() ; ++msgNumber) - { - newMessageNumbers.push_back(msgNumber); - } - - events.push_back(make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_ADDED, - newMessageNumbers)); - } - - // Dispatch notifications - for (std::vector >::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/src/net/imap/IMAPFolderStatus.cpp b/src/net/imap/IMAPFolderStatus.cpp deleted file mode 100644 index c78a40f3..00000000 --- a/src/net/imap/IMAPFolderStatus.cpp +++ /dev/null @@ -1,307 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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) -{ -} - - -unsigned int IMAPFolderStatus::getMessageCount() const -{ - return m_count; -} - - -unsigned int IMAPFolderStatus::getUnseenCount() const -{ - return m_unseen; -} - - -unsigned int 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 IMAPFolderStatus::clone() const -{ - return make_shared (*this); -} - - -bool IMAPFolderStatus::updateFromResponse(const IMAPParser::mailbox_data* resp) -{ - bool changed = false; - - if (resp->type() == IMAPParser::mailbox_data::STATUS) - { - const IMAPParser::status_att_list* statusAttList = resp->status_att_list(); - - for (std::vector ::const_iterator - jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt) - { - switch ((*jt)->type()) - { - case IMAPParser::status_att_val::MESSAGES: - { - const unsigned int count = - static_cast ((*jt)->value_as_number()->value()); - - if (m_count != count) - { - m_count = count; - changed = true; - } - - break; - } - case IMAPParser::status_att_val::UNSEEN: - { - const unsigned int unseen = - static_cast ((*jt)->value_as_number()->value()); - - if (m_unseen != unseen) - { - m_unseen = unseen; - changed = true; - } - - break; - } - case IMAPParser::status_att_val::RECENT: - { - const unsigned int recent = - static_cast ((*jt)->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 ((*jt)->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 ((*jt)->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 ((*jt)->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 unsigned int count = - static_cast (resp->number()->value()); - - if (m_count != count) - { - m_count = count; - changed = true; - } - } - else if (resp->type() == IMAPParser::mailbox_data::RECENT) - { - const unsigned int recent = - static_cast (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 (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 (resp->nz_number()->value()); - - if (m_uidNext != uidNext) - { - m_uidNext = uidNext; - changed = true; - } - - break; - } - case IMAPParser::resp_text_code::UNSEEN: - { - const unsigned int unseen = - static_cast (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 (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/src/net/imap/IMAPMessage.cpp b/src/net/imap/IMAPMessage.cpp deleted file mode 100644 index c11aafc2..00000000 --- a/src/net/imap/IMAPMessage.cpp +++ /dev/null @@ -1,649 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include -#include - - -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_os(os), m_progress(progress) - { - } - - target* targetFor(const IMAPParser::component& comp, const int /* data */) - { - if (typeid(comp) == typeid(IMAPParser::msg_att_item)) - { - const int type = static_cast - (comp).type(); - - if (type == IMAPParser::msg_att_item::BODY_SECTION || - type == IMAPParser::msg_att_item::RFC822_TEXT) - { - return new targetStream(m_progress, m_os); - } - } - - return (NULL); - } - -private: - - utility::outputStream& m_os; - utility::progressListener* m_progress; -}; - -#endif // VMIME_BUILDING_DOC - - - -// -// IMAPMessage -// - - -IMAPMessage::IMAPMessage(shared_ptr folder, const int 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(shared_ptr folder, const int 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() -{ - shared_ptr folder = m_folder.lock(); - - if (folder) - folder->unregisterMessage(this); -} - - -void IMAPMessage::onFolderClosed() -{ - m_folder.reset(); -} - - -int 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 IMAPMessage::getStructure() const -{ - if (m_structure == NULL) - throw exceptions::unfetched_object(); - - return m_structure; -} - - -shared_ptr IMAPMessage::getStructure() -{ - if (m_structure == NULL) - throw exceptions::unfetched_object(); - - return m_structure; -} - - -shared_ptr 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 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 - (shared_ptr p, - utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const bool peek) const -{ - shared_ptr 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(shared_ptr p) -{ - shared_ptr 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 (p)->getOrCreateHeader().parse(oss.str()); -} - - -void IMAPMessage::fetchPartHeaderForStructure(shared_ptr str) -{ - for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) - { - shared_ptr part = str->getPartAt(i); - - // Fetch header of current part - fetchPartHeader(part); - - // Fetch header of sub-parts - fetchPartHeaderForStructure(part->getStructure()); - } -} - - -void IMAPMessage::extractImpl - (shared_ptr p, - utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const int extractFlags) const -{ - shared_ptr folder = m_folder.lock(); - - IMAPMessage_literalHandler literalHandler(os, progress); - - // Construct section identifier - std::ostringstream section; - section.imbue(std::locale::classic()); - - if (p != NULL) - { - shared_ptr currentPart = dynamicCast (p); - std::vector 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 ::reverse_iterator it = numbers.rbegin() ; it != numbers.rend() ; ++it) - { - if (it != numbers.rbegin()) section << "."; - section << (*it + 1); - } - } - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - if (m_uid.empty()) - command << "FETCH " << m_num << " BODY"; - else - command << "UID FETCH " << m_uid << " BODY"; - - /* - BODY[] header + body - BODY.PEEK[] header + body (peek) - BODY[HEADER] header - BODY.PEEK[HEADER] header (peek) - BODY[TEXT] body - BODY.PEEK[TEXT] body (peek) - */ - - if (extractFlags & EXTRACT_PEEK) - command << ".PEEK"; - - command << "["; - - if (section.str().empty()) - { - // header + body - if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) - command << ""; - // body only - else if (extractFlags & EXTRACT_BODY) - command << "TEXT"; - // header only - else if (extractFlags & EXTRACT_HEADER) - command << "HEADER"; - } - else - { - command << section.str(); - - // header + body - if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) - throw exceptions::operation_not_supported(); - // body only - else if (extractFlags & EXTRACT_BODY) - command << ".TEXT"; - // header only - else if (extractFlags & EXTRACT_HEADER) - command << ".MIME"; // "MIME" not "HEADER" for parts - } - - command << "]"; - - if (start != 0 || length != static_cast (-1)) - command << "<" << start << "." << length << ">"; - - // Send the request - constCast (folder)->m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr resp - (constCast (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) - } -} - - -int IMAPMessage::processFetchResponse - (const fetchAttributes& options, const IMAPParser::message_data* msgData) -{ - shared_ptr folder = m_folder.lock(); - - // Get message attributes - const std::vector atts = msgData->msg_att()->items(); - int changes = 0; - - for (std::vector ::const_iterator - it = atts.begin() ; it != atts.end() ; ++it) - { - switch ((*it)->type()) - { - case IMAPParser::msg_att_item::FLAGS: - { - int flags = IMAPUtils::messageFlagsFromFlags((*it)->flag_list()); - - if (m_flags != flags) - { - m_flags = flags; - changes |= events::messageChangedEvent::TYPE_FLAGS; - } - - break; - } - case IMAPParser::msg_att_item::UID: - { - m_uid = (*it)->unique_id()->value(); - break; - } - case IMAPParser::msg_att_item::MODSEQ: - { - m_modseq = (*it)->mod_sequence_value()->value(); - break; - } - case IMAPParser::msg_att_item::ENVELOPE: - { - if (!options.has(fetchAttributes::FULL_HEADER)) - { - const IMAPParser::envelope* env = (*it)->envelope(); - shared_ptr 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); - - // Bcc - mailboxList bcc; - IMAPUtils::convertAddressList(*(env->env_bcc()), bcc); - - if (!bcc.isEmpty()) - hdr->Bcc()->setValue(bcc); - } - - break; - } - case IMAPParser::msg_att_item::BODY_STRUCTURE: - { - m_structure = make_shared ((*it)->body()); - break; - } - case IMAPParser::msg_att_item::RFC822_HEADER: - { - getOrCreateHeader()->parse((*it)->nstring()->value()); - break; - } - case IMAPParser::msg_att_item::RFC822_SIZE: - { - m_size = static_cast ((*it)->number()->value()); - break; - } - case IMAPParser::msg_att_item::BODY_SECTION: - { - if (!options.has(fetchAttributes::FULL_HEADER)) - { - if ((*it)->section()->section_text1() && - (*it)->section()->section_text1()->type() - == IMAPParser::section_text::HEADER_FIELDS) - { - header tempHeader; - tempHeader.parse((*it)->nstring()->value()); - - vmime::header& hdr = *getOrCreateHeader(); - std::vector > fields = tempHeader.getFieldList(); - - for (std::vector >::const_iterator jt = fields.begin() ; - jt != fields.end() ; ++jt) - { - hdr.appendField(vmime::clone(*jt)); - } - } - } - - 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
IMAPMessage::getOrCreateHeader() -{ - if (m_header != NULL) - return (m_header); - else - return (m_header = make_shared
()); -} - - -void IMAPMessage::setFlags(const int flags, const int mode) -{ - shared_ptr 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 - (shared_ptr parentPart, shared_ptr str, int level) -{ - if (level == 0) - { - shared_ptr part = str->getPartAt(0); - - // Copy header - shared_ptr hdr = part->getHeader(); - parentPart->getHeader()->copyFrom(*hdr); - - // Initialize body - parentPart->getBody()->setContents - (make_shared - (dynamicCast (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 part = str->getPartAt(i); - - shared_ptr childPart = make_shared (); - - // Copy header - shared_ptr hdr = part->getHeader(); - childPart->getHeader()->copyFrom(*hdr); - - // Initialize body - childPart->getBody()->setContents - (make_shared - (dynamicCast (shared_from_this()), - part, childPart->getBody()->getEncoding())); - - // Add child part - parentPart->getBody()->appendPart(childPart); - - // Construct sub parts - constructParsedMessage(childPart, part->getStructure(), ++level); - } - } -} - - -shared_ptr IMAPMessage::getParsedMessage() -{ - // Fetch structure - shared_ptr structure; - - try - { - structure = getStructure(); - } - catch (exceptions::unfetched_object&) - { - std::vector > msgs; - msgs.push_back(dynamicCast (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 msg = make_shared (); - - constructParsedMessage(msg, structure); - - return msg; -} - - -void IMAPMessage::renumber(const int 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/src/net/imap/IMAPMessagePart.cpp b/src/net/imap/IMAPMessagePart.cpp deleted file mode 100644 index eed885dc..00000000 --- a/src/net/imap/IMAPMessagePart.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const int 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()); -} - - -IMAPMessagePart::IMAPMessagePart(shared_ptr parent, const int 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(); - } - 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_structure = null; -} - - -shared_ptr IMAPMessagePart::getStructure() const -{ - if (m_structure != NULL) - return m_structure; - else - return IMAPMessageStructure::emptyStructure(); -} - - -shared_ptr IMAPMessagePart::getStructure() -{ - if (m_structure != NULL) - return m_structure; - else - return IMAPMessageStructure::emptyStructure(); -} - - -shared_ptr IMAPMessagePart::getParent() const -{ - return m_parent.lock(); -} - - -const mediaType& IMAPMessagePart::getType() const -{ - return m_mediaType; -} - - -size_t IMAPMessagePart::getSize() const -{ - return m_size; -} - - -int IMAPMessagePart::getNumber() const -{ - return m_number; -} - - -shared_ptr IMAPMessagePart::getHeader() const -{ - if (m_header == NULL) - throw exceptions::unfetched_object(); - else - return m_header; -} - - -// static -shared_ptr IMAPMessagePart::create - (shared_ptr parent, const int number, const IMAPParser::body* body) -{ - if (body->body_type_mpart()) - { - shared_ptr part = make_shared (parent, number, body->body_type_mpart()); - part->m_structure = make_shared (part, body->body_type_mpart()->list()); - - return part; - } - else - { - return make_shared (parent, number, body->body_type_1part()); - } -} - - -header& IMAPMessagePart::getOrCreateHeader() -{ - if (m_header != NULL) - return *m_header; - else - return *(m_header = make_shared
()); -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPMessagePartContentHandler.cpp b/src/net/imap/IMAPMessagePartContentHandler.cpp deleted file mode 100644 index 1f53f082..00000000 --- a/src/net/imap/IMAPMessagePartContentHandler.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/inputStreamStringProxyAdapter.hpp" - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPMessagePartContentHandler::IMAPMessagePartContentHandler - (shared_ptr msg, shared_ptr part, const vmime::encoding& encoding) - : m_message(msg), m_part(part), m_encoding(encoding) -{ -} - - -shared_ptr IMAPMessagePartContentHandler::clone() const -{ - return make_shared - (constCast (m_message.lock()), - constCast (m_part.lock()), - m_encoding); -} - - -void IMAPMessagePartContentHandler::generate - (utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength) const -{ - shared_ptr msg = constCast (m_message.lock()); - shared_ptr part = constCast (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::inputStreamStringProxyAdapter in(oss.str()); - - std::ostringstream oss2; - utility::outputStreamAdapter tmp2(oss2); - - shared_ptr theDecoder = m_encoding.getEncoder(); - theDecoder->decode(in, tmp2); - - // Reencode to output stream - string str = oss2.str(); - utility::inputStreamStringAdapter tempIn(str); - - shared_ptr 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 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 msg = constCast (m_message.lock()); - shared_ptr part = constCast (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 theDecoder = m_encoding.getEncoder(); - theDecoder->decode(is, os, &plsa); - } -} - - -void IMAPMessagePartContentHandler::extractRaw - (utility::outputStream& os, utility::progressListener* progress) const -{ - shared_ptr msg = constCast (m_message.lock()); - shared_ptr part = constCast (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/src/net/imap/IMAPMessageStructure.cpp b/src/net/imap/IMAPMessageStructure.cpp deleted file mode 100644 index 8dc333e9..00000000 --- a/src/net/imap/IMAPMessageStructure.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const std::vector & list) -{ - int number = 0; - - for (std::vector ::const_iterator - it = list.begin() ; it != list.end() ; ++it, ++number) - { - m_parts.push_back(IMAPMessagePart::create(parent, number, *it)); - } -} - - -shared_ptr IMAPMessageStructure::getPartAt(const size_t x) const -{ - return m_parts[x]; -} - - -shared_ptr IMAPMessageStructure::getPartAt(const size_t x) -{ - return m_parts[x]; -} - - -size_t IMAPMessageStructure::getPartCount() const -{ - return m_parts.size(); -} - - -// static -shared_ptr IMAPMessageStructure::emptyStructure() -{ - static shared_ptr emptyStructure = make_shared (); - return emptyStructure; -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPSStore.cpp b/src/net/imap/IMAPSStore.cpp deleted file mode 100644 index c9e64f5b..00000000 --- a/src/net/imap/IMAPSStore.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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/src/net/imap/IMAPServiceInfos.cpp b/src/net/imap/IMAPServiceInfos.cpp deleted file mode 100644 index 46dbc2e1..00000000 --- a/src/net/imap/IMAPServiceInfos.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 IMAPServiceInfos::getAvailableProperties() const -{ - std::vector 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/src/net/imap/IMAPStore.cpp b/src/net/imap/IMAPStore.cpp deleted file mode 100644 index a1a8c9ca..00000000 --- a/src/net/imap/IMAPStore.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/exception.hpp" -#include "vmime/platform.hpp" - -#include - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPStore::IMAPStore(shared_ptr sess, shared_ptr auth, const bool secured) - : store(sess, getInfosInstance(), auth), m_connection(null), m_isIMAPS(secured) -{ -} - - -IMAPStore::~IMAPStore() -{ - try - { - if (isConnected()) - disconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -const string IMAPStore::getProtocolName() const -{ - return "imap"; -} - - -shared_ptr IMAPStore::getRootFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (folder::path(), - dynamicCast (shared_from_this())); -} - - -shared_ptr IMAPStore::getDefaultFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (folder::path::component("INBOX"), - dynamicCast (shared_from_this())); -} - - -shared_ptr IMAPStore::getFolder(const folder::path& path) -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (path, dynamicCast (shared_from_this())); -} - - -bool IMAPStore::isValidFolderName(const folder::path::component& /* name */) const -{ - return true; -} - - -void IMAPStore::connect() -{ - if (isConnected()) - throw exceptions::already_connected(); - - m_connection = make_shared - (dynamicCast (shared_from_this()), getAuthenticator()); - - try - { - m_connection->connect(); - } - catch (std::exception&) - { - m_connection = null; - throw; - } -} - - -bool IMAPStore::isConnected() const -{ - return (m_connection && m_connection->isConnected()); -} - - -bool IMAPStore::isIMAPS() const -{ - return m_isIMAPS; -} - - -bool IMAPStore::isSecuredConnection() const -{ - if (m_connection == NULL) - return false; - - return m_connection->isSecuredConnection(); -} - - -shared_ptr IMAPStore::getConnectionInfos() const -{ - if (m_connection == NULL) - return null; - - return m_connection->getConnectionInfos(); -} - - -shared_ptr IMAPStore::getConnection() -{ - return m_connection; -} - - -void IMAPStore::disconnect() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - for (std::list ::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(); - - m_connection->send(true, "NOOP", true); - - std::auto_ptr 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 ::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { - if ((*it)->isOpen()) - (*it)->noop(); - } -} - - -shared_ptr IMAPStore::connection() -{ - return (m_connection); -} - - -void IMAPStore::registerFolder(IMAPFolder* folder) -{ - m_folders.push_back(folder); -} - - -void IMAPStore::unregisterFolder(IMAPFolder* folder) -{ - std::list ::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/src/net/imap/IMAPTag.cpp b/src/net/imap/IMAPTag.cpp deleted file mode 100644 index 14d12788..00000000 --- a/src/net/imap/IMAPTag.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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); -} - - -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 ('0' + (m_number % 1000) / 100); - m_tag[2] = static_cast ('0' + (m_number % 100) / 10); - m_tag[3] = static_cast ('0' + m_number % 10); -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPUtils.cpp b/src/net/imap/IMAPUtils.cpp deleted file mode 100644 index ff81ce71..00000000 --- a/src/net/imap/IMAPUtils.cpp +++ /dev/null @@ -1,758 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include -#include - - -namespace vmime { -namespace net { -namespace imap { - - -// static -const string IMAPUtils::quoteString(const string& text) -{ - // - // ATOM_CHAR ::= - // - // atom_specials ::= "(" / ")" / "{" / SPACE / CTL / - // list_wildcards / quoted_specials - // - // list_wildcards ::= "%" / "*" - // - // quoted_specials ::= <"> / "\" - // - // CHAR ::= - // - // CTL ::= - // - - 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 (static_cast (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 - - // 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 (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; - 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))); -} - - -int IMAPUtils::folderTypeFromFlags(const IMAPParser::mailbox_flag_list* list) -{ - // Get folder type - int type = folder::TYPE_CONTAINS_MESSAGES | folder::TYPE_CONTAINS_FOLDERS; - const std::vector & flags = list->flags(); - - for (std::vector ::const_iterator it = flags.begin() ; - it != flags.end() ; ++it) - { - if ((*it)->type() == IMAPParser::mailbox_flag::NOSELECT) - type &= ~folder::TYPE_CONTAINS_MESSAGES; - } - - if (type & folder::TYPE_CONTAINS_MESSAGES) - type &= ~folder::TYPE_CONTAINS_FOLDERS; - - return (type); -} - - -int IMAPUtils::folderFlagsFromFlags(const IMAPParser::mailbox_flag_list* list) -{ - // Get folder flags - int folderFlags = folder::FLAG_CHILDREN; - const std::vector & flags = list->flags(); - - for (std::vector ::const_iterator it = flags.begin() ; - it != flags.end() ; ++it) - { - if ((*it)->type() == IMAPParser::mailbox_flag::NOSELECT) - folderFlags |= folder::FLAG_NO_OPEN; - else if ((*it)->type() == IMAPParser::mailbox_flag::NOINFERIORS) - folderFlags &= ~folder::FLAG_CHILDREN; - } - - return (folderFlags); -} - - -int IMAPUtils::messageFlagsFromFlags(const IMAPParser::flag_list* list) -{ - const std::vector & flagList = list->flags(); - int flags = 0; - - for (std::vector ::const_iterator - it = flagList.begin() ; it != flagList.end() ; ++it) - { - switch ((*it)->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); -} - - -const string IMAPUtils::messageFlagList(const int flags) -{ - std::vector flagList; - - 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"); - - if (!flagList.empty()) - { - std::ostringstream res; - res.imbue(std::locale::classic()); - - res << "("; - - if (flagList.size() >= 2) - { - std::copy(flagList.begin(), flagList.end() - 1, - std::ostream_iterator (res, " ")); - } - - res << *(flagList.end() - 1) << ")"; - - return (res.str()); - } - - return ""; -} - - -// 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 -const string IMAPUtils::buildFetchRequest - (shared_ptr 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 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->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 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 customHeaderFields = options.getHeaderFields(); - std::copy(customHeaderFields.begin(), customHeaderFields.end(), std::back_inserter(headerFields)); - - if (!headerFields.empty()) - { - string list; - - for (std::vector ::iterator it = headerFields.begin() ; - it != headerFields.end() ; ++it) - { - if (it != headerFields.begin()) - list += " "; - - list += *it; - } - - items.push_back("BODY[HEADER.FIELDS (" + list + ")]"); - } - } - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - if (msgs.isUIDSet()) - command << "UID FETCH " << messageSetToSequenceSet(msgs) << " ("; - else - command << "FETCH " << messageSetToSequenceSet(msgs) << " ("; - - for (std::vector ::const_iterator it = items.begin() ; - it != items.end() ; ++it) - { - if (it != items.begin()) command << " "; - command << *it; - } - - command << ")"; - - return command.str(); -} - - -// static -void IMAPUtils::convertAddressList - (const IMAPParser::address_list& src, mailboxList& dest) -{ - for (std::vector ::const_iterator - it = src.addresses().begin() ; it != src.addresses().end() ; ++it) - { - const IMAPParser::address& addr = **it; - - text name; - text::decodeAndUnfold(addr.addr_name()->value(), &name); - - string email = addr.addr_mailbox()->value() - + "@" + addr.addr_host()->value(); - - dest.appendMailbox(make_shared (name, email)); - } -} - - - -class IMAPUIDMessageSetEnumerator : public messageSetEnumerator -{ -public: - - IMAPUIDMessageSetEnumerator() - : m_first(true) - { - } - - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { - if (!m_first) - m_oss << ","; - - if (range.getFirst() == range.getLast()) - 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 - 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 (int 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 & list() const - { - return m_list; - } - -public: - - std::vector m_list; -}; - - - -// static -const string IMAPUtils::messageSetToSequenceSet(const messageSet& msgs) -{ - IMAPUIDMessageSetEnumerator en; - msgs.enumerate(en); - - return en.str(); -} - - -// static -const std::vector IMAPUtils::messageSetToNumberList(const messageSet& msgs) -{ - IMAPMessageSetEnumerator en; - msgs.enumerate(en); - - return en.list(); -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/maildir/format/courierMaildirFormat.cpp b/src/net/maildir/format/courierMaildirFormat.cpp deleted file mode 100644 index 6d460d5e..00000000 --- a/src/net/maildir/format/courierMaildirFormat.cpp +++ /dev/null @@ -1,542 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr ctx) - : maildirFormat(ctx) -{ -} - - -const string courierMaildirFormat::getName() const -{ - return "courier"; -} - - -void courierMaildirFormat::createFolder(const folder::path& path) -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) - throw exceptions::invalid_folder_name(); - - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); - - shared_ptr newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); - - rootDir->createDirectory(true); - - newDir->createDirectory(false); - tmpDir->createDirectory(false); - curDir->createDirectory(false); - - shared_ptr maildirFile = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY) - / utility::file::path::component("maildirfolder")); - - maildirFile->createFile(); -} - - -void courierMaildirFormat::destroyFolder(const folder::path& path) -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - // Recursively delete directories of subfolders - const std::vector folders = listFolders(path, true); - - for (std::vector ::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 folders = listFolders(oldPath, true); - - for (std::vector ::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 fsf = platform::getHandler()->getFileSystemFactory(); - - const utility::file::path oldFSPath = - folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY); - - const utility::file::path newFSPath = - folderPathToFileSystemPath(newPath, ROOT_DIRECTORY); - - shared_ptr rootDir = fsf->create(oldFSPath); - rootDir->rename(newFSPath); -} - - -bool courierMaildirFormat::folderExists(const folder::path& path) const -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); - - shared_ptr newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); - - shared_ptr 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 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 courierMaildirFormat::listFolders - (const folder::path& root, const bool recursive) const -{ - // First, list directories - std::vector dirs; - listDirectories(root, dirs, false); - - // Then, map directories to folders - std::vector folders; - - for (std::vector ::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 & dirs, const bool onlyTestForExistence) const -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr 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 it = rootDir->getFiles(); - - while (it->hasMoreElements()) - { - shared_ptr 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 fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr 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 it = rootDir->getFiles(); - - while (it->hasMoreElements()) - { - shared_ptr file = it->nextElement(); - - if (isSubfolderDirectory(*file)) - { - shared_ptr 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/src/net/maildir/format/kmailMaildirFormat.cpp b/src/net/maildir/format/kmailMaildirFormat.cpp deleted file mode 100644 index 975752a5..00000000 --- a/src/net/maildir/format/kmailMaildirFormat.cpp +++ /dev/null @@ -1,320 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr ctx) - : maildirFormat(ctx) -{ -} - - -const string kmailMaildirFormat::getName() const -{ - return "kmail"; -} - - -void kmailMaildirFormat::createFolder(const folder::path& path) -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) - throw exceptions::invalid_folder_name(); - - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); - - shared_ptr newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr 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 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 fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); - - shared_ptr newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr 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 kmailMaildirFormat::listFolders - (const folder::path& root, const bool recursive) const -{ - std::vector list; - listFoldersImpl(list, root, recursive); - - return list; -} - - -void kmailMaildirFormat::listFoldersImpl - (std::vector & list, const folder::path& root, const bool recursive) const -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr rootDir = fsf->create(folderPathToFileSystemPath(root, - root.isEmpty() ? ROOT_DIRECTORY : CONTAINER_DIRECTORY)); - - if (rootDir->exists()) - { - shared_ptr it = rootDir->getFiles(); - - while (it->hasMoreElements()) - { - shared_ptr 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 fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY)); - shared_ptr 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 fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, CONTAINER_DIRECTORY)); - - shared_ptr it = rootDir->getFiles(); - - while (it->hasMoreElements()) - { - shared_ptr 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/src/net/maildir/maildirFolder.cpp b/src/net/maildir/maildirFolder.cpp deleted file mode 100644 index 660178ff..00000000 --- a/src/net/maildir/maildirFolder.cpp +++ /dev/null @@ -1,1254 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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, shared_ptr 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() -{ - shared_ptr store = m_store.lock(); - - if (store) - { - if (m_open) - close(false); - - store->unregisterFolder(this); - } - else if (m_open) - { - close(false); - } -} - - -void maildirFolder::onStoreDisconnected() -{ - m_store.reset(); -} - - -int maildirFolder::getMode() const -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - return (m_mode); -} - - -int maildirFolder::getType() -{ - if (m_path.isEmpty()) - return (TYPE_CONTAINS_FOLDERS); - else - return (TYPE_CONTAINS_FOLDERS | TYPE_CONTAINS_MESSAGES); -} - - -int maildirFolder::getFlags() -{ - int flags = 0; - - if (m_store.lock()->getFormat()->folderHasSubfolders(m_path)) - flags |= FLAG_CHILDREN; // Contains at least one sub-folder - - return (flags); -} - - -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 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 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 ::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 ::iterator it = - std::find(m_messages.begin(), m_messages.end(), msg); - - if (it != m_messages.end()) - m_messages.erase(it); -} - - -void maildirFolder::create(const int /* type */) -{ - shared_ptr 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 event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_CREATED, m_path, m_path); - - notifyFolder(event); -} - - -void maildirFolder::destroy() -{ - shared_ptr 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 event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_DELETED, m_path, m_path); - - notifyFolder(event); -} - - -bool maildirFolder::exists() -{ - shared_ptr store = m_store.lock(); - - return store->getFormat()->folderExists(m_path); -} - - -bool maildirFolder::isOpen() const -{ - return (m_open); -} - - -void maildirFolder::scanFolder() -{ - shared_ptr store = m_store.lock(); - - try - { - m_messageCount = 0; - m_unreadMessageCount = 0; - - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - utility::file::path newDirPath = store->getFormat()->folderPathToFileSystemPath - (m_path, maildirFormat::NEW_DIRECTORY); - shared_ptr newDir = fsf->create(newDirPath); - - utility::file::path curDirPath = store->getFormat()->folderPathToFileSystemPath - (m_path, maildirFormat::CUR_DIRECTORY); - shared_ptr curDir = fsf->create(curDirPath); - - // New received messages (new/) - shared_ptr nit = newDir->getFiles(); - std::vector newMessageFilenames; - - while (nit->hasMoreElements()) - { - shared_ptr file = nit->nextElement(); - - if (maildirUtils::isMessageFile(*file)) - newMessageFilenames.push_back(file->getFullPath().getLastComponent()); - } - - // Current messages (cur/) - shared_ptr cit = curDir->getFiles(); - std::vector curMessageFilenames; - - while (cit->hasMoreElements()) - { - shared_ptr file = cit->nextElement(); - - if (maildirUtils::isMessageFile(*file)) - curMessageFilenames.push_back(file->getFullPath().getLastComponent()); - } - - // Update/delete existing messages (found in previous scan) - for (unsigned int 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 ::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 ::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 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 ::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 - int unreadMessageCount = 0; - - for (std::vector ::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 = m_messageInfos.size(); - } - catch (exceptions::filesystem_exception&) - { - // Should not happen... - } -} - - -shared_ptr maildirFolder::getMessage(const int num) -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (num < 1 || num > m_messageCount) - throw exceptions::message_not_found(); - - return make_shared - (dynamicCast (shared_from_this()), num); -} - - -std::vector > maildirFolder::getMessages(const messageSet& msgs) -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (msgs.isNumberSet()) - { - const std::vector numbers = maildirUtils::messageSetToNumberList(msgs); - - std::vector > messages; - shared_ptr thisFolder = dynamicCast (shared_from_this()); - - for (std::vector ::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 (thisFolder, *it)); - } - - return messages; - } - else - { - throw exceptions::operation_not_supported(); - } -} - - -int maildirFolder::getMessageCount() -{ - return (m_messageCount); -} - - -shared_ptr maildirFolder::getFolder(const folder::path::component& name) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - return make_shared (m_path / name, store); -} - - -std::vector > maildirFolder::getFolders(const bool recursive) -{ - shared_ptr store = m_store.lock(); - - if (!isOpen() && !store) - throw exceptions::illegal_state("Store disconnected"); - - std::vector > list; - - listFolders(list, recursive); - - return (list); -} - - -void maildirFolder::listFolders(std::vector >& list, const bool recursive) -{ - shared_ptr store = m_store.lock(); - - try - { - std::vector pathList = - store->getFormat()->listFolders(m_path, recursive); - - list.reserve(pathList.size()); - - for (std::vector ::size_type i = 0, n = pathList.size() ; i < n ; ++i) - { - shared_ptr subFolder = - make_shared (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 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 event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); - - notifyFolder(event); - - // Notify folders with the same path - for (std::list ::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 event = - make_shared - (dynamicCast ((*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 event = - make_shared - (dynamicCast ((*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 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 nums = maildirUtils::messageSetToNumberList(msgs); - - // Change message flags - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - utility::file::path curDirPath = store->getFormat()-> - folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); - - for (std::vector ::const_iterator it = - nums.begin() ; it != nums.end() ; ++it) - { - const int num = *it - 1; - - try - { - const utility::file::path::component path = m_messageInfos[num].path; - shared_ptr 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 ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags |= flags; - } - } - - break; - } - case message::FLAG_MODE_REMOVE: - { - for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags &= ~flags; - } - } - - break; - } - default: - case message::FLAG_MODE_SET: - { - for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags = flags; - } - } - - break; - } - - } - - // Notify message flags changed - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageChangedEvent::TYPE_FLAGS, nums); - - notifyMessageChanged(event); - - // TODO: notify other folders with the same path - } - else - { - throw exceptions::operation_not_supported(); - } -} - - -void maildirFolder::addMessage(shared_ptr 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); - - addMessage(strAdapter, str.length(), flags, date, progress); -} - - -void maildirFolder::addMessage(utility::inputStream& is, const size_t size, - const int flags, vmime::datetime* /* date */, utility::progressListener* progress) -{ - shared_ptr 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 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 == message::FLAG_UNDEFINED) ? 0 : flags)); - - try - { - shared_ptr tmpDir = fsf->create(tmpDirPath); - tmpDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { - // Don't throw now, it will fail later... - } - - try - { - shared_ptr 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 == message::FLAG_UNDEFINED) || !(flags & message::FLAG_SEEN)) - m_unreadMessageCount++; - - // Notification - std::vector nums; - nums.push_back(m_messageCount); - - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list ::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 event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); - - (*it)->notifyMessageCount(event); - } - } -} - - -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 fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr file = fsf->create(tmpDirPath / filename); - - if (progress) - progress->start(size); - - // First, write the message into 'tmp'... - try - { - file->createFile(); - - shared_ptr fw = file->getFileWriter(); - shared_ptr 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 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 file = fsf->create(dstDirPath / filename); - file->remove(); - } - catch (exceptions::filesystem_exception&) - { - // Ignore - } - - throw exceptions::command_error("ADD", "", "", e); - } - - if (progress) - progress->stop(size); -} - - -void maildirFolder::copyMessages(const folder::path& dest, const messageSet& msgs) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - shared_ptr 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 destTmpDir = fsf->create(destTmpDirPath); - destTmpDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { - // Don't throw now, it will fail later... - } - - try - { - shared_ptr destCurDir = fsf->create(destCurDirPath); - destCurDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { - // Don't throw now, it will fail later... - } - - // Copy messages - const std::vector nums = maildirUtils::messageSetToNumberList(msgs); - - try - { - for (std::vector ::const_iterator it = - nums.begin() ; it != nums.end() ; ++it) - { - const int 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 file = fsf->create(curDirPath / msg.path); - shared_ptr fr = file->getFileReader(); - shared_ptr is = fr->getInputStream(); - - copyMessageImpl(destTmpDirPath, destCurDirPath, - filename, *is, file->getLength(), NULL); - } - } - catch (exception& e) - { - notifyMessagesCopied(dest); - throw exceptions::command_error("COPY", "", "", e); - } - - notifyMessagesCopied(dest); -} - - -void maildirFolder::notifyMessagesCopied(const folder::path& dest) -{ - shared_ptr store = m_store.lock(); - - for (std::list ::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. - int count, unseen; - (*it)->status(count, unseen); - - return; - } - } -} - - -void maildirFolder::status(int& count, int& unseen) -{ - count = 0; - unseen = 0; - - shared_ptr status = getStatus(); - - count = status->getMessageCount(); - unseen = status->getUnseenCount(); -} - - -shared_ptr maildirFolder::getStatus() -{ - shared_ptr store = m_store.lock(); - - const int oldCount = m_messageCount; - - scanFolder(); - - shared_ptr status = make_shared (); - - status->setMessageCount(m_messageCount); - status->setUnseenCount(m_unreadMessageCount); - - // Notify message count changed (new messages) - if (m_messageCount > oldCount) - { - std::vector nums; - nums.reserve(m_messageCount - oldCount); - - for (int i = oldCount + 1, j = 0 ; i <= m_messageCount ; ++i, ++j) - nums[j] = i; - - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list ::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 event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); - - (*it)->notifyMessageCount(event); - } - } - } - - return status; -} - - -void maildirFolder::expunge() -{ - shared_ptr 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 fsf = platform::getHandler()->getFileSystemFactory(); - - utility::file::path curDirPath = store->getFormat()-> - folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); - - std::vector nums; - int unreadCount = 0; - - for (int 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 ::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 file = fsf->create(curDirPath / infos.path); - file->remove(); - } - catch (exceptions::filesystem_exception& e) - { - // Ignore (not important) - } - } - } - - if (!nums.empty()) - { - for (std::vector ::size_type i = nums.size() ; i != 0 ; --i) - m_messageInfos.erase(m_messageInfos.begin() + (i - 1)); - } - - m_messageCount -= nums.size(); - m_unreadMessageCount -= unreadCount; - - // Notify message expunged - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_REMOVED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list ::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 event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::messageCountEvent::TYPE_REMOVED, nums); - - (*it)->notifyMessageCount(event); - } - } -} - - -shared_ptr maildirFolder::getParent() -{ - if (m_path.isEmpty()) - return null; - else - return make_shared (m_path.getParent(), m_store.lock()); -} - - -shared_ptr maildirFolder::getStore() const -{ - return m_store.lock(); -} - - -shared_ptr maildirFolder::getStore() -{ - return m_store.lock(); -} - - -void maildirFolder::fetchMessages(std::vector >& msg, - const fetchAttributes& options, utility::progressListener* progress) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - const size_t total = msg.size(); - size_t current = 0; - - if (progress) - progress->start(total); - - shared_ptr thisFolder = dynamicCast (shared_from_this()); - - for (std::vector >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - dynamicCast (*it)->fetch(thisFolder, options); - - if (progress) - progress->progress(++current, total); - } - - if (progress) - progress->stop(total); -} - - -void maildirFolder::fetchMessage(shared_ptr msg, const fetchAttributes& options) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - dynamicCast (msg)->fetch - (dynamicCast (shared_from_this()), options); -} - - -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 int 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 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/src/net/maildir/maildirFolderStatus.cpp b/src/net/maildir/maildirFolderStatus.cpp deleted file mode 100644 index 9ee84dba..00000000 --- a/src/net/maildir/maildirFolderStatus.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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) -{ -} - - -unsigned int maildirFolderStatus::getMessageCount() const -{ - return m_count; -} - - -unsigned int maildirFolderStatus::getUnseenCount() const -{ - return m_unseen; -} - - -void maildirFolderStatus::setMessageCount(const unsigned int count) -{ - m_count = count; -} - - -void maildirFolderStatus::setUnseenCount(const unsigned int unseen) -{ - m_unseen = unseen; -} - - -shared_ptr maildirFolderStatus::clone() const -{ - return make_shared (*this); -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR diff --git a/src/net/maildir/maildirFormat.cpp b/src/net/maildir/maildirFormat.cpp deleted file mode 100644 index f7a3c8fe..00000000 --- a/src/net/maildir/maildirFormat.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr store) - : m_store(store) -{ -} - - -shared_ptr maildirFormat::context::getStore() const -{ - return constCast (m_store.lock()); -} - - -// -// maildirFormat -// - -maildirFormat::maildirFormat(shared_ptr ctx) - : m_context(ctx) -{ -} - - -shared_ptr maildirFormat::getContext() -{ - return m_context; -} - - -shared_ptr maildirFormat::getContext() const -{ - return m_context; -} - - -// static -shared_ptr maildirFormat::detect(shared_ptr store) -{ - shared_ptr ctx = make_shared (store); - - // Try Courier format - shared_ptr fmt = make_shared (ctx); - - if (fmt->supports()) - return fmt; - - // Default is KMail format - return make_shared (ctx); -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - diff --git a/src/net/maildir/maildirMessage.cpp b/src/net/maildir/maildirMessage.cpp deleted file mode 100644 index a14f067e..00000000 --- a/src/net/maildir/maildirMessage.cpp +++ /dev/null @@ -1,369 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr folder, const int 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() -{ - shared_ptr folder = m_folder.lock(); - - if (folder) - folder->unregisterMessage(this); -} - - -void maildirMessage::onFolderClosed() -{ - m_folder.reset(); -} - - -int 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 (-1)) - throw exceptions::unfetched_object(); - - return (m_size); -} - - -bool maildirMessage::isExpunged() const -{ - return (m_expunged); -} - - -shared_ptr maildirMessage::getStructure() const -{ - if (m_structure == NULL) - throw exceptions::unfetched_object(); - - return m_structure; -} - - -shared_ptr maildirMessage::getStructure() -{ - if (m_structure == NULL) - throw exceptions::unfetched_object(); - - return m_structure; -} - - -shared_ptr maildirMessage::getHeader() const -{ - if (m_header == NULL) - 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 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(shared_ptr p, utility::outputStream& os, - utility::progressListener* progress, const size_t start, - const size_t length, const bool peek) const -{ - shared_ptr mp = dynamicCast (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 folder = m_folder.lock(); - - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - const utility::file::path path = folder->getMessageFSPath(m_num); - shared_ptr file = fsf->create(path); - - shared_ptr reader = file->getFileReader(); - shared_ptr is = reader->getInputStream(); - - is->skip(start + partialStart); - - byte_t buffer[8192]; - size_t remaining = (partialLength == static_cast (-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(shared_ptr p) -{ - shared_ptr folder = m_folder.lock(); - - shared_ptr mp = dynamicCast (p); - - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - const utility::file::path path = folder->getMessageFSPath(m_num); - shared_ptr file = fsf->create(path); - - shared_ptr reader = file->getFileReader(); - shared_ptr 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(shared_ptr msgFolder, const fetchAttributes& options) -{ - shared_ptr folder = m_folder.lock(); - - if (folder != msgFolder) - throw exceptions::folder_not_found(); - - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - const utility::file::path path = folder->getMessageFSPath(m_num); - shared_ptr 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 reader = file->getFileReader(); - shared_ptr 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 (shared_ptr (), 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
maildirMessage::getOrCreateHeader() -{ - if (m_header != NULL) - return (m_header); - else - return (m_header = make_shared
()); -} - - -shared_ptr maildirMessage::getParsedMessage() -{ - std::ostringstream oss; - utility::outputStreamAdapter os(oss); - - extract(os); - - shared_ptr msg = make_shared (); - msg->parse(oss.str()); - - return msg; -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - diff --git a/src/net/maildir/maildirMessagePart.cpp b/src/net/maildir/maildirMessagePart.cpp deleted file mode 100644 index 6ae085c9..00000000 --- a/src/net/maildir/maildirMessagePart.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const int 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(); -} - - -maildirMessagePart::~maildirMessagePart() -{ -} - - -void maildirMessagePart::initStructure(const bodyPart& part) -{ - if (part.getBody()->getPartList().size() == 0) - m_structure = null; - else - { - m_structure = make_shared - (dynamicCast (shared_from_this()), - part.getBody()->getPartList()); - } -} - - -shared_ptr maildirMessagePart::getStructure() const -{ - if (m_structure != NULL) - return m_structure; - else - return maildirMessageStructure::emptyStructure(); -} - - -shared_ptr maildirMessagePart::getStructure() -{ - if (m_structure != NULL) - return m_structure; - else - return maildirMessageStructure::emptyStructure(); -} - - -const mediaType& maildirMessagePart::getType() const -{ - return m_mediaType; -} - - -size_t maildirMessagePart::getSize() const -{ - return m_size; -} - - -int maildirMessagePart::getNumber() const -{ - return m_number; -} - - -shared_ptr maildirMessagePart::getHeader() const -{ - if (m_header == NULL) - throw exceptions::unfetched_object(); - else - return m_header; -} - - -header& maildirMessagePart::getOrCreateHeader() -{ - if (m_header != NULL) - return *m_header; - else - return *(m_header = make_shared
()); -} - - -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/src/net/maildir/maildirMessageStructure.cpp b/src/net/maildir/maildirMessageStructure.cpp deleted file mode 100644 index f3b7cf59..00000000 --- a/src/net/maildir/maildirMessageStructure.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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::m_emptyStructure = make_shared (); - - -maildirMessageStructure::maildirMessageStructure() -{ -} - - -maildirMessageStructure::maildirMessageStructure(shared_ptr parent, const bodyPart& part) -{ - shared_ptr mpart = make_shared (parent, 0, part); - mpart->initStructure(part); - - m_parts.push_back(mpart); -} - - -maildirMessageStructure::maildirMessageStructure(shared_ptr parent, const std::vector >& list) -{ - for (unsigned int i = 0 ; i < list.size() ; ++i) - { - shared_ptr mpart = make_shared (parent, i, *list[i]); - mpart->initStructure(*list[i]); - - m_parts.push_back(mpart); - } -} - - -shared_ptr maildirMessageStructure::getPartAt(const size_t x) const -{ - return m_parts[x]; -} - - -shared_ptr maildirMessageStructure::getPartAt(const size_t x) -{ - return m_parts[x]; -} - - -size_t maildirMessageStructure::getPartCount() const -{ - return m_parts.size(); -} - - -// static -shared_ptr maildirMessageStructure::emptyStructure() -{ - return m_emptyStructure; -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR diff --git a/src/net/maildir/maildirServiceInfos.cpp b/src/net/maildir/maildirServiceInfos.cpp deleted file mode 100644 index 974a0c21..00000000 --- a/src/net/maildir/maildirServiceInfos.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 maildirServiceInfos::getAvailableProperties() const -{ - std::vector 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/src/net/maildir/maildirStore.cpp b/src/net/maildir/maildirStore.cpp deleted file mode 100644 index 87e733e2..00000000 --- a/src/net/maildir/maildirStore.cpp +++ /dev/null @@ -1,272 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 (getSession(), \ - dynamic_cast (getInfos()).getProperties().prop)) -#define HAS_PROPERTY(prop) \ - (getInfos().hasProperty(getSession(), \ - dynamic_cast (getInfos()).getProperties().prop)) - - -namespace vmime { -namespace net { -namespace maildir { - - -maildirStore::maildirStore(shared_ptr sess, shared_ptr auth) - : store(sess, getInfosInstance(), auth), m_connected(false) -{ -} - - -maildirStore::~maildirStore() -{ - try - { - if (isConnected()) - disconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -const string maildirStore::getProtocolName() const -{ - return "maildir"; -} - - -shared_ptr maildirStore::getRootFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (folder::path(), - dynamicCast (shared_from_this())); -} - - -shared_ptr maildirStore::getDefaultFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (folder::path::component("inbox"), - dynamicCast (shared_from_this())); -} - - -shared_ptr maildirStore::getFolder(const folder::path& path) -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (path, dynamicCast (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(); - int 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 fsf = platform::getHandler()->getFileSystemFactory(); - - m_fsPath = fsf->stringToPath(GET_PROPERTY(string, PROPERTY_SERVER_ROOTPATH)); - - shared_ptr 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 (shared_from_this())); - - m_connected = true; -} - - -bool maildirStore::isConnected() const -{ - return (m_connected); -} - - -bool maildirStore::isSecuredConnection() const -{ - return false; -} - - -shared_ptr maildirStore::getConnectionInfos() const -{ - return make_shared ("localhost", static_cast (0)); -} - - -void maildirStore::disconnect() -{ - for (std::list ::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 maildirStore::getFormat() -{ - return m_format; -} - - -shared_ptr maildirStore::getFormat() const -{ - return m_format; -} - - -void maildirStore::registerFolder(maildirFolder* folder) -{ - m_folders.push_back(folder); -} - - -void maildirStore::unregisterFolder(maildirFolder* folder) -{ - std::list ::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/src/net/maildir/maildirUtils.cpp b/src/net/maildir/maildirUtils.cpp deleted file mode 100644 index 77aac715..00000000 --- a/src/net/maildir/maildirUtils.cpp +++ /dev/null @@ -1,273 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr dir) -{ - shared_ptr files = dir->getFiles(); - - // First, delete files and subdirectories in this directory - while (files->hasMoreElements()) - { - shared_ptr 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: - - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { - for (int i = range.getFirst(), last = range.getLast() ; i <= last ; ++i) - list.push_back(i); - } - - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) - { - // Not supported - } - -public: - - std::vector list; -}; - - -// static -const std::vector maildirUtils::messageSetToNumberList(const messageSet& msgs) -{ - maildirMessageSetEnumerator en; - 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/src/net/message.cpp b/src/net/message.cpp deleted file mode 100644 index 6765e73c..00000000 --- a/src/net/message.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace net { - - -shared_ptr messagePart::getPartAt(const size_t pos) const -{ - return getStructure()->getPartAt(pos); -} - - -shared_ptr 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 (uid); - return os; -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/messageSet.cpp b/src/net/messageSet.cpp deleted file mode 100644 index 2939042e..00000000 --- a/src/net/messageSet.cpp +++ /dev/null @@ -1,369 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/messageSet.hpp" - -#include -#include -#include - - -namespace vmime { -namespace net { - - -// messageRange - -messageRange::messageRange() -{ -} - - -messageRange::~messageRange() -{ -} - - -// numberMessageRange - -numberMessageRange::numberMessageRange(const int number) - : m_first(number), m_last(number) -{ - if (number < 1) - throw std::invalid_argument("number"); -} - - -numberMessageRange::numberMessageRange(const int first, const int last) - : m_first(first), m_last(last) -{ - if (first < 1) - throw std::invalid_argument("first"); - else if (last != -1 && last < first) - throw std::invalid_argument("last"); -} - - -numberMessageRange::numberMessageRange(const numberMessageRange& other) - : messageRange(), m_first(other.m_first), m_last(other.m_last) -{ -} - - -int numberMessageRange::getFirst() const -{ - return m_first; -} - - -int 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::byNumber(const int number) -{ - messageSet set; - set.m_ranges.push_back(new numberMessageRange(number)); - - return set; -} - - -// static -messageSet messageSet::byNumber(const int first, const int last) -{ - messageSet set; - set.m_ranges.push_back(new numberMessageRange(first, last)); - - return set; -} - - -// static -messageSet messageSet::byNumber(const std::vector & numbers) -{ - // Sort a copy of the list - std::vector 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 - int previous = -1, rangeStart = -1; - messageSet set; - - for (std::vector ::const_iterator it = sortedNumbers.begin() ; - it != sortedNumbers.end() ; ++it) - { - const int current = *it; - - if (current == previous) - continue; // skip duplicates - - if (previous == -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 & uids) -{ - std::vector 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 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 = -1U, rangeStart = -1U; - messageSet set; - - for (std::vector ::const_iterator it = sortedUIDs.begin() ; - it != sortedUIDs.end() ; ++it) - { - const vmime_uint32 current = *it; - - if (current == previous) - continue; // skip duplicates - - if (previous == -1U) - { - 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 (m_ranges[0]) != NULL; -} - - -bool messageSet::isUIDSet() const -{ - return !isEmpty() && dynamic_cast (m_ranges[0]) != NULL; -} - - -} // net -} // vmime diff --git a/src/net/pop3/POP3Command.cpp b/src/net/pop3/POP3Command.cpp deleted file mode 100644 index 6fe301ce..00000000 --- a/src/net/pop3/POP3Command.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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) - : m_text(text) -{ -} - - -// static -shared_ptr POP3Command::CAPA() -{ - return createCommand("CAPA"); -} - - -// static -shared_ptr POP3Command::NOOP() -{ - return createCommand("NOOP"); -} - - -// static -shared_ptr POP3Command::AUTH(const string& mechName) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "AUTH " << mechName; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr POP3Command::STLS() -{ - return createCommand("STLS"); -} - - -// static -shared_ptr 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::USER(const string& username) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "USER " << username; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr POP3Command::PASS(const string& password) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "PASS " << password; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr POP3Command::STAT() -{ - return createCommand("STAT"); -} - - -// static -shared_ptr POP3Command::LIST() -{ - return createCommand("LIST"); -} - - -// static -shared_ptr 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::UIDL() -{ - return createCommand("UIDL"); -} - - -// static -shared_ptr 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::DELE(const unsigned long msg) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "DELE " << msg; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr 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::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::RSET() -{ - return createCommand("RSET"); -} - - -// static -shared_ptr POP3Command::QUIT() -{ - return createCommand("QUIT"); -} - - -// static -shared_ptr POP3Command::createCommand(const string& text) -{ - return shared_ptr (new POP3Command(text)); -} - - -const string POP3Command::getText() const -{ - return m_text; -} - - -void POP3Command::send(shared_ptr conn) -{ - conn->getSocket()->send(m_text + "\r\n"); -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/src/net/pop3/POP3Connection.cpp b/src/net/pop3/POP3Connection.cpp deleted file mode 100644 index 5fa923f4..00000000 --- a/src/net/pop3/POP3Connection.cpp +++ /dev/null @@ -1,675 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 (getSession(), \ - dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) -#define HAS_PROPERTY(prop) \ - (m_store.lock()->getInfos().hasProperty(getSession(), \ - dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) - - -namespace vmime { -namespace net { -namespace pop3 { - - - -POP3Connection::POP3Connection(shared_ptr store, shared_ptr auth) - : m_store(store), m_auth(auth), m_socket(null), m_timeoutHandler(null), - m_authenticated(false), m_secured(false), m_capabilitiesFetched(false) -{ -} - - -POP3Connection::~POP3Connection() -{ - try - { - if (isConnected()) - disconnect(); - else if (m_socket) - internalDisconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -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 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); - -#if VMIME_HAVE_TLS_SUPPORT - if (store->isPOP3S()) // dedicated port/POP3S - { - shared_ptr tlsSession = tls::TLSSession::create - (store->getCertificateVerifier(), - store->getSession()->getTLSProperties()); - - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); - - m_socket = tlsSocket; - - m_secured = true; - m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); - } - else -#endif // VMIME_HAVE_TLS_SUPPORT - { - m_cntInfos = make_shared (address, port); - } - - m_socket->connect(address, port); - - // Connection - // - // eg: C: - // --- S: +OK MailSite POP3 Server 5.3.4.0 Ready <36938848.1056800841.634@somewhere.com> - - shared_ptr response = POP3Response::readResponse - (dynamicCast (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 (shared_from_this())); - POP3Response::readResponse(dynamicCast (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& e) - { - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) - { - // Can't fallback on APOP/normal authentication - internalDisconnect(); - throw e; - } - else - { - // Ignore, will try APOP/normal authentication - } - } - catch (exception& e) - { - internalDisconnect(); - throw e; - } - } -#endif // VMIME_HAVE_SASL_SUPPORT - - // Secured authentication with APOP (if requested and if available) - // - // eg: C: APOP vincent - // --- S: +OK vincent is a valid mailbox - - const string username = getAuthenticator()->getUsername(); - const string password = getAuthenticator()->getPassword(); - - shared_ptr conn = dynamicCast (shared_from_this()); - shared_ptr response; - - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP)) - { - if (randomMID.getLeft().length() != 0 && - randomMID.getRight().length() != 0) - { - // is the result of MD5 applied to "password" - shared_ptr 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 (getAuthenticator())) - throw exceptions::authentication_error("No SASL authenticator available."); - - std::vector capa = getCapabilities(); - std::vector 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); - string mech; - - while (iss >> mech) - saslMechs.push_back(mech); - } - } - - if (saslMechs.empty()) - throw exceptions::authentication_error("No SASL mechanism available."); - - std::vector > mechList; - - shared_ptr saslContext = - make_shared (); - - 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 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 (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 mech = mechList[i]; - - shared_ptr saslSession = - saslContext->createSession("pop3", getAuthenticator(), mech); - - saslSession->init(); - - POP3Command::AUTH(mech->getName())->send(dynamicCast (shared_from_this())); - - for (bool cont = true ; cont ; ) - { - shared_ptr response = - POP3Response::readResponse(dynamicCast (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 - m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n"); - } - 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"); - } - 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 (shared_from_this())); - - shared_ptr response = - POP3Response::readResponse(dynamicCast (shared_from_this())); - - if (!response->isSuccess()) - throw exceptions::command_error("STLS", response->getFirstLine()); - - shared_ptr tlsSession = tls::TLSSession::create - (m_store.lock()->getCertificateVerifier(), - m_store.lock()->getSession()->getTLSProperties()); - - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); - - tlsSocket->handshake(m_timeoutHandler); - - m_socket = tlsSocket; - - m_secured = true; - m_cntInfos = make_shared - (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 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 (shared_from_this())); - - shared_ptr response = - POP3Response::readMultilineResponse(dynamicCast (shared_from_this())); - - std::vector 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 POP3Connection::getConnectionInfos() const -{ - return m_cntInfos; -} - - -shared_ptr POP3Connection::getStore() -{ - return m_store.lock(); -} - - -shared_ptr POP3Connection::getSession() -{ - return m_store.lock()->getSession(); -} - - -shared_ptr POP3Connection::getSocket() -{ - return m_socket; -} - - -shared_ptr POP3Connection::getTimeoutHandler() -{ - return m_timeoutHandler; -} - - -shared_ptr POP3Connection::getAuthenticator() -{ - return m_auth; -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/src/net/pop3/POP3Folder.cpp b/src/net/pop3/POP3Folder.cpp deleted file mode 100644 index 096de8af..00000000 --- a/src/net/pop3/POP3Folder.cpp +++ /dev/null @@ -1,729 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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, shared_ptr 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() -{ - shared_ptr store = m_store.lock(); - - if (store) - { - if (m_open) - close(false); - - store->unregisterFolder(this); - } - else if (m_open) - { - onClose(); - } -} - - -int POP3Folder::getMode() const -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - return (m_mode); -} - - -int POP3Folder::getType() -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (m_path.isEmpty()) - return (TYPE_CONTAINS_FOLDERS); - else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") - return (TYPE_CONTAINS_MESSAGES); - else - throw exceptions::folder_not_found(); -} - - -int POP3Folder::getFlags() -{ - return (0); -} - - -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 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 response = POP3Response::readResponse(store->getConnection()); - - if (!response->isSuccess()) - throw exceptions::command_error("STAT", response->getFirstLine()); - - std::istringstream iss(response->getText()); - 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 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 int /* type */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::destroy() -{ - throw exceptions::operation_not_supported(); -} - - -bool POP3Folder::exists() -{ - shared_ptr 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 POP3Folder::getMessage(const int num) -{ - shared_ptr 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 (dynamicCast (shared_from_this()), num); -} - - -std::vector > POP3Folder::getMessages(const messageSet& msgs) -{ - shared_ptr 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 numbers = POP3Utils::messageSetToNumberList(msgs); - - std::vector > messages; - shared_ptr thisFolder(dynamicCast (shared_from_this())); - - for (std::vector ::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 (thisFolder, *it)); - } - - return messages; - } - else - { - throw exceptions::operation_not_supported(); - } -} - - -int POP3Folder::getMessageCount() -{ - shared_ptr 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 POP3Folder::getFolder(const folder::path::component& name) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - return make_shared (m_path / name, store); -} - - -std::vector > POP3Folder::getFolders(const bool /* recursive */) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - if (m_path.isEmpty()) - { - std::vector > v; - v.push_back(make_shared (folder::path::component("INBOX"), store)); - return (v); - } - else - { - std::vector > v; - return (v); - } -} - - -void POP3Folder::fetchMessages(std::vector >& msg, const fetchAttributes& options, - utility::progressListener* progress) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - const size_t total = msg.size(); - size_t current = 0; - - if (progress) - progress->start(total); - - for (std::vector >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - dynamicCast (*it)->fetch - (dynamicCast (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 response = - POP3Response::readMultilineResponse(store->getConnection()); - - if (response->isSuccess()) - { - // C: LIST - // S: +OK - // S: 1 47548 - // S: 2 12653 - // S: . - std::map result; - POP3Utils::parseMultiListOrUidlResponse(response, result); - - for (std::vector >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - shared_ptr m = dynamicCast (*it); - - std::map ::const_iterator x = result.find(m->m_num); - - if (x != result.end()) - { - size_t size = 0; - - std::istringstream iss((*x).second); - 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 response = - POP3Response::readMultilineResponse(store->getConnection()); - - if (response->isSuccess()) - { - // C: UIDL - // S: +OK - // S: 1 whqtswO00WBw418f9t5JxYwZ - // S: 2 QhdPYR:00WBw1Ph7x7 - // S: . - std::map result; - POP3Utils::parseMultiListOrUidlResponse(response, result); - - for (std::vector >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - shared_ptr m = dynamicCast (*it); - - std::map ::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(shared_ptr msg, const fetchAttributes& options) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - dynamicCast (msg)->fetch - (dynamicCast (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 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 >> size; - - dynamicCast (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 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 (msg)->m_uid = - string(it, responseText.end()); - } - } - } -} - - -int POP3Folder::getFetchCapabilities() const -{ - return fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | - fetchAttributes::SIZE | fetchAttributes::FULL_HEADER | - fetchAttributes::UID | fetchAttributes::IMPORTANCE; -} - - -shared_ptr POP3Folder::getParent() -{ - if (m_path.isEmpty()) - return null; - else - return make_shared (m_path.getParent(), m_store.lock()); -} - - -shared_ptr POP3Folder::getStore() const -{ - return m_store.lock(); -} - - -shared_ptr 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 store = m_store.lock(); - - const std::vector nums = POP3Utils::messageSetToNumberList(msgs); - - 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 ::const_iterator - it = nums.begin() ; it != nums.end() ; ++it) - { - POP3Command::DELE(*it)->send(store->getConnection()); - - shared_ptr response = - POP3Response::readResponse(store->getConnection()); - - if (!response->isSuccess()) - throw exceptions::command_error("DELE", response->getFirstLine()); - } - - // Sort message list - std::vector 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 ::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 event = - make_shared - (dynamicCast (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(); -} - - -void POP3Folder::addMessage - (shared_ptr /* msg */, const int /* flags */, - vmime::datetime* /* date */, utility::progressListener* /* progress */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::addMessage - (utility::inputStream& /* is */, const size_t /* size */, const int /* flags */, - vmime::datetime* /* date */, utility::progressListener* /* progress */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::copyMessages(const folder::path& /* dest */, const messageSet& /* msgs */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::status(int& count, int& unseen) -{ - count = 0; - unseen = 0; - - shared_ptr status = getStatus(); - - count = status->getMessageCount(); - unseen = status->getUnseenCount(); -} - - -shared_ptr POP3Folder::getStatus() -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - POP3Command::STAT()->send(store->getConnection()); - - shared_ptr response = - POP3Response::readResponse(store->getConnection()); - - if (!response->isSuccess()) - throw exceptions::command_error("STAT", response->getFirstLine()); - - - unsigned int count = 0; - - std::istringstream iss(response->getText()); - iss >> count; - - shared_ptr status = make_shared (); - - status->setMessageCount(count); - status->setUnseenCount(count); - - // Update local message count - if (m_messageCount != count) - { - const int oldCount = m_messageCount; - - m_messageCount = count; - - if (count > oldCount) - { - std::vector nums; - nums.reserve(count - oldCount); - - for (int i = oldCount + 1, j = 0 ; i <= count ; ++i, ++j) - nums[j] = i; - - // Notify message count changed - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list ::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 event = - make_shared - (dynamicCast ((*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 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/src/net/pop3/POP3FolderStatus.cpp b/src/net/pop3/POP3FolderStatus.cpp deleted file mode 100644 index 944379ac..00000000 --- a/src/net/pop3/POP3FolderStatus.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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) -{ -} - - -unsigned int POP3FolderStatus::getMessageCount() const -{ - return m_count; -} - - -unsigned int POP3FolderStatus::getUnseenCount() const -{ - return m_unseen; -} - - -void POP3FolderStatus::setMessageCount(const unsigned int count) -{ - m_count = count; -} - - -void POP3FolderStatus::setUnseenCount(const unsigned int unseen) -{ - m_unseen = unseen; -} - - -shared_ptr POP3FolderStatus::clone() const -{ - return make_shared (*this); -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/src/net/pop3/POP3Message.cpp b/src/net/pop3/POP3Message.cpp deleted file mode 100644 index 08523611..00000000 --- a/src/net/pop3/POP3Message.cpp +++ /dev/null @@ -1,250 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace net { -namespace pop3 { - - -POP3Message::POP3Message(shared_ptr folder, const int num) - : m_folder(folder), m_num(num), m_size(-1), m_deleted(false) -{ - folder->registerMessage(this); -} - - -POP3Message::~POP3Message() -{ - shared_ptr folder = m_folder.lock(); - - if (folder) - folder->unregisterMessage(this); -} - - -void POP3Message::onFolderClosed() -{ - m_folder.reset(); -} - - -int 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 (-1)) - throw exceptions::unfetched_object(); - - return (m_size); -} - - -bool POP3Message::isExpunged() const -{ - return (false); -} - - -int POP3Message::getFlags() const -{ - int flags = FLAG_RECENT; - - if (m_deleted) - flags |= FLAG_DELETED; - - return (flags); -} - - -shared_ptr POP3Message::getStructure() const -{ - throw exceptions::operation_not_supported(); -} - - -shared_ptr POP3Message::getStructure() -{ - throw exceptions::operation_not_supported(); -} - - -shared_ptr POP3Message::getHeader() const -{ - if (m_header == NULL) - 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 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 (-1)) - throw exceptions::partial_fetch_not_supported(); - - // Emit the "RETR" command - shared_ptr store = constCast (folder)->m_store.lock(); - - POP3Command::RETR(m_num)->send(store->getConnection()); - - try - { - POP3Response::readLargeResponse - (store->getConnection(), os, progress, m_size); - } - catch (exceptions::command_error& e) - { - throw exceptions::command_error("RETR", e.response()); - } -} - - -void POP3Message::extractPart - (shared_ptr /* 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(shared_ptr /* p */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Message::fetch(shared_ptr msgFolder, const fetchAttributes& options) -{ - shared_ptr 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 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
(); - 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 POP3Message::getParsedMessage() -{ - std::ostringstream oss; - utility::outputStreamAdapter os(oss); - - extract(os); - - shared_ptr msg = make_shared (); - msg->parse(oss.str()); - - return msg; -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 - diff --git a/src/net/pop3/POP3Response.cpp b/src/net/pop3/POP3Response.cpp deleted file mode 100644 index 1dc5ee76..00000000 --- a/src/net/pop3/POP3Response.cpp +++ /dev/null @@ -1,428 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sok, shared_ptr toh) - : m_socket(sok), m_timeoutHandler(toh) -{ -} - - -// static -shared_ptr POP3Response::readResponse(shared_ptr conn) -{ - shared_ptr resp = shared_ptr - (new POP3Response(conn->getSocket(), conn->getTimeoutHandler())); - - string buffer; - resp->readResponseImpl(buffer, /* multiLine */ false); - - resp->m_firstLine = buffer; - resp->m_code = getResponseCode(buffer); - stripResponseCode(buffer, resp->m_text); - - return resp; -} - - -// static -shared_ptr POP3Response::readMultilineResponse(shared_ptr conn) -{ - shared_ptr resp = shared_ptr - (new POP3Response(conn->getSocket(), conn->getTimeoutHandler())); - - 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; - - while (std::getline(iss, line, '\n')) - resp->m_lines.push_back(utility::stringUtils::trim(line)); - - return resp; -} - - -// static -shared_ptr POP3Response::readLargeResponse - (shared_ptr conn, utility::outputStream& os, - utility::progressListener* progress, const size_t predictedSize) -{ - shared_ptr resp = shared_ptr - (new POP3Response(conn->getSocket(), conn->getTimeoutHandler())); - - string firstLine; - resp->readResponseImpl(firstLine, os, progress, predictedSize); - - resp->m_firstLine = firstLine; - resp->m_code = getResponseCode(firstLine); - stripResponseCode(firstLine, resp->m_text); - - 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 - { - platform::getHandler()->wait(); - 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 ((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); - } - } -} - - -void 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()) - { -#if 0 // not supported - // Check for possible cancellation - if (progress && progress->cancel()) - throw exceptions::operation_cancelled(); -#endif - - // 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 - { - platform::getHandler()->wait(); - 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); -} - - -// 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/src/net/pop3/POP3SStore.cpp b/src/net/pop3/POP3SStore.cpp deleted file mode 100644 index f1c3da74..00000000 --- a/src/net/pop3/POP3SStore.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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/src/net/pop3/POP3ServiceInfos.cpp b/src/net/pop3/POP3ServiceInfos.cpp deleted file mode 100644 index 4760d4f2..00000000 --- a/src/net/pop3/POP3ServiceInfos.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 POP3ServiceInfos::getAvailableProperties() const -{ - std::vector 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/src/net/pop3/POP3Store.cpp b/src/net/pop3/POP3Store.cpp deleted file mode 100644 index e6e95b1b..00000000 --- a/src/net/pop3/POP3Store.cpp +++ /dev/null @@ -1,240 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace net { -namespace pop3 { - - -POP3Store::POP3Store(shared_ptr sess, shared_ptr auth, const bool secured) - : store(sess, getInfosInstance(), auth), m_isPOP3S(secured) -{ -} - - -POP3Store::~POP3Store() -{ - try - { - if (isConnected()) - disconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -const string POP3Store::getProtocolName() const -{ - return "pop3"; -} - - -shared_ptr POP3Store::getDefaultFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (folder::path(folder::path::component("INBOX")), - dynamicCast (shared_from_this())); -} - - -shared_ptr POP3Store::getRootFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (folder::path(), dynamicCast (shared_from_this())); -} - - -shared_ptr POP3Store::getFolder(const folder::path& path) -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (path, dynamicCast (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 - (dynamicCast (shared_from_this()), getAuthenticator()); - - try - { - m_connection->connect(); - } - catch (std::exception&) - { - m_connection = null; - throw; - } -} - - -bool POP3Store::isPOP3S() const -{ - return m_isPOP3S; -} - - -bool POP3Store::isConnected() const -{ - return m_connection && m_connection->isConnected(); -} - - -bool POP3Store::isSecuredConnection() const -{ - if (m_connection == NULL) - return false; - - return m_connection->isSecuredConnection(); -} - - -shared_ptr POP3Store::getConnectionInfos() const -{ - if (m_connection == NULL) - return null; - - return m_connection->getConnectionInfos(); -} - - -shared_ptr POP3Store::getConnection() -{ - return m_connection; -} - - -void POP3Store::disconnect() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - for (std::list ::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 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 ::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/src/net/pop3/POP3Utils.cpp b/src/net/pop3/POP3Utils.cpp deleted file mode 100644 index 7ba65fff..00000000 --- a/src/net/pop3/POP3Utils.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace net { -namespace pop3 { - - -// static -void POP3Utils::parseMultiListOrUidlResponse(shared_ptr response, std::map & result) -{ - std::map 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()) - { - int 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 ::value_type(number, string(it, line.end()))); - } - } - } -} - - - -class POP3MessageSetEnumerator : public messageSetEnumerator -{ -public: - - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { - for (int i = range.getFirst(), last = range.getLast() ; i <= last ; ++i) - list.push_back(i); - } - - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) - { - // Not supported - } - -public: - - std::vector list; -}; - - -// static -const std::vector POP3Utils::messageSetToNumberList(const messageSet& msgs) -{ - POP3MessageSetEnumerator en; - msgs.enumerate(en); - - return en.list; -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 - diff --git a/src/net/sendmail/sendmailServiceInfos.cpp b/src/net/sendmail/sendmailServiceInfos.cpp deleted file mode 100644 index 21cac00c..00000000 --- a/src/net/sendmail/sendmailServiceInfos.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 sendmailServiceInfos::getAvailableProperties() const -{ - std::vector 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/src/net/sendmail/sendmailTransport.cpp b/src/net/sendmail/sendmailTransport.cpp deleted file mode 100644 index 8ef18e3b..00000000 --- a/src/net/sendmail/sendmailTransport.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 (getSession(), \ - dynamic_cast (getInfos()).getProperties().prop)) -#define HAS_PROPERTY(prop) \ - (getInfos().hasProperty(getSession(), \ - dynamic_cast (getInfos()).getProperties().prop)) - - -namespace vmime { -namespace net { -namespace sendmail { - - -sendmailTransport::sendmailTransport(shared_ptr sess, shared_ptr auth) - : transport(sess, getInfosInstance(), auth), m_connected(false) -{ -} - - -sendmailTransport::~sendmailTransport() -{ - try - { - if (isConnected()) - disconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -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 sendmailTransport::getConnectionInfos() const -{ - return make_shared ("localhost", static_cast (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) -{ - // 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 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 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 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/src/net/service.cpp b/src/net/service.cpp deleted file mode 100644 index c52ba592..00000000 --- a/src/net/service.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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" - -#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(shared_ptr sess, const serviceInfos& /* infos */, - shared_ptr auth) - : m_session(sess), m_auth(auth) -{ - if (!auth) - { -#if VMIME_HAVE_SASL_SUPPORT - m_auth = make_shared - (); -#else - m_auth = make_shared - (); -#endif // VMIME_HAVE_SASL_SUPPORT - } - -#if VMIME_HAVE_TLS_SUPPORT - m_certVerifier = make_shared (); -#endif // VMIME_HAVE_TLS_SUPPORT - - m_socketFactory = platform::getHandler()->getSocketFactory(); -} - - -service::~service() -{ -} - - -shared_ptr service::getSession() const -{ - return (m_session); -} - - -shared_ptr service::getSession() -{ - return (m_session); -} - - -shared_ptr service::getAuthenticator() const -{ - return (m_auth); -} - - -shared_ptr service::getAuthenticator() -{ - return (m_auth); -} - - -void service::setAuthenticator(shared_ptr auth) -{ - m_auth = auth; -} - - -#if VMIME_HAVE_TLS_SUPPORT - -void service::setCertificateVerifier(shared_ptr cv) -{ - m_certVerifier = cv; -} - - -shared_ptr service::getCertificateVerifier() -{ - return m_certVerifier; -} - -#endif // VMIME_HAVE_TLS_SUPPORT - - -void service::setSocketFactory(shared_ptr sf) -{ - m_socketFactory = sf; -} - - -shared_ptr service::getSocketFactory() -{ - return m_socketFactory; -} - - -void service::setTimeoutHandlerFactory(shared_ptr thf) -{ - m_toHandlerFactory = thf; -} - - -shared_ptr service::getTimeoutHandlerFactory() -{ - return m_toHandlerFactory; -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/serviceFactory.cpp b/src/net/serviceFactory.cpp deleted file mode 100644 index 98aee646..00000000 --- a/src/net/serviceFactory.cpp +++ /dev/null @@ -1,145 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 "src/net/builtinServices.inl" - - -namespace vmime { -namespace net { - - -serviceFactory::serviceFactory() -{ -} - - -serviceFactory::~serviceFactory() -{ -} - - -shared_ptr serviceFactory::getInstance() -{ - static serviceFactory instance; - return shared_ptr (&instance, noop_shared_ptr_deleter ()); -} - - -shared_ptr serviceFactory::create - (shared_ptr sess, const string& protocol, - shared_ptr auth) -{ - return (getServiceByProtocol(protocol)->create(sess, auth)); -} - - -shared_ptr serviceFactory::create - (shared_ptr sess, const utility::url& u, - shared_ptr auth) -{ - shared_ptr 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 serviceFactory::getServiceByProtocol(const string& protocol) const -{ - const string name(utility::stringUtils::toLower(protocol)); - - for (std::vector >::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 serviceFactory::getServiceAt(const size_t pos) const -{ - return (m_services[pos]); -} - - -const std::vector > serviceFactory::getServiceList() const -{ - std::vector > res; - - for (std::vector >::const_iterator it = m_services.begin() ; - it != m_services.end() ; ++it) - { - res.push_back(*it); - } - - return (res); -} - - -void serviceFactory::registerService(shared_ptr reg) -{ - m_services.push_back(reg); -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/serviceInfos.cpp b/src/net/serviceInfos.cpp deleted file mode 100644 index 8de0529e..00000000 --- a/src/net/serviceInfos.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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); - -#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(shared_ptr 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/src/net/serviceRegistration.inl b/src/net/serviceRegistration.inl deleted file mode 100644 index 2366fe01..00000000 --- a/src/net/serviceRegistration.inl +++ /dev/null @@ -1,98 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 registeredServiceImpl : public serviceFactory::registeredService -{ -public: - - registeredServiceImpl(const string& name, const int type) - : m_type(type), m_name(name), m_servInfos(S::getInfosInstance()) - { - } - - shared_ptr create - (shared_ptr sess, - shared_ptr auth) const - { - return make_shared (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 serviceRegisterer -{ -public: - - serviceRegisterer(const string& protocol, const service::Type type) - { - serviceFactory::getInstance()->registerService - (make_shared >(protocol, type)); - } -}; - - -} // net -} // vmime - - -#define REGISTER_SERVICE(p_class, p_name, p_type) \ - vmime::net::serviceRegisterer \ - p_name(#p_name, vmime::net::service::p_type) - - -#endif // VMIME_BUILDING_DOC - diff --git a/src/net/session.cpp b/src/net/session.cpp deleted file mode 100644 index 36b9f2c3..00000000 --- a/src/net/session.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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() - : m_tlsProps(make_shared ()) -{ -} - - -session::session(const session& sess) - : object(), m_props(sess.m_props), - m_tlsProps(make_shared (*sess.m_tlsProps)) -{ -} - - -session::session(const propertySet& props) - : m_props(props), m_tlsProps(make_shared ()) -{ -} - - -session::~session() -{ -} - - -shared_ptr session::getTransport(shared_ptr auth) -{ - return (getTransport(m_props["transport.protocol"], auth)); -} - - -shared_ptr session::getTransport - (const string& protocol, shared_ptr auth) -{ - shared_ptr sess(dynamicCast (shared_from_this())); - shared_ptr sv = serviceFactory::getInstance()->create(sess, protocol, auth); - - if (!sv || sv->getType() != service::TYPE_TRANSPORT) - return null; - - return dynamicCast (sv); -} - - -shared_ptr session::getTransport - (const utility::url& url, shared_ptr auth) -{ - shared_ptr sess(dynamicCast (shared_from_this())); - shared_ptr sv = serviceFactory::getInstance()->create(sess, url, auth); - - if (!sv || sv->getType() != service::TYPE_TRANSPORT) - return null; - - return dynamicCast (sv); -} - - -shared_ptr session::getStore(shared_ptr auth) -{ - return (getStore(m_props["store.protocol"], auth)); -} - - -shared_ptr session::getStore - (const string& protocol, shared_ptr auth) -{ - shared_ptr sess(dynamicCast (shared_from_this())); - shared_ptr sv = serviceFactory::getInstance()->create(sess, protocol, auth); - - if (!sv || sv->getType() != service::TYPE_STORE) - return null; - - return dynamicCast (sv); -} - - -shared_ptr session::getStore - (const utility::url& url, shared_ptr auth) -{ - shared_ptr sess(dynamicCast (shared_from_this())); - shared_ptr sv = serviceFactory::getInstance()->create(sess, url, auth); - - if (!sv || sv->getType() != service::TYPE_STORE) - return null; - - return dynamicCast (sv); -} - - -const propertySet& session::getProperties() const -{ - return (m_props); -} - - -propertySet& session::getProperties() -{ - return (m_props); -} - - -void session::setTLSProperties(shared_ptr tlsProps) -{ - m_tlsProps = make_shared (*tlsProps); -} - - -shared_ptr session::getTLSProperties() const -{ - return m_tlsProps; -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/smtp/SMTPChunkingOutputStreamAdapter.cpp b/src/net/smtp/SMTPChunkingOutputStreamAdapter.cpp deleted file mode 100644 index 69f63bc9..00000000 --- a/src/net/smtp/SMTPChunkingOutputStreamAdapter.cpp +++ /dev/null @@ -1,145 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace net { -namespace smtp { - - -SMTPChunkingOutputStreamAdapter::SMTPChunkingOutputStreamAdapter(shared_ptr conn) - : m_connection(conn), m_bufferSize(0), m_chunkCount(0) -{ -} - - -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 PIPELINING is not supported, read one response for this BDAT command - if (!m_connection->hasExtension("PIPELINING")) - { - shared_ptr 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 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(data, data + 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; -} - - -size_t SMTPChunkingOutputStreamAdapter::getBlockSize() -{ - return sizeof(m_buffer); -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/net/smtp/SMTPCommand.cpp b/src/net/smtp/SMTPCommand.cpp deleted file mode 100644 index 949ab0c1..00000000 --- a/src/net/smtp/SMTPCommand.cpp +++ /dev/null @@ -1,214 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/mailbox.hpp" -#include "vmime/utility/outputStreamAdapter.hpp" - - -namespace vmime { -namespace net { -namespace smtp { - - -SMTPCommand::SMTPCommand(const string& text) - : m_text(text) -{ -} - - -// static -shared_ptr SMTPCommand::EHLO(const string& hostname) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "EHLO " << hostname; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr SMTPCommand::HELO(const string& hostname) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "HELO " << hostname; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr SMTPCommand::AUTH(const string& mechName) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "AUTH " << mechName; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr SMTPCommand::STARTTLS() -{ - return createCommand("STARTTLS"); -} - - -// static -shared_ptr SMTPCommand::MAIL(const mailbox& mbox, const bool utf8) -{ - return MAIL(mbox, utf8, 0); -} - - -// static -shared_ptr SMTPCommand::MAIL(const mailbox& mbox, const bool utf8, const size_t size) -{ - 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 (utf8) - cmd << " SMTPUTF8"; - - if (size != 0) - cmd << " SIZE=" << size; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr SMTPCommand::RCPT(const mailbox& mbox, const bool utf8) -{ - 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 << ">"; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr SMTPCommand::RSET() -{ - return createCommand("RSET"); -} - - -// static -shared_ptr SMTPCommand::DATA() -{ - return createCommand("DATA"); -} - - -// static -shared_ptr 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::NOOP() -{ - return createCommand("NOOP"); -} - - -// static -shared_ptr SMTPCommand::QUIT() -{ - return createCommand("QUIT"); -} - - -// static -shared_ptr SMTPCommand::createCommand(const string& text) -{ - return shared_ptr (new SMTPCommand(text)); -} - - -const string SMTPCommand::getText() const -{ - return m_text; -} - - -void SMTPCommand::writeToSocket(shared_ptr sok) -{ - sok->send(m_text + "\r\n"); -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/net/smtp/SMTPCommandSet.cpp b/src/net/smtp/SMTPCommandSet.cpp deleted file mode 100644 index 3e03427c..00000000 --- a/src/net/smtp/SMTPCommandSet.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace net { -namespace smtp { - - -SMTPCommandSet::SMTPCommandSet(const bool pipeline) - : SMTPCommand(""), m_pipeline(pipeline), - m_started(false), m_lastCommandSent() -{ -} - - -// static -shared_ptr SMTPCommandSet::create(const bool pipeline) -{ - return shared_ptr (new SMTPCommandSet(pipeline)); -} - - -void SMTPCommandSet::addCommand(shared_ptr 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(shared_ptr sok) -{ - if (m_pipeline) - { - if (!m_started) - { - // Send all commands at once - for (std::list >::const_iterator it = m_commands.begin() ; - it != m_commands.end() ; ++it) - { - shared_ptr cmd = *it; - cmd->writeToSocket(sok); - } - } - - if (!m_commands.empty()) - { - // Advance the pointer to last command sent - shared_ptr cmd = m_commands.front(); - m_commands.pop_front(); - - m_lastCommandSent = cmd; - } - } - else - { - if (!m_commands.empty()) - { - // Send only one command - shared_ptr cmd = m_commands.front(); - m_commands.pop_front(); - - cmd->writeToSocket(sok); - - m_lastCommandSent = cmd; - } - } - - m_started = true; -} - - -const string SMTPCommandSet::getText() const -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - - for (std::list >::const_iterator it = m_commands.begin() ; - it != m_commands.end() ; ++it) - { - cmd << (*it)->getText() << "\r\n"; - } - - return cmd.str(); -} - - -bool SMTPCommandSet::isFinished() const -{ - return (m_pipeline && m_started) || (m_commands.size() == 0 && m_started); -} - - -shared_ptr SMTPCommandSet::getLastCommandSent() const -{ - return m_lastCommandSent; -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/net/smtp/SMTPConnection.cpp b/src/net/smtp/SMTPConnection.cpp deleted file mode 100644 index 26be25db..00000000 --- a/src/net/smtp/SMTPConnection.cpp +++ /dev/null @@ -1,618 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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" -#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 (getSession(), \ - dynamic_cast (m_transport.lock()->getInfos()).getProperties().prop)) -#define HAS_PROPERTY(prop) \ - (m_transport.lock()->getInfos().hasProperty(getSession(), \ - dynamic_cast (m_transport.lock()->getInfos()).getProperties().prop)) - - -namespace vmime { -namespace net { -namespace smtp { - - - -SMTPConnection::SMTPConnection(shared_ptr transport, shared_ptr auth) - : m_transport(transport), m_auth(auth), m_socket(null), m_timeoutHandler(null), - m_authenticated(false), m_secured(false), m_extendedSMTP(false) -{ -} - - -SMTPConnection::~SMTPConnection() -{ - try - { - if (isConnected()) - disconnect(); - else if (m_socket) - internalDisconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -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 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); - -#if VMIME_HAVE_TLS_SUPPORT - if (transport->isSMTPS()) // dedicated port/SMTPS - { - shared_ptr tlsSession = tls::TLSSession::create - (transport->getCertificateVerifier(), - transport->getSession()->getTLSProperties()); - - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); - - m_socket = tlsSocket; - - m_secured = true; - m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); - } - else -#endif // VMIME_HAVE_TLS_SUPPORT - { - m_cntInfos = make_shared (address, port); - } - - m_socket->connect(address, port); - - // Connection - // - // eg: C: - // --- S: 220 smtp.domain.com Service ready - - shared_ptr 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 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); - - string ext; - iss >> ext; - - std::vector 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 * params) const -{ - std::map >::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 - // First, try SASL authentication - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) - { - try - { - authenticateSASL(); - - m_authenticated = true; - return; - } - catch (exceptions::authentication_error& e) - { - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) - { - // Can't fallback on normal authentication - internalDisconnect(); - throw e; - } - else - { - // Ignore, will try normal authentication - } - } - catch (exception& e) - { - internalDisconnect(); - throw e; - } - } -#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 (getAuthenticator())) - throw exceptions::authentication_error("No SASL authenticator available."); - - // Obtain SASL mechanisms supported by server from ESMTP extensions - std::vector saslMechs; - hasExtension("AUTH", &saslMechs); - - if (saslMechs.empty()) - throw exceptions::authentication_error("No SASL mechanism available."); - - std::vector > mechList; - - shared_ptr saslContext = - make_shared (); - - 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 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 (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 mech = mechList[i]; - - shared_ptr saslSession = - saslContext->createSession("smtp", getAuthenticator(), mech); - - saslSession->init(); - - sendRequest(SMTPCommand::AUTH(mech->getName())); - - for (bool cont = true ; cont ; ) - { - shared_ptr 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 - m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n"); - } - 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"); - } - 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 resp = readResponse(); - - if (resp->getCode() != 220) - { - throw SMTPCommandError("STARTTLS", resp->getText(), - resp->getCode(), resp->getEnhancedCode()); - } - - shared_ptr tlsSession = tls::TLSSession::create - (getTransport()->getCertificateVerifier(), - getTransport()->getSession()->getTLSProperties()); - - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); - - tlsSocket->handshake(m_timeoutHandler); - - m_socket = tlsSocket; - - m_secured = true; - m_cntInfos = make_shared - (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() -{ - try - { - sendRequest(SMTPCommand::QUIT()); - readResponse(); - } - 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(shared_ptr cmd) -{ - cmd->writeToSocket(m_socket); -} - - -shared_ptr SMTPConnection::readResponse() -{ - shared_ptr resp = SMTPResponse::readResponse - (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 SMTPConnection::getConnectionInfos() const -{ - return m_cntInfos; -} - - -shared_ptr SMTPConnection::getTransport() -{ - return m_transport.lock(); -} - - -shared_ptr SMTPConnection::getSession() -{ - return m_transport.lock()->getSession(); -} - - -shared_ptr SMTPConnection::getSocket() -{ - return m_socket; -} - - -shared_ptr SMTPConnection::getTimeoutHandler() -{ - return m_timeoutHandler; -} - - -shared_ptr SMTPConnection::getAuthenticator() -{ - return m_auth; -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/net/smtp/SMTPExceptions.cpp b/src/net/smtp/SMTPExceptions.cpp deleted file mode 100644 index 0c3112c0..00000000 --- a/src/net/smtp/SMTPExceptions.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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"; -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/net/smtp/SMTPResponse.cpp b/src/net/smtp/SMTPResponse.cpp deleted file mode 100644 index f7980351..00000000 --- a/src/net/smtp/SMTPResponse.cpp +++ /dev/null @@ -1,334 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace net { -namespace smtp { - - -SMTPResponse::SMTPResponse(shared_ptr sok, shared_ptr toh, const state& st) - : m_socket(sok), m_timeoutHandler(toh), - 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::readResponse - (shared_ptr sok, shared_ptr toh, const state& st) -{ - shared_ptr resp = shared_ptr (new SMTPResponse(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; - - 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 - { - platform::getHandler()->wait(); - 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); - - 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/src/net/smtp/SMTPSTransport.cpp b/src/net/smtp/SMTPSTransport.cpp deleted file mode 100644 index ab64d49d..00000000 --- a/src/net/smtp/SMTPSTransport.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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/src/net/smtp/SMTPServiceInfos.cpp b/src/net/smtp/SMTPServiceInfos.cpp deleted file mode 100644 index 532bb8b8..00000000 --- a/src/net/smtp/SMTPServiceInfos.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 SMTPServiceInfos::getAvailableProperties() const -{ - std::vector 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/src/net/smtp/SMTPTransport.cpp b/src/net/smtp/SMTPTransport.cpp deleted file mode 100644 index 0020d010..00000000 --- a/src/net/smtp/SMTPTransport.cpp +++ /dev/null @@ -1,420 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr auth, const bool secured) - : transport(sess, getInfosInstance(), auth), m_isSMTPS(secured), m_needReset(false) -{ -} - - -SMTPTransport::~SMTPTransport() -{ - try - { - if (isConnected()) - disconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -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 - (dynamicCast (shared_from_this()), getAuthenticator()); - - try - { - m_connection->connect(); - } - catch (std::exception&) - { - m_connection = null; - throw; - } -} - - -bool SMTPTransport::isConnected() const -{ - return m_connection && m_connection->isConnected(); -} - - -bool SMTPTransport::isSecuredConnection() const -{ - if (m_connection == NULL) - return false; - - return m_connection->isSecuredConnection(); -} - - -shared_ptr SMTPTransport::getConnectionInfos() const -{ - if (m_connection == NULL) - return null; - - return m_connection->getConnectionInfos(); -} - - -shared_ptr 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 resp = m_connection->readResponse(); - - if (resp->getCode() != 250) - { - throw SMTPCommandError - ("NOOP", resp->getText(), resp->getCode(), resp->getEnhancedCode()); - } -} - - -void SMTPTransport::sendEnvelope - (const mailbox& expeditor, const mailboxList& recipients, - const mailbox& sender, bool sendDATACommand, - const size_t size) -{ - // If no recipient/expeditor was found, throw an exception - if (recipients.isEmpty()) - throw exceptions::no_recipient(); - else if (expeditor.isEmpty()) - throw exceptions::no_expeditor(); - - - const bool needReset = m_needReset; - const bool hasPipelining = m_connection->hasExtension("PIPELINING") && - getInfos().getPropertyValue (getSession(), - dynamic_cast (getInfos()).getProperties().PROPERTY_OPTIONS_PIPELINING); - - shared_ptr resp; - shared_ptr commands = SMTPCommandSet::create(hasPipelining); - - // Emit a "RSET" command if we previously sent a message on this connection - if (needReset) - commands->addCommand(SMTPCommand::RSET()); - - // Emit the "MAIL" command - const bool hasSMTPUTF8 = m_connection->hasExtension("SMTPUTF8"); - const bool hasSize = m_connection->hasExtension("SIZE"); - - if (!sender.isEmpty()) - commands->addCommand(SMTPCommand::MAIL(sender, hasSMTPUTF8, hasSize ? size : 0)); - else - commands->addCommand(SMTPCommand::MAIL(expeditor, hasSMTPUTF8, hasSize ? size : 0)); - - // 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)); - } - - // Prepare sending of message data - if (sendDATACommand) - commands->addCommand(SMTPCommand::DATA()); - - // Read response for "RSET" command - if (needReset) - { - commands->writeToSocket(m_connection->getSocket()); - - if ((resp = m_connection->readResponse())->getCode() != 250) - { - disconnect(); - - throw SMTPCommandError - (commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode()); - } - } - - // Read response for "MAIL" command - commands->writeToSocket(m_connection->getSocket()); - - if ((resp = m_connection->readResponse())->getCode() != 250) - { - // SIZE extension: insufficient system storage - if (resp->getCode() == 452) - { - disconnect(); - - 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) - { - disconnect(); - - throw SMTPMessageSizeExceedsMaxLimitsException - (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode())); - } - // Other error - else - { - disconnect(); - - 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()); - - resp = m_connection->readResponse(); - - if (resp->getCode() != 250 && - resp->getCode() != 251) - { - // SIZE extension: insufficient system storage - if (resp->getCode() == 452) - { - disconnect(); - - 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) - { - disconnect(); - - throw SMTPMessageSizeExceedsMaxLimitsException - (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode())); - } - // Other error - else - { - disconnect(); - - throw SMTPCommandError - (commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode()); - } - } - } - - // Read response for "DATA" command - if (sendDATACommand) - { - commands->writeToSocket(m_connection->getSocket()); - - if ((resp = m_connection->readResponse())->getCode() != 354) - { - disconnect(); - - 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) -{ - if (!isConnected()) - throw exceptions::not_connected(); - - // Send message envelope - sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ true, size); - - // 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"); - - shared_ptr resp; - - if ((resp = m_connection->readResponse())->getCode() != 250) - { - disconnect(); - - throw SMTPCommandError - ("DATA", resp->getText(), resp->getCode(), resp->getEnhancedCode()); - } -} - - -void SMTPTransport::send - (shared_ptr msg, const mailbox& expeditor, const mailboxList& recipients, - utility::progressListener* progress, const mailbox& sender) -{ - 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 (getSession(), - dynamic_cast (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); - return; - } - - // Send message envelope - sendEnvelope(expeditor, recipients, sender, - /* sendDATACommand */ false, msg->getGeneratedSize(ctx)); - - // Send the message by chunks - SMTPChunkingOutputStreamAdapter chunkStream(m_connection); - - 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/src/net/tls/TLSProperties.cpp b/src/net/tls/TLSProperties.cpp deleted file mode 100644 index 1986db79..00000000 --- a/src/net/tls/TLSProperties.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/net/tls/TLSSecuredConnectionInfos.cpp b/src/net/tls/TLSSecuredConnectionInfos.cpp deleted file mode 100644 index 4856e9af..00000000 --- a/src/net/tls/TLSSecuredConnectionInfos.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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, - shared_ptr tlsSession, shared_ptr 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 TLSSecuredConnectionInfos::getPeerCertificates() const -{ - return m_tlsSocket->getPeerCertificates(); -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT - diff --git a/src/net/tls/TLSSession.cpp b/src/net/tls/TLSSession.cpp deleted file mode 100644 index a46f07ca..00000000 --- a/src/net/tls/TLSSession.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/net/tls/TLSSocket.cpp b/src/net/tls/TLSSocket.cpp deleted file mode 100644 index 0419a571..00000000 --- a/src/net/tls/TLSSocket.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/net/tls/gnutls/TLSProperties_GnuTLS.cpp b/src/net/tls/gnutls/TLSProperties_GnuTLS.cpp deleted file mode 100644 index 36ab7d7a..00000000 --- a/src/net/tls/gnutls/TLSProperties_GnuTLS.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#if GNUTLS_VERSION_NUMBER < 0x030000 -#include -#endif - - -namespace vmime { -namespace net { -namespace tls { - - -TLSProperties::TLSProperties() - : m_data(make_shared ()) -{ - setCipherSuite(CIPHERSUITE_DEFAULT); -} - - -TLSProperties::TLSProperties(const TLSProperties& props) - : object(), - m_data(make_shared ()) -{ - *dynamicCast (m_data) = *dynamicCast (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 (m_data)->cipherSuite = cipherSuite; -} - - -const string TLSProperties::getCipherSuite() const -{ - return dynamicCast (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/src/net/tls/gnutls/TLSSession_GnuTLS.cpp b/src/net/tls/gnutls/TLSSession_GnuTLS.cpp deleted file mode 100644 index 1c520ed1..00000000 --- a/src/net/tls/gnutls/TLSSession_GnuTLS.cpp +++ /dev/null @@ -1,300 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#if GNUTLS_VERSION_NUMBER < 0x030000 -#include -#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 -# if VMIME_GNUTLS_NEEDS_GCRYPT -# include -# endif -# include -#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 -#include - -#if VMIME_DEBUG && GNUTLS_DEBUG - #include -#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 anonCred; - gnutls_certificate_credentials certCred; -}; - -static TLSGlobal g_gnutlsGlobal; - - -#endif // VMIME_BUILDING_DOC - - - -// static -shared_ptr TLSSession::create(shared_ptr cv, shared_ptr props) -{ - return make_shared (cv, props); -} - - -TLSSession_GnuTLS::TLSSession_GnuTLS(shared_ptr cv, shared_ptr props) - : m_certVerifier(cv), m_props(props) -{ - int res; - - m_gnutlsSession = new gnutls_session; - - 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() -{ - if (m_gnutlsSession) - { - gnutls_deinit(*m_gnutlsSession); - - delete m_gnutlsSession; - m_gnutlsSession = NULL; - } -} - - -shared_ptr TLSSession_GnuTLS::getSocket(shared_ptr sok) -{ - return TLSSocket::wrap(dynamicCast (shared_from_this()), sok); -} - - -shared_ptr 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/src/net/tls/gnutls/TLSSocket_GnuTLS.cpp b/src/net/tls/gnutls/TLSSocket_GnuTLS.cpp deleted file mode 100644 index 5a90565b..00000000 --- a/src/net/tls/gnutls/TLSSocket_GnuTLS.cpp +++ /dev/null @@ -1,490 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - -#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 - - -namespace vmime { -namespace net { -namespace tls { - - -// static -shared_ptr TLSSocket::wrap(shared_ptr session, shared_ptr sok) -{ - return make_shared - (dynamicCast (session), sok); -} - - -TLSSocket_GnuTLS::TLSSocket_GnuTLS(shared_ptr session, shared_ptr sok) - : m_session(session), m_wrapped(sok), m_connected(false), - m_handshaking(false), m_ex(NULL), m_status(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); -} - - -TLSSocket_GnuTLS::~TLSSocket_GnuTLS() -{ - if (m_ex) - { - delete m_ex; - m_ex = NULL; - } - - try - { - disconnect(); - } - catch (...) - { - // Don't throw exception in destructor - } -} - - -void TLSSocket_GnuTLS::connect(const string& address, const port_t port) -{ - m_wrapped->connect(address, port); - - handshake(null); - - m_connected = true; -} - - -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(); -} - - -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 (buffer.data()), buffer.length()); -} - - -void TLSSocket_GnuTLS::send(const char* str) -{ - sendRaw(reinterpret_cast (str), ::strlen(str)); -} - - -size_t TLSSocket_GnuTLS::receiveRaw(byte_t* buffer, const size_t count) -{ - m_status &= ~STATUS_WOULDBLOCK; - - const ssize_t ret = gnutls_record_recv - (*m_session->m_gnutlsSession, - buffer, static_cast (count)); - - if (m_ex) - internalThrow(); - - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - m_status |= STATUS_WOULDBLOCK; - return 0; - } - - TLSSession_GnuTLS::throwTLSException("gnutls_record_recv", static_cast (ret)); - } - - return static_cast (ret); -} - - -void TLSSocket_GnuTLS::sendRaw(const byte_t* buffer, const size_t count) -{ - ssize_t ret = gnutls_record_send - (*m_session->m_gnutlsSession, - buffer, static_cast (count)); - - if (m_ex) - internalThrow(); - - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - m_status |= STATUS_WOULDBLOCK; - return; - } - - TLSSession_GnuTLS::throwTLSException("gnutls_record_send", static_cast (ret)); - } -} - - -size_t TLSSocket_GnuTLS::sendRawNonBlocking(const byte_t* buffer, const size_t count) -{ - ssize_t ret = gnutls_record_send - (*m_session->m_gnutlsSession, - buffer, static_cast (count)); - - if (m_ex) - internalThrow(); - - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - m_status |= STATUS_WOULDBLOCK; - return 0; - } - - TLSSession_GnuTLS::throwTLSException("gnutls_record_send", static_cast (ret)); - } - - return static_cast (ret); -} - - -unsigned int TLSSocket_GnuTLS::getStatus() const -{ - return m_status | m_wrapped->getStatus(); -} - - -void TLSSocket_GnuTLS::handshake(shared_ptr toHandler) -{ - if (toHandler) - toHandler->resetTimeOut(); - - // Start handshaking process - m_handshaking = true; - m_toHandler = toHandler; - - try - { - while (true) - { - const int ret = gnutls_handshake(*m_session->m_gnutlsSession); - - if (m_ex) - internalThrow(); - - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN || - ret == GNUTLS_E_INTERRUPTED) - { - // Non-fatal error - platform::getHandler()->wait(); - } - else - { - TLSSession_GnuTLS::throwTLSException("gnutls_handshake", ret); - } - } - else - { - // Successful handshake - break; - } - } - } - catch (...) - { - m_handshaking = false; - m_toHandler = null; - - throw; - } - - m_handshaking = false; - m_toHandler = null; - - // Verify server's certificate(s) - shared_ptr certs = getPeerCertificates(); - - if (certs == NULL) - throw exceptions::tls_exception("No peer certificate."); - - m_session->getCertificateVerifier()->verify(certs, getPeerName()); - - m_connected = true; -} - - -ssize_t TLSSocket_GnuTLS::gnutlsPushFunc - (gnutls_transport_ptr trspt, const void* data, size_t len) -{ - TLSSocket_GnuTLS* sok = reinterpret_cast (trspt); - - try - { - sok->m_wrapped->sendRaw - (reinterpret_cast (data), len); - } - catch (exception& e) - { - // Workaround for bad behaviour when throwing C++ exceptions - // from C functions (GNU TLS) - sok->m_ex = e.clone(); - return -1; - } - - return len; -} - - -ssize_t TLSSocket_GnuTLS::gnutlsPullFunc - (gnutls_transport_ptr trspt, void* data, size_t len) -{ - TLSSocket_GnuTLS* sok = reinterpret_cast (trspt); - - try - { - // Workaround for cross-platform asynchronous handshaking: - // gnutls_handshake() only returns GNUTLS_E_AGAIN if recv() - // returns -1 and errno is set to EGAIN... - if (sok->m_handshaking) - { - while (true) - { - const ssize_t ret = static_cast - (sok->m_wrapped->receiveRaw - (reinterpret_cast (data), len)); - - if (ret == 0) - { - // No data available yet - platform::getHandler()->wait(); - } - else - { - return ret; - } - - // Check whether the time-out delay is elapsed - if (sok->m_toHandler && sok->m_toHandler->isTimeOut()) - { - if (!sok->m_toHandler->handleTimeOut()) - throw exceptions::operation_timed_out(); - - sok->m_toHandler->resetTimeOut(); - } - } - } - else - { - const ssize_t n = static_cast - (sok->m_wrapped->receiveRaw - (reinterpret_cast (data), len)); - - if (n == 0 && sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) - return GNUTLS_E_AGAIN; - - return n; - } - } - catch (exception& e) - { - // Workaround for bad behaviour when throwing C++ exceptions - // from C functions (GNU TLS) - sok->m_ex = e.clone(); - return -1; - } -} - - -shared_ptr TLSSocket_GnuTLS::getPeerCertificates() const -{ - unsigned int certCount = 0; - const gnutls_datum* rawData = gnutls_certificate_get_peers - (*m_session->m_gnutlsSession, &certCount); - - if (rawData == NULL) - return null; - - // Try X.509 - gnutls_x509_crt* x509Certs = new gnutls_x509_crt[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) - { - // XXX more fine-grained error reporting? - delete [] x509Certs; - return null; - } - } - - { - std::vector > 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 data(dataSize); - - gnutls_x509_crt_export(x509Certs[i], - GNUTLS_X509_FMT_DER, &data[0], &dataSize); - - shared_ptr 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 (certs); - } - - delete [] x509Certs; - - return null; -} - - -// 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. - -#ifndef VMIME_BUILDING_DOC - -class TLSSocket_DeleteExWrapper : public object -{ -public: - - TLSSocket_DeleteExWrapper(exception* ex) : m_ex(ex) { } - ~TLSSocket_DeleteExWrapper() { delete m_ex; } - -private: - - exception* m_ex; -}; - -#endif // VMIME_BUILDING_DOC - - -void TLSSocket_GnuTLS::internalThrow() -{ - static std::vector > exToDelete; - - if (m_ex) - { - // Reset the current exception pointer to prevent the same - // exception from being thrown again later - exception* ex = m_ex; - m_ex = NULL; - - // To avoid memory leaks - exToDelete.push_back(make_shared (ex)); - - throw *ex; - } -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS diff --git a/src/net/tls/openssl/OpenSSLInitializer.cpp b/src/net/tls/openssl/OpenSSLInitializer.cpp deleted file mode 100644 index 1bbb9ee5..00000000 --- a/src/net/tls/openssl/OpenSSLInitializer.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/utility/sync/autoLock.hpp" -#include "vmime/utility/sync/criticalSection.hpp" - -#include "vmime/platform.hpp" - -#include -#include -#include -#include - -#if OPENSSL_VERSION_NUMBER >= 0x0907000L -# include -#endif - - -namespace vmime { -namespace net { -namespace tls { - - -shared_ptr * OpenSSLInitializer::sm_mutexes; - - -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_config(NULL); -#endif - - SSL_load_error_strings(); - SSL_library_init(); - OpenSSL_add_all_algorithms(); - - unsigned char seed[SEEDSIZE]; - vmime::platform::getHandler()->generateRandomBytes(seed, SEEDSIZE); - RAND_seed(seed, SEEDSIZE); - - int numMutexes = CRYPTO_num_locks(); - sm_mutexes = new shared_ptr [numMutexes]; - - for (int i = 0 ; i < numMutexes ; ++i) - sm_mutexes[i] = vmime::platform::getHandler()->createCriticalSection(); - - CRYPTO_set_locking_callback(&OpenSSLInitializer::lock); - CRYPTO_set_id_callback(&OpenSSLInitializer::id); -} - - -// static -void OpenSSLInitializer::uninitialize() -{ - EVP_cleanup(); - ERR_free_strings(); - - CRYPTO_set_locking_callback(NULL); - CRYPTO_set_id_callback(NULL); - - delete [] sm_mutexes; -} - - -// static -void OpenSSLInitializer::lock(int mode, int n, const char* /* file */, int /* line */) -{ - if (mode & CRYPTO_LOCK) - sm_mutexes[n]->lock(); - else - sm_mutexes[n]->unlock(); -} - - -// static -unsigned long OpenSSLInitializer::id() -{ - return vmime::platform::getHandler()->getThreadId(); -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL - diff --git a/src/net/tls/openssl/TLSProperties_OpenSSL.cpp b/src/net/tls/openssl/TLSProperties_OpenSSL.cpp deleted file mode 100644 index 932477df..00000000 --- a/src/net/tls/openssl/TLSProperties_OpenSSL.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - - -namespace vmime { -namespace net { -namespace tls { - - -TLSProperties::TLSProperties() - : m_data(make_shared ()) -{ - setCipherSuite(CIPHERSUITE_DEFAULT); -} - - -TLSProperties::TLSProperties(const TLSProperties& props) - : object(), - m_data(make_shared ()) -{ - *dynamicCast (m_data) = *dynamicCast (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 (m_data)->cipherSuite = cipherSuite; -} - - -const string TLSProperties::getCipherSuite() const -{ - return dynamicCast (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/src/net/tls/openssl/TLSSession_OpenSSL.cpp b/src/net/tls/openssl/TLSSession_OpenSSL.cpp deleted file mode 100644 index cf600a63..00000000 --- a/src/net/tls/openssl/TLSSession_OpenSSL.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/exception.hpp" - -#include -#include - - -namespace vmime { -namespace net { -namespace tls { - - -static OpenSSLInitializer::autoInitializer openSSLInitializer; - - -// static -shared_ptr TLSSession::create(shared_ptr cv, shared_ptr props) -{ - return make_shared (cv, props); -} - - -TLSSession_OpenSSL::TLSSession_OpenSSL(shared_ptr cv, shared_ptr 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 TLSSession_OpenSSL::getSocket(shared_ptr sok) -{ - return TLSSocket::wrap(dynamicCast (shared_from_this()), sok); -} - - -shared_ptr TLSSession_OpenSSL::getCertificateVerifier() -{ - return m_certVerifier; -} - - -void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile) -{ - 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 exceptions::certificate_exception(oss.str()); - } -} - - -void TLSSession_OpenSSL::useCertificateChainFile(const vmime::string& chainFile) -{ - 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 exceptions::certificate_exception(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/src/net/tls/openssl/TLSSocket_OpenSSL.cpp b/src/net/tls/openssl/TLSSocket_OpenSSL.cpp deleted file mode 100644 index ef6647d6..00000000 --- a/src/net/tls/openssl/TLSSocket_OpenSSL.cpp +++ /dev/null @@ -1,601 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - -#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 -#include - - -namespace vmime { -namespace net { -namespace tls { - - -static OpenSSLInitializer::autoInitializer openSSLInitializer; - - -// 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 -}; - - -// static -shared_ptr TLSSocket::wrap(shared_ptr session, shared_ptr sok) -{ - return make_shared - (dynamicCast (session), sok); -} - - -TLSSocket_OpenSSL::TLSSocket_OpenSSL(shared_ptr session, shared_ptr sok) - : m_session(session), m_wrapped(sok), m_connected(false), m_ssl(0), m_status(0), m_ex(NULL) -{ -} - - -TLSSocket_OpenSSL::~TLSSocket_OpenSSL() -{ - try - { - disconnect(); - - if (m_ssl) - { - SSL_free(m_ssl); - m_ssl = 0; - } - } - catch (...) - { - // Don't throw in destructor - } -} - - -void TLSSocket_OpenSSL::createSSLHandle() -{ - if (m_wrapped->isConnected()) - { - BIO* sockBio = BIO_new(&sm_customBIOMethod); - sockBio->ptr = this; - sockBio->init = 1; - - 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_connect_state(m_ssl); - } - else - { - throw exceptions::tls_exception("Unconnected socket error"); - } -} - - -void TLSSocket_OpenSSL::connect(const string& address, const port_t port) -{ - m_wrapped->connect(address, port); - - createSSLHandle(); - - handshake(null); - - m_connected = true; -} - - -void TLSSocket_OpenSSL::disconnect() -{ - if (m_connected) - { - 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); - } - - m_wrapped->disconnect(); - m_connected = false; - } -} - - -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(); -} - - -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 (buffer.data()), buffer.length()); -} - - -void TLSSocket_OpenSSL::send(const char* str) -{ - sendRaw(reinterpret_cast (str), ::strlen(str)); -} - - -size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) -{ - m_status &= ~STATUS_WOULDBLOCK; - - int rc = SSL_read(m_ssl, buffer, static_cast (count)); - - if (m_ex.get()) - internalThrow(); - - if (rc <= 0) - { - int error = SSL_get_error(m_ssl, rc); - - if (error == SSL_ERROR_WANT_WRITE || error == SSL_ERROR_WANT_READ) - { - m_status |= STATUS_WOULDBLOCK; - return 0; - } - - handleError(rc); - } - - return rc; -} - - -void TLSSocket_OpenSSL::sendRaw(const byte_t* buffer, const size_t count) -{ - sendRawNonBlocking(buffer, count); -} - - -size_t TLSSocket_OpenSSL::sendRawNonBlocking(const byte_t* buffer, const size_t count) -{ - m_status &= ~STATUS_WOULDBLOCK; - - int rc = SSL_write(m_ssl, buffer, static_cast (count)); - - if (m_ex.get()) - internalThrow(); - - if (rc <= 0) - { - int error = SSL_get_error(m_ssl, rc); - - if (error == SSL_ERROR_WANT_WRITE || error == SSL_ERROR_WANT_READ) - { - m_status |= STATUS_WOULDBLOCK; - return 0; - } - - handleError(rc); - } - - return rc; -} - - -void TLSSocket_OpenSSL::handshake(shared_ptr toHandler) -{ - if (toHandler) - toHandler->resetTimeOut(); - - // Start handshaking process - m_toHandler = toHandler; - - if (!m_ssl) - createSSLHandle(); - - try - { - int rc; - - while ((rc = SSL_do_handshake(m_ssl)) <= 0) - { - const int err = SSL_get_error(m_ssl, rc); - - if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) - { - // No data available yet - platform::getHandler()->wait(); - } - else - { - handleError(rc); - } - - // Check whether the time-out delay is elapsed - if (m_toHandler && m_toHandler->isTimeOut()) - { - if (!m_toHandler->handleTimeOut()) - throw exceptions::operation_timed_out(); - - m_toHandler->resetTimeOut(); - } - } - } - catch (...) - { - SSL_free(m_ssl); - m_ssl = 0; - m_toHandler = null; - throw; - } - - m_toHandler = null; - - // Verify server's certificate(s) - shared_ptr certs = getPeerCertificates(); - - if (certs == NULL) - throw exceptions::tls_exception("No peer certificate."); - - m_session->getCertificateVerifier()->verify(certs, getPeerName()); - - m_connected = true; -} - - -shared_ptr TLSSocket_OpenSSL::getPeerCertificates() const -{ - 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 > certs; - - for (int i = 0; i < certCount && !error; i++) - { - shared_ptr 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 (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: - return; - - case SSL_ERROR_SYSCALL: - { - if (lastError == 0) - { - if (rc == 0) - { - throw exceptions::tls_exception("SSL connection unexpectedly closed"); - } - else - { - vmime::string msg; - std::ostringstream oss(msg); - 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 (bio->ptr); - - if (!bio->init || !sok) - return -1; - - try - { - const size_t n = sok->m_wrapped->sendRawNonBlocking - (reinterpret_cast (buf), len); - - if (n == 0 && sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) - { - BIO_set_retry_write(bio); - return -1; - } - - return static_cast (len); - } - 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 (bio->ptr); - - if (!bio->init || !sok) - return -1; - - try - { - const size_t n = sok->m_wrapped->receiveRaw - (reinterpret_cast (buf), len); - - if (n == 0 || sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) - { - BIO_set_retry_read(bio); - return -1; - } - - return static_cast (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 (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->shutdown; - break; - - case BIO_CTRL_SET_CLOSE: - - bio->shutdown = static_cast (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->init = 0; - bio->num = 0; - bio->ptr = NULL; - bio->flags = 0; - - return 1; -} - - -// static -int TLSSocket_OpenSSL::bio_destroy(BIO* bio) -{ - if (bio == NULL) - return 0; - - if (bio->shutdown) - { - bio->ptr = NULL; - bio->init = 0; - bio->flags = 0; - } - - return 1; -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL diff --git a/src/net/transport.cpp b/src/net/transport.cpp deleted file mode 100644 index dd7281d0..00000000 --- a/src/net/transport.cpp +++ /dev/null @@ -1,236 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, const serviceInfos& infos, shared_ptr auth) - : service(sess, infos, auth) -{ -} - - -shared_ptr transport::processHeaderField(shared_ptr 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(shared_ptr
header) -{ - if (header->getFieldCount() == 0) - return; - - // Remove/replace fields - for (size_t idx = header->getFieldCount() ; idx != 0 ; --idx) - { - shared_ptr field = header->getFieldAt(idx - 1); - shared_ptr 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 mbox = dynamicCast (list.getAddressAt(i)->clone()); - - if (mbox != NULL) - recipients.appendMailbox(mbox); - } -} - - -void transport::send(shared_ptr msg, utility::progressListener* progress) -{ - // Extract expeditor - shared_ptr fromMbox = - msg->getHeader()->findFieldValue (fields::FROM); - - if (!fromMbox) - throw exceptions::no_expeditor(); - - mailbox expeditor = *fromMbox; - - // Extract sender - shared_ptr senderMbox = - msg->getHeader()->findFieldValue (fields::SENDER); - - mailbox sender; - - if (!senderMbox) - sender = expeditor; - else - sender = *senderMbox; - - // Extract recipients - mailboxList recipients; - - // -- "To" field - shared_ptr addresses = - msg->getHeader()->findFieldValue (fields::TO); - - if (addresses) - extractMailboxes(recipients, *addresses); - - // -- "Cc" field - addresses = - msg->getHeader()->findFieldValue (fields::CC); - - if (addresses) - extractMailboxes(recipients, *addresses); - - // -- "Bcc" field - addresses = - msg->getHeader()->findFieldValue (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
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(shared_ptr _msg, - shared_ptr _hdr) - : msg(_msg), hdr(msg->getHeader()) - { - // Set new header - msg->setHeader(_hdr); - } - - ~XChangeMsgHeader() - { - // Revert original header - msg->setHeader(hdr); - } - - private: - - shared_ptr msg; - shared_ptr hdr; - } headerExchanger(msg, hdr); - - send(msg, expeditor, recipients, progress, sender); -} - - -void transport::send - (shared_ptr msg, const mailbox& expeditor, const mailboxList& recipients, - utility::progressListener* progress, const mailbox& sender) -{ - // 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); -} - - -transport::Type transport::getType() const -{ - return (TYPE_TRANSPORT); -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/object.cpp b/src/object.cpp deleted file mode 100644 index d07c3c19..00000000 --- a/src/object.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/parameter.cpp b/src/parameter.cpp deleted file mode 100644 index b8d5b36e..00000000 --- a/src/parameter.cpp +++ /dev/null @@ -1,603 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 ()) -{ -} - - -parameter::parameter(const string& name, const word& value) - : m_name(name), m_value(make_shared (value)) -{ -} - - -parameter::parameter(const string& name, const string& value) - : m_name(name), m_value(make_shared (value)) -{ -} - - -parameter::parameter(const parameter&) - : component() -{ -} - - -shared_ptr parameter::clone() const -{ - shared_ptr p = make_shared (m_name); - p->copyFrom(*this); - - return (p); -} - - -void parameter::copyFrom(const component& other) -{ - const parameter& param = dynamic_cast (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 & chunks) -{ - bool foundCharsetChunk = false; - - charset ch(charsets::US_ASCII); - - std::ostringstream value; - value.imbue(std::locale::classic()); - - for (std::vector ::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) - { - // Ignore language - ++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 (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); -} - - -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, - // also generate a normal "7bit/us-ascii" parameter - - // [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) - { - // 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 ; i < value.length() ; ++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; - } - else - { - extended = true; - } - } - - } // !needQuotedPrintable - - if (needQuoting) - { - sevenBitStream << '"'; - ++pos; - } - -#if VMIME_ALWAYS_GENERATE_7BIT_PARAMETER - os << sevenBitBuffer; -#endif // !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER - - // Also generate an extended parameter if the value contains 8-bit characters - // or is too long for a single line - if (extended || cutValue) - { - -#if VMIME_ALWAYS_GENERATE_7BIT_PARAMETER - - os << ';'; - ++pos; - -#else // !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER - - // The data output to 'sevenBitBuffer' will be discarded in this case - pos = curLinePos; - -#endif // VMIME_ALWAYS_GENERATE_7BIT_PARAMETER - - /* 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 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 (c) / 16; - const int h2 = static_cast (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; - } - } - } -#if !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER - else - { - // 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; - } -#endif // !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER - - if (newLinePos) - *newLinePos = pos; -} - - -const std::vector > parameter::getChildComponents() -{ - std::vector > list; - - list.push_back(m_value); - - return list; -} - - -} // vmime - diff --git a/src/parameterizedHeaderField.cpp b/src/parameterizedHeaderField.cpp deleted file mode 100644 index e2925d25..00000000 --- a/src/parameterizedHeaderField.cpp +++ /dev/null @@ -1,580 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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* - - tspecials := "(" / ")" / "<" / ">" / "@" - / "," / ";" / ":" / "\" / <"> - / "/" / "[" / "]" / "?" / "=" - ; Must be in quoted-string, - ; to use within parameter values -*/ - - -#ifndef VMIME_BUILDING_DOC - -struct paramInfo -{ - bool extended; - std::vector 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 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 ::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 ::value_type(name, info)); - } - } - - // Skip white-spaces after this parameter - while (p < pend && parserHelpers::isSpace(*p)) ++p; - } - } - - for (std::map ::const_iterator it = params.begin() ; - it != params.end() ; ++it) - { - const paramInfo& info = (*it).second; - - // Append this parameter to the list - shared_ptr param = make_shared ((*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 >::const_iterator - it = m_params.begin() ; it != m_params.end() ; ++it) - { - os << "; "; - pos += 2; - - (*it)->generate(ctx, os, pos, &pos); - } - - if (newLinePos) - *newLinePos = pos; -} - - -void parameterizedHeaderField::copyFrom(const component& other) -{ - headerField::copyFrom(other); - - const parameterizedHeaderField& source = dynamic_cast(other); - - removeAllParameters(); - - for (std::vector >::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 >::const_iterator pos = m_params.begin(); - const std::vector >::const_iterator end = m_params.end(); - - for ( ; pos != end && utility::stringUtils::toLower((*pos)->getName()) != name ; ++pos) {} - - return (pos != end); -} - - -shared_ptr parameterizedHeaderField::findParameter(const string& paramName) const -{ - const string name = utility::stringUtils::toLower(paramName); - - // Find the first parameter that matches the specified name - std::vector >::const_iterator pos = m_params.begin(); - const std::vector >::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 parameterizedHeaderField::getParameter(const string& paramName) -{ - const string name = utility::stringUtils::toLower(paramName); - - // Find the first parameter that matches the specified name - std::vector >::const_iterator pos = m_params.begin(); - const std::vector >::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 param = make_shared (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(shared_ptr param) -{ - m_params.push_back(param); -} - - -void parameterizedHeaderField::insertParameterBefore(shared_ptr beforeParam, shared_ptr param) -{ - const std::vector >::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, shared_ptr param) -{ - if (pos >= m_params.size()) - throw std::out_of_range("Invalid position"); - - m_params.insert(m_params.begin() + pos, param); -} - - -void parameterizedHeaderField::insertParameterAfter(shared_ptr afterParam, shared_ptr param) -{ - const std::vector >::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, shared_ptr 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(shared_ptr param) -{ - const std::vector >::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 >::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 parameterizedHeaderField::getParameterAt(const size_t pos) -{ - return (m_params[pos]); -} - - -const shared_ptr parameterizedHeaderField::getParameterAt(const size_t pos) const -{ - return (m_params[pos]); -} - - -const std::vector > parameterizedHeaderField::getParameterList() const -{ - std::vector > list; - - list.reserve(m_params.size()); - - for (std::vector >::const_iterator it = m_params.begin() ; - it != m_params.end() ; ++it) - { - list.push_back(*it); - } - - return (list); -} - - -const std::vector > parameterizedHeaderField::getParameterList() -{ - return (m_params); -} - - -const std::vector > parameterizedHeaderField::getChildComponents() -{ - std::vector > list = headerField::getChildComponents(); - - for (std::vector >::iterator it = m_params.begin() ; - it != m_params.end() ; ++it) - { - list.push_back(*it); - } - - return (list); -} - - -} // vmime - diff --git a/src/parsedMessageAttachment.cpp b/src/parsedMessageAttachment.cpp deleted file mode 100644 index 242bfde0..00000000 --- a/src/parsedMessageAttachment.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr 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 parsedMessageAttachment::getData() const -{ - if (m_data == NULL) - { - std::ostringstream oss; - utility::outputStreamAdapter os(oss); - - m_msg->generate(os); - - m_data = make_shared (oss.str()); - } - - return m_data; -} - - -const encoding parsedMessageAttachment::getEncoding() const -{ - return encoding(encodingTypes::EIGHT_BIT); // not important -} - - -shared_ptr parsedMessageAttachment::getPart() const -{ - return null; -} - - -shared_ptr parsedMessageAttachment::getHeader() const -{ - return null; -} - - -shared_ptr parsedMessageAttachment::getMessage() const -{ - return m_msg; -} - - -void parsedMessageAttachment::generateIn(shared_ptr parent) const -{ - // Create and append a new part for this attachment - shared_ptr part = make_shared (); - 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/src/parsingContext.cpp b/src/parsingContext.cpp deleted file mode 100644 index 527f4705..00000000 --- a/src/parsingContext.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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() -{ -} - - -parsingContext::parsingContext(const parsingContext& ctx) - : context(ctx) -{ -} - - -parsingContext& parsingContext::getDefaultContext() -{ - static parsingContext ctx; - return ctx; -} - - -} // vmime diff --git a/src/path.cpp b/src/path.cpp deleted file mode 100644 index 3f1bc6af..00000000 --- a/src/path.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 (other); - - m_localPart = p.m_localPart; - m_domain = p.m_domain; -} - - -shared_ptr path::clone() const -{ - return make_shared (*this); -} - - -path& path::operator=(const path& other) -{ - copyFrom(other); - return (*this); -} - - -const std::vector > path::getChildComponents() -{ - return std::vector >(); -} - - -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 != NULL) - *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/src/plainTextPart.cpp b/src/plainTextPart.cpp deleted file mode 100644 index 7a1542d7..00000000 --- a/src/plainTextPart.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 ()) -{ -} - - -plainTextPart::~plainTextPart() -{ -} - - -const mediaType plainTextPart::getType() const -{ - return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); -} - - -size_t plainTextPart::getPartCount() const -{ - return (1); -} - - -void plainTextPart::generateIn(shared_ptr /* message */, shared_ptr parent) const -{ - // Create a new part - shared_ptr part = make_shared (); - 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(shared_ptr /* message */, - shared_ptr /* parent */, shared_ptr textPart) -{ - m_text = vmime::clone(textPart->getBody()->getContents()); - - shared_ptr ctf = - textPart->getHeader()->findField (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 plainTextPart::getText() const -{ - return (m_text); -} - - -void plainTextPart::setText(shared_ptr text) -{ - m_text = vmime::clone(text); -} - - -} // vmime diff --git a/src/platform.cpp b/src/platform.cpp deleted file mode 100644 index 631d5bcf..00000000 --- a/src/platform.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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::sm_handler; - - -platform::handler::~handler() -{ -} - - -// static -shared_ptr platform::getDefaultHandler() -{ - -#if VMIME_PLATFORM_IS_WINDOWS - return make_shared (); -#elif VMIME_PLATFORM_IS_POSIX - return make_shared (); -#else - return null; -#endif - -} - - -// static -shared_ptr 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 defaultHandler = getDefaultHandler(); - - if (defaultHandler) - { - sm_handler = defaultHandler; - return sm_handler; - } - - // Oops... no platform handler! - throw exceptions::no_platform_handler(); -} - - -} // vmime diff --git a/src/platforms/posix/posixChildProcess.cpp b/src/platforms/posix/posixChildProcess.cpp deleted file mode 100644 index 54d4cd75..00000000 --- a/src/platforms/posix/posixChildProcess.cpp +++ /dev/null @@ -1,404 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include -#include -#include -#include -#include - - -namespace vmime { -namespace platforms { -namespace posix { - - -// posixChildProcessFactory - -shared_ptr posixChildProcessFactory::create(const utility::file::path& path) const -{ - return make_shared (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 (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 (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 -// Copyright 2000 Ximian, Inc. (www.ximian.com) - -void posixChildProcess::start(const std::vector 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 (argv)); - _exit(255); - } - - if (flags & FLAG_REDIRECT_STDIN) - { - m_stdIn = make_shared (m_pipe[1]); - } - else - { - close(m_pipe[1]); - m_pipe[1] = 0; - } - - if (flags & FLAG_REDIRECT_STDOUT) - { - m_stdOut = make_shared (m_pipe[0]); - } - else - { - close(m_pipe[0]); - m_pipe[0] = 0; - } - - m_pid = pid; - m_started = true; -} - - -shared_ptr posixChildProcess::getStdIn() -{ - return (m_stdIn); -} - - -shared_ptr 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) - { - std::auto_ptr 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/src/platforms/posix/posixCriticalSection.cpp b/src/platforms/posix/posixCriticalSection.cpp deleted file mode 100644 index fb2c469c..00000000 --- a/src/platforms/posix/posixCriticalSection.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/platforms/posix/posixFile.cpp b/src/platforms/posix/posixFile.cpp deleted file mode 100644 index 9387414d..00000000 --- a/src/platforms/posix/posixFile.cpp +++ /dev/null @@ -1,628 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include -#include - -#include -#include - -#include - -#include -#include - -#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 != NULL) - { - if (::closedir(m_dir) == -1) - posixFileSystemFactory::reportError(m_path, errno); - } -} - - -bool posixFileIterator::hasMoreElements() const -{ - return (m_dirEntry != NULL); -} - - -shared_ptr posixFileIterator::nextElement() -{ - shared_ptr file = make_shared - (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 (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 (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 (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 posixFileWriter::getOutputStream() -{ - int fd = 0; - - if ((fd = ::open(m_nativePath.c_str(), O_WRONLY, 0660)) == -1) - posixFileSystemFactory::reportError(m_path, errno); - - return make_shared (m_path, fd); -} - - - -// -// posixFileReader -// - -posixFileReader::posixFileReader(const vmime::utility::file::path& path, const vmime::string& nativePath) - : m_path(path), m_nativePath(nativePath) -{ -} - - -shared_ptr posixFileReader::getInputStream() -{ - int fd = 0; - - if ((fd = ::open(m_nativePath.c_str(), O_RDONLY, 0640)) == -1) - posixFileSystemFactory::reportError(m_path, errno); - - return make_shared (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 (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 posixFile::getParent() const -{ - if (m_path.isEmpty()) - return null; - else - return make_shared (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 posixFile::getFileWriter() -{ - return make_shared (m_path, m_nativePath); -} - - -shared_ptr posixFile::getFileReader() -{ - return make_shared (m_path, m_nativePath); -} - - -shared_ptr posixFile::getFiles() const -{ - if (!isDirectory()) - throw vmime::exceptions::not_a_directory(m_path); - - return make_shared (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 posixFileSystemFactory::create(const vmime::utility::file::path& path) const -{ - return make_shared (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::string(str.begin() + prev, str.begin() + offset)); - - prev = offset + 1; - offset++; - } - - if (prev < str.length()) - path.appendComponent(vmime::string(str.begin() + prev, str.end())); - - return (path); -} - - -const vmime::string posixFileSystemFactory::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 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 (int 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/src/platforms/posix/posixHandler.cpp b/src/platforms/posix/posixHandler.cpp deleted file mode 100644 index 7ab0341a..00000000 --- a/src/platforms/posix/posixHandler.cpp +++ /dev/null @@ -1,322 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include -#include -#include -#include -#include - -#include -#include - -#if VMIME_HAVE_SYSCALL -# include -#endif - -#include - -#include -#include -#include - -#if VMIME_HAVE_PTHREAD -# include -#endif // VMIME_HAVE_PTHREAD - -/* -#ifdef _POSIX_PRIORITY_SCHEDULING - #include -#endif // _POSIX_PRIORITY_SCHEDULING -*/ - - -#if VMIME_HAVE_PTHREAD - -namespace -{ - // This construction ensures mutex will be initialized in compile-time - // and will be available any time in the runtime. - pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; - - // Helper lock, to be exception safe all the time. - class PLockHelper - { - public: - - PLockHelper() - { - if (pthread_mutex_lock(&g_mutex) != 0) - assert(!"unable to lock mutex - thread safety's void"); - } - - ~PLockHelper() - { - if (pthread_mutex_unlock(&g_mutex) != 0) - assert(!"unable to unlock mutex - application's dead..."); - } - - private: - - // Object cannot be copied - PLockHelper(const PLockHelper&); - const PLockHelper& operator=(const PLockHelper&); - }; - -} // unnamed namespace - -#endif // VMIME_HAVE_PTHREAD - - -namespace vmime { -namespace platforms { -namespace posix { - - -posixHandler::posixHandler() -{ -#if VMIME_HAVE_MESSAGING_FEATURES - m_socketFactory = make_shared (); -#endif -#if VMIME_HAVE_FILESYSTEM_FEATURES - m_fileSysFactory = make_shared (); - m_childProcFactory = make_shared (); -#endif -} - - -posixHandler::~posixHandler() -{ -} - - -unsigned long posixHandler::getUnixTime() const -{ - return static_cast (::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 long 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, diff / 60); // minutes needed -} - - -const vmime::charset posixHandler::getLocalCharset() const -{ - const PLockHelper lock; - - const char* prevLocale = ::setlocale(LC_ALL, ""); - vmime::charset ch(::nl_langinfo(CODESET)); - ::setlocale(LC_ALL, prevLocale); - - return (ch); -} - - -static inline bool isFQDN(const vmime::string& str) -{ - if (utility::stringUtils::isStringEqualNoCase(str, "localhost", 9)) - return false; - - const vmime::size_t p = str.find_first_of("."); - return p != vmime::string::npos && p > 0 && p != str.length() - 1; -} - - -const vmime::string posixHandler::getHostName() const -{ - char hostname[256]; - - // Try with 'gethostname' - ::gethostname(hostname, sizeof(hostname)); - hostname[sizeof(hostname) - 1] = '\0'; - - // If this is a Fully-Qualified Domain Name (FQDN), return immediately - if (isFQDN(hostname)) - return hostname; - - if (::strlen(hostname) == 0) - ::strcpy(hostname, "localhost"); - - // Try to get canonical name for the hostname - 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) - { - for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) - { - if (isFQDN(p->ai_canonname)) - { - const string ret(p->ai_canonname); - freeaddrinfo(info); - return ret; - } - } - - freeaddrinfo(info); - } - - return hostname; -} - - -unsigned int posixHandler::getProcessId() const -{ - return (::getpid()); -} - - -unsigned int posixHandler::getThreadId() const -{ -#if VMIME_HAVE_GETTID - return static_cast (::gettid()); -#elif VMIME_HAVE_SYSCALL && VMIME_HAVE_SYSCALL_GETTID - return static_cast (::syscall(SYS_gettid)); -#else - #error We have no implementation of getThreadId() for this platform! -#endif -} - - -#if VMIME_HAVE_MESSAGING_FEATURES - -shared_ptr posixHandler::getSocketFactory() -{ - return m_socketFactory; -} - -#endif - - -#if VMIME_HAVE_FILESYSTEM_FEATURES - -shared_ptr posixHandler::getFileSystemFactory() -{ - return m_fileSysFactory; -} - - -shared_ptr posixHandler::getChildProcessFactory() -{ - return m_childProcFactory; -} - -#endif - - -void posixHandler::wait() const -{ -/* -#ifdef _POSIX_PRIORITY_SCHEDULING - ::sched_yield(); -#else - ::sleep(1); -#endif // _POSIX_PRIORITY_SCHEDULING -*/ - - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 500000; // 500 microseconds - - nanosleep(&ts, NULL); -} - - -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 (rand() % 255); - } -} - - -shared_ptr posixHandler::createCriticalSection() -{ - return make_shared (); -} - - -} // posix -} // platforms -} // vmime - - -#endif // VMIME_PLATFORM_IS_POSIX diff --git a/src/platforms/posix/posixSocket.cpp b/src/platforms/posix/posixSocket.cpp deleted file mode 100644 index ab434116..00000000 --- a/src/platforms/posix/posixSocket.cpp +++ /dev/null @@ -1,680 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 - - -namespace vmime { -namespace platforms { -namespace posix { - - -// -// posixSocket -// - -posixSocket::posixSocket(shared_ptr 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 VMIME_HAVE_GETADDRINFO // use thread-safe and IPv6-aware getaddrinfo() if available - - // Resolve address, if needed - struct ::addrinfo hints; - memset(&hints, 0, sizeof(hints)); - - hints.ai_flags = AI_CANONNAME; - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - std::ostringstream portStr; - portStr.imbue(std::locale::classic()); - - portStr << port; - - struct ::addrinfo* res0; - - if (::getaddrinfo(address.c_str(), portStr.str().c_str(), &hints, &res0) != 0) - { - // Error: cannot resolve address - throw vmime::exceptions::connection_error("Cannot resolve address."); - } - - m_serverAddress = address; - - // Connect to host - int sock = -1; - struct ::addrinfo* res = res0; - - for ( ; sock == -1 && res != NULL ; res = res->ai_next) - { - sock = ::socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - if (sock < 0) - continue; // try next - - if (m_timeoutHandler != NULL) - { - ::fcntl(sock, F_SETFL, ::fcntl(sock, F_GETFL) | O_NONBLOCK); - - if (::connect(sock, res->ai_addr, res->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: - - ::close(sock); - sock = -1; - continue; // try next - } - - // Wait for socket to be connected. - // We will check for time out every second. - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); - - fd_set fdsError; - FD_ZERO(&fdsError); - FD_SET(sock, &fdsError); - - struct timeval tm; - tm.tv_sec = 1; - tm.tv_usec = 0; - - m_timeoutHandler->resetTimeOut(); - - bool connected = false; - - do - { - const int ret = select(sock + 1, NULL, &fds, &fdsError, &tm); - - // Success - if (ret > 0) - { - connected = true; - break; - } - // Error - else if (ret < -1) - { - if (errno != EINTR) - { - // Cancel connection - break; - } - } - // 1-second timeout - else if (ret == 0) - { - if (m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - { - // Cancel connection - break; - } - else - { - // Reset timeout and keep waiting for connection - m_timeoutHandler->resetTimeOut(); - } - } - else - { - // Keep waiting for connection - } - } - - ::sched_yield(); - - } while (true); - - if (!connected) - { - ::close(sock); - sock = -1; - continue; // try next - } - - break; - } - } - else - { - if (::connect(sock, res->ai_addr, res->ai_addrlen) < 0) - { - ::close(sock); - sock = -1; - continue; // try next - } - } - } - - ::freeaddrinfo(res0); - - if (sock == -1) - { - try - { - throwSocketError(errno); - } - catch (exceptions::socket_exception& e) - { - 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 (port)); - addr.sin_addr.s_addr = ::inet_addr(address.c_str()); - - if (addr.sin_addr.s_addr == static_cast (-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 (&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) - { - throw vmime::exceptions::connection_error - ("Error while creating socket.", e); - } - } - - // Start connection - if (::connect(m_desc, reinterpret_cast (&addr), sizeof(addr)) == -1) - { - try - { - throwSocketError(errno); - } - catch (exceptions::socket_exception& e) - { - ::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); -} - - -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) - { - ::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); - - getpeername(m_desc, reinterpret_cast (&peer), &peerLen); - - // Convert to numerical presentation format - char numericAddress[1024]; - - if (inet_ntop(peer.sa_family, &peer, numericAddress, sizeof(numericAddress)) != NULL) - return string(numericAddress); - - return ""; // should not happen -} - - -const string posixSocket::getPeerName() const -{ - // Get address of connected peer - sockaddr peer; - socklen_t peerLen = sizeof(peer); - - getpeername(m_desc, reinterpret_cast (&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())) - { - -#if VMIME_HAVE_GETNAMEINFO - - char host[NI_MAXHOST + 1]; - char service[NI_MAXSERV + 1]; - - if (getnameinfo(reinterpret_cast (&peer), peerLen, - host, sizeof(host), service, sizeof(service), - /* flags */ NI_NAMEREQD) == 0) - { - return string(host); - } - -#else - - struct hostent *hp; - - if ((hp = gethostbyaddr(reinterpret_cast (&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 -} - - -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 - fd_set fds; - FD_ZERO(&fds); - FD_SET(m_desc, &fds); - - struct timeval tv; - tv.tv_sec = 1; - tv.tv_usec = 0; - - ssize_t ret = ::select(m_desc + 1, &fds, NULL, NULL, &tv); - - if (ret < 0) - { - if (!IS_EAGAIN(errno)) - throwSocketError(errno); - - // 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(errno); - } - else - { - // Reset timeout - m_timeoutHandler->resetTimeOut(); - } - } - - m_status |= STATUS_WOULDBLOCK; - - // Continue waiting for data - return 0; - } - - // Read available data - 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 (buffer.data()), buffer.length()); -} - - -void posixSocket::send(const char* str) -{ - sendRaw(reinterpret_cast (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) - { - const ssize_t ret = ::send(m_desc, buffer, size, 0); - - if (ret <= 0) - { - if (ret < 0 && !IS_EAGAIN(errno)) - throwSocketError(errno); - - platform::getHandler()->wait(); - } - 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; - - const ssize_t ret = ::send(m_desc, buffer, count, 0); - - 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 - throwSocketError(errno); - } - 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) -{ - string msg; - - 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 occured 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: - case ENOTCONN: msg = "ENOTCONN: not connected"; break; - case ECONNREFUSED: msg = "ECONNREFUSED: connection refused"; break; - default: - - std::ostringstream oss; - oss << ::strerror(err); - - msg = oss.str(); - break; - } - - throw exceptions::socket_exception(msg); -} - - -unsigned int posixSocket::getStatus() const -{ - return m_status; -} - - - -// -// posixSocketFactory -// - -shared_ptr posixSocketFactory::create() -{ - shared_ptr th; - return make_shared (th); -} - - -shared_ptr posixSocketFactory::create(shared_ptr th) -{ - return make_shared (th); -} - - -} // posix -} // platforms -} // vmime - - -#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES diff --git a/src/platforms/windows/windowsCriticalSection.cpp b/src/platforms/windows/windowsCriticalSection.cpp deleted file mode 100644 index d6ef0c45..00000000 --- a/src/platforms/windows/windowsCriticalSection.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/platforms/windows/windowsFile.cpp b/src/platforms/windows/windowsFile.cpp deleted file mode 100644 index 6aa0fea8..00000000 --- a/src/platforms/windows/windowsFile.cpp +++ /dev/null @@ -1,553 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - -#include "vmime/exception.hpp" -#include "vmime/utility/stringUtils.hpp" - - -namespace vmime { -namespace platforms { -namespace windows { - - -shared_ptr windowsFileSystemFactory::create(const vmime::utility::file::path& path) const -{ - return make_shared (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::string(str.begin() + prev, str.begin() + offset)); - - prev = offset + 1; - offset++; - } - - if (prev < str.length()) - path.appendComponent(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 windowsFile::getParent() const -{ - if (m_path.isEmpty()) - return NULL; - else - return make_shared (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 windowsFile::getFileWriter() -{ - return make_shared (m_path, m_nativePath); -} - -shared_ptr windowsFile::getFileReader() -{ - return make_shared (m_path, m_nativePath); -} - -shared_ptr windowsFile::getFiles() const -{ - return make_shared (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(fullPath); - 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 windowsFileIterator::nextElement() -{ - shared_ptr pFile = make_shared - (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 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 (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 (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 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 (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/src/platforms/windows/windowsHandler.cpp b/src/platforms/windows/windowsHandler.cpp deleted file mode 100644 index 9c96b271..00000000 --- a/src/platforms/windows/windowsHandler.cpp +++ /dev/null @@ -1,329 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include -#include -#include // for WSAStartup() -#include // for winnls.h -#include -#include - -#if VMIME_HAVE_MLANG -# include -#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 (); -#endif -#if VMIME_HAVE_FILESYSTEM_FEATURES - m_fileSysFactory = make_shared (); -#endif -} - - -windowsHandler::~windowsHandler() -{ - WSACleanup(); -} - - -unsigned long windowsHandler::getUnixTime() const -{ - return static_cast (::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 -} - - -static inline bool isFQDN(const vmime::string& str) -{ - if (utility::stringUtils::isStringEqualNoCase(str, "localhost", 9)) - return false; - - const vmime::size_t p = str.find_first_of("."); - return p != vmime::string::npos && p > 0 && p != str.length() - 1; -} - - -const vmime::string windowsHandler::getHostName() const -{ - char hostname[256]; - - // Try with 'gethostname' - ::gethostname(hostname, sizeof(hostname)); - hostname[sizeof(hostname) - 1] = '\0'; - - // If this is a Fully-Qualified Domain Name (FQDN), return immediately - if (isFQDN(hostname)) - return hostname; - - if (::strlen(hostname) == 0) - { -#if VMIME_HAVE_STRCPY_S - ::strcpy_s(hostname, "localhost"); -#else - ::strcpy(hostname, "localhost"); -#endif // VMIME_HAVE_STRCPY_S - } - - // Try to get canonical name for the hostname - 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) - { - for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) - { - if (p->ai_canonname && isFQDN(p->ai_canonname)) - { - const string ret(p->ai_canonname); - freeaddrinfo(info); - return ret; - } - } - - freeaddrinfo(info); - } - - return hostname; -} - - -unsigned int windowsHandler::getProcessId() const -{ - return (static_cast (::GetCurrentProcessId())); -} - - -unsigned int windowsHandler::getThreadId() const -{ - return static_cast (::GetCurrentThreadId()); -} - - -#if VMIME_HAVE_MESSAGING_FEATURES - -shared_ptr windowsHandler::getSocketFactory() -{ - return m_socketFactory; -} - -#endif - - -#if VMIME_HAVE_FILESYSTEM_FEATURES - -shared_ptr windowsHandler::getFileSystemFactory() -{ - return m_fileSysFactory; -} - - -shared_ptr windowsHandler::getChildProcessFactory() -{ - // TODO: Not implemented - return (NULL); -} - -#endif - - -void windowsHandler::wait() const -{ - ::Sleep(100); -} - - -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 (count), static_cast (buffer)); - CryptReleaseContext(cryptProvider, 0); -} - - -shared_ptr windowsHandler::createCriticalSection() -{ - return make_shared (); -} - - -} // posix -} // platforms -} // vmime - - -#endif // VMIME_PLATFORM_IS_WINDOWS - diff --git a/src/platforms/windows/windowsSocket.cpp b/src/platforms/windows/windowsSocket.cpp deleted file mode 100644 index 40e69363..00000000 --- a/src/platforms/windows/windowsSocket.cpp +++ /dev/null @@ -1,484 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/exception.hpp" - -#include - - -namespace vmime { -namespace platforms { -namespace windows { - - -// -// windowsSocket -// - -windowsSocket::windowsSocket(shared_ptr 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 (port)); - addr.sin_addr.s_addr = ::inet_addr(address.c_str()); - - if (addr.sin_addr.s_addr == static_cast (-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 (&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 (&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) - { - ::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 (&peer), &peerLen); - - // Convert to numerical presentation format - char host[NI_MAXHOST + 1]; - char service[NI_MAXSERV + 1]; - - if (getnameinfo(reinterpret_cast (&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 (&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 (&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 = vmime::string(m_buffer, size); -} - - -size_t windowsSocket::receiveRaw(char* buffer, const size_t count) -{ - m_status &= ~STATUS_WOULDBLOCK; - - // Check whether data is available - bool timedout; - waitForData(READ, timedout); - - if (timedout) - { - // 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, 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 (buffer.data()), buffer.length()); -} - - -void windowsSocket::send(const char* str) -{ - sendRaw(reinterpret_cast (str), strlen(str)); -} - - -void windowsSocket::sendRaw(const char* buffer, const size_t count) -{ - m_status &= ~STATUS_WOULDBLOCK; - - size_t size = count; - - while (size > 0) - { - const int ret = ::send(m_desc, buffer, size, 0); - - if (ret == SOCKET_ERROR) - { - int err = WSAGetLastError(); - - if (err != WSAEWOULDBLOCK) - throwSocketError(err); - - bool timedout; - waitForData(WRITE, timedout); - } - else - { - buffer += ret; - size -= ret; - } - } - - // Reset timeout - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); -} - - -size_t windowsSocket::sendRawNonBlocking(const char* buffer, const size_t count) -{ - m_status &= ~STATUS_WOULDBLOCK; - - const int ret = ::send(m_desc, 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); -} - - -void windowsSocket::waitForData(const WaitOpType t, bool& timedOut) -{ - // Check whether data is available - fd_set fds; - FD_ZERO(&fds); - FD_SET(m_desc, &fds); - - struct timeval tv; - tv.tv_sec = 1; - tv.tv_usec = 0; - - int ret; - - if (t & READ) - ret = ::select(m_desc + 1, &fds, NULL, NULL, &tv); - else if (t & WRITE) - ret = ::select(m_desc + 1, NULL, &fds, NULL, &tv); - else - ret = ::select(m_desc + 1, &fds, &fds, NULL, &tv); - - timedOut = (ret == 0); - - if (ret == SOCKET_ERROR) - { - int err = WSAGetLastError(); - throwSocketError(err); - } -} - - - -// -// posixSocketFactory -// - -shared_ptr windowsSocketFactory::create() -{ - shared_ptr th = NULL; - return make_shared (th); -} - -shared_ptr windowsSocketFactory::create(shared_ptr th) -{ - return make_shared (th); -} - -} // posix -} // platforms -} // vmime - - -#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/propertySet.cpp b/src/propertySet.cpp deleted file mode 100644 index c22e79a6..00000000 --- a/src/propertySet.cpp +++ /dev/null @@ -1,382 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 >::const_iterator it = set.m_props.begin() ; it != set.m_props.end() ; ++it) - m_props.push_back(make_shared (**it)); -} - - -propertySet::~propertySet() -{ - removeAllProperties(); -} - - -propertySet& propertySet::operator=(const propertySet& set) -{ - removeAllProperties(); - - for (std::list >::const_iterator it = set.m_props.begin() ; it != set.m_props.end() ; ++it) - m_props.push_back(make_shared (**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 >::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 (option, value)); - } - } -} - - -shared_ptr propertySet::find(const string& name) const -{ - std::list >::const_iterator it = std::find_if - (m_props.begin(), m_props.end(), propFinder(name)); - - return (it != m_props.end() ? *it : null); -} - - -shared_ptr propertySet::findOrCreate(const string& name) -{ - std::list >::const_iterator it = std::find_if - (m_props.begin(), m_props.end(), propFinder(name)); - - if (it != m_props.end()) - { - return (*it); - } - else - { - shared_ptr prop = make_shared (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 > propertySet::getPropertyList() const -{ - std::vector > res; - - for (list_type::const_iterator it = m_props.begin() ; it != m_props.end() ; ++it) - res.push_back(*it); - - return (res); -} - - -const std::vector > propertySet::getPropertyList() -{ - std::vector > 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/src/relay.cpp b/src/relay.cpp deleted file mode 100644 index e5d30c9e..00000000 --- a/src/relay.cpp +++ /dev/null @@ -1,354 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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))); - - string word; - std::vector 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 ::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 ::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 (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 relay::clone() const -{ - return make_shared (*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 & relay::getWithList() const -{ - return (m_with); -} - - -std::vector & relay::getWithList() -{ - return (m_with); -} - - -const std::vector > relay::getChildComponents() -{ - // TODO: should fields inherit from 'component'? (using typeAdapter) - return std::vector >(); -} - - -} // vmime diff --git a/src/security/cert/X509Certificate.cpp b/src/security/cert/X509Certificate.cpp deleted file mode 100644 index 2eebabfd..00000000 --- a/src/security/cert/X509Certificate.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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" - - -namespace vmime { -namespace security { -namespace cert { - - -X509Certificate::~X509Certificate() -{ -} - - -} // cert -} // security -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/src/security/cert/certificateChain.cpp b/src/security/cert/certificateChain.cpp deleted file mode 100644 index 3cb4e360..00000000 --- a/src/security/cert/certificateChain.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 >& certs) - : m_certs(certs) -{ -} - - -unsigned int certificateChain::getCount() const -{ - return static_cast (m_certs.size()); -} - - -shared_ptr certificateChain::getAt(const unsigned int index) -{ - return m_certs[index]; -} - - -} // cert -} // security -} // vmime - diff --git a/src/security/cert/defaultCertificateVerifier.cpp b/src/security/cert/defaultCertificateVerifier.cpp deleted file mode 100644 index 1a95b353..00000000 --- a/src/security/cert/defaultCertificateVerifier.cpp +++ /dev/null @@ -1,178 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_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 - (shared_ptr 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 exceptions::unsupported_certificate_type(type); -} - - -void defaultCertificateVerifier::verifyX509 - (shared_ptr 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 (unsigned int i = 0 ; i < chain->getCount() - 1 ; ++i) - { - shared_ptr cert = - dynamicCast (chain->getAt(i)); - - shared_ptr next = - dynamicCast (chain->getAt(i + 1)); - - if (!cert->checkIssuer(next)) - { - throw exceptions::certificate_verification_exception - ("Subject/issuer verification failed."); - } - } - } - - // For every certificate in the chain, verify that the certificate - // is valid at the current time - const datetime now = datetime::now(); - - for (unsigned int i = 0 ; i < chain->getCount() ; ++i) - { - shared_ptr cert = - dynamicCast (chain->getAt(i)); - - const datetime begin = cert->getActivationDate(); - const datetime end = cert->getExpirationDate(); - - if (now < begin || now > end) - { - throw exceptions::certificate_verification_exception - ("Validity date check failed."); - } - } - - // 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 lastCert = - dynamicCast (chain->getAt(chain->getCount() - 1)); - - bool trusted = false; - - for (unsigned int i = 0 ; !trusted && i < m_x509RootCAs.size() ; ++i) - { - shared_ptr rootCa = m_x509RootCAs[i]; - - if (lastCert->verify(rootCa)) - trusted = true; - } - - // -- Next, if the issuer certificate cannot be verified against - // -- root CAs, compare the subject's certificate against the - // -- trusted certificates - shared_ptr firstCert = - dynamicCast (chain->getAt(0)); - - for (unsigned int i = 0 ; !trusted && i < m_x509TrustedCerts.size() ; ++i) - { - shared_ptr cert = m_x509TrustedCerts[i]; - - if (firstCert->equals(cert)) - trusted = true; - } - - if (!trusted) - { - throw exceptions::certificate_verification_exception - ("Cannot verify certificate against trusted certificates."); - } - - // Ensure the first certificate's subject name matches server hostname - if (!firstCert->verifyHostName(hostname)) - { - throw exceptions::certificate_verification_exception - ("Server identity cannot be verified."); - } -} - - -void defaultCertificateVerifier::setX509RootCAs - (const std::vector >& caCerts) -{ - m_x509RootCAs = caCerts; -} - - -void defaultCertificateVerifier::setX509TrustedCerts - (const std::vector >& trustedCerts) -{ - m_x509TrustedCerts = trustedCerts; -} - - -} // cert -} // security -} // vmime - -#endif diff --git a/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp b/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp deleted file mode 100644 index f96ddddb..00000000 --- a/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp +++ /dev/null @@ -1,290 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - -#include - -#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); - } - - - gnutls_x509_crt 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::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::import - (const byte_t* data, const size_t length) -{ - gnutls_datum buffer; - buffer.data = const_cast (data); - buffer.size = static_cast (length); - - // Try DER format - shared_ptr derCert = make_shared (); - - if (gnutls_x509_crt_import(derCert->m_data->cert, &buffer, GNUTLS_X509_FMT_DER) >= 0) - return derCert; - - // Try PEM format - shared_ptr pemCert = make_shared (); - - if (gnutls_x509_crt_import(pemCert->m_data->cert, &buffer, GNUTLS_X509_FMT_PEM) >= 0) - return pemCert; - - return null; -} - - -void X509Certificate_GnuTLS::write - (utility::outputStream& os, const Format format) const -{ - size_t dataSize = 0; - gnutls_x509_crt_fmt 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 data(dataSize); - - gnutls_x509_crt_export(m_data->cert, fmt, &data[0], &dataSize); - - os.write(reinterpret_cast (&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(shared_ptr issuer_) const -{ - shared_ptr issuer = - dynamicCast (issuer_); - - return (gnutls_x509_crt_check_issuer - (m_data->cert, issuer->m_data->cert) >= 1); -} - - -bool X509Certificate_GnuTLS::verify(shared_ptr caCert_) const -{ - shared_ptr caCert = - dynamicCast (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) const -{ - return gnutls_x509_crt_check_hostname(m_data->cert, hostname.c_str()) != 0; -} - - -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 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 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::getType() const -{ - return "X.509"; -} - - -int X509Certificate_GnuTLS::getVersion() const -{ - return gnutls_x509_crt_get_version(m_data->cert); -} - - -bool X509Certificate_GnuTLS::equals(shared_ptr other) const -{ - shared_ptr otherX509 = - dynamicCast (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/src/security/cert/openssl/X509Certificate_OpenSSL.cpp b/src/security/cert/openssl/X509Certificate_OpenSSL.cpp deleted file mode 100644 index 5f81b2bf..00000000 --- a/src/security/cert/openssl/X509Certificate_OpenSSL.cpp +++ /dev/null @@ -1,574 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include -#include -#include - -#include "vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp" - -#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp" - -#include "vmime/utility/outputStreamByteArrayAdapter.hpp" - -#include "vmime/exception.hpp" - -#include -#include -#include -#include -#include -#include - - -#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 ::const_iterator - c_it = m_monthMap.find(mstr); - - if (c_it != m_monthMap.end()) - return c_it->second; - - return -1; - } - -private: - - std::map m_monthMap; -}; - -static monthMap sg_monthMap; - - - -struct OpenSSLX509CertificateInternalData -{ - OpenSSLX509CertificateInternalData() - { - cert = 0; - } - - ~OpenSSLX509CertificateInternalData() - { - if (cert) - X509_free(cert); - } - - X509* cert; -}; - -#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_OpenSSL::importInternal(X509* cert) -{ - if (cert) - return make_shared (reinterpret_cast (cert)); - - return null; -} - - -// static -shared_ptr 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::import - (const byte_t* data, const size_t length) -{ - shared_ptr cert = make_shared (); - - BIO* membio = BIO_new_mem_buf(const_cast (data), static_cast (length)); - - if (!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0)) - { - BIO_vfree(membio); - return null; - } - - BIO_vfree(membio); - - return cert; -} - - -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 (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 (out), dataSize); - os.flush(); - BIO_vfree(membio); - } - else - { - throw vmime::exceptions::unsupported_certificate_type("Unknown cert type"); - } - - 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 vmime::exceptions::certificate_exception( - "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(shared_ptr cert_) const -{ - shared_ptr cert = - dynamicCast (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(shared_ptr caCert_) const -{ - shared_ptr caCert = - dynamicCast (caCert_); - - - 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) 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; - } - - // Now, look in subject alternative names - for (int i = 0, extCount = X509_get_ext_count(m_data->cert) ; i < extCount ; ++i) - { - X509_EXTENSION* ext = X509_get_ext(m_data->cert, i); - const char* extStr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); - - if (strcmp(extStr, "subjectAltName") == 0) - { -#ifdef _WIN32 - X509V3_EXT_METHOD* method; -#else - const X509V3_EXT_METHOD* method; -#endif - - if ((method = X509V3_EXT_get(ext)) != NULL) - { - const unsigned char* extVal = ext->value->data; - void *extValStr; - - if (method->it) - { - extValStr = ASN1_item_d2i - (NULL, &extVal, ext->value->length, ASN1_ITEM_ptr(method->it)); - } - else - { - extValStr = method->d2i - (NULL, &extVal, ext->value->length); - } - - if (extValStr && method->i2v) - { - STACK_OF(CONF_VALUE)* val = method->i2v(method, extValStr, NULL); - - for (int j = 0 ; j < sk_CONF_VALUE_num(val) ; ++j) - { - CONF_VALUE* cnf = sk_CONF_VALUE_value(val, j); - - if ((strcasecmp(cnf->name, "DNS") == 0 && - strcasecmp(cnf->value, hostname.c_str()) == 0) - || - (strncasecmp(cnf->name, "IP", 2) == 0 && - strcasecmp(cnf->value, hostname.c_str()) == 0)) - { - return true; - } - } - } - } - } - } - - return false; -} - - -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(time); - ASN1_TIME_print(out, asn1_time); - - int 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, *result; - 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, ":"); - } - } - - n = BIO_get_mem_data(out, &fingerprint); - result = new unsigned char[n]; - memcpy (result, fingerprint, n); - BIO_free(out); - - byteArray res; - res.insert(res.end(), &result[0], &result[0] + n); - - 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::getType() const -{ - return "X.509"; -} - - -int X509Certificate_OpenSSL::getVersion() const -{ - return (int)X509_get_version(m_data->cert); -} - - -bool X509Certificate_OpenSSL::equals(shared_ptr other) const -{ - shared_ptr otherX509 = - dynamicCast (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/src/security/defaultAuthenticator.cpp b/src/security/defaultAuthenticator.cpp deleted file mode 100644 index 790196d2..00000000 --- a/src/security/defaultAuthenticator.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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 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::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(shared_ptr serv) -{ - m_service = serv; -} - - -weak_ptr defaultAuthenticator::getService() const -{ - return m_service; -} - - -} // security -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/security/digest/md5/md5MessageDigest.cpp b/src/security/digest/md5/md5MessageDigest.cpp deleted file mode 100644 index a83f0623..00000000 --- a/src/security/digest/md5/md5MessageDigest.cpp +++ /dev/null @@ -1,347 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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 (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 (m_byteCount << 3); - m_block.b32[15] = static_cast (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<>(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 (m_hash); -} - - -} // md5 -} // digest -} // security -} // vmime - diff --git a/src/security/digest/messageDigest.cpp b/src/security/digest/messageDigest.cpp deleted file mode 100644 index 18fc8628..00000000 --- a/src/security/digest/messageDigest.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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/src/security/digest/messageDigestFactory.cpp b/src/security/digest/messageDigestFactory.cpp deleted file mode 100644 index 2831c5a1..00000000 --- a/src/security/digest/messageDigestFactory.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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"); - registerAlgorithm ("sha1"); -} - - -messageDigestFactory::~messageDigestFactory() -{ -} - - -messageDigestFactory* messageDigestFactory::getInstance() -{ - static messageDigestFactory instance; - return (&instance); -} - - -shared_ptr 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 messageDigestFactory::getSupportedAlgorithms() const -{ - std::vector 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/src/security/digest/sha1/sha1MessageDigest.cpp b/src/security/digest/sha1/sha1MessageDigest.cpp deleted file mode 100644 index aa055af5..00000000 --- a/src/security/digest/sha1/sha1MessageDigest.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -// 100% public domain. - -#include "vmime/security/digest/sha1/sha1MessageDigest.hpp" - -#include -#include - - -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 (s.data()), s.length()); -} - - -void sha1MessageDigest::update(const byte_t* buffer, const size_t offset, - const unsigned long 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 (len << 3)) < static_cast (len << 3)) - m_count[1]++; - - m_count[1] += static_cast (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 - ((m_count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); // Endian independent - } - - update(reinterpret_cast ("\200"), 1); - - while ((m_count[0] & 504) != 448) - update(reinterpret_cast ("\0"), 1); - - update(finalcount, 8); // Should cause a transform() - - for (i = 0 ; i < 20 ; i++) - { - m_digest[i] = static_cast - ((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 (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 (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/src/security/sasl/SASLContext.cpp b/src/security/sasl/SASLContext.cpp deleted file mode 100644 index 3474cbeb..00000000 --- a/src/security/sasl/SASLContext.cpp +++ /dev/null @@ -1,208 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#include - -#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); -} - - -shared_ptr SASLContext::createSession - (const string& serviceName, - shared_ptr auth, shared_ptr mech) -{ - return make_shared - (serviceName, dynamicCast (shared_from_this()), auth, mech); -} - - -shared_ptr SASLContext::createMechanism(const string& name) -{ - return SASLMechanismFactory::getInstance()->create - (dynamicCast (shared_from_this()), name); -} - - -shared_ptr SASLContext::suggestMechanism - (const std::vector >& 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 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 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/src/security/sasl/SASLMechanismFactory.cpp b/src/security/sasl/SASLMechanismFactory.cpp deleted file mode 100644 index 255a13f1..00000000 --- a/src/security/sasl/SASLMechanismFactory.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - -#include - -#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 SASLMechanismFactory::create - (shared_ptr ctx, const string& name_) -{ - const string name(utility::stringUtils::toUpper(name_)); - - // Check for built-in mechanisms - if (isMechanismSupported(name)) - { - return make_shared (ctx, name); - } - // Check for registered mechanisms - else - { - MapType::iterator it = m_mechs.find(name); - - if (it != m_mechs.end()) - return (*it).second->create(ctx, name); - } - - throw exceptions::no_such_mechanism(name); - return null; -} - - -const std::vector SASLMechanismFactory::getSupportedMechanisms() const -{ - std::vector 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 (gsasl_client_support_p(m_gsaslContext, name.c_str()) != 0 || - m_mechs.find(name) != m_mechs.end()); -} - - -} // sasl -} // security -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT - diff --git a/src/security/sasl/SASLSession.cpp b/src/security/sasl/SASLSession.cpp deleted file mode 100644 index 087ef27b..00000000 --- a/src/security/sasl/SASLSession.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#include - -#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, shared_ptr ctx, - shared_ptr auth, shared_ptr 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; -} - - -void SASLSession::init() -{ - shared_ptr saslAuth = dynamicCast (m_auth); - - if (saslAuth) - { - saslAuth->setSASLMechanism(m_mech); - saslAuth->setSASLSession(dynamicCast (shared_from_this())); - } -} - - -shared_ptr SASLSession::getAuthenticator() -{ - return m_auth; -} - - -shared_ptr SASLSession::getMechanism() -{ - return m_mech; -} - - -shared_ptr 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 (shared_from_this()), - challenge, challengeLen, response, responseLen); -} - - -shared_ptr SASLSession::getSecuredSocket(shared_ptr sok) -{ - return make_shared (dynamicCast (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 (gsasl_callback_hook_get(ctx)); - if (!sess) return GSASL_AUTHENTICATION_ERROR; - - shared_ptr 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 (exceptions::no_auth_information&) - catch (...) - { - return GSASL_NO_CALLBACK; - } -} - - -} // sasl -} // security -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT - diff --git a/src/security/sasl/SASLSocket.cpp b/src/security/sasl/SASLSocket.cpp deleted file mode 100644 index 12d634c2..00000000 --- a/src/security/sasl/SASLSocket.cpp +++ /dev/null @@ -1,236 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - -#include - - -namespace vmime { -namespace security { -namespace sasl { - - - -SASLSocket::SASLSocket(shared_ptr sess, shared_ptr 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(); -} - - -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 (buffer.data()), buffer.length()); -} - - -void SASLSocket::send(const char* str) -{ - sendRaw(reinterpret_cast (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/src/security/sasl/builtinSASLMechanism.cpp b/src/security/sasl/builtinSASLMechanism.cpp deleted file mode 100644 index e179e715..00000000 --- a/src/security/sasl/builtinSASLMechanism.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#include "vmime/security/sasl/builtinSASLMechanism.hpp" - -#include "vmime/security/sasl/SASLContext.hpp" -#include "vmime/security/sasl/SASLSession.hpp" - -#include "vmime/exception.hpp" - -#include -#include - - -namespace vmime { -namespace security { -namespace sasl { - - -builtinSASLMechanism::builtinSASLMechanism(shared_ptr 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 - (shared_ptr 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 (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; -} - - -void builtinSASLMechanism::encode - (shared_ptr 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 (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 (coutputLen); - } - catch (...) - { - gsasl_free(coutput); - throw; - } - - gsasl_free(coutput); -} - - -void builtinSASLMechanism::decode - (shared_ptr 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 (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 (coutputLen); - } - catch (...) - { - gsasl_free(coutput); - throw; - } - - gsasl_free(coutput); -} - - -} // sasl -} // security -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT - diff --git a/src/security/sasl/defaultSASLAuthenticator.cpp b/src/security/sasl/defaultSASLAuthenticator.cpp deleted file mode 100644 index 7fe9b3eb..00000000 --- a/src/security/sasl/defaultSASLAuthenticator.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 > - defaultSASLAuthenticator::getAcceptableMechanisms - (const std::vector >& available, - shared_ptr suggested) const -{ - if (suggested) - { - std::vector > 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::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(shared_ptr serv) -{ - m_service = serv; - m_default.setService(serv); -} - - -weak_ptr defaultSASLAuthenticator::getService() const -{ - return m_service; -} - - -void defaultSASLAuthenticator::setSASLSession(shared_ptr sess) -{ - m_saslSession = sess; -} - - -shared_ptr defaultSASLAuthenticator::getSASLSession() const -{ - return constCast (m_saslSession.lock()); -} - - -void defaultSASLAuthenticator::setSASLMechanism(shared_ptr mech) -{ - m_saslMech = mech; -} - - -shared_ptr defaultSASLAuthenticator::getSASLMechanism() const -{ - return m_saslMech; -} - - -} // sasl -} // security -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT - diff --git a/src/streamContentHandler.cpp b/src/streamContentHandler.cpp deleted file mode 100644 index 8676cc34..00000000 --- a/src/streamContentHandler.cpp +++ /dev/null @@ -1,234 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr 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 streamContentHandler::clone() const -{ - return make_shared (*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(shared_ptr 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 theDecoder = m_encoding.getEncoder(); - shared_ptr 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 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 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 (m_stream) != NULL) - 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/src/stringContentHandler.cpp b/src/stringContentHandler.cpp deleted file mode 100644 index 9a66663c..00000000 --- a/src/stringContentHandler.cpp +++ /dev/null @@ -1,236 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/inputStreamStringProxyAdapter.hpp" -#include "vmime/utility/outputStreamAdapter.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(const utility::stringProxy& str, const vmime::encoding& enc) - : m_encoding(enc), m_string(str) -{ -} - - -stringContentHandler::stringContentHandler(const string& buffer, const size_t start, - const size_t end, const vmime::encoding& enc) - : m_encoding(enc), m_string(buffer, start, end) -{ -} - - -stringContentHandler::~stringContentHandler() -{ -} - - -shared_ptr stringContentHandler::clone() const -{ - return make_shared (*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 utility::stringProxy& str, const vmime::encoding& enc) -{ - m_encoding = enc; - m_string = str; -} - - -void stringContentHandler::setData(const string& buffer, const vmime::encoding& enc) -{ - m_encoding = enc; - m_string.set(buffer); -} - - -void stringContentHandler::setData(const string& buffer, const size_t start, - const size_t end, const vmime::encoding& enc) -{ - m_encoding = enc; - m_string.set(buffer, start, end); -} - - -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 theDecoder = m_encoding.getEncoder(); - shared_ptr theEncoder = enc.getEncoder(); - - theEncoder->getProperties()["maxlinelength"] = maxLineLength; - theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT); - - utility::inputStreamStringProxyAdapter 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 - { - m_string.extract(os); - } - } - // Need to encode data before - else - { - shared_ptr theEncoder = enc.getEncoder(); - theEncoder->getProperties()["maxlinelength"] = maxLineLength; - theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT); - - utility::inputStreamStringProxyAdapter in(m_string); - - theEncoder->encode(in, os); - } -} - - -void stringContentHandler::extract(utility::outputStream& os, - utility::progressListener* progress) const -{ - // No decoding to perform - if (!isEncoded()) - { - m_string.extract(os, 0, m_string.length(), progress); - } - // Need to decode data - else - { - shared_ptr theDecoder = m_encoding.getEncoder(); - - utility::inputStreamStringProxyAdapter in(m_string); - utility::progressListenerSizeAdapter plsa(progress, getLength()); - - theDecoder->decode(in, os, &plsa); - } -} - - -void stringContentHandler::extractRaw(utility::outputStream& os, - utility::progressListener* progress) const -{ - m_string.extract(os, 0, 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/src/text.cpp b/src/text.cpp deleted file mode 100644 index 08fc9ba9..00000000 --- a/src/text.cpp +++ /dev/null @@ -1,435 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 (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 > 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 (other); - - removeAllWords(); - - for (std::vector >::const_iterator i = t.m_words.begin() ; i != t.m_words.end() ; ++i) - m_words.push_back(make_shared (**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 >::const_iterator i = m_words.begin(); - std::vector >::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 >::const_iterator i = m_words.begin() ; i != m_words.end() ; ++i) - out += (*i)->getConvertedText(dest, opts); - - return (out); -} - - -void text::appendWord(shared_ptr w) -{ - m_words.push_back(w); -} - - -void text::insertWordBefore(const size_t pos, shared_ptr w) -{ - m_words.insert(m_words.begin() + pos, w); -} - - -void text::insertWordAfter(const size_t pos, shared_ptr w) -{ - m_words.insert(m_words.begin() + pos + 1, w); -} - - -void text::removeWord(const size_t pos) -{ - const std::vector >::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 text::getWordAt(const size_t pos) -{ - return (m_words[pos]); -} - - -const shared_ptr text::getWordAt(const size_t pos) const -{ - return (m_words[pos]); -} - - -const std::vector > text::getWordList() const -{ - std::vector > list; - - list.reserve(m_words.size()); - - for (std::vector >::const_iterator it = m_words.begin() ; - it != m_words.end() ; ++it) - { - list.push_back(*it); - } - - return (list); -} - - -const std::vector > text::getWordList() -{ - return (m_words); -} - - -shared_ptr text::clone() const -{ - return make_shared (*this); -} - - -shared_ptr text::newFromString(const string& in, const charset& ch) -{ - shared_ptr t = make_shared (); - - 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 (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 w = getWordAt(getWordCount() - 1); - w->getBuffer() += " " + chunk; - } - else - { - if (count) - { - shared_ptr w = getWordAt(getWordCount() - 1); - w->getBuffer() += ' '; - } - - appendWord(make_shared (chunk, ch)); - - prevIs8bit = true; - ++count; - } - } - else - { - if (count && !prevIs8bit) - { - shared_ptr w = getWordAt(getWordCount() - 1); - w->getBuffer() += " " + chunk; - } - else - { - appendWord(make_shared - (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::decodeAndUnfold(const string& in) -{ - shared_ptr t = make_shared (); - - decodeAndUnfold(parsingContext::getDefaultContext(), in, t.get()); - - return t; -} - - -shared_ptr text::decodeAndUnfold(const parsingContext& ctx, const string& in) -{ - shared_ptr t = make_shared (); - - 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 != NULL) ? generateInExisting : new text(); - - out->removeAllWords(); - - const std::vector > words = word::parseMultiple(ctx, in, 0, in.length(), NULL); - - copy_vector(words, out->m_words); - - return (out); -} - - -const std::vector > text::getChildComponents() -{ - std::vector > list; - - copy_vector(m_words, list); - - return (list); -} - - -const string text::getWholeBuffer() const -{ - string res; - - for (std::vector >::const_iterator it = m_words.begin() ; - it != m_words.end() ; ++it) - { - res += (*it)->getBuffer(); - } - - return res; -} - - -} // vmime diff --git a/src/textPartFactory.cpp b/src/textPartFactory.cpp deleted file mode 100644 index 85fea6e4..00000000 --- a/src/textPartFactory.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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() -{ - // Register some default names - registerType (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); - registerType (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML)); -} - - -textPartFactory::~textPartFactory() -{ -} - - -textPartFactory* textPartFactory::getInstance() -{ - static textPartFactory instance; - return (&instance); -} - - -shared_ptr 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(); -} - - -} // vmime diff --git a/src/utility/datetimeUtils.cpp b/src/utility/datetimeUtils.cpp deleted file mode 100644 index 2b55177e..00000000 --- a/src/utility/datetimeUtils.cpp +++ /dev/null @@ -1,333 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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/src/utility/encoder/b64Encoder.cpp b/src/utility/encoder/b64Encoder.cpp deleted file mode 100644 index 274c23c0..00000000 --- a/src/utility/encoder/b64Encoder.cpp +++ /dev/null @@ -1,330 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 b64Encoder::getAvailableProperties() const -{ - std::vector 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 (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 ("maxlinelength", static_cast (-1)); - - const bool cutLines = (propMaxLineLength != static_cast (-1)); - const size_t maxLineLength = std::min(propMaxLineLength, static_cast (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; - } - } - } - - // Decode the bytes - byte_t c1 = bytes[0]; - byte_t c2 = bytes[1]; - - if (c1 == '=' || c2 == '=') // end - break; - - output[0] = static_cast ((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 (((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 (((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 ("maxlinelength", static_cast (-1)); - - const bool cutLines = (propMaxLineLength != static_cast (-1)); - const size_t maxLineLength = std::min(propMaxLineLength, static_cast (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/src/utility/encoder/binaryEncoder.cpp b/src/utility/encoder/binaryEncoder.cpp deleted file mode 100644 index 7d7c40d1..00000000 --- a/src/utility/encoder/binaryEncoder.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/utility/encoder/eightBitEncoder.cpp b/src/utility/encoder/eightBitEncoder.cpp deleted file mode 100644 index 4ab07f06..00000000 --- a/src/utility/encoder/eightBitEncoder.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/utility/encoder/encoder.cpp b/src/utility/encoder/encoder.cpp deleted file mode 100644 index b4b13249..00000000 --- a/src/utility/encoder/encoder.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 encoder::getAvailableProperties() const -{ - std::vector list; - return (list); -} - - -} // encoder -} // utility -} // vmime diff --git a/src/utility/encoder/encoderFactory.cpp b/src/utility/encoder/encoderFactory.cpp deleted file mode 100644 index 098a810a..00000000 --- a/src/utility/encoder/encoderFactory.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 ("base64"); - registerName ("quoted-printable"); - registerName ("uuencode"); - registerName ("7bit"); - registerName ("8bit"); - registerName ("binary"); - - // Also register some non-standard encoding names - registerName ("7-bit"); - registerName ("8-bit"); - - // Finally, register some bogus encoding names, for compatibility - registerName ("bmoted-printable"); -} - - -encoderFactory::~encoderFactory() -{ -} - - -shared_ptr encoderFactory::getInstance() -{ - static encoderFactory instance; - return shared_ptr (&instance, noop_shared_ptr_deleter ()); -} - - -shared_ptr encoderFactory::create(const string& name) -{ - return (getEncoderByName(name)->create()); -} - - -const shared_ptr encoderFactory::getEncoderByName(const string& name) const -{ - const string lcName(utility::stringUtils::toLower(name)); - - for (std::vector >::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 encoderFactory::getEncoderAt(const size_t pos) const -{ - return (m_encoders[pos]); -} - - -const std::vector > encoderFactory::getEncoderList() const -{ - std::vector > res; - - for (std::vector >::const_iterator it = m_encoders.begin() ; - it != m_encoders.end() ; ++it) - { - res.push_back(*it); - } - - return (res); -} - - -} // encoder -} // utility -} // vmime diff --git a/src/utility/encoder/noopEncoder.cpp b/src/utility/encoder/noopEncoder.cpp deleted file mode 100644 index 3d991b5d..00000000 --- a/src/utility/encoder/noopEncoder.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/utility/encoder/qpEncoder.cpp b/src/utility/encoder/qpEncoder.cpp deleted file mode 100644 index c77b5163..00000000 --- a/src/utility/encoder/qpEncoder.cpp +++ /dev/null @@ -1,558 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 qpEncoder::getAvailableProperties() const -{ - std::vector 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: . " -// -// 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 (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 ("maxlinelength", static_cast (-1)); - - const bool rfc2047 = getProperties().getProperty ("rfc2047", false); - const bool text = getProperties().getProperty ("text", false); // binary mode by default - - const bool cutLines = (propMaxLineLength != static_cast (-1)); - const size_t maxLineLength = std::min(propMaxLineLength, static_cast (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 (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; - } - // 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 ("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 - (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; - } - - // no break here... - } - default: - { - outBuffer[outBufferPos++] = c; - } - - } - - 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 ("maxlinelength", static_cast (-1)); - - const bool cutLines = (propMaxLineLength != static_cast (-1)); - const size_t maxLineLength = std::min(propMaxLineLength, static_cast (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/src/utility/encoder/sevenBitEncoder.cpp b/src/utility/encoder/sevenBitEncoder.cpp deleted file mode 100644 index 7c76d73f..00000000 --- a/src/utility/encoder/sevenBitEncoder.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/utility/encoder/uuEncoder.cpp b/src/utility/encoder/uuEncoder.cpp deleted file mode 100644 index 0375a397..00000000 --- a/src/utility/encoder/uuEncoder.cpp +++ /dev/null @@ -1,344 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 uuEncoder::getAvailableProperties() const -{ - std::vector 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 ((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 ("filename", ""); - const string propMode = getProperties().getProperty ("mode", "644"); - - const size_t maxLineLength = - std::min(getProperties().getProperty ("maxlinelength", 46), static_cast (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 (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 (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 (3)); - - switch (n) - { - default: - case 3: outBuffer[j + 2] = static_cast (UUDECODE(c3) << 6 | UUDECODE(c4)); - case 2: outBuffer[j + 1] = static_cast (UUDECODE(c2) << 4 | UUDECODE(c3) >> 2); - case 1: outBuffer[j] = static_cast (UUDECODE(c1) << 2 | UUDECODE(c2) >> 4); - case 0: break; - } - - 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/src/utility/filteredStream.cpp b/src/utility/filteredStream.cpp deleted file mode 100644 index bb705162..00000000 --- a/src/utility/filteredStream.cpp +++ /dev/null @@ -1,391 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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; - - // Replace "\n.." with "\n." - while (readPtr < end) - { - if (*readPtr == '.') - { - const byte_t prevChar2 = - (readPtr == data + 1 ? m_previousChar1 : - readPtr == data ? m_previousChar2 : *(readPtr - 2)); - const byte_t prevChar1 = - (readPtr == data ? m_previousChar1 : *(readPtr - 1)); - - if (prevChar2 == '\n' && prevChar1 == '.') - { - // Ignore last dot - } - else - { - *writePtr = *readPtr; - - ++writePtr; - ++written; - } - } - else - { - *writePtr = *readPtr; - - ++writePtr; - ++written; - } - - ++readPtr; - } - - m_previousChar2 = (read >= 2 ? data[read - 2] : m_previousChar1); - m_previousChar1 = (read >= 1 ? data[read - 1] : '\0'); - - 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 - 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) // 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(); -} - - -// 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 -} - - -// 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(); -} - - -// 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/src/utility/inputStream.cpp b/src/utility/inputStream.cpp deleted file mode 100644 index a7d6bc0f..00000000 --- a/src/utility/inputStream.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/utility/inputStreamAdapter.cpp b/src/utility/inputStreamAdapter.cpp deleted file mode 100644 index c0b06be4..00000000 --- a/src/utility/inputStreamAdapter.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 (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/src/utility/inputStreamByteBufferAdapter.cpp b/src/utility/inputStreamByteBufferAdapter.cpp deleted file mode 100644 index c270ea56..00000000 --- a/src/utility/inputStreamByteBufferAdapter.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/utility/inputStreamPointerAdapter.cpp b/src/utility/inputStreamPointerAdapter.cpp deleted file mode 100644 index 6bf0461a..00000000 --- a/src/utility/inputStreamPointerAdapter.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/src/utility/inputStreamSocketAdapter.cpp b/src/utility/inputStreamSocketAdapter.cpp deleted file mode 100644 index d78855eb..00000000 --- a/src/utility/inputStreamSocketAdapter.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/inputStreamSocketAdapter.hpp" - - -#if VMIME_HAVE_MESSAGING_FEATURES - - -#include "vmime/net/socket.hpp" - - -namespace vmime { -namespace utility { - - -inputStreamSocketAdapter::inputStreamSocketAdapter(net::socket& sok) - : m_socket(sok) -{ -} - - -bool inputStreamSocketAdapter::eof() const -{ - // Can't know... - return false; -} - - -void inputStreamSocketAdapter::reset() -{ - // Not supported -} - - -size_t inputStreamSocketAdapter::read - (byte_t* const data, const size_t count) -{ - return m_socket.receiveRaw(data, count); -} - - -size_t inputStreamSocketAdapter::skip - (const size_t /* count */) -{ - // Not supported - return 0; -} - - -size_t inputStreamSocketAdapter::getBlockSize() -{ - return m_socket.getBlockSize(); -} - - -} // utility -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/utility/inputStreamStringAdapter.cpp b/src/utility/inputStreamStringAdapter.cpp deleted file mode 100644 index 9b897b97..00000000 --- a/src/utility/inputStreamStringAdapter.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/inputStreamStringAdapter.hpp" - - -namespace vmime { -namespace utility { - - -inputStreamStringAdapter::inputStreamStringAdapter(const string& buffer) - : m_buffer(buffer), m_begin(0), m_end(buffer.length()), m_pos(0) -{ -} - - -inputStreamStringAdapter::inputStreamStringAdapter(const string& buffer, - const size_t begin, const size_t end) - : m_buffer(buffer), m_begin(begin), m_end(end), m_pos(begin) -{ -} - - -bool inputStreamStringAdapter::eof() const -{ - return (m_pos >= m_end); -} - - -void inputStreamStringAdapter::reset() -{ - m_pos = m_begin; -} - - -size_t inputStreamStringAdapter::read - (byte_t* const data, const size_t count) -{ - if (m_pos + count >= m_end) - { - const size_t remaining = m_end - m_pos; - - std::copy(m_buffer.begin() + m_pos, m_buffer.end(), data); - m_pos = m_end; - return (remaining); - } - else - { - std::copy(m_buffer.begin() + m_pos, m_buffer.begin() + m_pos + count, data); - m_pos += count; - return (count); - } -} - - -size_t inputStreamStringAdapter::skip(const size_t count) -{ - if (m_pos + count >= m_end) - { - const size_t remaining = m_end - m_pos; - m_pos = m_end; - return (remaining); - } - else - { - m_pos += count; - return (count); - } -} - - -size_t inputStreamStringAdapter::getPosition() const -{ - return m_pos - m_begin; -} - - -void inputStreamStringAdapter::seek(const size_t pos) -{ - if (m_begin + pos <= m_end) - m_pos = m_begin + pos; -} - - -} // utility -} // vmime - diff --git a/src/utility/inputStreamStringProxyAdapter.cpp b/src/utility/inputStreamStringProxyAdapter.cpp deleted file mode 100644 index 5513de80..00000000 --- a/src/utility/inputStreamStringProxyAdapter.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/inputStreamStringProxyAdapter.hpp" -#include "vmime/utility/stringProxy.hpp" - - -namespace vmime { -namespace utility { - - -inputStreamStringProxyAdapter::inputStreamStringProxyAdapter(const stringProxy& buffer) - : m_buffer(buffer), m_pos(0) -{ -} - - -bool inputStreamStringProxyAdapter::eof() const -{ - return (m_pos >= m_buffer.length()); -} - - -void inputStreamStringProxyAdapter::reset() -{ - m_pos = 0; -} - - -size_t inputStreamStringProxyAdapter::read - (byte_t* const data, const size_t count) -{ - const size_t remaining = m_buffer.length() - m_pos; - - if (count > remaining) - { - std::copy(m_buffer.it_begin() + m_pos, m_buffer.it_end(), data); - m_pos = m_buffer.length(); - return (remaining); - } - else - { - std::copy(m_buffer.it_begin() + m_pos, m_buffer.it_begin() + m_pos + count, data); - m_pos += count; - return (count); - } -} - - -size_t inputStreamStringProxyAdapter::skip(const size_t count) -{ - const size_t remaining = m_buffer.length() - m_pos; - - if (count > remaining) - { - m_pos = m_buffer.length(); - return (remaining); - } - else - { - m_pos += count; - return (count); - } -} - - -size_t inputStreamStringProxyAdapter::getPosition() const -{ - return m_pos; -} - - -void inputStreamStringProxyAdapter::seek(const size_t pos) -{ - if (pos <= m_buffer.length()) - m_pos = pos; -} - - -} // utility -} // vmime - diff --git a/src/utility/outputStream.cpp b/src/utility/outputStream.cpp deleted file mode 100644 index 070e28c5..00000000 --- a/src/utility/outputStream.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/outputStream.hpp" - - -namespace vmime { -namespace utility { - - -void outputStream::write(const byte_t* const data, const size_t count) -{ - writeImpl(data, count); -} - - -void outputStream::write(const char* const data, const size_t count) -{ - writeImpl(reinterpret_cast (data), count); -} - - -} // utility -} // vmime - diff --git a/src/utility/outputStreamAdapter.cpp b/src/utility/outputStreamAdapter.cpp deleted file mode 100644 index ed90c7d3..00000000 --- a/src/utility/outputStreamAdapter.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/outputStreamAdapter.hpp" - - -namespace vmime { -namespace utility { - - -outputStreamAdapter::outputStreamAdapter(std::ostream& os) - : m_stream(os) -{ -} - - -void outputStreamAdapter::writeImpl - (const byte_t* const data, const size_t count) -{ - m_stream.exceptions(std::ios_base::badbit); - m_stream.write(reinterpret_cast (data), count); -} - - -void outputStreamAdapter::flush() -{ - m_stream.exceptions(std::ios_base::badbit); - m_stream.flush(); -} - - -} // utility -} // vmime - diff --git a/src/utility/outputStreamByteArrayAdapter.cpp b/src/utility/outputStreamByteArrayAdapter.cpp deleted file mode 100644 index 1bed735b..00000000 --- a/src/utility/outputStreamByteArrayAdapter.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/outputStreamByteArrayAdapter.hpp" - - -namespace vmime { -namespace utility { - - -outputStreamByteArrayAdapter::outputStreamByteArrayAdapter(byteArray& array) - : m_array(array) -{ -} - - -void outputStreamByteArrayAdapter::writeImpl - (const byte_t* const data, const size_t count) -{ - m_array.insert(m_array.end(), data, data + count); -} - - -void outputStreamByteArrayAdapter::flush() -{ - // Do nothing -} - - -} // utility -} // vmime - diff --git a/src/utility/outputStreamSocketAdapter.cpp b/src/utility/outputStreamSocketAdapter.cpp deleted file mode 100644 index 03194497..00000000 --- a/src/utility/outputStreamSocketAdapter.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/outputStreamSocketAdapter.hpp" - - -#if VMIME_HAVE_MESSAGING_FEATURES - - -#include "vmime/net/socket.hpp" - - -namespace vmime { -namespace utility { - - -outputStreamSocketAdapter::outputStreamSocketAdapter(net::socket& sok) - : m_socket(sok) -{ -} - - -void outputStreamSocketAdapter::writeImpl - (const byte_t* const data, const size_t count) -{ - m_socket.sendRaw(data, count); -} - - -void outputStreamSocketAdapter::flush() -{ - // Do nothing -} - - -size_t outputStreamSocketAdapter::getBlockSize() -{ - return m_socket.getBlockSize(); -} - - - -} // utility -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/utility/outputStreamStringAdapter.cpp b/src/utility/outputStreamStringAdapter.cpp deleted file mode 100644 index 7105480c..00000000 --- a/src/utility/outputStreamStringAdapter.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/outputStreamStringAdapter.hpp" - -#include "vmime/utility/stringUtils.hpp" - - -namespace vmime { -namespace utility { - - -outputStreamStringAdapter::outputStreamStringAdapter(string& buffer) - : m_buffer(buffer) -{ -} - - -void outputStreamStringAdapter::writeImpl - (const byte_t* const data, const size_t count) -{ - vmime::utility::stringUtils::appendBytesToString(m_buffer, data, count); -} - - -void outputStreamStringAdapter::flush() -{ - // Do nothing -} - - -} // utility -} // vmime - diff --git a/src/utility/parserInputStreamAdapter.cpp b/src/utility/parserInputStreamAdapter.cpp deleted file mode 100644 index 5ab26ef0..00000000 --- a/src/utility/parserInputStreamAdapter.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/parserInputStreamAdapter.hpp" - - -namespace vmime { -namespace utility { - - -parserInputStreamAdapter::parserInputStreamAdapter(shared_ptr stream) - : m_stream(stream) -{ -} - - -bool parserInputStreamAdapter::eof() const -{ - return m_stream->eof(); -} - - -void parserInputStreamAdapter::reset() -{ - m_stream->reset(); -} - - -size_t parserInputStreamAdapter::read - (byte_t* const data, const size_t count) -{ - return m_stream->read(data, count); -} - - -shared_ptr parserInputStreamAdapter::getUnderlyingStream() -{ - return m_stream; -} - - -const string parserInputStreamAdapter::extract(const size_t begin, const size_t end) const -{ - const size_t initialPos = m_stream->getPosition(); - - byte_t *buffer = NULL; - - try - { - buffer = new byte_t[end - begin + 1]; - - m_stream->seek(begin); - - const size_t readBytes = m_stream->read(buffer, end - begin); - buffer[readBytes] = '\0'; - - m_stream->seek(initialPos); - - string str(buffer, buffer + readBytes); - delete [] buffer; - - return str; - } - catch (...) - { - delete [] buffer; - - m_stream->seek(initialPos); - throw; - } -} - - -size_t parserInputStreamAdapter::findNext - (const string& token, const size_t startPosition) -{ - static const unsigned int BUFFER_SIZE = 4096; - - // Token must not be longer than BUFFER_SIZE/2 - if (token.empty() || token.length() > BUFFER_SIZE / 2) - return npos; - - const size_t initialPos = getPosition(); - - seek(startPosition); - - try - { - byte_t findBuffer[BUFFER_SIZE]; - byte_t* findBuffer1 = findBuffer; - byte_t* findBuffer2 = findBuffer + (BUFFER_SIZE / 2); - - size_t findBufferLen = 0; - size_t findBufferOffset = 0; - - bool isEOF = false; - - // Fill in initial buffer - findBufferLen = read(findBuffer, BUFFER_SIZE); - - while (findBufferLen != 0) - { - // Find token - for (byte_t *begin = findBuffer, *end = findBuffer + findBufferLen - token.length() ; - begin <= end ; ++begin) - { - if (begin[0] == token[0] && - (token.length() == 1 || - memcmp(static_cast (&begin[1]), - static_cast (token.data() + 1), - token.length() - 1) == 0)) - { - seek(initialPos); - return startPosition + findBufferOffset + (begin - findBuffer); - } - } - - // Rotate buffer - memcpy(findBuffer1, findBuffer2, (BUFFER_SIZE / 2)); - - // Read more bytes - if (findBufferLen < BUFFER_SIZE && (eof() || isEOF)) - { - break; - } - else - { - const size_t bytesRead = read(findBuffer2, BUFFER_SIZE / 2); - - if (bytesRead == 0) - { - isEOF = true; - } - else - { - findBufferLen = (BUFFER_SIZE / 2) + bytesRead; - findBufferOffset += (BUFFER_SIZE / 2); - } - } - } - - seek(initialPos); - } - catch (...) - { - seek(initialPos); - throw; - } - - return npos; -} - - -} // utility -} // vmime - diff --git a/src/utility/path.cpp b/src/utility/path.cpp deleted file mode 100644 index 9f746d54..00000000 --- a/src/utility/path.cpp +++ /dev/null @@ -1,266 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/path.hpp" - -#include - - -namespace vmime { -namespace utility { - - -path::path() -{ -} - - -path::path(const component& c) -{ - m_list.push_back(c); -} - - -path::path(const path& p) - : object() -{ - m_list.resize(p.m_list.size()); - std::copy(p.m_list.begin(), p.m_list.end(), m_list.begin()); -} - - -path::path(const string& s) -{ - m_list.push_back(component(s)); -} - - -path path::operator/(const path& p) const -{ - path pr(*this); - pr /= p; - - return (pr); -} - - -path path::operator/(const component& c) const -{ - path pr(*this); - pr /= c; - - return (pr); -} - - -path& path::operator/=(const path& p) -{ - const list::size_type size = m_list.size(); - - m_list.resize(size + p.m_list.size()); - std::copy(p.m_list.begin(), p.m_list.end(), m_list.begin() + size); - - return (*this); -} - - -path& path::operator/=(const component& c) -{ - m_list.push_back(c); - return (*this); -} - - -path path::getParent() const -{ - path p; - - if (!isEmpty()) - { - p.m_list.resize(m_list.size() - 1); - std::copy(m_list.begin(), m_list.end() - 1, p.m_list.begin()); - } - - return (p); -} - - -path& path::operator=(const path& p) -{ - m_list.resize(p.m_list.size()); - std::copy(p.m_list.begin(), p.m_list.end(), m_list.begin()); - - return (*this); -} - - -path& path::operator=(const component& c) -{ - m_list.resize(1); - m_list[0] = c; - - return (*this); -} - - -bool path::operator==(const path& p) const -{ - if (m_list.size() != p.m_list.size()) - return (false); - - list::const_iterator i = m_list.begin(); - list::const_iterator j = p.m_list.begin(); - - bool equal = true; - - for ( ; equal && i != m_list.end() ; ++i, ++j) - //equal = (*i == *j); - equal = ((*i).getBuffer() == (*j).getBuffer()); - - return (equal); -} - - -bool path::operator!=(const path& p) const -{ - return (!(*this == p)); -} - - -bool path::isEmpty() const -{ - return (m_list.empty()); -} - - -bool path::isRoot() const -{ - return (m_list.empty()); -} - - -const path::component path::getLastComponent() const -{ - return (m_list[m_list.size() - 1]); -} - - -path::component& path::getLastComponent() -{ - return (m_list[m_list.size() - 1]); -} - - -size_t path::getSize() const -{ - return (m_list.size()); -} - - -const path::component& path::operator[](const size_t x) const -{ - return (m_list[x]); -} - - -path::component& path::operator[](const size_t x) -{ - return (m_list[x]); -} - - -bool path::isDirectParentOf(const path& p) const -{ - if (p.getSize() != getSize() + 1) - return (false); - - bool equal = true; - - for (list::size_type i = 0 ; equal && i < m_list.size() ; ++i) - equal = (m_list[i] == p.m_list[i]); - - return (equal); -} - - -bool path::isParentOf(const path& p) const -{ - if (p.getSize() < getSize() + 1) - return (false); - - bool equal = true; - - for (list::size_type i = 0 ; equal && i < m_list.size() ; ++i) - equal = (m_list[i] == p.m_list[i]); - - return (equal); -} - - -void path::renameParent(const path& oldPath, const path& newPath) -{ - if (isEmpty() || oldPath.getSize() > getSize()) - return; - - bool equal = true; - list::size_type i; - - for (i = 0 ; equal && i < oldPath.m_list.size() ; ++i) - equal = (m_list[i] == oldPath.m_list[i]); - - if (i != oldPath.m_list.size()) - return; - - list newList; - - for (list::size_type j = 0 ; j < newPath.m_list.size() ; ++j) - newList.push_back(newPath.m_list[j]); - - for (list::size_type j = i ; j < m_list.size() ; ++j) - newList.push_back(m_list[j]); - - m_list.resize(newList.size()); - std::copy(newList.begin(), newList.end(), m_list.begin()); -} - - -void path::appendComponent(const path::component& c) -{ - m_list.push_back(c); -} - - -const path::component& path::getComponentAt(const size_t pos) const -{ - return (m_list[pos]); -} - - -path::component& path::getComponentAt(const size_t pos) -{ - return (m_list[pos]); -} - - -} // utility -} // vmime diff --git a/src/utility/progressListener.cpp b/src/utility/progressListener.cpp deleted file mode 100644 index cef074e5..00000000 --- a/src/utility/progressListener.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/progressListener.hpp" - - -namespace vmime { -namespace utility { - - -// progressListenerSizeAdapter - -progressListenerSizeAdapter::progressListenerSizeAdapter - (progressListener* list, const size_t total) - : m_wrapped(list), m_total(total) -{ -} - - -bool progressListenerSizeAdapter::cancel() const -{ - return (m_wrapped ? m_wrapped->cancel() : false); -} - - -void progressListenerSizeAdapter::start(const size_t predictedTotal) -{ - if (m_wrapped) - m_wrapped->start(predictedTotal); -} - - -void progressListenerSizeAdapter::progress(const size_t current, const size_t currentTotal) -{ - if (m_wrapped) - { - if (currentTotal > m_total) - m_total = currentTotal; - - m_wrapped->progress(current, m_total); - } -} - - -void progressListenerSizeAdapter::stop(const size_t total) -{ - if (m_wrapped) - { - if (total > m_total) - m_total = total; - - m_wrapped->stop(m_total); - } -} - - -} // utility -} // vmime - diff --git a/src/utility/random.cpp b/src/utility/random.cpp deleted file mode 100644 index 97d12ddc..00000000 --- a/src/utility/random.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/random.hpp" -#include "vmime/platform.hpp" - -#include - - -namespace vmime { -namespace utility { - - -static unsigned int getRandomSeed() -{ - unsigned int seed; - - platform::getHandler()->generateRandomBytes - (reinterpret_cast (&seed), sizeof(seed)); - - return seed; -} - - -unsigned int random::getNext() -{ - static unsigned int next = getRandomSeed(); - - // Park and Miller's minimal standard generator: - // xn+1 = (a * xn + b) mod c - // xn+1 = (16807 * xn) mod (2^31 - 1) - next = static_cast((16807 * next) % 2147483647ul); - return next; -} - - -unsigned int random::getTime() -{ - return static_cast ((platform::getHandler()->getUnixTime())); -} - - -unsigned int random::getProcess() -{ - return (platform::getHandler()->getProcessId()); -} - - -const string random::getString(const size_t length, const string& randomChars) -{ - string res; - res.resize(length); - - const unsigned int x = static_cast (randomChars.length()); - size_t c = 0; - - while (c < length) - { - for (unsigned int n = random::getNext() ; n != 0 && c < length ; n /= x) - { - res[c++] = randomChars[n % x]; - } - } - - return (res); -} - - -} // utility -} // vmime diff --git a/src/utility/seekableInputStreamRegionAdapter.cpp b/src/utility/seekableInputStreamRegionAdapter.cpp deleted file mode 100644 index cede1ba9..00000000 --- a/src/utility/seekableInputStreamRegionAdapter.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/seekableInputStreamRegionAdapter.hpp" - - -namespace vmime { -namespace utility { - - -seekableInputStreamRegionAdapter::seekableInputStreamRegionAdapter - (shared_ptr stream, const size_t begin, const size_t length) - : m_stream(stream), m_begin(begin), m_length(length), m_position(0) -{ -} - - -bool seekableInputStreamRegionAdapter::eof() const -{ - return m_position >= m_length; -} - - -void seekableInputStreamRegionAdapter::reset() -{ - m_position = 0; -} - - -size_t seekableInputStreamRegionAdapter::read - (byte_t* const data, const size_t count) -{ - m_stream->seek(m_begin + m_position); - - size_t readBytes = 0; - - if (m_position + count >= m_length) - { - const size_t remaining = m_length - m_position; - readBytes = m_stream->read(data, remaining); - } - else - { - readBytes = m_stream->read(data, count); - } - - m_position += readBytes; - - return readBytes; -} - - -size_t seekableInputStreamRegionAdapter::skip(const size_t count) -{ - if (m_position + count >= m_length) - { - const size_t remaining = m_length - m_position; - m_position += remaining; - return remaining; - } - else - { - m_position += count; - return count; - } -} - - -size_t seekableInputStreamRegionAdapter::getPosition() const -{ - return m_position; -} - - -void seekableInputStreamRegionAdapter::seek(const size_t pos) -{ - if (pos > m_length) - m_position = m_length; - else - m_position = pos; -} - - -} // utility -} // vmime - diff --git a/src/utility/stream.cpp b/src/utility/stream.cpp deleted file mode 100644 index 232b23c7..00000000 --- a/src/utility/stream.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/stream.hpp" - - - -namespace vmime { -namespace utility { - - -size_t stream::getBlockSize() -{ - return 32768; // 32 KB -} - - -} // utility -} // vmime - diff --git a/src/utility/streamUtils.cpp b/src/utility/streamUtils.cpp deleted file mode 100644 index f3cc69ef..00000000 --- a/src/utility/streamUtils.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/streamUtils.hpp" - -#include // for std::copy -#include // for std::back_inserter - - - -namespace vmime { -namespace utility { - - -outputStream& operator<<(outputStream& os, const byte_t c) -{ - os.write(&c, 1); - return (os); -} - - -outputStream& operator<<(outputStream& os, const string& str) -{ - os.write(str.data(), str.length()); - return (os); -} - - -size_t bufferedStreamCopy(inputStream& is, outputStream& os) -{ - return bufferedStreamCopy(is, os, 0, NULL); -} - - -size_t bufferedStreamCopyRange(inputStream& is, outputStream& os, - const size_t start, const size_t length) -{ - const size_t blockSize = - std::min(is.getBlockSize(), os.getBlockSize()); - - is.skip(start); - - std::vector vbuffer(blockSize); - - byte_t* buffer = &vbuffer.front(); - size_t total = 0; - - while (!is.eof() && total < length) - { - const size_t remaining = std::min(length - total, blockSize); - const size_t read = is.read(buffer, remaining); - - if (read != 0) - { - os.write(buffer, read); - total += read; - } - } - - return total; -} - - -size_t bufferedStreamCopy(inputStream& is, outputStream& os, - const size_t length, progressListener* progress) -{ - const size_t blockSize = - std::min(is.getBlockSize(), os.getBlockSize()); - - std::vector vbuffer(blockSize); - - byte_t* buffer = &vbuffer.front(); - size_t total = 0; - - if (progress != NULL) - progress->start(length); - - while (!is.eof()) - { - const size_t read = is.read(buffer, blockSize); - - if (read != 0) - { - os.write(buffer, read); - total += read; - - if (progress != NULL) - progress->progress(total, std::max(total, length)); - } - } - - if (progress != NULL) - progress->stop(total); - - return (total); -} - - -} // utility -} // vmime - diff --git a/src/utility/stringProxy.cpp b/src/utility/stringProxy.cpp deleted file mode 100644 index 67c96816..00000000 --- a/src/utility/stringProxy.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/stringProxy.hpp" - -#include "vmime/utility/outputStreamAdapter.hpp" - -#include -#include - - -namespace vmime { -namespace utility { - - -stringProxy::stringProxy() - : m_start(0), m_end(0) -{ -} - - -stringProxy::stringProxy(const stringProxy& s) - : m_buffer(s.m_buffer), m_start(s.m_start), m_end(s.m_end) -{ -} - - -stringProxy::stringProxy(const string& s, const size_t start, const size_t end) - : m_buffer(s), m_start(start), - m_end(end == std::numeric_limits ::max() ? s.length() : end) -{ -} - - -void stringProxy::set(const string& s, const size_t start, const size_t end) -{ - m_buffer = s; - m_start = start; - - if (end == std::numeric_limits ::max()) - m_end = s.length(); - else - m_end = end; -} - - -void stringProxy::detach() -{ - m_buffer.clear(); - m_start = m_end = 0; -} - - -stringProxy& stringProxy::operator=(const stringProxy& s) -{ - m_buffer = s.m_buffer; - m_start = s.m_start; - m_end = s.m_end; - - return (*this); -} - - -stringProxy& stringProxy::operator=(const string& s) -{ - m_buffer = s; - m_start = 0; - m_end = s.length(); - - return (*this); -} - - -void stringProxy::extract(outputStream& os, const size_t start, const size_t end, - utility::progressListener* progress) const -{ - size_t len = 0; - - if (end == std::numeric_limits ::max()) - len = m_end - start - m_start; - else if (end > start) - len = end - start; - - if (progress) - progress->start(len); - - os.write(m_buffer.data() + m_start + start, len); - - if (progress) - { - progress->progress(len, len); - progress->stop(len); - } -} - - -size_t stringProxy::length() const -{ - return (m_end - m_start); -} - - -size_t stringProxy::start() const -{ - return (m_start); -} - - -size_t stringProxy::end() const -{ - return (m_end); -} - - -std::ostream& operator<<(std::ostream& os, const stringProxy& s) -{ - outputStreamAdapter adapter(os); - s.extract(adapter); - return (os); -} - - -outputStream& operator<<(outputStream& os, const stringProxy& s) -{ - s.extract(os); - return (os); -} - - -} // utility -} // vmime diff --git a/src/utility/stringUtils.cpp b/src/utility/stringUtils.cpp deleted file mode 100644 index dd99d845..00000000 --- a/src/utility/stringUtils.cpp +++ /dev/null @@ -1,242 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/stringUtils.hpp" -#include "vmime/parserHelpers.hpp" - - -namespace vmime { -namespace utility { - - -bool stringUtils::isStringEqualNoCase - (const string& s1, const char* s2, const size_t n) -{ - // 'n' is the number of characters to compare - // 's2' must be in lowercase letters only - if (s1.length() < n) - return (false); - - const std::ctype & fac = - std::use_facet >(std::locale::classic()); - - bool equal = true; - - for (size_t i = 0 ; equal && i < n ; ++i) - equal = (fac.tolower(static_cast (s1[i])) == s2[i]); - - return (equal); -} - - -bool stringUtils::isStringEqualNoCase(const string& s1, const string& s2) -{ - if (s1.length() != s2.length()) - return (false); - - const std::ctype & fac = - std::use_facet >(std::locale::classic()); - - bool equal = true; - const string::const_iterator end = s1.end(); - - for (string::const_iterator i = s1.begin(), j = s2.begin(); i != end ; ++i, ++j) - equal = (fac.tolower(static_cast (*i)) == fac.tolower(static_cast (*j))); - - return (equal); -} - - -bool stringUtils::isStringEqualNoCase - (const string::const_iterator begin, const string::const_iterator end, - const char* s, const size_t n) -{ - if (static_cast (end - begin) < n) - return (false); - - const std::ctype & fac = - std::use_facet >(std::locale::classic()); - - bool equal = true; - char* c = const_cast(s); - size_t r = n; - - for (string::const_iterator i = begin ; equal && r && *c ; ++i, ++c, --r) - equal = (fac.tolower(static_cast (*i)) == static_cast (*c)); - - return (r == 0 && equal); -} - - -const string stringUtils::toLower(const string& str) -{ - const std::ctype & fac = - std::use_facet >(std::locale::classic()); - - string out; - out.resize(str.size()); - - for (size_t i = 0, len = str.length() ; i < len ; ++i) - out[i] = fac.tolower(static_cast (str[i])); - - return out; -} - - -const string stringUtils::toUpper(const string& str) -{ - const std::ctype & fac = - std::use_facet >(std::locale::classic()); - - string out; - out.resize(str.size()); - - for (size_t i = 0, len = str.length() ; i < len ; ++i) - out[i] = fac.toupper(static_cast (str[i])); - - return out; -} - - -const string stringUtils::trim(const string& str) -{ - string::const_iterator b = str.begin(); - string::const_iterator e = str.end(); - - if (b != e) - { - for ( ; b != e && parserHelpers::isSpace(*b) ; ++b) {} - for ( ; e != b && parserHelpers::isSpace(*(e - 1)) ; --e) {} - } - - return (string(b, e)); -} - - -size_t stringUtils::countASCIIchars - (const string::const_iterator begin, const string::const_iterator end) -{ - size_t count = 0; - - for (string::const_iterator i = begin ; i != end ; ++i) - { - if (parserHelpers::isAscii(*i)) - { - if (*i != '=' || ((i + 1) != end && *(i + 1) != '?')) // To avoid bad behaviour... - ++count; - } - } - - return (count); -} - - -bool stringUtils::is7bit(const string& str) -{ - return countASCIIchars(str.begin(), str.end()) == str.length(); -} - - -size_t stringUtils::findFirstNonASCIIchar - (const string::const_iterator begin, const string::const_iterator end) -{ - size_t pos = string::npos; - - for (string::const_iterator i = begin ; i != end ; ++i) - { - if (!parserHelpers::isAscii(*i)) - { - pos = i - begin; - break; - } - } - - return pos; -} - - -const string stringUtils::unquote(const string& str) -{ - if (str.length() < 2) - return str; - - if (str[0] != '"' || str[str.length() - 1] != '"') - return str; - - string res; - res.reserve(str.length()); - - bool escaped = false; - - for (string::const_iterator it = str.begin() + 1, end = str.end() - 1 ; it != end ; ++it) - { - const char c = *it; - - if (escaped) - { - res += c; - escaped = false; - } - else if (!escaped && c == '\\') - { - escaped = true; - } - else - { - res += c; - } - } - - return res; -} - - -bool stringUtils::needQuoting(const string& str, const string& specialChars) -{ - return str.find_first_of(specialChars.c_str()) != string::npos; -} - - -string stringUtils::quote - (const string& str, const string& escapeSpecialChars, const string& escapeChar) -{ - std::ostringstream oss; - size_t lastPos = 0, pos = 0; - - while ((pos = str.find_first_of(escapeSpecialChars, lastPos)) != string::npos) - { - oss << str.substr(lastPos, pos - lastPos) - << escapeChar - << str[pos]; - - lastPos = pos + 1; - } - - oss << str.substr(lastPos); - - return oss.str(); -} - - -} // utility -} // vmime diff --git a/src/utility/sync/criticalSection.cpp b/src/utility/sync/criticalSection.cpp deleted file mode 100644 index f2512d14..00000000 --- a/src/utility/sync/criticalSection.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/sync/criticalSection.hpp" - - -namespace vmime { -namespace utility { -namespace sync { - - -criticalSection::criticalSection() -{ -} - - -criticalSection::~criticalSection() -{ -} - - -} // sync -} // utility -} // vmime diff --git a/src/utility/url.cpp b/src/utility/url.cpp deleted file mode 100644 index ce0dc39a..00000000 --- a/src/utility/url.cpp +++ /dev/null @@ -1,406 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/url.hpp" - -#include "vmime/parserHelpers.hpp" -#include "vmime/utility/urlUtils.hpp" -#include "vmime/exception.hpp" - -#include - - -namespace vmime { -namespace utility { - - -// Unspecified port -const port_t url::UNSPECIFIED_PORT = static_cast (-1); - -// Known protocols -const string url::PROTOCOL_FILE = "file"; -const string url::PROTOCOL_HTTP = "http"; -const string url::PROTOCOL_FTP = "ftp"; - - - -url::url(const string& s) -{ - parse(s); -} - - -url::url(const url& u) -{ - operator=(u); -} - - -url::url(const string& protocol, const string& host, const port_t port, - const string& path, const string& username, const string& password) - : m_protocol(protocol), m_username(username), m_password(password), - m_host(host), m_port(port), m_path(path) -{ -} - - -url& url::operator=(const url& u) -{ - m_protocol = u.m_protocol; - - m_username = u.m_username; - m_password = u.m_password; - - m_host = u.m_host; - m_port = u.m_port; - - m_path = u.m_path; - - m_params = u.m_params; - - return (*this); -} - - -url& url::operator=(const string& s) -{ - parse(s); - - return (*this); -} - - -url::operator string() const -{ - return build(); -} - - -const string url::build() const -{ - std::ostringstream oss; - oss.imbue(std::locale::classic()); - - oss << m_protocol << "://"; - - if (!m_username.empty()) - { - oss << urlUtils::encode(m_username); - - if (!m_password.empty()) - { - oss << ":"; - oss << urlUtils::encode(m_password); - } - - oss << "@"; - } - - oss << urlUtils::encode(m_host); - - if (m_port != UNSPECIFIED_PORT) - { - oss << ":"; - oss << m_port; - } - - if (!m_path.empty()) - { - oss << "/"; - oss << urlUtils::encode(m_path); - } - - - if (!m_params.empty()) - { - if (m_path.empty()) - oss << "/"; - - oss << "?"; - - for (std::map ::const_iterator it = m_params.begin() ; - it != m_params.end() ; ++it) - { - if (it != m_params.begin()) - oss << "&"; - - oss << urlUtils::encode((*it).first); - oss << "="; - oss << urlUtils::encode((*it).second); - } - } - - return (oss.str()); -} - - -void url::parse(const string& str) -{ - // Protocol - const size_t protoEnd = str.find("://"); - if (protoEnd == string::npos) throw exceptions::malformed_url("No protocol separator"); - - const string proto = - utility::stringUtils::toLower(string(str.begin(), str.begin() + protoEnd)); - - // Username/password - size_t slashPos = str.find('/', protoEnd + 3); - if (slashPos == string::npos) slashPos = str.length(); - - size_t atPos = str.rfind('@', slashPos); - string hostPart; - - string username; - string password; - - if (proto == PROTOCOL_FILE) - { - // No user name, password and host part. - slashPos = protoEnd + 3; - } - else - { - if (atPos != string::npos && atPos < slashPos) - { - const string userPart(str.begin() + protoEnd + 3, str.begin() + atPos); - const size_t colonPos = userPart.find(':'); - - if (colonPos == string::npos) - { - username = userPart; - } - else - { - username = string(userPart.begin(), userPart.begin() + colonPos); - password = string(userPart.begin() + colonPos + 1, userPart.end()); - } - - hostPart = string(str.begin() + atPos + 1, str.begin() + slashPos); - } - else - { - hostPart = string(str.begin() + protoEnd + 3, str.begin() + slashPos); - } - } - - // Host/port - const size_t colonPos = hostPart.find(':'); - - string host; - string port; - - if (colonPos == string::npos) - { - host = utility::stringUtils::trim(hostPart); - } - else - { - host = utility::stringUtils::trim(string(hostPart.begin(), hostPart.begin() + colonPos)); - port = utility::stringUtils::trim(string(hostPart.begin() + colonPos + 1, hostPart.end())); - } - - // Path - string path = utility::stringUtils::trim(string(str.begin() + slashPos, str.end())); - string params; - - size_t paramSep = path.find_first_of('?'); - - if (paramSep != string::npos) - { - params = string(path.begin() + paramSep + 1, path.end()); - path.erase(path.begin() + paramSep, path.end()); - } - - if (path == "/") - path.clear(); - - // Some sanity check - if (proto.empty()) - throw exceptions::malformed_url("No protocol specified"); - else if (host.empty()) - { - // Accept empty host (eg. "file:///home/vincent/mydoc") - if (proto != PROTOCOL_FILE) - throw exceptions::malformed_url("No host specified"); - } - - bool onlyDigit = true; - - for (string::const_iterator it = port.begin() ; - onlyDigit && it != port.end() ; ++it) - { - onlyDigit = parserHelpers::isDigit(*it); - } - - if (!onlyDigit) - throw exceptions::malformed_url("Port can only contain digits"); - - std::istringstream iss(port); - port_t portNum = 0; - - iss >> portNum; - - if (portNum == 0) - portNum = UNSPECIFIED_PORT; - - // Extract parameters - m_params.clear(); - - if (!params.empty()) - { - size_t pos = 0; - - do - { - const size_t start = pos; - - pos = params.find_first_of('&', pos); - - const size_t equal = params.find_first_of('=', start); - const size_t end = - (pos == string::npos ? params.length() : pos); - - string name; - string value; - - if (equal == string::npos || equal > pos) // no value - { - name = string(params.begin() + start, params.begin() + end); - value = name; - } - else - { - name = string(params.begin() + start, params.begin() + equal); - value = string(params.begin() + equal + 1, params.begin() + end); - } - - name = urlUtils::decode(name); - value = urlUtils::decode(value); - - m_params[name] = value; - - if (pos != string::npos) - ++pos; - } - while (pos != string::npos); - } - - // Now, save URL parts - m_protocol = proto; - - m_username = urlUtils::decode(username); - m_password = urlUtils::decode(password); - - m_host = urlUtils::decode(host); - m_port = portNum; - - m_path = urlUtils::decode(path); -} - - -const string& url::getProtocol() const -{ - return (m_protocol); -} - - -void url::setProtocol(const string& protocol) -{ - m_protocol = protocol; -} - - -const string& url::getUsername() const -{ - return (m_username); -} - - -void url::setUsername(const string& username) -{ - m_username = username; -} - - -const string& url::getPassword() const -{ - return (m_password); -} - - -void url::setPassword(const string& password) -{ - m_password = password; -} - - -const string& url::getHost() const -{ - return (m_host); -} - - -void url::setHost(const string& host) -{ - m_host = host; -} - - -port_t url::getPort() const -{ - return (m_port); -} - - -void url::setPort(const port_t port) -{ - m_port = port; -} - - -const string& url::getPath() const -{ - return (m_path); -} - - -void url::setPath(const string& path) -{ - m_path = path; -} - - -const std::map & url::getParams() const -{ - return (m_params); -} - - -std::map & url::getParams() -{ - return (m_params); -} - - -} // utility -} // vmime diff --git a/src/utility/urlUtils.cpp b/src/utility/urlUtils.cpp deleted file mode 100644 index 20818764..00000000 --- a/src/utility/urlUtils.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/urlUtils.hpp" -#include "vmime/parserHelpers.hpp" - - -namespace vmime { -namespace utility { - - -const string urlUtils::encode(const string& s) -{ - static const string RESERVED_CHARS = - /* reserved */ "$&+,/:;=?@" - /* unsafe */ "<>#%{}[]|\\^\"~`"; - - string result; - result.reserve(s.length()); - - for (string::const_iterator it = s.begin() ; it != s.end() ; ++it) - { - const char c = *it; - - if (parserHelpers::isPrint(c) && !parserHelpers::isSpace(c) && - static_cast (c) <= 127 && - RESERVED_CHARS.find(c) == string::npos) - { - result += c; - } - else - { - char hex[4]; - const unsigned char k = static_cast (c); - - hex[0] = '%'; - hex[1] = "0123456789ABCDEF"[k / 16]; - hex[2] = "0123456789ABCDEF"[k % 16]; - hex[3] = 0; - - result += hex; - } - } - - return (result); -} - - -const string urlUtils::decode(const string& s) -{ - string result; - result.reserve(s.length()); - - for (string::const_iterator it = s.begin() ; it != s.end() ; ) - { - const char c = *it; - - switch (c) - { - case '%': - { - ++it; // skip '%' - - const char_t p = (it != s.end() ? *(it++) : 0); - const char_t q = (it != s.end() ? *(it++) : 0); - - unsigned int r = 0; - - switch (p) - { - case 0: r = '%'; break; - case 'a': case 'A': r = 10; break; - case 'b': case 'B': r = 11; break; - case 'c': case 'C': r = 12; break; - case 'd': case 'D': r = 13; break; - case 'e': case 'E': r = 14; break; - case 'f': case 'F': r = 15; break; - default: r = p - '0'; break; - } - - if (q != 0) - { - r *= 16; - - switch (q) - { - case 'a': case 'A': r += 10; break; - case 'b': case 'B': r += 11; break; - case 'c': case 'C': r += 12; break; - case 'd': case 'D': r += 13; break; - case 'e': case 'E': r += 14; break; - case 'f': case 'F': r += 15; break; - default: r += q - '0'; break; - } - } - - result += static_cast (r); - break; - } - default: - - result += c; - ++it; - break; - } - } - - return (result); -} - - -} // utility -} // vmime diff --git a/src/vmime/address.cpp b/src/vmime/address.cpp new file mode 100644 index 00000000..c6fa74f1 --- /dev/null +++ b/src/vmime/address.cpp @@ -0,0 +1,216 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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::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
parsedAddress; + + if (isGroup) + parsedAddress = make_shared (); + else + parsedAddress = make_shared (); + + parsedAddress->parse(ctx, buffer, start, pos, NULL); + parsedAddress->setParsedBounds(start, pos); + + return (parsedAddress); + } + + return null; +} + + +} // vmime diff --git a/src/vmime/address.hpp b/src/vmime/address.hpp new file mode 100644 index 00000000..5eb510f9 --- /dev/null +++ b/src/vmime/address.hpp @@ -0,0 +1,87 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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
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/src/vmime/addressList.cpp b/src/vmime/addressList.cpp new file mode 100644 index 00000000..5c7d34ac --- /dev/null +++ b/src/vmime/addressList.cpp @@ -0,0 +1,305 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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
parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, NULL); + + if (parsedAddress != NULL) + 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 >::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 (other); + + removeAllAddresses(); + + for (std::vector >::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
(other.getMailboxAt(i)->clone())); + + return (*this); +} + + +shared_ptr addressList::clone() const +{ + return make_shared (*this); +} + + +void addressList::appendAddress(shared_ptr
addr) +{ + m_list.push_back(addr); +} + + +void addressList::insertAddressBefore(shared_ptr
beforeAddress, shared_ptr
addr) +{ + const std::vector >::iterator it = std::find + (m_list.begin(), m_list.end(), beforeAddress); + + if (it == m_list.end()) + throw std::out_of_range("Invalid position"); + + m_list.insert(it, addr); +} + + +void addressList::insertAddressBefore(const size_t pos, shared_ptr
addr) +{ + if (pos >= m_list.size()) + throw std::out_of_range("Invalid position"); + + m_list.insert(m_list.begin() + pos, addr); +} + + +void addressList::insertAddressAfter(shared_ptr
afterAddress, shared_ptr
addr) +{ + const std::vector >::iterator it = std::find + (m_list.begin(), m_list.end(), afterAddress); + + if (it == m_list.end()) + throw std::out_of_range("Invalid position"); + + m_list.insert(it + 1, addr); +} + + +void addressList::insertAddressAfter(const size_t pos, shared_ptr
addr) +{ + if (pos >= m_list.size()) + throw std::out_of_range("Invalid position"); + + m_list.insert(m_list.begin() + pos + 1, addr); +} + + +void addressList::removeAddress(shared_ptr
addr) +{ + const std::vector >::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 >::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
addressList::getAddressAt(const size_t pos) +{ + return (m_list[pos]); +} + + +const shared_ptr addressList::getAddressAt(const size_t pos) const +{ + return (m_list[pos]); +} + + +const std::vector > addressList::getAddressList() const +{ + std::vector > list; + + list.reserve(m_list.size()); + + for (std::vector >::const_iterator it = m_list.begin() ; + it != m_list.end() ; ++it) + { + list.push_back(*it); + } + + return (list); +} + + +const std::vector > addressList::getAddressList() +{ + return (m_list); +} + + +const std::vector > addressList::getChildComponents() +{ + std::vector > list; + + copy_vector(m_list, list); + + return (list); +} + + +shared_ptr addressList::toMailboxList() const +{ + shared_ptr res = make_shared (); + + for (std::vector >::const_iterator it = m_list.begin() ; + it != m_list.end() ; ++it) + { + shared_ptr addr = *it; + + if (addr->isGroup()) + { + const std::vector > mailboxes = + dynamicCast (addr)->getMailboxList(); + + for (std::vector >::const_iterator jt = mailboxes.begin() ; + jt != mailboxes.end() ; ++jt) + { + res->appendMailbox(vmime::clone(*jt)); + } + } + else + { + res->appendMailbox(dynamicCast (addr->clone())); + } + } + + return res; +} + + +} // vmime diff --git a/src/vmime/addressList.hpp b/src/vmime/addressList.hpp new file mode 100644 index 00000000..0df657d3 --- /dev/null +++ b/src/vmime/addressList.hpp @@ -0,0 +1,192 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + void copyFrom(const component& other); + addressList& operator=(const addressList& other); + addressList& operator=(const mailboxList& other); + + const std::vector > getChildComponents(); + + + /** Add a address at the end of the list. + * + * @param addr address to append + */ + void appendAddress(shared_ptr
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(shared_ptr
beforeAddress, shared_ptr
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, shared_ptr
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(shared_ptr
afterAddress, shared_ptr
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, shared_ptr
addr); + + /** Remove the specified address from the list. + * + * @param addr address to remove + * @throw std::out_of_range if the address is not in the list + */ + void removeAddress(shared_ptr
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
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 getAddressAt(const size_t pos) const; + + /** Return the address list. + * + * @return list of addresses + */ + const std::vector > getAddressList() const; + + /** Return the address list. + * + * @return list of addresses + */ + const std::vector > 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 toMailboxList() const; + +private: + + std::vector > 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/src/vmime/attachment.hpp b/src/vmime/attachment.hpp new file mode 100644 index 00000000..9730bc6c --- /dev/null +++ b/src/vmime/attachment.hpp @@ -0,0 +1,118 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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 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 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(shared_ptr parent) const = 0; +}; + + +} // vmime + + +#endif // VMIME_ATTACHMENT_HPP_INCLUDED diff --git a/src/vmime/attachmentHelper.cpp b/src/vmime/attachmentHelper.cpp new file mode 100644 index 00000000..152daeed --- /dev/null +++ b/src/vmime/attachmentHelper.cpp @@ -0,0 +1,312 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime +{ + + +// static +bool attachmentHelper::isBodyPartAnAttachment + (shared_ptr part, const unsigned int options) +{ + // First, try with "Content-Disposition" field. + // If not present, we will try with "Content-Type" field. + shared_ptr cdf = + part->getHeader()->findField (fields::CONTENT_DISPOSITION); + + if (cdf) + { + const contentDisposition disp = *cdf->getValue (); + + 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() == NULL) + return false; + + return true; + } + + return false; + } + } + + // Assume "attachment" if type is not "text/..." or "multipart/...". + mediaType type; + bool hasContentTypeName = false; + + shared_ptr ctf = + part->getHeader()->findField (fields::CONTENT_TYPE); + + if (ctf) + { + type = *ctf->getValue (); + + 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() == NULL) + 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 attachmentHelper::getBodyPartAttachment + (shared_ptr part, const unsigned int options) +{ + if (!isBodyPartAnAttachment(part, options)) + return null; + + mediaType type; + + shared_ptr ctf = + part->getHeader()->findField (fields::CONTENT_TYPE); + + if (ctf) + { + type = *ctf->getValue (); + } + 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 (part); + } + else + { + return make_shared (part); + } +} + + +// static +const std::vector > + attachmentHelper::findAttachmentsInMessage + (shared_ptr msg, const unsigned int options) +{ + return findAttachmentsInBodyPart(msg, options); +} + + +// static +const std::vector > + attachmentHelper::findAttachmentsInBodyPart + (shared_ptr part, const unsigned int options) +{ + std::vector > atts; + + // Test this part + if (isBodyPartAnAttachment(part, options)) + { + atts.push_back(getBodyPartAttachment(part, options)); + } + // Find in sub-parts + else + { + shared_ptr bdy = part->getBody(); + + for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) + { + std::vector > partAtts = + findAttachmentsInBodyPart(bdy->getPartAt(i), options); + + std::copy(partAtts.begin(), partAtts.end(), std::back_inserter(atts)); + } + } + + return atts; +} + + +// static +void attachmentHelper::addAttachment(shared_ptr msg, shared_ptr 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 part = findBodyPart(msg, mpMixed); + + if (part == NULL) // 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 container = make_shared (); + + 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 > 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 child = make_shared (); + + 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 ()); + + 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 attachmentHelper::findBodyPart + (shared_ptr part, const mediaType& type) +{ + if (part->getBody()->getContentType() == type) + return part; + + // Try in sub-parts + shared_ptr bdy = part->getBody(); + + for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) + { + shared_ptr found = + findBodyPart(bdy->getPartAt(i), type); + + if (found != NULL) + return found; + } + + return null; +} + + +// static +void attachmentHelper::addAttachment(shared_ptr msg, shared_ptr amsg) +{ + shared_ptr att = make_shared (amsg); + addAttachment(msg, att); +} + + +} // vmime + diff --git a/src/vmime/attachmentHelper.hpp b/src/vmime/attachmentHelper.hpp new file mode 100644 index 00000000..e03a4f7d --- /dev/null +++ b/src/vmime/attachmentHelper.hpp @@ -0,0 +1,121 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr 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 + getBodyPartAttachment(shared_ptr 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 > + findAttachmentsInBodyPart(shared_ptr 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 > + findAttachmentsInMessage(shared_ptr msg, const unsigned int options = 0); + + /** Add an attachment to the specified message. + * + * @param msg message into which to add the attachment + * @param att attachment to add + */ + static void addAttachment(shared_ptr msg, shared_ptr att); + + /** Add a message attachment to the specified message. + * + * @param msg message into which to add the attachment + * @param amsg message to attach + */ + static void addAttachment(shared_ptr msg, shared_ptr amsg); + +protected: + + static shared_ptr findBodyPart + (shared_ptr part, const mediaType& type); +}; + + +} // vmime + + +#endif // VMIME_ATTACHMENTHELPER_HPP_INCLUDED + diff --git a/src/vmime/base.cpp b/src/vmime/base.cpp new file mode 100644 index 00000000..9f9a87be --- /dev/null +++ b/src/vmime/base.cpp @@ -0,0 +1,161 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 ::max(); +} + + +const size_t npos = std::numeric_limits ::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). +// + +class initializer +{ +public: + + 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/src/vmime/base.hpp b/src/vmime/base.hpp new file mode 100644 index 00000000..f6515794 --- /dev/null +++ b/src/vmime/base.hpp @@ -0,0 +1,258 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include +#include +#include +#include +#include + +#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 + operator shared_ptr () { return shared_ptr (); } + }; + + 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 + inline T const* cbegin(T const (&array)[N]) + { + return (array); + } + + template + inline T const* cend(T const (&array)[N]) + { + return (array + N); + } + + template + inline T* begin(T (&array)[N]) + { + return (array); + } + + template + inline T* end(T (&array)[N]) + { + return (array + N); + } + + template + inline size_t count(T const (&/* array */)[N]) + { + return (N); + } + + + // Copy one vector to another, with type conversion + + template + 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 (obj->clone()). + */ + template + shared_ptr clone(shared_ptr obj) + { + return dynamic_pointer_cast (obj->clone()); + } + + /** Clone helper (using a const shared_ptr). + * This is an alias for dynamic_pointer_cast (obj->clone()). + */ + template + shared_ptr clone(shared_ptr obj) + { + return dynamic_pointer_cast (obj->clone()); + } + + /** Clone helper (using a const reference). + * This is an alias for dynamic_pointer_cast (obj.clone()). + */ + template + shared_ptr clone(const T& obj) + { + return dynamic_pointer_cast (obj.clone()); + } + + /** Downcast helper. + * Usage: vmime::dynamicCast (obj), where 'obj' is of + * type Type, and DerivedType is derived from Type. + */ + template + shared_ptr dynamicCast(shared_ptr obj) + { + return dynamic_pointer_cast (obj); + } + + /** Const cast helper. + */ + template + shared_ptr constCast(const shared_ptr & obj) + { + return const_pointer_cast (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/src/vmime/body.cpp b/src/vmime/body.cpp new file mode 100644 index 00000000..8f5401cf --- /dev/null +++ b/src/vmime/body.cpp @@ -0,0 +1,1050 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 ()) +{ +} + + +body::~body() +{ +} + + +// static +size_t body::findNextBoundaryPosition + (shared_ptr parser, const string& boundary, + const size_t position, const size_t end, + size_t* boundaryStart, size_t* boundaryEnd) +{ + size_t pos = position; + + while (pos != npos && pos < end) + { + pos = parser->findNext(boundary, pos); + + if (pos == npos) + break; // not found + + if (pos != 0) + { + // Skip transport padding bytes (SPACE or HTAB), if any + size_t advance = 0; + + while (pos != 0) + { + parser->seek(pos - advance - 1); + + const byte_t c = parser->peekByte(); + + if (c == ' ' || c == '\t') + ++advance; + else + break; + } + + // Ensure the bytes before boundary are "[LF]--": boundary should be + // at the beginning of a line, and should start with "--" + if (pos - advance >= 3) + { + parser->seek(pos - advance - 3); + + if (parser->matchBytes("\n--", 3)) + { + parser->seek(pos + boundary.length()); + + const byte_t next = parser->peekByte(); + + // Boundary should be followed by a new line or a dash + if (next == '\r' || next == '\n' || next == '-') + { + // Get rid of the "[CR]" just before "[LF]--", if any + if (pos - advance >= 4) + { + parser->seek(pos - advance - 4); + + if (parser->peekByte() == '\r') + advance++; + } + + *boundaryStart = pos - advance - 3; + *boundaryEnd = pos + boundary.length(); + + return pos; + } + } + } + } + + // Boundary is a prefix of another, continue the search + pos++; + } + + return pos; +} + + +void body::parseImpl + (const parsingContext& /* ctx */, + shared_ptr 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 ctf = + m_part->getHeader()->findField (fields::CONTENT_TYPE); + + if (ctf) + { + const mediaType type = *ctf->getValue (); + + 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 #1521, Page 31: + // "...(If a boundary 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; + } + + if (index == 0) + { + if (partEnd > partStart) + { + vmime::text text; + text.parse(parser, partStart, partEnd); + + m_prologText = text.getWholeBuffer(); + } + else + { + m_prologText = ""; + } + } + else // index > 0 + { + shared_ptr 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(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 (); + + // Last part was not found: recover from missing boundary + if (!lastPart && pos == npos) + { + shared_ptr part = m_part->createChildPart(); + + try + { + part->parse(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(parser, partStart, end); + + m_epilogText = text.getWholeBuffer(); + } + } + // Treat the contents as 'simple' data + else + { + encoding enc; + + shared_ptr cef = + m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING); + + if (cef) + { + enc = *cef->getValue (); + } + else + { + // Defaults to "7bit" (RFC-1521) + enc = vmime::encoding(encodingTypes::SEVEN_BIT); + } + + // Extract the (encoded) contents + const size_t length = end - position; + + shared_ptr contentStream = + make_shared + (parser->getUnderlyingStream(), position, length); + + m_contents = make_shared (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 ctf = + m_part->getHeader()->findField (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 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 + { + shared_ptr srcEncoder = m_contents->getEncoding().getEncoder(); + shared_ptr 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 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 (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 (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 ctf = + dynamicCast (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 ctf = + m_part->getHeader()->findField (fields::CONTENT_TYPE); + + if (ctf) + { + return *ctf->getValue (); + } + else + { + // Defaults to "text/plain" (RFC-1521) + return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); + } +} + + +void body::setCharset(const charset& chset) +{ + shared_ptr ctf = + m_part->getHeader()->findField (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 ctf = + m_part->getHeader()->findField (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 cef = + m_part->getHeader()->findField(fields::CONTENT_TRANSFER_ENCODING); + + if (cef) + { + return *cef->getValue (); + } + 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 >::iterator it = m_parts.begin() ; + it != m_parts.end() ; ++it) + { + shared_ptr childPart = *it; + parent->importChildPart(childPart); + } +} + + +bool body::isRootPart() const +{ + return (m_part == NULL || m_part->getParentPart() == NULL); +} + + +shared_ptr body::clone() const +{ + shared_ptr bdy = make_shared (); + + bdy->copyFrom(*this); + + return (bdy); +} + + +void body::copyFrom(const component& other) +{ + const body& bdy = dynamic_cast (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 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 body::getContents() const +{ + return (m_contents); +} + + +void body::setContents(shared_ptr contents) +{ + m_contents = contents; +} + + +void body::setContents(shared_ptr contents, const mediaType& type) +{ + m_contents = contents; + + setContentType(type); +} + + +void body::setContents(shared_ptr contents, const mediaType& type, const charset& chset) +{ + m_contents = contents; + + setContentType(type, chset); +} + + +void body::setContents(shared_ptr contents, const mediaType& type, + const charset& chset, const encoding& enc) +{ + m_contents = contents; + + setContentType(type, chset); + setEncoding(enc); +} + + +void body::initNewPart(shared_ptr 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 != NULL) + { + m_part->importChildPart(part); + + shared_ptr
hdr = m_part->getHeader(); + + // Check whether we have a boundary string + shared_ptr ctf = + hdr->findField (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 ()->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 (fields::CONTENT_TYPE); + + ctf->setValue(mediaType(mediaTypes::MULTIPART, mediaTypes::MULTIPART_MIXED)); + ctf->setBoundary(generateRandomBoundaryString()); + } + } +} + + +void body::appendPart(shared_ptr part) +{ + initNewPart(part); + + m_parts.push_back(part); +} + + +void body::insertPartBefore(shared_ptr beforePart, shared_ptr part) +{ + initNewPart(part); + + const std::vector >::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, shared_ptr part) +{ + initNewPart(part); + + m_parts.insert(m_parts.begin() + pos, part); +} + + +void body::insertPartAfter(shared_ptr afterPart, shared_ptr part) +{ + initNewPart(part); + + const std::vector >::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, shared_ptr part) +{ + initNewPart(part); + + m_parts.insert(m_parts.begin() + pos + 1, part); +} + + +void body::removePart(shared_ptr part) +{ + const std::vector >::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 body::getPartAt(const size_t pos) +{ + return (m_parts[pos]); +} + + +const shared_ptr body::getPartAt(const size_t pos) const +{ + return (m_parts[pos]); +} + + +const std::vector > body::getPartList() const +{ + std::vector > list; + + list.reserve(m_parts.size()); + + for (std::vector >::const_iterator it = m_parts.begin() ; + it != m_parts.end() ; ++it) + { + list.push_back(*it); + } + + return (list); +} + + +const std::vector > body::getPartList() +{ + return (m_parts); +} + + +const std::vector > body::getChildComponents() +{ + std::vector > list; + + copy_vector(m_parts, list); + + return (list); +} + + +} // vmime diff --git a/src/vmime/body.hpp b/src/vmime/body.hpp new file mode 100644 index 00000000..e47f97e9 --- /dev/null +++ b/src/vmime/body.hpp @@ -0,0 +1,344 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr 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(shared_ptr beforePart, shared_ptr 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, shared_ptr 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(shared_ptr afterPart, shared_ptr part); + + /** Insert a new part after the specified position. + * + * @param pos position of the part before the new part + * @param part part to insert + */ + void insertPartAfter(const size_t pos, shared_ptr part); + + /** Remove the specified part from the list. + * + * @param part part to remove + * @throw exceptions::no_such_part if the part is not in the list + */ + void removePart(shared_ptr 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 getPartAt(const size_t pos); + + /** Return the part at the specified position. + * + * @param pos position + * @return part at position 'pos' + */ + const shared_ptr getPartAt(const size_t pos) const; + + /** Return the part list. + * + * @return list of parts + */ + const std::vector > getPartList() const; + + /** Return the part list. + * + * @return list of parts + */ + const std::vector > 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 getContents() const; + + /** Set the body contents. + * + * @param contents new body contents + */ + void setContents(shared_ptr contents); + + /** Set the body contents and type. + * + * @param contents new body contents + * @param type type of contents + */ + void setContents(shared_ptr 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(shared_ptr 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(shared_ptr 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 clone() const; + void copyFrom(const component& other); + body& operator=(const body& other); + + const std::vector > 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 m_contents; + + bodyPart* m_part; + + std::vector > m_parts; + + bool isRootPart() const; + + void initNewPart(shared_ptr 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 + (shared_ptr parser, const string& boundary, + const size_t position, const size_t end, + size_t* boundaryStart, size_t* boundaryEnd); + + // Component parsing & assembling + void parseImpl + (const parsingContext& ctx, + shared_ptr 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/src/vmime/bodyPart.cpp b/src/vmime/bodyPart.cpp new file mode 100644 index 00000000..12896f84 --- /dev/null +++ b/src/vmime/bodyPart.cpp @@ -0,0 +1,190 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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
()), + m_body(make_shared ()), + m_parent() +{ + m_body->setParentPart(this); +} + + +void bodyPart::parseImpl + (const parsingContext& ctx, shared_ptr 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 bodyPart::clone() const +{ + shared_ptr p = make_shared (); + + 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 (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 bodyPart::getHeader() const +{ + return (m_header); +} + + +shared_ptr
bodyPart::getHeader() +{ + return (m_header); +} + + +void bodyPart::setHeader(shared_ptr
h) +{ + m_header = h; +} + + +const shared_ptr bodyPart::getBody() const +{ + return (m_body); +} + + +shared_ptr bodyPart::getBody() +{ + return (m_body); +} + + +void bodyPart::setBody(shared_ptr b) +{ + bodyPart* oldPart = b->m_part; + + m_body = b; + m_body->setParentPart(this); + + // A body is associated to one and only one part + if (oldPart != NULL) + oldPart->setBody(make_shared ()); +} + + +bodyPart* bodyPart::getParentPart() +{ + return m_parent; +} + + +const bodyPart* bodyPart::getParentPart() const +{ + return m_parent; +} + + +shared_ptr bodyPart::createChildPart() +{ + shared_ptr part = make_shared (); + part->m_parent = this; + + return part; +} + + +void bodyPart::importChildPart(shared_ptr part) +{ + part->m_parent = this; +} + + +const std::vector > bodyPart::getChildComponents() +{ + std::vector > list; + + list.push_back(m_header); + list.push_back(m_body); + + return (list); +} + + +} // vmime + diff --git a/src/vmime/bodyPart.hpp b/src/vmime/bodyPart.hpp new file mode 100644 index 00000000..214cb208 --- /dev/null +++ b/src/vmime/bodyPart.hpp @@ -0,0 +1,155 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 getHeader() const; + + /** Return the header section of this part. + * + * @return header section + */ + shared_ptr
getHeader(); + + /** Replaces the header section of this part. + * + * @param header the new header of this part + */ + void setHeader(shared_ptr
header); + + /** Return the body section of this part. + * + * @return body section + */ + const shared_ptr getBody() const; + + /** Return the body section of this part. + * + * @return body section + */ + shared_ptr getBody(); + + /** Replaces the body section of this part. + * + * @param body new body section + */ + void setBody(shared_ptr 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 clone() const; + void copyFrom(const component& other); + bodyPart& operator=(const bodyPart& other); + + const std::vector > getChildComponents(); + + size_t getGeneratedSize(const generationContext& ctx); + +private: + + shared_ptr
m_header; + mutable shared_ptr 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 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(shared_ptr part); + + // Component parsing & assembling + void parseImpl + (const parsingContext& ctx, + shared_ptr 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/src/vmime/bodyPartAttachment.cpp b/src/vmime/bodyPartAttachment.cpp new file mode 100644 index 00000000..0684a896 --- /dev/null +++ b/src/vmime/bodyPartAttachment.cpp @@ -0,0 +1,146 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr part) + : m_part(part) +{ +} + + +const mediaType bodyPartAttachment::getType() const +{ + shared_ptr ctf = getContentType(); + + if (ctf) + { + return *ctf->getValue (); + } + 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 cdf = getContentDisposition(); + + if (cdf && cdf->hasFilename()) + { + name = cdf->getFilename(); + } + // Try the 'name' parameter of 'Content-Type' field + else + { + shared_ptr ctf = getContentType(); + + if (ctf) + { + shared_ptr prm = ctf->findParameter("name"); + + if (prm != NULL) + name = prm->getValue(); + } + } + + return name; +} + + +const text bodyPartAttachment::getDescription() const +{ + text description; + + shared_ptr cd = + getHeader()->findField(fields::CONTENT_DESCRIPTION); + + if (cd) + { + description = *cd->getValue (); + } + else + { + // No description available. + } + + return description; +} + + +const encoding bodyPartAttachment::getEncoding() const +{ + return m_part->getBody()->getEncoding(); +} + + +const shared_ptr bodyPartAttachment::getData() const +{ + return m_part->getBody()->getContents(); +} + + +shared_ptr bodyPartAttachment::getPart() const +{ + return m_part; +} + + +shared_ptr bodyPartAttachment::getHeader() const +{ + return m_part->getHeader(); +} + + +shared_ptr bodyPartAttachment::getContentDisposition() const +{ + return getHeader()->findField (fields::CONTENT_DISPOSITION); +} + + +shared_ptr bodyPartAttachment::getContentType() const +{ + return getHeader()->findField (fields::CONTENT_TYPE); +} + + +void bodyPartAttachment::generateIn(shared_ptr /* parent */) const +{ + // Not used +} + + +} // vmime + diff --git a/src/vmime/bodyPartAttachment.hpp b/src/vmime/bodyPartAttachment.hpp new file mode 100644 index 00000000..e1a4a89a --- /dev/null +++ b/src/vmime/bodyPartAttachment.hpp @@ -0,0 +1,78 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr part); + + const mediaType getType() const; + const word getName() const; + const text getDescription() const; + const encoding getEncoding() const; + + const shared_ptr getData() const; + + shared_ptr getPart() const; + shared_ptr getHeader() const; + +private: + + void generateIn(shared_ptr parent) const; + + shared_ptr getContentDisposition() const; + shared_ptr getContentType() const; + + + shared_ptr m_part; +}; + + +} // vmime + + +#endif // VMIME_BUILDING_DOC + + +#endif // VMIME_BODYPARTATTACHMENT_HPP_INCLUDED + diff --git a/src/vmime/charset.cpp b/src/vmime/charset.cpp new file mode 100644 index 00000000..22bff301 --- /dev/null +++ b/src/vmime/charset.cpp @@ -0,0 +1,210 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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 conv = charsetConverter::create(source, dest, opts); + conv->convert(in, out); +} + + +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 charset::clone() const +{ + return make_shared (m_name); +} + + +const string& charset::getName() const +{ + return (m_name); +} + + +void charset::copyFrom(const component& other) +{ + m_name = dynamic_cast (other).m_name; +} + + +const std::vector > charset::getChildComponents() +{ + return std::vector >(); +} + + + +// 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/src/vmime/charset.hpp b/src/vmime/charset.hpp new file mode 100644 index 00000000..5bd50fdf --- /dev/null +++ b/src/vmime/charset.hpp @@ -0,0 +1,148 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 > 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 platformHandler::getLocalCharset() + * 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::charset_conv_error if an error occured 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::charset_conv_error if an error occured during + * the conversion + */ + static void convert(utility::inputStream& in, utility::outputStream& out, + const charset& source, const charset& dest, + const charsetConverterOptions& opts = charsetConverterOptions()); + + shared_ptr 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/src/vmime/charsetConverter.cpp b/src/vmime/charsetConverter.cpp new file mode 100644 index 00000000..87886823 --- /dev/null +++ b/src/vmime/charsetConverter.cpp @@ -0,0 +1,45 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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::create + (const charset& source, const charset& dest, + const charsetConverterOptions& opts) +{ + if (source == "idna" || dest == "idna") + return make_shared (source, dest, opts); + else + return createGenericConverter(source, dest, opts); +} + + +} // vmime diff --git a/src/vmime/charsetConverter.hpp b/src/vmime/charsetConverter.hpp new file mode 100644 index 00000000..07f38d8f --- /dev/null +++ b/src/vmime/charsetConverter.hpp @@ -0,0 +1,119 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 error + * occured when initializing convert, or during charset conversion. + */ + +class VMIME_EXPORT charsetFilteredOutputStream : public filteredOutputStream +{ +}; + + +} // utility + + +/** Convert between charsets. + */ + +class VMIME_EXPORT charsetConverter : public object +{ +public: + + /** Construct and initialize an iconv charset converter. + * + * @param source input charset + * @param dest output charset + * @param opts conversion options + */ + static shared_ptr 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 + * @throws exceptions::charset_conv_error if an error occured during + * the conversion + */ + virtual void convert(const string& in, string& out) = 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 + * @throws exceptions::charset_conv_error if an error occured during + * the conversion + */ + virtual void convert(utility::inputStream& in, utility::outputStream& out) = 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 + * @return a filtered output stream, or NULL if not supported + */ + virtual shared_ptr getFilteredOutputStream(utility::outputStream& os) = 0; + +private: + + static shared_ptr createGenericConverter + (const charset& source, const charset& dest, + const charsetConverterOptions& opts); +}; + + +} // vmime + + +#endif // VMIME_CHARSETCONVERTER_HPP_INCLUDED diff --git a/src/vmime/charsetConverterOptions.cpp b/src/vmime/charsetConverterOptions.cpp new file mode 100644 index 00000000..caeacd01 --- /dev/null +++ b/src/vmime/charsetConverterOptions.cpp @@ -0,0 +1,37 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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() + : invalidSequence("?") +{ +} + + +} // vmime diff --git a/src/vmime/charsetConverterOptions.hpp b/src/vmime/charsetConverterOptions.hpp new file mode 100644 index 00000000..07e7a138 --- /dev/null +++ b/src/vmime/charsetConverterOptions.hpp @@ -0,0 +1,53 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(); + + + /** Replace invalid sequences with this string. */ + string invalidSequence; +}; + + +} // vmime + + +#endif // VMIME_CHARSETCONVERTEROPTIONS_HPP_INCLUDED diff --git a/src/vmime/charsetConverter_iconv.cpp b/src/vmime/charsetConverter_iconv.cpp new file mode 100644 index 00000000..75d7b170 --- /dev/null +++ b/src/vmime/charsetConverter_iconv.cpp @@ -0,0 +1,475 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + #include + + // 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 (ptr)) { } + + operator const char**() { return m_ptr; } + operator char**() { return const_cast (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 (ptr)) { } + + operator char**() { return m_ptr; } + + private: + + char** m_ptr; + }; + +#endif // VMIME_BUILDING_DOC +} + + + +// Output replacement char when an invalid sequence is encountered +template +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 (-1)) + { + out.write(invalidCharOutBuffer, 16 - invalidCharOutLen); + } +} + + + +namespace vmime +{ + + +// static +shared_ptr charsetConverter::createGenericConverter + (const charset& source, const charset& dest, + const charsetConverterOptions& opts) +{ + return make_shared (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 (-1)) + { + iconv_t* p = new iconv_t; + *p= cd; + + m_desc = p; + } +} + + +charsetConverter_iconv::~charsetConverter_iconv() +{ + if (m_desc != NULL) + { + // Close iconv handle + iconv_close(*static_cast (m_desc)); + + delete static_cast (m_desc); + m_desc = NULL; + } +} + + +void charsetConverter_iconv::convert(utility::inputStream& in, utility::outputStream& out) +{ + if (m_desc == NULL) + throw exceptions::charset_conv_error("Cannot initialize converter."); + + const iconv_t cd = *static_cast (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 (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 (-1)) + { + // 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); + + // 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 (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 (inPtr), inBuffer + sizeof(inBuffer), inBuffer); + inPos = inLength; + + if (errno != E2BIG) + prevIsInvalid = true; + } + } + else + { + // Write successfully converted bytes + out.write(outBuffer, sizeof(outBuffer) - outLength); + + 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) +{ + if (m_source == m_dest) + { + // No conversion needed + out = in; + return; + } + + out.clear(); + + utility::inputStreamStringAdapter is(in); + utility::outputStreamStringAdapter os(out); + + convert(is, os); + + os.flush(); +} + + +shared_ptr charsetConverter_iconv::getFilteredOutputStream(utility::outputStream& os) +{ + return make_shared (m_source, m_dest, &os); +} + + + +// charsetFilteredOutputStream_iconv + +namespace utility { + + +charsetFilteredOutputStream_iconv::charsetFilteredOutputStream_iconv + (const charset& source, const charset& dest, outputStream* os) + : m_desc(NULL), m_sourceCharset(source), m_destCharset(dest), + m_stream(*os), m_unconvCount(0) +{ + // Get an iconv descriptor + const iconv_t cd = iconv_open(dest.getName().c_str(), source.getName().c_str()); + + if (cd != reinterpret_cast (-1)) + { + iconv_t* p = new iconv_t; + *p= cd; + + m_desc = p; + } +} + + +charsetFilteredOutputStream_iconv::~charsetFilteredOutputStream_iconv() +{ + if (m_desc != NULL) + { + // Close iconv handle + iconv_close(*static_cast (m_desc)); + + delete static_cast (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 == NULL) + throw exceptions::charset_conv_error("Cannot initialize converter."); + + const iconv_t cd = *static_cast (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)) + { + 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 (-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 (-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 == NULL) + throw exceptions::charset_conv_error("Cannot initialize converter."); + + const iconv_t cd = *static_cast (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 (-1)) + { + const size_t inputConverted = inLength0 - inLength; + + // Skip a "blocking" character + if (inputConverted == 0) + { + 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/src/vmime/charsetConverter_iconv.hpp b/src/vmime/charsetConverter_iconv.hpp new file mode 100644 index 00000000..4167dc4e --- /dev/null +++ b/src/vmime/charsetConverter_iconv.hpp @@ -0,0 +1,135 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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); + void convert(utility::inputStream& in, utility::outputStream& out); + + shared_ptr getFilteredOutputStream(utility::outputStream& os); + +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 + */ + charsetFilteredOutputStream_iconv + (const charset& source, const charset& dest, outputStream* os); + + ~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]; +}; + + +} // utility + + +} // vmime + + +#endif // VMIME_CHARSETCONV_LIB_IS_ICONV + +#endif // VMIME_CHARSETCONVERTER_ICONV_HPP_INCLUDED diff --git a/src/vmime/charsetConverter_icu.cpp b/src/vmime/charsetConverter_icu.cpp new file mode 100644 index 00000000..3374d448 --- /dev/null +++ b/src/vmime/charsetConverter_icu.cpp @@ -0,0 +1,408 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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" + + +extern "C" +{ +#ifndef VMIME_BUILDING_DOC + + #include + #include + +#endif // VMIME_BUILDING_DOC +} + + +#include + + +namespace vmime +{ + + +// static +shared_ptr charsetConverter::createGenericConverter + (const charset& source, const charset& dest, + const charsetConverterOptions& opts) +{ + return make_shared (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 (err != U_ZERO_ERROR) + { + throw exceptions::charset_conv_error + ("Cannot initialize ICU converter for source charset '" + source.getName() + "'."); + } + + m_to = ucnv_open(dest.getName().c_str(), &err); + + if (err != U_ZERO_ERROR) + { + throw exceptions::charset_conv_error + ("Cannot initialize ICU converter for destination charset '" + dest.getName() + "'."); + } +} + + +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) +{ + UErrorCode err = U_ZERO_ERROR; + + // From buffers + byte_t cpInBuffer[16]; // stream data put here + size_t outSize = ucnv_getMinCharSize(m_from) * sizeof(cpInBuffer) * sizeof(UChar); + UChar* uOutBuffer = new UChar[outSize]; // Unicode chars end up here + + // Auto delete Unicode char buffer + std::auto_ptr cleanup(uOutBuffer); + + // To buffers + // converted (char) data end up here + size_t cpOutBufferSz = ucnv_getMaxCharSize(m_to) * outSize; + char* cpOutBuffer = new char[cpOutBufferSz]; + std::auto_ptr cleanupOut(cpOutBuffer); + + // 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 setting replacement char."); + + // 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 (&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; + UChar* targetLimit = target + outSize; + + toErr = U_ZERO_ERROR; + ucnv_toUnicode(m_from, &target, targetLimit, + &source, sourceLimit, NULL, flush, &toErr); + + if (toErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(toErr)) + 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; + UChar* uSourceLimit = target; + UErrorCode fromErr; + + // Loop until converted chars are fully written + do + { + char* cpTarget = &cpOutBuffer[0]; + const char* cpTargetLimit = cpOutBuffer + cpOutBufferSz; + + fromErr = U_ZERO_ERROR; + + // Write converted bytes (Unicode) to destination codepage + ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit, + &uSource, uSourceLimit, NULL, flush, &fromErr); + + if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr)) + throw exceptions::charset_conv_error("[ICU] Error converting from Unicode to " + m_dest.getName()); + + // Write to destination stream + out.write(cpOutBuffer, (cpTarget - cpOutBuffer)); + + } while (fromErr == U_BUFFER_OVERFLOW_ERROR); + + } while (toErr == U_BUFFER_OVERFLOW_ERROR); + } +} + + +void charsetConverter_icu::convert(const string& in, string& out) +{ + if (m_source == m_dest) + { + // No conversion needed + out = in; + return; + } + + out.clear(); + + utility::inputStreamStringAdapter is(in); + utility::outputStreamStringAdapter os(out); + + convert(is, os); + + os.flush(); +} + + +shared_ptr charsetConverter_icu::getFilteredOutputStream(utility::outputStream& os) +{ + return make_shared (m_source, m_dest, &os); +} + + + +// charsetFilteredOutputStream_icu + +namespace utility { + + +charsetFilteredOutputStream_icu::charsetFilteredOutputStream_icu + (const charset& source, const charset& dest, outputStream* os) + : m_from(NULL), m_to(NULL), m_sourceCharset(source), m_destCharset(dest), m_stream(*os) +{ + UErrorCode err = U_ZERO_ERROR; + m_from = ucnv_open(source.getName().c_str(), &err); + + if (err != U_ZERO_ERROR) + { + throw exceptions::charset_conv_error + ("Cannot initialize ICU converter for source charset '" + source.getName() + "'."); + } + + m_to = ucnv_open(dest.getName().c_str(), &err); + + if (err != U_ZERO_ERROR) + { + throw exceptions::charset_conv_error + ("Cannot initialize ICU converter for destination charset '" + dest.getName() + "'."); + } + + // Set replacement chars for when converting from Unicode to codepage + icu::UnicodeString substString(vmime::charsetConverterOptions().invalidSequence.c_str()); + ucnv_setSubstString(m_to, substString.getTerminatedBuffer(), -1, &err); + + if (U_FAILURE(err)) + throw exceptions::charset_conv_error("[ICU] Error setting replacement char."); +} + + +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 == NULL || m_to == NULL) + throw exceptions::charset_conv_error("Cannot initialize converters."); + + // Allocate buffer for Unicode chars + size_t uniSize = ucnv_getMinCharSize(m_from) * count * sizeof(UChar); + UChar* uniBuffer = new UChar[uniSize]; + std::auto_ptr uniCleanup(uniBuffer); // auto delete Unicode buffer + + // Conversion loop + UErrorCode toErr = U_ZERO_ERROR; + + const char* uniSource = reinterpret_cast (data); + const char* uniSourceLimit = uniSource + count; + + do + { + // Convert from source charset to Unicode + UChar* uniTarget = uniBuffer; + UChar* uniTargetLimit = uniBuffer + 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) + { + throw exceptions::charset_conv_error + ("[ICU] Error converting to Unicode from '" + m_sourceCharset.getName() + "'."); + } + + const size_t uniLength = uniTarget - uniBuffer; + + // Allocate buffer for destination charset + size_t cpSize = ucnv_getMinCharSize(m_to) * uniLength; + char* cpBuffer = new char[cpSize]; + std::auto_ptr cpCleanup(cpBuffer); // auto delete CP buffer + + // Convert from Unicode to destination charset + UErrorCode fromErr = U_ZERO_ERROR; + + const UChar* cpSource = uniBuffer; + const UChar* cpSourceLimit = uniBuffer + uniLength; + + do + { + char* cpTarget = cpBuffer; + char* cpTargetLimit = cpBuffer + 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)) + { + throw exceptions::charset_conv_error + ("[ICU] Error converting from Unicode to '" + m_destCharset.getName() + "'."); + } + + const size_t cpLength = cpTarget - cpBuffer; + + // Write successfully converted bytes + m_stream.write(cpBuffer, cpLength); + + } while (fromErr == U_BUFFER_OVERFLOW_ERROR); + + } while (toErr == U_BUFFER_OVERFLOW_ERROR); +} + + +void charsetFilteredOutputStream_icu::flush() +{ + if (m_from == NULL || m_to == NULL) + throw exceptions::charset_conv_error("Cannot initialize converters."); + + // Allocate buffer for Unicode chars + size_t uniSize = ucnv_getMinCharSize(m_from) * 1024 * sizeof(UChar); + UChar* uniBuffer = new UChar[uniSize]; + std::auto_ptr uniCleanup(uniBuffer); // auto delete Unicode buffer + + // 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; + UChar* uniTargetLimit = uniBuffer + 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; + + // Allocate buffer for destination charset + size_t cpSize = ucnv_getMinCharSize(m_to) * uniLength; + char* cpBuffer = new char[cpSize]; + std::auto_ptr cpCleanup(cpBuffer); // auto delete CP buffer + + // Convert from Unicode to destination charset + UErrorCode fromErr = U_ZERO_ERROR; + + const UChar* cpSource = uniBuffer; + const UChar* cpSourceLimit = uniBuffer + uniLength; + + do + { + char* cpTarget = cpBuffer; + char* cpTargetLimit = cpBuffer + 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; + + // Write successfully converted bytes + m_stream.write(cpBuffer, 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/src/vmime/charsetConverter_icu.hpp b/src/vmime/charsetConverter_icu.hpp new file mode 100644 index 00000000..5d054413 --- /dev/null +++ b/src/vmime/charsetConverter_icu.hpp @@ -0,0 +1,126 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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); + void convert(utility::inputStream& in, utility::outputStream& out); + + shared_ptr getFilteredOutputStream(utility::outputStream& os); + +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 + */ + charsetFilteredOutputStream_icu + (const charset& source, const charset& dest, outputStream* os); + + ~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; +}; + + +} // utility + + +} // vmime + + +#endif // VMIME_CHARSETCONV_LIB_IS_ICU + +#endif // VMIME_CHARSETCONVERTER_ICU_HPP_INCLUDED diff --git a/src/vmime/charsetConverter_idna.cpp b/src/vmime/charsetConverter_idna.cpp new file mode 100644 index 00000000..aea6eca7 --- /dev/null +++ b/src/vmime/charsetConverter_idna.cpp @@ -0,0 +1,168 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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) +{ + // 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); + + out << outStr; +} + + +void charsetConverter_idna::convert(const string& in, string& out) +{ + if (m_source == m_dest) + { + // No conversion needed + out = in; + return; + } + + out.clear(); + + if (m_dest == "idna") + { + if (utility::stringUtils::is7bit(in)) + { + // 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 unichars; + unichars.reserve(inUTF8.length()); + + while (ch < end) + { + const utf8::uint32_t uc = utf8::unchecked::next(ch); + unichars.push_back(uc); + } + + std::vector output(inUTF8.length() * 2); + punycode_uint outputLen = output.size(); + + const punycode_status status = punycode_encode + (unichars.size(), &unichars[0], /* case_flags */ NULL, &outputLen, &output[0]); + + if (status == punycode_success) + { + out = string("xn--") + string(output.begin(), output.begin() + outputLen); + } + else + { + // TODO + } + } + else if (m_source == "idna") + { + if (in.length() < 5 || in.substr(0, 4) != "xn--") + { + // Not an IDNA string + out = in; + return; + } + + std::vector output(in.length() - 4); + punycode_uint outputLen = output.size(); + + const punycode_status status = punycode_decode + (in.length() - 4, &in[4], &outputLen, &output[0], /* case_flags */ NULL); + + if (status == punycode_success) + { + std::vector outUTF8Bytes(outputLen * 4); + char* p = &outUTF8Bytes[0]; + + for (std::vector ::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); + } + else + { + // TODO + } + } +} + + +shared_ptr charsetConverter_idna::getFilteredOutputStream(utility::outputStream& /* os */) +{ + return null; +} + + +} // vmime diff --git a/src/vmime/charsetConverter_idna.hpp b/src/vmime/charsetConverter_idna.hpp new file mode 100644 index 00000000..874d6bf1 --- /dev/null +++ b/src/vmime/charsetConverter_idna.hpp @@ -0,0 +1,70 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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); + void convert(utility::inputStream& in, utility::outputStream& out); + + shared_ptr getFilteredOutputStream(utility::outputStream& os); + +private: + + charset m_source; + charset m_dest; + + charsetConverterOptions m_options; +}; + + +} // vmime + + +#endif // VMIME_CHARSETCONVERTER_IDNA_HPP_INCLUDED diff --git a/src/vmime/component.cpp b/src/vmime/component.cpp new file mode 100644 index 00000000..46ff4036 --- /dev/null +++ b/src/vmime/component.cpp @@ -0,0 +1,244 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime +{ + + +component::component() + : m_parsedOffset(0), m_parsedLength(0) +{ +} + + +component::~component() +{ +} + + +void component::parse + (shared_ptr inputStream, const size_t length) +{ + parse(inputStream, 0, length, NULL); +} + + +void component::parse + (shared_ptr inputStream, const size_t position, + const size_t end, size_t* newPosition) +{ + parse(parsingContext::getDefaultContext(), inputStream, position, end, newPosition); +} + + +void component::parse + (const parsingContext& ctx, + shared_ptr inputStream, const size_t position, + const size_t end, size_t* newPosition) +{ + m_parsedOffset = m_parsedLength = 0; + + shared_ptr seekableStream = + dynamicCast (inputStream); + + if (seekableStream == NULL || 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 parser = + make_shared (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 > children = getChildComponents(); + + for (size_t i = 0, n = children.size() ; i < n ; ++i) + children[i]->offsetParsedBounds(offset); +} + + +void component::parseImpl + (const parsingContext& ctx, shared_ptr 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 != NULL) + *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 stream = + make_shared (buffer); + + shared_ptr parser = + make_shared (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 > children = getChildComponents(); + size_t totalSize = 0; + + for (std::vector >::iterator it = children.begin() ; it != children.end() ; ++it) + totalSize += (*it)->getGeneratedSize(ctx); + + return totalSize; +} + + +} // vmime + diff --git a/src/vmime/component.hpp b/src/vmime/component.hpp new file mode 100644 index 00000000..87d465e8 --- /dev/null +++ b/src/vmime/component.hpp @@ -0,0 +1,257 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr 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 + (shared_ptr 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, + shared_ptr 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 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 > 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, + shared_ptr 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/src/vmime/constants.cpp b/src/vmime/constants.cpp new file mode 100644 index 00000000..3b0a54c0 --- /dev/null +++ b/src/vmime/constants.cpp @@ -0,0 +1,237 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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"; +} + + +} // vmime diff --git a/src/vmime/constants.hpp b/src/vmime/constants.hpp new file mode 100644 index 00000000..8e6e3f83 --- /dev/null +++ b/src/vmime/constants.hpp @@ -0,0 +1,256 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free SOFTWARE; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software FOUNDATION; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A 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 + +#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 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; + } +} + + +#endif // VMIME_CONSTANTS_HPP_INCLUDED diff --git a/src/vmime/contentDisposition.cpp b/src/vmime/contentDisposition.cpp new file mode 100644 index 00000000..3cf92e27 --- /dev/null +++ b/src/vmime/contentDisposition.cpp @@ -0,0 +1,133 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 contentDisposition::clone() const +{ + return make_shared (*this); +} + + +void contentDisposition::copyFrom(const component& other) +{ + const contentDisposition& d = dynamic_cast (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 > contentDisposition::getChildComponents() +{ + return std::vector >(); +} + + +} // vmime diff --git a/src/vmime/contentDisposition.hpp b/src/vmime/contentDisposition.hpp new file mode 100644 index 00000000..c934b81d --- /dev/null +++ b/src/vmime/contentDisposition.hpp @@ -0,0 +1,99 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + void copyFrom(const component& other); + contentDisposition& operator=(const contentDisposition& other); + + const std::vector > 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/src/vmime/contentDispositionField.cpp b/src/vmime/contentDispositionField.cpp new file mode 100644 index 00000000..5a9c1212 --- /dev/null +++ b/src/vmime/contentDispositionField.cpp @@ -0,0 +1,158 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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&) + : headerField(), parameterizedHeaderField() +{ +} + + +bool contentDispositionField::hasCreationDate() const +{ + return findParameter("creation-date"); +} + + +const datetime contentDispositionField::getCreationDate() const +{ + shared_ptr param = findParameter("creation-date"); + + if (param) + return param->getValueAs (); + else + return datetime::now(); +} + + +void contentDispositionField::setCreationDate(const datetime& creationDate) +{ + getParameter("creation-date")->setValue(creationDate); +} + + +bool contentDispositionField::hasModificationDate() const +{ + return findParameter("modification-date"); +} + + +const datetime contentDispositionField::getModificationDate() const +{ + shared_ptr param = findParameter("modification-date"); + + if (param) + return param->getValueAs (); + else + return datetime::now(); +} + + +void contentDispositionField::setModificationDate(const datetime& modificationDate) +{ + getParameter("modification-date")->setValue(modificationDate); +} + + +bool contentDispositionField::hasReadDate() const +{ + return findParameter("read-date"); +} + + +const datetime contentDispositionField::getReadDate() const +{ + shared_ptr param = findParameter("read-date"); + + if (param) + return param->getValueAs (); + else + return datetime::now(); +} + + +void contentDispositionField::setReadDate(const datetime& readDate) +{ + getParameter("read-date")->setValue(readDate); +} + + +bool contentDispositionField::hasFilename() const +{ + return findParameter("filename"); +} + + +const word contentDispositionField::getFilename() const +{ + shared_ptr 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 findParameter("size"); +} + + +const string contentDispositionField::getSize() const +{ + shared_ptr 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/src/vmime/contentDispositionField.hpp b/src/vmime/contentDispositionField.hpp new file mode 100644 index 00000000..aac4c5de --- /dev/null +++ b/src/vmime/contentDispositionField.hpp @@ -0,0 +1,148 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/contentHandler.cpp b/src/vmime/contentHandler.cpp new file mode 100644 index 00000000..3afe4324 --- /dev/null +++ b/src/vmime/contentHandler.cpp @@ -0,0 +1,40 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/contentHandler.hpp b/src/vmime/contentHandler.hpp new file mode 100644 index 00000000..f62af166 --- /dev/null +++ b/src/vmime/contentHandler.hpp @@ -0,0 +1,139 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#include "vmime/base.hpp" +#include "vmime/utility/stringProxy.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 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/src/vmime/contentTypeField.cpp b/src/vmime/contentTypeField.cpp new file mode 100644 index 00000000..9f38294a --- /dev/null +++ b/src/vmime/contentTypeField.cpp @@ -0,0 +1,113 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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&) + : headerField(), parameterizedHeaderField() +{ +} + + +bool contentTypeField::hasBoundary() const +{ + return findParameter("boundary"); +} + + +const string contentTypeField::getBoundary() const +{ + shared_ptr 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 findParameter("charset"); +} + + +const charset contentTypeField::getCharset() const +{ + shared_ptr param = findParameter("charset"); + + if (param) + return param->getValueAs (); + else + return charset(); +} + + +void contentTypeField::setCharset(const charset& ch) +{ + getParameter("charset")->setValue(ch); +} + + +bool contentTypeField::hasReportType() const +{ + return findParameter("report-type"); +} + + +const string contentTypeField::getReportType() const +{ + shared_ptr 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/src/vmime/contentTypeField.hpp b/src/vmime/contentTypeField.hpp new file mode 100644 index 00000000..8604c4a3 --- /dev/null +++ b/src/vmime/contentTypeField.hpp @@ -0,0 +1,114 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/context.cpp b/src/vmime/context.cpp new file mode 100644 index 00000000..07fe4875 --- /dev/null +++ b/src/vmime/context.cpp @@ -0,0 +1,87 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/context.hpp b/src/vmime/context.hpp new file mode 100644 index 00000000..767ec05a --- /dev/null +++ b/src/vmime/context.hpp @@ -0,0 +1,122 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + 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/src/vmime/dateTime.cpp b/src/vmime/dateTime.cpp new file mode 100644 index 00000000..eca8e785 --- /dev/null +++ b/src/vmime/dateTime.cpp @@ -0,0 +1,894 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#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 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 (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 datetime::clone() const +{ + return make_shared (*this); +} + + +const std::vector > datetime::getChildComponents() +{ + return std::vector >(); +} + + +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/src/vmime/dateTime.hpp b/src/vmime/dateTime.hpp new file mode 100644 index 00000000..7af63040 --- /dev/null +++ b/src/vmime/dateTime.hpp @@ -0,0 +1,263 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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 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 > 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/src/vmime/defaultAttachment.cpp b/src/vmime/defaultAttachment.cpp new file mode 100644 index 00000000..8f8ad453 --- /dev/null +++ b/src/vmime/defaultAttachment.cpp @@ -0,0 +1,146 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr data, + const encoding& enc, const mediaType& type, const text& desc, const word& name) + : m_type(type), m_desc(desc), m_data(data), m_encoding(enc), m_name(name) +{ +} + + +defaultAttachment::defaultAttachment(shared_ptr 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(shared_ptr parent) const +{ + // Create and append a new part for this attachment + shared_ptr part = make_shared (); + parent->getBody()->appendPart(part); + + generatePart(part); +} + + +void defaultAttachment::generatePart(shared_ptr 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 (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 defaultAttachment::getData() const +{ + return m_data; +} + + +const encoding defaultAttachment::getEncoding() const +{ + return m_encoding; +} + + +shared_ptr defaultAttachment::getPart() const +{ + return null; +} + + +shared_ptr defaultAttachment::getHeader() const +{ + return null; +} + + +} // vmime diff --git a/src/vmime/defaultAttachment.hpp b/src/vmime/defaultAttachment.hpp new file mode 100644 index 00000000..6eb0c5b6 --- /dev/null +++ b/src/vmime/defaultAttachment.hpp @@ -0,0 +1,88 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr data, const encoding& enc, const mediaType& type, const text& desc = NULL_TEXT, const word& name = NULL_WORD); + defaultAttachment(shared_ptr 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 getData() const; + const encoding getEncoding() const; + + shared_ptr getPart() const; + + shared_ptr getHeader() const; + +protected: + + mediaType m_type; /**< Media type (eg. "application/octet-stream") */ + text m_desc; /**< Description (eg. "The image you requested") */ + shared_ptr 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(shared_ptr parent) const; + +protected: + + virtual void generatePart(shared_ptr part) const; +}; + + +} // vmime + + +#endif // VMIME_DEFAULTATTACHMENT_HPP_INCLUDED diff --git a/src/vmime/disposition.cpp b/src/vmime/disposition.cpp new file mode 100644 index 00000000..352d3251 --- /dev/null +++ b/src/vmime/disposition.cpp @@ -0,0 +1,329 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 disposition::clone() const +{ + shared_ptr disp = make_shared (); + + 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 (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 > disposition::getChildComponents() +{ + return std::vector >(); +} + + +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 ::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 ::const_iterator it = m_modifiers.begin() ; + it != m_modifiers.end() ; ++it) + { + if (*it == modifierLC) + return (true); + } + + return (false); +} + + +const std::vector 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 ::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/src/vmime/disposition.hpp b/src/vmime/disposition.hpp new file mode 100644 index 00000000..7322c21d --- /dev/null +++ b/src/vmime/disposition.hpp @@ -0,0 +1,159 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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 clone() const; + void copyFrom(const component& other); + disposition& operator=(const disposition& other); + + const std::vector > 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 getModifierList() const; + +private: + + string m_actionMode; + string m_sendingMode; + string m_type; + + std::vector 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/src/vmime/emailAddress.cpp b/src/vmime/emailAddress.cpp new file mode 100644 index 00000000..e185b17b --- /dev/null +++ b/src/vmime/emailAddress.cpp @@ -0,0 +1,539 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +{ + + +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_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; + + 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; + + case State_LocalPartStart: + + if (c == '"') + { + state = State_LocalPartQuoted; + ++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_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_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(); + + m_localName = word(localPart.str(), vmime::charsets::UTF_8); + m_domainName = word(domainPart.str(), vmime::charsets::UTF_8); + } + + setParsedBounds(position, p - pend); + + if (newPosition) + *newPosition = p - pend; +} + + +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(); +} + + +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 (other); + + m_localName = source.m_localName; + m_domainName = source.m_domainName; +} + + +emailAddress& emailAddress::operator=(const emailAddress& other) +{ + copyFrom(other); + return (*this); +} + + +shared_ptr emailAddress::clone() const +{ + return make_shared (*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 > emailAddress::getChildComponents() +{ + return std::vector >(); +} + + +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 (m_localName)); + txt.appendWord(make_shared ("@", vmime::charsets::US_ASCII)); + txt.appendWord(make_shared (m_domainName)); + + return txt; +} + + +} // vmime diff --git a/src/vmime/emailAddress.hpp b/src/vmime/emailAddress.hpp new file mode 100644 index 00000000..30ee24ab --- /dev/null +++ b/src/vmime/emailAddress.hpp @@ -0,0 +1,135 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + emailAddress& operator=(const emailAddress& other); + + const std::vector > 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/src/vmime/emptyContentHandler.cpp b/src/vmime/emptyContentHandler.cpp new file mode 100644 index 00000000..e0f191f3 --- /dev/null +++ b/src/vmime/emptyContentHandler.cpp @@ -0,0 +1,117 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 emptyContentHandler::clone() const +{ + return make_shared (); +} + + +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/src/vmime/emptyContentHandler.hpp b/src/vmime/emptyContentHandler.hpp new file mode 100644 index 00000000..369a4206 --- /dev/null +++ b/src/vmime/emptyContentHandler.hpp @@ -0,0 +1,70 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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/src/vmime/encoding.cpp b/src/vmime/encoding.cpp new file mode 100644 index 00000000..26922395 --- /dev/null +++ b/src/vmime/encoding.cpp @@ -0,0 +1,300 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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 encoding::getEncoder() const +{ + shared_ptr 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(), 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 + (shared_ptr 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(shared_ptr 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 encoding::clone() const +{ + return make_shared (*this); +} + + +void encoding::copyFrom(const component& other) +{ + const encoding& e = dynamic_cast (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 > encoding::getChildComponents() +{ + return std::vector >(); +} + + +} // vmime diff --git a/src/vmime/encoding.hpp b/src/vmime/encoding.hpp new file mode 100644 index 00000000..3148f899 --- /dev/null +++ b/src/vmime/encoding.hpp @@ -0,0 +1,172 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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); + +public: + + /** 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 > 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(shared_ptr 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(shared_ptr data, const charset& chset, const EncodingUsage usage = USAGE_BINARY_DATA); + + + shared_ptr 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 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/src/vmime/exception.cpp b/src/vmime/exception.cpp new file mode 100644 index 00000000..042ac4f4 --- /dev/null +++ b/src/vmime/exception.cpp @@ -0,0 +1,748 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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() + : m_what(""), m_other(NULL) +{ +} + + +exception::exception(const string& what, const exception& other) + : m_what(what), m_other(&other != &NO_EXCEPTION ? other.clone() : NULL) +{ +} + + +exception::exception(const exception& e) + : std::exception(), m_what(e.what()), m_other(e.m_other == NULL ? NULL : e.m_other->clone()) +{ +} + + +exception::~exception() throw() +{ + delete (m_other); +} + + +const char* exception::what() const throw() +{ + return (m_what.c_str()); +} + + +const char* exception::what() throw() +{ + return (m_what.c_str()); +} + + +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"; } + + +// +// 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"; } + + +// +// 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"; } + + +// +// certificate_exception +// + +certificate_exception::~certificate_exception() throw() {} +certificate_exception::certificate_exception(const string& what, const exception& other) + : tls_exception(what, other) {} + +exception* certificate_exception::clone() const { return new certificate_exception(*this); } +const char* certificate_exception::name() const throw() { return "certificate_exception"; } + + +// +// certificate_verification_exception +// + +certificate_verification_exception::~certificate_verification_exception() throw() {} +certificate_verification_exception::certificate_verification_exception(const string& what, const exception& other) + : certificate_exception(what, other) {} + +exception* certificate_verification_exception::clone() const { return new certificate_verification_exception(*this); } +const char* certificate_verification_exception::name() const throw() { return "certificate_verification_exception"; } + + +// +// unsupported_certificate_type +// + +unsupported_certificate_type::~unsupported_certificate_type() throw() {} +unsupported_certificate_type::unsupported_certificate_type(const string& type, const exception& other) + : certificate_exception("Unsupported certificate type: '" + type + "'", other) {} + +exception* unsupported_certificate_type::clone() const { return new unsupported_certificate_type(*this); } +const char* unsupported_certificate_type::name() const throw() { return "unsupported_certificate_type"; } + + +#endif // VMIME_HAVE_TLS_SUPPORT + + +} // exceptions + + +} // vmime + diff --git a/src/vmime/exception.hpp b/src/vmime/exception.hpp new file mode 100644 index 00000000..e2afcc62 --- /dev/null +++ b/src/vmime/exception.hpp @@ -0,0 +1,906 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#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::exception +{ +private: + + string m_what; + exception* m_other; + + exception(); + +public: + + exception(const string& what, const exception& other = NO_EXCEPTION); + exception(const exception& e); + + virtual ~exception() throw(); + + /** Return a description of the error. + * + * @return error message + */ + const char* what() const throw(); + + /** Return a description of the error. + * + * @return error message + */ + const char* what() throw(); + + /** Return the next exception in the chain (encapsulated exception). + * + * @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(); +}; + + +/** 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(); + +}; + + +/** 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(); +}; + + +class VMIME_EXPORT certificate_exception : public tls_exception +{ +public: + + certificate_exception(const string& what, const exception& other = NO_EXCEPTION); + ~certificate_exception() throw(); + + exception* clone() const; + const char* name() const throw(); +}; + + +class VMIME_EXPORT certificate_verification_exception : public certificate_exception +{ +public: + + certificate_verification_exception(const string& what, const exception& other = NO_EXCEPTION); + ~certificate_verification_exception() throw (); + + exception* clone() const; + const char* name() const throw (); +}; + + +class VMIME_EXPORT unsupported_certificate_type : public certificate_exception +{ +public: + + unsupported_certificate_type(const string& type, const exception& other = NO_EXCEPTION); + ~unsupported_certificate_type() throw (); + + exception* clone() const; + const char* name() const throw (); +}; + + +#endif // VMIME_HAVE_TLS_SUPPORT + + + +} // exceptions + + +} // vmime + + +#endif // VMIME_EXCEPTION_HPP_INCLUDED diff --git a/src/vmime/export.hpp b/src/vmime/export.hpp new file mode 100644 index 00000000..90f0cc3a --- /dev/null +++ b/src/vmime/export.hpp @@ -0,0 +1,36 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/fileAttachment.cpp b/src/vmime/fileAttachment.cpp new file mode 100644 index 00000000..25a97fcc --- /dev/null +++ b/src/vmime/fileAttachment.cpp @@ -0,0 +1,223 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + +#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(shared_ptr 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(shared_ptr 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(shared_ptr 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 fsf = platform::getHandler()->getFileSystemFactory(); + utility::file::path path = fsf->stringToPath(filepath); + + shared_ptr file = fsf->create(path); + + if (!file->isFile()) + throw exceptions::open_file_error(); + + m_data = make_shared + (file->getFileReader()->getInputStream(), file->getLength()); + + m_fileInfo.setFilename(path.getLastComponent()); + m_fileInfo.setSize(file->getLength()); +} + + +void fileAttachment::setData(shared_ptr cts) +{ + m_data = cts; + + m_fileInfo.setSize(cts->getLength()); +} + + +void fileAttachment::generatePart(shared_ptr part) const +{ + defaultAttachment::generatePart(part); + + shared_ptr cdf = + dynamicCast (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 != NULL); } +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 != NULL); } +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 != NULL); } +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 != NULL); } +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 != NULL); } +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/src/vmime/fileAttachment.hpp b/src/vmime/fileAttachment.hpp new file mode 100644 index 00000000..1e7a808a --- /dev/null +++ b/src/vmime/fileAttachment.hpp @@ -0,0 +1,197 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr cts, const word& filename, const mediaType& type); + fileAttachment(shared_ptr cts, const word& filename, const mediaType& type, const text& desc); + fileAttachment(shared_ptr cts, const word& filename, const mediaType& type, const text& desc, const encoding& enc); + + /** Stores information about a file attachment. + */ + class 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(shared_ptr cts); + + fileInfo m_fileInfo; + + void generatePart(shared_ptr part) const; +}; + + +} // vmime + + +#endif // VMIME_HAVE_FILESYSTEM_FEATURES + +#endif // VMIME_FILEATTACHMENT_HPP_INCLUDED diff --git a/src/vmime/fileContentHandler.cpp b/src/vmime/fileContentHandler.cpp new file mode 100644 index 00000000..53ec9f69 --- /dev/null +++ b/src/vmime/fileContentHandler.cpp @@ -0,0 +1,81 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/fileContentHandler.hpp" + + +namespace vmime +{ + + +fileContentHandler::fileContentHandler() + : streamContentHandler() +{ +} + + +fileContentHandler::fileContentHandler + (shared_ptr 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 fileContentHandler::clone() const +{ + return make_shared (*this); +} + + +void fileContentHandler::setData + (shared_ptr file, const vmime::encoding& enc) +{ + m_file = file; + m_encoding = enc; + + streamContentHandler::setData + (file->getFileReader()->getInputStream(), file->getLength(), enc); +} + + +} // vmime diff --git a/src/vmime/fileContentHandler.hpp b/src/vmime/fileContentHandler.hpp new file mode 100644 index 00000000..68b4d396 --- /dev/null +++ b/src/vmime/fileContentHandler.hpp @@ -0,0 +1,93 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/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 + (shared_ptr file, + const vmime::encoding& enc = NO_ENCODING); + + ~fileContentHandler(); + + fileContentHandler(const fileContentHandler& cts); + fileContentHandler& operator=(const fileContentHandler& cts); + + shared_ptr 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 + (shared_ptr 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 m_file; +}; + + +} // vmime + + +#endif // VMIME_FILECONTENTHANDLER_HPP_INCLUDED diff --git a/src/vmime/generatedMessageAttachment.cpp b/src/vmime/generatedMessageAttachment.cpp new file mode 100644 index 00000000..0473d247 --- /dev/null +++ b/src/vmime/generatedMessageAttachment.cpp @@ -0,0 +1,107 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr part) + : m_bpa(make_shared (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 generatedMessageAttachment::getData() const +{ + return m_bpa->getData(); +} + + +const encoding generatedMessageAttachment::getEncoding() const +{ + return m_bpa->getEncoding(); +} + + +shared_ptr generatedMessageAttachment::getPart() const +{ + return m_bpa->getPart(); +} + + +shared_ptr generatedMessageAttachment::getHeader() const +{ + return m_bpa->getHeader(); +} + + +shared_ptr generatedMessageAttachment::getMessage() const +{ + if (m_msg == NULL) + { + // Extract data + std::ostringstream oss; + utility::outputStreamAdapter os(oss); + + getData()->extract(os); + + // Parse message + m_msg = make_shared (); + m_msg->parse(oss.str()); + } + + return m_msg; +} + + +void generatedMessageAttachment::generateIn(shared_ptr /* parent */) const +{ + // Not used (see 'parsedMessageAttachment') +} + + +} // vmime + diff --git a/src/vmime/generatedMessageAttachment.hpp b/src/vmime/generatedMessageAttachment.hpp new file mode 100644 index 00000000..7137b22b --- /dev/null +++ b/src/vmime/generatedMessageAttachment.hpp @@ -0,0 +1,79 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr part); + + const mediaType getType() const; + const text getDescription() const; + const word getName() const; + + const shared_ptr getData() const; + + const encoding getEncoding() const; + + shared_ptr getPart() const; + + shared_ptr getHeader() const; + + shared_ptr getMessage() const; + +protected: + + void generateIn(shared_ptr parent) const; + +private: + + shared_ptr m_bpa; + mutable shared_ptr m_msg; +}; + + +} // vmime + + +#endif // !VMIME_BUILDING_DOC + + +#endif // VMIME_GENERATEDMESSAGEATTACHMENT_HPP_INCLUDED + diff --git a/src/vmime/generationContext.cpp b/src/vmime/generationContext.cpp new file mode 100644 index 00000000..e9662883 --- /dev/null +++ b/src/vmime/generationContext.cpp @@ -0,0 +1,109 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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("") +{ +} + + +generationContext::generationContext(const generationContext& ctx) + : context(ctx), + m_maxLineLength(ctx.m_maxLineLength), + m_prologText(ctx.m_prologText), + m_epilogText(ctx.m_epilogText) +{ +} + + +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; +} + + +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; +} + + +} // vmime diff --git a/src/vmime/generationContext.hpp b/src/vmime/generationContext.hpp new file mode 100644 index 00000000..949f06ac --- /dev/null +++ b/src/vmime/generationContext.hpp @@ -0,0 +1,106 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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; +}; + + +} // vmime + + +#endif // VMIME_GENERATIONCONTEXT_HPP_INCLUDED diff --git a/src/vmime/header.cpp b/src/vmime/header.cpp new file mode 100644 index 00000000..34b5fa6e --- /dev/null +++ b/src/vmime/header.cpp @@ -0,0 +1,388 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + + +namespace vmime +{ + + +header::header() +{ +} + + +header::~header() +{ + removeAllFields(); +} + + +/* + + RFC #822: + 3.2. HEADER FIELD DEFINITIONS + +field = field-name ":" [ field-body ] CRLF + +field-name = 1* + +field-body = field-body-contents + [CRLF LWSP-char field-body] + +field-body-contents = + +*/ + +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 field = headerField::parseNext(ctx, buffer, pos, end, &pos); + if (field == NULL) 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 >::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 header::clone() const +{ + shared_ptr
hdr = make_shared
(); + + hdr->m_fields.reserve(m_fields.size()); + + for (std::vector >::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 (other); + + std::vector > fields; + + fields.reserve(h.m_fields.size()); + + for (std::vector >::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 >::const_iterator pos = + std::find_if(m_fields.begin(), m_fields.end(), + fieldHasName(utility::stringUtils::toLower(fieldName))); + + return (pos != m_fields.end()); +} + + +shared_ptr header::findField(const string& fieldName) const +{ + // Find the first field that matches the specified name + std::vector >::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 > header::findAllFields(const string& fieldName) +{ + std::vector > result; + std::back_insert_iterator > > back(result); + + std::remove_copy_if(m_fields.begin(), m_fields.end(), back, + fieldHasNotName(utility::stringUtils::toLower(fieldName))); + + return result; +} + + +shared_ptr header::getField(const string& fieldName) +{ + const string name = utility::stringUtils::toLower(fieldName); + + // Find the first field that matches the specified name + std::vector >::const_iterator pos = m_fields.begin(); + const std::vector >::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 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(shared_ptr field) +{ + m_fields.push_back(field); +} + + +void header::insertFieldBefore(shared_ptr beforeField, shared_ptr field) +{ + const std::vector >::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, shared_ptr field) +{ + m_fields.insert(m_fields.begin() + pos, field); +} + + +void header::insertFieldAfter(shared_ptr afterField, shared_ptr field) +{ + const std::vector >::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, shared_ptr field) +{ + m_fields.insert(m_fields.begin() + pos + 1, field); +} + + +void header::removeField(shared_ptr field) +{ + const std::vector >::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 >::iterator it = m_fields.begin() + pos; + + m_fields.erase(it); +} + + +void header::replaceField(shared_ptr field, shared_ptr newField) +{ + insertFieldBefore(field, newField); + removeField(field); +} + + +void header::removeAllFields() +{ + m_fields.clear(); +} + + +void header::removeAllFields(const string& fieldName) +{ + std::vector > 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 header::getFieldAt(const size_t pos) +{ + return (m_fields[pos]); +} + + +const shared_ptr header::getFieldAt(const size_t pos) const +{ + return (m_fields[pos]); +} + + +const std::vector > header::getFieldList() const +{ + std::vector > list; + + list.reserve(m_fields.size()); + + for (std::vector >::const_iterator it = m_fields.begin() ; + it != m_fields.end() ; ++it) + { + list.push_back(*it); + } + + return (list); +} + + +const std::vector > header::getFieldList() +{ + return (m_fields); +} + + +const std::vector > header::getChildComponents() +{ + std::vector > 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 & 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 & field) +{ + return utility::stringUtils::toLower(field->getName()) != m_name; +} + + +} // vmime diff --git a/src/vmime/header.hpp b/src/vmime/header.hpp new file mode 100644 index 00000000..d2d20727 --- /dev/null +++ b/src/vmime/header.hpp @@ -0,0 +1,346 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 methodName() { return getField(fields::fieldName); } \ + shared_ptr 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 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 + shared_ptr findField(const string& fieldName) const + { + return dynamicCast (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 + shared_ptr findFieldValue(const string& fieldName) const + { + shared_ptr field = findField(fieldName); + + if (field) + return dynamicCast (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 > 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 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 + shared_ptr getField(const string& fieldName) + { + return dynamicCast (getField(fieldName)); + } + + /** Add a field at the end of the list. + * + * @param field field to append + */ + void appendField(shared_ptr 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(shared_ptr beforeField, shared_ptr 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, shared_ptr 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(shared_ptr afterField, shared_ptr 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, shared_ptr 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(shared_ptr 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(shared_ptr field, shared_ptr 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 getFieldAt(const size_t pos); + + /** Return the field at the specified position. + * + * @param pos position + * @return field at position 'pos' + */ + const shared_ptr getFieldAt(const size_t pos) const; + + /** Return the field list. + * + * @return list of fields + */ + const std::vector > getFieldList() const; + + /** Return the field list. + * + * @return list of fields + */ + const std::vector > getFieldList(); + + shared_ptr clone() const; + void copyFrom(const component& other); + header& operator=(const header& other); + + const std::vector > getChildComponents(); + + size_t getGeneratedSize(const generationContext& ctx); + +private: + + std::vector > m_fields; + + + class fieldHasName + { + public: + + fieldHasName(const string& name); + bool operator() (const shared_ptr & field); + + private: + + string m_name; + }; + + class fieldHasNotName + { + public: + + fieldHasNotName(const string& name); + bool operator() (const shared_ptr & 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/src/vmime/headerField.cpp b/src/vmime/headerField.cpp new file mode 100644 index 00000000..f4c6187e --- /dev/null +++ b/src/vmime/headerField.cpp @@ -0,0 +1,381 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 headerField::clone() const +{ + shared_ptr field = headerFieldFactory::getInstance()->create(m_name); + + field->copyFrom(*this); + + return (field); +} + + +void headerField::copyFrom(const component& other) +{ + const headerField& hf = dynamic_cast (other); + + m_value->copyFrom(*hf.m_value); +} + + +headerField& headerField::operator=(const headerField& other) +{ + copyFrom(other); + return (*this); +} + + +shared_ptr 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] != ':') + { + // 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; + } + else + { + // Extract the field name + const string name(buffer.begin() + nameStart, + buffer.begin() + nameEnd); + + // Skip ':' character + ++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; + + // Extract the field value + while (pos < end) + { + c = buffer[pos]; + + // Check for folded line + if (c == '\r' && pos + 2 < end && buffer[pos + 1] == '\n' && + (buffer[pos + 2] == ' ' || buffer[pos + 2] == '\t')) + { + pos += 3; + } + // Check for end of contents + if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') + { + contentsEnd = pos; + pos += 2; + break; + } + else if (c == '\n') + { + contentsEnd = pos; + ++pos; + break; + } + + while (pos < end) + { + c = buffer[pos]; + + // Check for end of line + if (c == '\r' && pos + 1 < end && buffer[pos + 1] == '\n') + { + contentsEnd = pos; + pos += 2; + break; + } + else if (c == '\n') + { + contentsEnd = pos; + ++pos; + break; + } + + ++pos; + } + + // Handle the case of folded lines + if (buffer[pos] == ' ' || buffer[pos] == '\t') + { + // This is a folding white-space: we keep it as is and + // we continue with contents parsing... + + // If the line contains only space characters, we assume it is + // the end of the headers. This is not strictly standard-compliant + // but, hey, we can't fail when parsing some malformed mails... + while (pos < end && (buffer[pos] == ' ' || buffer[pos] == '\t')) + ++pos; + + if ((pos < end && buffer[pos] == '\n') || + (pos + 1 < end && buffer[pos] == '\r' && buffer[pos + 1] == '\n')) + { + break; + } + } + else + { + // End of this field + break; + } + } + + 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 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 > headerField::getChildComponents() +{ + std::vector > list; + + if (m_value) + list.push_back(m_value); + + return (list); +} + + +shared_ptr headerField::getValue() const +{ + return m_value; +} + + +shared_ptr headerField::getValue() +{ + return m_value; +} + + +void headerField::setValue(shared_ptr value) +{ + if (!headerFieldFactory::getInstance()->isValueTypeValid(*this, *value)) + throw exceptions::bad_field_value_type(getName()); + + if (value != NULL) + m_value = value; +} + + +void headerField::setValueConst(shared_ptr 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/src/vmime/headerField.hpp b/src/vmime/headerField.hpp new file mode 100644 index 00000000..555805db --- /dev/null +++ b/src/vmime/headerField.hpp @@ -0,0 +1,190 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + void copyFrom(const component& other); + headerField& operator=(const headerField& other); + + const std::vector > 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 getValue() const; + + /** Return the read-only value object attached to this field, + * casted to the specified type. + * + * @return value object + */ + template + shared_ptr getValue() const + { + return dynamicCast (m_value); + } + + /** Return the value object attached to this field. + * + * @return value object + */ + virtual shared_ptr getValue(); + + /** Return the value object attached to this field, + * casted to the specified type. + * + * @return value object + */ + template + shared_ptr getValue() + { + return dynamicCast (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(shared_ptr 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(shared_ptr 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 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 m_value; +}; + + +} // vmime + + +#endif // VMIME_HEADERFIELD_HPP_INCLUDED diff --git a/src/vmime/headerFieldFactory.cpp b/src/vmime/headerFieldFactory.cpp new file mode 100644 index 00000000..5c60543e --- /dev/null +++ b/src/vmime/headerFieldFactory.cpp @@ -0,0 +1,151 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 (vmime::fields::CONTENT_TYPE); + registerField (vmime::fields::CONTENT_TRANSFER_ENCODING); + registerField (vmime::fields::CONTENT_DISPOSITION); + + registerField (vmime::fields::FROM); + registerField (vmime::fields::SENDER); + registerField (vmime::fields::REPLY_TO); + registerField (vmime::fields::DELIVERED_TO); + + // Register standard field values + registerFieldValue (vmime::fields::FROM); + registerFieldValue (vmime::fields::TO); + registerFieldValue (vmime::fields::CC); + registerFieldValue (vmime::fields::BCC); + registerFieldValue (vmime::fields::SENDER); + registerFieldValue (vmime::fields::DATE); + registerFieldValue (vmime::fields::RECEIVED); + registerFieldValue (vmime::fields::SUBJECT); + registerFieldValue (vmime::fields::REPLY_TO); + registerFieldValue (vmime::fields::DELIVERED_TO); + registerFieldValue (vmime::fields::ORGANIZATION); + registerFieldValue (vmime::fields::USER_AGENT); + registerFieldValue (vmime::fields::RETURN_PATH); + registerFieldValue (vmime::fields::CONTENT_TYPE); + registerFieldValue (vmime::fields::CONTENT_TRANSFER_ENCODING); + registerFieldValue (vmime::fields::CONTENT_DESCRIPTION); + registerFieldValue (vmime::fields::MIME_VERSION); + registerFieldValue (vmime::fields::CONTENT_DISPOSITION); + registerFieldValue (vmime::fields::CONTENT_ID); + registerFieldValue (vmime::fields::MESSAGE_ID); + registerFieldValue (vmime::fields::CONTENT_LOCATION); + registerFieldValue (vmime::fields::IN_REPLY_TO); + registerFieldValue (vmime::fields::REFERENCES); + + registerFieldValue (vmime::fields::ORIGINAL_MESSAGE_ID); + registerFieldValue (vmime::fields::DISPOSITION); + registerFieldValue (vmime::fields::DISPOSITION_NOTIFICATION_TO); +} + + +headerFieldFactory::~headerFieldFactory() +{ +} + + +shared_ptr headerFieldFactory::getInstance() +{ + static headerFieldFactory instance; + return shared_ptr (&instance, noop_shared_ptr_deleter ()); +} + + +shared_ptr headerFieldFactory::create + (const string& name, const string& body) +{ + NameMap::const_iterator pos = m_nameMap.find(utility::stringUtils::toLower(name)); + shared_ptr field; + + if (pos != m_nameMap.end()) + field = ((*pos).second)(); + else + field = registerer ::creator(); + + field->setName(name); + field->setValue(createValue(name)); + + if (body != NULL_STRING) + field->parse(body); + + return field; +} + + +shared_ptr headerFieldFactory::createValue(const string& fieldName) +{ + ValueMap::const_iterator pos = m_valueMap.find + (utility::stringUtils::toLower(fieldName)); + + shared_ptr value; + + if (pos != m_valueMap.end()) + value = ((*pos).second.allocFunc)(); + else + value = registerer ::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/src/vmime/headerFieldFactory.hpp b/src/vmime/headerFieldFactory.hpp new file mode 100644 index 00000000..960f27b7 --- /dev/null +++ b/src/vmime/headerFieldFactory.hpp @@ -0,0 +1,152 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 (*AllocFunc)(void); + typedef std::map NameMap; + + NameMap m_nameMap; + + + struct ValueInfo + { + typedef shared_ptr (*ValueAllocFunc)(void); + typedef bool (*ValueTypeCheckFunc)(const object&); + + ValueAllocFunc allocFunc; + ValueTypeCheckFunc checkTypeFunc; + }; + + typedef std::map ValueMap; + + ValueMap m_valueMap; + +public: + + static shared_ptr getInstance(); + +#ifndef VMIME_BUILDING_DOC + // TYPE must inherit from BASE_TYPE + template + class registerer + { + public: + + static bool checkType(const object& obj) + { + const TYPE* typedObj = dynamic_cast (&obj); + return typedObj != NULL; + } + + static shared_ptr creator() + { + // Allocate a new object + return shared_ptr (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 + void registerField(const string& name) + { + m_nameMap.insert(NameMap::value_type + (utility::stringUtils::toLower(name), + ®isterer ::creator)); + } + + /** Register a field value type. + * + * @param T value class (must inherit from 'headerFieldValue') + * @param name field name + */ + template + void registerFieldValue(const string& name) + { + ValueInfo vi; + vi.allocFunc = ®isterer ::creator; + vi.checkTypeFunc = ®isterer ::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 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 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/src/vmime/headerFieldValue.cpp b/src/vmime/headerFieldValue.cpp new file mode 100644 index 00000000..a93e0061 --- /dev/null +++ b/src/vmime/headerFieldValue.cpp @@ -0,0 +1,44 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/headerFieldValue.hpp b/src/vmime/headerFieldValue.hpp new file mode 100644 index 00000000..a3681953 --- /dev/null +++ b/src/vmime/headerFieldValue.hpp @@ -0,0 +1,52 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/htmlTextPart.cpp b/src/vmime/htmlTextPart.cpp new file mode 100644 index 00000000..44459336 --- /dev/null +++ b/src/vmime/htmlTextPart.cpp @@ -0,0 +1,510 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 ()), + m_text(make_shared ()) +{ +} + + +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(shared_ptr /* message */, shared_ptr parent) const +{ + // Plain text + if (!m_plainText->isEmpty()) + { + // -- Create a new part + shared_ptr part = make_shared (); + 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 htmlPart = make_shared (); + + // -- 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 relPart = make_shared (); + 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 >::const_iterator it = m_objects.begin() ; + it != m_objects.end() ; ++it) + { + shared_ptr objPart = make_shared (); + relPart->getBody()->appendPart(objPart); + + string id = (*it)->getId(); + + if (id.substr(0, 4) == "CID:") + 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 >& cidParts, std::vector >& locParts) +{ + for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i) + { + shared_ptr 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 ctf = + part.getHeader()->findField(fields::CONTENT_TYPE); + + if (ctf) + { + type = *ctf->getValue (); + } + else + { + // No "Content-type" field: assume "application/octet-stream". + } + + m_objects.push_back(make_shared + (vmime::clone(part.getBody()->getContents()), + part.getBody()->getEncoding(), id, type, refType)); +} + + +void htmlTextPart::parse(shared_ptr message, shared_ptr parent, shared_ptr textPart) +{ + // Search for possible embedded objects in the _whole_ message. + std::vector > cidParts; + std::vector > 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 ctf = + textPart->getHeader()->findField (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 >::const_iterator p = cidParts.begin() ; p != cidParts.end() ; ++p) + { + const shared_ptr midField = + (*p)->getHeader()->findField(fields::CONTENT_ID); + + const messageId mid = *midField->getValue (); + + 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 >::const_iterator p = locParts.begin() ; p != locParts.end() ; ++p) + { + const shared_ptr locField = + (*p)->getHeader()->findField(fields::CONTENT_LOCATION); + + const text loc = *locField->getValue (); + 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 (); + } +} + + +bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& parent, const bodyPart& textPart) +{ + // We search for the nearest "multipart/alternative" part. + const shared_ptr ctf = + part.getHeader()->findField(fields::CONTENT_TYPE); + + if (ctf) + { + const mediaType type = *ctf->getValue (); + + if (type.getType() == mediaTypes::MULTIPART && + type.getSubType() == mediaTypes::MULTIPART_ALTERNATIVE) + { + shared_ptr foundPart; + + for (size_t i = 0 ; i < part.getBody()->getPartCount() ; ++i) + { + const shared_ptr 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 p = part.getBody()->getPartAt(i); + + const shared_ptr ctf = + p->getHeader()->findField(fields::CONTENT_TYPE); + + if (ctf) + { + + const mediaType type = *ctf->getValue (); + + 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 htmlTextPart::getPlainText() const +{ + return m_plainText; +} + + +void htmlTextPart::setPlainText(shared_ptr plainText) +{ + m_plainText = plainText->clone(); +} + + +const shared_ptr htmlTextPart::getText() const +{ + return m_text; +} + + +void htmlTextPart::setText(shared_ptr text) +{ + m_text = text->clone(); +} + + +size_t htmlTextPart::getObjectCount() const +{ + return m_objects.size(); +} + + +shared_ptr htmlTextPart::getObjectAt(const size_t pos) const +{ + return m_objects[pos]; +} + + +shared_ptr htmlTextPart::findObject(const string& id) const +{ + for (std::vector >::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 >::const_iterator o = m_objects.begin() ; + o != m_objects.end() ; ++o) + { + if ((*o)->matchesId(id)) + return true; + } + + return false; +} + + +shared_ptr htmlTextPart::addObject + (shared_ptr data, const vmime::encoding& enc, const mediaType& type) +{ + const messageId mid(messageId::generateId()); + + shared_ptr obj = make_shared + (data, enc, mid.getId(), type, embeddedObject::REFERENCED_BY_ID); + + m_objects.push_back(obj); + + return obj; +} + + +shared_ptr htmlTextPart::addObject + (shared_ptr data, const mediaType& type) +{ + return addObject(data, encoding::decide(data), type); +} + + +shared_ptr htmlTextPart::addObject + (const string& data, const mediaType& type) +{ + shared_ptr cts = make_shared (data); + return addObject(cts, encoding::decide(cts), type); +} + + + +// +// htmlTextPart::embeddedObject +// + +htmlTextPart::embeddedObject::embeddedObject + (shared_ptr 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 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/src/vmime/htmlTextPart.hpp b/src/vmime/htmlTextPart.hpp new file mode 100644 index 00000000..4c1a8632 --- /dev/null +++ b/src/vmime/htmlTextPart.hpp @@ -0,0 +1,237 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 getPlainText() const; + void setPlainText(shared_ptr plainText); + + const shared_ptr getText() const; + void setText(shared_ptr text); + + /** Embedded object (eg: image for <IMG> tag). + */ + class 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(shared_ptr 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 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 <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 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 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 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 <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 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 <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 addObject(shared_ptr 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 <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 addObject(shared_ptr data, const encoding& enc, const mediaType& type); + + + size_t getPartCount() const; + + void generateIn(shared_ptr message, shared_ptr parent) const; + void parse(shared_ptr message, shared_ptr parent, shared_ptr textPart); + +private: + + shared_ptr m_plainText; + shared_ptr m_text; + charset m_charset; + + std::vector > m_objects; + + void findEmbeddedParts(const bodyPart& part, std::vector >& cidParts, std::vector >& 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/src/vmime/mailbox.cpp b/src/vmime/mailbox.cpp new file mode 100644 index 00000000..7c6d5e3b --- /dev/null +++ b/src/vmime/mailbox.cpp @@ -0,0 +1,510 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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; + + // Ignore blank spaces at the beginning + while (p < pend && parserHelpers::isSpace(*p)) ++p; + + // Current state for parsing machine + enum States + { + State_None, + State_Name, + State_Address + }; + + States state = State_Name; // let's start with name, we will see later (*) + + // Temporary buffers for extracted name and address + string name; + string address; + bool hadBrackets = false; + + while (p < pend) + { + if (state == State_Name) + { + if (*p == '<') + { + state = State_Address; + continue; + } + + if (*p == '"') // Quoted string + { + ++p; + + bool escaped = false; + + while (p < pend) + { + if (escaped) + { + name += *p; + escaped = false; + } + else if (*p == '\\') + { + escaped = true; + } + else + { + if (*p == '"') + { + ++p; + break; + } + else + { + name += *p; + } + } + + ++p; + } + } + else + { + bool escaped = false; + int comment = 0; + + while (p < pend) + { + if (escaped) + { + if (!comment) name += *p; + 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 == '<') + { + // Erase any space between display name and
+ string::iterator q = name.end(); + + while (q != name.begin() && parserHelpers::isSpace(*(q - 1))) + --q; + + name.erase(q, name.end()); + + break; + } + else if (/* parserHelpers::isSpace(*p) || */ *p == '@') + { + break; + } + else + { + name += *p; + } + + ++p; + } + } + + if (p < pend && *p == '@') + { + // (*) Actually, we were parsing the local-part of an address + // and not a display name... + address = name; + name.clear(); + + bool escaped = false; + int comment = 0; + + while (p < pend) + { + if (escaped) + { + if (!comment) address += *p; + 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 (parserHelpers::isSpace(*p)) + { + break; + } + else + { + address += *p; + } + + ++p; + } + + break; + } + else + { + while (p < pend && parserHelpers::isSpace(*p)) ++p; + state = State_None; + } + } + else if (state == State_Address) + { + // Skip '<' character + if (*p == '<') + ++p; + + bool escaped = false; + int comment = 0; + + while (p < pend) + { + if (escaped) + { + if (!comment) address += *p; + 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 == '<') + { + // 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! + name += address; + address.clear(); + } + else if (*p == '>') + { + hadBrackets = true; + break; + } + else if (!parserHelpers::isSpace(*p)) + { + address += *p; + } + + ++p; + } + + break; + } + else + { + while (p < pend && parserHelpers::isSpace(*p)) ++p; + + if (p < pend) + { + //if (*p == '<') + state = State_Address; + } + } + } + + // 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 " ; , < > ( ) @ / ? . = : + + // 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 '\r': + case '\n': + case '\t': + case ';': + case ',': + case '<': case '>': + case '(': case ')': + case '@': + case '/': + case '?': + case '.': + case '=': + case ':': + case '"': + + forceEncode = true; + break; + } + } + } + else + { + 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 (other); + + m_name = source.m_name; + m_email = source.m_email; +} + + +mailbox& mailbox::operator=(const mailbox& other) +{ + copyFrom(other); + return (*this); +} + + +shared_ptr mailbox::clone() const +{ + return make_shared (*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 > mailbox::getChildComponents() +{ + return std::vector >(); +} + + +} // vmime diff --git a/src/vmime/mailbox.hpp b/src/vmime/mailbox.hpp new file mode 100644 index 00000000..88abc0f5 --- /dev/null +++ b/src/vmime/mailbox.hpp @@ -0,0 +1,123 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + mailbox& operator=(const mailbox& other); + + bool isEmpty() const; + + void clear(); + + const std::vector > 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/src/vmime/mailboxField.cpp b/src/vmime/mailboxField.cpp new file mode 100644 index 00000000..29fe9d33 --- /dev/null +++ b/src/vmime/mailboxField.cpp @@ -0,0 +1,90 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 mbox = make_shared (); + + // 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
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 group = dynamicCast (parsedAddress); + + if (!group->isEmpty()) + mbox = group->getMailboxAt(0); + } + else + { + // Parse only if it is a mailbox + mbox = dynamicCast (parsedAddress); + } + } + + mbox->setParsedBounds(position, end); + + setValue(mbox); + + setParsedBounds(position, end); + + if (newPosition) + *newPosition = end; +} + + +} // vmime + + +#endif // VMIME_BUILDING_DOC + diff --git a/src/vmime/mailboxField.hpp b/src/vmime/mailboxField.hpp new file mode 100644 index 00000000..ca6863c0 --- /dev/null +++ b/src/vmime/mailboxField.hpp @@ -0,0 +1,68 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/mailboxGroup.cpp b/src/vmime/mailboxGroup.cpp new file mode 100644 index 00000000..5e8d6b1b --- /dev/null +++ b/src/vmime/mailboxGroup.cpp @@ -0,0 +1,377 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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
parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, &isLastAddressOfGroup); + + if (parsedAddress) + { + if (parsedAddress->isGroup()) + { + shared_ptr group = dynamicCast (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 (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 >::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 (other); + + m_name = source.m_name; + + removeAllMailboxes(); + + for (std::vector >::const_iterator it = source.m_list.begin() ; + it != source.m_list.end() ; ++it) + { + m_list.push_back(vmime::clone(*it)); + } +} + + +shared_ptr mailboxGroup::clone() const +{ + return make_shared (*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(shared_ptr mbox) +{ + m_list.push_back(mbox); +} + + +void mailboxGroup::insertMailboxBefore(shared_ptr beforeMailbox, shared_ptr mbox) +{ + const std::vector >::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, shared_ptr mbox) +{ + if (pos >= m_list.size()) + throw std::out_of_range("Invalid position"); + + m_list.insert(m_list.begin() + pos, mbox); +} + + +void mailboxGroup::insertMailboxAfter(shared_ptr afterMailbox, shared_ptr mbox) +{ + const std::vector >::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, shared_ptr 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(shared_ptr mbox) +{ + const std::vector >::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 >::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 mailboxGroup::getMailboxAt(const size_t pos) +{ + return (m_list[pos]); +} + + +const shared_ptr mailboxGroup::getMailboxAt(const size_t pos) const +{ + return (m_list[pos]); +} + + +const std::vector > mailboxGroup::getMailboxList() const +{ + std::vector > list; + + list.reserve(m_list.size()); + + for (std::vector >::const_iterator it = m_list.begin() ; + it != m_list.end() ; ++it) + { + list.push_back(*it); + } + + return (list); +} + + +const std::vector > mailboxGroup::getMailboxList() +{ + return (m_list); +} + + +const std::vector > mailboxGroup::getChildComponents() +{ + std::vector > list; + + copy_vector(m_list, list); + + return (list); + +} + + +} // vmime diff --git a/src/vmime/mailboxGroup.hpp b/src/vmime/mailboxGroup.hpp new file mode 100644 index 00000000..b264cf60 --- /dev/null +++ b/src/vmime/mailboxGroup.hpp @@ -0,0 +1,194 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + mailboxGroup& operator=(const component& other); + + const std::vector > 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(shared_ptr 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(shared_ptr beforeMailbox, shared_ptr 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, shared_ptr 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(shared_ptr afterMailbox, shared_ptr 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, shared_ptr 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(shared_ptr 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 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 getMailboxAt(const size_t pos) const; + + /** Return the mailbox list. + * + * @return list of mailboxes + */ + const std::vector > getMailboxList() const; + + /** Return the mailbox list. + * + * @return list of mailboxes + */ + const std::vector > getMailboxList(); + + bool isGroup() const; + +private: + + text m_name; + std::vector > 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/src/vmime/mailboxList.cpp b/src/vmime/mailboxList.cpp new file mode 100644 index 00000000..b356a1e7 --- /dev/null +++ b/src/vmime/mailboxList.cpp @@ -0,0 +1,230 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr mbox) +{ + m_list.appendAddress(mbox); +} + + +void mailboxList::insertMailboxBefore(shared_ptr beforeMailbox, shared_ptr mbox) +{ + m_list.insertAddressBefore(beforeMailbox, mbox); +} + + +void mailboxList::insertMailboxBefore(const size_t pos, shared_ptr mbox) +{ + m_list.insertAddressBefore(pos, mbox); +} + + +void mailboxList::insertMailboxAfter(shared_ptr afterMailbox, shared_ptr mbox) +{ + m_list.insertAddressAfter(afterMailbox, mbox); +} + + +void mailboxList::insertMailboxAfter(const size_t pos, shared_ptr mbox) +{ + m_list.insertAddressAfter(pos, mbox); +} + + +void mailboxList::removeMailbox(shared_ptr 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 mailboxList::getMailboxAt(const size_t pos) +{ + return dynamicCast (m_list.getAddressAt(pos)); +} + + +const shared_ptr mailboxList::getMailboxAt(const size_t pos) const +{ + return dynamicCast (m_list.getAddressAt(pos)); +} + + +const std::vector > mailboxList::getMailboxList() const +{ + const std::vector > addrList = m_list.getAddressList(); + std::vector > res; + + for (std::vector >::const_iterator it = addrList.begin() ; + it != addrList.end() ; ++it) + { + const shared_ptr mbox = dynamicCast (*it); + + if (mbox != NULL) + res.push_back(mbox); + } + + return (res); +} + + +const std::vector > mailboxList::getMailboxList() +{ + const std::vector > addrList = m_list.getAddressList(); + std::vector > res; + + for (std::vector >::const_iterator it = addrList.begin() ; + it != addrList.end() ; ++it) + { + const shared_ptr mbox = dynamicCast (*it); + + if (mbox != NULL) + res.push_back(mbox); + } + + return (res); +} + + +shared_ptr mailboxList::clone() const +{ + return make_shared (*this); +} + + +void mailboxList::copyFrom(const component& other) +{ + const mailboxList& mboxList = dynamic_cast (other); + + m_list = mboxList.m_list; +} + + +mailboxList& mailboxList::operator=(const mailboxList& other) +{ + copyFrom(other); + return (*this); +} + + +const std::vector > 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
parsedAddress = address::parseNext(ctx, buffer, pos, end, &pos, NULL); + + if (parsedAddress != NULL) + { + if (parsedAddress->isGroup()) + { + shared_ptr group = dynamicCast (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 mailboxList::toAddressList() const +{ + return vmime::clone(m_list); +} + + +} // vmime + diff --git a/src/vmime/mailboxList.hpp b/src/vmime/mailboxList.hpp new file mode 100644 index 00000000..125c238e --- /dev/null +++ b/src/vmime/mailboxList.hpp @@ -0,0 +1,184 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + void copyFrom(const component& other); + mailboxList& operator=(const mailboxList& other); + + const std::vector > getChildComponents(); + + /** Add a mailbox at the end of the list. + * + * @param mbox mailbox to append + */ + void appendMailbox(shared_ptr 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(shared_ptr beforeMailbox, shared_ptr 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, shared_ptr 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(shared_ptr afterMailbox, shared_ptr 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, shared_ptr 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(shared_ptr 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 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 getMailboxAt(const size_t pos) const; + + /** Return the mailbox list. + * + * @return list of mailboxes + */ + const std::vector > getMailboxList() const; + + /** Return the mailbox list. + * + * @return list of mailboxes + */ + const std::vector > getMailboxList(); + + /** Return a list of addresses. + * + * @return list of addresses + */ + shared_ptr 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/src/vmime/mdn/MDNHelper.cpp b/src/vmime/mdn/MDNHelper.cpp new file mode 100644 index 00000000..1205aef2 --- /dev/null +++ b/src/vmime/mdn/MDNHelper.cpp @@ -0,0 +1,353 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr msg, const mailboxList& mailboxes) +{ + shared_ptr
hdr = msg->getHeader(); + + hdr->DispositionNotificationTo()->setValue(mailboxes); +} + + +void MDNHelper::attachMDNRequest(shared_ptr msg, const mailbox& mbox) +{ + mailboxList mboxList; + mboxList.appendMailbox(vmime::clone(mbox)); + + attachMDNRequest(msg, mboxList); +} + + +const std::vector MDNHelper::getPossibleMDNs(const shared_ptr msg) +{ + std::vector result; + + const shared_ptr hdr = msg->getHeader(); + + if (hdr->hasField(fields::DISPOSITION_NOTIFICATION_TO)) + { + const mailboxList& dnto = + *hdr->DispositionNotificationTo()->getValue (); + + 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 msg) +{ + const shared_ptr 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 (hdr->ContentType()); + + const mediaType type = *ctf.getValue (); + + 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 msg) +{ + if (!isMDN(msg)) + throw exceptions::invalid_argument(); + + return receivedMDNInfos(msg); +} + + +bool MDNHelper::needConfirmation(const shared_ptr msg) +{ + shared_ptr 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 (); + + 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 (); + + if (mbox.getEmail() != rp.getLocalPart() + "@" + rp.getDomain()) + return true; + } + + // User confirmation not needed + return false; +} + + +shared_ptr MDNHelper::buildMDN(const sendableMDNInfos& mdnInfos, + const string& text, + const charset& ch, + const mailbox& expeditor, + const disposition& dispo, + const string& reportingUA, + const std::vector & reportingUAProducts, + const std::map & fields) +{ + // Create a new message + shared_ptr msg = make_shared (); + + // Fill-in header fields + shared_ptr
hdr = msg->getHeader(); + + hdr->ContentType()->setValue(mediaType(vmime::mediaTypes::MULTIPART, + vmime::mediaTypes::MULTIPART_REPORT)); + dynamicCast (hdr->ContentType())->setReportType("disposition-notification"); + + hdr->Disposition()->setValue(dispo); + + addressList to; + to.appendAddress(make_shared (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 MDNHelper::createFirstMDNPart(const sendableMDNInfos& /* mdnInfos */, + const string& text, const charset& ch) +{ + shared_ptr part = make_shared (); + + // Header + shared_ptr
hdr = part->getHeader(); + + hdr->ContentType()->setValue(mediaType(vmime::mediaTypes::TEXT, + vmime::mediaTypes::TEXT_PLAIN)); + + dynamicCast (hdr->ContentType())->setCharset(ch); + + // Body + part->getBody()->setContents(make_shared (text)); + + return (part); +} + + +shared_ptr MDNHelper::createSecondMDNPart(const sendableMDNInfos& mdnInfos, + const disposition& dispo, + const string& reportingUA, + const std::vector & reportingUAProducts, + const std::map & additionalFields) +{ + shared_ptr part = make_shared (); + + // Header + shared_ptr
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 rua = headerFieldFactory::getInstance()-> + create(vmime::fields::REPORTING_UA); + + rua->setValue(ruaText); + + fields.appendField(rua); + } + + // -- Final-Recipient + shared_ptr 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 ::const_iterator it; + + if (additionalFields.size() > 0) + { + it = additionalFields.find(vmime::fields::ERROR); + if (it != additionalFields.end()) + { + shared_ptr error = headerFieldFactory::getInstance()-> + create(vmime::fields::ERROR); + error->setValue(it->second); + fields.appendField(error); + } + + it = additionalFields.find(vmime::fields::WARNING); + if (it != additionalFields.end()) + { + shared_ptr warn = headerFieldFactory::getInstance()-> + create(vmime::fields::WARNING); + warn->setValue(it->second); + fields.appendField(warn); + } + + it = additionalFields.find(vmime::fields::FAILURE); + if (it != additionalFields.end()) + { + shared_ptr 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 (oss.str())); + + return (part); +} + + +shared_ptr MDNHelper::createThirdMDNPart(const sendableMDNInfos& mdnInfos) +{ + shared_ptr part = make_shared (); + + // Header + shared_ptr
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 (oss.str())); + + return (part); +} + + +} // mdn +} // vmime diff --git a/src/vmime/mdn/MDNHelper.hpp b/src/vmime/mdn/MDNHelper.hpp new file mode 100644 index 00000000..2584978f --- /dev/null +++ b/src/vmime/mdn/MDNHelper.hpp @@ -0,0 +1,139 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr 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(shared_ptr 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 getPossibleMDNs(const shared_ptr 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 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 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 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 buildMDN(const sendableMDNInfos& mdnInfos, + const string& text, + const charset& ch, + const mailbox& expeditor, + const disposition& dispo, + const string& reportingUA = NULL_STRING, + const std::vector & reportingUAProducts + = std::vector (), + const std::map & fields + = (std::map ())); + +private: + + static shared_ptr createFirstMDNPart(const sendableMDNInfos& mdnInfos, + const string& text, const charset& ch); + + static shared_ptr createSecondMDNPart(const sendableMDNInfos& mdnInfos, + const disposition& dispo, + const string& reportingUA, + const std::vector & reportingUAProducts, + const std::map & fields); + + + static shared_ptr createThirdMDNPart(const sendableMDNInfos& mdnInfos); +}; + + +} // mdn +} // vmime + + +#endif // VMIME_MDN_MDNHELPER_HPP_INCLUDED diff --git a/src/vmime/mdn/MDNInfos.cpp b/src/vmime/mdn/MDNInfos.cpp new file mode 100644 index 00000000..a70161b7 --- /dev/null +++ b/src/vmime/mdn/MDNInfos.cpp @@ -0,0 +1,38 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/mdn/MDNInfos.hpp b/src/vmime/mdn/MDNInfos.hpp new file mode 100644 index 00000000..030aa23e --- /dev/null +++ b/src/vmime/mdn/MDNInfos.hpp @@ -0,0 +1,58 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 getMessage() const = 0; +}; + + +} // mdn +} // vmime + + +#endif // VMIME_MDN_MDNINFOS_HPP_INCLUDED diff --git a/src/vmime/mdn/receivedMDNInfos.cpp b/src/vmime/mdn/receivedMDNInfos.cpp new file mode 100644 index 00000000..53b2281e --- /dev/null +++ b/src/vmime/mdn/receivedMDNInfos.cpp @@ -0,0 +1,136 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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 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 bdy = m_msg->getBody(); + + for (size_t i = 0 ; i < bdy->getPartCount() ; ++i) + { + const shared_ptr part = bdy->getPartAt(i); + + if (!part->getHeader()->hasField(fields::CONTENT_TYPE)) + continue; + + const mediaType& type = *part->getHeader()->ContentType()->getValue (); + + // 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 omid = + fields.findFieldValue (fields::ORIGINAL_MESSAGE_ID); + + if (omid) + m_omid = *omid; + + shared_ptr disp = + fields.findFieldValue (fields::DISPOSITION); + + if (disp) + m_disp = *disp; + + shared_ptr contentMIC = + fields.findFieldValue ("Received-content-MIC"); + + if (contentMIC) + m_contentMIC = contentMIC->generate(); + } + } +} + + +} // mdn +} // vmime diff --git a/src/vmime/mdn/receivedMDNInfos.hpp b/src/vmime/mdn/receivedMDNInfos.hpp new file mode 100644 index 00000000..c6953a24 --- /dev/null +++ b/src/vmime/mdn/receivedMDNInfos.hpp @@ -0,0 +1,94 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 msg); + receivedMDNInfos(const receivedMDNInfos& other); + + receivedMDNInfos& operator=(const receivedMDNInfos& other); + + + const shared_ptr 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 m_msg; + + disposition m_disp; + messageId m_omid; + string m_contentMIC; +}; + + +} // mdn +} // vmime + + +#endif // VMIME_MDN_RECEIVEDMDNINFOS_HPP_INCLUDED diff --git a/src/vmime/mdn/sendableMDNInfos.cpp b/src/vmime/mdn/sendableMDNInfos.cpp new file mode 100644 index 00000000..c145c3b6 --- /dev/null +++ b/src/vmime/mdn/sendableMDNInfos.cpp @@ -0,0 +1,71 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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 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/src/vmime/mdn/sendableMDNInfos.hpp b/src/vmime/mdn/sendableMDNInfos.hpp new file mode 100644 index 00000000..e4f6d20d --- /dev/null +++ b/src/vmime/mdn/sendableMDNInfos.hpp @@ -0,0 +1,73 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 msg, const mailbox& mbox); + sendableMDNInfos(const sendableMDNInfos& other); + + sendableMDNInfos& operator=(const sendableMDNInfos& other); + + const shared_ptr 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 m_msg; + mailbox m_mailbox; +}; + + +} // mdn +} // vmime + + +#endif // VMIME_MDN_SENDABLEMDNINFOS_HPP_INCLUDED diff --git a/src/vmime/mediaType.cpp b/src/vmime/mediaType.cpp new file mode 100644 index 00000000..60486da7 --- /dev/null +++ b/src/vmime/mediaType.cpp @@ -0,0 +1,187 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 mediaType::clone() const +{ + return make_shared (m_type, m_subType); +} + + +void mediaType::copyFrom(const component& other) +{ + const mediaType& mt = dynamic_cast (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 > mediaType::getChildComponents() +{ + return std::vector >(); +} + + +} // vmime diff --git a/src/vmime/mediaType.hpp b/src/vmime/mediaType.hpp new file mode 100644 index 00000000..a7d6f4e4 --- /dev/null +++ b/src/vmime/mediaType.hpp @@ -0,0 +1,119 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + void copyFrom(const component& other); + mediaType& operator=(const mediaType& other); + + const std::vector > 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/src/vmime/message.cpp b/src/vmime/message.cpp new file mode 100644 index 00000000..76735496 --- /dev/null +++ b/src/vmime/message.cpp @@ -0,0 +1,48 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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/src/vmime/message.hpp b/src/vmime/message.hpp new file mode 100644 index 00000000..62ff77e1 --- /dev/null +++ b/src/vmime/message.hpp @@ -0,0 +1,62 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/messageAttachment.hpp b/src/vmime/messageAttachment.hpp new file mode 100644 index 00000000..641fd3e1 --- /dev/null +++ b/src/vmime/messageAttachment.hpp @@ -0,0 +1,55 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 getMessage() const = 0; +}; + + +} // vmime + + +#endif // VMIME_MESSAGEATTACHMENT_HPP_INCLUDED + diff --git a/src/vmime/messageBuilder.cpp b/src/vmime/messageBuilder.cpp new file mode 100644 index 00000000..64880483 --- /dev/null +++ b/src/vmime/messageBuilder.cpp @@ -0,0 +1,329 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 messageBuilder::construct() const +{ + // Create a new message + shared_ptr msg = make_shared (); + + // 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 subPart = make_shared (); + 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 >::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 bodyCopy = vmime::clone(part.getBody()); + + // First, copy (and replace) the header fields + const std::vector > fields = part.getHeader()->getFieldList(); + + for (std::vector >::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(shared_ptr attach) +{ + appendAttachment(attach); +} + + +void messageBuilder::appendAttachment(shared_ptr attach) +{ + m_attach.push_back(attach); +} + + +void messageBuilder::constructTextPart(const mediaType& type) +{ + shared_ptr part; + + try + { + part = textPartFactory::getInstance()->create(type); + } + catch (exceptions::no_factory_available& e) + { + throw; + } + + m_textPart = part; +} + + +shared_ptr 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 messageBuilder::getAttachmentAt(const size_t pos) const +{ + return (m_attach[pos]); +} + + +shared_ptr messageBuilder::getAttachmentAt(const size_t pos) +{ + return (m_attach[pos]); +} + + +size_t messageBuilder::getAttachmentCount() const +{ + return (m_attach.size()); +} + + +const std::vector > messageBuilder::getAttachmentList() const +{ + std::vector > res; + + res.reserve(m_attach.size()); + + for (std::vector >::const_iterator it = m_attach.begin() ; + it != m_attach.end() ; ++it) + { + res.push_back(*it); + } + + return (res); +} + + +const std::vector > messageBuilder::getAttachmentList() +{ + return (m_attach); +} + + +} // vmime diff --git a/src/vmime/messageBuilder.hpp b/src/vmime/messageBuilder.hpp new file mode 100644 index 00000000..af86e826 --- /dev/null +++ b/src/vmime/messageBuilder.hpp @@ -0,0 +1,223 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr attach); + + /** Attach a new object to the message. + * + * @param attach new attachment + */ + void appendAttachment(shared_ptr 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 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 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 > getAttachmentList() const; + + /** Return the list of attachments. + * + * @return list of attachments + */ + const std::vector > 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 getTextPart(); + + /** Construct a new message based on the information specified + * in this object. + * + * @return a new message + */ + shared_ptr construct() const; + +private: + + mailbox m_from; + + addressList m_to; + addressList m_cc; + addressList m_bcc; + + text m_subject; + + shared_ptr m_textPart; + + std::vector > m_attach; +}; + + +} // vmime + + +#endif // VMIME_MESSAGEBUILDER_HPP_INCLUDED diff --git a/src/vmime/messageId.cpp b/src/vmime/messageId.cpp new file mode 100644 index 00000000..edc4d1fb --- /dev/null +++ b/src/vmime/messageId.cpp @@ -0,0 +1,300 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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::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 mid = make_shared (); + mid->parse(ctx, buffer, begin, pos, NULL); + + if (newPosition != NULL) + *newPosition = pos; + + return (mid); + } + + if (newPosition != NULL) + *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 (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 messageId::clone() const +{ + return make_shared (*this); +} + + +void messageId::copyFrom(const component& other) +{ + const messageId& mid = dynamic_cast (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 > messageId::getChildComponents() +{ + return std::vector >(); +} + + +} // vmime diff --git a/src/vmime/messageId.hpp b/src/vmime/messageId.hpp new file mode 100644 index 00000000..83527468 --- /dev/null +++ b/src/vmime/messageId.hpp @@ -0,0 +1,143 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + void copyFrom(const component& other); + messageId& operator=(const messageId& other); + + const std::vector > 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 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/src/vmime/messageIdSequence.cpp b/src/vmime/messageIdSequence.cpp new file mode 100644 index 00000000..23b12773 --- /dev/null +++ b/src/vmime/messageIdSequence.cpp @@ -0,0 +1,252 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime +{ + + + + +messageIdSequence::messageIdSequence() +{ +} + + +messageIdSequence::~messageIdSequence() +{ + removeAllMessageIds(); +} + + +messageIdSequence::messageIdSequence(const messageIdSequence& midSeq) + : headerFieldValue() +{ + copyFrom(midSeq); +} + + +shared_ptr messageIdSequence::clone() const +{ + return make_shared (*this); +} + + +void messageIdSequence::copyFrom(const component& other) +{ + const messageIdSequence& midSeq = dynamic_cast (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 > messageIdSequence::getChildComponents() +{ + std::vector > 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 parsedMid = messageId::parseNext(ctx, buffer, pos, end, &pos); + + if (parsedMid != NULL) + 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 >::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(shared_ptr mid) +{ + m_list.push_back(mid); +} + + +void messageIdSequence::insertMessageIdBefore(shared_ptr beforeMid, shared_ptr mid) +{ + const std::vector >::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, shared_ptr mid) +{ + m_list.insert(m_list.begin() + pos, mid); +} + + +void messageIdSequence::insertMessageIdAfter(shared_ptr afterMid, shared_ptr mid) +{ + const std::vector >::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, shared_ptr mid) +{ + m_list.insert(m_list.begin() + pos + 1, mid); +} + + +void messageIdSequence::removeMessageId(shared_ptr mid) +{ + const std::vector >::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 >::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 messageIdSequence::getMessageIdAt(const size_t pos) +{ + return (m_list[pos]); +} + + +const shared_ptr messageIdSequence::getMessageIdAt(const size_t pos) const +{ + return (m_list[pos]); +} + + +const std::vector > messageIdSequence::getMessageIdList() const +{ + std::vector > list; + + list.reserve(m_list.size()); + + for (std::vector >::const_iterator it = m_list.begin() ; + it != m_list.end() ; ++it) + { + list.push_back(*it); + } + + return (list); +} + + +const std::vector > messageIdSequence::getMessageIdList() +{ + return (m_list); +} + + +} // vmime diff --git a/src/vmime/messageIdSequence.hpp b/src/vmime/messageIdSequence.hpp new file mode 100644 index 00000000..07f0c422 --- /dev/null +++ b/src/vmime/messageIdSequence.hpp @@ -0,0 +1,172 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + void copyFrom(const component& other); + messageIdSequence& operator=(const messageIdSequence& other); + + const std::vector > getChildComponents(); + + + /** Add a message-id at the end of the list. + * + * @param mid message-id to append + */ + void appendMessageId(shared_ptr 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(shared_ptr beforeMid, shared_ptr 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, shared_ptr 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(shared_ptr afterMid, shared_ptr 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, shared_ptr 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(shared_ptr 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 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 getMessageIdAt(const size_t pos) const; + + /** Return the message-id list. + * + * @return list of message-ids + */ + const std::vector > getMessageIdList() const; + + /** Return the message-id list. + * + * @return list of message-ids + */ + const std::vector > getMessageIdList(); + +private: + + std::vector > 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/src/vmime/messageParser.cpp b/src/vmime/messageParser.cpp new file mode 100644 index 00000000..5fe219f3 --- /dev/null +++ b/src/vmime/messageParser.cpp @@ -0,0 +1,322 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 msg = make_shared (); + msg->parse(buffer); + + parse(msg); +} + + +messageParser::messageParser(shared_ptr msg) +{ + parse(msg); +} + + +messageParser::~messageParser() +{ +} + + +void messageParser::parse(shared_ptr 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 fldValue = msg->getHeader()->findFieldValue (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 recv = msg->getHeader()->findField(fields::RECEIVED); + + if (recv) + { + m_date = recv->getValue ()->getDate(); + } + else + { + shared_ptr date = msg->getHeader()->findField(fields::DATE); + + if (date) + m_date = *date->getValue (); + else + m_date = datetime::now(); + } + + // Attachments + findAttachments(msg); + + // Text parts + findTextParts(msg, msg); +} + + +void messageParser::findAttachments(shared_ptr msg) +{ + m_attach = attachmentHelper::findAttachmentsInMessage(msg); +} + + +void messageParser::findTextParts(shared_ptr msg, shared_ptr 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 ctf = + msg->getHeader()->findField (fields::CONTENT_TYPE); + + if (ctf) + { + const mediaType ctfType = *ctf->getValue (); + + if (ctfType.getType() == mediaTypes::TEXT) + { + type = ctfType; + accept = true; + } + } + else + { + // No "Content-type" field: assume "text/plain". + accept = true; + } + + if (accept) + { + shared_ptr txtPart = textPartFactory::getInstance()->create(type); + txtPart->parse(msg, msg, msg); + + m_textParts.push_back(txtPart); + } + } + // Multipart message + else + { + findSubTextParts(msg, part); + } +} + + +bool messageParser::findSubTextParts(shared_ptr msg, shared_ptr 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 > textParts; + + for (size_t i = 0 ; i < part->getBody()->getPartCount() ; ++i) + { + const shared_ptr p = part->getBody()->getPartAt(i); + + shared_ptr ctf = + p->getHeader()->findField (fields::CONTENT_TYPE); + + if (ctf) + { + const mediaType type = *ctf->getValue (); + contentDisposition disp; // default should be inline + + if (type.getType() == mediaTypes::TEXT) + { + shared_ptr cdf = p->getHeader()-> + findField (fields::CONTENT_DISPOSITION); + + if (cdf) + { + disp = *cdf->getValue (); + } + 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 >::const_iterator p = textParts.begin() ; + p != textParts.end() ; ++p) + { + const contentTypeField& ctf = + *(*p)->getHeader()->findField (fields::CONTENT_TYPE); + + const mediaType type = *ctf.getValue (); + + try + { + shared_ptr 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 > messageParser::getAttachmentList() const +{ + return m_attach; +} + + +size_t messageParser::getAttachmentCount() const +{ + return (m_attach.size()); +} + + +const shared_ptr messageParser::getAttachmentAt(const size_t pos) const +{ + return (m_attach[pos]); +} + + +const std::vector > messageParser::getTextPartList() const +{ + std::vector > res; + + res.reserve(m_textParts.size()); + + for (std::vector >::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 messageParser::getTextPartAt(const size_t pos) const +{ + return (m_textParts[pos]); +} + + +} // vmime diff --git a/src/vmime/messageParser.hpp b/src/vmime/messageParser.hpp new file mode 100644 index 00000000..c3a48f11 --- /dev/null +++ b/src/vmime/messageParser.hpp @@ -0,0 +1,159 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr 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 getAttachmentAt(const size_t pos) const; + + /** Return the attachments of the message. + * + * @return list of attachments in the message + */ + const std::vector > getAttachmentList() const; + + /** Return the text parts of the message. + * + * @return list of text parts in the message + */ + const std::vector > 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 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 > m_attach; + + std::vector > m_textParts; + + void parse(shared_ptr msg); + + void findAttachments(shared_ptr msg); + + void findTextParts(shared_ptr msg, shared_ptr part); + bool findSubTextParts(shared_ptr msg, shared_ptr part); +}; + + +} // vmime + + +#endif // VMIME_MESSAGEPARSER_HPP_INCLUDED diff --git a/src/vmime/misc/importanceHelper.cpp b/src/vmime/misc/importanceHelper.cpp new file mode 100644 index 00000000..b13f7466 --- /dev/null +++ b/src/vmime/misc/importanceHelper.cpp @@ -0,0 +1,162 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr msg) +{ + resetImportanceHeader(msg->getHeader()); +} + + +void importanceHelper::resetImportanceHeader(shared_ptr
hdr) +{ + shared_ptr fld; + + if ((fld = hdr->findField("X-Priority"))) + hdr->removeField(fld); + + if ((fld = hdr->findField("Importance"))) + hdr->removeField(fld); +} + + +importanceHelper::Importance importanceHelper::getImportance(shared_ptr msg) +{ + return getImportanceHeader(msg->getHeader()); +} + + +importanceHelper::Importance importanceHelper::getImportanceHeader(shared_ptr hdr) +{ + // Try "X-Priority" field + shared_ptr fld = hdr->findField("X-Priority"); + + if (fld) + { + const string value = fld->getValue ()->getWholeBuffer(); + + int n = IMPORTANCE_NORMAL; + + std::istringstream iss(value); + 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 ()->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(shared_ptr msg, const Importance i) +{ + setImportanceHeader(msg->getHeader(), i); +} + + +void importanceHelper::setImportanceHeader(shared_ptr
hdr, const Importance i) +{ + // "X-Priority:" Field + shared_ptr 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/src/vmime/misc/importanceHelper.hpp b/src/vmime/misc/importanceHelper.hpp new file mode 100644 index 00000000..ae8297fc --- /dev/null +++ b/src/vmime/misc/importanceHelper.hpp @@ -0,0 +1,105 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr msg); + + /** Reset the importance of a message to the default importance. + * + * @param hdr message header on which to reset importance + */ + static void resetImportanceHeader(shared_ptr
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(shared_ptr 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(shared_ptr hdr); + + /** Set the importance of the specified message. + * + * @param msg message on which to set importance + * @param i new message importance + */ + static void setImportance(shared_ptr 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(shared_ptr
hdr, const Importance i); +}; + + +} // misc +} // vmime + + +#endif // VMIME_MISC_IMPORTANCEHELPER_HPP_INCLUDED diff --git a/src/vmime/net/builtinServices.inl b/src/vmime/net/builtinServices.inl new file mode 100644 index 00000000..fa2f3fe3 --- /dev/null +++ b/src/vmime/net/builtinServices.inl @@ -0,0 +1,76 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/connectionInfos.hpp b/src/vmime/net/connectionInfos.hpp new file mode 100644 index 00000000..6c86eeab --- /dev/null +++ b/src/vmime/net/connectionInfos.hpp @@ -0,0 +1,68 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/defaultConnectionInfos.cpp b/src/vmime/net/defaultConnectionInfos.cpp new file mode 100644 index 00000000..335e8f6f --- /dev/null +++ b/src/vmime/net/defaultConnectionInfos.cpp @@ -0,0 +1,60 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/defaultConnectionInfos.hpp b/src/vmime/net/defaultConnectionInfos.hpp new file mode 100644 index 00000000..50673bbc --- /dev/null +++ b/src/vmime/net/defaultConnectionInfos.hpp @@ -0,0 +1,66 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/events.cpp b/src/vmime/net/events.cpp new file mode 100644 index 00000000..a19e1738 --- /dev/null +++ b/src/vmime/net/events.cpp @@ -0,0 +1,166 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace net { +namespace events { + + +// +// event +// + +event::event() +{ +} + + +event::~event() +{ +} + + +// +// messageCountEvent +// + +const char* messageCountEvent::EVENT_CLASS = "messageCountEvent"; + + +messageCountEvent::messageCountEvent + (shared_ptr folder, const Types type, const std::vector & nums) + : m_folder(folder), m_type(type) +{ + m_nums.resize(nums.size()); + std::copy(nums.begin(), nums.end(), m_nums.begin()); +} + + +shared_ptr messageCountEvent::getFolder() const { return (m_folder); } +messageCountEvent::Types messageCountEvent::getType() const { return (m_type); } +const std::vector & messageCountEvent::getNumbers() const { return (m_nums); } + + +void messageCountEvent::dispatch(messageCountListener* listener) +{ + if (m_type == TYPE_ADDED) + listener->messagesAdded(dynamicCast (shared_from_this())); + else + listener->messagesRemoved(dynamicCast (shared_from_this())); +} + + +const char* messageCountEvent::getClass() const +{ + return EVENT_CLASS; +} + + +// +// messageChangedEvent +// + +const char* messageChangedEvent::EVENT_CLASS = "messageChangedEvent"; + + +messageChangedEvent::messageChangedEvent + (shared_ptr folder, const Types type, const std::vector & nums) + : m_folder(folder), m_type(type) +{ + m_nums.resize(nums.size()); + std::copy(nums.begin(), nums.end(), m_nums.begin()); +} + + +shared_ptr messageChangedEvent::getFolder() const { return (m_folder); } +messageChangedEvent::Types messageChangedEvent::getType() const { return (m_type); } +const std::vector & messageChangedEvent::getNumbers() const { return (m_nums); } + + +void messageChangedEvent::dispatch(messageChangedListener* listener) +{ + listener->messageChanged(dynamicCast (shared_from_this())); +} + + +const char* messageChangedEvent::getClass() const +{ + return EVENT_CLASS; +} + + +// +// folderEvent +// + +const char* folderEvent::EVENT_CLASS = "folderEvent"; + + +folderEvent::folderEvent + (shared_ptr 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 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 (shared_from_this())); break; + case TYPE_RENAMED: listener->folderRenamed(dynamicCast (shared_from_this())); break; + case TYPE_DELETED: listener->folderDeleted(dynamicCast (shared_from_this())); break; + } +} + + +const char* folderEvent::getClass() const +{ + return EVENT_CLASS; +} + + +} // events +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + diff --git a/src/vmime/net/events.hpp b/src/vmime/net/events.hpp new file mode 100644 index 00000000..a3e952d4 --- /dev/null +++ b/src/vmime/net/events.hpp @@ -0,0 +1,273 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#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: + + 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(shared_ptr folder, const Types type, const std::vector & nums); + + /** Return the folder in which messages have been added/removed. + * + * @return folder in which message count changed + */ + shared_ptr 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 & 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 m_folder; + const Types m_type; + std::vector m_nums; +}; + + +/** Listener for events about the message count in a folder. + */ + +class VMIME_EXPORT messageCountListener +{ +protected: + + virtual ~messageCountListener() { } + +public: + + virtual void messagesAdded(shared_ptr event) = 0; + virtual void messagesRemoved(shared_ptr 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(shared_ptr folder, const Types type, const std::vector & nums); + + /** Return the folder in which messages have changed. + * + * @return folder in which message count changed + */ + shared_ptr 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 & 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 m_folder; + const Types m_type; + std::vector m_nums; +}; + + +/** Listener for events occuring on a message. + */ + +class VMIME_EXPORT messageChangedListener +{ +protected: + + virtual ~messageChangedListener() { } + +public: + + virtual void messageChanged(shared_ptr 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(shared_ptr folder, const Types type, const utility::path& oldPath, const utility::path& newPath); + + /** Return the folder on which the event occured. + * + * @return folder on which the event occured + */ + shared_ptr 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 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(shared_ptr event) = 0; + virtual void folderRenamed(shared_ptr event) = 0; + virtual void folderDeleted(shared_ptr event) = 0; +}; + + +} // events +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_NET_EVENTS_HPP_INCLUDED diff --git a/src/vmime/net/fetchAttributes.cpp b/src/vmime/net/fetchAttributes.cpp new file mode 100644 index 00000000..85a41b8c --- /dev/null +++ b/src/vmime/net/fetchAttributes.cpp @@ -0,0 +1,95 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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 fetchAttributes::getHeaderFields() const +{ + return m_headers; +} + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES diff --git a/src/vmime/net/fetchAttributes.hpp b/src/vmime/net/fetchAttributes.hpp new file mode 100644 index 00000000..d01e9f50 --- /dev/null +++ b/src/vmime/net/fetchAttributes.hpp @@ -0,0 +1,142 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#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 getHeaderFields() const; + +private: + + int m_predefinedAttribs; + std::vector m_headers; +}; + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + + +#endif // VMIME_NET_FETCHATTRIBUTES_HPP_INCLUDED diff --git a/src/vmime/net/folder.cpp b/src/vmime/net/folder.cpp new file mode 100644 index 00000000..1d6f3140 --- /dev/null +++ b/src/vmime/net/folder.cpp @@ -0,0 +1,127 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace net { + + +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(shared_ptr event) +{ + for (std::list ::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(shared_ptr event) +{ + for (std::list ::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(shared_ptr event) +{ + for (std::list ::iterator + it = m_folderListeners.begin() ; it != m_folderListeners.end() ; ++it) + { + event->dispatch(*it); + } +} + + +void folder::notifyEvent(shared_ptr event) +{ + if (event->getClass() == events::messageCountEvent::EVENT_CLASS) + { + notifyMessageCount(dynamicCast (event)); + } + else if (event->getClass() == events::messageChangedEvent::EVENT_CLASS) + { + notifyMessageChanged(dynamicCast (event)); + } + else if (event->getClass() == events::folderEvent::EVENT_CLASS) + { + notifyFolder(dynamicCast (event)); + } +} + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + diff --git a/src/vmime/net/folder.hpp b/src/vmime/net/folder.hpp new file mode 100644 index 00000000..38ba4597 --- /dev/null +++ b/src/vmime/net/folder.hpp @@ -0,0 +1,399 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#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/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 +{ +protected: + + folder(const folder&) : object() { } + folder() { } + +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). */ + }; + + /** Folder types. + */ + enum Types + { + TYPE_CONTAINS_FOLDERS = (1 << 0), /**< Folder can contain folders. */ + TYPE_CONTAINS_MESSAGES = (1 << 1), /**< Folder can contain messages. */ + + TYPE_UNDEFINED = 9999 /**< Used internally (this should not be returned + by the type() function). */ + }; + + /** Folder flags. + */ + enum Flags + { + FLAG_CHILDREN = (1 << 0), /**< Folder contains subfolders. */ + FLAG_NO_OPEN = (1 << 1), /**< Folder cannot be open. */ + + FLAG_UNDEFINED = 9999 /**< Used internally (this should not be returned + by the type() function). */ + }; + + /** Return the type of this folder. + * + * @return folder type (see folder::Types) + */ + virtual int getType() = 0; + + /** Return the flags of this folder. + * + * @return folder flags (see folder::Flags) + */ + virtual int getFlags() = 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 type folder type (see folder::Types) + * @throw exceptions::net_exception if an error occurs + */ + virtual void create(const int type) = 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 getMessage(const int 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 > getMessages(const messageSet& msgs) = 0; + + /** Return the number of messages in this folder. + * + * @return number of messages in the folder + */ + virtual int 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 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 > 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 + * @param date date/time for the new message (if NULL, the current time is used) + * @param progress progress listener, or NULL if not used + * @throw exceptions::net_exception if an error occurs + */ + virtual void addMessage(shared_ptr msg, const int flags = message::FLAG_UNDEFINED, 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 + * @param date date/time for the new message (if NULL, the current time is used) + * @param progress progress listener, or NULL if not used + * @throw exceptions::net_exception if an error occurs + */ + virtual void addMessage(utility::inputStream& is, const size_t size, const int flags = message::FLAG_UNDEFINED, 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 + * @throw exceptions::net_exception if an error occurs + */ + virtual void 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(int& count, int& unseen) = 0; + + /** Request folder status without opening it. + * + * @return current folder status + * @throw exceptions::net_exception if an error occurs + */ + virtual shared_ptr 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 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 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 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 >& 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(shared_ptr msg, 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 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(shared_ptr event); + void notifyMessageCount(shared_ptr event); + void notifyFolder(shared_ptr event); + void notifyEvent(shared_ptr event); + +private: + + std::list m_messageChangedListeners; + std::list m_messageCountListeners; + std::list m_folderListeners; +}; + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_NET_FOLDER_HPP_INCLUDED diff --git a/src/vmime/net/folderStatus.hpp b/src/vmime/net/folderStatus.hpp new file mode 100644 index 00000000..b94db052 --- /dev/null +++ b/src/vmime/net/folderStatus.hpp @@ -0,0 +1,74 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 unsigned int getMessageCount() const = 0; + + /** Returns the number of unseen messages in the folder. + * + * @return number of unseen messages + */ + virtual unsigned int getUnseenCount() const = 0; + + /** Clones this object. + * + * @return a copy of this object + */ + virtual shared_ptr clone() const = 0; +}; + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_NET_FOLDERSTATUS_HPP_INCLUDED diff --git a/src/vmime/net/imap/IMAPConnection.cpp b/src/vmime/net/imap/IMAPConnection.cpp new file mode 100644 index 00000000..234c2b6a --- /dev/null +++ b/src/vmime/net/imap/IMAPConnection.cpp @@ -0,0 +1,814 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/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 + + +// Helpers for service properties +#define GET_PROPERTY(type, prop) \ + (m_store.lock()->getInfos().getPropertyValue (getSession(), \ + dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) +#define HAS_PROPERTY(prop) \ + (m_store.lock()->getInfos().hasProperty(getSession(), \ + dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) + + +namespace vmime { +namespace net { +namespace imap { + + +IMAPConnection::IMAPConnection(shared_ptr store, shared_ptr 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) +{ +} + + +IMAPConnection::~IMAPConnection() +{ + try + { + if (isConnected()) + disconnect(); + else if (m_socket) + internalDisconnect(); + } + catch (vmime::exception&) + { + // Ignore + } +} + + +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 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); + +#if VMIME_HAVE_TLS_SUPPORT + if (store->isIMAPS()) // dedicated port/IMAPS + { + shared_ptr tlsSession = tls::TLSSession::create + (store->getCertificateVerifier(), + store->getSession()->getTLSProperties()); + + shared_ptr tlsSocket = + tlsSession->getSocket(m_socket); + + m_socket = tlsSocket; + + m_secured = true; + m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); + } + else +#endif // VMIME_HAVE_TLS_SUPPORT + { + m_cntInfos = make_shared (address, port); + } + + m_socket->connect(address, port); + + + m_tag = make_shared (); + m_parser = make_shared (m_tag, m_socket, m_timeoutHandler); + + + setState(STATE_NON_AUTHENTICATED); + + + // Connection greeting + // + // eg: C: + // --- S: * OK mydomain.org IMAP4rev1 v12.256 server ready + + std::auto_ptr 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()); + } + +#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& e) + { + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) + { + // Can't fallback on normal authentication + internalDisconnect(); + throw e; + } + else + { + // Ignore, will try normal authentication + } + } + catch (exception& e) + { + internalDisconnect(); + throw e; + } + } +#endif // VMIME_HAVE_SASL_SUPPORT + + // Normal authentication + const string username = getAuthenticator()->getUsername(); + const string password = getAuthenticator()->getPassword(); + + send(true, "LOGIN " + IMAPUtils::quoteString(username) + + " " + IMAPUtils::quoteString(password), true); + + std::auto_ptr resp(m_parser->readResponse()); + + 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 (getAuthenticator())) + throw exceptions::authentication_error("No SASL authenticator available."); + + const std::vector capa = getCapabilities(); + std::vector 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 > mechList; + + shared_ptr saslContext = + make_shared (); + + 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 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 (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 mech = mechList[i]; + + shared_ptr saslSession = + saslContext->createSession("imap", getAuthenticator(), mech); + + saslSession->init(); + + send(true, "AUTHENTICATE " + mech->getName(), true); + + for (bool cont = true ; cont ; ) + { + std::auto_ptr resp(m_parser->readResponse()); + + 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 + { + std::vector + respDataList = resp->continue_req_or_response_data(); + + string response; + bool hasResponse = false; + + for (unsigned int i = 0 ; i < respDataList.size() ; ++i) + { + if (respDataList[i]->continue_req()) + { + response = respDataList[i]->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 + send(false, saslContext->encodeB64(resp, respLen), true); + + // 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 + send(false, "*", true); + } + 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 + { + send(true, "STARTTLS", true); + + std::auto_ptr resp(m_parser->readResponse()); + + 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 tlsSession = tls::TLSSession::create + (m_store.lock()->getCertificateVerifier(), + m_store.lock()->getSession()->getTLSProperties()); + + shared_ptr tlsSocket = + tlsSession->getSocket(m_socket); + + tlsSocket->handshake(m_timeoutHandler); + + m_socket = tlsSocket; + m_parser->setSocket(m_socket); + + m_secured = true; + m_cntInfos = make_shared + (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 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; +} + + +void IMAPConnection::invalidateCapabilities() +{ + m_capabilities.clear(); + m_capabilitiesFetched = false; +} + + +void IMAPConnection::fetchCapabilities() +{ + send(true, "CAPABILITY", true); + + std::auto_ptr resp(m_parser->readResponse()); + + 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) +{ + const std::vector & respDataList = + resp->continue_req_or_response_data(); + + for (size_t i = 0 ; i < respDataList.size() ; ++i) + { + if (respDataList[i]->response_data() == NULL) + continue; + + const IMAPParser::capability_data* capaData = + respDataList[i]->response_data()->capability_data(); + + if (capaData == NULL) + continue; + + processCapabilityResponseData(capaData); + return true; + } + + return false; +} + + +void IMAPConnection::processCapabilityResponseData(const IMAPParser::capability_data* capaData) +{ + std::vector res; + + std::vector caps = capaData->capabilities(); + + for (unsigned int j = 0 ; j < caps.size() ; ++j) + { + if (caps[j]->auth_type()) + res.push_back("AUTH=" + caps[j]->auth_type()->name()); + else + res.push_back(utility::stringUtils::toUpper(caps[j]->atom()->value())); + } + + m_capabilities = res; + m_capabilitiesFetched = true; +} + + +shared_ptr 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 IMAPConnection::getConnectionInfos() const +{ + return m_cntInfos; +} + + +void IMAPConnection::disconnect() +{ + if (!isConnected()) + throw exceptions::not_connected(); + + internalDisconnect(); +} + + +void IMAPConnection::internalDisconnect() +{ + if (isConnected()) + { + send(true, "LOGOUT", true); + + m_socket->disconnect(); + m_socket = null; + } + + m_timeoutHandler = null; + + m_state = STATE_LOGOUT; + + m_secured = false; + m_cntInfos = null; +} + + +void IMAPConnection::initHierarchySeparator() +{ + send(true, "LIST \"\" \"\"", true); + + std::auto_ptr resp(m_parser->readResponse()); + + 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 std::vector & 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() == NULL) + continue; + + const IMAPParser::mailbox_data* mailboxData = + static_cast + (respDataList[i]->response_data())->mailbox_data(); + + if (mailboxData == NULL || 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::send(bool tag, const string& what, bool end) +{ + if (tag && !m_firstTag) + ++(*m_tag); + +#if VMIME_DEBUG + std::ostringstream oss; + + if (tag) + { + oss << string(*m_tag); + oss << " "; + } + + oss << what; + + if (end) + oss << "\r\n"; + + m_socket->send(oss.str()); +#else + if (tag) + { + m_socket->send(*m_tag); + m_socket->send(" "); + } + + m_socket->send(what); + + if (end) + { + m_socket->send("\r\n"); + } +#endif + + if (tag) + m_firstTag = false; +} + + +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(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 IMAPConnection::getStore() const +{ + return m_store.lock(); +} + + +shared_ptr IMAPConnection::getStore() +{ + return m_store.lock(); +} + + +shared_ptr IMAPConnection::getSession() +{ + return m_store.lock()->getSession(); +} + + +shared_ptr IMAPConnection::getSocket() const +{ + return m_socket; +} + + +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/src/vmime/net/imap/IMAPConnection.hpp b/src/vmime/net/imap/IMAPConnection.hpp new file mode 100644 index 00000000..b38d0c27 --- /dev/null +++ b/src/vmime/net/imap/IMAPConnection.hpp @@ -0,0 +1,163 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/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 VMIME_EXPORT IMAPConnection : public object +{ +public: + + IMAPConnection(shared_ptr store, shared_ptr 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 send(bool tag, const string& what, bool end); + void sendRaw(const byte_t* buffer, const size_t count); + + IMAPParser::response* readResponse(IMAPParser::literalHandler* lh = NULL); + + + shared_ptr getStore() const; + shared_ptr getStore(); + + shared_ptr getSession(); + + void fetchCapabilities(); + void invalidateCapabilities(); + const std::vector getCapabilities(); + bool hasCapability(const string& capa); + + shared_ptr getAuthenticator(); + + bool isSecuredConnection() const; + shared_ptr getConnectionInfos() const; + + shared_ptr getSocket() const; + + 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 m_store; + + shared_ptr m_auth; + + shared_ptr m_socket; + + shared_ptr m_parser; + + shared_ptr m_tag; + + char m_hierarchySeparator; + + ProtocolStates m_state; + + shared_ptr m_timeoutHandler; + + bool m_secured; + shared_ptr m_cntInfos; + + bool m_firstTag; + + std::vector m_capabilities; + bool m_capabilitiesFetched; + + bool m_noModSeq; + + + 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/src/vmime/net/imap/IMAPFolder.cpp b/src/vmime/net/imap/IMAPFolder.cpp new file mode 100644 index 00000000..fb98887c --- /dev/null +++ b/src/vmime/net/imap/IMAPFolder.cpp @@ -0,0 +1,1511 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/message.hpp" + +#include "vmime/exception.hpp" + +#include "vmime/utility/outputStreamAdapter.hpp" + +#include +#include + + +namespace vmime { +namespace net { +namespace imap { + + +IMAPFolder::IMAPFolder(const folder::path& path, shared_ptr store, const int type, const int flags) + : 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_type(type), m_flags(flags) +{ + store->registerFolder(this); + + m_status = make_shared (); +} + + +IMAPFolder::~IMAPFolder() +{ + shared_ptr store = m_store.lock(); + + if (store) + { + if (m_open) + close(false); + + store->unregisterFolder(this); + } + else if (m_open) + { + m_connection = null; + onClose(); + } +} + + +int IMAPFolder::getMode() const +{ + if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + return (m_mode); +} + + +int IMAPFolder::getType() +{ + if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + // Root folder + if (m_path.isEmpty()) + { + return (TYPE_CONTAINS_FOLDERS); + } + else + { + if (m_type == TYPE_UNDEFINED) + testExistAndGetType(); + + return (m_type); + } +} + + +int IMAPFolder::getFlags() +{ + if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + // Root folder + if (m_path.isEmpty()) + { + return (FLAG_CHILDREN | FLAG_NO_OPEN); + } + else + { + if (m_flags == FLAG_UNDEFINED) + testExistAndGetType(); + + return (m_flags); + } +} + + +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 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 ::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 connection = + make_shared (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::ostringstream oss; + + if (mode == MODE_READ_ONLY) + oss << "EXAMINE "; + else + oss << "SELECT "; + + oss << IMAPUtils::quoteString(IMAPUtils::pathToString + (connection->hierarchySeparator(), getFullPath())); + + if (m_connection->hasCapability("CONDSTORE")) + oss << " (CONDSTORE)"; + + connection->send(true, oss.str(), true); + + // Read the response + std::auto_ptr 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"); + } + + const std::vector & respDataList = + resp->continue_req_or_response_data(); + + for (std::vector ::const_iterator + it = respDataList.begin() ; it != respDataList.end() ; ++it) + { + if ((*it)->response_data() == NULL) + { + throw exceptions::command_error("SELECT", + resp->getErrorLog(), "invalid response"); + } + + const IMAPParser::response_data* responseData = (*it)->response_data(); + + // OK Untagged responses: UNSEEN, PERMANENTFLAGS, UIDVALIDITY (optional) + if (responseData->resp_cond_state()) + { + const IMAPParser::resp_text_code* code = + responseData->resp_cond_state()->resp_text()->resp_text_code(); + + if (code != NULL) + { + 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: + { + m_type = IMAPUtils::folderTypeFromFlags + (responseData->mailbox_data()->mailbox_flag_list()); + + m_flags = IMAPUtils::folderFlagsFromFlags + (responseData->mailbox_data()->mailbox_flag_list()); + + break; + } + + } + } + } + + processStatusUpdate(resp.get()); + + // Check for access mode (read-only or read-write) + const IMAPParser::resp_text_code* respTextCode = resp->response_done()-> + response_tagged()->resp_cond_state()->resp_text()->resp_text_code(); + + 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 store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + + if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + shared_ptr 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(); + + oldConnection->send(true, "CLOSE", true); + } + + // 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 (); + + onClose(); +} + + +void IMAPFolder::onClose() +{ + for (std::vector ::iterator it = m_messages.begin() ; + it != m_messages.end() ; ++it) + { + (*it)->onFolderClosed(); + } + + m_messages.clear(); +} + + +void IMAPFolder::create(const int type) +{ + shared_ptr 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 (type & TYPE_CONTAINS_FOLDERS) + mailbox += m_connection->hierarchySeparator(); + + std::ostringstream oss; + oss << "CREATE " << IMAPUtils::quoteString(mailbox); + + m_connection->send(true, oss.str(), true); + + + std::auto_ptr 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 event = + make_shared + (dynamicCast (shared_from_this()), + events::folderEvent::TYPE_CREATED, m_path, m_path); + + notifyFolder(event); +} + + +void IMAPFolder::destroy() +{ + shared_ptr 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()); + + std::ostringstream oss; + oss << "DELETE " << IMAPUtils::quoteString(mailbox); + + m_connection->send(true, oss.str(), true); + + + std::auto_ptr 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 event = + make_shared + (dynamicCast (shared_from_this()), + events::folderEvent::TYPE_DELETED, m_path, m_path); + + notifyFolder(event); +} + + +bool IMAPFolder::exists() +{ + shared_ptr store = m_store.lock(); + + if (!isOpen() && !store) + throw exceptions::illegal_state("Store disconnected"); + + return (testExistAndGetType() != TYPE_UNDEFINED); +} + + +int IMAPFolder::testExistAndGetType() +{ + m_type = TYPE_UNDEFINED; + + // 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 + + std::ostringstream oss; + oss << "LIST \"\" "; + oss << IMAPUtils::quoteString(IMAPUtils::pathToString + (m_connection->hierarchySeparator(), getFullPath())); + + m_connection->send(true, oss.str(), true); + + + std::auto_ptr 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 + const std::vector & respDataList = + resp->continue_req_or_response_data(); + + for (std::vector ::const_iterator + it = respDataList.begin() ; it != respDataList.end() ; ++it) + { + if ((*it)->response_data() == NULL) + { + throw exceptions::command_error("LIST", + resp->getErrorLog(), "invalid response"); + } + + const IMAPParser::mailbox_data* mailboxData = + (*it)->response_data()->mailbox_data(); + + // We are only interested in responses of type "LIST" + if (mailboxData != NULL && mailboxData->type() == IMAPParser::mailbox_data::LIST) + { + // Get the folder type/flags at the same time + m_type = IMAPUtils::folderTypeFromFlags + (mailboxData->mailbox_list()->mailbox_flag_list()); + + m_flags = IMAPUtils::folderFlagsFromFlags + (mailboxData->mailbox_list()->mailbox_flag_list()); + } + } + + return (m_type); +} + + +bool IMAPFolder::isOpen() const +{ + return (m_open); +} + + +shared_ptr IMAPFolder::getMessage(const int 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 (dynamicCast (shared_from_this()), num); +} + + +std::vector > IMAPFolder::getMessages(const messageSet& msgs) +{ + if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + if (msgs.isEmpty()) + return std::vector >(); + + std::vector > messages; + + if (msgs.isNumberSet()) + { + const std::vector numbers = IMAPUtils::messageSetToNumberList(msgs); + + shared_ptr thisFolder = dynamicCast (shared_from_this()); + + for (std::vector ::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) + messages.push_back(make_shared (thisFolder, *it)); + } + else if (msgs.isUIDSet()) + { + // 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 + + // Prepare command and arguments + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + + cmd << "UID FETCH " << IMAPUtils::messageSetToSequenceSet(msgs) << " UID"; + + // Send the request + m_connection->send(true, cmd.str(), true); + + // Get the response + std::auto_ptr 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 + const std::vector & respDataList = + resp->continue_req_or_response_data(); + + for (std::vector ::const_iterator + it = respDataList.begin() ; it != respDataList.end() ; ++it) + { + if ((*it)->response_data() == NULL) + { + throw exceptions::command_error("UID FETCH ... UID", + resp->getErrorLog(), "invalid response"); + } + + const IMAPParser::message_data* messageData = + (*it)->response_data()->message_data(); + + // We are only interested in responses of type "FETCH" + if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) + continue; + + // Get Process fetch response for this message + const int msgNum = static_cast (messageData->number()); + message::uid msgUID; + + // Find UID in message attributes + const std::vector atts = messageData->msg_att()->items(); + + for (std::vector ::const_iterator + it = atts.begin() ; it != atts.end() ; ++it) + { + if ((*it)->type() == IMAPParser::msg_att_item::UID) + { + msgUID = (*it)->unique_id()->value(); + break; + } + } + + if (!msgUID.empty()) + { + shared_ptr thisFolder = dynamicCast (shared_from_this()); + messages.push_back(make_shared (thisFolder, msgNum, msgUID)); + } + } + } + + return messages; +} + + +int 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 IMAPFolder::getFolder(const folder::path::component& name) +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + + return make_shared (m_path / name, store); +} + + +std::vector > IMAPFolder::getFolders(const bool recursive) +{ + shared_ptr 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 + + std::ostringstream oss; + oss << "LIST "; + + const string pathString = IMAPUtils::pathToString + (m_connection->hierarchySeparator(), getFullPath()); + + if (recursive) + { + oss << IMAPUtils::quoteString(pathString); + oss << " *"; + } + else + { + if (pathString.empty()) // don't add sep for root folder + oss << "\"\""; + else + oss << IMAPUtils::quoteString(pathString + m_connection->hierarchySeparator()); + + oss << " %"; + } + + m_connection->send(true, oss.str(), true); + + + std::auto_ptr 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"); + } + + const std::vector & respDataList = + resp->continue_req_or_response_data(); + + + std::vector > v; + + for (std::vector ::const_iterator + it = respDataList.begin() ; it != respDataList.end() ; ++it) + { + if ((*it)->response_data() == NULL) + { + throw exceptions::command_error("LIST", + resp->getErrorLog(), "invalid response"); + } + + const IMAPParser::mailbox_data* mailboxData = + (*it)->response_data()->mailbox_data(); + + if (mailboxData == NULL || mailboxData->type() != IMAPParser::mailbox_data::LIST) + continue; + + // Get folder path + const class IMAPParser::mailbox* 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 + const class IMAPParser::mailbox_flag_list* mailbox_flag_list = + mailboxData->mailbox_list()->mailbox_flag_list(); + + v.push_back(make_shared (path, store, + IMAPUtils::folderTypeFromFlags(mailbox_flag_list), + IMAPUtils::folderFlagsFromFlags(mailbox_flag_list))); + } + } + + return (v); +} + + +void IMAPFolder::fetchMessages(std::vector >& msg, const fetchAttributes& options, + utility::progressListener* progress) +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + else if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + // Build message numbers list + std::vector list; + list.reserve(msg.size()); + + std::map > numberToMsg; + + for (std::vector >::iterator it = msg.begin() ; it != msg.end() ; ++it) + { + list.push_back((*it)->getNumber()); + numberToMsg[(*it)->getNumber()] = dynamicCast (*it); + } + + // Send the request + const string command = IMAPUtils::buildFetchRequest + (m_connection, messageSet::byNumber(list), options); + + m_connection->send(true, command, true); + + // Get the response + std::auto_ptr 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"); + } + + const std::vector & respDataList = + resp->continue_req_or_response_data(); + + const size_t total = msg.size(); + size_t current = 0; + + if (progress) + progress->start(total); + + try + { + for (std::vector ::const_iterator + it = respDataList.begin() ; it != respDataList.end() ; ++it) + { + if ((*it)->response_data() == NULL) + { + throw exceptions::command_error("FETCH", + resp->getErrorLog(), "invalid response"); + } + + const IMAPParser::message_data* messageData = + (*it)->response_data()->message_data(); + + // We are only interested in responses of type "FETCH" + if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) + continue; + + // Process fetch response for this message + const int num = static_cast (messageData->number()); + + std::map >::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(shared_ptr msg, const fetchAttributes& options) +{ + std::vector > msgs; + msgs.push_back(msg); + + fetchMessages(msgs, options, /* progress */ NULL); +} + + +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 IMAPFolder::getParent() +{ + if (m_path.isEmpty()) + return null; + else + return make_shared (m_path.getParent(), m_store.lock()); +} + + +shared_ptr IMAPFolder::getStore() const +{ + return m_store.lock(); +} + + +shared_ptr IMAPFolder::getStore() +{ + return m_store.lock(); +} + + +void IMAPFolder::registerMessage(IMAPMessage* msg) +{ + m_messages.push_back(msg); +} + + +void IMAPFolder::unregisterMessage(IMAPMessage* msg) +{ + std::vector ::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 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"); + + // Build the request text + std::ostringstream command; + command.imbue(std::locale::classic()); + + if (msgs.isUIDSet()) + command << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs); + else + command << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs); + + command << " +FLAGS (\\Deleted)"; + + // Send the request + m_connection->send(true, command.str(), true); + + // Get the response + std::auto_ptr 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) +{ + // Build the request text + std::ostringstream command; + command.imbue(std::locale::classic()); + + if (msgs.isUIDSet()) + command << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs); + else + command << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs); + + switch (mode) + { + case message::FLAG_MODE_ADD: command << " +FLAGS "; break; + case message::FLAG_MODE_REMOVE: command << " -FLAGS "; break; + default: + case message::FLAG_MODE_SET: command << " FLAGS "; break; + } + + const string flagList = IMAPUtils::messageFlagList(flags); + + if (!flagList.empty()) + { + command << flagList; + + // Send the request + m_connection->send(true, command.str(), true); + + // Get the response + std::auto_ptr 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::addMessage(shared_ptr 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); + + addMessage(strAdapter, str.length(), flags, date, progress); +} + + +void IMAPFolder::addMessage(utility::inputStream& is, const size_t size, const int flags, + vmime::datetime* date, utility::progressListener* progress) +{ + shared_ptr 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"); + + // Build the request text + std::ostringstream command; + command.imbue(std::locale::classic()); + + command << "APPEND " << IMAPUtils::quoteString(IMAPUtils::pathToString + (m_connection->hierarchySeparator(), getFullPath())) << ' '; + + const string flagList = IMAPUtils::messageFlagList(flags); + + if (flags != message::FLAG_UNDEFINED && !flagList.empty()) + { + command << flagList; + command << ' '; + } + + if (date != NULL) + { + command << IMAPUtils::dateTime(*date); + command << ' '; + } + + command << '{' << size << '}'; + + // Send the request + m_connection->send(true, command.str(), true); + + // Get the response + std::auto_ptr resp(m_connection->readResponse()); + + bool ok = false; + const std::vector & respList + = resp->continue_req_or_response_data(); + + for (std::vector ::const_iterator + 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"); + } + + // 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 (m_connection->getSocket()->getBlockSize())); + + std::vector vbuffer(blockSize); + byte_t* buffer = &vbuffer.front(); + + while (!is.eof()) + { + // Read some data from the input stream + const size_t read = is.read(buffer, sizeof(buffer)); + current += read; + + // Put read data into socket output stream + m_connection->sendRaw(buffer, read); + + // Notify progress + if (progress) + progress->progress(current, total); + } + + m_connection->send(false, "", true); + + if (progress) + progress->stop(total); + + // Get the response + std::auto_ptr 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(resp.get()); +} + + +void IMAPFolder::expunge() +{ + shared_ptr 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 + m_connection->send(true, "EXPUNGE", true); + + // Get the response + std::auto_ptr 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 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(); + + // Build the request text + std::ostringstream command; + command.imbue(std::locale::classic()); + + command << "RENAME "; + command << IMAPUtils::quoteString(IMAPUtils::pathToString + (m_connection->hierarchySeparator(), getFullPath())) << " "; + command << IMAPUtils::quoteString(IMAPUtils::pathToString + (m_connection->hierarchySeparator(), newPath)); + + // Send the request + m_connection->send(true, command.str(), true); + + // Get the response + std::auto_ptr 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 event = + make_shared + (dynamicCast (shared_from_this()), + events::folderEvent::TYPE_RENAMED, oldPath, newPath); + + notifyFolder(event); + + // Notify sub-folders + for (std::list ::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 event = + make_shared + (dynamicCast ((*it)->shared_from_this()), + events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path); + + (*it)->notifyFolder(event); + } + } + + processStatusUpdate(resp.get()); +} + + +void IMAPFolder::copyMessages(const folder::path& dest, const messageSet& set) +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + else if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + // Build the request text + std::ostringstream command; + command.imbue(std::locale::classic()); + + command << "COPY " << IMAPUtils::messageSetToSequenceSet(set) << " "; + command << IMAPUtils::quoteString(IMAPUtils::pathToString + (m_connection->hierarchySeparator(), dest)); + + // Send the request + m_connection->send(true, command.str(), true); + + // Get the response + std::auto_ptr 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()); +} + + +void IMAPFolder::status(int& count, int& unseen) +{ + count = 0; + unseen = 0; + + shared_ptr status = getStatus(); + + count = status->getMessageCount(); + unseen = status->getUnseenCount(); +} + + +shared_ptr IMAPFolder::getStatus() +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + + // Build the request text + std::ostringstream command; + command.imbue(std::locale::classic()); + + command << "STATUS "; + command << IMAPUtils::quoteString(IMAPUtils::pathToString + (m_connection->hierarchySeparator(), getFullPath())); + command << " ("; + + command << "MESSAGES" << ' ' << "UNSEEN" << ' ' << "UIDNEXT" << ' ' << "UIDVALIDITY"; + + if (m_connection->hasCapability("CONDSTORE")) + command << ' ' << "HIGHESTMODSEQ"; + + command << ")"; + + // Send the request + m_connection->send(true, command.str(), true); + + // Get the response + std::auto_ptr 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"); + } + + const std::vector & respDataList = + resp->continue_req_or_response_data(); + + for (std::vector ::const_iterator + it = respDataList.begin() ; it != respDataList.end() ; ++it) + { + if ((*it)->response_data() != NULL) + { + const IMAPParser::response_data* responseData = (*it)->response_data(); + + if (responseData->mailbox_data() && + responseData->mailbox_data()->type() == IMAPParser::mailbox_data::STATUS) + { + shared_ptr status = make_shared (); + 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 store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + + m_connection->send(true, "NOOP", true); + + std::auto_ptr 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 IMAPFolder::getMessageNumbersStartingOnUID(const message::uid& uid) +{ + std::vector v; + + std::ostringstream command; + command.imbue(std::locale::classic()); + + command << "SEARCH UID " << uid << ":*"; + + // Send the request + m_connection->send(true, command.str(), true); + + // Get the response + std::auto_ptr 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"); + } + + const std::vector & respDataList = resp->continue_req_or_response_data(); + + for (std::vector ::const_iterator + it = respDataList.begin() ; it != respDataList.end() ; ++it) + { + if ((*it)->response_data() == NULL) + { + throw exceptions::command_error("SEARCH", + resp->getErrorLog(), "invalid response"); + } + + const IMAPParser::mailbox_data* mailboxData = + (*it)->response_data()->mailbox_data(); + + // We are only interested in responses of type "SEARCH" + if (mailboxData == NULL || + mailboxData->type() != IMAPParser::mailbox_data::SEARCH) + { + continue; + } + + for (std::vector ::const_iterator + it = mailboxData->search_nz_number_list().begin() ; + it != mailboxData->search_nz_number_list().end(); + ++it) + { + v.push_back((*it)->value()); + } + } + + processStatusUpdate(resp.get()); + + return v; +} + + +void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) +{ + std::vector > events; + + shared_ptr 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()) + { + const IMAPParser::resp_text_code* code = + resp->response_done()->response_tagged() + ->resp_cond_state()->resp_text()->resp_text_code(); + + m_status->updateFromResponse(code); + } + + // Process untagged responses + for (std::vector ::const_iterator + 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()) + { + const IMAPParser::resp_text_code* code = + (*it)->response_data()->resp_cond_state()->resp_text()->resp_text_code(); + + m_status->updateFromResponse(code); + } + else if ((*it)->response_data() && (*it)->response_data()->mailbox_data()) + { + m_status->updateFromResponse((*it)->response_data()->mailbox_data()); + } + else if ((*it)->response_data() && (*it)->response_data()->message_data()) + { + const IMAPParser::message_data* msgData = (*it)->response_data()->message_data(); + const int msgNumber = msgData->number(); + + if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::FETCH) + { + // Message changed + for (std::vector ::iterator mit = + m_messages.begin() ; mit != m_messages.end() ; ++mit) + { + if ((*mit)->getNumber() == msgNumber) + (*mit)->processFetchResponse(/* options */ 0, msgData); + } + + events.push_back(make_shared + (dynamicCast (shared_from_this()), + events::messageChangedEvent::TYPE_FLAGS, + std::vector (1, msgNumber))); + } + else if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::EXPUNGE) + { + // A message has been expunged, renumber messages + for (std::vector ::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 + (dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_REMOVED, + std::vector (1, msgNumber))); + + expungedMessageCount++; + } + } + } + + // New messages arrived + if (m_status->getMessageCount() > oldStatus->getMessageCount() - expungedMessageCount) + { + std::vector newMessageNumbers; + + for (int msgNumber = oldStatus->getMessageCount() - expungedMessageCount ; + msgNumber <= m_status->getMessageCount() ; ++msgNumber) + { + newMessageNumbers.push_back(msgNumber); + } + + events.push_back(make_shared + (dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + newMessageNumbers)); + } + + // Dispatch notifications + for (std::vector >::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/src/vmime/net/imap/IMAPFolder.hpp b/src/vmime/net/imap/IMAPFolder.hpp new file mode 100644 index 00000000..cc7334ff --- /dev/null +++ b/src/vmime/net/imap/IMAPFolder.hpp @@ -0,0 +1,204 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + +#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, shared_ptr store, const int type = TYPE_UNDEFINED, const int flags = FLAG_UNDEFINED); + + ~IMAPFolder(); + + int getMode() const; + + int getType(); + + int getFlags(); + + 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 int type); + + bool exists(); + + void destroy(); + + bool isOpen() const; + + shared_ptr getMessage(const int num); + std::vector > getMessages(const messageSet& msgs); + + std::vector getMessageNumbersStartingOnUID(const message::uid& uid); + + int getMessageCount(); + + shared_ptr getFolder(const folder::path::component& name); + std::vector > 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); + + void addMessage(shared_ptr msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); + void addMessage(utility::inputStream& is, const size_t size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); + + void copyMessages(const folder::path& dest, const messageSet& msgs); + + void status(int& count, int& unseen); + shared_ptr getStatus(); + + void noop(); + + void expunge(); + + shared_ptr getParent(); + + shared_ptr getStore() const; + shared_ptr getStore(); + + + void fetchMessages(std::vector >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL); + void fetchMessage(shared_ptr msg, const fetchAttributes& options); + + 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 m_store; + shared_ptr m_connection; + + folder::path m_path; + folder::path::component m_name; + + int m_mode; + bool m_open; + + int m_type; + int m_flags; + + shared_ptr m_status; + + std::vector 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/src/vmime/net/imap/IMAPFolderStatus.cpp b/src/vmime/net/imap/IMAPFolderStatus.cpp new file mode 100644 index 00000000..c78a40f3 --- /dev/null +++ b/src/vmime/net/imap/IMAPFolderStatus.cpp @@ -0,0 +1,307 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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) +{ +} + + +unsigned int IMAPFolderStatus::getMessageCount() const +{ + return m_count; +} + + +unsigned int IMAPFolderStatus::getUnseenCount() const +{ + return m_unseen; +} + + +unsigned int 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 IMAPFolderStatus::clone() const +{ + return make_shared (*this); +} + + +bool IMAPFolderStatus::updateFromResponse(const IMAPParser::mailbox_data* resp) +{ + bool changed = false; + + if (resp->type() == IMAPParser::mailbox_data::STATUS) + { + const IMAPParser::status_att_list* statusAttList = resp->status_att_list(); + + for (std::vector ::const_iterator + jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt) + { + switch ((*jt)->type()) + { + case IMAPParser::status_att_val::MESSAGES: + { + const unsigned int count = + static_cast ((*jt)->value_as_number()->value()); + + if (m_count != count) + { + m_count = count; + changed = true; + } + + break; + } + case IMAPParser::status_att_val::UNSEEN: + { + const unsigned int unseen = + static_cast ((*jt)->value_as_number()->value()); + + if (m_unseen != unseen) + { + m_unseen = unseen; + changed = true; + } + + break; + } + case IMAPParser::status_att_val::RECENT: + { + const unsigned int recent = + static_cast ((*jt)->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 ((*jt)->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 ((*jt)->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 ((*jt)->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 unsigned int count = + static_cast (resp->number()->value()); + + if (m_count != count) + { + m_count = count; + changed = true; + } + } + else if (resp->type() == IMAPParser::mailbox_data::RECENT) + { + const unsigned int recent = + static_cast (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 (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 (resp->nz_number()->value()); + + if (m_uidNext != uidNext) + { + m_uidNext = uidNext; + changed = true; + } + + break; + } + case IMAPParser::resp_text_code::UNSEEN: + { + const unsigned int unseen = + static_cast (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 (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/src/vmime/net/imap/IMAPFolderStatus.hpp b/src/vmime/net/imap/IMAPFolderStatus.hpp new file mode 100644 index 00000000..03ca5937 --- /dev/null +++ b/src/vmime/net/imap/IMAPFolderStatus.hpp @@ -0,0 +1,124 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + unsigned int getMessageCount() const; + unsigned int getUnseenCount() const; + + shared_ptr clone() const; + + /** Returns the the number of messages with the Recent flag set. + * + * @return number of messages flagged Recent + */ + unsigned int 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: + + unsigned int m_count; + unsigned int m_unseen; + unsigned int 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/src/vmime/net/imap/IMAPMessage.cpp b/src/vmime/net/imap/IMAPMessage.cpp new file mode 100644 index 00000000..c11aafc2 --- /dev/null +++ b/src/vmime/net/imap/IMAPMessage.cpp @@ -0,0 +1,649 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include +#include + + +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_os(os), m_progress(progress) + { + } + + target* targetFor(const IMAPParser::component& comp, const int /* data */) + { + if (typeid(comp) == typeid(IMAPParser::msg_att_item)) + { + const int type = static_cast + (comp).type(); + + if (type == IMAPParser::msg_att_item::BODY_SECTION || + type == IMAPParser::msg_att_item::RFC822_TEXT) + { + return new targetStream(m_progress, m_os); + } + } + + return (NULL); + } + +private: + + utility::outputStream& m_os; + utility::progressListener* m_progress; +}; + +#endif // VMIME_BUILDING_DOC + + + +// +// IMAPMessage +// + + +IMAPMessage::IMAPMessage(shared_ptr folder, const int 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(shared_ptr folder, const int 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() +{ + shared_ptr folder = m_folder.lock(); + + if (folder) + folder->unregisterMessage(this); +} + + +void IMAPMessage::onFolderClosed() +{ + m_folder.reset(); +} + + +int 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 IMAPMessage::getStructure() const +{ + if (m_structure == NULL) + throw exceptions::unfetched_object(); + + return m_structure; +} + + +shared_ptr IMAPMessage::getStructure() +{ + if (m_structure == NULL) + throw exceptions::unfetched_object(); + + return m_structure; +} + + +shared_ptr 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 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 + (shared_ptr p, + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, const size_t length, + const bool peek) const +{ + shared_ptr 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(shared_ptr p) +{ + shared_ptr 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 (p)->getOrCreateHeader().parse(oss.str()); +} + + +void IMAPMessage::fetchPartHeaderForStructure(shared_ptr str) +{ + for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) + { + shared_ptr part = str->getPartAt(i); + + // Fetch header of current part + fetchPartHeader(part); + + // Fetch header of sub-parts + fetchPartHeaderForStructure(part->getStructure()); + } +} + + +void IMAPMessage::extractImpl + (shared_ptr p, + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, const size_t length, + const int extractFlags) const +{ + shared_ptr folder = m_folder.lock(); + + IMAPMessage_literalHandler literalHandler(os, progress); + + // Construct section identifier + std::ostringstream section; + section.imbue(std::locale::classic()); + + if (p != NULL) + { + shared_ptr currentPart = dynamicCast (p); + std::vector 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 ::reverse_iterator it = numbers.rbegin() ; it != numbers.rend() ; ++it) + { + if (it != numbers.rbegin()) section << "."; + section << (*it + 1); + } + } + + // Build the request text + std::ostringstream command; + command.imbue(std::locale::classic()); + + if (m_uid.empty()) + command << "FETCH " << m_num << " BODY"; + else + command << "UID FETCH " << m_uid << " BODY"; + + /* + BODY[] header + body + BODY.PEEK[] header + body (peek) + BODY[HEADER] header + BODY.PEEK[HEADER] header (peek) + BODY[TEXT] body + BODY.PEEK[TEXT] body (peek) + */ + + if (extractFlags & EXTRACT_PEEK) + command << ".PEEK"; + + command << "["; + + if (section.str().empty()) + { + // header + body + if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) + command << ""; + // body only + else if (extractFlags & EXTRACT_BODY) + command << "TEXT"; + // header only + else if (extractFlags & EXTRACT_HEADER) + command << "HEADER"; + } + else + { + command << section.str(); + + // header + body + if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) + throw exceptions::operation_not_supported(); + // body only + else if (extractFlags & EXTRACT_BODY) + command << ".TEXT"; + // header only + else if (extractFlags & EXTRACT_HEADER) + command << ".MIME"; // "MIME" not "HEADER" for parts + } + + command << "]"; + + if (start != 0 || length != static_cast (-1)) + command << "<" << start << "." << length << ">"; + + // Send the request + constCast (folder)->m_connection->send(true, command.str(), true); + + // Get the response + std::auto_ptr resp + (constCast (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) + } +} + + +int IMAPMessage::processFetchResponse + (const fetchAttributes& options, const IMAPParser::message_data* msgData) +{ + shared_ptr folder = m_folder.lock(); + + // Get message attributes + const std::vector atts = msgData->msg_att()->items(); + int changes = 0; + + for (std::vector ::const_iterator + it = atts.begin() ; it != atts.end() ; ++it) + { + switch ((*it)->type()) + { + case IMAPParser::msg_att_item::FLAGS: + { + int flags = IMAPUtils::messageFlagsFromFlags((*it)->flag_list()); + + if (m_flags != flags) + { + m_flags = flags; + changes |= events::messageChangedEvent::TYPE_FLAGS; + } + + break; + } + case IMAPParser::msg_att_item::UID: + { + m_uid = (*it)->unique_id()->value(); + break; + } + case IMAPParser::msg_att_item::MODSEQ: + { + m_modseq = (*it)->mod_sequence_value()->value(); + break; + } + case IMAPParser::msg_att_item::ENVELOPE: + { + if (!options.has(fetchAttributes::FULL_HEADER)) + { + const IMAPParser::envelope* env = (*it)->envelope(); + shared_ptr 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); + + // Bcc + mailboxList bcc; + IMAPUtils::convertAddressList(*(env->env_bcc()), bcc); + + if (!bcc.isEmpty()) + hdr->Bcc()->setValue(bcc); + } + + break; + } + case IMAPParser::msg_att_item::BODY_STRUCTURE: + { + m_structure = make_shared ((*it)->body()); + break; + } + case IMAPParser::msg_att_item::RFC822_HEADER: + { + getOrCreateHeader()->parse((*it)->nstring()->value()); + break; + } + case IMAPParser::msg_att_item::RFC822_SIZE: + { + m_size = static_cast ((*it)->number()->value()); + break; + } + case IMAPParser::msg_att_item::BODY_SECTION: + { + if (!options.has(fetchAttributes::FULL_HEADER)) + { + if ((*it)->section()->section_text1() && + (*it)->section()->section_text1()->type() + == IMAPParser::section_text::HEADER_FIELDS) + { + header tempHeader; + tempHeader.parse((*it)->nstring()->value()); + + vmime::header& hdr = *getOrCreateHeader(); + std::vector > fields = tempHeader.getFieldList(); + + for (std::vector >::const_iterator jt = fields.begin() ; + jt != fields.end() ; ++jt) + { + hdr.appendField(vmime::clone(*jt)); + } + } + } + + 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
IMAPMessage::getOrCreateHeader() +{ + if (m_header != NULL) + return (m_header); + else + return (m_header = make_shared
()); +} + + +void IMAPMessage::setFlags(const int flags, const int mode) +{ + shared_ptr 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 + (shared_ptr parentPart, shared_ptr str, int level) +{ + if (level == 0) + { + shared_ptr part = str->getPartAt(0); + + // Copy header + shared_ptr hdr = part->getHeader(); + parentPart->getHeader()->copyFrom(*hdr); + + // Initialize body + parentPart->getBody()->setContents + (make_shared + (dynamicCast (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 part = str->getPartAt(i); + + shared_ptr childPart = make_shared (); + + // Copy header + shared_ptr hdr = part->getHeader(); + childPart->getHeader()->copyFrom(*hdr); + + // Initialize body + childPart->getBody()->setContents + (make_shared + (dynamicCast (shared_from_this()), + part, childPart->getBody()->getEncoding())); + + // Add child part + parentPart->getBody()->appendPart(childPart); + + // Construct sub parts + constructParsedMessage(childPart, part->getStructure(), ++level); + } + } +} + + +shared_ptr IMAPMessage::getParsedMessage() +{ + // Fetch structure + shared_ptr structure; + + try + { + structure = getStructure(); + } + catch (exceptions::unfetched_object&) + { + std::vector > msgs; + msgs.push_back(dynamicCast (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 msg = make_shared (); + + constructParsedMessage(msg, structure); + + return msg; +} + + +void IMAPMessage::renumber(const int 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/src/vmime/net/imap/IMAPMessage.hpp b/src/vmime/net/imap/IMAPMessage.hpp new file mode 100644 index 00000000..92903d69 --- /dev/null +++ b/src/vmime/net/imap/IMAPMessage.hpp @@ -0,0 +1,191 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr folder, const int num); + IMAPMessage(shared_ptr folder, const int num, const uid& uid); + + ~IMAPMessage(); + + int 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 getStructure() const; + shared_ptr getStructure(); + + shared_ptr 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 + (shared_ptr 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(shared_ptr p); + + shared_ptr getParsedMessage(); + +private: + + /** Renumbers the message. + * + * @param number new sequence number + */ + void renumber(const int 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(shared_ptr 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(shared_ptr parentPart, shared_ptr str, int level = 0); + + + enum ExtractFlags + { + EXTRACT_HEADER = 0x1, + EXTRACT_BODY = 0x2, + EXTRACT_PEEK = 0x10 + }; + + void extractImpl + (shared_ptr p, + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, const size_t length, + const int extractFlags) const; + + + shared_ptr
getOrCreateHeader(); + + + void onFolderClosed(); + + weak_ptr m_folder; + + int m_num; + size_t m_size; + int m_flags; + bool m_expunged; + uid m_uid; + vmime_uint64 m_modseq; + + shared_ptr
m_header; + shared_ptr 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/src/vmime/net/imap/IMAPMessagePart.cpp b/src/vmime/net/imap/IMAPMessagePart.cpp new file mode 100644 index 00000000..eed885dc --- /dev/null +++ b/src/vmime/net/imap/IMAPMessagePart.cpp @@ -0,0 +1,161 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const int 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()); +} + + +IMAPMessagePart::IMAPMessagePart(shared_ptr parent, const int 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(); + } + 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_structure = null; +} + + +shared_ptr IMAPMessagePart::getStructure() const +{ + if (m_structure != NULL) + return m_structure; + else + return IMAPMessageStructure::emptyStructure(); +} + + +shared_ptr IMAPMessagePart::getStructure() +{ + if (m_structure != NULL) + return m_structure; + else + return IMAPMessageStructure::emptyStructure(); +} + + +shared_ptr IMAPMessagePart::getParent() const +{ + return m_parent.lock(); +} + + +const mediaType& IMAPMessagePart::getType() const +{ + return m_mediaType; +} + + +size_t IMAPMessagePart::getSize() const +{ + return m_size; +} + + +int IMAPMessagePart::getNumber() const +{ + return m_number; +} + + +shared_ptr IMAPMessagePart::getHeader() const +{ + if (m_header == NULL) + throw exceptions::unfetched_object(); + else + return m_header; +} + + +// static +shared_ptr IMAPMessagePart::create + (shared_ptr parent, const int number, const IMAPParser::body* body) +{ + if (body->body_type_mpart()) + { + shared_ptr part = make_shared (parent, number, body->body_type_mpart()); + part->m_structure = make_shared (part, body->body_type_mpart()->list()); + + return part; + } + else + { + return make_shared (parent, number, body->body_type_1part()); + } +} + + +header& IMAPMessagePart::getOrCreateHeader() +{ + if (m_header != NULL) + return *m_header; + else + return *(m_header = make_shared
()); +} + + +} // imap +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP + diff --git a/src/vmime/net/imap/IMAPMessagePart.hpp b/src/vmime/net/imap/IMAPMessagePart.hpp new file mode 100644 index 00000000..af8581d7 --- /dev/null +++ b/src/vmime/net/imap/IMAPMessagePart.hpp @@ -0,0 +1,92 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const int number, const IMAPParser::body_type_mpart* mpart); + IMAPMessagePart(shared_ptr parent, const int number, const IMAPParser::body_type_1part* part); + + shared_ptr getStructure() const; + shared_ptr getStructure(); + + shared_ptr getParent() const; + + const mediaType& getType() const; + size_t getSize() const; + int getNumber() const; + + shared_ptr getHeader() const; + + + static shared_ptr create + (shared_ptr parent, const int number, const IMAPParser::body* body); + + + header& getOrCreateHeader(); + +private: + + shared_ptr m_structure; + weak_ptr m_parent; + shared_ptr
m_header; + + int m_number; + size_t m_size; + mediaType m_mediaType; +}; + + +} // imap +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP + +#endif // VMIME_NET_IMAP_IMAPMESSAGEPART_HPP_INCLUDED + diff --git a/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp b/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp new file mode 100644 index 00000000..1f53f082 --- /dev/null +++ b/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp @@ -0,0 +1,216 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/inputStreamStringProxyAdapter.hpp" + + +namespace vmime { +namespace net { +namespace imap { + + +IMAPMessagePartContentHandler::IMAPMessagePartContentHandler + (shared_ptr msg, shared_ptr part, const vmime::encoding& encoding) + : m_message(msg), m_part(part), m_encoding(encoding) +{ +} + + +shared_ptr IMAPMessagePartContentHandler::clone() const +{ + return make_shared + (constCast (m_message.lock()), + constCast (m_part.lock()), + m_encoding); +} + + +void IMAPMessagePartContentHandler::generate + (utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength) const +{ + shared_ptr msg = constCast (m_message.lock()); + shared_ptr part = constCast (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::inputStreamStringProxyAdapter in(oss.str()); + + std::ostringstream oss2; + utility::outputStreamAdapter tmp2(oss2); + + shared_ptr theDecoder = m_encoding.getEncoder(); + theDecoder->decode(in, tmp2); + + // Reencode to output stream + string str = oss2.str(); + utility::inputStreamStringAdapter tempIn(str); + + shared_ptr 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 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 msg = constCast (m_message.lock()); + shared_ptr part = constCast (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 theDecoder = m_encoding.getEncoder(); + theDecoder->decode(is, os, &plsa); + } +} + + +void IMAPMessagePartContentHandler::extractRaw + (utility::outputStream& os, utility::progressListener* progress) const +{ + shared_ptr msg = constCast (m_message.lock()); + shared_ptr part = constCast (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/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp b/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp new file mode 100644 index 00000000..cb52b2e3 --- /dev/null +++ b/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp @@ -0,0 +1,87 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr msg, shared_ptr part, const vmime::encoding& encoding); + + shared_ptr 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 m_message; + weak_ptr 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/src/vmime/net/imap/IMAPMessageStructure.cpp b/src/vmime/net/imap/IMAPMessageStructure.cpp new file mode 100644 index 00000000..8dc333e9 --- /dev/null +++ b/src/vmime/net/imap/IMAPMessageStructure.cpp @@ -0,0 +1,94 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const std::vector & list) +{ + int number = 0; + + for (std::vector ::const_iterator + it = list.begin() ; it != list.end() ; ++it, ++number) + { + m_parts.push_back(IMAPMessagePart::create(parent, number, *it)); + } +} + + +shared_ptr IMAPMessageStructure::getPartAt(const size_t x) const +{ + return m_parts[x]; +} + + +shared_ptr IMAPMessageStructure::getPartAt(const size_t x) +{ + return m_parts[x]; +} + + +size_t IMAPMessageStructure::getPartCount() const +{ + return m_parts.size(); +} + + +// static +shared_ptr IMAPMessageStructure::emptyStructure() +{ + static shared_ptr emptyStructure = make_shared (); + return emptyStructure; +} + + +} // imap +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP + diff --git a/src/vmime/net/imap/IMAPMessageStructure.hpp b/src/vmime/net/imap/IMAPMessageStructure.hpp new file mode 100644 index 00000000..44b6d6f0 --- /dev/null +++ b/src/vmime/net/imap/IMAPMessageStructure.hpp @@ -0,0 +1,75 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const std::vector & list); + + shared_ptr getPartAt(const size_t x) const; + shared_ptr getPartAt(const size_t x); + size_t getPartCount() const; + + static shared_ptr emptyStructure(); + +private: + + std::vector > 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/src/vmime/net/imap/IMAPParser.hpp b/src/vmime/net/imap/IMAPParser.hpp new file mode 100644 index 00000000..8c7fcb60 --- /dev/null +++ b/src/vmime/net/imap/IMAPParser.hpp @@ -0,0 +1,5617 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/imap/IMAPTag.hpp" + +#include +#include +#include + + +//#define DEBUG_RESPONSE 1 + + +#if DEBUG_RESPONSE +# include +#endif + + +namespace vmime { +namespace net { +namespace imap { + + +#if DEBUG_RESPONSE + static int IMAPParserDebugResponse_level = 0; + static std::vector IMAPParserDebugResponse_stack; + + class IMAPParserDebugResponse + { + public: + + IMAPParserDebugResponse(const string& name, string& line, const size_t currentPos) + : m_name(name), m_line(line), m_pos(currentPos) + { + ++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 ::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 << (std::uncaught_exception() ? "FALSE" : "TRUE") << ", 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; + }; + + + #define DEBUG_ENTER_COMPONENT(x) \ + IMAPParserDebugResponse dbg(x, line, *currentPos) + + #define DEBUG_FOUND(x, y) \ + std::cout << "FOUND: " << x << ": " << y << std::endl; +#else + #define DEBUG_ENTER_COMPONENT(x) + #define DEBUG_FOUND(x, y) +#endif + + +class VMIME_EXPORT IMAPParser : public object +{ +public: + + IMAPParser(weak_ptr tag, weak_ptr sok, weak_ptr _timeoutHandler) + : m_tag(tag), m_socket(sok), m_progress(NULL), m_strict(false), + m_literalHandler(NULL), m_timeoutHandler(_timeoutHandler) + { + } + + + shared_ptr getTag() const + { + return m_tag.lock(); + } + + void setSocket(shared_ptr sok) + { + m_socket = sok; + } + + /** 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; + + 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) { } + + const vmime::string& string() const { return (m_string); } + vmime::string& string() { return (m_string); } + + + void putData(const vmime::string& chunk) + { + m_string += chunk; + } + + private: + + vmime::string& m_string; + }; + + + // Target: redirect to an output stream + class targetStream : public target + { + public: + + targetStream(utility::progressListener* progress, utility::outputStream& stream) + : target(progress), m_stream(stream) { } + + 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()); + } + + private: + + utility::outputStream& m_stream; + }; + + + // 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 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 void go(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 \ + { \ + void go(IMAPParser& parser, string& line, size_t* currentPos) \ + { \ + DEBUG_ENTER_COMPONENT(#name); \ + parent::go(parser, line, currentPos); \ + } \ + } + + + // + // Parse one character + // + + template + class one_char : public component + { + public: + + void go(IMAPParser& /* parser */, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT(string("one_char <") + C + ">: current='" + ((*currentPos < line.length() ? line[*currentPos] : '?')) + "'"); + + const size_t pos = *currentPos; + + if (pos < line.length() && line[pos] == C) + *currentPos = pos + 1; + else + throw exceptions::invalid_response("", makeResponseLine("", line, pos)); + } + }; + + + // + // SPACE ::= + // + + class SPACE : public component + { + public: + + void go(IMAPParser& /* parser */, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("SPACE"); + + size_t pos = *currentPos; + + while (pos < line.length() && (line[pos] == ' ' || line[pos] == '\t')) + ++pos; + + if (pos > *currentPos) + *currentPos = pos; + else + throw exceptions::invalid_response("", makeResponseLine("SPACE", line, pos)); + } + }; + + + // + // CR ::= + // LF ::= + // CRLF ::= CR LF + // + + class CRLF : public component + { + public: + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("CRLF"); + + size_t pos = *currentPos; + + parser.check (line, &pos, true); + + if (pos + 1 < line.length() && + line[pos] == 0x0d && line[pos + 1] == 0x0a) + { + *currentPos = pos + 2; + } + else + { + throw exceptions::invalid_response("", makeResponseLine("CRLF", line, pos)); + } + } + }; + + + // + // SPACE ::= + // CTL ::= + // CHAR ::= + // ATOM_CHAR ::= + // atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / quoted_specials + // list_wildcards ::= "%" / "*" + // quoted_specials ::= <"> / "\" + // + // tag ::= 1* (named "xtag") + // + + class xtag : public component + { + public: + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("tag"); + + size_t pos = *currentPos; + + bool end = false; + + string tagString; + 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; + } + } + + if (tagString == string(*parser.getTag())) + { + *currentPos = pos; + } + else + { + // Invalid tag + throw exceptions::invalid_response("", makeResponseLine("tag", line, pos)); + } + } + }; + + + // + // 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) + // + + class number : public component + { + public: + + number(const bool nonZero = false) + : m_nonZero(nonZero), m_value(0) + { + } + + void go(IMAPParser& /* parser */, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("number"); + + 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) + { + m_value = val; + *currentPos = pos; + } + else + { + throw exceptions::invalid_response("", makeResponseLine("number", line, pos)); + } + } + + private: + + const bool m_nonZero; + unsigned long m_value; + + public: + + unsigned long value() const { return (m_value); } + }; + + + // 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) + { + } + }; + + + // + // text ::= 1*TEXT_CHAR + // + // CHAR ::= + // TEXT_CHAR ::= + // + + class text : public component + { + public: + + text(bool allow8bits = false, const char except = 0) + : m_allow8bits(allow8bits), m_except(except) + { + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("text"); + + 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) + { + m_value.resize(len); + std::copy(line.begin() + *currentPos, line.begin() + pos, m_value.begin()); + + *currentPos = pos; + } + else + { + throw exceptions::invalid_response("", makeResponseLine("text", line, pos)); + } + } + + private: + + string m_value; + const bool m_allow8bits; + const char m_except; + + public: + + const string& value() const { return (m_value); } + }; + + + class text8 : public text + { + public: + + text8() : text(true) + { + } + }; + + + template + class text_except : public text + { + public: + + text_except() : text(false, C) + { + } + }; + + + template + class text8_except : public text + { + public: + + text8_except() : text(true, C) + { + } + }; + + + // + // QUOTED_CHAR ::= / "\" quoted_specials + // quoted_specials ::= <"> / "\" + // TEXT_CHAR ::= + // CHAR ::= + // + + class QUOTED_CHAR : public component + { + public: + + void go(IMAPParser& /* parser */, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("quoted_char"); + + size_t pos = *currentPos; + + const unsigned char c = static_cast (pos < line.length() ? line[pos] : 0); + + if (c >= 0x01 && c <= 0x7f && // 0x01 - 0x7f + c != '"' && c != '\\' && // quoted_specials + c != '\r' && c != '\n') // CR and LF + { + m_value = c; + *currentPos = pos + 1; + } + else if (c == '\\' && pos + 1 < line.length() && + (line[pos + 1] == '"' || line[pos + 1] == '\\')) + { + m_value = line[pos + 1]; + *currentPos = pos + 2; + } + else + { + throw exceptions::invalid_response("", makeResponseLine("QUOTED_CHAR", line, pos)); + } + } + + private: + + char m_value; + + public: + + char value() const { return (m_value); } + }; + + + // + // quoted ::= <"> *QUOTED_CHAR <"> + // QUOTED_CHAR ::= / "\" quoted_specials + // quoted_specials ::= <"> / "\" + // TEXT_CHAR ::= + // CHAR ::= + // + + class quoted_text : public component + { + public: + + void go(IMAPParser& /* parser */, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("quoted_text"); + + size_t pos = *currentPos; + size_t len = 0; + bool valid = false; + + m_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 == '\\') + m_value += c; + else + { + m_value += '\\'; + m_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 + { + m_value += c; + + ++pos; + ++len; + } + else + { + valid = false; + end = true; + } + } + } + + if (valid) + { + *currentPos = pos; + } + else + { + throw exceptions::invalid_response("", makeResponseLine("quoted_text", line, pos)); + } + } + + private: + + string m_value; + + public: + + const string& value() const { return (m_value); } + }; + + + // + // nil ::= "NIL" + // + + class NIL : public component + { + public: + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("NIL"); + + size_t pos = *currentPos; + + parser.checkWithArg (line, &pos, "nil"); + + *currentPos = pos; + } + }; + + + // + // string ::= quoted / literal ----> named 'xstring' + // + // nil ::= "NIL" + // quoted ::= <"> *QUOTED_CHAR <"> + // QUOTED_CHAR ::= / "\" quoted_specials + // quoted_specials ::= <"> / "\" + // TEXT_CHAR ::= + // CHAR ::= + // literal ::= "{" number "}" CRLF *CHAR8 + // ;; Number represents the number of CHAR8 octets + // CHAR8 ::= + // + + class xstring : public component + { + public: + + xstring(const bool canBeNIL = false, component* comp = NULL, const int data = 0) + : m_canBeNIL(canBeNIL), m_component(comp), m_data(data) + { + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("string"); + + size_t pos = *currentPos; + + if (m_canBeNIL && + parser.checkWithArg (line, &pos, "nil", true)) + { + // NIL + } + else + { + pos = *currentPos; + + // quoted ::= <"> *QUOTED_CHAR <"> + if (parser.check >(line, &pos, true)) + { + std::auto_ptr text(parser.get (line, &pos)); + parser.check >(line, &pos); + + if (parser.m_literalHandler != NULL) + { + literalHandler::target* target = + parser.m_literalHandler->targetFor(*m_component, m_data); + + if (target != NULL) + { + m_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); + } + + delete (target); + } + else + { + m_value = text->value(); + } + } + else + { + m_value = text->value(); + } + + DEBUG_FOUND("string[quoted]", ""); + } + // literal ::= "{" number "}" CRLF *CHAR8 + else + { + parser.check >(line, &pos); + + number* num = parser.get (line, &pos); + + const size_t length = num->value(); + delete (num); + + parser.check >(line, &pos); + + parser.check (line, &pos); + + + if (parser.m_literalHandler != NULL) + { + literalHandler::target* target = + parser.m_literalHandler->targetFor(*m_component, m_data); + + if (target != NULL) + { + m_value = "[literal-handler]"; + + parser.m_progress = target->progressListener(); + parser.readLiteral(*target, length); + parser.m_progress = NULL; + + delete (target); + } + else + { + literalHandler::targetString target(NULL, m_value); + parser.readLiteral(target, length); + } + } + else + { + literalHandler::targetString target(NULL, m_value); + parser.readLiteral(target, length); + } + + line += parser.readLine(); + + DEBUG_FOUND("string[literal]", ""); + } + } + + *currentPos = pos; + } + + private: + + bool m_canBeNIL; + string m_value; + + component* m_component; + const int m_data; + + public: + + const string& value() const { return (m_value); } + void setValue(const string& val) { m_value = val; } + }; + + + // + // nstring ::= string / nil + // + + class nstring : public xstring + { + public: + + nstring(component* comp = NULL, const int data = 0) + : xstring(true, comp, data) + { + } + }; + + + // + // astring ::= atom / string + // + + class astring : public component + { + public: + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("astring"); + + size_t pos = *currentPos; + + xstring* str = NULL; + + if ((str = parser.get (line, &pos, true))) + { + m_value = str->value(); + delete (str); + } + else + { + atom* at = parser.get (line, &pos); + m_value = at->value(); + delete (at); + } + + *currentPos = pos; + } + + private: + + string m_value; + + public: + + const string& value() const { return (m_value); } + }; + + + // + // atom ::= 1*ATOM_CHAR + // + // ATOM_CHAR ::= + // atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / quoted_specials + // CHAR ::= + // CTL ::= + // list_wildcards ::= "%" / "*" + // quoted_specials ::= <"> / "\" + // SPACE ::= + // + + class atom : public component + { + public: + + void go(IMAPParser& /* parser */, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("atom"); + + 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) + { + m_value.resize(len); + std::copy(line.begin() + *currentPos, line.begin() + pos, m_value.begin()); + + *currentPos = pos; + } + else + { + throw exceptions::invalid_response("", makeResponseLine("atom", line, pos)); + } + } + + private: + + string m_value; + + public: + + const string& value() const { return (m_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: + + special_atom(const char* str) + : m_string(str) // 'string' must be in lower-case + { + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT(string("special_atom(") + m_string + ")"); + + size_t pos = *currentPos; + + atom::go(parser, line, &pos); + + 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) + { + throw exceptions::invalid_response("", makeResponseLine(string("special_atom <") + m_string + ">", line, pos)); + } + else + { + *currentPos = pos; + } + } + + private: + + const char* m_string; + }; + + + // + // text_mime2 ::= "=?" "?" "?" "?=" + // ;; Syntax defined in [MIME-HDRS] + // + + class text_mime2 : public component + { + public: + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("text_mime2"); + + size_t pos = *currentPos; + + atom* theCharset = NULL, *theEncoding = NULL; + text* theText = NULL; + + try + { + parser.check >(line, &pos); + + theCharset = parser.get (line, &pos); + + parser.check >(line, &pos); + + theEncoding = parser.get (line, &pos); + + parser.check >(line, &pos); + + theText = parser.get >(line, &pos); + + parser.check >(line, &pos); + parser.check value()[0] == 'Q') + { + // Quoted-printable + theEncoder = new utility::encoder::qpEncoder(); + theEncoder->getProperties()["rfc2047"] = true; + } + else if (theEncoding->value()[0] == 'b' || theEncoding->value()[0] == 'B') + { + // Base64 + theEncoder = new utility::encoder::b64Encoder(); + } + + if (theEncoder) + { + utility::inputStreamStringAdapter in(theText->value()); + utility::outputStreamStringAdapter out(m_value); + + theEncoder->decode(in, out); + delete (theEncoder); + } + // No decoder available + else + { + m_value = theText->value(); + } + + delete (theEncoding); + delete (theText); + + *currentPos = pos; + } + + private: + + vmime::charset m_charset; + string m_value; + + public: + + const vmime::charset& charset() const { return (m_charset); } + const string& value() const { return (m_value); } + }; + + + // seq-number = nz-number / "*" + // ; message sequence number (COPY, FETCH, STORE + // ; commands) or unique identifier (UID COPY, + // ; UID FETCH, UID STORE commands). + + class seq_number : public component + { + public: + + seq_number() + : m_number(NULL), m_star(false) + { + } + + ~seq_number() + { + delete m_number; + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("seq_number"); + + size_t pos = *currentPos; + + if (parser.check >(line, &pos, true)) + { + m_star = true; + m_number = NULL; + } + else + { + m_star = false; + m_number = parser.get (line, &pos); + } + + *currentPos = pos; + } + + private: + + IMAPParser::number* m_number; + bool m_star; + + public: + + const IMAPParser::number* number() const { return m_number; } + bool star() const { return m_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. + + class seq_range : public component + { + public: + + seq_range() + : m_first(NULL), m_last(NULL) + { + } + + ~seq_range() + { + delete m_first; + delete m_last; + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("seq_range"); + + size_t pos = *currentPos; + + m_first = parser.get (line, &pos); + + parser.check >(line, &pos); + + m_last = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::seq_number* m_first; + IMAPParser::seq_number* m_last; + + public: + + const IMAPParser::seq_number* first() const { return m_first; } + const IMAPParser::seq_number* last() const { return m_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 + + class sequence_set : public component + { + public: + + sequence_set() + : m_number(NULL), m_range(NULL), m_nextSet(NULL) + { + } + + ~sequence_set() + { + delete m_number; + delete m_range; + delete m_nextSet; + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("sequence_set"); + + size_t pos = *currentPos; + + if ((m_range = parser.get (line, &pos, true)) == NULL) + m_number = parser.get (line, &pos); + + if (parser.check >(line, &pos, true)) + m_nextSet = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::seq_number* m_number; + IMAPParser::seq_range* m_range; + IMAPParser::sequence_set* m_nextSet; + + public: + + const IMAPParser::seq_number* seq_number() const { return m_number; } + const IMAPParser::seq_range* seq_range() const { return m_range; } + const IMAPParser::sequence_set* next_sequence_set() const { return m_nextSet; } + }; + + + // mod-sequence-value = 1*DIGIT + // ;; Positive unsigned 64-bit integer + // ;; (mod-sequence) + // ;; (1 <= n < 18,446,744,073,709,551,615) + + class mod_sequence_value : public component + { + public: + + mod_sequence_value() + : m_value(0) + { + } + + void go(IMAPParser& /* parser */, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("mod_sequence_value"); + + 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; + } + } + + m_value = val; + + *currentPos = pos; + } + + private: + + vmime_uint64 m_value; + + public: + + vmime_uint64 value() const { return m_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 + // + + class flag : public component + { + public: + + flag() + : m_type(UNKNOWN), m_flag_keyword(NULL) + { + } + + ~flag() + { + delete (m_flag_keyword); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("flag_keyword"); + + size_t pos = *currentPos; + + if (parser.check >(line, &pos, true)) + { + if (parser.check >(line, &pos, true)) + { + m_type = STAR; + } + else + { + atom* at = parser.get (line, &pos); + const string name = utility::stringUtils::toLower(at->value()); + delete (at); + + if (name == "answered") + m_type = ANSWERED; + else if (name == "flagged") + m_type = FLAGGED; + else if (name == "deleted") + m_type = DELETED; + else if (name == "seen") + m_type = SEEN; + else if (name == "draft") + m_type = DRAFT; + else + { + m_type = UNKNOWN; + m_name = name; + } + } + } + else + { + m_type = KEYWORD_OR_EXTENSION; + m_flag_keyword = parser.get (line, &pos); + } + + *currentPos = pos; + } + + + enum Type + { + UNKNOWN, + ANSWERED, + FLAGGED, + DELETED, + SEEN, + DRAFT, + KEYWORD_OR_EXTENSION, + STAR // * = custom flags allowed + }; + + private: + + Type m_type; + string m_name; + + IMAPParser::atom* m_flag_keyword; + + public: + + Type type() const { return (m_type); } + const string& name() const { return (m_name); } + + const IMAPParser::atom* flag_keyword() const { return (m_flag_keyword); } + }; + + + // + // flag_list ::= "(" #flag ")" + // + + class flag_list : public component + { + public: + + ~flag_list() + { + for (std::vector ::iterator it = m_flags.begin() ; + it != m_flags.end() ; ++it) + { + delete (*it); + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("flag_list"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + + while (!parser.check >(line, &pos, true)) + { + m_flags.push_back(parser.get (line, &pos)); + parser.check (line, &pos, true); + } + + *currentPos = pos; + } + + private: + + std::vector m_flags; + + public: + + const std::vector & flags() const { return (m_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. + // + + class mailbox : public component + { + public: + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("mailbox"); + + size_t pos = *currentPos; + + if (parser.checkWithArg (line, &pos, "inbox", true)) + { + m_type = INBOX; + m_name = "INBOX"; + } + else + { + m_type = OTHER; + + astring* astr = parser.get (line, &pos); + m_name = astr->value(); + delete (astr); + } + + *currentPos = pos; + } + + + enum Type + { + INBOX, + OTHER + }; + + private: + + Type m_type; + string m_name; + + public: + + Type type() const { return (m_type); } + const string& name() const { return (m_name); } + }; + + + // + // mailbox_flag := "\Marked" / "\Noinferiors" / + // "\Noselect" / "\Unmarked" / flag_extension + // + + class mailbox_flag : public component + { + public: + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("mailbox_flag"); + + size_t pos = *currentPos; + + if (parser.check >(line, &pos, true)) + { + atom* at = parser.get (line, &pos); + const string name = utility::stringUtils::toLower(at->value()); + delete (at); + + if (name == "marked") + m_type = MARKED; + else if (name == "noinferiors") + m_type = NOINFERIORS; + else if (name == "noselect") + m_type = NOSELECT; + else if (name == "unmarked") + m_type = UNMARKED; + else + { + m_type = UNKNOWN; + m_name = "\\" + name; + } + } + else + { + atom* at = parser.get (line, &pos); + const string name = utility::stringUtils::toLower(at->value()); + delete (at); + + m_type = UNKNOWN; + m_name = name; + } + + *currentPos = pos; + } + + + enum Type + { + UNKNOWN, + MARKED, + NOINFERIORS, + NOSELECT, + UNMARKED + }; + + private: + + Type m_type; + string m_name; + + public: + + Type type() const { return (m_type); } + const string& name() const { return (m_name); } + }; + + + // + // mailbox_flag_list ::= "(" #(mailbox_flag) ")" + // + + class mailbox_flag_list : public component + { + public: + + ~mailbox_flag_list() + { + for (std::vector ::iterator it = m_flags.begin() ; + it != m_flags.end() ; ++it) + { + delete (*it); + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("mailbox_flag_list"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + + while (!parser.check >(line, &pos, true)) + { + m_flags.push_back(parser.get (line, &pos)); + parser.check (line, &pos, true); + } + + *currentPos = pos; + } + + private: + + std::vector m_flags; + + public: + + const std::vector & flags() const { return (m_flags); } + }; + + + // + // mailbox_list ::= mailbox_flag_list SPACE + // (<"> QUOTED_CHAR <"> / nil) SPACE mailbox + // + + class mailbox_list : public component + { + public: + + mailbox_list() + : m_mailbox_flag_list(NULL), + m_mailbox(NULL), m_quoted_char('\0') + { + } + + ~mailbox_list() + { + delete (m_mailbox_flag_list); + delete (m_mailbox); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("mailbox_list"); + + size_t pos = *currentPos; + + m_mailbox_flag_list = parser.get (line, &pos); + + parser.check (line, &pos); + + if (!parser.check (line, &pos, true)) + { + parser.check >(line, &pos); + + QUOTED_CHAR* qc = parser.get (line, &pos); + m_quoted_char = qc->value(); + delete (qc); + + parser.check >(line, &pos); + } + + parser.check (line, &pos); + + m_mailbox = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::mailbox_flag_list* m_mailbox_flag_list; + IMAPParser::mailbox* m_mailbox; + char m_quoted_char; + + public: + + const IMAPParser::mailbox_flag_list* mailbox_flag_list() const { return (m_mailbox_flag_list); } + const IMAPParser::mailbox* mailbox() const { return (m_mailbox); } + char quoted_char() const { return (m_quoted_char); } + }; + + + // + // auth_type ::= atom + // ;; Defined by [IMAP-AUTH] + // + + class auth_type : public component + { + public: + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("auth_type"); + + atom* at = parser.get (line, currentPos); + m_name = utility::stringUtils::toLower(at->value()); + delete (at); + + if (m_name == "kerberos_v4") + m_type = KERBEROS_V4; + else if (m_name == "gssapi") + m_type = GSSAPI; + else if (m_name == "skey") + m_type = SKEY; + else + m_type = UNKNOWN; + } + + + enum Type + { + UNKNOWN, + + // RFC 1731 - IMAP4 Authentication Mechanisms + KERBEROS_V4, + GSSAPI, + SKEY + }; + + private: + + Type m_type; + string m_name; + + public: + + Type type() const { return (m_type); } + const string name() const { return (m_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 + // + + class status_att_val : public component + { + public: + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("status_att"); + + size_t pos = *currentPos; + + // "HIGHESTMODSEQ" SP mod-sequence-valzer + if (parser.checkWithArg (line, &pos, "highestmodseq", true)) + { + m_type = HIGHESTMODSEQ; + + parser.check (line, &pos); + m_value = parser.get (line, &pos); + } + else + { + if (parser.checkWithArg (line, &pos, "messages", true)) + { + m_type = MESSAGES; + } + else if (parser.checkWithArg (line, &pos, "recent", true)) + { + m_type = RECENT; + } + else if (parser.checkWithArg (line, &pos, "uidnext", true)) + { + m_type = UIDNEXT; + } + else if (parser.checkWithArg (line, &pos, "uidvalidity", true)) + { + m_type = UIDVALIDITY; + } + else + { + parser.checkWithArg (line, &pos, "unseen"); + m_type = UNSEEN; + } + + parser.check (line, &pos); + m_value = parser.get (line, &pos); + } + + *currentPos = pos; + } + + + enum Type + { + // Extensions + HIGHESTMODSEQ, + + // Standard IMAP + MESSAGES, + RECENT, + UIDNEXT, + UIDVALIDITY, + UNSEEN + }; + + private: + + Type m_type; + IMAPParser::component* m_value; + + public: + + Type type() const { return (m_type); } + + const IMAPParser::number* value_as_number() const + { + return dynamic_cast (m_value); + } + + const IMAPParser::mod_sequence_value* value_as_mod_sequence_value() const + { + return dynamic_cast (m_value); + } + }; + + + // status-att-list = status-att-val *(SP status-att-val) + + class status_att_list : public component + { + public: + + ~status_att_list() + { + for (std::vector ::iterator it = m_values.begin() ; + it != m_values.end() ; ++it) + { + delete *it; + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("status_att_list"); + + size_t pos = *currentPos; + + m_values.push_back(parser.get (line, &pos)); + + while (parser.check (line, &pos, true)) + m_values.push_back(parser.get (line, &pos)); + + *currentPos = pos; + } + + private: + + std::vector m_values; + + public: + + const std::vector & values() const { return m_values; } + }; + + + // + // capability ::= "AUTH=" auth_type / atom + // ;; New capabilities MUST begin with "X" or be + // ;; registered with IANA as standard or standards-track + // + + class capability : public component + { + public: + + capability() + : m_auth_type(NULL), m_atom(NULL) + { + } + + ~capability() + { + delete (m_auth_type); + delete (m_atom); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("capability"); + + size_t pos = *currentPos; + + class atom* at = parser.get (line, &pos); + + string value = at->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; + m_auth_type = parser.get (value, &pos); + delete (at); + } + else + { + m_atom = at; + } + + *currentPos = pos; + } + + private: + + IMAPParser::auth_type* m_auth_type; + IMAPParser::atom* m_atom; + + public: + + const IMAPParser::auth_type* auth_type() const { return (m_auth_type); } + const IMAPParser::atom* atom() const { return (m_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. + // + + class capability_data : public component + { + public: + + ~capability_data() + { + for (std::vector ::iterator it = m_capabilities.begin() ; + it != m_capabilities.end() ; ++it) + { + delete (*it); + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("capability_data"); + + size_t pos = *currentPos; + + parser.checkWithArg (line, &pos, "capability"); + + while (parser.check (line, &pos, true)) + { + capability* cap; + + if (parser.isStrict() || m_capabilities.empty()) + cap = parser.get (line, &pos); + else + cap = parser.get (line, &pos, /* noThrow */ true); // allow SPACE at end of line (Apple iCloud IMAP server) + + if (cap == NULL) break; + + m_capabilities.push_back(cap); + } + + *currentPos = pos; + } + + private: + + std::vector m_capabilities; + + public: + + const std::vector & capabilities() const { return (m_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 <"> + // + + class date_time : public component + { + public: + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("date_time"); + + size_t pos = *currentPos; + + // <"> date_day_fixed "-" date_month "-" date_year + parser.check >(line, &pos); + parser.check (line, &pos, true); + + std::auto_ptr nd(parser.get (line, &pos)); + + parser.check >(line, &pos); + + std::auto_ptr amo(parser.get (line, &pos)); + + parser.check >(line, &pos); + + std::auto_ptr ny(parser.get (line, &pos)); + + parser.check (line, &pos, true); + + // 2digit ":" 2digit ":" 2digit + std::auto_ptr nh(parser.get (line, &pos)); + + parser.check >(line, &pos); + + std::auto_ptr nmi(parser.get (line, &pos)); + + parser.check >(line, &pos); + + std::auto_ptr ns(parser.get (line, &pos)); + + parser.check (line, &pos, true); + + // ("+" / "-") 4digit + int sign = 1; + + if (!(parser.check >(line, &pos, true))) + parser.check >(line, &pos); + + std::auto_ptr nz(parser.get (line, &pos)); + + parser.check >(line, &pos); + + + m_datetime.setHour(static_cast (std::min(std::max(nh->value(), 0ul), 23ul))); + m_datetime.setMinute(static_cast (std::min(std::max(nmi->value(), 0ul), 59ul))); + m_datetime.setSecond(static_cast (std::min(std::max(ns->value(), 0ul), 59ul))); + + const int zone = static_cast (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 (std::min(std::max(nd->value(), 1ul), 31ul))); + m_datetime.setYear(static_cast (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; + } + + private: + + vmime::datetime m_datetime; + }; + + + // + // header_fld_name ::= astring + // + + typedef astring header_fld_name; + + + // + // header_list ::= "(" 1#header_fld_name ")" + // + + class header_list : public component + { + public: + + ~header_list() + { + for (std::vector ::iterator it = m_fld_names.begin() ; + it != m_fld_names.end() ; ++it) + { + delete (*it); + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("header_list"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + + while (!parser.check >(line, &pos, true)) + { + m_fld_names.push_back(parser.get (line, &pos)); + parser.check (line, &pos, true); + } + + *currentPos = pos; + } + + private: + + std::vector m_fld_names; + + public: + + const std::vector & fld_names() const { return (m_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. + // + + class body_extension : public component + { + public: + + body_extension() + : m_nstring(NULL), m_number(NULL) + { + } + + ~body_extension() + { + delete (m_nstring); + delete (m_number); + + for (std::vector ::iterator it = m_body_extensions.begin() ; + it != m_body_extensions.end() ; ++it) + { + delete (*it); + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + size_t pos = *currentPos; + + if (parser.check >(line, &pos, true)) + { + m_body_extensions.push_back + (parser.get (line, &pos)); + + while (!parser.check >(line, &pos, true)) + { + m_body_extensions.push_back(parser.get (line, &pos)); + parser.check (line, &pos, true); + } + } + else + { + if (!(m_nstring = parser.get (line, &pos, true))) + m_number = parser.get (line, &pos); + } + + *currentPos = pos; + } + + private: + + IMAPParser::nstring* m_nstring; + IMAPParser::number* m_number; + + std::vector m_body_extensions; + + public: + + IMAPParser::nstring* nstring() const { return (m_nstring); } + IMAPParser::number* number() const { return (m_number); } + + const std::vector & body_extensions() const { return (m_body_extensions); } + }; + + + // + // section_text ::= "HEADER" / "HEADER.FIELDS" [".NOT"] + // SPACE header_list / "TEXT" / "MIME" + // + + class section_text : public component + { + public: + + section_text() + : m_header_list(NULL) + { + } + + ~section_text() + { + delete (m_header_list); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("section_text"); + + size_t pos = *currentPos; + + // "HEADER.FIELDS" [".NOT"] SPACE header_list + const bool b1 = parser.checkWithArg (line, &pos, "header.fields.not", true); + const bool b2 = (b1 ? false : parser.checkWithArg (line, &pos, "header.fields", true)); + + if (b1 || b2) + { + m_type = b1 ? HEADER_FIELDS_NOT : HEADER_FIELDS; + + parser.check (line, &pos); + m_header_list = parser.get (line, &pos); + } + // "HEADER" + else if (parser.checkWithArg (line, &pos, "header", true)) + { + m_type = HEADER; + } + // "MIME" + else if (parser.checkWithArg (line, &pos, "mime", true)) + { + m_type = MIME; + } + // "TEXT" + else + { + m_type = TEXT; + + parser.checkWithArg (line, &pos, "text"); + } + + *currentPos = pos; + } + + + enum Type + { + HEADER, + HEADER_FIELDS, + HEADER_FIELDS_NOT, + MIME, + TEXT + }; + + private: + + Type m_type; + IMAPParser::header_list* m_header_list; + + public: + + Type type() const { return (m_type); } + const IMAPParser::header_list* header_list() const { return (m_header_list); } + }; + + + // + // section ::= "[" [section_text / (nz_number *["." nz_number] + // ["." (section_text / "MIME")])] "]" + // + + class section : public component + { + public: + + section() + : m_section_text1(NULL), m_section_text2(NULL) + { + } + + ~section() + { + delete (m_section_text1); + delete (m_section_text2); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("section"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + + if (!parser.check >(line, &pos, true)) + { + if (!(m_section_text1 = parser.get (line, &pos, true))) + { + nz_number* num = parser.get (line, &pos); + m_nz_numbers.push_back(static_cast (num->value())); + delete (num); + + while (parser.check >(line, &pos, true)) + { + if ((num = parser.get (line, &pos, true))) + { + m_nz_numbers.push_back(static_cast (num->value())); + delete (num); + } + else + { + m_section_text2 = parser.get (line, &pos); + break; + } + } + } + + parser.check >(line, &pos); + } + + *currentPos = pos; + } + + private: + + section_text* m_section_text1; + section_text* m_section_text2; + std::vector m_nz_numbers; + + public: + + const section_text* section_text1() const { return (m_section_text1); } + const section_text* section_text2() const { return (m_section_text2); } + const std::vector & nz_numbers() const { return (m_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 ")" + // + + class address : public component + { + public: + + address() + : m_addr_name(NULL), m_addr_adl(NULL), + m_addr_mailbox(NULL), m_addr_host(NULL) + { + } + + ~address() + { + delete (m_addr_name); + delete (m_addr_adl); + delete (m_addr_mailbox); + delete (m_addr_host); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("address"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + m_addr_name = parser.get (line, &pos); + parser.check (line, &pos); + m_addr_adl = parser.get (line, &pos); + parser.check (line, &pos); + m_addr_mailbox = parser.get (line, &pos); + parser.check (line, &pos); + m_addr_host = parser.get (line, &pos); + parser.check >(line, &pos); + + *currentPos = pos; + } + + private: + + nstring* m_addr_name; + nstring* m_addr_adl; + nstring* m_addr_mailbox; + nstring* m_addr_host; + + public: + + nstring* addr_name() const { return (m_addr_name); } + nstring* addr_adl() const { return (m_addr_adl); } + nstring* addr_mailbox() const { return (m_addr_mailbox); } + nstring* addr_host() const { return (m_addr_host); } + }; + + + // + // address_list ::= "(" 1*address ")" / nil + // + + class address_list : public component + { + public: + + ~address_list() + { + for (std::vector ::iterator it = m_addresses.begin() ; + it != m_addresses.end() ; ++it) + { + delete (*it); + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("address_list"); + + size_t pos = *currentPos; + + if (!parser.check (line, &pos, true)) + { + parser.check >(line, &pos); + + while (!parser.check >(line, &pos, true)) + { + m_addresses.push_back(parser.get
(line, &pos)); + parser.check (line, &pos, true); + } + } + + *currentPos = pos; + } + + private: + + std::vector m_addresses; + + public: + + const std::vector & addresses() const { return (m_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 ")" + // + + class envelope : public component + { + public: + + envelope() + : m_env_date(NULL), m_env_subject(NULL), + m_env_from(NULL), m_env_sender(NULL), m_env_reply_to(NULL), + m_env_to(NULL), m_env_cc(NULL), m_env_bcc(NULL), + m_env_in_reply_to(NULL), m_env_message_id(NULL) + { + } + + ~envelope() + { + delete (m_env_date); + delete (m_env_subject); + delete (m_env_from); + delete (m_env_sender); + delete (m_env_reply_to); + delete (m_env_to); + delete (m_env_cc); + delete (m_env_bcc); + delete (m_env_in_reply_to); + delete (m_env_message_id); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("envelope"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + + m_env_date = parser.get (line, &pos); + parser.check (line, &pos); + + m_env_subject = parser.get (line, &pos); + parser.check (line, &pos); + + m_env_from = parser.get (line, &pos); + parser.check (line, &pos); + + m_env_sender = parser.get (line, &pos); + parser.check (line, &pos); + + m_env_reply_to = parser.get (line, &pos); + parser.check (line, &pos); + + m_env_to = parser.get (line, &pos); + parser.check (line, &pos); + + m_env_cc = parser.get (line, &pos); + parser.check (line, &pos); + + m_env_bcc = parser.get (line, &pos); + parser.check (line, &pos); + + m_env_in_reply_to = parser.get (line, &pos); + parser.check (line, &pos); + + m_env_message_id = parser.get (line, &pos); + + parser.check >(line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::env_date* m_env_date; + IMAPParser::env_subject* m_env_subject; + IMAPParser::env_from* m_env_from; + IMAPParser::env_sender* m_env_sender; + IMAPParser::env_reply_to* m_env_reply_to; + IMAPParser::env_to* m_env_to; + IMAPParser::env_cc* m_env_cc; + IMAPParser::env_bcc* m_env_bcc; + IMAPParser::env_in_reply_to* m_env_in_reply_to; + IMAPParser::env_message_id* m_env_message_id; + + public: + + const IMAPParser::env_date* env_date() const { return (m_env_date); } + const IMAPParser::env_subject* env_subject() const { return (m_env_subject); } + const IMAPParser::env_from* env_from() const { return (m_env_from); } + const IMAPParser::env_sender* env_sender() const { return (m_env_sender); } + const IMAPParser::env_reply_to* env_reply_to() const { return (m_env_reply_to); } + const IMAPParser::env_to* env_to() const { return (m_env_to); } + const IMAPParser::env_cc* env_cc() const { return (m_env_cc); } + const IMAPParser::env_bcc* env_bcc() const { return (m_env_bcc); } + const IMAPParser::env_in_reply_to* env_in_reply_to() const { return (m_env_in_reply_to); } + const IMAPParser::env_message_id* env_message_id() const { return (m_env_message_id); } + }; + + + // + // body_fld_desc ::= nstring + // + + typedef nstring body_fld_desc; + + + // + // body_fld_id ::= nstring + // + + typedef nstring body_fld_id; + + + // + // body_fld_md5 ::= nstring + // + + typedef nstring body_fld_md5; + + + // + // body_fld_octets ::= number + // + + typedef number body_fld_octets; + + + // + // body_fld_lines ::= number + // + + typedef number body_fld_lines; + + + // + // body_fld_enc ::= (<"> ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + // "QUOTED-PRINTABLE") <">) / string + // + + typedef xstring body_fld_enc; + + + // + // body_fld_param_item ::= string SPACE string + // + + class body_fld_param_item : public component + { + public: + + body_fld_param_item() + : m_string1(NULL), m_string2(NULL) + { + } + + ~body_fld_param_item() + { + delete (m_string1); + delete (m_string2); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body_fld_param_item"); + + size_t pos = *currentPos; + + if (!parser.isStrict()) + { + // Some servers send an instead of a here: + // eg. ... (CHARSET "X-UNKNOWN") ... + if (!(m_string1 = parser.get (line, &pos, true))) + { + std::auto_ptr at(parser.get (line, &pos)); + + m_string1 = new xstring(); + m_string1->setValue(at->value()); + } + } + else + { + m_string1 = parser.get (line, &pos); + } + + parser.check (line, &pos); + m_string2 = parser.get (line, &pos); + + DEBUG_FOUND("body_fld_param_item", "<" << m_string1->value() << ", " << m_string2->value() << ">"); + + *currentPos = pos; + } + + private: + + xstring* m_string1; + xstring* m_string2; + + public: + + const xstring* string1() const { return (m_string1); } + const xstring* string2() const { return (m_string2); } + }; + + + // + // body_fld_param ::= "(" 1#(body_fld_param_item) ")" / nil + // + + class body_fld_param : public component + { + public: + + ~body_fld_param() + { + for (std::vector ::iterator it = m_items.begin() ; + it != m_items.end() ; ++it) + { + delete (*it); + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body_fld_param"); + + size_t pos = *currentPos; + + if (parser.check >(line, &pos, true)) + { + m_items.push_back(parser.get (line, &pos)); + + while (!parser.check >(line, &pos, true)) + { + parser.check (line, &pos); + m_items.push_back(parser.get (line, &pos)); + } + } + else + { + parser.check (line, &pos); + } + + *currentPos = pos; + } + + private: + + std::vector m_items; + + public: + + const std::vector & items() const { return (m_items); } + }; + + + // + // body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil + // + + class body_fld_dsp : public component + { + public: + + body_fld_dsp() + : m_string(NULL), m_body_fld_param(NULL) + { + } + + ~body_fld_dsp() + { + delete (m_string); + delete (m_body_fld_param); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body_fld_dsp"); + + size_t pos = *currentPos; + + if (parser.check >(line, &pos, true)) + { + m_string = parser.get (line, &pos); + parser.check (line, &pos); + m_body_fld_param = parser.get (line, &pos); + parser.check >(line, &pos); + } + else + { + parser.check (line, &pos); + } + + *currentPos = pos; + } + + private: + + class xstring* m_string; + class body_fld_param* m_body_fld_param; + + public: + + const class xstring* str() const { return (m_string); } + const class body_fld_param* body_fld_param() const { return (m_body_fld_param); } + }; + + + // + // body_fld_lang ::= nstring / "(" 1#string ")" + // + + class body_fld_lang : public component + { + public: + + ~body_fld_lang() + { + for (std::vector ::iterator it = m_strings.begin() ; + it != m_strings.end() ; ++it) + { + delete (*it); + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body_fld_lang"); + + size_t pos = *currentPos; + + if (parser.check >(line, &pos, true)) + { + m_strings.push_back(parser.get (line, &pos)); + + while (!parser.check >(line, &pos, true)) + { + parser.check (line, &pos); + m_strings.push_back(parser.get (line, &pos)); + } + } + else + { + m_strings.push_back(parser.get (line, &pos)); + } + + *currentPos = pos; + } + + private: + + std::vector m_strings; + + public: + + const std::vector & strings() const { return (m_strings); } + }; + + + // + // body_fields ::= body_fld_param SPACE body_fld_id SPACE + // body_fld_desc SPACE body_fld_enc SPACE + // body_fld_octets + // + + class body_fields : public component + { + public: + + body_fields() + : m_body_fld_param(NULL), m_body_fld_id(NULL), + m_body_fld_desc(NULL), m_body_fld_enc(NULL), m_body_fld_octets(NULL) + { + } + + ~body_fields() + { + delete (m_body_fld_param); + delete (m_body_fld_id); + delete (m_body_fld_desc); + delete (m_body_fld_enc); + delete (m_body_fld_octets); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body_fields"); + + size_t pos = *currentPos; + + m_body_fld_param = parser.get (line, &pos); + parser.check (line, &pos); + m_body_fld_id = parser.get (line, &pos); + parser.check (line, &pos); + m_body_fld_desc = parser.get (line, &pos); + parser.check (line, &pos); + m_body_fld_enc = parser.get (line, &pos); + parser.check (line, &pos); + m_body_fld_octets = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::body_fld_param* m_body_fld_param; + IMAPParser::body_fld_id* m_body_fld_id; + IMAPParser::body_fld_desc* m_body_fld_desc; + IMAPParser::body_fld_enc* m_body_fld_enc; + IMAPParser::body_fld_octets* m_body_fld_octets; + + public: + + const IMAPParser::body_fld_param* body_fld_param() const { return (m_body_fld_param); } + const IMAPParser::body_fld_id* body_fld_id() const { return (m_body_fld_id); } + const IMAPParser::body_fld_desc* body_fld_desc() const { return (m_body_fld_desc); } + const IMAPParser::body_fld_enc* body_fld_enc() const { return (m_body_fld_enc); } + const IMAPParser::body_fld_octets* body_fld_octets() const { return (m_body_fld_octets); } + }; + + + // + // media_subtype ::= string + // ;; Defined in [MIME-IMT] + // + + typedef xstring media_subtype; + + + // + // media_text ::= <"> "TEXT" <"> SPACE media_subtype + // ;; Defined in [MIME-IMT] + // + + class media_text : public component + { + public: + + media_text() + : m_media_subtype(NULL) + { + } + + ~media_text() + { + delete (m_media_subtype); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("media_text"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + parser.checkWithArg (line, &pos, "text"); + parser.check >(line, &pos); + parser.check (line, &pos); + + m_media_subtype = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::media_subtype* m_media_subtype; + + public: + + const IMAPParser::media_subtype* media_subtype() const { return (m_media_subtype); } + }; + + + // + // media_message ::= <"> "MESSAGE" <"> SPACE <"> "RFC822" <"> + // ;; Defined in [MIME-IMT] + // + + class media_message : public component + { + public: + + media_message() + : m_media_subtype(NULL) + { + } + + ~media_message() + { + delete m_media_subtype; + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("media_message"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + parser.checkWithArg (line, &pos, "message"); + parser.check >(line, &pos); + parser.check (line, &pos); + + //parser.check >(line, &pos); + //parser.checkWithArg (line, &pos, "rfc822"); + //parser.check >(line, &pos); + + m_media_subtype = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::media_subtype* m_media_subtype; + + public: + + const IMAPParser::media_subtype* media_subtype() const { return (m_media_subtype); } + }; + + + // + // media_basic ::= (<"> ("APPLICATION" / "AUDIO" / "IMAGE" / + // "MESSAGE" / "VIDEO") <">) / string) + // SPACE media_subtype + // ;; Defined in [MIME-IMT] + + class media_basic : public component + { + public: + + media_basic() + : m_media_type(NULL), m_media_subtype(NULL) + { + } + + ~media_basic() + { + delete (m_media_type); + delete (m_media_subtype); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("media_basic"); + + size_t pos = *currentPos; + + m_media_type = parser.get (line, &pos); + + parser.check (line, &pos); + + m_media_subtype = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::xstring* m_media_type; + IMAPParser::media_subtype* m_media_subtype; + + public: + + const IMAPParser::xstring* media_type() const { return (m_media_type); } + const IMAPParser::media_subtype* media_subtype() const { return (m_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 + // + + class body_ext_1part : public component + { + public: + + body_ext_1part() + : m_body_fld_md5(NULL), m_body_fld_dsp(NULL), m_body_fld_lang(NULL) + { + } + + ~body_ext_1part() + { + delete (m_body_fld_md5); + delete (m_body_fld_dsp); + delete (m_body_fld_lang); + + for (std::vector ::iterator it = m_body_extensions.begin() ; + it != m_body_extensions.end() ; ++it) + { + delete (*it); + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body_ext_1part"); + + size_t pos = *currentPos; + + m_body_fld_md5 = parser.get (line, &pos); + + // [SPACE body_fld_dsp + if (parser.check (line, &pos, true)) + { + m_body_fld_dsp = parser.get (line, &pos); + + // [SPACE body_fld_lang + if (parser.check (line, &pos, true)) + { + m_body_fld_lang = parser.get (line, &pos); + + // [SPACE 1#body_extension] + if (parser.check (line, &pos, true)) + { + m_body_extensions.push_back + (parser.get (line, &pos)); + + parser.check (line, &pos, true); + + body_extension* ext = NULL; + + while ((ext = parser.get (line, &pos, true)) != NULL) + { + m_body_extensions.push_back(ext); + parser.check (line, &pos, true); + } + } + } + } + + *currentPos = pos; + } + + private: + + IMAPParser::body_fld_md5* m_body_fld_md5; + IMAPParser::body_fld_dsp* m_body_fld_dsp; + IMAPParser::body_fld_lang* m_body_fld_lang; + + std::vector m_body_extensions; + + public: + + const IMAPParser::body_fld_md5* body_fld_md5() const { return (m_body_fld_md5); } + const IMAPParser::body_fld_dsp* body_fld_dsp() const { return (m_body_fld_dsp); } + const IMAPParser::body_fld_lang* body_fld_lang() const { return (m_body_fld_lang); } + + const std::vector body_extensions() const { return (m_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 + + class body_ext_mpart : public component + { + public: + + body_ext_mpart() + : m_body_fld_param(NULL), m_body_fld_dsp(NULL), m_body_fld_lang(NULL) + { + } + + ~body_ext_mpart() + { + delete (m_body_fld_param); + delete (m_body_fld_dsp); + delete (m_body_fld_lang); + + for (std::vector ::iterator it = m_body_extensions.begin() ; + it != m_body_extensions.end() ; ++it) + { + delete (*it); + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body_ext_mpart"); + + size_t pos = *currentPos; + + m_body_fld_param = parser.get (line, &pos); + + // [SPACE body_fld_dsp SPACE body_fld_lang [SPACE 1#body_extension]] + if (parser.check (line, &pos, true)) + { + m_body_fld_dsp = parser.get (line, &pos); + parser.check (line, &pos); + m_body_fld_lang = parser.get (line, &pos); + + // [SPACE 1#body_extension] + if (parser.check (line, &pos, true)) + { + m_body_extensions.push_back + (parser.get (line, &pos)); + + parser.check (line, &pos, true); + + body_extension* ext = NULL; + + while ((ext = parser.get (line, &pos, true)) != NULL) + { + m_body_extensions.push_back(ext); + parser.check (line, &pos, true); + } + } + } + + *currentPos = pos; + } + + private: + + IMAPParser::body_fld_param* m_body_fld_param; + IMAPParser::body_fld_dsp* m_body_fld_dsp; + IMAPParser::body_fld_lang* m_body_fld_lang; + + std::vector m_body_extensions; + + public: + + const IMAPParser::body_fld_param* body_fld_param() const { return (m_body_fld_param); } + const IMAPParser::body_fld_dsp* body_fld_dsp() const { return (m_body_fld_dsp); } + const IMAPParser::body_fld_lang* body_fld_lang() const { return (m_body_fld_lang); } + + const std::vector body_extensions() const { return (m_body_extensions); } + }; + + + // + // body_type_basic ::= media_basic SPACE body_fields + // ;; MESSAGE subtype MUST NOT be "RFC822" + // + + class body_type_basic : public component + { + public: + + body_type_basic() + : m_media_basic(NULL), m_body_fields(NULL) + { + } + + ~body_type_basic() + { + delete (m_media_basic); + delete (m_body_fields); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body_type_basic"); + + size_t pos = *currentPos; + + m_media_basic = parser.get (line, &pos); + parser.check (line, &pos); + m_body_fields = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::media_basic* m_media_basic; + IMAPParser::body_fields* m_body_fields; + + public: + + const IMAPParser::media_basic* media_basic() const { return (m_media_basic); } + const IMAPParser::body_fields* body_fields() const { return (m_body_fields); } + }; + + + // + // body_type_msg ::= media_message SPACE body_fields SPACE envelope + // SPACE body SPACE body_fld_lines + // + + class xbody; + typedef xbody body; + + class body_type_msg : public component + { + public: + + body_type_msg() + : m_media_message(NULL), m_body_fields(NULL), + m_envelope(NULL), m_body(NULL), m_body_fld_lines(NULL) + { + } + + ~body_type_msg() + { + delete (m_media_message); + delete (m_body_fields); + delete (m_envelope); + delete (m_body); + delete (m_body_fld_lines); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body_type_msg"); + + size_t pos = *currentPos; + + m_media_message = parser.get (line, &pos); + parser.check (line, &pos); + m_body_fields = parser.get (line, &pos); + parser.check (line, &pos); + + // BUGFIX: made SPACE optional. This is not standard, but some servers + // seem to return responses like that... + m_envelope = parser.get (line, &pos); + parser.check (line, &pos, true); + m_body = parser.get (line, &pos); + parser.check (line, &pos, true); + m_body_fld_lines = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::media_message* m_media_message; + IMAPParser::body_fields* m_body_fields; + IMAPParser::envelope* m_envelope; + IMAPParser::xbody* m_body; + IMAPParser::body_fld_lines* m_body_fld_lines; + + public: + + const IMAPParser::media_message* media_message() const { return (m_media_message); } + const IMAPParser::body_fields* body_fields() const { return (m_body_fields); } + const IMAPParser::envelope* envelope() const { return (m_envelope); } + const IMAPParser::xbody* body() const { return (m_body); } + const IMAPParser::body_fld_lines* body_fld_lines() const { return (m_body_fld_lines); } + }; + + + // + // body_type_text ::= media_text SPACE body_fields SPACE body_fld_lines + // + + class body_type_text : public component + { + public: + + body_type_text() + : m_media_text(NULL), + m_body_fields(NULL), m_body_fld_lines(NULL) + { + } + + ~body_type_text() + { + delete (m_media_text); + delete (m_body_fields); + delete (m_body_fld_lines); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body_type_text"); + + size_t pos = *currentPos; + + m_media_text = parser.get (line, &pos); + parser.check (line, &pos); + m_body_fields = parser.get (line, &pos); + parser.check (line, &pos); + m_body_fld_lines = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::media_text* m_media_text; + IMAPParser::body_fields* m_body_fields; + IMAPParser::body_fld_lines* m_body_fld_lines; + + public: + + const IMAPParser::media_text* media_text() const { return (m_media_text); } + const IMAPParser::body_fields* body_fields() const { return (m_body_fields); } + const IMAPParser::body_fld_lines* body_fld_lines() const { return (m_body_fld_lines); } + }; + + + // + // body_type_1part ::= (body_type_basic / body_type_msg / body_type_text) + // [SPACE body_ext_1part] + // + + class body_type_1part : public component + { + public: + + body_type_1part() + : m_body_type_basic(NULL), m_body_type_msg(NULL), + m_body_type_text(NULL), m_body_ext_1part(NULL) + { + } + + ~body_type_1part() + { + delete (m_body_type_basic); + delete (m_body_type_msg); + delete (m_body_type_text); + + delete (m_body_ext_1part); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body_type_1part"); + + size_t pos = *currentPos; + + if (!(m_body_type_text = parser.get (line, &pos, true))) + if (!(m_body_type_msg = parser.get (line, &pos, true))) + m_body_type_basic = parser.get (line, &pos); + + if (parser.check (line, &pos, true)) + { + m_body_ext_1part = parser.get (line, &pos, true); + + if (!m_body_ext_1part) + --pos; + } + + *currentPos = pos; + } + + private: + + IMAPParser::body_type_basic* m_body_type_basic; + IMAPParser::body_type_msg* m_body_type_msg; + IMAPParser::body_type_text* m_body_type_text; + + IMAPParser::body_ext_1part* m_body_ext_1part; + + public: + + const IMAPParser::body_type_basic* body_type_basic() const { return (m_body_type_basic); } + const IMAPParser::body_type_msg* body_type_msg() const { return (m_body_type_msg); } + const IMAPParser::body_type_text* body_type_text() const { return (m_body_type_text); } + + const IMAPParser::body_ext_1part* body_ext_1part() const { return (m_body_ext_1part); } + }; + + + // + // body_type_mpart ::= 1*body SPACE media_subtype + // [SPACE body_ext_mpart] + // + + class body_type_mpart : public component + { + public: + + body_type_mpart() + : m_media_subtype(NULL), m_body_ext_mpart(NULL) + { + } + + ~body_type_mpart() + { + delete (m_media_subtype); + delete (m_body_ext_mpart); + + for (std::vector ::iterator it = m_list.begin() ; + it != m_list.end() ; ++it) + { + delete (*it); + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body_type_mpart"); + + size_t pos = *currentPos; + + m_list.push_back(parser.get (line, &pos)); + + for (xbody* b ; (b = parser.get (line, &pos, true)) ; ) + m_list.push_back(b); + + parser.check (line, &pos); + + m_media_subtype = parser.get (line, &pos); + + if (parser.check (line, &pos, true)) + m_body_ext_mpart = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::media_subtype* m_media_subtype; + IMAPParser::body_ext_mpart* m_body_ext_mpart; + + std::vector m_list; + + public: + + const std::vector & list() const { return (m_list); } + + const IMAPParser::media_subtype* media_subtype() const { return (m_media_subtype); } + const IMAPParser::body_ext_mpart* body_ext_mpart() const { return (m_body_ext_mpart); } + }; + + + // + // xbody ::= "(" body_type_1part / body_type_mpart ")" + // + + class xbody : public component + { + public: + + xbody() + : m_body_type_1part(NULL), m_body_type_mpart(NULL) + { + } + + ~xbody() + { + delete (m_body_type_1part); + delete (m_body_type_mpart); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("body"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + + if (!(m_body_type_mpart = parser.get (line, &pos, true))) + m_body_type_1part = parser.get (line, &pos); + + parser.check >(line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::body_type_1part* m_body_type_1part; + IMAPParser::body_type_mpart* m_body_type_mpart; + + public: + + const IMAPParser::body_type_1part* body_type_1part() const { return (m_body_type_1part); } + const IMAPParser::body_type_mpart* body_type_mpart() const { return (m_body_type_mpart); } + }; + + + // + // uniqueid ::= nz_number + // ;; Strictly ascending + // + // 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 ")" + + class msg_att_item : public component + { + public: + + msg_att_item() + : m_date_time(NULL), m_number(NULL), m_envelope(NULL), + m_uniqueid(NULL), m_nstring(NULL), m_body(NULL), m_flag_list(NULL), + m_section(NULL), m_mod_sequence_value(NULL) + + { + } + + ~msg_att_item() + { + delete (m_date_time); + delete (m_number); + delete (m_envelope); + delete (m_uniqueid); + delete (m_nstring); + delete (m_body); + delete (m_flag_list); + delete (m_section); + delete m_mod_sequence_value; + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("msg_att_item"); + + size_t pos = *currentPos; + + // "ENVELOPE" SPACE envelope + if (parser.checkWithArg (line, &pos, "envelope", true)) + { + m_type = ENVELOPE; + + parser.check (line, &pos); + m_envelope = parser.get (line, &pos); + } + // "FLAGS" SPACE "(" #(flag / "\Recent") ")" + else if (parser.checkWithArg (line, &pos, "flags", true)) + { + m_type = FLAGS; + + parser.check (line, &pos); + + m_flag_list = parser.get (line, &pos); + } + // "INTERNALDATE" SPACE date_time + else if (parser.checkWithArg (line, &pos, "internaldate", true)) + { + m_type = INTERNALDATE; + + parser.check (line, &pos); + m_date_time = parser.get (line, &pos); + } + // "RFC822" ".HEADER" SPACE nstring + else if (parser.checkWithArg (line, &pos, "rfc822.header", true)) + { + m_type = RFC822_HEADER; + + parser.check (line, &pos); + + m_nstring = parser.get (line, &pos); + } + // "RFC822" ".TEXT" SPACE nstring + else if (parser.checkWithArg (line, &pos, "rfc822.text", true)) + { + m_type = RFC822_TEXT; + + parser.check (line, &pos); + + m_nstring = parser.getWithArgs + (line, &pos, this, RFC822_TEXT); + } + // "RFC822.SIZE" SPACE number + else if (parser.checkWithArg (line, &pos, "rfc822.size", true)) + { + m_type = RFC822_SIZE; + + parser.check (line, &pos); + m_number = parser.get (line, &pos); + } + // "RFC822" SPACE nstring + else if (parser.checkWithArg (line, &pos, "rfc822", true)) + { + m_type = RFC822; + + parser.check (line, &pos); + + m_nstring = parser.get (line, &pos); + } + // "BODY" "STRUCTURE" SPACE body + else if (parser.checkWithArg (line, &pos, "bodystructure", true)) + { + m_type = BODY_STRUCTURE; + + parser.check (line, &pos); + + m_body = parser.get (line, &pos); + } + // "BODY" section ["<" number ">"] SPACE nstring + // "BODY" SPACE body + else if (parser.checkWithArg (line, &pos, "body", true)) + { + m_section = parser.get (line, &pos, true); + + // "BODY" section ["<" number ">"] SPACE nstring + if (m_section != NULL) + { + m_type = BODY_SECTION; + + if (parser.check >(line, &pos, true)) + { + m_number = parser.get (line, &pos); + parser.check '> >(line, &pos); + } + + parser.check (line, &pos); + + m_nstring = parser.getWithArgs + (line, &pos, this, BODY_SECTION); + } + // "BODY" SPACE body + else + { + m_type = BODY; + + parser.check (line, &pos); + + m_body = parser.get (line, &pos); + } + } + // "MODSEQ" SP "(" mod_sequence_value ")" + else if (parser.checkWithArg (line, &pos, "modseq", true)) + { + m_type = MODSEQ; + + parser.check (line, &pos); + parser.check >(line, &pos); + + m_mod_sequence_value = parser.get (line, &pos); + + parser.check >(line, &pos); + } + // "UID" SPACE uniqueid + else + { + m_type = UID; + + parser.checkWithArg (line, &pos, "uid"); + parser.check (line, &pos); + + m_uniqueid = parser.get (line, &pos); + } + + *currentPos = pos; + } + + + enum Type + { + ENVELOPE, + FLAGS, + INTERNALDATE, + RFC822, + RFC822_SIZE, + RFC822_HEADER, + RFC822_TEXT, + BODY, + BODY_SECTION, + BODY_STRUCTURE, + UID, + MODSEQ + }; + + private: + + Type m_type; + + IMAPParser::date_time* m_date_time; + IMAPParser::number* m_number; + IMAPParser::envelope* m_envelope; + IMAPParser::nz_number* m_uniqueid; + IMAPParser::nstring* m_nstring; + IMAPParser::xbody* m_body; + IMAPParser::flag_list* m_flag_list; + IMAPParser::section* m_section; + IMAPParser::mod_sequence_value* m_mod_sequence_value; + + public: + + Type type() const { return (m_type); } + + const IMAPParser::date_time* date_time() const { return (m_date_time); } + const IMAPParser::number* number() const { return (m_number); } + const IMAPParser::envelope* envelope() const { return (m_envelope); } + const IMAPParser::nz_number* unique_id() const { return (m_uniqueid); } + const IMAPParser::nstring* nstring() const { return (m_nstring); } + const IMAPParser::xbody* body() const { return (m_body); } + const IMAPParser::flag_list* flag_list() const { return (m_flag_list); } + const IMAPParser::section* section() const { return (m_section); } + const IMAPParser::mod_sequence_value* mod_sequence_value() { return m_mod_sequence_value; } + }; + + + // + // msg_att ::= "(" 1#(msg_att_item) ")" + // + + class msg_att : public component + { + public: + + ~msg_att() + { + for (std::vector ::iterator it = m_items.begin() ; + it != m_items.end() ; ++it) + { + delete (*it); + } + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("msg_att"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + + m_items.push_back(parser.get (line, &pos)); + + while (!parser.check >(line, &pos, true)) + { + parser.check (line, &pos); + m_items.push_back(parser.get (line, &pos)); + } + + *currentPos = pos; + } + + private: + + std::vector m_items; + + public: + + const std::vector & items() const { return (m_items); } + }; + + + // + // message_data ::= nz_number SPACE ("EXPUNGE" / + // ("FETCH" SPACE msg_att)) + // + + class message_data : public component + { + public: + + message_data() + : m_number(0), m_msg_att(NULL) + { + } + + ~message_data() + { + delete (m_msg_att); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("message_data"); + + size_t pos = *currentPos; + + nz_number* num = parser.get (line, &pos); + m_number = static_cast (num->value()); + delete (num); + + parser.check (line, &pos); + + if (parser.checkWithArg (line, &pos, "expunge", true)) + { + m_type = EXPUNGE; + } + else + { + parser.checkWithArg (line, &pos, "fetch"); + + parser.check (line, &pos); + + m_type = FETCH; + m_msg_att = parser.get (line, &pos); + } + + *currentPos = pos; + } + + + enum Type + { + EXPUNGE, + FETCH + }; + + private: + + Type m_type; + unsigned int m_number; + IMAPParser::msg_att* m_msg_att; + + public: + + Type type() const { return (m_type); } + unsigned int number() const { return (m_number); } + const IMAPParser::msg_att* msg_att() const { return (m_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 / + // atom [SPACE 1*] + // + // IMAP Extension for Conditional STORE (RFC-4551): + // + // resp-text-code =/ "HIGHESTMODSEQ" SP mod-sequence-value / + // "NOMODSEQ" / + // "MODIFIED" SP set + + class resp_text_code : public component + { + public: + + resp_text_code() + : m_nz_number(NULL), m_atom(NULL), m_flag_list(NULL), + m_text(NULL), m_capability_data(NULL) + { + } + + ~resp_text_code() + { + delete (m_nz_number); + delete (m_atom); + delete (m_flag_list); + delete (m_text); + delete m_capability_data; + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("resp_text_code"); + + size_t pos = *currentPos; + + // "ALERT" + if (parser.checkWithArg (line, &pos, "alert", true)) + { + m_type = ALERT; + } + // "PARSE" + else if (parser.checkWithArg (line, &pos, "parse", true)) + { + m_type = PARSE; + } + // capability_data + else if ((m_capability_data = parser.get (line, &pos, true))) + { + m_type = CAPABILITY; + } + // "PERMANENTFLAGS" SPACE flag_list + else if (parser.checkWithArg (line, &pos, "permanentflags", true)) + { + m_type = PERMANENTFLAGS; + + parser.check (line, &pos); + + m_flag_list = parser.get (line, &pos); + } + // "READ-ONLY" + else if (parser.checkWithArg (line, &pos, "read-only", true)) + { + m_type = READ_ONLY; + } + // "READ-WRITE" + else if (parser.checkWithArg (line, &pos, "read-write", true)) + { + m_type = READ_WRITE; + } + // "TRYCREATE" + else if (parser.checkWithArg (line, &pos, "trycreate", true)) + { + m_type = TRYCREATE; + } + // "UIDVALIDITY" SPACE nz_number + else if (parser.checkWithArg (line, &pos, "uidvalidity", true)) + { + m_type = UIDVALIDITY; + + parser.check (line, &pos); + m_nz_number = parser.get (line, &pos); + } + // "UIDNEXT" SPACE nz_number + else if (parser.checkWithArg (line, &pos, "uidnext", true)) + { + m_type = UIDNEXT; + + parser.check (line, &pos); + m_nz_number = parser.get (line, &pos); + } + // "UNSEEN" SPACE nz_number + else if (parser.checkWithArg (line, &pos, "unseen", true)) + { + m_type = UNSEEN; + + parser.check (line, &pos); + m_nz_number = parser.get (line, &pos); + } + // "HIGHESTMODSEQ" SP mod-sequence-value + else if (parser.checkWithArg (line, &pos, "highestmodseq", true)) + { + m_type = HIGHESTMODSEQ; + + parser.check (line, &pos); + m_mod_sequence_value = parser.get (line, &pos); + } + // "NOMODSEQ" + else if (parser.checkWithArg (line, &pos, "nomodseq", true)) + { + m_type = NOMODSEQ; + } + // "MODIFIED" SP sequence-set + else if (parser.checkWithArg (line, &pos, "modified", true)) + { + m_type = MODIFIED; + + parser.check (line, &pos); + + m_sequence_set = parser.get (line, &pos); + } + // atom [SPACE 1*] + else + { + m_type = OTHER; + + m_atom = parser.get (line, &pos); + + if (parser.check (line, &pos, true)) + m_text = parser.get >(line, &pos); + } + + *currentPos = pos; + } + + + enum Type + { + // Extensions + HIGHESTMODSEQ, + NOMODSEQ, + MODIFIED, + + // Standard IMAP + ALERT, + PARSE, + CAPABILITY, + PERMANENTFLAGS, + READ_ONLY, + READ_WRITE, + TRYCREATE, + UIDVALIDITY, + UIDNEXT, + UNSEEN, + OTHER + }; + + private: + + Type m_type; + + IMAPParser::nz_number* m_nz_number; + IMAPParser::atom* m_atom; + IMAPParser::flag_list* m_flag_list; + IMAPParser::text* m_text; + IMAPParser::mod_sequence_value* m_mod_sequence_value; + IMAPParser::sequence_set* m_sequence_set; + IMAPParser::capability_data* m_capability_data; + + public: + + Type type() const { return (m_type); } + + const IMAPParser::nz_number* nz_number() const { return (m_nz_number); } + const IMAPParser::atom* atom() const { return (m_atom); } + const IMAPParser::flag_list* flag_list() const { return (m_flag_list); } + const IMAPParser::text* text() const { return (m_text); } + const IMAPParser::mod_sequence_value* mod_sequence_value() const { return m_mod_sequence_value; } + const IMAPParser::sequence_set* sequence_set() const { return m_sequence_set; } + const IMAPParser::capability_data* capability_data() const { return m_capability_data; } + }; + + + // + // resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text) + // ;; text SHOULD NOT begin with "[" or "=" + + class resp_text : public component + { + public: + + resp_text() + : m_resp_text_code(NULL) + { + } + + ~resp_text() + { + delete (m_resp_text_code); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("resp_text"); + + size_t pos = *currentPos; + + if (parser.check >(line, &pos, true)) + { + m_resp_text_code = parser.get (line, &pos); + + parser.check >(line, &pos); + parser.check (line, &pos, true); + } + + text_mime2* text1 = parser.get (line, &pos, true); + + if (text1 != NULL) + { + m_text = text1->value(); + delete (text1); + } + else + { + IMAPParser::text* text2 = + parser.get (line, &pos, true); + + if (text2 != NULL) + { + m_text = text2->value(); + delete (text2); + } + else + { + // Empty response text + } + } + + *currentPos = pos; + } + + private: + + IMAPParser::resp_text_code* m_resp_text_code; + string m_text; + + public: + + const IMAPParser::resp_text_code* resp_text_code() const { return (m_resp_text_code); } + const string& text() const { return (m_text); } + }; + + + // + // continue_req ::= "+" SPACE (resp_text / base64) + // + + class continue_req : public component + { + public: + + continue_req() + : m_resp_text(NULL) + { + } + + ~continue_req() + { + delete (m_resp_text); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("continue_req"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + + if (!parser.isStrict()) + { + // Some servers do not send SPACE when response text is empty + if (parser.check (line, &pos, true)) + m_resp_text = parser.get (line, &pos); + else + m_resp_text = new IMAPParser::resp_text(); // empty + } + else + { + parser.check (line, &pos); + + m_resp_text = parser.get (line, &pos); + } + + parser.check (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::resp_text* m_resp_text; + + public: + + const IMAPParser::resp_text* resp_text() const { return (m_resp_text); } + }; + + + // + // resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text + // ;; Status condition + // + + class resp_cond_state : public component + { + public: + + resp_cond_state() + : m_resp_text(NULL), m_status(BAD) + { + } + + ~resp_cond_state() + { + delete (m_resp_text); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("resp_cond_state"); + + size_t pos = *currentPos; + + if (parser.checkWithArg (line, &pos, "ok", true)) + { + m_status = OK; + } + else if (parser.checkWithArg (line, &pos, "no", true)) + { + m_status = NO; + } + else + { + parser.checkWithArg (line, &pos, "bad"); + m_status = BAD; + } + + parser.check (line, &pos); + + m_resp_text = parser.get (line, &pos); + + *currentPos = pos; + } + + + enum Status + { + OK, + NO, + BAD + }; + + private: + + IMAPParser::resp_text* m_resp_text; + Status m_status; + + public: + + const IMAPParser::resp_text* resp_text() const { return (m_resp_text); } + Status status() const { return (m_status); } + }; + + + // + // resp_cond_bye ::= "BYE" SPACE resp_text + // + + class resp_cond_bye : public component + { + public: + + resp_cond_bye() + : m_resp_text(NULL) + { + } + + ~resp_cond_bye() + { + delete (m_resp_text); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("resp_cond_bye"); + + size_t pos = *currentPos; + + parser.checkWithArg (line, &pos, "bye"); + + parser.check (line, &pos); + + m_resp_text = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::resp_text* m_resp_text; + + public: + + const IMAPParser::resp_text* resp_text() const { return (m_resp_text); } + }; + + + // + // resp_cond_auth ::= ("OK" / "PREAUTH") SPACE resp_text + // ;; Authentication condition + // + + class resp_cond_auth : public component + { + public: + + resp_cond_auth() + : m_resp_text(NULL) + { + } + + ~resp_cond_auth() + { + delete (m_resp_text); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("resp_cond_auth"); + + size_t pos = *currentPos; + + if (parser.checkWithArg (line, &pos, "ok", true)) + { + m_cond = OK; + } + else + { + parser.checkWithArg (line, &pos, "preauth"); + + m_cond = PREAUTH; + } + + parser.check (line, &pos); + + m_resp_text = parser.get (line, &pos); + + *currentPos = pos; + } + + + enum Condition + { + OK, + PREAUTH + }; + + private: + + Condition m_cond; + IMAPParser::resp_text* m_resp_text; + + public: + + Condition condition() const { return (m_cond); } + const IMAPParser::resp_text* resp_text() const { return (m_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" + // + + class mailbox_data : public component + { + public: + + mailbox_data() + : m_number(NULL), m_mailbox_flag_list(NULL), m_mailbox_list(NULL), + m_mailbox(NULL), m_text(NULL), m_status_att_list(NULL) + { + } + + ~mailbox_data() + { + delete (m_number); + delete (m_mailbox_flag_list); + delete (m_mailbox_list); + delete (m_mailbox); + delete (m_text); + + for (std::vector ::iterator it = m_search_nz_number_list.begin() ; + it != m_search_nz_number_list.end() ; ++it) + { + delete (*it); + } + + delete m_status_att_list; + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("mailbox_data"); + + size_t pos = *currentPos; + + m_number = parser.get (line, &pos, true); + + if (m_number) + { + parser.check (line, &pos); + + if (parser.checkWithArg (line, &pos, "exists", true)) + { + m_type = EXISTS; + } + else + { + parser.checkWithArg (line, &pos, "recent"); + + m_type = RECENT; + } + } + else + { + // "FLAGS" SPACE mailbox_flag_list + if (parser.checkWithArg (line, &pos, "flags", true)) + { + parser.check (line, &pos); + + m_mailbox_flag_list = parser.get (line, &pos); + + m_type = FLAGS; + } + // "LIST" SPACE mailbox_list + else if (parser.checkWithArg (line, &pos, "list", true)) + { + parser.check (line, &pos); + + m_mailbox_list = parser.get (line, &pos); + + m_type = LIST; + } + // "LSUB" SPACE mailbox_list + else if (parser.checkWithArg (line, &pos, "lsub", true)) + { + parser.check (line, &pos); + + m_mailbox_list = parser.get (line, &pos); + + m_type = LSUB; + } + // "MAILBOX" SPACE text + else if (parser.checkWithArg (line, &pos, "mailbox", true)) + { + parser.check (line, &pos); + + m_text = parser.get (line, &pos); + + m_type = MAILBOX; + } + // "SEARCH" [SPACE 1#nz_number] + else if (parser.checkWithArg (line, &pos, "search", true)) + { + if (parser.check (line, &pos, true)) + { + m_search_nz_number_list.push_back + (parser.get (line, &pos)); + + while (parser.check (line, &pos, true)) + { + m_search_nz_number_list.push_back + (parser.get (line, &pos)); + } + } + + m_type = SEARCH; + } + // "STATUS" SPACE mailbox SPACE + // "(" [status_att_list] ")" + else + { + parser.checkWithArg (line, &pos, "status"); + parser.check (line, &pos); + + m_mailbox = parser.get (line, &pos); + + parser.check (line, &pos); + + parser.check >(line, &pos); + + m_status_att_list = parser.get (line, &pos, true); + + parser.check >(line, &pos); + + m_type = STATUS; + } + } + + *currentPos = pos; + } + + + enum Type + { + FLAGS, + LIST, + LSUB, + MAILBOX, + SEARCH, + STATUS, + EXISTS, + RECENT + }; + + private: + + Type m_type; + + IMAPParser::number* m_number; + IMAPParser::mailbox_flag_list* m_mailbox_flag_list; + IMAPParser::mailbox_list* m_mailbox_list; + IMAPParser::mailbox* m_mailbox; + IMAPParser::text* m_text; + std::vector m_search_nz_number_list; + IMAPParser::status_att_list* m_status_att_list; + + public: + + Type type() const { return (m_type); } + + const IMAPParser::number* number() const { return (m_number); } + const IMAPParser::mailbox_flag_list* mailbox_flag_list() const { return (m_mailbox_flag_list); } + const IMAPParser::mailbox_list* mailbox_list() const { return (m_mailbox_list); } + const IMAPParser::mailbox* mailbox() const { return (m_mailbox); } + const IMAPParser::text* text() const { return (m_text); } + const std::vector & search_nz_number_list() const { return (m_search_nz_number_list); } + const IMAPParser::status_att_list* status_att_list() const { return m_status_att_list; } + }; + + + // + // response_data ::= "*" SPACE (resp_cond_state / resp_cond_bye / + // mailbox_data / message_data / capability_data) CRLF + // + + class response_data : public component + { + public: + + response_data() + : m_resp_cond_state(NULL), m_resp_cond_bye(NULL), + m_mailbox_data(NULL), m_message_data(NULL), m_capability_data(NULL) + { + } + + ~response_data() + { + delete (m_resp_cond_state); + delete (m_resp_cond_bye); + delete (m_mailbox_data); + delete (m_message_data); + delete (m_capability_data); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("response_data"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + parser.check (line, &pos); + + if (!(m_resp_cond_state = parser.get (line, &pos, true))) + if (!(m_resp_cond_bye = parser.get (line, &pos, true))) + if (!(m_mailbox_data = parser.get (line, &pos, true))) + if (!(m_message_data = parser.get (line, &pos, true))) + m_capability_data = parser.get (line, &pos); + + if (!parser.isStrict()) + { + // Allow SPACEs at end of line + while (parser.check (line, &pos, /* noThrow */ true)) + ; + } + + parser.check (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::resp_cond_state* m_resp_cond_state; + IMAPParser::resp_cond_bye* m_resp_cond_bye; + IMAPParser::mailbox_data* m_mailbox_data; + IMAPParser::message_data* m_message_data; + IMAPParser::capability_data* m_capability_data; + + public: + + const IMAPParser::resp_cond_state* resp_cond_state() const { return (m_resp_cond_state); } + const IMAPParser::resp_cond_bye* resp_cond_bye() const { return (m_resp_cond_bye); } + const IMAPParser::mailbox_data* mailbox_data() const { return (m_mailbox_data); } + const IMAPParser::message_data* message_data() const { return (m_message_data); } + const IMAPParser::capability_data* capability_data() const { return (m_capability_data); } + }; + + + class continue_req_or_response_data : public component + { + public: + + continue_req_or_response_data() + : m_continue_req(NULL), m_response_data(NULL) + { + } + + ~continue_req_or_response_data() + { + delete (m_continue_req); + delete (m_response_data); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("continue_req_or_response_data"); + + size_t pos = *currentPos; + + if (!(m_continue_req = parser.get (line, &pos, true))) + m_response_data = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::continue_req* m_continue_req; + IMAPParser::response_data* m_response_data; + + public: + + const IMAPParser::continue_req* continue_req() const { return (m_continue_req); } + const IMAPParser::response_data* response_data() const { return (m_response_data); } + }; + + + // + // response_fatal ::= "*" SPACE resp_cond_bye CRLF + // ;; Server closes connection immediately + // + + class response_fatal : public component + { + public: + + response_fatal() + : m_resp_cond_bye(NULL) + { + } + + ~response_fatal() + { + delete (m_resp_cond_bye); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("response_fatal"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + parser.check (line, &pos); + + m_resp_cond_bye = parser.get (line, &pos); + + if (!parser.isStrict()) + { + // Allow SPACEs at end of line + while (parser.check (line, &pos, /* noThrow */ true)) + ; + } + + parser.check (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::resp_cond_bye* m_resp_cond_bye; + + public: + + const IMAPParser::resp_cond_bye* resp_cond_bye() const { return (m_resp_cond_bye); } + }; + + + // + // response_tagged ::= tag SPACE resp_cond_state CRLF + // + + class response_tagged : public component + { + public: + + response_tagged() + : m_resp_cond_state(NULL) + { + } + + ~response_tagged() + { + delete (m_resp_cond_state); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("response_tagged"); + + size_t pos = *currentPos; + + parser.check (line, &pos); + parser.check (line, &pos); + m_resp_cond_state = parser.get (line, &pos); + + if (!parser.isStrict()) + { + // Allow SPACEs at end of line + while (parser.check (line, &pos, /* noThrow */ true)) + ; + } + + parser.check (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::resp_cond_state* m_resp_cond_state; + + public: + + const IMAPParser::resp_cond_state* resp_cond_state() const { return (m_resp_cond_state); } + }; + + + // + // response_done ::= response_tagged / response_fatal + // + + class response_done : public component + { + public: + + response_done() + : m_response_tagged(NULL), m_response_fatal(NULL) + { + } + + ~response_done() + { + delete (m_response_tagged); + delete (m_response_fatal); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("response_done"); + + size_t pos = *currentPos; + + if (!(m_response_tagged = parser.get (line, &pos, true))) + m_response_fatal = parser.get (line, &pos); + + *currentPos = pos; + } + + private: + + IMAPParser::response_tagged* m_response_tagged; + IMAPParser::response_fatal* m_response_fatal; + + public: + + const IMAPParser::response_tagged* response_tagged() const { return (m_response_tagged); } + const IMAPParser::response_fatal* response_fatal() const { return (m_response_fatal); } + }; + + + // + // response ::= *(continue_req / response_data) response_done + // + + class response : public component + { + public: + + response() + : m_response_done(NULL) + { + } + + ~response() + { + for (std::vector ::iterator + it = m_continue_req_or_response_data.begin() ; + it != m_continue_req_or_response_data.end() ; ++it) + { + delete (*it); + } + + delete (m_response_done); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("response"); + + size_t pos = *currentPos; + string curLine = line; + bool partial = false; // partial response + + IMAPParser::continue_req_or_response_data* resp = NULL; + + while ((resp = parser.get (curLine, &pos, true)) != NULL) + { + m_continue_req_or_response_data.push_back(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) + m_response_done = parser.get (curLine, &pos); + + *currentPos = pos; + } + + + 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; + } + + private: + + std::vector m_continue_req_or_response_data; + IMAPParser::response_done* m_response_done; + + string m_errorLog; + + public: + + const std::vector & continue_req_or_response_data() const { return (m_continue_req_or_response_data); } + const IMAPParser::response_done* response_done() const { return (m_response_done); } + }; + + + // + // greeting ::= "*" SPACE (resp_cond_auth / resp_cond_bye) CRLF + // + + class greeting : public component + { + public: + + greeting() + : m_resp_cond_auth(NULL), m_resp_cond_bye(NULL) + { + } + + ~greeting() + { + delete (m_resp_cond_auth); + delete (m_resp_cond_bye); + } + + void go(IMAPParser& parser, string& line, size_t* currentPos) + { + DEBUG_ENTER_COMPONENT("greeting"); + + size_t pos = *currentPos; + + parser.check >(line, &pos); + parser.check (line, &pos); + + if (!(m_resp_cond_auth = parser.get (line, &pos, true))) + m_resp_cond_bye = parser.get (line, &pos); + + parser.check (line, &pos); + + *currentPos = pos; + } + + void setErrorLog(const string& errorLog) + { + m_errorLog = errorLog; + } + + const string& getErrorLog() const + { + return m_errorLog; + } + + private: + + IMAPParser::resp_cond_auth* m_resp_cond_auth; + IMAPParser::resp_cond_bye* m_resp_cond_bye; + + string m_errorLog; + + public: + + const IMAPParser::resp_cond_auth* resp_cond_auth() const { return (m_resp_cond_auth); } + const IMAPParser::resp_cond_bye* resp_cond_bye() const { return (m_resp_cond_bye); } + }; + + + + // + // The main functions used to parse a response + // + + response* readResponse(literalHandler* lh = NULL) + { + size_t pos = 0; + string line = readLine(); + + m_literalHandler = lh; + response* resp = get (line, &pos); + m_literalHandler = NULL; + + resp->setErrorLog(lastLine()); + + return (resp); + } + + + greeting* readGreeting() + { + size_t pos = 0; + string line = readLine(); + + greeting* greet = get (line, &pos); + + greet->setErrorLog(lastLine()); + + return greet; + } + + + // + // Get a token and advance + // + + template + TYPE* get(string& line, size_t* currentPos, + const bool noThrow = false) + { + component* resp = new TYPE; + return internalGet (resp, line, currentPos, noThrow); + } + + + template + TYPE* getWithArgs(string& line, size_t* currentPos, + ARG1_TYPE arg1, ARG2_TYPE arg2, const bool noThrow = false) + { + component* resp = new TYPE(arg1, arg2); + return internalGet (resp, line, currentPos, noThrow); + } + + +private: + + template + TYPE* internalGet(component* resp, string& line, size_t* currentPos, + const bool noThrow = false) + { + const size_t oldPos = *currentPos; + + try + { + resp->go(*this, line, currentPos); + } + catch (exceptions::operation_timed_out&) + { + // Always rethrow + throw; + } + catch (exception&) + { + *currentPos = oldPos; + + delete (resp); + if (!noThrow) throw; + return (NULL); + } + + return static_cast (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 a token and advance + // + + template + bool check(string& line, size_t* currentPos, + const bool noThrow = false) + { + const size_t oldPos = *currentPos; + + try + { + TYPE term; + term.go(*this, line, currentPos); + } + catch (exceptions::operation_timed_out&) + { + // Always rethrow + throw; + } + catch (exception&) + { + *currentPos = oldPos; + + if (!noThrow) throw; + return false; + } + + return true; + } + + template + bool checkWithArg(string& line, size_t* currentPos, + const ARG_TYPE arg, const bool noThrow = false) + { + const size_t oldPos = *currentPos; + + try + { + TYPE term(arg); + term.go(*this, line, currentPos); + } + catch (exceptions::operation_timed_out&) + { + // Always rethrow + throw; + } + catch (exception&) + { + *currentPos = oldPos; + + if (!noThrow) throw; + return false; + } + + return true; + } + + +private: + + weak_ptr m_tag; + weak_ptr m_socket; + + utility::progressListener* m_progress; + + bool m_strict; + + literalHandler* m_literalHandler; + + weak_ptr m_timeoutHandler; + + + string m_buffer; + + string m_lastLine; + +public: + + // + // Read one 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 + + return (line); + } + + + // + // Read available data from socket stream + // + + void read() + { + string receiveBuffer; + + shared_ptr toh = m_timeoutHandler.lock(); + shared_ptr 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 + { + platform::getHandler()->wait(); + 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 toh = m_timeoutHandler.lock(); + shared_ptr 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 + { + platform::getHandler()->wait(); + 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_progress) + m_progress->stop(count); + } +}; + + +} // imap +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP + +#endif // VMIME_NET_IMAP_IMAPPARSER_HPP_INCLUDED diff --git a/src/vmime/net/imap/IMAPSStore.cpp b/src/vmime/net/imap/IMAPSStore.cpp new file mode 100644 index 00000000..c9e64f5b --- /dev/null +++ b/src/vmime/net/imap/IMAPSStore.cpp @@ -0,0 +1,79 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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/src/vmime/net/imap/IMAPSStore.hpp b/src/vmime/net/imap/IMAPSStore.hpp new file mode 100644 index 00000000..9d27bdd0 --- /dev/null +++ b/src/vmime/net/imap/IMAPSStore.hpp @@ -0,0 +1,71 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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/src/vmime/net/imap/IMAPServiceInfos.cpp b/src/vmime/net/imap/IMAPServiceInfos.cpp new file mode 100644 index 00000000..46dbc2e1 --- /dev/null +++ b/src/vmime/net/imap/IMAPServiceInfos.cpp @@ -0,0 +1,137 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 IMAPServiceInfos::getAvailableProperties() const +{ + std::vector 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/src/vmime/net/imap/IMAPServiceInfos.hpp b/src/vmime/net/imap/IMAPServiceInfos.hpp new file mode 100644 index 00000000..376f4476 --- /dev/null +++ b/src/vmime/net/imap/IMAPServiceInfos.hpp @@ -0,0 +1,91 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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/src/vmime/net/imap/IMAPStore.cpp b/src/vmime/net/imap/IMAPStore.cpp new file mode 100644 index 00000000..a1a8c9ca --- /dev/null +++ b/src/vmime/net/imap/IMAPStore.cpp @@ -0,0 +1,267 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/exception.hpp" +#include "vmime/platform.hpp" + +#include + + +namespace vmime { +namespace net { +namespace imap { + + +IMAPStore::IMAPStore(shared_ptr sess, shared_ptr auth, const bool secured) + : store(sess, getInfosInstance(), auth), m_connection(null), m_isIMAPS(secured) +{ +} + + +IMAPStore::~IMAPStore() +{ + try + { + if (isConnected()) + disconnect(); + } + catch (vmime::exception&) + { + // Ignore + } +} + + +const string IMAPStore::getProtocolName() const +{ + return "imap"; +} + + +shared_ptr IMAPStore::getRootFolder() +{ + if (!isConnected()) + throw exceptions::illegal_state("Not connected"); + + return make_shared + (folder::path(), + dynamicCast (shared_from_this())); +} + + +shared_ptr IMAPStore::getDefaultFolder() +{ + if (!isConnected()) + throw exceptions::illegal_state("Not connected"); + + return make_shared + (folder::path::component("INBOX"), + dynamicCast (shared_from_this())); +} + + +shared_ptr IMAPStore::getFolder(const folder::path& path) +{ + if (!isConnected()) + throw exceptions::illegal_state("Not connected"); + + return make_shared + (path, dynamicCast (shared_from_this())); +} + + +bool IMAPStore::isValidFolderName(const folder::path::component& /* name */) const +{ + return true; +} + + +void IMAPStore::connect() +{ + if (isConnected()) + throw exceptions::already_connected(); + + m_connection = make_shared + (dynamicCast (shared_from_this()), getAuthenticator()); + + try + { + m_connection->connect(); + } + catch (std::exception&) + { + m_connection = null; + throw; + } +} + + +bool IMAPStore::isConnected() const +{ + return (m_connection && m_connection->isConnected()); +} + + +bool IMAPStore::isIMAPS() const +{ + return m_isIMAPS; +} + + +bool IMAPStore::isSecuredConnection() const +{ + if (m_connection == NULL) + return false; + + return m_connection->isSecuredConnection(); +} + + +shared_ptr IMAPStore::getConnectionInfos() const +{ + if (m_connection == NULL) + return null; + + return m_connection->getConnectionInfos(); +} + + +shared_ptr IMAPStore::getConnection() +{ + return m_connection; +} + + +void IMAPStore::disconnect() +{ + if (!isConnected()) + throw exceptions::not_connected(); + + for (std::list ::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(); + + m_connection->send(true, "NOOP", true); + + std::auto_ptr 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 ::iterator it = m_folders.begin() ; + it != m_folders.end() ; ++it) + { + if ((*it)->isOpen()) + (*it)->noop(); + } +} + + +shared_ptr IMAPStore::connection() +{ + return (m_connection); +} + + +void IMAPStore::registerFolder(IMAPFolder* folder) +{ + m_folders.push_back(folder); +} + + +void IMAPStore::unregisterFolder(IMAPFolder* folder) +{ + std::list ::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/src/vmime/net/imap/IMAPStore.hpp b/src/vmime/net/imap/IMAPStore.hpp new file mode 100644 index 00000000..f854fadf --- /dev/null +++ b/src/vmime/net/imap/IMAPStore.hpp @@ -0,0 +1,120 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr auth, const bool secured = false); + ~IMAPStore(); + + const string getProtocolName() const; + + shared_ptr getDefaultFolder(); + shared_ptr getRootFolder(); + shared_ptr 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 getConnectionInfos() const; + shared_ptr getConnection(); + +protected: + + // Connection + shared_ptr m_connection; + + + + shared_ptr connection(); + + + void registerFolder(IMAPFolder* folder); + void unregisterFolder(IMAPFolder* folder); + + std::list 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/src/vmime/net/imap/IMAPTag.cpp b/src/vmime/net/imap/IMAPTag.cpp new file mode 100644 index 00000000..14d12788 --- /dev/null +++ b/src/vmime/net/imap/IMAPTag.cpp @@ -0,0 +1,122 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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); +} + + +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 ('0' + (m_number % 1000) / 100); + m_tag[2] = static_cast ('0' + (m_number % 100) / 10); + m_tag[3] = static_cast ('0' + m_number % 10); +} + + +} // imap +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP + diff --git a/src/vmime/net/imap/IMAPTag.hpp b/src/vmime/net/imap/IMAPTag.hpp new file mode 100644 index 00000000..430a3b10 --- /dev/null +++ b/src/vmime/net/imap/IMAPTag.hpp @@ -0,0 +1,79 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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); + IMAPTag(const IMAPTag& tag); + +public: + + IMAPTag(); + + IMAPTag& operator++(); // ++IMAPTag + const IMAPTag operator++(int); // IMAPTag++ + + int maximumNumber() const; + int number() const; + + operator string() 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/src/vmime/net/imap/IMAPUtils.cpp b/src/vmime/net/imap/IMAPUtils.cpp new file mode 100644 index 00000000..ff81ce71 --- /dev/null +++ b/src/vmime/net/imap/IMAPUtils.cpp @@ -0,0 +1,758 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include +#include + + +namespace vmime { +namespace net { +namespace imap { + + +// static +const string IMAPUtils::quoteString(const string& text) +{ + // + // ATOM_CHAR ::= + // + // atom_specials ::= "(" / ")" / "{" / SPACE / CTL / + // list_wildcards / quoted_specials + // + // list_wildcards ::= "%" / "*" + // + // quoted_specials ::= <"> / "\" + // + // CHAR ::= + // + // CTL ::= + // + + 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 (static_cast (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 + + // 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 (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; + 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))); +} + + +int IMAPUtils::folderTypeFromFlags(const IMAPParser::mailbox_flag_list* list) +{ + // Get folder type + int type = folder::TYPE_CONTAINS_MESSAGES | folder::TYPE_CONTAINS_FOLDERS; + const std::vector & flags = list->flags(); + + for (std::vector ::const_iterator it = flags.begin() ; + it != flags.end() ; ++it) + { + if ((*it)->type() == IMAPParser::mailbox_flag::NOSELECT) + type &= ~folder::TYPE_CONTAINS_MESSAGES; + } + + if (type & folder::TYPE_CONTAINS_MESSAGES) + type &= ~folder::TYPE_CONTAINS_FOLDERS; + + return (type); +} + + +int IMAPUtils::folderFlagsFromFlags(const IMAPParser::mailbox_flag_list* list) +{ + // Get folder flags + int folderFlags = folder::FLAG_CHILDREN; + const std::vector & flags = list->flags(); + + for (std::vector ::const_iterator it = flags.begin() ; + it != flags.end() ; ++it) + { + if ((*it)->type() == IMAPParser::mailbox_flag::NOSELECT) + folderFlags |= folder::FLAG_NO_OPEN; + else if ((*it)->type() == IMAPParser::mailbox_flag::NOINFERIORS) + folderFlags &= ~folder::FLAG_CHILDREN; + } + + return (folderFlags); +} + + +int IMAPUtils::messageFlagsFromFlags(const IMAPParser::flag_list* list) +{ + const std::vector & flagList = list->flags(); + int flags = 0; + + for (std::vector ::const_iterator + it = flagList.begin() ; it != flagList.end() ; ++it) + { + switch ((*it)->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); +} + + +const string IMAPUtils::messageFlagList(const int flags) +{ + std::vector flagList; + + 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"); + + if (!flagList.empty()) + { + std::ostringstream res; + res.imbue(std::locale::classic()); + + res << "("; + + if (flagList.size() >= 2) + { + std::copy(flagList.begin(), flagList.end() - 1, + std::ostream_iterator (res, " ")); + } + + res << *(flagList.end() - 1) << ")"; + + return (res.str()); + } + + return ""; +} + + +// 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 +const string IMAPUtils::buildFetchRequest + (shared_ptr 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 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->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 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 customHeaderFields = options.getHeaderFields(); + std::copy(customHeaderFields.begin(), customHeaderFields.end(), std::back_inserter(headerFields)); + + if (!headerFields.empty()) + { + string list; + + for (std::vector ::iterator it = headerFields.begin() ; + it != headerFields.end() ; ++it) + { + if (it != headerFields.begin()) + list += " "; + + list += *it; + } + + items.push_back("BODY[HEADER.FIELDS (" + list + ")]"); + } + } + + // Build the request text + std::ostringstream command; + command.imbue(std::locale::classic()); + + if (msgs.isUIDSet()) + command << "UID FETCH " << messageSetToSequenceSet(msgs) << " ("; + else + command << "FETCH " << messageSetToSequenceSet(msgs) << " ("; + + for (std::vector ::const_iterator it = items.begin() ; + it != items.end() ; ++it) + { + if (it != items.begin()) command << " "; + command << *it; + } + + command << ")"; + + return command.str(); +} + + +// static +void IMAPUtils::convertAddressList + (const IMAPParser::address_list& src, mailboxList& dest) +{ + for (std::vector ::const_iterator + it = src.addresses().begin() ; it != src.addresses().end() ; ++it) + { + const IMAPParser::address& addr = **it; + + text name; + text::decodeAndUnfold(addr.addr_name()->value(), &name); + + string email = addr.addr_mailbox()->value() + + "@" + addr.addr_host()->value(); + + dest.appendMailbox(make_shared (name, email)); + } +} + + + +class IMAPUIDMessageSetEnumerator : public messageSetEnumerator +{ +public: + + IMAPUIDMessageSetEnumerator() + : m_first(true) + { + } + + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) + { + if (!m_first) + m_oss << ","; + + if (range.getFirst() == range.getLast()) + 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 + 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 (int 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 & list() const + { + return m_list; + } + +public: + + std::vector m_list; +}; + + + +// static +const string IMAPUtils::messageSetToSequenceSet(const messageSet& msgs) +{ + IMAPUIDMessageSetEnumerator en; + msgs.enumerate(en); + + return en.str(); +} + + +// static +const std::vector IMAPUtils::messageSetToNumberList(const messageSet& msgs) +{ + IMAPMessageSetEnumerator en; + msgs.enumerate(en); + + return en.list(); +} + + +} // imap +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP + diff --git a/src/vmime/net/imap/IMAPUtils.hpp b/src/vmime/net/imap/IMAPUtils.hpp new file mode 100644 index 00000000..988b6a2c --- /dev/null +++ b/src/vmime/net/imap/IMAPUtils.hpp @@ -0,0 +1,129 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/mailboxList.hpp" + +#include + + +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); + + static int folderTypeFromFlags(const IMAPParser::mailbox_flag_list* list); + static int folderFlagsFromFlags(const IMAPParser::mailbox_flag_list* list); + + static int messageFlagsFromFlags(const IMAPParser::flag_list* list); + + static const 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 const string buildFetchRequest + (shared_ptr 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); + + /** Returns a list of message sequence numbers given a message set. + * + * @param msgs message set + * @return list of message numbers + */ + static const std::vector messageSetToNumberList(const messageSet& msgs); + +private: + + static const string buildFetchRequestImpl + (shared_ptr 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/src/vmime/net/imap/imap.hpp b/src/vmime/net/imap/imap.hpp new file mode 100644 index 00000000..5e10619a --- /dev/null +++ b/src/vmime/net/imap/imap.hpp @@ -0,0 +1,35 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/maildir/format/courierMaildirFormat.cpp b/src/vmime/net/maildir/format/courierMaildirFormat.cpp new file mode 100644 index 00000000..6d460d5e --- /dev/null +++ b/src/vmime/net/maildir/format/courierMaildirFormat.cpp @@ -0,0 +1,542 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr ctx) + : maildirFormat(ctx) +{ +} + + +const string courierMaildirFormat::getName() const +{ + return "courier"; +} + + +void courierMaildirFormat::createFolder(const folder::path& path) +{ + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); + + if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) + throw exceptions::invalid_folder_name(); + + shared_ptr rootDir = fsf->create + (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); + + shared_ptr newDir = fsf->create + (folderPathToFileSystemPath(path, NEW_DIRECTORY)); + shared_ptr tmpDir = fsf->create + (folderPathToFileSystemPath(path, TMP_DIRECTORY)); + shared_ptr curDir = fsf->create + (folderPathToFileSystemPath(path, CUR_DIRECTORY)); + + rootDir->createDirectory(true); + + newDir->createDirectory(false); + tmpDir->createDirectory(false); + curDir->createDirectory(false); + + shared_ptr maildirFile = fsf->create + (folderPathToFileSystemPath(path, ROOT_DIRECTORY) + / utility::file::path::component("maildirfolder")); + + maildirFile->createFile(); +} + + +void courierMaildirFormat::destroyFolder(const folder::path& path) +{ + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); + + // Recursively delete directories of subfolders + const std::vector folders = listFolders(path, true); + + for (std::vector ::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 folders = listFolders(oldPath, true); + + for (std::vector ::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 fsf = platform::getHandler()->getFileSystemFactory(); + + const utility::file::path oldFSPath = + folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY); + + const utility::file::path newFSPath = + folderPathToFileSystemPath(newPath, ROOT_DIRECTORY); + + shared_ptr rootDir = fsf->create(oldFSPath); + rootDir->rename(newFSPath); +} + + +bool courierMaildirFormat::folderExists(const folder::path& path) const +{ + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); + + shared_ptr rootDir = fsf->create + (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); + + shared_ptr newDir = fsf->create + (folderPathToFileSystemPath(path, NEW_DIRECTORY)); + shared_ptr tmpDir = fsf->create + (folderPathToFileSystemPath(path, TMP_DIRECTORY)); + shared_ptr curDir = fsf->create + (folderPathToFileSystemPath(path, CUR_DIRECTORY)); + + shared_ptr 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 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 courierMaildirFormat::listFolders + (const folder::path& root, const bool recursive) const +{ + // First, list directories + std::vector dirs; + listDirectories(root, dirs, false); + + // Then, map directories to folders + std::vector folders; + + for (std::vector ::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 & dirs, const bool onlyTestForExistence) const +{ + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); + + shared_ptr 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 it = rootDir->getFiles(); + + while (it->hasMoreElements()) + { + shared_ptr 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 fsf = platform::getHandler()->getFileSystemFactory(); + + shared_ptr 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 it = rootDir->getFiles(); + + while (it->hasMoreElements()) + { + shared_ptr file = it->nextElement(); + + if (isSubfolderDirectory(*file)) + { + shared_ptr 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/src/vmime/net/maildir/format/courierMaildirFormat.hpp b/src/vmime/net/maildir/format/courierMaildirFormat.hpp new file mode 100644 index 00000000..b8443426 --- /dev/null +++ b/src/vmime/net/maildir/format/courierMaildirFormat.hpp @@ -0,0 +1,121 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr 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 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 & 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/src/vmime/net/maildir/format/kmailMaildirFormat.cpp b/src/vmime/net/maildir/format/kmailMaildirFormat.cpp new file mode 100644 index 00000000..975752a5 --- /dev/null +++ b/src/vmime/net/maildir/format/kmailMaildirFormat.cpp @@ -0,0 +1,320 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr ctx) + : maildirFormat(ctx) +{ +} + + +const string kmailMaildirFormat::getName() const +{ + return "kmail"; +} + + +void kmailMaildirFormat::createFolder(const folder::path& path) +{ + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); + + if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) + throw exceptions::invalid_folder_name(); + + shared_ptr rootDir = fsf->create + (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); + + shared_ptr newDir = fsf->create + (folderPathToFileSystemPath(path, NEW_DIRECTORY)); + shared_ptr tmpDir = fsf->create + (folderPathToFileSystemPath(path, TMP_DIRECTORY)); + shared_ptr 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 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 fsf = platform::getHandler()->getFileSystemFactory(); + + shared_ptr rootDir = fsf->create + (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); + + shared_ptr newDir = fsf->create + (folderPathToFileSystemPath(path, NEW_DIRECTORY)); + shared_ptr tmpDir = fsf->create + (folderPathToFileSystemPath(path, TMP_DIRECTORY)); + shared_ptr 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 kmailMaildirFormat::listFolders + (const folder::path& root, const bool recursive) const +{ + std::vector list; + listFoldersImpl(list, root, recursive); + + return list; +} + + +void kmailMaildirFormat::listFoldersImpl + (std::vector & list, const folder::path& root, const bool recursive) const +{ + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); + + shared_ptr rootDir = fsf->create(folderPathToFileSystemPath(root, + root.isEmpty() ? ROOT_DIRECTORY : CONTAINER_DIRECTORY)); + + if (rootDir->exists()) + { + shared_ptr it = rootDir->getFiles(); + + while (it->hasMoreElements()) + { + shared_ptr 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 fsf = platform::getHandler()->getFileSystemFactory(); + + shared_ptr rootDir = fsf->create + (folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY)); + shared_ptr 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 fsf = platform::getHandler()->getFileSystemFactory(); + + shared_ptr rootDir = fsf->create + (folderPathToFileSystemPath(path, CONTAINER_DIRECTORY)); + + shared_ptr it = rootDir->getFiles(); + + while (it->hasMoreElements()) + { + shared_ptr 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/src/vmime/net/maildir/format/kmailMaildirFormat.hpp b/src/vmime/net/maildir/format/kmailMaildirFormat.hpp new file mode 100644 index 00000000..98ca212e --- /dev/null +++ b/src/vmime/net/maildir/format/kmailMaildirFormat.hpp @@ -0,0 +1,109 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr 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 listFolders + (const folder::path& root, const bool recursive) const; + +protected: + + bool supports() const; + + + /** Recursive implementation of listFolders(). + */ + void listFoldersImpl(std::vector & 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/src/vmime/net/maildir/maildir.hpp b/src/vmime/net/maildir/maildir.hpp new file mode 100644 index 00000000..42bbbea4 --- /dev/null +++ b/src/vmime/net/maildir/maildir.hpp @@ -0,0 +1,34 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/maildir/maildirFolder.cpp b/src/vmime/net/maildir/maildirFolder.cpp new file mode 100644 index 00000000..660178ff --- /dev/null +++ b/src/vmime/net/maildir/maildirFolder.cpp @@ -0,0 +1,1254 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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, shared_ptr 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() +{ + shared_ptr store = m_store.lock(); + + if (store) + { + if (m_open) + close(false); + + store->unregisterFolder(this); + } + else if (m_open) + { + close(false); + } +} + + +void maildirFolder::onStoreDisconnected() +{ + m_store.reset(); +} + + +int maildirFolder::getMode() const +{ + if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + return (m_mode); +} + + +int maildirFolder::getType() +{ + if (m_path.isEmpty()) + return (TYPE_CONTAINS_FOLDERS); + else + return (TYPE_CONTAINS_FOLDERS | TYPE_CONTAINS_MESSAGES); +} + + +int maildirFolder::getFlags() +{ + int flags = 0; + + if (m_store.lock()->getFormat()->folderHasSubfolders(m_path)) + flags |= FLAG_CHILDREN; // Contains at least one sub-folder + + return (flags); +} + + +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 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 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 ::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 ::iterator it = + std::find(m_messages.begin(), m_messages.end(), msg); + + if (it != m_messages.end()) + m_messages.erase(it); +} + + +void maildirFolder::create(const int /* type */) +{ + shared_ptr 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 event = + make_shared + (dynamicCast (shared_from_this()), + events::folderEvent::TYPE_CREATED, m_path, m_path); + + notifyFolder(event); +} + + +void maildirFolder::destroy() +{ + shared_ptr 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 event = + make_shared + (dynamicCast (shared_from_this()), + events::folderEvent::TYPE_DELETED, m_path, m_path); + + notifyFolder(event); +} + + +bool maildirFolder::exists() +{ + shared_ptr store = m_store.lock(); + + return store->getFormat()->folderExists(m_path); +} + + +bool maildirFolder::isOpen() const +{ + return (m_open); +} + + +void maildirFolder::scanFolder() +{ + shared_ptr store = m_store.lock(); + + try + { + m_messageCount = 0; + m_unreadMessageCount = 0; + + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); + + utility::file::path newDirPath = store->getFormat()->folderPathToFileSystemPath + (m_path, maildirFormat::NEW_DIRECTORY); + shared_ptr newDir = fsf->create(newDirPath); + + utility::file::path curDirPath = store->getFormat()->folderPathToFileSystemPath + (m_path, maildirFormat::CUR_DIRECTORY); + shared_ptr curDir = fsf->create(curDirPath); + + // New received messages (new/) + shared_ptr nit = newDir->getFiles(); + std::vector newMessageFilenames; + + while (nit->hasMoreElements()) + { + shared_ptr file = nit->nextElement(); + + if (maildirUtils::isMessageFile(*file)) + newMessageFilenames.push_back(file->getFullPath().getLastComponent()); + } + + // Current messages (cur/) + shared_ptr cit = curDir->getFiles(); + std::vector curMessageFilenames; + + while (cit->hasMoreElements()) + { + shared_ptr file = cit->nextElement(); + + if (maildirUtils::isMessageFile(*file)) + curMessageFilenames.push_back(file->getFullPath().getLastComponent()); + } + + // Update/delete existing messages (found in previous scan) + for (unsigned int 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 ::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 ::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 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 ::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 + int unreadMessageCount = 0; + + for (std::vector ::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 = m_messageInfos.size(); + } + catch (exceptions::filesystem_exception&) + { + // Should not happen... + } +} + + +shared_ptr maildirFolder::getMessage(const int num) +{ + if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + if (num < 1 || num > m_messageCount) + throw exceptions::message_not_found(); + + return make_shared + (dynamicCast (shared_from_this()), num); +} + + +std::vector > maildirFolder::getMessages(const messageSet& msgs) +{ + if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + if (msgs.isNumberSet()) + { + const std::vector numbers = maildirUtils::messageSetToNumberList(msgs); + + std::vector > messages; + shared_ptr thisFolder = dynamicCast (shared_from_this()); + + for (std::vector ::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 (thisFolder, *it)); + } + + return messages; + } + else + { + throw exceptions::operation_not_supported(); + } +} + + +int maildirFolder::getMessageCount() +{ + return (m_messageCount); +} + + +shared_ptr maildirFolder::getFolder(const folder::path::component& name) +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + + return make_shared (m_path / name, store); +} + + +std::vector > maildirFolder::getFolders(const bool recursive) +{ + shared_ptr store = m_store.lock(); + + if (!isOpen() && !store) + throw exceptions::illegal_state("Store disconnected"); + + std::vector > list; + + listFolders(list, recursive); + + return (list); +} + + +void maildirFolder::listFolders(std::vector >& list, const bool recursive) +{ + shared_ptr store = m_store.lock(); + + try + { + std::vector pathList = + store->getFormat()->listFolders(m_path, recursive); + + list.reserve(pathList.size()); + + for (std::vector ::size_type i = 0, n = pathList.size() ; i < n ; ++i) + { + shared_ptr subFolder = + make_shared (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 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 event = + make_shared + (dynamicCast (shared_from_this()), + events::folderEvent::TYPE_RENAMED, oldPath, newPath); + + notifyFolder(event); + + // Notify folders with the same path + for (std::list ::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 event = + make_shared + (dynamicCast ((*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 event = + make_shared + (dynamicCast ((*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 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 nums = maildirUtils::messageSetToNumberList(msgs); + + // Change message flags + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); + + utility::file::path curDirPath = store->getFormat()-> + folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); + + for (std::vector ::const_iterator it = + nums.begin() ; it != nums.end() ; ++it) + { + const int num = *it - 1; + + try + { + const utility::file::path::component path = m_messageInfos[num].path; + shared_ptr 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 ::iterator it = + m_messages.begin() ; it != m_messages.end() ; ++it) + { + if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && + (*it)->m_flags != message::FLAG_UNDEFINED) + { + (*it)->m_flags |= flags; + } + } + + break; + } + case message::FLAG_MODE_REMOVE: + { + for (std::vector ::iterator it = + m_messages.begin() ; it != m_messages.end() ; ++it) + { + if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && + (*it)->m_flags != message::FLAG_UNDEFINED) + { + (*it)->m_flags &= ~flags; + } + } + + break; + } + default: + case message::FLAG_MODE_SET: + { + for (std::vector ::iterator it = + m_messages.begin() ; it != m_messages.end() ; ++it) + { + if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && + (*it)->m_flags != message::FLAG_UNDEFINED) + { + (*it)->m_flags = flags; + } + } + + break; + } + + } + + // Notify message flags changed + shared_ptr event = + make_shared + (dynamicCast (shared_from_this()), + events::messageChangedEvent::TYPE_FLAGS, nums); + + notifyMessageChanged(event); + + // TODO: notify other folders with the same path + } + else + { + throw exceptions::operation_not_supported(); + } +} + + +void maildirFolder::addMessage(shared_ptr 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); + + addMessage(strAdapter, str.length(), flags, date, progress); +} + + +void maildirFolder::addMessage(utility::inputStream& is, const size_t size, + const int flags, vmime::datetime* /* date */, utility::progressListener* progress) +{ + shared_ptr 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 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 == message::FLAG_UNDEFINED) ? 0 : flags)); + + try + { + shared_ptr tmpDir = fsf->create(tmpDirPath); + tmpDir->createDirectory(true); + } + catch (exceptions::filesystem_exception&) + { + // Don't throw now, it will fail later... + } + + try + { + shared_ptr 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 == message::FLAG_UNDEFINED) || !(flags & message::FLAG_SEEN)) + m_unreadMessageCount++; + + // Notification + std::vector nums; + nums.push_back(m_messageCount); + + shared_ptr event = + make_shared + (dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_ADDED, nums); + + notifyMessageCount(event); + + // Notify folders with the same path + for (std::list ::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 event = + make_shared + (dynamicCast ((*it)->shared_from_this()), + events::messageCountEvent::TYPE_ADDED, nums); + + (*it)->notifyMessageCount(event); + } + } +} + + +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 fsf = platform::getHandler()->getFileSystemFactory(); + + shared_ptr file = fsf->create(tmpDirPath / filename); + + if (progress) + progress->start(size); + + // First, write the message into 'tmp'... + try + { + file->createFile(); + + shared_ptr fw = file->getFileWriter(); + shared_ptr 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 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 file = fsf->create(dstDirPath / filename); + file->remove(); + } + catch (exceptions::filesystem_exception&) + { + // Ignore + } + + throw exceptions::command_error("ADD", "", "", e); + } + + if (progress) + progress->stop(size); +} + + +void maildirFolder::copyMessages(const folder::path& dest, const messageSet& msgs) +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + else if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + shared_ptr 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 destTmpDir = fsf->create(destTmpDirPath); + destTmpDir->createDirectory(true); + } + catch (exceptions::filesystem_exception&) + { + // Don't throw now, it will fail later... + } + + try + { + shared_ptr destCurDir = fsf->create(destCurDirPath); + destCurDir->createDirectory(true); + } + catch (exceptions::filesystem_exception&) + { + // Don't throw now, it will fail later... + } + + // Copy messages + const std::vector nums = maildirUtils::messageSetToNumberList(msgs); + + try + { + for (std::vector ::const_iterator it = + nums.begin() ; it != nums.end() ; ++it) + { + const int 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 file = fsf->create(curDirPath / msg.path); + shared_ptr fr = file->getFileReader(); + shared_ptr is = fr->getInputStream(); + + copyMessageImpl(destTmpDirPath, destCurDirPath, + filename, *is, file->getLength(), NULL); + } + } + catch (exception& e) + { + notifyMessagesCopied(dest); + throw exceptions::command_error("COPY", "", "", e); + } + + notifyMessagesCopied(dest); +} + + +void maildirFolder::notifyMessagesCopied(const folder::path& dest) +{ + shared_ptr store = m_store.lock(); + + for (std::list ::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. + int count, unseen; + (*it)->status(count, unseen); + + return; + } + } +} + + +void maildirFolder::status(int& count, int& unseen) +{ + count = 0; + unseen = 0; + + shared_ptr status = getStatus(); + + count = status->getMessageCount(); + unseen = status->getUnseenCount(); +} + + +shared_ptr maildirFolder::getStatus() +{ + shared_ptr store = m_store.lock(); + + const int oldCount = m_messageCount; + + scanFolder(); + + shared_ptr status = make_shared (); + + status->setMessageCount(m_messageCount); + status->setUnseenCount(m_unreadMessageCount); + + // Notify message count changed (new messages) + if (m_messageCount > oldCount) + { + std::vector nums; + nums.reserve(m_messageCount - oldCount); + + for (int i = oldCount + 1, j = 0 ; i <= m_messageCount ; ++i, ++j) + nums[j] = i; + + shared_ptr event = + make_shared + (dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_ADDED, nums); + + notifyMessageCount(event); + + // Notify folders with the same path + for (std::list ::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 event = + make_shared + (dynamicCast ((*it)->shared_from_this()), + events::messageCountEvent::TYPE_ADDED, nums); + + (*it)->notifyMessageCount(event); + } + } + } + + return status; +} + + +void maildirFolder::expunge() +{ + shared_ptr 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 fsf = platform::getHandler()->getFileSystemFactory(); + + utility::file::path curDirPath = store->getFormat()-> + folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); + + std::vector nums; + int unreadCount = 0; + + for (int 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 ::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 file = fsf->create(curDirPath / infos.path); + file->remove(); + } + catch (exceptions::filesystem_exception& e) + { + // Ignore (not important) + } + } + } + + if (!nums.empty()) + { + for (std::vector ::size_type i = nums.size() ; i != 0 ; --i) + m_messageInfos.erase(m_messageInfos.begin() + (i - 1)); + } + + m_messageCount -= nums.size(); + m_unreadMessageCount -= unreadCount; + + // Notify message expunged + shared_ptr event = + make_shared + (dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_REMOVED, nums); + + notifyMessageCount(event); + + // Notify folders with the same path + for (std::list ::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 event = + make_shared + (dynamicCast ((*it)->shared_from_this()), + events::messageCountEvent::TYPE_REMOVED, nums); + + (*it)->notifyMessageCount(event); + } + } +} + + +shared_ptr maildirFolder::getParent() +{ + if (m_path.isEmpty()) + return null; + else + return make_shared (m_path.getParent(), m_store.lock()); +} + + +shared_ptr maildirFolder::getStore() const +{ + return m_store.lock(); +} + + +shared_ptr maildirFolder::getStore() +{ + return m_store.lock(); +} + + +void maildirFolder::fetchMessages(std::vector >& msg, + const fetchAttributes& options, utility::progressListener* progress) +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + else if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + const size_t total = msg.size(); + size_t current = 0; + + if (progress) + progress->start(total); + + shared_ptr thisFolder = dynamicCast (shared_from_this()); + + for (std::vector >::iterator it = msg.begin() ; + it != msg.end() ; ++it) + { + dynamicCast (*it)->fetch(thisFolder, options); + + if (progress) + progress->progress(++current, total); + } + + if (progress) + progress->stop(total); +} + + +void maildirFolder::fetchMessage(shared_ptr msg, const fetchAttributes& options) +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + else if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + dynamicCast (msg)->fetch + (dynamicCast (shared_from_this()), options); +} + + +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 int 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 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/src/vmime/net/maildir/maildirFolder.hpp b/src/vmime/net/maildir/maildirFolder.hpp new file mode 100644 index 00000000..5cff53fc --- /dev/null +++ b/src/vmime/net/maildir/maildirFolder.hpp @@ -0,0 +1,190 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + +#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() { } + +public: + + maildirFolder(const folder::path& path, shared_ptr store); + + ~maildirFolder(); + + + int getMode() const; + + int getType(); + + int getFlags(); + + 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 int type); + + bool exists(); + + void destroy(); + + bool isOpen() const; + + shared_ptr getMessage(const int num); + std::vector > getMessages(const messageSet& msgs); + + int getMessageCount(); + + shared_ptr getFolder(const folder::path::component& name); + std::vector > 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); + + void addMessage(shared_ptr msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); + void addMessage(utility::inputStream& is, const size_t size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); + + void copyMessages(const folder::path& dest, const messageSet& msgs); + + void status(int& count, int& unseen); + shared_ptr getStatus(); + + void expunge(); + + shared_ptr getParent(); + + shared_ptr getStore() const; + shared_ptr getStore(); + + + void fetchMessages(std::vector >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL); + void fetchMessage(shared_ptr msg, const fetchAttributes& options); + + int getFetchCapabilities() const; + + std::vector getMessageNumbersStartingOnUID(const message::uid& uid); + +private: + + void scanFolder(); + + void listFolders(std::vector >& list, const bool recursive); + + void registerMessage(maildirMessage* msg); + void unregisterMessage(maildirMessage* msg); + + const utility::file::path getMessageFSPath(const int number) const; + + void onStoreDisconnected(); + + void onClose(); + + void deleteMessagesImpl(const std::vector & nums); + void setMessageFlagsImpl(const std::vector & nums, const int flags, const int mode); + + void copyMessagesImpl(const folder::path& dest, const std::vector & 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 m_store; + + folder::path m_path; + folder::path::component m_name; + + int m_mode; + bool m_open; + + int m_unreadMessageCount; + int 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 m_messageInfos; + + // Instanciated message objects + std::vector 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/src/vmime/net/maildir/maildirFolderStatus.cpp b/src/vmime/net/maildir/maildirFolderStatus.cpp new file mode 100644 index 00000000..9ee84dba --- /dev/null +++ b/src/vmime/net/maildir/maildirFolderStatus.cpp @@ -0,0 +1,88 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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) +{ +} + + +unsigned int maildirFolderStatus::getMessageCount() const +{ + return m_count; +} + + +unsigned int maildirFolderStatus::getUnseenCount() const +{ + return m_unseen; +} + + +void maildirFolderStatus::setMessageCount(const unsigned int count) +{ + m_count = count; +} + + +void maildirFolderStatus::setUnseenCount(const unsigned int unseen) +{ + m_unseen = unseen; +} + + +shared_ptr maildirFolderStatus::clone() const +{ + return make_shared (*this); +} + + +} // maildir +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR diff --git a/src/vmime/net/maildir/maildirFolderStatus.hpp b/src/vmime/net/maildir/maildirFolderStatus.hpp new file mode 100644 index 00000000..155fb20f --- /dev/null +++ b/src/vmime/net/maildir/maildirFolderStatus.hpp @@ -0,0 +1,76 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + unsigned int getMessageCount() const; + unsigned int getUnseenCount() const; + + shared_ptr clone() const; + + + void setMessageCount(const unsigned int count); + void setUnseenCount(const unsigned int unseen); + +private: + + unsigned int m_count; + unsigned int 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/src/vmime/net/maildir/maildirFormat.cpp b/src/vmime/net/maildir/maildirFormat.cpp new file mode 100644 index 00000000..f7a3c8fe --- /dev/null +++ b/src/vmime/net/maildir/maildirFormat.cpp @@ -0,0 +1,109 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr store) + : m_store(store) +{ +} + + +shared_ptr maildirFormat::context::getStore() const +{ + return constCast (m_store.lock()); +} + + +// +// maildirFormat +// + +maildirFormat::maildirFormat(shared_ptr ctx) + : m_context(ctx) +{ +} + + +shared_ptr maildirFormat::getContext() +{ + return m_context; +} + + +shared_ptr maildirFormat::getContext() const +{ + return m_context; +} + + +// static +shared_ptr maildirFormat::detect(shared_ptr store) +{ + shared_ptr ctx = make_shared (store); + + // Try Courier format + shared_ptr fmt = make_shared (ctx); + + if (fmt->supports()) + return fmt; + + // Default is KMail format + return make_shared (ctx); +} + + +} // maildir +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR + diff --git a/src/vmime/net/maildir/maildirFormat.hpp b/src/vmime/net/maildir/maildirFormat.hpp new file mode 100644 index 00000000..c0daf288 --- /dev/null +++ b/src/vmime/net/maildir/maildirFormat.hpp @@ -0,0 +1,195 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr store); + + shared_ptr getStore() const; + + private: + + weak_ptr 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 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 detect(shared_ptr 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(shared_ptr ctx); + + + /** Returns the current context. + * + * @return current context + */ + shared_ptr getContext(); + + /** Returns the current context (const version). + * + * @return current context + */ + shared_ptr 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 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/src/vmime/net/maildir/maildirMessage.cpp b/src/vmime/net/maildir/maildirMessage.cpp new file mode 100644 index 00000000..a14f067e --- /dev/null +++ b/src/vmime/net/maildir/maildirMessage.cpp @@ -0,0 +1,369 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr folder, const int 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() +{ + shared_ptr folder = m_folder.lock(); + + if (folder) + folder->unregisterMessage(this); +} + + +void maildirMessage::onFolderClosed() +{ + m_folder.reset(); +} + + +int 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 (-1)) + throw exceptions::unfetched_object(); + + return (m_size); +} + + +bool maildirMessage::isExpunged() const +{ + return (m_expunged); +} + + +shared_ptr maildirMessage::getStructure() const +{ + if (m_structure == NULL) + throw exceptions::unfetched_object(); + + return m_structure; +} + + +shared_ptr maildirMessage::getStructure() +{ + if (m_structure == NULL) + throw exceptions::unfetched_object(); + + return m_structure; +} + + +shared_ptr maildirMessage::getHeader() const +{ + if (m_header == NULL) + 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 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(shared_ptr p, utility::outputStream& os, + utility::progressListener* progress, const size_t start, + const size_t length, const bool peek) const +{ + shared_ptr mp = dynamicCast (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 folder = m_folder.lock(); + + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); + + const utility::file::path path = folder->getMessageFSPath(m_num); + shared_ptr file = fsf->create(path); + + shared_ptr reader = file->getFileReader(); + shared_ptr is = reader->getInputStream(); + + is->skip(start + partialStart); + + byte_t buffer[8192]; + size_t remaining = (partialLength == static_cast (-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(shared_ptr p) +{ + shared_ptr folder = m_folder.lock(); + + shared_ptr mp = dynamicCast (p); + + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); + + const utility::file::path path = folder->getMessageFSPath(m_num); + shared_ptr file = fsf->create(path); + + shared_ptr reader = file->getFileReader(); + shared_ptr 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(shared_ptr msgFolder, const fetchAttributes& options) +{ + shared_ptr folder = m_folder.lock(); + + if (folder != msgFolder) + throw exceptions::folder_not_found(); + + shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); + + const utility::file::path path = folder->getMessageFSPath(m_num); + shared_ptr 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 reader = file->getFileReader(); + shared_ptr 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 (shared_ptr (), 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
maildirMessage::getOrCreateHeader() +{ + if (m_header != NULL) + return (m_header); + else + return (m_header = make_shared
()); +} + + +shared_ptr maildirMessage::getParsedMessage() +{ + std::ostringstream oss; + utility::outputStreamAdapter os(oss); + + extract(os); + + shared_ptr msg = make_shared (); + msg->parse(oss.str()); + + return msg; +} + + +} // maildir +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR + diff --git a/src/vmime/net/maildir/maildirMessage.hpp b/src/vmime/net/maildir/maildirMessage.hpp new file mode 100644 index 00000000..7480d49c --- /dev/null +++ b/src/vmime/net/maildir/maildirMessage.hpp @@ -0,0 +1,116 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr folder, const int num); + + ~maildirMessage(); + + + int getNumber() const; + + const uid getUID() const; + + size_t getSize() const; + + bool isExpunged() const; + + shared_ptr getStructure() const; + shared_ptr getStructure(); + + shared_ptr 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(shared_ptr 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(shared_ptr p); + + shared_ptr getParsedMessage(); + +private: + + void fetch(shared_ptr folder, const fetchAttributes& options); + + void onFolderClosed(); + + shared_ptr
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 m_folder; + + int m_num; + size_t m_size; + int m_flags; + bool m_expunged; + uid m_uid; + + shared_ptr
m_header; + shared_ptr 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/src/vmime/net/maildir/maildirMessagePart.cpp b/src/vmime/net/maildir/maildirMessagePart.cpp new file mode 100644 index 00000000..6ae085c9 --- /dev/null +++ b/src/vmime/net/maildir/maildirMessagePart.cpp @@ -0,0 +1,155 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const int 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(); +} + + +maildirMessagePart::~maildirMessagePart() +{ +} + + +void maildirMessagePart::initStructure(const bodyPart& part) +{ + if (part.getBody()->getPartList().size() == 0) + m_structure = null; + else + { + m_structure = make_shared + (dynamicCast (shared_from_this()), + part.getBody()->getPartList()); + } +} + + +shared_ptr maildirMessagePart::getStructure() const +{ + if (m_structure != NULL) + return m_structure; + else + return maildirMessageStructure::emptyStructure(); +} + + +shared_ptr maildirMessagePart::getStructure() +{ + if (m_structure != NULL) + return m_structure; + else + return maildirMessageStructure::emptyStructure(); +} + + +const mediaType& maildirMessagePart::getType() const +{ + return m_mediaType; +} + + +size_t maildirMessagePart::getSize() const +{ + return m_size; +} + + +int maildirMessagePart::getNumber() const +{ + return m_number; +} + + +shared_ptr maildirMessagePart::getHeader() const +{ + if (m_header == NULL) + throw exceptions::unfetched_object(); + else + return m_header; +} + + +header& maildirMessagePart::getOrCreateHeader() +{ + if (m_header != NULL) + return *m_header; + else + return *(m_header = make_shared
()); +} + + +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/src/vmime/net/maildir/maildirMessagePart.hpp b/src/vmime/net/maildir/maildirMessagePart.hpp new file mode 100644 index 00000000..3a4be0f3 --- /dev/null +++ b/src/vmime/net/maildir/maildirMessagePart.hpp @@ -0,0 +1,99 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const int number, const bodyPart& part); + ~maildirMessagePart(); + + + shared_ptr getStructure() const; + shared_ptr getStructure(); + + weak_ptr getParent() const { return (m_parent); } + + const mediaType& getType() const; + size_t getSize() const; + int getNumber() const; + + shared_ptr 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 m_structure; + weak_ptr m_parent; + shared_ptr
m_header; + + int m_number; + size_t m_size; + mediaType m_mediaType; + + 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/src/vmime/net/maildir/maildirMessageStructure.cpp b/src/vmime/net/maildir/maildirMessageStructure.cpp new file mode 100644 index 00000000..f3b7cf59 --- /dev/null +++ b/src/vmime/net/maildir/maildirMessageStructure.cpp @@ -0,0 +1,98 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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::m_emptyStructure = make_shared (); + + +maildirMessageStructure::maildirMessageStructure() +{ +} + + +maildirMessageStructure::maildirMessageStructure(shared_ptr parent, const bodyPart& part) +{ + shared_ptr mpart = make_shared (parent, 0, part); + mpart->initStructure(part); + + m_parts.push_back(mpart); +} + + +maildirMessageStructure::maildirMessageStructure(shared_ptr parent, const std::vector >& list) +{ + for (unsigned int i = 0 ; i < list.size() ; ++i) + { + shared_ptr mpart = make_shared (parent, i, *list[i]); + mpart->initStructure(*list[i]); + + m_parts.push_back(mpart); + } +} + + +shared_ptr maildirMessageStructure::getPartAt(const size_t x) const +{ + return m_parts[x]; +} + + +shared_ptr maildirMessageStructure::getPartAt(const size_t x) +{ + return m_parts[x]; +} + + +size_t maildirMessageStructure::getPartCount() const +{ + return m_parts.size(); +} + + +// static +shared_ptr maildirMessageStructure::emptyStructure() +{ + return m_emptyStructure; +} + + +} // maildir +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR diff --git a/src/vmime/net/maildir/maildirMessageStructure.hpp b/src/vmime/net/maildir/maildirMessageStructure.hpp new file mode 100644 index 00000000..a43fc15c --- /dev/null +++ b/src/vmime/net/maildir/maildirMessageStructure.hpp @@ -0,0 +1,76 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const bodyPart& part); + maildirMessageStructure(shared_ptr parent, const std::vector >& list); + + + shared_ptr getPartAt(const size_t x) const; + shared_ptr getPartAt(const size_t x); + + size_t getPartCount() const; + + static shared_ptr emptyStructure(); + +private: + + static shared_ptr m_emptyStructure; + + std::vector > 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/src/vmime/net/maildir/maildirServiceInfos.cpp b/src/vmime/net/maildir/maildirServiceInfos.cpp new file mode 100644 index 00000000..974a0c21 --- /dev/null +++ b/src/vmime/net/maildir/maildirServiceInfos.cpp @@ -0,0 +1,77 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 maildirServiceInfos::getAvailableProperties() const +{ + std::vector 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/src/vmime/net/maildir/maildirServiceInfos.hpp b/src/vmime/net/maildir/maildirServiceInfos.hpp new file mode 100644 index 00000000..70ddc6dc --- /dev/null +++ b/src/vmime/net/maildir/maildirServiceInfos.hpp @@ -0,0 +1,71 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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/src/vmime/net/maildir/maildirStore.cpp b/src/vmime/net/maildir/maildirStore.cpp new file mode 100644 index 00000000..87e733e2 --- /dev/null +++ b/src/vmime/net/maildir/maildirStore.cpp @@ -0,0 +1,272 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 (getSession(), \ + dynamic_cast (getInfos()).getProperties().prop)) +#define HAS_PROPERTY(prop) \ + (getInfos().hasProperty(getSession(), \ + dynamic_cast (getInfos()).getProperties().prop)) + + +namespace vmime { +namespace net { +namespace maildir { + + +maildirStore::maildirStore(shared_ptr sess, shared_ptr auth) + : store(sess, getInfosInstance(), auth), m_connected(false) +{ +} + + +maildirStore::~maildirStore() +{ + try + { + if (isConnected()) + disconnect(); + } + catch (vmime::exception&) + { + // Ignore + } +} + + +const string maildirStore::getProtocolName() const +{ + return "maildir"; +} + + +shared_ptr maildirStore::getRootFolder() +{ + if (!isConnected()) + throw exceptions::illegal_state("Not connected"); + + return make_shared + (folder::path(), + dynamicCast (shared_from_this())); +} + + +shared_ptr maildirStore::getDefaultFolder() +{ + if (!isConnected()) + throw exceptions::illegal_state("Not connected"); + + return make_shared + (folder::path::component("inbox"), + dynamicCast (shared_from_this())); +} + + +shared_ptr maildirStore::getFolder(const folder::path& path) +{ + if (!isConnected()) + throw exceptions::illegal_state("Not connected"); + + return make_shared + (path, dynamicCast (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(); + int 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 fsf = platform::getHandler()->getFileSystemFactory(); + + m_fsPath = fsf->stringToPath(GET_PROPERTY(string, PROPERTY_SERVER_ROOTPATH)); + + shared_ptr 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 (shared_from_this())); + + m_connected = true; +} + + +bool maildirStore::isConnected() const +{ + return (m_connected); +} + + +bool maildirStore::isSecuredConnection() const +{ + return false; +} + + +shared_ptr maildirStore::getConnectionInfos() const +{ + return make_shared ("localhost", static_cast (0)); +} + + +void maildirStore::disconnect() +{ + for (std::list ::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 maildirStore::getFormat() +{ + return m_format; +} + + +shared_ptr maildirStore::getFormat() const +{ + return m_format; +} + + +void maildirStore::registerFolder(maildirFolder* folder) +{ + m_folders.push_back(folder); +} + + +void maildirStore::unregisterFolder(maildirFolder* folder) +{ + std::list ::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/src/vmime/net/maildir/maildirStore.hpp b/src/vmime/net/maildir/maildirStore.hpp new file mode 100644 index 00000000..efadfdfe --- /dev/null +++ b/src/vmime/net/maildir/maildirStore.hpp @@ -0,0 +1,120 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace net { +namespace maildir { + + +class maildirFolder; + + +/** maildir store service. + */ + +class VMIME_EXPORT maildirStore : public store +{ + friend class maildirFolder; + +public: + + maildirStore(shared_ptr sess, shared_ptr auth); + ~maildirStore(); + + const string getProtocolName() const; + + shared_ptr getDefaultFolder(); + shared_ptr getRootFolder(); + shared_ptr 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 getConnectionInfos() const; + + shared_ptr getFormat(); + shared_ptr getFormat() const; + +private: + + void registerFolder(maildirFolder* folder); + void unregisterFolder(maildirFolder* folder); + + + std::list m_folders; + + shared_ptr 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/src/vmime/net/maildir/maildirUtils.cpp b/src/vmime/net/maildir/maildirUtils.cpp new file mode 100644 index 00000000..77aac715 --- /dev/null +++ b/src/vmime/net/maildir/maildirUtils.cpp @@ -0,0 +1,273 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr dir) +{ + shared_ptr files = dir->getFiles(); + + // First, delete files and subdirectories in this directory + while (files->hasMoreElements()) + { + shared_ptr 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: + + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) + { + for (int i = range.getFirst(), last = range.getLast() ; i <= last ; ++i) + list.push_back(i); + } + + void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) + { + // Not supported + } + +public: + + std::vector list; +}; + + +// static +const std::vector maildirUtils::messageSetToNumberList(const messageSet& msgs) +{ + maildirMessageSetEnumerator en; + 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/src/vmime/net/maildir/maildirUtils.hpp b/src/vmime/net/maildir/maildirUtils.hpp new file mode 100644 index 00000000..82deefbb --- /dev/null +++ b/src/vmime/net/maildir/maildirUtils.hpp @@ -0,0 +1,151 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr dir); + + /** Returns a list of message numbers given a message set. + * + * @param msgs message set + * @return list of message numbers + */ + static const std::vector messageSetToNumberList(const messageSet& msgs); +}; + + +} // maildir +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR + +#endif // VMIME_NET_MAILDIR_MAILDIRUTILS_HPP_INCLUDED diff --git a/src/vmime/net/message.cpp b/src/vmime/net/message.cpp new file mode 100644 index 00000000..6765e73c --- /dev/null +++ b/src/vmime/net/message.cpp @@ -0,0 +1,150 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace net { + + +shared_ptr messagePart::getPartAt(const size_t pos) const +{ + return getStructure()->getPartAt(pos); +} + + +shared_ptr 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 (uid); + return os; +} + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + diff --git a/src/vmime/net/message.hpp b/src/vmime/net/message.hpp new file mode 100644 index 00000000..5bb62c53 --- /dev/null +++ b/src/vmime/net/message.hpp @@ -0,0 +1,355 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/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 +{ +protected: + + messagePart() { } + messagePart(const messagePart&) : object() { } + + virtual ~messagePart() { } + +public: + + /** Return the structure of this part. + * + * @return structure of the part + */ + virtual shared_ptr getStructure() const = 0; + + /** Return the structure of this part. + * + * @return structure of the part + */ + virtual shared_ptr 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 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 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 int getNumber() const = 0; + + /** 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 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 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 +{ +protected: + + messageStructure() { } + messageStructure(const messageStructure&) : object() { } + +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 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 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 +{ +protected: + + message() { } + message(const message&) : object() { } + +public: + + virtual ~message() { } + + /** 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 getStructure() const = 0; + + /** Return the MIME structure of the message (must fetch before). + * + * @return MIME structure of the message + */ + virtual shared_ptr getStructure() = 0; + + /** Return a reference to the header fields of the message (must fetch before). + * + * @return header section of the message + */ + virtual shared_ptr 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 int 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'. */ + + FLAG_UNDEFINED = 9999 /**< Used internally (this should not be returned + by the flags() function). */ + }; + + /** 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 + (shared_ptr 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(shared_ptr 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 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/src/vmime/net/messageSet.cpp b/src/vmime/net/messageSet.cpp new file mode 100644 index 00000000..2939042e --- /dev/null +++ b/src/vmime/net/messageSet.cpp @@ -0,0 +1,369 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/messageSet.hpp" + +#include +#include +#include + + +namespace vmime { +namespace net { + + +// messageRange + +messageRange::messageRange() +{ +} + + +messageRange::~messageRange() +{ +} + + +// numberMessageRange + +numberMessageRange::numberMessageRange(const int number) + : m_first(number), m_last(number) +{ + if (number < 1) + throw std::invalid_argument("number"); +} + + +numberMessageRange::numberMessageRange(const int first, const int last) + : m_first(first), m_last(last) +{ + if (first < 1) + throw std::invalid_argument("first"); + else if (last != -1 && last < first) + throw std::invalid_argument("last"); +} + + +numberMessageRange::numberMessageRange(const numberMessageRange& other) + : messageRange(), m_first(other.m_first), m_last(other.m_last) +{ +} + + +int numberMessageRange::getFirst() const +{ + return m_first; +} + + +int 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::byNumber(const int number) +{ + messageSet set; + set.m_ranges.push_back(new numberMessageRange(number)); + + return set; +} + + +// static +messageSet messageSet::byNumber(const int first, const int last) +{ + messageSet set; + set.m_ranges.push_back(new numberMessageRange(first, last)); + + return set; +} + + +// static +messageSet messageSet::byNumber(const std::vector & numbers) +{ + // Sort a copy of the list + std::vector 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 + int previous = -1, rangeStart = -1; + messageSet set; + + for (std::vector ::const_iterator it = sortedNumbers.begin() ; + it != sortedNumbers.end() ; ++it) + { + const int current = *it; + + if (current == previous) + continue; // skip duplicates + + if (previous == -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 & uids) +{ + std::vector 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 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 = -1U, rangeStart = -1U; + messageSet set; + + for (std::vector ::const_iterator it = sortedUIDs.begin() ; + it != sortedUIDs.end() ; ++it) + { + const vmime_uint32 current = *it; + + if (current == previous) + continue; // skip duplicates + + if (previous == -1U) + { + 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 (m_ranges[0]) != NULL; +} + + +bool messageSet::isUIDSet() const +{ + return !isEmpty() && dynamic_cast (m_ranges[0]) != NULL; +} + + +} // net +} // vmime diff --git a/src/vmime/net/messageSet.hpp b/src/vmime/net/messageSet.hpp new file mode 100644 index 00000000..6c7d7f44 --- /dev/null +++ b/src/vmime/net/messageSet.hpp @@ -0,0 +1,335 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/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 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 int 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 int first, const int 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 + */ + int 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 + */ + int getLast() const; + + void enumerate(messageSetEnumerator& en) const; + + messageRange* clone() const; + +private: + + int 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 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 int 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 int first, const int 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 & 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 & 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; + +private: + + messageSet(); + + std::vector m_ranges; +}; + + +} // net +} // vmime + + +#endif // VMIME_NET_MESSAGESET_HPP_INCLUDED diff --git a/src/vmime/net/pop3/POP3Command.cpp b/src/vmime/net/pop3/POP3Command.cpp new file mode 100644 index 00000000..6fe301ce --- /dev/null +++ b/src/vmime/net/pop3/POP3Command.cpp @@ -0,0 +1,230 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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) + : m_text(text) +{ +} + + +// static +shared_ptr POP3Command::CAPA() +{ + return createCommand("CAPA"); +} + + +// static +shared_ptr POP3Command::NOOP() +{ + return createCommand("NOOP"); +} + + +// static +shared_ptr POP3Command::AUTH(const string& mechName) +{ + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "AUTH " << mechName; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr POP3Command::STLS() +{ + return createCommand("STLS"); +} + + +// static +shared_ptr 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::USER(const string& username) +{ + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "USER " << username; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr POP3Command::PASS(const string& password) +{ + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "PASS " << password; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr POP3Command::STAT() +{ + return createCommand("STAT"); +} + + +// static +shared_ptr POP3Command::LIST() +{ + return createCommand("LIST"); +} + + +// static +shared_ptr 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::UIDL() +{ + return createCommand("UIDL"); +} + + +// static +shared_ptr 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::DELE(const unsigned long msg) +{ + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "DELE " << msg; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr 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::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::RSET() +{ + return createCommand("RSET"); +} + + +// static +shared_ptr POP3Command::QUIT() +{ + return createCommand("QUIT"); +} + + +// static +shared_ptr POP3Command::createCommand(const string& text) +{ + return shared_ptr (new POP3Command(text)); +} + + +const string POP3Command::getText() const +{ + return m_text; +} + + +void POP3Command::send(shared_ptr conn) +{ + conn->getSocket()->send(m_text + "\r\n"); +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/src/vmime/net/pop3/POP3Command.hpp b/src/vmime/net/pop3/POP3Command.hpp new file mode 100644 index 00000000..cc3c4fd5 --- /dev/null +++ b/src/vmime/net/pop3/POP3Command.hpp @@ -0,0 +1,113 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 CAPA(); + static shared_ptr NOOP(); + static shared_ptr AUTH(const string& mechName); + static shared_ptr STLS(); + static shared_ptr APOP(const string& username, const string& digest); + static shared_ptr USER(const string& username); + static shared_ptr PASS(const string& password); + static shared_ptr STAT(); + static shared_ptr LIST(); + static shared_ptr LIST(const unsigned long msg); + static shared_ptr UIDL(); + static shared_ptr UIDL(const unsigned long msg); + static shared_ptr DELE(const unsigned long msg); + static shared_ptr RETR(const unsigned long msg); + static shared_ptr TOP(const unsigned long msg, const unsigned long lines); + static shared_ptr RSET(); + static shared_ptr QUIT(); + + /** Creates a new POP3 command with the specified text. + * + * @param text command text + * @return a new POP3Command object + */ + static shared_ptr createCommand(const string& text); + + /** Sends this command over the specified connection. + * + * @param conn connection onto which the command will be sent + */ + virtual void send(shared_ptr 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; + +protected: + + POP3Command(const string& text); + POP3Command(const POP3Command&); + +private: + + string m_text; +}; + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + +#endif // VMIME_NET_POP3_POP3COMMAND_HPP_INCLUDED diff --git a/src/vmime/net/pop3/POP3Connection.cpp b/src/vmime/net/pop3/POP3Connection.cpp new file mode 100644 index 00000000..5fa923f4 --- /dev/null +++ b/src/vmime/net/pop3/POP3Connection.cpp @@ -0,0 +1,675 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 (getSession(), \ + dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) +#define HAS_PROPERTY(prop) \ + (m_store.lock()->getInfos().hasProperty(getSession(), \ + dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) + + +namespace vmime { +namespace net { +namespace pop3 { + + + +POP3Connection::POP3Connection(shared_ptr store, shared_ptr auth) + : m_store(store), m_auth(auth), m_socket(null), m_timeoutHandler(null), + m_authenticated(false), m_secured(false), m_capabilitiesFetched(false) +{ +} + + +POP3Connection::~POP3Connection() +{ + try + { + if (isConnected()) + disconnect(); + else if (m_socket) + internalDisconnect(); + } + catch (vmime::exception&) + { + // Ignore + } +} + + +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 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); + +#if VMIME_HAVE_TLS_SUPPORT + if (store->isPOP3S()) // dedicated port/POP3S + { + shared_ptr tlsSession = tls::TLSSession::create + (store->getCertificateVerifier(), + store->getSession()->getTLSProperties()); + + shared_ptr tlsSocket = + tlsSession->getSocket(m_socket); + + m_socket = tlsSocket; + + m_secured = true; + m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); + } + else +#endif // VMIME_HAVE_TLS_SUPPORT + { + m_cntInfos = make_shared (address, port); + } + + m_socket->connect(address, port); + + // Connection + // + // eg: C: + // --- S: +OK MailSite POP3 Server 5.3.4.0 Ready <36938848.1056800841.634@somewhere.com> + + shared_ptr response = POP3Response::readResponse + (dynamicCast (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 (shared_from_this())); + POP3Response::readResponse(dynamicCast (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& e) + { + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) + { + // Can't fallback on APOP/normal authentication + internalDisconnect(); + throw e; + } + else + { + // Ignore, will try APOP/normal authentication + } + } + catch (exception& e) + { + internalDisconnect(); + throw e; + } + } +#endif // VMIME_HAVE_SASL_SUPPORT + + // Secured authentication with APOP (if requested and if available) + // + // eg: C: APOP vincent + // --- S: +OK vincent is a valid mailbox + + const string username = getAuthenticator()->getUsername(); + const string password = getAuthenticator()->getPassword(); + + shared_ptr conn = dynamicCast (shared_from_this()); + shared_ptr response; + + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP)) + { + if (randomMID.getLeft().length() != 0 && + randomMID.getRight().length() != 0) + { + // is the result of MD5 applied to "password" + shared_ptr 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 (getAuthenticator())) + throw exceptions::authentication_error("No SASL authenticator available."); + + std::vector capa = getCapabilities(); + std::vector 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); + string mech; + + while (iss >> mech) + saslMechs.push_back(mech); + } + } + + if (saslMechs.empty()) + throw exceptions::authentication_error("No SASL mechanism available."); + + std::vector > mechList; + + shared_ptr saslContext = + make_shared (); + + 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 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 (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 mech = mechList[i]; + + shared_ptr saslSession = + saslContext->createSession("pop3", getAuthenticator(), mech); + + saslSession->init(); + + POP3Command::AUTH(mech->getName())->send(dynamicCast (shared_from_this())); + + for (bool cont = true ; cont ; ) + { + shared_ptr response = + POP3Response::readResponse(dynamicCast (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 + m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n"); + } + 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"); + } + 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 (shared_from_this())); + + shared_ptr response = + POP3Response::readResponse(dynamicCast (shared_from_this())); + + if (!response->isSuccess()) + throw exceptions::command_error("STLS", response->getFirstLine()); + + shared_ptr tlsSession = tls::TLSSession::create + (m_store.lock()->getCertificateVerifier(), + m_store.lock()->getSession()->getTLSProperties()); + + shared_ptr tlsSocket = + tlsSession->getSocket(m_socket); + + tlsSocket->handshake(m_timeoutHandler); + + m_socket = tlsSocket; + + m_secured = true; + m_cntInfos = make_shared + (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 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 (shared_from_this())); + + shared_ptr response = + POP3Response::readMultilineResponse(dynamicCast (shared_from_this())); + + std::vector 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 POP3Connection::getConnectionInfos() const +{ + return m_cntInfos; +} + + +shared_ptr POP3Connection::getStore() +{ + return m_store.lock(); +} + + +shared_ptr POP3Connection::getSession() +{ + return m_store.lock()->getSession(); +} + + +shared_ptr POP3Connection::getSocket() +{ + return m_socket; +} + + +shared_ptr POP3Connection::getTimeoutHandler() +{ + return m_timeoutHandler; +} + + +shared_ptr POP3Connection::getAuthenticator() +{ + return m_auth; +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/src/vmime/net/pop3/POP3Connection.hpp b/src/vmime/net/pop3/POP3Connection.hpp new file mode 100644 index 00000000..3622f745 --- /dev/null +++ b/src/vmime/net/pop3/POP3Connection.hpp @@ -0,0 +1,125 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/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: + + POP3Connection(shared_ptr store, shared_ptr auth); + virtual ~POP3Connection(); + + + virtual void connect(); + virtual bool isConnected() const; + virtual void disconnect(); + + bool isSecuredConnection() const; + shared_ptr getConnectionInfos() const; + + virtual shared_ptr getStore(); + virtual shared_ptr getSocket(); + virtual shared_ptr getTimeoutHandler(); + virtual shared_ptr getAuthenticator(); + virtual shared_ptr getSession(); + +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 getCapabilities(); + + void internalDisconnect(); + + + weak_ptr m_store; + + shared_ptr m_auth; + shared_ptr m_socket; + shared_ptr m_timeoutHandler; + + bool m_authenticated; + bool m_secured; + + shared_ptr m_cntInfos; + + std::vector 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/src/vmime/net/pop3/POP3Folder.cpp b/src/vmime/net/pop3/POP3Folder.cpp new file mode 100644 index 00000000..096de8af --- /dev/null +++ b/src/vmime/net/pop3/POP3Folder.cpp @@ -0,0 +1,729 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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, shared_ptr 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() +{ + shared_ptr store = m_store.lock(); + + if (store) + { + if (m_open) + close(false); + + store->unregisterFolder(this); + } + else if (m_open) + { + onClose(); + } +} + + +int POP3Folder::getMode() const +{ + if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + return (m_mode); +} + + +int POP3Folder::getType() +{ + if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + if (m_path.isEmpty()) + return (TYPE_CONTAINS_FOLDERS); + else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") + return (TYPE_CONTAINS_MESSAGES); + else + throw exceptions::folder_not_found(); +} + + +int POP3Folder::getFlags() +{ + return (0); +} + + +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 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 response = POP3Response::readResponse(store->getConnection()); + + if (!response->isSuccess()) + throw exceptions::command_error("STAT", response->getFirstLine()); + + std::istringstream iss(response->getText()); + 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 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 int /* type */) +{ + throw exceptions::operation_not_supported(); +} + + +void POP3Folder::destroy() +{ + throw exceptions::operation_not_supported(); +} + + +bool POP3Folder::exists() +{ + shared_ptr 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 POP3Folder::getMessage(const int num) +{ + shared_ptr 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 (dynamicCast (shared_from_this()), num); +} + + +std::vector > POP3Folder::getMessages(const messageSet& msgs) +{ + shared_ptr 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 numbers = POP3Utils::messageSetToNumberList(msgs); + + std::vector > messages; + shared_ptr thisFolder(dynamicCast (shared_from_this())); + + for (std::vector ::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 (thisFolder, *it)); + } + + return messages; + } + else + { + throw exceptions::operation_not_supported(); + } +} + + +int POP3Folder::getMessageCount() +{ + shared_ptr 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 POP3Folder::getFolder(const folder::path::component& name) +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + + return make_shared (m_path / name, store); +} + + +std::vector > POP3Folder::getFolders(const bool /* recursive */) +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + + if (m_path.isEmpty()) + { + std::vector > v; + v.push_back(make_shared (folder::path::component("INBOX"), store)); + return (v); + } + else + { + std::vector > v; + return (v); + } +} + + +void POP3Folder::fetchMessages(std::vector >& msg, const fetchAttributes& options, + utility::progressListener* progress) +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + else if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + const size_t total = msg.size(); + size_t current = 0; + + if (progress) + progress->start(total); + + for (std::vector >::iterator it = msg.begin() ; + it != msg.end() ; ++it) + { + dynamicCast (*it)->fetch + (dynamicCast (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 response = + POP3Response::readMultilineResponse(store->getConnection()); + + if (response->isSuccess()) + { + // C: LIST + // S: +OK + // S: 1 47548 + // S: 2 12653 + // S: . + std::map result; + POP3Utils::parseMultiListOrUidlResponse(response, result); + + for (std::vector >::iterator it = msg.begin() ; + it != msg.end() ; ++it) + { + shared_ptr m = dynamicCast (*it); + + std::map ::const_iterator x = result.find(m->m_num); + + if (x != result.end()) + { + size_t size = 0; + + std::istringstream iss((*x).second); + 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 response = + POP3Response::readMultilineResponse(store->getConnection()); + + if (response->isSuccess()) + { + // C: UIDL + // S: +OK + // S: 1 whqtswO00WBw418f9t5JxYwZ + // S: 2 QhdPYR:00WBw1Ph7x7 + // S: . + std::map result; + POP3Utils::parseMultiListOrUidlResponse(response, result); + + for (std::vector >::iterator it = msg.begin() ; + it != msg.end() ; ++it) + { + shared_ptr m = dynamicCast (*it); + + std::map ::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(shared_ptr msg, const fetchAttributes& options) +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + else if (!isOpen()) + throw exceptions::illegal_state("Folder not open"); + + dynamicCast (msg)->fetch + (dynamicCast (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 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 >> size; + + dynamicCast (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 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 (msg)->m_uid = + string(it, responseText.end()); + } + } + } +} + + +int POP3Folder::getFetchCapabilities() const +{ + return fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | + fetchAttributes::SIZE | fetchAttributes::FULL_HEADER | + fetchAttributes::UID | fetchAttributes::IMPORTANCE; +} + + +shared_ptr POP3Folder::getParent() +{ + if (m_path.isEmpty()) + return null; + else + return make_shared (m_path.getParent(), m_store.lock()); +} + + +shared_ptr POP3Folder::getStore() const +{ + return m_store.lock(); +} + + +shared_ptr 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 store = m_store.lock(); + + const std::vector nums = POP3Utils::messageSetToNumberList(msgs); + + 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 ::const_iterator + it = nums.begin() ; it != nums.end() ; ++it) + { + POP3Command::DELE(*it)->send(store->getConnection()); + + shared_ptr response = + POP3Response::readResponse(store->getConnection()); + + if (!response->isSuccess()) + throw exceptions::command_error("DELE", response->getFirstLine()); + } + + // Sort message list + std::vector 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 ::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 event = + make_shared + (dynamicCast (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(); +} + + +void POP3Folder::addMessage + (shared_ptr /* msg */, const int /* flags */, + vmime::datetime* /* date */, utility::progressListener* /* progress */) +{ + throw exceptions::operation_not_supported(); +} + + +void POP3Folder::addMessage + (utility::inputStream& /* is */, const size_t /* size */, const int /* flags */, + vmime::datetime* /* date */, utility::progressListener* /* progress */) +{ + throw exceptions::operation_not_supported(); +} + + +void POP3Folder::copyMessages(const folder::path& /* dest */, const messageSet& /* msgs */) +{ + throw exceptions::operation_not_supported(); +} + + +void POP3Folder::status(int& count, int& unseen) +{ + count = 0; + unseen = 0; + + shared_ptr status = getStatus(); + + count = status->getMessageCount(); + unseen = status->getUnseenCount(); +} + + +shared_ptr POP3Folder::getStatus() +{ + shared_ptr store = m_store.lock(); + + if (!store) + throw exceptions::illegal_state("Store disconnected"); + + POP3Command::STAT()->send(store->getConnection()); + + shared_ptr response = + POP3Response::readResponse(store->getConnection()); + + if (!response->isSuccess()) + throw exceptions::command_error("STAT", response->getFirstLine()); + + + unsigned int count = 0; + + std::istringstream iss(response->getText()); + iss >> count; + + shared_ptr status = make_shared (); + + status->setMessageCount(count); + status->setUnseenCount(count); + + // Update local message count + if (m_messageCount != count) + { + const int oldCount = m_messageCount; + + m_messageCount = count; + + if (count > oldCount) + { + std::vector nums; + nums.reserve(count - oldCount); + + for (int i = oldCount + 1, j = 0 ; i <= count ; ++i, ++j) + nums[j] = i; + + // Notify message count changed + shared_ptr event = + make_shared + (dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_ADDED, nums); + + notifyMessageCount(event); + + // Notify folders with the same path + for (std::list ::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 event = + make_shared + (dynamicCast ((*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 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/src/vmime/net/pop3/POP3Folder.hpp b/src/vmime/net/pop3/POP3Folder.hpp new file mode 100644 index 00000000..27ea6e5f --- /dev/null +++ b/src/vmime/net/pop3/POP3Folder.hpp @@ -0,0 +1,157 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + +#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&); + +public: + + POP3Folder(const folder::path& path, shared_ptr store); + + ~POP3Folder(); + + int getMode() const; + + int getType(); + + int getFlags(); + + 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 int type); + + bool exists(); + + void destroy(); + + bool isOpen() const; + + shared_ptr getMessage(const int num); + std::vector > getMessages(const messageSet& msgs); + + int getMessageCount(); + + shared_ptr getFolder(const folder::path::component& name); + std::vector > 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); + + void addMessage(shared_ptr msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); + void addMessage(utility::inputStream& is, const size_t size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); + + void copyMessages(const folder::path& dest, const messageSet& msgs); + + void status(int& count, int& unseen); + shared_ptr getStatus(); + + void expunge(); + + shared_ptr getParent(); + + shared_ptr getStore() const; + shared_ptr getStore(); + + + void fetchMessages(std::vector >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL); + void fetchMessage(shared_ptr msg, const fetchAttributes& options); + + int getFetchCapabilities() const; + + std::vector getMessageNumbersStartingOnUID(const message::uid& uid); + +private: + + void registerMessage(POP3Message* msg); + void unregisterMessage(POP3Message* msg); + + void onStoreDisconnected(); + + void onClose(); + + + weak_ptr m_store; + + folder::path m_path; + folder::path::component m_name; + + int m_mode; + bool m_open; + + int m_messageCount; + + typedef std::map 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/src/vmime/net/pop3/POP3FolderStatus.cpp b/src/vmime/net/pop3/POP3FolderStatus.cpp new file mode 100644 index 00000000..944379ac --- /dev/null +++ b/src/vmime/net/pop3/POP3FolderStatus.cpp @@ -0,0 +1,88 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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) +{ +} + + +unsigned int POP3FolderStatus::getMessageCount() const +{ + return m_count; +} + + +unsigned int POP3FolderStatus::getUnseenCount() const +{ + return m_unseen; +} + + +void POP3FolderStatus::setMessageCount(const unsigned int count) +{ + m_count = count; +} + + +void POP3FolderStatus::setUnseenCount(const unsigned int unseen) +{ + m_unseen = unseen; +} + + +shared_ptr POP3FolderStatus::clone() const +{ + return make_shared (*this); +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/src/vmime/net/pop3/POP3FolderStatus.hpp b/src/vmime/net/pop3/POP3FolderStatus.hpp new file mode 100644 index 00000000..70ba48b6 --- /dev/null +++ b/src/vmime/net/pop3/POP3FolderStatus.hpp @@ -0,0 +1,76 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + unsigned int getMessageCount() const; + unsigned int getUnseenCount() const; + + shared_ptr clone() const; + + + void setMessageCount(const unsigned int count); + void setUnseenCount(const unsigned int unseen); + +private: + + unsigned int m_count; + unsigned int 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/src/vmime/net/pop3/POP3Message.cpp b/src/vmime/net/pop3/POP3Message.cpp new file mode 100644 index 00000000..08523611 --- /dev/null +++ b/src/vmime/net/pop3/POP3Message.cpp @@ -0,0 +1,250 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace net { +namespace pop3 { + + +POP3Message::POP3Message(shared_ptr folder, const int num) + : m_folder(folder), m_num(num), m_size(-1), m_deleted(false) +{ + folder->registerMessage(this); +} + + +POP3Message::~POP3Message() +{ + shared_ptr folder = m_folder.lock(); + + if (folder) + folder->unregisterMessage(this); +} + + +void POP3Message::onFolderClosed() +{ + m_folder.reset(); +} + + +int 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 (-1)) + throw exceptions::unfetched_object(); + + return (m_size); +} + + +bool POP3Message::isExpunged() const +{ + return (false); +} + + +int POP3Message::getFlags() const +{ + int flags = FLAG_RECENT; + + if (m_deleted) + flags |= FLAG_DELETED; + + return (flags); +} + + +shared_ptr POP3Message::getStructure() const +{ + throw exceptions::operation_not_supported(); +} + + +shared_ptr POP3Message::getStructure() +{ + throw exceptions::operation_not_supported(); +} + + +shared_ptr POP3Message::getHeader() const +{ + if (m_header == NULL) + 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 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 (-1)) + throw exceptions::partial_fetch_not_supported(); + + // Emit the "RETR" command + shared_ptr store = constCast (folder)->m_store.lock(); + + POP3Command::RETR(m_num)->send(store->getConnection()); + + try + { + POP3Response::readLargeResponse + (store->getConnection(), os, progress, m_size); + } + catch (exceptions::command_error& e) + { + throw exceptions::command_error("RETR", e.response()); + } +} + + +void POP3Message::extractPart + (shared_ptr /* 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(shared_ptr /* p */) +{ + throw exceptions::operation_not_supported(); +} + + +void POP3Message::fetch(shared_ptr msgFolder, const fetchAttributes& options) +{ + shared_ptr 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 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
(); + 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 POP3Message::getParsedMessage() +{ + std::ostringstream oss; + utility::outputStreamAdapter os(oss); + + extract(os); + + shared_ptr msg = make_shared (); + msg->parse(oss.str()); + + return msg; +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + diff --git a/src/vmime/net/pop3/POP3Message.hpp b/src/vmime/net/pop3/POP3Message.hpp new file mode 100644 index 00000000..87e71ba7 --- /dev/null +++ b/src/vmime/net/pop3/POP3Message.hpp @@ -0,0 +1,121 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr folder, const int num); + + ~POP3Message(); + + + int getNumber() const; + + const uid getUID() const; + + size_t getSize() const; + + bool isExpunged() const; + + shared_ptr getStructure() const; + shared_ptr getStructure(); + + shared_ptr 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 + (shared_ptr 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(shared_ptr p); + + shared_ptr getParsedMessage(); + +private: + + void fetch(shared_ptr folder, const fetchAttributes& options); + + void onFolderClosed(); + + weak_ptr m_folder; + int m_num; + uid m_uid; + size_t m_size; + + bool m_deleted; + + shared_ptr
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/src/vmime/net/pop3/POP3Response.cpp b/src/vmime/net/pop3/POP3Response.cpp new file mode 100644 index 00000000..1dc5ee76 --- /dev/null +++ b/src/vmime/net/pop3/POP3Response.cpp @@ -0,0 +1,428 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sok, shared_ptr toh) + : m_socket(sok), m_timeoutHandler(toh) +{ +} + + +// static +shared_ptr POP3Response::readResponse(shared_ptr conn) +{ + shared_ptr resp = shared_ptr + (new POP3Response(conn->getSocket(), conn->getTimeoutHandler())); + + string buffer; + resp->readResponseImpl(buffer, /* multiLine */ false); + + resp->m_firstLine = buffer; + resp->m_code = getResponseCode(buffer); + stripResponseCode(buffer, resp->m_text); + + return resp; +} + + +// static +shared_ptr POP3Response::readMultilineResponse(shared_ptr conn) +{ + shared_ptr resp = shared_ptr + (new POP3Response(conn->getSocket(), conn->getTimeoutHandler())); + + 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; + + while (std::getline(iss, line, '\n')) + resp->m_lines.push_back(utility::stringUtils::trim(line)); + + return resp; +} + + +// static +shared_ptr POP3Response::readLargeResponse + (shared_ptr conn, utility::outputStream& os, + utility::progressListener* progress, const size_t predictedSize) +{ + shared_ptr resp = shared_ptr + (new POP3Response(conn->getSocket(), conn->getTimeoutHandler())); + + string firstLine; + resp->readResponseImpl(firstLine, os, progress, predictedSize); + + resp->m_firstLine = firstLine; + resp->m_code = getResponseCode(firstLine); + stripResponseCode(firstLine, resp->m_text); + + 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 + { + platform::getHandler()->wait(); + 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 ((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); + } + } +} + + +void 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()) + { +#if 0 // not supported + // Check for possible cancellation + if (progress && progress->cancel()) + throw exceptions::operation_cancelled(); +#endif + + // 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 + { + platform::getHandler()->wait(); + 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); +} + + +// 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/src/vmime/net/pop3/POP3Response.hpp b/src/vmime/net/pop3/POP3Response.hpp new file mode 100644 index 00000000..20477b5e --- /dev/null +++ b/src/vmime/net/pop3/POP3Response.hpp @@ -0,0 +1,182 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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" + + +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 readResponse(shared_ptr 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 readMultilineResponse(shared_ptr 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 readLargeResponse + (shared_ptr 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(shared_ptr sok, shared_ptr toh); + + void readResponseImpl(string& buffer, const bool multiLine); + void 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 m_socket; + shared_ptr m_timeoutHandler; + + string m_firstLine; + ResponseCode m_code; + string m_text; + + std::vector 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/src/vmime/net/pop3/POP3SStore.cpp b/src/vmime/net/pop3/POP3SStore.cpp new file mode 100644 index 00000000..f1c3da74 --- /dev/null +++ b/src/vmime/net/pop3/POP3SStore.cpp @@ -0,0 +1,79 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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/src/vmime/net/pop3/POP3SStore.hpp b/src/vmime/net/pop3/POP3SStore.hpp new file mode 100644 index 00000000..e60b4ef8 --- /dev/null +++ b/src/vmime/net/pop3/POP3SStore.hpp @@ -0,0 +1,71 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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/src/vmime/net/pop3/POP3ServiceInfos.cpp b/src/vmime/net/pop3/POP3ServiceInfos.cpp new file mode 100644 index 00000000..4760d4f2 --- /dev/null +++ b/src/vmime/net/pop3/POP3ServiceInfos.cpp @@ -0,0 +1,143 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 POP3ServiceInfos::getAvailableProperties() const +{ + std::vector 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/src/vmime/net/pop3/POP3ServiceInfos.hpp b/src/vmime/net/pop3/POP3ServiceInfos.hpp new file mode 100644 index 00000000..710d8be3 --- /dev/null +++ b/src/vmime/net/pop3/POP3ServiceInfos.hpp @@ -0,0 +1,93 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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/src/vmime/net/pop3/POP3Store.cpp b/src/vmime/net/pop3/POP3Store.cpp new file mode 100644 index 00000000..e6e95b1b --- /dev/null +++ b/src/vmime/net/pop3/POP3Store.cpp @@ -0,0 +1,240 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace net { +namespace pop3 { + + +POP3Store::POP3Store(shared_ptr sess, shared_ptr auth, const bool secured) + : store(sess, getInfosInstance(), auth), m_isPOP3S(secured) +{ +} + + +POP3Store::~POP3Store() +{ + try + { + if (isConnected()) + disconnect(); + } + catch (vmime::exception&) + { + // Ignore + } +} + + +const string POP3Store::getProtocolName() const +{ + return "pop3"; +} + + +shared_ptr POP3Store::getDefaultFolder() +{ + if (!isConnected()) + throw exceptions::illegal_state("Not connected"); + + return make_shared + (folder::path(folder::path::component("INBOX")), + dynamicCast (shared_from_this())); +} + + +shared_ptr POP3Store::getRootFolder() +{ + if (!isConnected()) + throw exceptions::illegal_state("Not connected"); + + return make_shared + (folder::path(), dynamicCast (shared_from_this())); +} + + +shared_ptr POP3Store::getFolder(const folder::path& path) +{ + if (!isConnected()) + throw exceptions::illegal_state("Not connected"); + + return make_shared + (path, dynamicCast (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 + (dynamicCast (shared_from_this()), getAuthenticator()); + + try + { + m_connection->connect(); + } + catch (std::exception&) + { + m_connection = null; + throw; + } +} + + +bool POP3Store::isPOP3S() const +{ + return m_isPOP3S; +} + + +bool POP3Store::isConnected() const +{ + return m_connection && m_connection->isConnected(); +} + + +bool POP3Store::isSecuredConnection() const +{ + if (m_connection == NULL) + return false; + + return m_connection->isSecuredConnection(); +} + + +shared_ptr POP3Store::getConnectionInfos() const +{ + if (m_connection == NULL) + return null; + + return m_connection->getConnectionInfos(); +} + + +shared_ptr POP3Store::getConnection() +{ + return m_connection; +} + + +void POP3Store::disconnect() +{ + if (!isConnected()) + throw exceptions::not_connected(); + + for (std::list ::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 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 ::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/src/vmime/net/pop3/POP3Store.hpp b/src/vmime/net/pop3/POP3Store.hpp new file mode 100644 index 00000000..b35659a0 --- /dev/null +++ b/src/vmime/net/pop3/POP3Store.hpp @@ -0,0 +1,116 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr auth, const bool secured = false); + ~POP3Store(); + + const string getProtocolName() const; + + shared_ptr getDefaultFolder(); + shared_ptr getRootFolder(); + shared_ptr 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 getConnectionInfos() const; + shared_ptr getConnection(); + + bool isPOP3S() const; + +private: + + shared_ptr m_connection; + + + void registerFolder(POP3Folder* folder); + void unregisterFolder(POP3Folder* folder); + + std::list 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/src/vmime/net/pop3/POP3Utils.cpp b/src/vmime/net/pop3/POP3Utils.cpp new file mode 100644 index 00000000..7ba65fff --- /dev/null +++ b/src/vmime/net/pop3/POP3Utils.cpp @@ -0,0 +1,114 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace net { +namespace pop3 { + + +// static +void POP3Utils::parseMultiListOrUidlResponse(shared_ptr response, std::map & result) +{ + std::map 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()) + { + int 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 ::value_type(number, string(it, line.end()))); + } + } + } +} + + + +class POP3MessageSetEnumerator : public messageSetEnumerator +{ +public: + + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) + { + for (int i = range.getFirst(), last = range.getLast() ; i <= last ; ++i) + list.push_back(i); + } + + void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) + { + // Not supported + } + +public: + + std::vector list; +}; + + +// static +const std::vector POP3Utils::messageSetToNumberList(const messageSet& msgs) +{ + POP3MessageSetEnumerator en; + msgs.enumerate(en); + + return en.list; +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + diff --git a/src/vmime/net/pop3/POP3Utils.hpp b/src/vmime/net/pop3/POP3Utils.hpp new file mode 100644 index 00000000..c7459efe --- /dev/null +++ b/src/vmime/net/pop3/POP3Utils.hpp @@ -0,0 +1,86 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#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 + (shared_ptr response, std::map & result); + + /** Returns a list of message numbers given a message set. + * + * @param msgs message set + * @return list of message numbers + */ + static const std::vector messageSetToNumberList(const messageSet& msgs); +}; + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + +#endif // VMIME_NET_POP3_POP3UTILS_HPP_INCLUDED + diff --git a/src/vmime/net/pop3/pop3.hpp b/src/vmime/net/pop3/pop3.hpp new file mode 100644 index 00000000..366b1e4a --- /dev/null +++ b/src/vmime/net/pop3/pop3.hpp @@ -0,0 +1,35 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/securedConnectionInfos.hpp b/src/vmime/net/securedConnectionInfos.hpp new file mode 100644 index 00000000..8ed8b138 --- /dev/null +++ b/src/vmime/net/securedConnectionInfos.hpp @@ -0,0 +1,55 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/sendmail/sendmail.hpp b/src/vmime/net/sendmail/sendmail.hpp new file mode 100644 index 00000000..b3692526 --- /dev/null +++ b/src/vmime/net/sendmail/sendmail.hpp @@ -0,0 +1,31 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/sendmail/sendmailServiceInfos.cpp b/src/vmime/net/sendmail/sendmailServiceInfos.cpp new file mode 100644 index 00000000..21cac00c --- /dev/null +++ b/src/vmime/net/sendmail/sendmailServiceInfos.cpp @@ -0,0 +1,78 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 sendmailServiceInfos::getAvailableProperties() const +{ + std::vector 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/src/vmime/net/sendmail/sendmailServiceInfos.hpp b/src/vmime/net/sendmail/sendmailServiceInfos.hpp new file mode 100644 index 00000000..de94e392 --- /dev/null +++ b/src/vmime/net/sendmail/sendmailServiceInfos.hpp @@ -0,0 +1,71 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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/src/vmime/net/sendmail/sendmailTransport.cpp b/src/vmime/net/sendmail/sendmailTransport.cpp new file mode 100644 index 00000000..8ef18e3b --- /dev/null +++ b/src/vmime/net/sendmail/sendmailTransport.cpp @@ -0,0 +1,230 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 (getSession(), \ + dynamic_cast (getInfos()).getProperties().prop)) +#define HAS_PROPERTY(prop) \ + (getInfos().hasProperty(getSession(), \ + dynamic_cast (getInfos()).getProperties().prop)) + + +namespace vmime { +namespace net { +namespace sendmail { + + +sendmailTransport::sendmailTransport(shared_ptr sess, shared_ptr auth) + : transport(sess, getInfosInstance(), auth), m_connected(false) +{ +} + + +sendmailTransport::~sendmailTransport() +{ + try + { + if (isConnected()) + disconnect(); + } + catch (vmime::exception&) + { + // Ignore + } +} + + +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 sendmailTransport::getConnectionInfos() const +{ + return make_shared ("localhost", static_cast (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) +{ + // 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 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 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 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/src/vmime/net/sendmail/sendmailTransport.hpp b/src/vmime/net/sendmail/sendmailTransport.hpp new file mode 100644 index 00000000..d1c6aec0 --- /dev/null +++ b/src/vmime/net/sendmail/sendmailTransport.hpp @@ -0,0 +1,103 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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()); + + bool isSecuredConnection() const; + shared_ptr getConnectionInfos() const; + +private: + + void internalDisconnect(); + + void internalSend(const std::vector 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/src/vmime/net/service.cpp b/src/vmime/net/service.cpp new file mode 100644 index 00000000..c52ba592 --- /dev/null +++ b/src/vmime/net/service.cpp @@ -0,0 +1,152 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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" + +#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(shared_ptr sess, const serviceInfos& /* infos */, + shared_ptr auth) + : m_session(sess), m_auth(auth) +{ + if (!auth) + { +#if VMIME_HAVE_SASL_SUPPORT + m_auth = make_shared + (); +#else + m_auth = make_shared + (); +#endif // VMIME_HAVE_SASL_SUPPORT + } + +#if VMIME_HAVE_TLS_SUPPORT + m_certVerifier = make_shared (); +#endif // VMIME_HAVE_TLS_SUPPORT + + m_socketFactory = platform::getHandler()->getSocketFactory(); +} + + +service::~service() +{ +} + + +shared_ptr service::getSession() const +{ + return (m_session); +} + + +shared_ptr service::getSession() +{ + return (m_session); +} + + +shared_ptr service::getAuthenticator() const +{ + return (m_auth); +} + + +shared_ptr service::getAuthenticator() +{ + return (m_auth); +} + + +void service::setAuthenticator(shared_ptr auth) +{ + m_auth = auth; +} + + +#if VMIME_HAVE_TLS_SUPPORT + +void service::setCertificateVerifier(shared_ptr cv) +{ + m_certVerifier = cv; +} + + +shared_ptr service::getCertificateVerifier() +{ + return m_certVerifier; +} + +#endif // VMIME_HAVE_TLS_SUPPORT + + +void service::setSocketFactory(shared_ptr sf) +{ + m_socketFactory = sf; +} + + +shared_ptr service::getSocketFactory() +{ + return m_socketFactory; +} + + +void service::setTimeoutHandlerFactory(shared_ptr thf) +{ + m_toHandlerFactory = thf; +} + + +shared_ptr service::getTimeoutHandlerFactory() +{ + return m_toHandlerFactory; +} + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + diff --git a/src/vmime/net/service.hpp b/src/vmime/net/service.hpp new file mode 100644 index 00000000..6969ac20 --- /dev/null +++ b/src/vmime/net/service.hpp @@ -0,0 +1,233 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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" + +#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 +{ +protected: + + service(shared_ptr sess, const serviceInfos& infos, shared_ptr 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 getSession() const; + + /** Return the session object associated with this service instance. + * + * @return session object + */ + shared_ptr 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 getAuthenticator() const; + + /** Return the authenticator object used with this service instance. + * + * @return authenticator object + */ + shared_ptr getAuthenticator(); + + /** Set the authenticator object used with this service instance. + * + * @param auth authenticator object + */ + void setAuthenticator(shared_ptr auth); + +#if VMIME_HAVE_TLS_SUPPORT + + /** Set the object responsible for verifying certificates when + * using secured connections (TLS/SSL). + */ + void setCertificateVerifier(shared_ptr cv); + + /** Get the object responsible for verifying certificates when + * using secured connections (TLS/SSL). + */ + shared_ptr getCertificateVerifier(); + +#endif // VMIME_HAVE_TLS_SUPPORT + + /** Set the factory used to create socket objects for this + * service. + * + * @param sf socket factory + */ + void setSocketFactory(shared_ptr sf); + + /** Return the factory used to create socket objects for this + * service. + * + * @return socket factory + */ + shared_ptr getSocketFactory(); + + /** Set the factory used to create timeoutHandler objects for + * this service. By default, no timeout handler is used. Not all + * services support timeout handling. + * + * @param thf timeoutHandler factory + */ + void setTimeoutHandlerFactory(shared_ptr thf); + + /** Return the factory used to create timeoutHandler objects for + * this service. + * + * @return timeoutHandler factory + */ + shared_ptr getTimeoutHandlerFactory(); + + /** 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 + 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 getConnectionInfos() const = 0; + +private: + + shared_ptr m_session; + shared_ptr m_auth; + +#if VMIME_HAVE_TLS_SUPPORT + shared_ptr m_certVerifier; +#endif // VMIME_HAVE_TLS_SUPPORT + + shared_ptr m_socketFactory; + + shared_ptr m_toHandlerFactory; +}; + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_NET_SERVICE_HPP_INCLUDED diff --git a/src/vmime/net/serviceFactory.cpp b/src/vmime/net/serviceFactory.cpp new file mode 100644 index 00000000..bbc9944a --- /dev/null +++ b/src/vmime/net/serviceFactory.cpp @@ -0,0 +1,145 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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::getInstance() +{ + static serviceFactory instance; + return shared_ptr (&instance, noop_shared_ptr_deleter ()); +} + + +shared_ptr serviceFactory::create + (shared_ptr sess, const string& protocol, + shared_ptr auth) +{ + return (getServiceByProtocol(protocol)->create(sess, auth)); +} + + +shared_ptr serviceFactory::create + (shared_ptr sess, const utility::url& u, + shared_ptr auth) +{ + shared_ptr 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 serviceFactory::getServiceByProtocol(const string& protocol) const +{ + const string name(utility::stringUtils::toLower(protocol)); + + for (std::vector >::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 serviceFactory::getServiceAt(const size_t pos) const +{ + return (m_services[pos]); +} + + +const std::vector > serviceFactory::getServiceList() const +{ + std::vector > res; + + for (std::vector >::const_iterator it = m_services.begin() ; + it != m_services.end() ; ++it) + { + res.push_back(*it); + } + + return (res); +} + + +void serviceFactory::registerService(shared_ptr reg) +{ + m_services.push_back(reg); +} + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + diff --git a/src/vmime/net/serviceFactory.hpp b/src/vmime/net/serviceFactory.hpp new file mode 100644 index 00000000..9295b345 --- /dev/null +++ b/src/vmime/net/serviceFactory.hpp @@ -0,0 +1,165 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#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 getInstance(); + + /** Information about a registered service. */ + class registeredService : public object + { + friend class serviceFactory; + + protected: + + virtual ~registeredService() { } + + public: + + virtual shared_ptr create + (shared_ptr sess, + shared_ptr 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(shared_ptr 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 create + (shared_ptr sess, + const string& protocol, + shared_ptr 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 create + (shared_ptr sess, + const utility::url& u, + shared_ptr 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 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 getServiceAt(const size_t pos) const; + + /** Return a list of all registered services. + * + * @return list of registered services + */ + const std::vector > getServiceList() const; + +private: + + std::vector > m_services; +}; + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_NET_SERVICEFACTORY_HPP_INCLUDED diff --git a/src/vmime/net/serviceInfos.cpp b/src/vmime/net/serviceInfos.cpp new file mode 100644 index 00000000..8de0529e --- /dev/null +++ b/src/vmime/net/serviceInfos.cpp @@ -0,0 +1,167 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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); + +#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(shared_ptr 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/src/vmime/net/serviceInfos.hpp b/src/vmime/net/serviceInfos.hpp new file mode 100644 index 00000000..6e3209ca --- /dev/null +++ b/src/vmime/net/serviceInfos.hpp @@ -0,0 +1,246 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#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 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; + +#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 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 + const TYPE getPropertyValue(shared_ptr s, const property& p) const + { + if (p.getFlags() & property::FLAG_REQUIRED) + return s->getProperties()[getPropertyPrefix() + p.getName()].template getValue (); + + return s->getProperties().template getProperty (getPropertyPrefix() + p.getName(), + propertySet::valueFromString (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(shared_ptr s, const property& p) const; +}; + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_NET_SERVICEINFOS_HPP_INCLUDED diff --git a/src/vmime/net/serviceRegistration.inl b/src/vmime/net/serviceRegistration.inl new file mode 100644 index 00000000..2366fe01 --- /dev/null +++ b/src/vmime/net/serviceRegistration.inl @@ -0,0 +1,98 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 registeredServiceImpl : public serviceFactory::registeredService +{ +public: + + registeredServiceImpl(const string& name, const int type) + : m_type(type), m_name(name), m_servInfos(S::getInfosInstance()) + { + } + + shared_ptr create + (shared_ptr sess, + shared_ptr auth) const + { + return make_shared (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 serviceRegisterer +{ +public: + + serviceRegisterer(const string& protocol, const service::Type type) + { + serviceFactory::getInstance()->registerService + (make_shared >(protocol, type)); + } +}; + + +} // net +} // vmime + + +#define REGISTER_SERVICE(p_class, p_name, p_type) \ + vmime::net::serviceRegisterer \ + p_name(#p_name, vmime::net::service::p_type) + + +#endif // VMIME_BUILDING_DOC + diff --git a/src/vmime/net/session.cpp b/src/vmime/net/session.cpp new file mode 100644 index 00000000..36b9f2c3 --- /dev/null +++ b/src/vmime/net/session.cpp @@ -0,0 +1,158 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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() + : m_tlsProps(make_shared ()) +{ +} + + +session::session(const session& sess) + : object(), m_props(sess.m_props), + m_tlsProps(make_shared (*sess.m_tlsProps)) +{ +} + + +session::session(const propertySet& props) + : m_props(props), m_tlsProps(make_shared ()) +{ +} + + +session::~session() +{ +} + + +shared_ptr session::getTransport(shared_ptr auth) +{ + return (getTransport(m_props["transport.protocol"], auth)); +} + + +shared_ptr session::getTransport + (const string& protocol, shared_ptr auth) +{ + shared_ptr sess(dynamicCast (shared_from_this())); + shared_ptr sv = serviceFactory::getInstance()->create(sess, protocol, auth); + + if (!sv || sv->getType() != service::TYPE_TRANSPORT) + return null; + + return dynamicCast (sv); +} + + +shared_ptr session::getTransport + (const utility::url& url, shared_ptr auth) +{ + shared_ptr sess(dynamicCast (shared_from_this())); + shared_ptr sv = serviceFactory::getInstance()->create(sess, url, auth); + + if (!sv || sv->getType() != service::TYPE_TRANSPORT) + return null; + + return dynamicCast (sv); +} + + +shared_ptr session::getStore(shared_ptr auth) +{ + return (getStore(m_props["store.protocol"], auth)); +} + + +shared_ptr session::getStore + (const string& protocol, shared_ptr auth) +{ + shared_ptr sess(dynamicCast (shared_from_this())); + shared_ptr sv = serviceFactory::getInstance()->create(sess, protocol, auth); + + if (!sv || sv->getType() != service::TYPE_STORE) + return null; + + return dynamicCast (sv); +} + + +shared_ptr session::getStore + (const utility::url& url, shared_ptr auth) +{ + shared_ptr sess(dynamicCast (shared_from_this())); + shared_ptr sv = serviceFactory::getInstance()->create(sess, url, auth); + + if (!sv || sv->getType() != service::TYPE_STORE) + return null; + + return dynamicCast (sv); +} + + +const propertySet& session::getProperties() const +{ + return (m_props); +} + + +propertySet& session::getProperties() +{ + return (m_props); +} + + +void session::setTLSProperties(shared_ptr tlsProps) +{ + m_tlsProps = make_shared (*tlsProps); +} + + +shared_ptr session::getTLSProperties() const +{ + return m_tlsProps; +} + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + diff --git a/src/vmime/net/session.hpp b/src/vmime/net/session.hpp new file mode 100644 index 00000000..a7e0ea1a --- /dev/null +++ b/src/vmime/net/session.hpp @@ -0,0 +1,178 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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" + +#include "vmime/net/tls/TLSProperties.hpp" + +#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: + + session(); + session(const session& sess); + session(const propertySet& props); + + virtual ~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 getTransport + (shared_ptr 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 getTransport + (const string& protocol, + shared_ptr 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 getTransport + (const utility::url& url, + shared_ptr 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 getStore(shared_ptr 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 getStore + (const string& protocol, + shared_ptr 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 getStore + (const utility::url& url, + shared_ptr auth = null); + + /** Properties for the session and for the services. + */ + const propertySet& getProperties() const; + + /** Properties for the session and for the services. + */ + propertySet& getProperties(); + + /** Set properties for SSL/TLS secured connections in this session. + * + * @param tlsProps SSL/TLS properties + */ + void setTLSProperties(shared_ptr tlsProps); + + /** Get properties for SSL/TLS secured connections in this session. + * + * @return SSL/TLS properties + */ + shared_ptr getTLSProperties() const; + +private: + + propertySet m_props; + + shared_ptr m_tlsProps; +}; + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_NET_SESSION_HPP_INCLUDED diff --git a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp new file mode 100644 index 00000000..69f63bc9 --- /dev/null +++ b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp @@ -0,0 +1,145 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace net { +namespace smtp { + + +SMTPChunkingOutputStreamAdapter::SMTPChunkingOutputStreamAdapter(shared_ptr conn) + : m_connection(conn), m_bufferSize(0), m_chunkCount(0) +{ +} + + +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 PIPELINING is not supported, read one response for this BDAT command + if (!m_connection->hasExtension("PIPELINING")) + { + shared_ptr 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 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(data, data + 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; +} + + +size_t SMTPChunkingOutputStreamAdapter::getBlockSize() +{ + return sizeof(m_buffer); +} + + +} // smtp +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp new file mode 100644 index 00000000..cfb3f50f --- /dev/null +++ b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp @@ -0,0 +1,85 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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" + + +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(shared_ptr conn); + + 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 m_connection; + + byte_t m_buffer[262144]; // 256 KB + size_t m_bufferSize; + + unsigned int m_chunkCount; +}; + + +} // smtp +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP + +#endif // VMIME_NET_SMTP_SMTPCHUNKINGOUTPUTSTREAMADAPTER_HPP_INCLUDED diff --git a/src/vmime/net/smtp/SMTPCommand.cpp b/src/vmime/net/smtp/SMTPCommand.cpp new file mode 100644 index 00000000..949ab0c1 --- /dev/null +++ b/src/vmime/net/smtp/SMTPCommand.cpp @@ -0,0 +1,214 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/mailbox.hpp" +#include "vmime/utility/outputStreamAdapter.hpp" + + +namespace vmime { +namespace net { +namespace smtp { + + +SMTPCommand::SMTPCommand(const string& text) + : m_text(text) +{ +} + + +// static +shared_ptr SMTPCommand::EHLO(const string& hostname) +{ + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "EHLO " << hostname; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr SMTPCommand::HELO(const string& hostname) +{ + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "HELO " << hostname; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr SMTPCommand::AUTH(const string& mechName) +{ + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "AUTH " << mechName; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr SMTPCommand::STARTTLS() +{ + return createCommand("STARTTLS"); +} + + +// static +shared_ptr SMTPCommand::MAIL(const mailbox& mbox, const bool utf8) +{ + return MAIL(mbox, utf8, 0); +} + + +// static +shared_ptr SMTPCommand::MAIL(const mailbox& mbox, const bool utf8, const size_t size) +{ + 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 (utf8) + cmd << " SMTPUTF8"; + + if (size != 0) + cmd << " SIZE=" << size; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr SMTPCommand::RCPT(const mailbox& mbox, const bool utf8) +{ + 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 << ">"; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr SMTPCommand::RSET() +{ + return createCommand("RSET"); +} + + +// static +shared_ptr SMTPCommand::DATA() +{ + return createCommand("DATA"); +} + + +// static +shared_ptr 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::NOOP() +{ + return createCommand("NOOP"); +} + + +// static +shared_ptr SMTPCommand::QUIT() +{ + return createCommand("QUIT"); +} + + +// static +shared_ptr SMTPCommand::createCommand(const string& text) +{ + return shared_ptr (new SMTPCommand(text)); +} + + +const string SMTPCommand::getText() const +{ + return m_text; +} + + +void SMTPCommand::writeToSocket(shared_ptr sok) +{ + sok->send(m_text + "\r\n"); +} + + +} // smtp +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/vmime/net/smtp/SMTPCommand.hpp b/src/vmime/net/smtp/SMTPCommand.hpp new file mode 100644 index 00000000..dbb0888b --- /dev/null +++ b/src/vmime/net/smtp/SMTPCommand.hpp @@ -0,0 +1,111 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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; + + +namespace smtp { + + +/** A SMTP command, as sent to server. + */ +class VMIME_EXPORT SMTPCommand : public object +{ +public: + + static shared_ptr HELO(const string& hostname); + static shared_ptr EHLO(const string& hostname); + static shared_ptr AUTH(const string& mechName); + static shared_ptr STARTTLS(); + static shared_ptr MAIL(const mailbox& mbox, const bool utf8); + static shared_ptr MAIL(const mailbox& mbox, const bool utf8, const size_t size); + static shared_ptr RCPT(const mailbox& mbox, const bool utf8); + static shared_ptr RSET(); + static shared_ptr DATA(); + static shared_ptr BDAT(const size_t chunkSize, const bool last); + static shared_ptr NOOP(); + static shared_ptr QUIT(); + + /** Creates a new SMTP command with the specified text. + * + * @param text command text + * @return a new SMTPCommand object + */ + static shared_ptr createCommand(const string& text); + + /** Sends this command to the specified socket. + * + * @param sok socket to which the command will be written + */ + virtual void writeToSocket(shared_ptr sok); + + /** Returns the full text of the command, including command name + * and parameters (if any). + * + * @return command text (eg. "RCPT TO:") + */ + virtual const string getText() const; + +protected: + + SMTPCommand(const string& text); + SMTPCommand(const SMTPCommand&); + +private: + + string m_text; +}; + + +} // smtp +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP + +#endif // VMIME_NET_SMTP_SMTPCOMMAND_HPP_INCLUDED diff --git a/src/vmime/net/smtp/SMTPCommandSet.cpp b/src/vmime/net/smtp/SMTPCommandSet.cpp new file mode 100644 index 00000000..3e03427c --- /dev/null +++ b/src/vmime/net/smtp/SMTPCommandSet.cpp @@ -0,0 +1,144 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace net { +namespace smtp { + + +SMTPCommandSet::SMTPCommandSet(const bool pipeline) + : SMTPCommand(""), m_pipeline(pipeline), + m_started(false), m_lastCommandSent() +{ +} + + +// static +shared_ptr SMTPCommandSet::create(const bool pipeline) +{ + return shared_ptr (new SMTPCommandSet(pipeline)); +} + + +void SMTPCommandSet::addCommand(shared_ptr 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(shared_ptr sok) +{ + if (m_pipeline) + { + if (!m_started) + { + // Send all commands at once + for (std::list >::const_iterator it = m_commands.begin() ; + it != m_commands.end() ; ++it) + { + shared_ptr cmd = *it; + cmd->writeToSocket(sok); + } + } + + if (!m_commands.empty()) + { + // Advance the pointer to last command sent + shared_ptr cmd = m_commands.front(); + m_commands.pop_front(); + + m_lastCommandSent = cmd; + } + } + else + { + if (!m_commands.empty()) + { + // Send only one command + shared_ptr cmd = m_commands.front(); + m_commands.pop_front(); + + cmd->writeToSocket(sok); + + m_lastCommandSent = cmd; + } + } + + m_started = true; +} + + +const string SMTPCommandSet::getText() const +{ + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + + for (std::list >::const_iterator it = m_commands.begin() ; + it != m_commands.end() ; ++it) + { + cmd << (*it)->getText() << "\r\n"; + } + + return cmd.str(); +} + + +bool SMTPCommandSet::isFinished() const +{ + return (m_pipeline && m_started) || (m_commands.size() == 0 && m_started); +} + + +shared_ptr SMTPCommandSet::getLastCommandSent() const +{ + return m_lastCommandSent; +} + + +} // smtp +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/vmime/net/smtp/SMTPCommandSet.hpp b/src/vmime/net/smtp/SMTPCommandSet.hpp new file mode 100644 index 00000000..8e744c2b --- /dev/null +++ b/src/vmime/net/smtp/SMTPCommandSet.hpp @@ -0,0 +1,105 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#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 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(shared_ptr 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 getLastCommandSent() const; + + + void writeToSocket(shared_ptr sok); + + const string getText() const; + +private: + + SMTPCommandSet(const bool pipeline); + SMTPCommandSet(const SMTPCommandSet&); + + + bool m_pipeline; + bool m_started; + std::list > m_commands; + shared_ptr 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/src/vmime/net/smtp/SMTPConnection.cpp b/src/vmime/net/smtp/SMTPConnection.cpp new file mode 100644 index 00000000..26be25db --- /dev/null +++ b/src/vmime/net/smtp/SMTPConnection.cpp @@ -0,0 +1,618 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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" +#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 (getSession(), \ + dynamic_cast (m_transport.lock()->getInfos()).getProperties().prop)) +#define HAS_PROPERTY(prop) \ + (m_transport.lock()->getInfos().hasProperty(getSession(), \ + dynamic_cast (m_transport.lock()->getInfos()).getProperties().prop)) + + +namespace vmime { +namespace net { +namespace smtp { + + + +SMTPConnection::SMTPConnection(shared_ptr transport, shared_ptr auth) + : m_transport(transport), m_auth(auth), m_socket(null), m_timeoutHandler(null), + m_authenticated(false), m_secured(false), m_extendedSMTP(false) +{ +} + + +SMTPConnection::~SMTPConnection() +{ + try + { + if (isConnected()) + disconnect(); + else if (m_socket) + internalDisconnect(); + } + catch (vmime::exception&) + { + // Ignore + } +} + + +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 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); + +#if VMIME_HAVE_TLS_SUPPORT + if (transport->isSMTPS()) // dedicated port/SMTPS + { + shared_ptr tlsSession = tls::TLSSession::create + (transport->getCertificateVerifier(), + transport->getSession()->getTLSProperties()); + + shared_ptr tlsSocket = + tlsSession->getSocket(m_socket); + + m_socket = tlsSocket; + + m_secured = true; + m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); + } + else +#endif // VMIME_HAVE_TLS_SUPPORT + { + m_cntInfos = make_shared (address, port); + } + + m_socket->connect(address, port); + + // Connection + // + // eg: C: + // --- S: 220 smtp.domain.com Service ready + + shared_ptr 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 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); + + string ext; + iss >> ext; + + std::vector 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 * params) const +{ + std::map >::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 + // First, try SASL authentication + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) + { + try + { + authenticateSASL(); + + m_authenticated = true; + return; + } + catch (exceptions::authentication_error& e) + { + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) + { + // Can't fallback on normal authentication + internalDisconnect(); + throw e; + } + else + { + // Ignore, will try normal authentication + } + } + catch (exception& e) + { + internalDisconnect(); + throw e; + } + } +#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 (getAuthenticator())) + throw exceptions::authentication_error("No SASL authenticator available."); + + // Obtain SASL mechanisms supported by server from ESMTP extensions + std::vector saslMechs; + hasExtension("AUTH", &saslMechs); + + if (saslMechs.empty()) + throw exceptions::authentication_error("No SASL mechanism available."); + + std::vector > mechList; + + shared_ptr saslContext = + make_shared (); + + 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 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 (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 mech = mechList[i]; + + shared_ptr saslSession = + saslContext->createSession("smtp", getAuthenticator(), mech); + + saslSession->init(); + + sendRequest(SMTPCommand::AUTH(mech->getName())); + + for (bool cont = true ; cont ; ) + { + shared_ptr 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 + m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n"); + } + 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"); + } + 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 resp = readResponse(); + + if (resp->getCode() != 220) + { + throw SMTPCommandError("STARTTLS", resp->getText(), + resp->getCode(), resp->getEnhancedCode()); + } + + shared_ptr tlsSession = tls::TLSSession::create + (getTransport()->getCertificateVerifier(), + getTransport()->getSession()->getTLSProperties()); + + shared_ptr tlsSocket = + tlsSession->getSocket(m_socket); + + tlsSocket->handshake(m_timeoutHandler); + + m_socket = tlsSocket; + + m_secured = true; + m_cntInfos = make_shared + (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() +{ + try + { + sendRequest(SMTPCommand::QUIT()); + readResponse(); + } + 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(shared_ptr cmd) +{ + cmd->writeToSocket(m_socket); +} + + +shared_ptr SMTPConnection::readResponse() +{ + shared_ptr resp = SMTPResponse::readResponse + (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 SMTPConnection::getConnectionInfos() const +{ + return m_cntInfos; +} + + +shared_ptr SMTPConnection::getTransport() +{ + return m_transport.lock(); +} + + +shared_ptr SMTPConnection::getSession() +{ + return m_transport.lock()->getSession(); +} + + +shared_ptr SMTPConnection::getSocket() +{ + return m_socket; +} + + +shared_ptr SMTPConnection::getTimeoutHandler() +{ + return m_timeoutHandler; +} + + +shared_ptr SMTPConnection::getAuthenticator() +{ + return m_auth; +} + + +} // smtp +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/vmime/net/smtp/SMTPConnection.hpp b/src/vmime/net/smtp/SMTPConnection.hpp new file mode 100644 index 00000000..cc59ef34 --- /dev/null +++ b/src/vmime/net/smtp/SMTPConnection.hpp @@ -0,0 +1,129 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/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(shared_ptr transport, shared_ptr auth); + virtual ~SMTPConnection(); + + + virtual void connect(); + virtual bool isConnected() const; + virtual void disconnect(); + + bool isSecuredConnection() const; + shared_ptr getConnectionInfos() const; + + virtual shared_ptr getTransport(); + virtual shared_ptr getSocket(); + virtual shared_ptr getTimeoutHandler(); + virtual shared_ptr getAuthenticator(); + virtual shared_ptr getSession(); + + void sendRequest(shared_ptr cmd); + shared_ptr readResponse(); + + bool hasExtension(const std::string& extName, std::vector * 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 m_transport; + + shared_ptr m_auth; + shared_ptr m_socket; + shared_ptr m_timeoutHandler; + + SMTPResponse::state m_responseState; + + bool m_authenticated; + bool m_secured; + + shared_ptr m_cntInfos; + + bool m_extendedSMTP; + std::map > 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/src/vmime/net/smtp/SMTPExceptions.cpp b/src/vmime/net/smtp/SMTPExceptions.cpp new file mode 100644 index 00000000..0c3112c0 --- /dev/null +++ b/src/vmime/net/smtp/SMTPExceptions.cpp @@ -0,0 +1,151 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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"; +} + + +} // smtp +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/vmime/net/smtp/SMTPExceptions.hpp b/src/vmime/net/smtp/SMTPExceptions.hpp new file mode 100644 index 00000000..75842042 --- /dev/null +++ b/src/vmime/net/smtp/SMTPExceptions.hpp @@ -0,0 +1,127 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP + +#endif // VMIME_NET_SMTP_SMTPEXCEPTIONS_HPP_INCLUDED + diff --git a/src/vmime/net/smtp/SMTPResponse.cpp b/src/vmime/net/smtp/SMTPResponse.cpp new file mode 100644 index 00000000..f7980351 --- /dev/null +++ b/src/vmime/net/smtp/SMTPResponse.cpp @@ -0,0 +1,334 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace net { +namespace smtp { + + +SMTPResponse::SMTPResponse(shared_ptr sok, shared_ptr toh, const state& st) + : m_socket(sok), m_timeoutHandler(toh), + 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::readResponse + (shared_ptr sok, shared_ptr toh, const state& st) +{ + shared_ptr resp = shared_ptr (new SMTPResponse(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; + + 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 + { + platform::getHandler()->wait(); + 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); + + 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/src/vmime/net/smtp/SMTPResponse.hpp b/src/vmime/net/smtp/SMTPResponse.hpp new file mode 100644 index 00000000..000448ac --- /dev/null +++ b/src/vmime/net/smtp/SMTPResponse.hpp @@ -0,0 +1,186 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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; + + +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 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 readResponse(shared_ptr sok, shared_ptr 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(shared_ptr sok, shared_ptr 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 m_lines; + + shared_ptr m_socket; + shared_ptr m_timeoutHandler; + + 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/src/vmime/net/smtp/SMTPSTransport.cpp b/src/vmime/net/smtp/SMTPSTransport.cpp new file mode 100644 index 00000000..ab64d49d --- /dev/null +++ b/src/vmime/net/smtp/SMTPSTransport.cpp @@ -0,0 +1,79 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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/src/vmime/net/smtp/SMTPSTransport.hpp b/src/vmime/net/smtp/SMTPSTransport.hpp new file mode 100644 index 00000000..7782f711 --- /dev/null +++ b/src/vmime/net/smtp/SMTPSTransport.hpp @@ -0,0 +1,71 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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/src/vmime/net/smtp/SMTPServiceInfos.cpp b/src/vmime/net/smtp/SMTPServiceInfos.cpp new file mode 100644 index 00000000..532bb8b8 --- /dev/null +++ b/src/vmime/net/smtp/SMTPServiceInfos.cpp @@ -0,0 +1,146 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 SMTPServiceInfos::getAvailableProperties() const +{ + std::vector 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/src/vmime/net/smtp/SMTPServiceInfos.hpp b/src/vmime/net/smtp/SMTPServiceInfos.hpp new file mode 100644 index 00000000..f783194d --- /dev/null +++ b/src/vmime/net/smtp/SMTPServiceInfos.hpp @@ -0,0 +1,95 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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/src/vmime/net/smtp/SMTPTransport.cpp b/src/vmime/net/smtp/SMTPTransport.cpp new file mode 100644 index 00000000..0020d010 --- /dev/null +++ b/src/vmime/net/smtp/SMTPTransport.cpp @@ -0,0 +1,420 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr auth, const bool secured) + : transport(sess, getInfosInstance(), auth), m_isSMTPS(secured), m_needReset(false) +{ +} + + +SMTPTransport::~SMTPTransport() +{ + try + { + if (isConnected()) + disconnect(); + } + catch (vmime::exception&) + { + // Ignore + } +} + + +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 + (dynamicCast (shared_from_this()), getAuthenticator()); + + try + { + m_connection->connect(); + } + catch (std::exception&) + { + m_connection = null; + throw; + } +} + + +bool SMTPTransport::isConnected() const +{ + return m_connection && m_connection->isConnected(); +} + + +bool SMTPTransport::isSecuredConnection() const +{ + if (m_connection == NULL) + return false; + + return m_connection->isSecuredConnection(); +} + + +shared_ptr SMTPTransport::getConnectionInfos() const +{ + if (m_connection == NULL) + return null; + + return m_connection->getConnectionInfos(); +} + + +shared_ptr 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 resp = m_connection->readResponse(); + + if (resp->getCode() != 250) + { + throw SMTPCommandError + ("NOOP", resp->getText(), resp->getCode(), resp->getEnhancedCode()); + } +} + + +void SMTPTransport::sendEnvelope + (const mailbox& expeditor, const mailboxList& recipients, + const mailbox& sender, bool sendDATACommand, + const size_t size) +{ + // If no recipient/expeditor was found, throw an exception + if (recipients.isEmpty()) + throw exceptions::no_recipient(); + else if (expeditor.isEmpty()) + throw exceptions::no_expeditor(); + + + const bool needReset = m_needReset; + const bool hasPipelining = m_connection->hasExtension("PIPELINING") && + getInfos().getPropertyValue (getSession(), + dynamic_cast (getInfos()).getProperties().PROPERTY_OPTIONS_PIPELINING); + + shared_ptr resp; + shared_ptr commands = SMTPCommandSet::create(hasPipelining); + + // Emit a "RSET" command if we previously sent a message on this connection + if (needReset) + commands->addCommand(SMTPCommand::RSET()); + + // Emit the "MAIL" command + const bool hasSMTPUTF8 = m_connection->hasExtension("SMTPUTF8"); + const bool hasSize = m_connection->hasExtension("SIZE"); + + if (!sender.isEmpty()) + commands->addCommand(SMTPCommand::MAIL(sender, hasSMTPUTF8, hasSize ? size : 0)); + else + commands->addCommand(SMTPCommand::MAIL(expeditor, hasSMTPUTF8, hasSize ? size : 0)); + + // 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)); + } + + // Prepare sending of message data + if (sendDATACommand) + commands->addCommand(SMTPCommand::DATA()); + + // Read response for "RSET" command + if (needReset) + { + commands->writeToSocket(m_connection->getSocket()); + + if ((resp = m_connection->readResponse())->getCode() != 250) + { + disconnect(); + + throw SMTPCommandError + (commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode()); + } + } + + // Read response for "MAIL" command + commands->writeToSocket(m_connection->getSocket()); + + if ((resp = m_connection->readResponse())->getCode() != 250) + { + // SIZE extension: insufficient system storage + if (resp->getCode() == 452) + { + disconnect(); + + 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) + { + disconnect(); + + throw SMTPMessageSizeExceedsMaxLimitsException + (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode())); + } + // Other error + else + { + disconnect(); + + 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()); + + resp = m_connection->readResponse(); + + if (resp->getCode() != 250 && + resp->getCode() != 251) + { + // SIZE extension: insufficient system storage + if (resp->getCode() == 452) + { + disconnect(); + + 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) + { + disconnect(); + + throw SMTPMessageSizeExceedsMaxLimitsException + (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode())); + } + // Other error + else + { + disconnect(); + + throw SMTPCommandError + (commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode()); + } + } + } + + // Read response for "DATA" command + if (sendDATACommand) + { + commands->writeToSocket(m_connection->getSocket()); + + if ((resp = m_connection->readResponse())->getCode() != 354) + { + disconnect(); + + 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) +{ + if (!isConnected()) + throw exceptions::not_connected(); + + // Send message envelope + sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ true, size); + + // 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"); + + shared_ptr resp; + + if ((resp = m_connection->readResponse())->getCode() != 250) + { + disconnect(); + + throw SMTPCommandError + ("DATA", resp->getText(), resp->getCode(), resp->getEnhancedCode()); + } +} + + +void SMTPTransport::send + (shared_ptr msg, const mailbox& expeditor, const mailboxList& recipients, + utility::progressListener* progress, const mailbox& sender) +{ + 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 (getSession(), + dynamic_cast (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); + return; + } + + // Send message envelope + sendEnvelope(expeditor, recipients, sender, + /* sendDATACommand */ false, msg->getGeneratedSize(ctx)); + + // Send the message by chunks + SMTPChunkingOutputStreamAdapter chunkStream(m_connection); + + 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/src/vmime/net/smtp/SMTPTransport.hpp b/src/vmime/net/smtp/SMTPTransport.hpp new file mode 100644 index 00000000..a0f02418 --- /dev/null +++ b/src/vmime/net/smtp/SMTPTransport.hpp @@ -0,0 +1,131 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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()); + + void send + (shared_ptr msg, + const mailbox& expeditor, + const mailboxList& recipients, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox()); + + bool isSecuredConnection() const; + shared_ptr getConnectionInfos() const; + shared_ptr getConnection(); + + bool isSMTPS() const; + +private: + + /** 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) + */ + void sendEnvelope + (const mailbox& expeditor, + const mailboxList& recipients, + const mailbox& sender, + bool sendDATACommand, + const size_t size); + + + shared_ptr 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/src/vmime/net/smtp/smtp.hpp b/src/vmime/net/smtp/smtp.hpp new file mode 100644 index 00000000..2a9ee312 --- /dev/null +++ b/src/vmime/net/smtp/smtp.hpp @@ -0,0 +1,33 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/socket.hpp b/src/vmime/net/socket.hpp new file mode 100644 index 00000000..537c34bb --- /dev/null +++ b/src/vmime/net/socket.hpp @@ -0,0 +1,184 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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" + + +namespace vmime { +namespace net { + + +/** Interface for connecting to servers. + */ + +class VMIME_EXPORT socket : public object +{ +public: + + enum Status + { + STATUS_WOULDBLOCK = 0x1 /**< The receive operation would block. */ + }; + + + 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; + + /** 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; + +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 create() = 0; + + /** Creates a socket with the specified timeout handler. + * + * @param th timeout handler + * @return a new socket + */ + virtual shared_ptr create(shared_ptr th) = 0; +}; + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_NET_SOCKET_HPP_INCLUDED diff --git a/src/vmime/net/store.hpp b/src/vmime/net/store.hpp new file mode 100644 index 00000000..37dcadbc --- /dev/null +++ b/src/vmime/net/store.hpp @@ -0,0 +1,114 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, const serviceInfos& infos, shared_ptr auth) + : service(sess, infos, auth) { } + +public: + + /** Return the default folder. This is protocol dependent + * and usually is the INBOX folder. + * + * @return default folder + */ + virtual shared_ptr 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 getRootFolder() = 0; + + /** Return the folder specified by the path. + * + * @param path absolute folder path + * @return folder at the specified path + */ + virtual shared_ptr 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 { return (TYPE_STORE); } +}; + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_NET_STORE_HPP_INCLUDED diff --git a/src/vmime/net/timeoutHandler.hpp b/src/vmime/net/timeoutHandler.hpp new file mode 100644 index 00000000..24129701 --- /dev/null +++ b/src/vmime/net/timeoutHandler.hpp @@ -0,0 +1,89 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 time-out in messaging services. + */ + +class VMIME_EXPORT timeoutHandler : public object +{ +public: + + virtual ~timeoutHandler() { } + + /** Called to test if the time limit has been reached. + * + * @return true if the time-out delay is elapsed + */ + virtual bool isTimeOut() = 0; + + /** Called to reset the time-out counter. + */ + virtual void resetTimeOut() = 0; + + /** Called when the time limit has been reached (when + * isTimeOut() returned true). + * + * @return true to continue (and reset the time-out) + * 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 create() = 0; +}; + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_NET_TIMEOUTHANDLER_HPP_INCLUDED diff --git a/src/vmime/net/tls/TLSProperties.cpp b/src/vmime/net/tls/TLSProperties.cpp new file mode 100644 index 00000000..1986db79 --- /dev/null +++ b/src/vmime/net/tls/TLSProperties.cpp @@ -0,0 +1,44 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/tls/TLSProperties.hpp b/src/vmime/net/tls/TLSProperties.hpp new file mode 100644 index 00000000..0dbc8f05 --- /dev/null +++ b/src/vmime/net/tls/TLSProperties.hpp @@ -0,0 +1,105 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 m_data; +}; + + +} // tls +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + +#endif // VMIME_NET_TLS_TLSPROPERTIES_HPP_INCLUDED diff --git a/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp b/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp new file mode 100644 index 00000000..4856e9af --- /dev/null +++ b/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp @@ -0,0 +1,72 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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, + shared_ptr tlsSession, shared_ptr 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 TLSSecuredConnectionInfos::getPeerCertificates() const +{ + return m_tlsSocket->getPeerCertificates(); +} + + +} // tls +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + diff --git a/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp b/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp new file mode 100644 index 00000000..e552d6f9 --- /dev/null +++ b/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp @@ -0,0 +1,84 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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, + shared_ptr tlsSession, shared_ptr 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 getPeerCertificates() const; + +private: + + string m_host; + port_t m_port; + + shared_ptr m_tlsSession; + shared_ptr m_tlsSocket; +}; + + +} // tls +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + +#endif // VMIME_NET_TLSSECUREDCONNECTIONINFOS_HPP_INCLUDED + diff --git a/src/vmime/net/tls/TLSSession.cpp b/src/vmime/net/tls/TLSSession.cpp new file mode 100644 index 00000000..a46f07ca --- /dev/null +++ b/src/vmime/net/tls/TLSSession.cpp @@ -0,0 +1,48 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/tls/TLSSession.hpp b/src/vmime/net/tls/TLSSession.hpp new file mode 100644 index 00000000..9e061f89 --- /dev/null +++ b/src/vmime/net/tls/TLSSession.hpp @@ -0,0 +1,93 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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: + + /** 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 create(shared_ptr cv, shared_ptr 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 getSocket(shared_ptr sok) = 0; + + /** Get the object responsible for verifying certificates when + * using secured connections (TLS/SSL). + */ + virtual shared_ptr 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/src/vmime/net/tls/TLSSocket.cpp b/src/vmime/net/tls/TLSSocket.cpp new file mode 100644 index 00000000..0419a571 --- /dev/null +++ b/src/vmime/net/tls/TLSSocket.cpp @@ -0,0 +1,44 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/tls/TLSSocket.hpp b/src/vmime/net/tls/TLSSocket.hpp new file mode 100644 index 00000000..e2668ad4 --- /dev/null +++ b/src/vmime/net/tls/TLSSocket.hpp @@ -0,0 +1,88 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 wrap(shared_ptr session, shared_ptr 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(shared_ptr toHandler = null) = 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 getPeerCertificates() const = 0; +}; + + +} // tls +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + +#endif // VMIME_NET_TLS_TLSSOCKET_HPP_INCLUDED diff --git a/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp b/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp new file mode 100644 index 00000000..36ab7d7a --- /dev/null +++ b/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp @@ -0,0 +1,113 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#if GNUTLS_VERSION_NUMBER < 0x030000 +#include +#endif + + +namespace vmime { +namespace net { +namespace tls { + + +TLSProperties::TLSProperties() + : m_data(make_shared ()) +{ + setCipherSuite(CIPHERSUITE_DEFAULT); +} + + +TLSProperties::TLSProperties(const TLSProperties& props) + : object(), + m_data(make_shared ()) +{ + *dynamicCast (m_data) = *dynamicCast (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 (m_data)->cipherSuite = cipherSuite; +} + + +const string TLSProperties::getCipherSuite() const +{ + return dynamicCast (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/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp b/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp new file mode 100644 index 00000000..2038778a --- /dev/null +++ b/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp @@ -0,0 +1,68 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp b/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp new file mode 100644 index 00000000..1c520ed1 --- /dev/null +++ b/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp @@ -0,0 +1,300 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#if GNUTLS_VERSION_NUMBER < 0x030000 +#include +#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 +# if VMIME_GNUTLS_NEEDS_GCRYPT +# include +# endif +# include +#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 +#include + +#if VMIME_DEBUG && GNUTLS_DEBUG + #include +#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 anonCred; + gnutls_certificate_credentials certCred; +}; + +static TLSGlobal g_gnutlsGlobal; + + +#endif // VMIME_BUILDING_DOC + + + +// static +shared_ptr TLSSession::create(shared_ptr cv, shared_ptr props) +{ + return make_shared (cv, props); +} + + +TLSSession_GnuTLS::TLSSession_GnuTLS(shared_ptr cv, shared_ptr props) + : m_certVerifier(cv), m_props(props) +{ + int res; + + m_gnutlsSession = new gnutls_session; + + 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() +{ + if (m_gnutlsSession) + { + gnutls_deinit(*m_gnutlsSession); + + delete m_gnutlsSession; + m_gnutlsSession = NULL; + } +} + + +shared_ptr TLSSession_GnuTLS::getSocket(shared_ptr sok) +{ + return TLSSocket::wrap(dynamicCast (shared_from_this()), sok); +} + + +shared_ptr 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/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp b/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp new file mode 100644 index 00000000..7f762b58 --- /dev/null +++ b/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp @@ -0,0 +1,91 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr cv, shared_ptr props); + ~TLSSession_GnuTLS(); + + + shared_ptr getSocket(shared_ptr sok); + + shared_ptr getCertificateVerifier(); + +private: + + TLSSession_GnuTLS(const TLSSession_GnuTLS&); + + static void throwTLSException(const string& fname, const int code); + + +#ifdef LIBGNUTLS_VERSION + gnutls_session* m_gnutlsSession; +#else + void* m_gnutlsSession; +#endif // LIBGNUTLS_VERSION + + shared_ptr m_certVerifier; + shared_ptr 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/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp new file mode 100644 index 00000000..5a90565b --- /dev/null +++ b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp @@ -0,0 +1,490 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + +#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 + + +namespace vmime { +namespace net { +namespace tls { + + +// static +shared_ptr TLSSocket::wrap(shared_ptr session, shared_ptr sok) +{ + return make_shared + (dynamicCast (session), sok); +} + + +TLSSocket_GnuTLS::TLSSocket_GnuTLS(shared_ptr session, shared_ptr sok) + : m_session(session), m_wrapped(sok), m_connected(false), + m_handshaking(false), m_ex(NULL), m_status(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); +} + + +TLSSocket_GnuTLS::~TLSSocket_GnuTLS() +{ + if (m_ex) + { + delete m_ex; + m_ex = NULL; + } + + try + { + disconnect(); + } + catch (...) + { + // Don't throw exception in destructor + } +} + + +void TLSSocket_GnuTLS::connect(const string& address, const port_t port) +{ + m_wrapped->connect(address, port); + + handshake(null); + + m_connected = true; +} + + +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(); +} + + +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 (buffer.data()), buffer.length()); +} + + +void TLSSocket_GnuTLS::send(const char* str) +{ + sendRaw(reinterpret_cast (str), ::strlen(str)); +} + + +size_t TLSSocket_GnuTLS::receiveRaw(byte_t* buffer, const size_t count) +{ + m_status &= ~STATUS_WOULDBLOCK; + + const ssize_t ret = gnutls_record_recv + (*m_session->m_gnutlsSession, + buffer, static_cast (count)); + + if (m_ex) + internalThrow(); + + if (ret < 0) + { + if (ret == GNUTLS_E_AGAIN) + { + m_status |= STATUS_WOULDBLOCK; + return 0; + } + + TLSSession_GnuTLS::throwTLSException("gnutls_record_recv", static_cast (ret)); + } + + return static_cast (ret); +} + + +void TLSSocket_GnuTLS::sendRaw(const byte_t* buffer, const size_t count) +{ + ssize_t ret = gnutls_record_send + (*m_session->m_gnutlsSession, + buffer, static_cast (count)); + + if (m_ex) + internalThrow(); + + if (ret < 0) + { + if (ret == GNUTLS_E_AGAIN) + { + m_status |= STATUS_WOULDBLOCK; + return; + } + + TLSSession_GnuTLS::throwTLSException("gnutls_record_send", static_cast (ret)); + } +} + + +size_t TLSSocket_GnuTLS::sendRawNonBlocking(const byte_t* buffer, const size_t count) +{ + ssize_t ret = gnutls_record_send + (*m_session->m_gnutlsSession, + buffer, static_cast (count)); + + if (m_ex) + internalThrow(); + + if (ret < 0) + { + if (ret == GNUTLS_E_AGAIN) + { + m_status |= STATUS_WOULDBLOCK; + return 0; + } + + TLSSession_GnuTLS::throwTLSException("gnutls_record_send", static_cast (ret)); + } + + return static_cast (ret); +} + + +unsigned int TLSSocket_GnuTLS::getStatus() const +{ + return m_status | m_wrapped->getStatus(); +} + + +void TLSSocket_GnuTLS::handshake(shared_ptr toHandler) +{ + if (toHandler) + toHandler->resetTimeOut(); + + // Start handshaking process + m_handshaking = true; + m_toHandler = toHandler; + + try + { + while (true) + { + const int ret = gnutls_handshake(*m_session->m_gnutlsSession); + + if (m_ex) + internalThrow(); + + if (ret < 0) + { + if (ret == GNUTLS_E_AGAIN || + ret == GNUTLS_E_INTERRUPTED) + { + // Non-fatal error + platform::getHandler()->wait(); + } + else + { + TLSSession_GnuTLS::throwTLSException("gnutls_handshake", ret); + } + } + else + { + // Successful handshake + break; + } + } + } + catch (...) + { + m_handshaking = false; + m_toHandler = null; + + throw; + } + + m_handshaking = false; + m_toHandler = null; + + // Verify server's certificate(s) + shared_ptr certs = getPeerCertificates(); + + if (certs == NULL) + throw exceptions::tls_exception("No peer certificate."); + + m_session->getCertificateVerifier()->verify(certs, getPeerName()); + + m_connected = true; +} + + +ssize_t TLSSocket_GnuTLS::gnutlsPushFunc + (gnutls_transport_ptr trspt, const void* data, size_t len) +{ + TLSSocket_GnuTLS* sok = reinterpret_cast (trspt); + + try + { + sok->m_wrapped->sendRaw + (reinterpret_cast (data), len); + } + catch (exception& e) + { + // Workaround for bad behaviour when throwing C++ exceptions + // from C functions (GNU TLS) + sok->m_ex = e.clone(); + return -1; + } + + return len; +} + + +ssize_t TLSSocket_GnuTLS::gnutlsPullFunc + (gnutls_transport_ptr trspt, void* data, size_t len) +{ + TLSSocket_GnuTLS* sok = reinterpret_cast (trspt); + + try + { + // Workaround for cross-platform asynchronous handshaking: + // gnutls_handshake() only returns GNUTLS_E_AGAIN if recv() + // returns -1 and errno is set to EGAIN... + if (sok->m_handshaking) + { + while (true) + { + const ssize_t ret = static_cast + (sok->m_wrapped->receiveRaw + (reinterpret_cast (data), len)); + + if (ret == 0) + { + // No data available yet + platform::getHandler()->wait(); + } + else + { + return ret; + } + + // Check whether the time-out delay is elapsed + if (sok->m_toHandler && sok->m_toHandler->isTimeOut()) + { + if (!sok->m_toHandler->handleTimeOut()) + throw exceptions::operation_timed_out(); + + sok->m_toHandler->resetTimeOut(); + } + } + } + else + { + const ssize_t n = static_cast + (sok->m_wrapped->receiveRaw + (reinterpret_cast (data), len)); + + if (n == 0 && sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) + return GNUTLS_E_AGAIN; + + return n; + } + } + catch (exception& e) + { + // Workaround for bad behaviour when throwing C++ exceptions + // from C functions (GNU TLS) + sok->m_ex = e.clone(); + return -1; + } +} + + +shared_ptr TLSSocket_GnuTLS::getPeerCertificates() const +{ + unsigned int certCount = 0; + const gnutls_datum* rawData = gnutls_certificate_get_peers + (*m_session->m_gnutlsSession, &certCount); + + if (rawData == NULL) + return null; + + // Try X.509 + gnutls_x509_crt* x509Certs = new gnutls_x509_crt[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) + { + // XXX more fine-grained error reporting? + delete [] x509Certs; + return null; + } + } + + { + std::vector > 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 data(dataSize); + + gnutls_x509_crt_export(x509Certs[i], + GNUTLS_X509_FMT_DER, &data[0], &dataSize); + + shared_ptr 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 (certs); + } + + delete [] x509Certs; + + return null; +} + + +// 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. + +#ifndef VMIME_BUILDING_DOC + +class TLSSocket_DeleteExWrapper : public object +{ +public: + + TLSSocket_DeleteExWrapper(exception* ex) : m_ex(ex) { } + ~TLSSocket_DeleteExWrapper() { delete m_ex; } + +private: + + exception* m_ex; +}; + +#endif // VMIME_BUILDING_DOC + + +void TLSSocket_GnuTLS::internalThrow() +{ + static std::vector > exToDelete; + + if (m_ex) + { + // Reset the current exception pointer to prevent the same + // exception from being thrown again later + exception* ex = m_ex; + m_ex = NULL; + + // To avoid memory leaks + exToDelete.push_back(make_shared (ex)); + + throw *ex; + } +} + + +} // tls +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS diff --git a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp new file mode 100644 index 00000000..885fac13 --- /dev/null +++ b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp @@ -0,0 +1,120 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr session, shared_ptr sok); + ~TLSSocket_GnuTLS(); + + + void handshake(shared_ptr toHandler = null); + + shared_ptr getPeerCertificates() const; + + // Implementation of 'socket' + void connect(const string& address, const port_t port); + void disconnect(); + bool isConnected() const; + + 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; + +private: + + void internalThrow(); + +#ifdef LIBGNUTLS_VERSION + static ssize_t gnutlsPushFunc(gnutls_transport_ptr trspt, const void* data, size_t len); + static ssize_t gnutlsPullFunc(gnutls_transport_ptr trspt, void* data, size_t len); +#else + static int gnutlsPushFunc(void* trspt, const void* data, size_t len); + static int gnutlsPullFunc(void* trspt, void* data, size_t len); +#endif // LIBGNUTLS_VERSION + + + shared_ptr m_session; + shared_ptr m_wrapped; + + bool m_connected; + + byte_t m_buffer[65536]; + + bool m_handshaking; + shared_ptr m_toHandler; + + exception* m_ex; + + unsigned int m_status; +}; + + +} // 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/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp b/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp new file mode 100644 index 00000000..1bbb9ee5 --- /dev/null +++ b/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp @@ -0,0 +1,142 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/utility/sync/autoLock.hpp" +#include "vmime/utility/sync/criticalSection.hpp" + +#include "vmime/platform.hpp" + +#include +#include +#include +#include + +#if OPENSSL_VERSION_NUMBER >= 0x0907000L +# include +#endif + + +namespace vmime { +namespace net { +namespace tls { + + +shared_ptr * OpenSSLInitializer::sm_mutexes; + + +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_config(NULL); +#endif + + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + + unsigned char seed[SEEDSIZE]; + vmime::platform::getHandler()->generateRandomBytes(seed, SEEDSIZE); + RAND_seed(seed, SEEDSIZE); + + int numMutexes = CRYPTO_num_locks(); + sm_mutexes = new shared_ptr [numMutexes]; + + for (int i = 0 ; i < numMutexes ; ++i) + sm_mutexes[i] = vmime::platform::getHandler()->createCriticalSection(); + + CRYPTO_set_locking_callback(&OpenSSLInitializer::lock); + CRYPTO_set_id_callback(&OpenSSLInitializer::id); +} + + +// static +void OpenSSLInitializer::uninitialize() +{ + EVP_cleanup(); + ERR_free_strings(); + + CRYPTO_set_locking_callback(NULL); + CRYPTO_set_id_callback(NULL); + + delete [] sm_mutexes; +} + + +// static +void OpenSSLInitializer::lock(int mode, int n, const char* /* file */, int /* line */) +{ + if (mode & CRYPTO_LOCK) + sm_mutexes[n]->lock(); + else + sm_mutexes[n]->unlock(); +} + + +// static +unsigned long OpenSSLInitializer::id() +{ + return vmime::platform::getHandler()->getThreadId(); +} + + +} // tls +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL + diff --git a/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp b/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp new file mode 100644 index 00000000..d7595aa8 --- /dev/null +++ b/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp @@ -0,0 +1,111 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +#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 + */ + class autoInitializer + { + public: + + autoInitializer(); + ~autoInitializer(); + }; + +protected: + + class oneTimeInitializer + { + public: + + oneTimeInitializer(); + ~oneTimeInitializer(); + }; + + + /** Initializes the OpenSSL lib + */ + static void initialize(); + + /** Shutdown the OpenSSL lib + */ + static void uninitialize(); + + + static shared_ptr getMutex(); + + enum + { + SEEDSIZE = 256 + }; + + + // OpenSSL multithreading support + static void lock(int mode, int n, const char* file, int line); + static unsigned long id(); + +private: + + static shared_ptr * sm_mutexes; +}; + + +} // 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/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp b/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp new file mode 100644 index 00000000..932477df --- /dev/null +++ b/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp @@ -0,0 +1,112 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + + +namespace vmime { +namespace net { +namespace tls { + + +TLSProperties::TLSProperties() + : m_data(make_shared ()) +{ + setCipherSuite(CIPHERSUITE_DEFAULT); +} + + +TLSProperties::TLSProperties(const TLSProperties& props) + : object(), + m_data(make_shared ()) +{ + *dynamicCast (m_data) = *dynamicCast (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 (m_data)->cipherSuite = cipherSuite; +} + + +const string TLSProperties::getCipherSuite() const +{ + return dynamicCast (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/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp b/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp new file mode 100644 index 00000000..5d2f075a --- /dev/null +++ b/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp @@ -0,0 +1,68 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp new file mode 100644 index 00000000..cf600a63 --- /dev/null +++ b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp @@ -0,0 +1,135 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/exception.hpp" + +#include +#include + + +namespace vmime { +namespace net { +namespace tls { + + +static OpenSSLInitializer::autoInitializer openSSLInitializer; + + +// static +shared_ptr TLSSession::create(shared_ptr cv, shared_ptr props) +{ + return make_shared (cv, props); +} + + +TLSSession_OpenSSL::TLSSession_OpenSSL(shared_ptr cv, shared_ptr 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 TLSSession_OpenSSL::getSocket(shared_ptr sok) +{ + return TLSSocket::wrap(dynamicCast (shared_from_this()), sok); +} + + +shared_ptr TLSSession_OpenSSL::getCertificateVerifier() +{ + return m_certVerifier; +} + + +void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile) +{ + 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 exceptions::certificate_exception(oss.str()); + } +} + + +void TLSSession_OpenSSL::useCertificateChainFile(const vmime::string& chainFile) +{ + 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 exceptions::certificate_exception(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/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp new file mode 100644 index 00000000..5a2b60a8 --- /dev/null +++ b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp @@ -0,0 +1,108 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace net { +namespace tls { + + +class TLSSession_OpenSSL : public TLSSession +{ + friend class TLSSocket_OpenSSL; + +public: + + TLSSession_OpenSSL(const shared_ptr cv, shared_ptr props); + ~TLSSession_OpenSSL(); + + + shared_ptr getSocket(shared_ptr sok); + + shared_ptr getCertificateVerifier(); + + + /** Set the private key to use if server requires a client certificate. + * + * @param keyfile Path to the private key in PEM format + * @param passwd_callback If the private key is stored encrypted the + */ + 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 m_certVerifier; + shared_ptr 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/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp new file mode 100644 index 00000000..ef6647d6 --- /dev/null +++ b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp @@ -0,0 +1,601 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + +#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 +#include + + +namespace vmime { +namespace net { +namespace tls { + + +static OpenSSLInitializer::autoInitializer openSSLInitializer; + + +// 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 +}; + + +// static +shared_ptr TLSSocket::wrap(shared_ptr session, shared_ptr sok) +{ + return make_shared + (dynamicCast (session), sok); +} + + +TLSSocket_OpenSSL::TLSSocket_OpenSSL(shared_ptr session, shared_ptr sok) + : m_session(session), m_wrapped(sok), m_connected(false), m_ssl(0), m_status(0), m_ex(NULL) +{ +} + + +TLSSocket_OpenSSL::~TLSSocket_OpenSSL() +{ + try + { + disconnect(); + + if (m_ssl) + { + SSL_free(m_ssl); + m_ssl = 0; + } + } + catch (...) + { + // Don't throw in destructor + } +} + + +void TLSSocket_OpenSSL::createSSLHandle() +{ + if (m_wrapped->isConnected()) + { + BIO* sockBio = BIO_new(&sm_customBIOMethod); + sockBio->ptr = this; + sockBio->init = 1; + + 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_connect_state(m_ssl); + } + else + { + throw exceptions::tls_exception("Unconnected socket error"); + } +} + + +void TLSSocket_OpenSSL::connect(const string& address, const port_t port) +{ + m_wrapped->connect(address, port); + + createSSLHandle(); + + handshake(null); + + m_connected = true; +} + + +void TLSSocket_OpenSSL::disconnect() +{ + if (m_connected) + { + 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); + } + + m_wrapped->disconnect(); + m_connected = false; + } +} + + +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(); +} + + +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 (buffer.data()), buffer.length()); +} + + +void TLSSocket_OpenSSL::send(const char* str) +{ + sendRaw(reinterpret_cast (str), ::strlen(str)); +} + + +size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) +{ + m_status &= ~STATUS_WOULDBLOCK; + + int rc = SSL_read(m_ssl, buffer, static_cast (count)); + + if (m_ex.get()) + internalThrow(); + + if (rc <= 0) + { + int error = SSL_get_error(m_ssl, rc); + + if (error == SSL_ERROR_WANT_WRITE || error == SSL_ERROR_WANT_READ) + { + m_status |= STATUS_WOULDBLOCK; + return 0; + } + + handleError(rc); + } + + return rc; +} + + +void TLSSocket_OpenSSL::sendRaw(const byte_t* buffer, const size_t count) +{ + sendRawNonBlocking(buffer, count); +} + + +size_t TLSSocket_OpenSSL::sendRawNonBlocking(const byte_t* buffer, const size_t count) +{ + m_status &= ~STATUS_WOULDBLOCK; + + int rc = SSL_write(m_ssl, buffer, static_cast (count)); + + if (m_ex.get()) + internalThrow(); + + if (rc <= 0) + { + int error = SSL_get_error(m_ssl, rc); + + if (error == SSL_ERROR_WANT_WRITE || error == SSL_ERROR_WANT_READ) + { + m_status |= STATUS_WOULDBLOCK; + return 0; + } + + handleError(rc); + } + + return rc; +} + + +void TLSSocket_OpenSSL::handshake(shared_ptr toHandler) +{ + if (toHandler) + toHandler->resetTimeOut(); + + // Start handshaking process + m_toHandler = toHandler; + + if (!m_ssl) + createSSLHandle(); + + try + { + int rc; + + while ((rc = SSL_do_handshake(m_ssl)) <= 0) + { + const int err = SSL_get_error(m_ssl, rc); + + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { + // No data available yet + platform::getHandler()->wait(); + } + else + { + handleError(rc); + } + + // Check whether the time-out delay is elapsed + if (m_toHandler && m_toHandler->isTimeOut()) + { + if (!m_toHandler->handleTimeOut()) + throw exceptions::operation_timed_out(); + + m_toHandler->resetTimeOut(); + } + } + } + catch (...) + { + SSL_free(m_ssl); + m_ssl = 0; + m_toHandler = null; + throw; + } + + m_toHandler = null; + + // Verify server's certificate(s) + shared_ptr certs = getPeerCertificates(); + + if (certs == NULL) + throw exceptions::tls_exception("No peer certificate."); + + m_session->getCertificateVerifier()->verify(certs, getPeerName()); + + m_connected = true; +} + + +shared_ptr TLSSocket_OpenSSL::getPeerCertificates() const +{ + 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 > certs; + + for (int i = 0; i < certCount && !error; i++) + { + shared_ptr 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 (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: + return; + + case SSL_ERROR_SYSCALL: + { + if (lastError == 0) + { + if (rc == 0) + { + throw exceptions::tls_exception("SSL connection unexpectedly closed"); + } + else + { + vmime::string msg; + std::ostringstream oss(msg); + 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 (bio->ptr); + + if (!bio->init || !sok) + return -1; + + try + { + const size_t n = sok->m_wrapped->sendRawNonBlocking + (reinterpret_cast (buf), len); + + if (n == 0 && sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) + { + BIO_set_retry_write(bio); + return -1; + } + + return static_cast (len); + } + 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 (bio->ptr); + + if (!bio->init || !sok) + return -1; + + try + { + const size_t n = sok->m_wrapped->receiveRaw + (reinterpret_cast (buf), len); + + if (n == 0 || sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) + { + BIO_set_retry_read(bio); + return -1; + } + + return static_cast (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 (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->shutdown; + break; + + case BIO_CTRL_SET_CLOSE: + + bio->shutdown = static_cast (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->init = 0; + bio->num = 0; + bio->ptr = NULL; + bio->flags = 0; + + return 1; +} + + +// static +int TLSSocket_OpenSSL::bio_destroy(BIO* bio) +{ + if (bio == NULL) + return 0; + + if (bio->shutdown) + { + bio->ptr = NULL; + bio->init = 0; + bio->flags = 0; + } + + return 1; +} + + +} // tls +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL diff --git a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp new file mode 100644 index 00000000..410fffcf --- /dev/null +++ b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp @@ -0,0 +1,132 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#include + + +namespace vmime { +namespace net { +namespace tls { + + +class TLSSession; +class TLSSession_OpenSSL; + + +class TLSSocket_OpenSSL : public TLSSocket +{ +public: + + TLSSocket_OpenSSL(shared_ptr session, shared_ptr sok); + ~TLSSocket_OpenSSL(); + + + void handshake(shared_ptr toHandler = null); + + shared_ptr getPeerCertificates() const; + + // Implementation of 'socket' + void connect(const string& address, const port_t port); + void disconnect(); + bool isConnected() const; + + 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; + +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 m_session; + + shared_ptr m_wrapped; + + bool m_connected; + + byte_t m_buffer[65536]; + + shared_ptr m_toHandler; + + SSL* m_ssl; + + unsigned long m_status; + + // Last exception thrown from C BIO functions + std::auto_ptr 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/src/vmime/net/transport.cpp b/src/vmime/net/transport.cpp new file mode 100644 index 00000000..dd7281d0 --- /dev/null +++ b/src/vmime/net/transport.cpp @@ -0,0 +1,236 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, const serviceInfos& infos, shared_ptr auth) + : service(sess, infos, auth) +{ +} + + +shared_ptr transport::processHeaderField(shared_ptr 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(shared_ptr
header) +{ + if (header->getFieldCount() == 0) + return; + + // Remove/replace fields + for (size_t idx = header->getFieldCount() ; idx != 0 ; --idx) + { + shared_ptr field = header->getFieldAt(idx - 1); + shared_ptr 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 mbox = dynamicCast (list.getAddressAt(i)->clone()); + + if (mbox != NULL) + recipients.appendMailbox(mbox); + } +} + + +void transport::send(shared_ptr msg, utility::progressListener* progress) +{ + // Extract expeditor + shared_ptr fromMbox = + msg->getHeader()->findFieldValue (fields::FROM); + + if (!fromMbox) + throw exceptions::no_expeditor(); + + mailbox expeditor = *fromMbox; + + // Extract sender + shared_ptr senderMbox = + msg->getHeader()->findFieldValue (fields::SENDER); + + mailbox sender; + + if (!senderMbox) + sender = expeditor; + else + sender = *senderMbox; + + // Extract recipients + mailboxList recipients; + + // -- "To" field + shared_ptr addresses = + msg->getHeader()->findFieldValue (fields::TO); + + if (addresses) + extractMailboxes(recipients, *addresses); + + // -- "Cc" field + addresses = + msg->getHeader()->findFieldValue (fields::CC); + + if (addresses) + extractMailboxes(recipients, *addresses); + + // -- "Bcc" field + addresses = + msg->getHeader()->findFieldValue (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
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(shared_ptr _msg, + shared_ptr _hdr) + : msg(_msg), hdr(msg->getHeader()) + { + // Set new header + msg->setHeader(_hdr); + } + + ~XChangeMsgHeader() + { + // Revert original header + msg->setHeader(hdr); + } + + private: + + shared_ptr msg; + shared_ptr hdr; + } headerExchanger(msg, hdr); + + send(msg, expeditor, recipients, progress, sender); +} + + +void transport::send + (shared_ptr msg, const mailbox& expeditor, const mailboxList& recipients, + utility::progressListener* progress, const mailbox& sender) +{ + // 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); +} + + +transport::Type transport::getType() const +{ + return (TYPE_TRANSPORT); +} + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + diff --git a/src/vmime/net/transport.hpp b/src/vmime/net/transport.hpp new file mode 100644 index 00000000..6c405cbb --- /dev/null +++ b/src/vmime/net/transport.hpp @@ -0,0 +1,137 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/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(shared_ptr sess, const serviceInfos& infos, shared_ptr 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 + */ + virtual void send(shared_ptr msg, utility::progressListener* progress = NULL); + + /** 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) + */ + virtual void send + (const mailbox& expeditor, + const mailboxList& recipients, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox()) = 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) + */ + virtual void send + (shared_ptr msg, + const mailbox& expeditor, + const mailboxList& recipients, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox()); + + + 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 processHeaderField(shared_ptr 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(shared_ptr
header); +}; + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_NET_TRANSPORT_HPP_INCLUDED diff --git a/src/vmime/object.cpp b/src/vmime/object.cpp new file mode 100644 index 00000000..d07c3c19 --- /dev/null +++ b/src/vmime/object.cpp @@ -0,0 +1,53 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/object.hpp b/src/vmime/object.hpp new file mode 100644 index 00000000..0b12df3c --- /dev/null +++ b/src/vmime/object.hpp @@ -0,0 +1,55 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 : public enable_shared_from_this +{ +protected: + + object(); + object(const object&); + + object& operator=(const object&); + + virtual ~object(); +}; + + +} // vmime + + +#endif // VMIME_OBJECT_HPP_INCLUDED + diff --git a/src/vmime/parameter.cpp b/src/vmime/parameter.cpp new file mode 100644 index 00000000..b8d5b36e --- /dev/null +++ b/src/vmime/parameter.cpp @@ -0,0 +1,603 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 ()) +{ +} + + +parameter::parameter(const string& name, const word& value) + : m_name(name), m_value(make_shared (value)) +{ +} + + +parameter::parameter(const string& name, const string& value) + : m_name(name), m_value(make_shared (value)) +{ +} + + +parameter::parameter(const parameter&) + : component() +{ +} + + +shared_ptr parameter::clone() const +{ + shared_ptr p = make_shared (m_name); + p->copyFrom(*this); + + return (p); +} + + +void parameter::copyFrom(const component& other) +{ + const parameter& param = dynamic_cast (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 & chunks) +{ + bool foundCharsetChunk = false; + + charset ch(charsets::US_ASCII); + + std::ostringstream value; + value.imbue(std::locale::classic()); + + for (std::vector ::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) + { + // Ignore language + ++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 (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); +} + + +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, + // also generate a normal "7bit/us-ascii" parameter + + // [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) + { + // 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 ; i < value.length() ; ++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; + } + else + { + extended = true; + } + } + + } // !needQuotedPrintable + + if (needQuoting) + { + sevenBitStream << '"'; + ++pos; + } + +#if VMIME_ALWAYS_GENERATE_7BIT_PARAMETER + os << sevenBitBuffer; +#endif // !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER + + // Also generate an extended parameter if the value contains 8-bit characters + // or is too long for a single line + if (extended || cutValue) + { + +#if VMIME_ALWAYS_GENERATE_7BIT_PARAMETER + + os << ';'; + ++pos; + +#else // !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER + + // The data output to 'sevenBitBuffer' will be discarded in this case + pos = curLinePos; + +#endif // VMIME_ALWAYS_GENERATE_7BIT_PARAMETER + + /* 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 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 (c) / 16; + const int h2 = static_cast (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; + } + } + } +#if !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER + else + { + // 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; + } +#endif // !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER + + if (newLinePos) + *newLinePos = pos; +} + + +const std::vector > parameter::getChildComponents() +{ + std::vector > list; + + list.push_back(m_value); + + return list; +} + + +} // vmime + diff --git a/src/vmime/parameter.hpp b/src/vmime/parameter.hpp new file mode 100644 index 00000000..682c391b --- /dev/null +++ b/src/vmime/parameter.hpp @@ -0,0 +1,153 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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: + + parameter(const string& name); + parameter(const string& name, const word& 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 clone() const; + void copyFrom(const component& other); + parameter& operator=(const parameter& other); + + const std::vector > 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: + * + *
+	  *    getParameter("creation-date")->getValueAs ()
+	  * 
+ * + * is equivalent to: + * + *
+	  *    shared_ptr  rawValue = getParameter("creation-date");
+	  *
+	  *    vmime::dateTime theDate;
+	  *    theDate.parse(rawValue->getBuffer());
+	  * 
+ * + * @param T type to which convert the value + * @return value + */ + template + 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 & chunks); + + + string m_name; + shared_ptr m_value; +}; + + +} // vmime + + +#endif // VMIME_PARAMETER_HPP_INCLUDED diff --git a/src/vmime/parameterizedHeaderField.cpp b/src/vmime/parameterizedHeaderField.cpp new file mode 100644 index 00000000..e2925d25 --- /dev/null +++ b/src/vmime/parameterizedHeaderField.cpp @@ -0,0 +1,580 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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* + + tspecials := "(" / ")" / "<" / ">" / "@" + / "," / ";" / ":" / "\" / <"> + / "/" / "[" / "]" / "?" / "=" + ; Must be in quoted-string, + ; to use within parameter values +*/ + + +#ifndef VMIME_BUILDING_DOC + +struct paramInfo +{ + bool extended; + std::vector 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 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 ::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 ::value_type(name, info)); + } + } + + // Skip white-spaces after this parameter + while (p < pend && parserHelpers::isSpace(*p)) ++p; + } + } + + for (std::map ::const_iterator it = params.begin() ; + it != params.end() ; ++it) + { + const paramInfo& info = (*it).second; + + // Append this parameter to the list + shared_ptr param = make_shared ((*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 >::const_iterator + it = m_params.begin() ; it != m_params.end() ; ++it) + { + os << "; "; + pos += 2; + + (*it)->generate(ctx, os, pos, &pos); + } + + if (newLinePos) + *newLinePos = pos; +} + + +void parameterizedHeaderField::copyFrom(const component& other) +{ + headerField::copyFrom(other); + + const parameterizedHeaderField& source = dynamic_cast(other); + + removeAllParameters(); + + for (std::vector >::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 >::const_iterator pos = m_params.begin(); + const std::vector >::const_iterator end = m_params.end(); + + for ( ; pos != end && utility::stringUtils::toLower((*pos)->getName()) != name ; ++pos) {} + + return (pos != end); +} + + +shared_ptr parameterizedHeaderField::findParameter(const string& paramName) const +{ + const string name = utility::stringUtils::toLower(paramName); + + // Find the first parameter that matches the specified name + std::vector >::const_iterator pos = m_params.begin(); + const std::vector >::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 parameterizedHeaderField::getParameter(const string& paramName) +{ + const string name = utility::stringUtils::toLower(paramName); + + // Find the first parameter that matches the specified name + std::vector >::const_iterator pos = m_params.begin(); + const std::vector >::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 param = make_shared (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(shared_ptr param) +{ + m_params.push_back(param); +} + + +void parameterizedHeaderField::insertParameterBefore(shared_ptr beforeParam, shared_ptr param) +{ + const std::vector >::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, shared_ptr param) +{ + if (pos >= m_params.size()) + throw std::out_of_range("Invalid position"); + + m_params.insert(m_params.begin() + pos, param); +} + + +void parameterizedHeaderField::insertParameterAfter(shared_ptr afterParam, shared_ptr param) +{ + const std::vector >::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, shared_ptr 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(shared_ptr param) +{ + const std::vector >::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 >::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 parameterizedHeaderField::getParameterAt(const size_t pos) +{ + return (m_params[pos]); +} + + +const shared_ptr parameterizedHeaderField::getParameterAt(const size_t pos) const +{ + return (m_params[pos]); +} + + +const std::vector > parameterizedHeaderField::getParameterList() const +{ + std::vector > list; + + list.reserve(m_params.size()); + + for (std::vector >::const_iterator it = m_params.begin() ; + it != m_params.end() ; ++it) + { + list.push_back(*it); + } + + return (list); +} + + +const std::vector > parameterizedHeaderField::getParameterList() +{ + return (m_params); +} + + +const std::vector > parameterizedHeaderField::getChildComponents() +{ + std::vector > list = headerField::getChildComponents(); + + for (std::vector >::iterator it = m_params.begin() ; + it != m_params.end() ; ++it) + { + list.push_back(*it); + } + + return (list); +} + + +} // vmime + diff --git a/src/vmime/parameterizedHeaderField.hpp b/src/vmime/parameterizedHeaderField.hpp new file mode 100644 index 00000000..509506a9 --- /dev/null +++ b/src/vmime/parameterizedHeaderField.hpp @@ -0,0 +1,208 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 : virtual 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 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 getParameter(const string& paramName); + + /** Add a parameter at the end of the list. + * + * @param param parameter to append + */ + void appendParameter(shared_ptr 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(shared_ptr beforeParam, shared_ptr 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, shared_ptr 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(shared_ptr afterParam, shared_ptr 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, shared_ptr 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(shared_ptr 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 getParameterAt(const size_t pos); + + /** Return the parameter at the specified position. + * + * @param pos position + * @return parameter at position 'pos' + */ + const shared_ptr getParameterAt(const size_t pos) const; + + /** Return the parameter list. + * + * @return list of parameters + */ + const std::vector > getParameterList() const; + + /** Return the parameter list. + * + * @return list of parameters + */ + const std::vector > getParameterList(); + + const std::vector > getChildComponents(); + +private: + + std::vector > 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/src/vmime/parsedMessageAttachment.cpp b/src/vmime/parsedMessageAttachment.cpp new file mode 100644 index 00000000..242bfde0 --- /dev/null +++ b/src/vmime/parsedMessageAttachment.cpp @@ -0,0 +1,116 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr 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 parsedMessageAttachment::getData() const +{ + if (m_data == NULL) + { + std::ostringstream oss; + utility::outputStreamAdapter os(oss); + + m_msg->generate(os); + + m_data = make_shared (oss.str()); + } + + return m_data; +} + + +const encoding parsedMessageAttachment::getEncoding() const +{ + return encoding(encodingTypes::EIGHT_BIT); // not important +} + + +shared_ptr parsedMessageAttachment::getPart() const +{ + return null; +} + + +shared_ptr parsedMessageAttachment::getHeader() const +{ + return null; +} + + +shared_ptr parsedMessageAttachment::getMessage() const +{ + return m_msg; +} + + +void parsedMessageAttachment::generateIn(shared_ptr parent) const +{ + // Create and append a new part for this attachment + shared_ptr part = make_shared (); + 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/src/vmime/parsedMessageAttachment.hpp b/src/vmime/parsedMessageAttachment.hpp new file mode 100644 index 00000000..6c96f80a --- /dev/null +++ b/src/vmime/parsedMessageAttachment.hpp @@ -0,0 +1,78 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr msg); + + const mediaType getType() const; + const text getDescription() const; + const word getName() const; + + const shared_ptr getData() const; + + const encoding getEncoding() const; + + shared_ptr getPart() const; + + shared_ptr getHeader() const; + + shared_ptr getMessage() const; + +protected: + + void generateIn(shared_ptr parent) const; + +private: + + shared_ptr m_msg; + mutable shared_ptr m_data; +}; + + +} // vmime + + +#endif // !VMIME_BUILDING_DOC + + +#endif // VMIME_PARSEDMESSAGEATTACHMENT_HPP_INCLUDED + diff --git a/src/vmime/parserHelpers.hpp b/src/vmime/parserHelpers.hpp new file mode 100644 index 00000000..ce3f422a --- /dev/null +++ b/src/vmime/parserHelpers.hpp @@ -0,0 +1,96 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + + +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 (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 (c); + return (x >= 0x20 && x <= 0x7E); + } +}; + + +} // vmime + + +#endif // VMIME_PARSERHELPERS_HPP_INCLUDED diff --git a/src/vmime/parsingContext.cpp b/src/vmime/parsingContext.cpp new file mode 100644 index 00000000..527f4705 --- /dev/null +++ b/src/vmime/parsingContext.cpp @@ -0,0 +1,49 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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() +{ +} + + +parsingContext::parsingContext(const parsingContext& ctx) + : context(ctx) +{ +} + + +parsingContext& parsingContext::getDefaultContext() +{ + static parsingContext ctx; + return ctx; +} + + +} // vmime diff --git a/src/vmime/parsingContext.hpp b/src/vmime/parsingContext.hpp new file mode 100644 index 00000000..27d14a60 --- /dev/null +++ b/src/vmime/parsingContext.hpp @@ -0,0 +1,59 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +{ + + +/** 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(); + +protected: + +}; + + +} // vmime + + +#endif // VMIME_PARSINGCONTEXT_HPP_INCLUDED diff --git a/src/vmime/path.cpp b/src/vmime/path.cpp new file mode 100644 index 00000000..3f1bc6af --- /dev/null +++ b/src/vmime/path.cpp @@ -0,0 +1,190 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 (other); + + m_localPart = p.m_localPart; + m_domain = p.m_domain; +} + + +shared_ptr path::clone() const +{ + return make_shared (*this); +} + + +path& path::operator=(const path& other) +{ + copyFrom(other); + return (*this); +} + + +const std::vector > path::getChildComponents() +{ + return std::vector >(); +} + + +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 != NULL) + *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/src/vmime/path.hpp b/src/vmime/path.hpp new file mode 100644 index 00000000..2ffa3c22 --- /dev/null +++ b/src/vmime/path.hpp @@ -0,0 +1,106 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + path& operator=(const path& other); + + const std::vector > 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/src/vmime/plainTextPart.cpp b/src/vmime/plainTextPart.cpp new file mode 100644 index 00000000..7a1542d7 --- /dev/null +++ b/src/vmime/plainTextPart.cpp @@ -0,0 +1,112 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 ()) +{ +} + + +plainTextPart::~plainTextPart() +{ +} + + +const mediaType plainTextPart::getType() const +{ + return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); +} + + +size_t plainTextPart::getPartCount() const +{ + return (1); +} + + +void plainTextPart::generateIn(shared_ptr /* message */, shared_ptr parent) const +{ + // Create a new part + shared_ptr part = make_shared (); + 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(shared_ptr /* message */, + shared_ptr /* parent */, shared_ptr textPart) +{ + m_text = vmime::clone(textPart->getBody()->getContents()); + + shared_ptr ctf = + textPart->getHeader()->findField (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 plainTextPart::getText() const +{ + return (m_text); +} + + +void plainTextPart::setText(shared_ptr text) +{ + m_text = vmime::clone(text); +} + + +} // vmime diff --git a/src/vmime/plainTextPart.hpp b/src/vmime/plainTextPart.hpp new file mode 100644 index 00000000..72a8a71c --- /dev/null +++ b/src/vmime/plainTextPart.hpp @@ -0,0 +1,68 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 getText() const; + void setText(shared_ptr text); + + size_t getPartCount() const; + + void generateIn(shared_ptr message, shared_ptr parent) const; + void parse(shared_ptr message, shared_ptr parent, shared_ptr textPart); + +private: + + shared_ptr m_text; + charset m_charset; +}; + + +} // vmime + + +#endif // VMIME_PLAINTEXTPART_HPP_INCLUDED diff --git a/src/vmime/platform.cpp b/src/vmime/platform.cpp new file mode 100644 index 00000000..631d5bcf --- /dev/null +++ b/src/vmime/platform.cpp @@ -0,0 +1,79 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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::sm_handler; + + +platform::handler::~handler() +{ +} + + +// static +shared_ptr platform::getDefaultHandler() +{ + +#if VMIME_PLATFORM_IS_WINDOWS + return make_shared (); +#elif VMIME_PLATFORM_IS_POSIX + return make_shared (); +#else + return null; +#endif + +} + + +// static +shared_ptr 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 defaultHandler = getDefaultHandler(); + + if (defaultHandler) + { + sm_handler = defaultHandler; + return sm_handler; + } + + // Oops... no platform handler! + throw exceptions::no_platform_handler(); +} + + +} // vmime diff --git a/src/vmime/platform.hpp b/src/vmime/platform.hpp new file mode 100644 index 00000000..c72f160e --- /dev/null +++ b/src/vmime/platform.hpp @@ -0,0 +1,170 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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; + + /** This function is called when VMime library is waiting for + * something (for example, it is called when there is no data + * available in a socket). On POSIX-compliant systems, a + * simple call to sched_yield() should suffice. + */ + virtual void wait() const = 0; + +#if VMIME_HAVE_MESSAGING_FEATURES + /** Return a pointer to the default socket factory for + * this platform. + * + * @return socket factory + */ + virtual shared_ptr 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 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 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 createCriticalSection() = 0; + }; + + + template + static void setHandler() + { + sm_handler = vmime::make_shared (); + } + + static shared_ptr getDefaultHandler(); + static shared_ptr getHandler(); + +private: + + static shared_ptr sm_handler; +}; + + +} // vmime + + +#endif // VMIME_PLATFORM_HPP_INCLUDED + diff --git a/src/vmime/platforms/posix/posixChildProcess.cpp b/src/vmime/platforms/posix/posixChildProcess.cpp new file mode 100644 index 00000000..54d4cd75 --- /dev/null +++ b/src/vmime/platforms/posix/posixChildProcess.cpp @@ -0,0 +1,404 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include +#include +#include +#include +#include + + +namespace vmime { +namespace platforms { +namespace posix { + + +// posixChildProcessFactory + +shared_ptr posixChildProcessFactory::create(const utility::file::path& path) const +{ + return make_shared (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 (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 (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 +// Copyright 2000 Ximian, Inc. (www.ximian.com) + +void posixChildProcess::start(const std::vector 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 (argv)); + _exit(255); + } + + if (flags & FLAG_REDIRECT_STDIN) + { + m_stdIn = make_shared (m_pipe[1]); + } + else + { + close(m_pipe[1]); + m_pipe[1] = 0; + } + + if (flags & FLAG_REDIRECT_STDOUT) + { + m_stdOut = make_shared (m_pipe[0]); + } + else + { + close(m_pipe[0]); + m_pipe[0] = 0; + } + + m_pid = pid; + m_started = true; +} + + +shared_ptr posixChildProcess::getStdIn() +{ + return (m_stdIn); +} + + +shared_ptr 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) + { + std::auto_ptr 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/src/vmime/platforms/posix/posixChildProcess.hpp b/src/vmime/platforms/posix/posixChildProcess.hpp new file mode 100644 index 00000000..5b9fa021 --- /dev/null +++ b/src/vmime/platforms/posix/posixChildProcess.hpp @@ -0,0 +1,92 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + + +namespace vmime { +namespace platforms { +namespace posix { + + +class posixChildProcess : public utility::childProcess +{ +public: + + posixChildProcess(const utility::file::path& path); + ~posixChildProcess(); + + void start(const std::vector args, const int flags = 0); + + shared_ptr getStdIn(); + shared_ptr getStdOut(); + + void waitForFinish(); + +private: + + utility::file::path m_processPath; + bool m_started; + + shared_ptr m_stdIn; + shared_ptr m_stdOut; + + sigset_t m_oldProcMask; + pid_t m_pid; + int m_pipe[2]; + + std::vector m_argVector; + const char** m_argArray; +}; + + +class posixChildProcessFactory : public utility::childProcessFactory +{ +public: + + shared_ptr 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/src/vmime/platforms/posix/posixCriticalSection.cpp b/src/vmime/platforms/posix/posixCriticalSection.cpp new file mode 100644 index 00000000..fb2c469c --- /dev/null +++ b/src/vmime/platforms/posix/posixCriticalSection.cpp @@ -0,0 +1,67 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/platforms/posix/posixCriticalSection.hpp b/src/vmime/platforms/posix/posixCriticalSection.hpp new file mode 100644 index 00000000..150799cd --- /dev/null +++ b/src/vmime/platforms/posix/posixCriticalSection.hpp @@ -0,0 +1,69 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + + +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/src/vmime/platforms/posix/posixFile.cpp b/src/vmime/platforms/posix/posixFile.cpp new file mode 100644 index 00000000..9387414d --- /dev/null +++ b/src/vmime/platforms/posix/posixFile.cpp @@ -0,0 +1,628 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include +#include + +#include +#include + +#include + +#include +#include + +#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 != NULL) + { + if (::closedir(m_dir) == -1) + posixFileSystemFactory::reportError(m_path, errno); + } +} + + +bool posixFileIterator::hasMoreElements() const +{ + return (m_dirEntry != NULL); +} + + +shared_ptr posixFileIterator::nextElement() +{ + shared_ptr file = make_shared + (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 (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 (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 (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 posixFileWriter::getOutputStream() +{ + int fd = 0; + + if ((fd = ::open(m_nativePath.c_str(), O_WRONLY, 0660)) == -1) + posixFileSystemFactory::reportError(m_path, errno); + + return make_shared (m_path, fd); +} + + + +// +// posixFileReader +// + +posixFileReader::posixFileReader(const vmime::utility::file::path& path, const vmime::string& nativePath) + : m_path(path), m_nativePath(nativePath) +{ +} + + +shared_ptr posixFileReader::getInputStream() +{ + int fd = 0; + + if ((fd = ::open(m_nativePath.c_str(), O_RDONLY, 0640)) == -1) + posixFileSystemFactory::reportError(m_path, errno); + + return make_shared (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 (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 posixFile::getParent() const +{ + if (m_path.isEmpty()) + return null; + else + return make_shared (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 posixFile::getFileWriter() +{ + return make_shared (m_path, m_nativePath); +} + + +shared_ptr posixFile::getFileReader() +{ + return make_shared (m_path, m_nativePath); +} + + +shared_ptr posixFile::getFiles() const +{ + if (!isDirectory()) + throw vmime::exceptions::not_a_directory(m_path); + + return make_shared (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 posixFileSystemFactory::create(const vmime::utility::file::path& path) const +{ + return make_shared (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::string(str.begin() + prev, str.begin() + offset)); + + prev = offset + 1; + offset++; + } + + if (prev < str.length()) + path.appendComponent(vmime::string(str.begin() + prev, str.end())); + + return (path); +} + + +const vmime::string posixFileSystemFactory::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 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 (int 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/src/vmime/platforms/posix/posixFile.hpp b/src/vmime/platforms/posix/posixFile.hpp new file mode 100644 index 00000000..20a56699 --- /dev/null +++ b/src/vmime/platforms/posix/posixFile.hpp @@ -0,0 +1,220 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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 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 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 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 getParent() const; + + void rename(const path& newName); + + void remove(); + + shared_ptr getFileWriter(); + shared_ptr getFileReader(); + + shared_ptr 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 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/src/vmime/platforms/posix/posixHandler.cpp b/src/vmime/platforms/posix/posixHandler.cpp new file mode 100644 index 00000000..7ab0341a --- /dev/null +++ b/src/vmime/platforms/posix/posixHandler.cpp @@ -0,0 +1,322 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include +#include +#include +#include +#include + +#include +#include + +#if VMIME_HAVE_SYSCALL +# include +#endif + +#include + +#include +#include +#include + +#if VMIME_HAVE_PTHREAD +# include +#endif // VMIME_HAVE_PTHREAD + +/* +#ifdef _POSIX_PRIORITY_SCHEDULING + #include +#endif // _POSIX_PRIORITY_SCHEDULING +*/ + + +#if VMIME_HAVE_PTHREAD + +namespace +{ + // This construction ensures mutex will be initialized in compile-time + // and will be available any time in the runtime. + pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; + + // Helper lock, to be exception safe all the time. + class PLockHelper + { + public: + + PLockHelper() + { + if (pthread_mutex_lock(&g_mutex) != 0) + assert(!"unable to lock mutex - thread safety's void"); + } + + ~PLockHelper() + { + if (pthread_mutex_unlock(&g_mutex) != 0) + assert(!"unable to unlock mutex - application's dead..."); + } + + private: + + // Object cannot be copied + PLockHelper(const PLockHelper&); + const PLockHelper& operator=(const PLockHelper&); + }; + +} // unnamed namespace + +#endif // VMIME_HAVE_PTHREAD + + +namespace vmime { +namespace platforms { +namespace posix { + + +posixHandler::posixHandler() +{ +#if VMIME_HAVE_MESSAGING_FEATURES + m_socketFactory = make_shared (); +#endif +#if VMIME_HAVE_FILESYSTEM_FEATURES + m_fileSysFactory = make_shared (); + m_childProcFactory = make_shared (); +#endif +} + + +posixHandler::~posixHandler() +{ +} + + +unsigned long posixHandler::getUnixTime() const +{ + return static_cast (::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 long 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, diff / 60); // minutes needed +} + + +const vmime::charset posixHandler::getLocalCharset() const +{ + const PLockHelper lock; + + const char* prevLocale = ::setlocale(LC_ALL, ""); + vmime::charset ch(::nl_langinfo(CODESET)); + ::setlocale(LC_ALL, prevLocale); + + return (ch); +} + + +static inline bool isFQDN(const vmime::string& str) +{ + if (utility::stringUtils::isStringEqualNoCase(str, "localhost", 9)) + return false; + + const vmime::size_t p = str.find_first_of("."); + return p != vmime::string::npos && p > 0 && p != str.length() - 1; +} + + +const vmime::string posixHandler::getHostName() const +{ + char hostname[256]; + + // Try with 'gethostname' + ::gethostname(hostname, sizeof(hostname)); + hostname[sizeof(hostname) - 1] = '\0'; + + // If this is a Fully-Qualified Domain Name (FQDN), return immediately + if (isFQDN(hostname)) + return hostname; + + if (::strlen(hostname) == 0) + ::strcpy(hostname, "localhost"); + + // Try to get canonical name for the hostname + 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) + { + for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) + { + if (isFQDN(p->ai_canonname)) + { + const string ret(p->ai_canonname); + freeaddrinfo(info); + return ret; + } + } + + freeaddrinfo(info); + } + + return hostname; +} + + +unsigned int posixHandler::getProcessId() const +{ + return (::getpid()); +} + + +unsigned int posixHandler::getThreadId() const +{ +#if VMIME_HAVE_GETTID + return static_cast (::gettid()); +#elif VMIME_HAVE_SYSCALL && VMIME_HAVE_SYSCALL_GETTID + return static_cast (::syscall(SYS_gettid)); +#else + #error We have no implementation of getThreadId() for this platform! +#endif +} + + +#if VMIME_HAVE_MESSAGING_FEATURES + +shared_ptr posixHandler::getSocketFactory() +{ + return m_socketFactory; +} + +#endif + + +#if VMIME_HAVE_FILESYSTEM_FEATURES + +shared_ptr posixHandler::getFileSystemFactory() +{ + return m_fileSysFactory; +} + + +shared_ptr posixHandler::getChildProcessFactory() +{ + return m_childProcFactory; +} + +#endif + + +void posixHandler::wait() const +{ +/* +#ifdef _POSIX_PRIORITY_SCHEDULING + ::sched_yield(); +#else + ::sleep(1); +#endif // _POSIX_PRIORITY_SCHEDULING +*/ + + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 500000; // 500 microseconds + + nanosleep(&ts, NULL); +} + + +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 (rand() % 255); + } +} + + +shared_ptr posixHandler::createCriticalSection() +{ + return make_shared (); +} + + +} // posix +} // platforms +} // vmime + + +#endif // VMIME_PLATFORM_IS_POSIX diff --git a/src/vmime/platforms/posix/posixHandler.hpp b/src/vmime/platforms/posix/posixHandler.hpp new file mode 100644 index 00000000..0bba372b --- /dev/null +++ b/src/vmime/platforms/posix/posixHandler.hpp @@ -0,0 +1,105 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 getSocketFactory(); +#endif + +#if VMIME_HAVE_FILESYSTEM_FEATURES + shared_ptr getFileSystemFactory(); + + shared_ptr getChildProcessFactory(); +#endif + + void wait() const; + + void generateRandomBytes(unsigned char* buffer, const unsigned int count); + + shared_ptr createCriticalSection(); + +private: + +#if VMIME_HAVE_MESSAGING_FEATURES + shared_ptr m_socketFactory; +#endif + +#if VMIME_HAVE_FILESYSTEM_FEATURES + shared_ptr m_fileSysFactory; + shared_ptr m_childProcFactory; +#endif +}; + + +} // posix +} // platforms +} // vmime + + +#endif // VMIME_PLATFORM_IS_POSIX + +#endif // VMIME_PLATFORMS_POSIX_HANDLER_HPP_INCLUDED diff --git a/src/vmime/platforms/posix/posixSocket.cpp b/src/vmime/platforms/posix/posixSocket.cpp new file mode 100644 index 00000000..ab434116 --- /dev/null +++ b/src/vmime/platforms/posix/posixSocket.cpp @@ -0,0 +1,680 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + + +namespace vmime { +namespace platforms { +namespace posix { + + +// +// posixSocket +// + +posixSocket::posixSocket(shared_ptr 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 VMIME_HAVE_GETADDRINFO // use thread-safe and IPv6-aware getaddrinfo() if available + + // Resolve address, if needed + struct ::addrinfo hints; + memset(&hints, 0, sizeof(hints)); + + hints.ai_flags = AI_CANONNAME; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + std::ostringstream portStr; + portStr.imbue(std::locale::classic()); + + portStr << port; + + struct ::addrinfo* res0; + + if (::getaddrinfo(address.c_str(), portStr.str().c_str(), &hints, &res0) != 0) + { + // Error: cannot resolve address + throw vmime::exceptions::connection_error("Cannot resolve address."); + } + + m_serverAddress = address; + + // Connect to host + int sock = -1; + struct ::addrinfo* res = res0; + + for ( ; sock == -1 && res != NULL ; res = res->ai_next) + { + sock = ::socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + if (sock < 0) + continue; // try next + + if (m_timeoutHandler != NULL) + { + ::fcntl(sock, F_SETFL, ::fcntl(sock, F_GETFL) | O_NONBLOCK); + + if (::connect(sock, res->ai_addr, res->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: + + ::close(sock); + sock = -1; + continue; // try next + } + + // Wait for socket to be connected. + // We will check for time out every second. + fd_set fds; + FD_ZERO(&fds); + FD_SET(sock, &fds); + + fd_set fdsError; + FD_ZERO(&fdsError); + FD_SET(sock, &fdsError); + + struct timeval tm; + tm.tv_sec = 1; + tm.tv_usec = 0; + + m_timeoutHandler->resetTimeOut(); + + bool connected = false; + + do + { + const int ret = select(sock + 1, NULL, &fds, &fdsError, &tm); + + // Success + if (ret > 0) + { + connected = true; + break; + } + // Error + else if (ret < -1) + { + if (errno != EINTR) + { + // Cancel connection + break; + } + } + // 1-second timeout + else if (ret == 0) + { + if (m_timeoutHandler->isTimeOut()) + { + if (!m_timeoutHandler->handleTimeOut()) + { + // Cancel connection + break; + } + else + { + // Reset timeout and keep waiting for connection + m_timeoutHandler->resetTimeOut(); + } + } + else + { + // Keep waiting for connection + } + } + + ::sched_yield(); + + } while (true); + + if (!connected) + { + ::close(sock); + sock = -1; + continue; // try next + } + + break; + } + } + else + { + if (::connect(sock, res->ai_addr, res->ai_addrlen) < 0) + { + ::close(sock); + sock = -1; + continue; // try next + } + } + } + + ::freeaddrinfo(res0); + + if (sock == -1) + { + try + { + throwSocketError(errno); + } + catch (exceptions::socket_exception& e) + { + 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 (port)); + addr.sin_addr.s_addr = ::inet_addr(address.c_str()); + + if (addr.sin_addr.s_addr == static_cast (-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 (&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) + { + throw vmime::exceptions::connection_error + ("Error while creating socket.", e); + } + } + + // Start connection + if (::connect(m_desc, reinterpret_cast (&addr), sizeof(addr)) == -1) + { + try + { + throwSocketError(errno); + } + catch (exceptions::socket_exception& e) + { + ::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); +} + + +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) + { + ::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); + + getpeername(m_desc, reinterpret_cast (&peer), &peerLen); + + // Convert to numerical presentation format + char numericAddress[1024]; + + if (inet_ntop(peer.sa_family, &peer, numericAddress, sizeof(numericAddress)) != NULL) + return string(numericAddress); + + return ""; // should not happen +} + + +const string posixSocket::getPeerName() const +{ + // Get address of connected peer + sockaddr peer; + socklen_t peerLen = sizeof(peer); + + getpeername(m_desc, reinterpret_cast (&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())) + { + +#if VMIME_HAVE_GETNAMEINFO + + char host[NI_MAXHOST + 1]; + char service[NI_MAXSERV + 1]; + + if (getnameinfo(reinterpret_cast (&peer), peerLen, + host, sizeof(host), service, sizeof(service), + /* flags */ NI_NAMEREQD) == 0) + { + return string(host); + } + +#else + + struct hostent *hp; + + if ((hp = gethostbyaddr(reinterpret_cast (&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 +} + + +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 + fd_set fds; + FD_ZERO(&fds); + FD_SET(m_desc, &fds); + + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + + ssize_t ret = ::select(m_desc + 1, &fds, NULL, NULL, &tv); + + if (ret < 0) + { + if (!IS_EAGAIN(errno)) + throwSocketError(errno); + + // 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(errno); + } + else + { + // Reset timeout + m_timeoutHandler->resetTimeOut(); + } + } + + m_status |= STATUS_WOULDBLOCK; + + // Continue waiting for data + return 0; + } + + // Read available data + 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 (buffer.data()), buffer.length()); +} + + +void posixSocket::send(const char* str) +{ + sendRaw(reinterpret_cast (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) + { + const ssize_t ret = ::send(m_desc, buffer, size, 0); + + if (ret <= 0) + { + if (ret < 0 && !IS_EAGAIN(errno)) + throwSocketError(errno); + + platform::getHandler()->wait(); + } + 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; + + const ssize_t ret = ::send(m_desc, buffer, count, 0); + + 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 + throwSocketError(errno); + } + 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) +{ + string msg; + + 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 occured 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: + case ENOTCONN: msg = "ENOTCONN: not connected"; break; + case ECONNREFUSED: msg = "ECONNREFUSED: connection refused"; break; + default: + + std::ostringstream oss; + oss << ::strerror(err); + + msg = oss.str(); + break; + } + + throw exceptions::socket_exception(msg); +} + + +unsigned int posixSocket::getStatus() const +{ + return m_status; +} + + + +// +// posixSocketFactory +// + +shared_ptr posixSocketFactory::create() +{ + shared_ptr th; + return make_shared (th); +} + + +shared_ptr posixSocketFactory::create(shared_ptr th) +{ + return make_shared (th); +} + + +} // posix +} // platforms +} // vmime + + +#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES diff --git a/src/vmime/platforms/posix/posixSocket.hpp b/src/vmime/platforms/posix/posixSocket.hpp new file mode 100644 index 00000000..4ec3edec --- /dev/null +++ b/src/vmime/platforms/posix/posixSocket.hpp @@ -0,0 +1,102 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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" + + +namespace vmime { +namespace platforms { +namespace posix { + + +class posixSocket : public vmime::net::socket +{ +public: + + posixSocket(shared_ptr th); + ~posixSocket(); + + void connect(const vmime::string& address, const vmime::port_t port); + bool isConnected() const; + void disconnect(); + + 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; + +protected: + + static void throwSocketError(const int err); + +private: + + shared_ptr m_timeoutHandler; + + byte_t m_buffer[65536]; + int m_desc; + + unsigned int m_status; + + string m_serverAddress; +}; + + + +class posixSocketFactory : public vmime::net::socketFactory +{ +public: + + shared_ptr create(); + shared_ptr create(shared_ptr th); +}; + + +} // posix +} // platforms +} // vmime + + +#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_PLATFORMS_POSIX_SOCKET_HPP_INCLUDED diff --git a/src/vmime/platforms/windows/windowsCriticalSection.cpp b/src/vmime/platforms/windows/windowsCriticalSection.cpp new file mode 100644 index 00000000..d6ef0c45 --- /dev/null +++ b/src/vmime/platforms/windows/windowsCriticalSection.cpp @@ -0,0 +1,67 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/platforms/windows/windowsCriticalSection.hpp b/src/vmime/platforms/windows/windowsCriticalSection.hpp new file mode 100644 index 00000000..7ed07835 --- /dev/null +++ b/src/vmime/platforms/windows/windowsCriticalSection.hpp @@ -0,0 +1,68 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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/src/vmime/platforms/windows/windowsFile.cpp b/src/vmime/platforms/windows/windowsFile.cpp new file mode 100644 index 00000000..6aa0fea8 --- /dev/null +++ b/src/vmime/platforms/windows/windowsFile.cpp @@ -0,0 +1,553 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + +#include "vmime/exception.hpp" +#include "vmime/utility/stringUtils.hpp" + + +namespace vmime { +namespace platforms { +namespace windows { + + +shared_ptr windowsFileSystemFactory::create(const vmime::utility::file::path& path) const +{ + return make_shared (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::string(str.begin() + prev, str.begin() + offset)); + + prev = offset + 1; + offset++; + } + + if (prev < str.length()) + path.appendComponent(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 windowsFile::getParent() const +{ + if (m_path.isEmpty()) + return NULL; + else + return make_shared (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 windowsFile::getFileWriter() +{ + return make_shared (m_path, m_nativePath); +} + +shared_ptr windowsFile::getFileReader() +{ + return make_shared (m_path, m_nativePath); +} + +shared_ptr windowsFile::getFiles() const +{ + return make_shared (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(fullPath); + 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 windowsFileIterator::nextElement() +{ + shared_ptr pFile = make_shared + (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 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 (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 (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 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 (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/src/vmime/platforms/windows/windowsFile.hpp b/src/vmime/platforms/windows/windowsFile.hpp new file mode 100644 index 00000000..3543ee8a --- /dev/null +++ b/src/vmime/platforms/windows/windowsFile.hpp @@ -0,0 +1,221 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace platforms { +namespace windows { + + +class windowsFileSystemFactory : public vmime::utility::fileSystemFactory +{ +public: + + shared_ptr 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 getParent() const; + + void rename(const path& newName); + void remove(); + + shared_ptr getFileWriter(); + + shared_ptr getFileReader(); + + shared_ptr 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 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 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 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/src/vmime/platforms/windows/windowsHandler.cpp b/src/vmime/platforms/windows/windowsHandler.cpp new file mode 100644 index 00000000..9c96b271 --- /dev/null +++ b/src/vmime/platforms/windows/windowsHandler.cpp @@ -0,0 +1,329 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include +#include +#include // for WSAStartup() +#include // for winnls.h +#include +#include + +#if VMIME_HAVE_MLANG +# include +#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 (); +#endif +#if VMIME_HAVE_FILESYSTEM_FEATURES + m_fileSysFactory = make_shared (); +#endif +} + + +windowsHandler::~windowsHandler() +{ + WSACleanup(); +} + + +unsigned long windowsHandler::getUnixTime() const +{ + return static_cast (::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 +} + + +static inline bool isFQDN(const vmime::string& str) +{ + if (utility::stringUtils::isStringEqualNoCase(str, "localhost", 9)) + return false; + + const vmime::size_t p = str.find_first_of("."); + return p != vmime::string::npos && p > 0 && p != str.length() - 1; +} + + +const vmime::string windowsHandler::getHostName() const +{ + char hostname[256]; + + // Try with 'gethostname' + ::gethostname(hostname, sizeof(hostname)); + hostname[sizeof(hostname) - 1] = '\0'; + + // If this is a Fully-Qualified Domain Name (FQDN), return immediately + if (isFQDN(hostname)) + return hostname; + + if (::strlen(hostname) == 0) + { +#if VMIME_HAVE_STRCPY_S + ::strcpy_s(hostname, "localhost"); +#else + ::strcpy(hostname, "localhost"); +#endif // VMIME_HAVE_STRCPY_S + } + + // Try to get canonical name for the hostname + 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) + { + for (struct addrinfo* p = info ; p != NULL ; p = p->ai_next) + { + if (p->ai_canonname && isFQDN(p->ai_canonname)) + { + const string ret(p->ai_canonname); + freeaddrinfo(info); + return ret; + } + } + + freeaddrinfo(info); + } + + return hostname; +} + + +unsigned int windowsHandler::getProcessId() const +{ + return (static_cast (::GetCurrentProcessId())); +} + + +unsigned int windowsHandler::getThreadId() const +{ + return static_cast (::GetCurrentThreadId()); +} + + +#if VMIME_HAVE_MESSAGING_FEATURES + +shared_ptr windowsHandler::getSocketFactory() +{ + return m_socketFactory; +} + +#endif + + +#if VMIME_HAVE_FILESYSTEM_FEATURES + +shared_ptr windowsHandler::getFileSystemFactory() +{ + return m_fileSysFactory; +} + + +shared_ptr windowsHandler::getChildProcessFactory() +{ + // TODO: Not implemented + return (NULL); +} + +#endif + + +void windowsHandler::wait() const +{ + ::Sleep(100); +} + + +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 (count), static_cast (buffer)); + CryptReleaseContext(cryptProvider, 0); +} + + +shared_ptr windowsHandler::createCriticalSection() +{ + return make_shared (); +} + + +} // posix +} // platforms +} // vmime + + +#endif // VMIME_PLATFORM_IS_WINDOWS + diff --git a/src/vmime/platforms/windows/windowsHandler.hpp b/src/vmime/platforms/windows/windowsHandler.hpp new file mode 100644 index 00000000..4a3678eb --- /dev/null +++ b/src/vmime/platforms/windows/windowsHandler.hpp @@ -0,0 +1,103 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 getSocketFactory(); +#endif + +#if VMIME_HAVE_FILESYSTEM_FEATURES + shared_ptr getFileSystemFactory(); + + shared_ptr getChildProcessFactory(); +#endif + + void wait() const; + + void generateRandomBytes(unsigned char* buffer, const unsigned int count); + + shared_ptr createCriticalSection(); + +private: + +#if VMIME_HAVE_MESSAGING_FEATURES + shared_ptr m_socketFactory; +#endif + +#if VMIME_HAVE_FILESYSTEM_FEATURES + shared_ptr m_fileSysFactory; +#endif +}; + + +} // windows +} // platforms +} // vmime + + +#endif // VMIME_PLATFORM_IS_WINDOWS + +#endif // VMIME_PLATFORMS_WINDOWS_HANDLER_HPP_INCLUDED diff --git a/src/vmime/platforms/windows/windowsSocket.cpp b/src/vmime/platforms/windows/windowsSocket.cpp new file mode 100644 index 00000000..40e69363 --- /dev/null +++ b/src/vmime/platforms/windows/windowsSocket.cpp @@ -0,0 +1,484 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/exception.hpp" + +#include + + +namespace vmime { +namespace platforms { +namespace windows { + + +// +// windowsSocket +// + +windowsSocket::windowsSocket(shared_ptr 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 (port)); + addr.sin_addr.s_addr = ::inet_addr(address.c_str()); + + if (addr.sin_addr.s_addr == static_cast (-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 (&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 (&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) + { + ::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 (&peer), &peerLen); + + // Convert to numerical presentation format + char host[NI_MAXHOST + 1]; + char service[NI_MAXSERV + 1]; + + if (getnameinfo(reinterpret_cast (&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 (&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 (&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 = vmime::string(m_buffer, size); +} + + +size_t windowsSocket::receiveRaw(char* buffer, const size_t count) +{ + m_status &= ~STATUS_WOULDBLOCK; + + // Check whether data is available + bool timedout; + waitForData(READ, timedout); + + if (timedout) + { + // 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, 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 (buffer.data()), buffer.length()); +} + + +void windowsSocket::send(const char* str) +{ + sendRaw(reinterpret_cast (str), strlen(str)); +} + + +void windowsSocket::sendRaw(const char* buffer, const size_t count) +{ + m_status &= ~STATUS_WOULDBLOCK; + + size_t size = count; + + while (size > 0) + { + const int ret = ::send(m_desc, buffer, size, 0); + + if (ret == SOCKET_ERROR) + { + int err = WSAGetLastError(); + + if (err != WSAEWOULDBLOCK) + throwSocketError(err); + + bool timedout; + waitForData(WRITE, timedout); + } + else + { + buffer += ret; + size -= ret; + } + } + + // Reset timeout + if (m_timeoutHandler) + m_timeoutHandler->resetTimeOut(); +} + + +size_t windowsSocket::sendRawNonBlocking(const char* buffer, const size_t count) +{ + m_status &= ~STATUS_WOULDBLOCK; + + const int ret = ::send(m_desc, 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); +} + + +void windowsSocket::waitForData(const WaitOpType t, bool& timedOut) +{ + // Check whether data is available + fd_set fds; + FD_ZERO(&fds); + FD_SET(m_desc, &fds); + + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + + int ret; + + if (t & READ) + ret = ::select(m_desc + 1, &fds, NULL, NULL, &tv); + else if (t & WRITE) + ret = ::select(m_desc + 1, NULL, &fds, NULL, &tv); + else + ret = ::select(m_desc + 1, &fds, &fds, NULL, &tv); + + timedOut = (ret == 0); + + if (ret == SOCKET_ERROR) + { + int err = WSAGetLastError(); + throwSocketError(err); + } +} + + + +// +// posixSocketFactory +// + +shared_ptr windowsSocketFactory::create() +{ + shared_ptr th = NULL; + return make_shared (th); +} + +shared_ptr windowsSocketFactory::create(shared_ptr th) +{ + return make_shared (th); +} + +} // posix +} // platforms +} // vmime + + +#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES + diff --git a/src/vmime/platforms/windows/windowsSocket.hpp b/src/vmime/platforms/windows/windowsSocket.hpp new file mode 100644 index 00000000..e3f43b7c --- /dev/null +++ b/src/vmime/platforms/windows/windowsSocket.hpp @@ -0,0 +1,114 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include "vmime/net/socket.hpp" + + +namespace vmime { +namespace platforms { +namespace windows { + + +class windowsSocket : public vmime::net::socket +{ +public: + + windowsSocket(); + windowsSocket(shared_ptr th); + ~windowsSocket(); + +public: + + void connect(const vmime::string& address, const vmime::port_t port); + bool isConnected() const; + void disconnect(); + + void receive(vmime::string& buffer); + size_t receiveRaw(char* buffer, const size_t count); + + void send(const vmime::string& buffer); + void sendRaw(const char* buffer, const size_t count); + size_t sendRawNonBlocking(const char* buffer, const size_t count); + + size_t getBlockSize() const; + + unsigned int getStatus() const; + + const string getPeerName() const; + const string getPeerAddress() const; + +protected: + + void throwSocketError(const int err); + + enum WaitOpType + { + READ = 1, + WRITE = 2, + BOTH = 4 + }; + + void waitForData(const WaitOpType t, bool& timedOut); + +private: + + shared_ptr m_timeoutHandler; + + char m_buffer[65536]; + SOCKET m_desc; + + unsigned int m_status; + + string m_serverAddress; +}; + + + +class windowsSocketFactory : public vmime::net::socketFactory +{ +public: + + shared_ptr create(); + shared_ptr create(shared_ptr th); +}; + + +} // windows +} // platforms +} // vmime + + +#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_PLATFORMS_WINDOWS_SOCKET_HPP_INCLUDED diff --git a/src/vmime/propertySet.cpp b/src/vmime/propertySet.cpp new file mode 100644 index 00000000..c22e79a6 --- /dev/null +++ b/src/vmime/propertySet.cpp @@ -0,0 +1,382 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 >::const_iterator it = set.m_props.begin() ; it != set.m_props.end() ; ++it) + m_props.push_back(make_shared (**it)); +} + + +propertySet::~propertySet() +{ + removeAllProperties(); +} + + +propertySet& propertySet::operator=(const propertySet& set) +{ + removeAllProperties(); + + for (std::list >::const_iterator it = set.m_props.begin() ; it != set.m_props.end() ; ++it) + m_props.push_back(make_shared (**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 >::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 (option, value)); + } + } +} + + +shared_ptr propertySet::find(const string& name) const +{ + std::list >::const_iterator it = std::find_if + (m_props.begin(), m_props.end(), propFinder(name)); + + return (it != m_props.end() ? *it : null); +} + + +shared_ptr propertySet::findOrCreate(const string& name) +{ + std::list >::const_iterator it = std::find_if + (m_props.begin(), m_props.end(), propFinder(name)); + + if (it != m_props.end()) + { + return (*it); + } + else + { + shared_ptr prop = make_shared (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 > propertySet::getPropertyList() const +{ + std::vector > res; + + for (list_type::const_iterator it = m_props.begin() ; it != m_props.end() ; ++it) + res.push_back(*it); + + return (res); +} + + +const std::vector > propertySet::getPropertyList() +{ + std::vector > 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/src/vmime/propertySet.hpp b/src/vmime/propertySet.hpp new file mode 100644 index 00000000..bf1c39bf --- /dev/null +++ b/src/vmime/propertySet.hpp @@ -0,0 +1,460 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include +#include +#include + +#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 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 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 + propertyProxy& operator=(const TYPE& value) + { + m_set->setProperty(m_name, value); + return (*this); + } + + template + void setValue(const TYPE& value) + { + m_set->setProperty(m_name, value); + } + + template + const TYPE getValue() const + { + return (m_set->getProperty (m_name)); + } + + operator string() const + { + return (m_set->getProperty (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 + const TYPE getValue() const + { + return (m_set->getProperty (m_name)); + } + + operator string() const + { + return (m_set->getProperty (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 + const TYPE getProperty(const string& name) const + { + const shared_ptr prop = find(name); + if (!prop) throw exceptions::no_such_property(name); + + //return (prop->getValue ()); // BUG: with g++ < 3.4 + return (prop->template getValue ()); + } + + /** 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 + const TYPE getProperty(const string& name, const TYPE defaultValue) const + { + const shared_ptr prop = find(name); + //return (prop ? prop->getValue () : defaultValue); // BUG: with g++ < 3.4 + return (prop ? prop->template getValue () : 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 + 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 , bool> + { + public: + + propFinder(const string& name) : m_name(utility::stringUtils::toLower(name)) { } + + bool operator()(shared_ptr p) const + { + return (utility::stringUtils::toLower(p->getName()) == m_name); + } + + private: + + const string m_name; + }; + + shared_ptr find(const string& name) const; + shared_ptr findOrCreate(const string& name); + + typedef std::list > list_type; + list_type m_props; + +public: + + template + 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 + 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 > getPropertyList() const; + + /** Return the property list. + * + * @return list of properties + */ + const std::vector > getPropertyList(); +}; + + +#ifndef VMIME_INLINE_TEMPLATE_SPECIALIZATION + +template <> VMIME_EXPORT void propertySet::property::setValue (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/src/vmime/relay.cpp b/src/vmime/relay.cpp new file mode 100644 index 00000000..e5d30c9e --- /dev/null +++ b/src/vmime/relay.cpp @@ -0,0 +1,354 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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))); + + string word; + std::vector 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 ::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 ::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 (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 relay::clone() const +{ + return make_shared (*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 & relay::getWithList() const +{ + return (m_with); +} + + +std::vector & relay::getWithList() +{ + return (m_with); +} + + +const std::vector > relay::getChildComponents() +{ + // TODO: should fields inherit from 'component'? (using typeAdapter) + return std::vector >(); +} + + +} // vmime diff --git a/src/vmime/relay.hpp b/src/vmime/relay.hpp new file mode 100644 index 00000000..35949ff1 --- /dev/null +++ b/src/vmime/relay.hpp @@ -0,0 +1,108 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + void copyFrom(const component& other); + relay& operator=(const relay& other); + + const std::vector > 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 & getWithList() const; + std::vector & getWithList(); + +private: + + string m_from; + string m_via; + string m_by; + string m_id; + string m_for; + std::vector 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/src/vmime/security/authenticator.hpp b/src/vmime/security/authenticator.hpp new file mode 100644 index 00000000..bef07b4a --- /dev/null +++ b/src/vmime/security/authenticator.hpp @@ -0,0 +1,128 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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(shared_ptr serv) = 0; +}; + + +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_SECURITY_AUTHENTICATOR_HPP_INCLUDED + diff --git a/src/vmime/security/cert/X509Certificate.cpp b/src/vmime/security/cert/X509Certificate.cpp new file mode 100644 index 00000000..2eebabfd --- /dev/null +++ b/src/vmime/security/cert/X509Certificate.cpp @@ -0,0 +1,48 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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" + + +namespace vmime { +namespace security { +namespace cert { + + +X509Certificate::~X509Certificate() +{ +} + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/src/vmime/security/cert/X509Certificate.hpp b/src/vmime/security/cert/X509Certificate.hpp new file mode 100644 index 00000000..215a86cf --- /dev/null +++ b/src/vmime/security/cert/X509Certificate.hpp @@ -0,0 +1,156 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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 import(const byte_t* data, const size_t length); + + /** 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; + + /** 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(shared_ptr 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(shared_ptr caCert) const = 0; + + /** Verify certificate's subject name against the given hostname. + * + * @param hostname DNS name of the server + * @return true if the match is successful, false otherwise + */ + virtual bool verifyHostName(const string& hostname) 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; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + +#endif // VMIME_SECURITY_CERT_X509CERTIFICATE_HPP_INCLUDED + diff --git a/src/vmime/security/cert/certificate.hpp b/src/vmime/security/cert/certificate.hpp new file mode 100644 index 00000000..aef1f1f9 --- /dev/null +++ b/src/vmime/security/cert/certificate.hpp @@ -0,0 +1,84 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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: + + /** 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(shared_ptr 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/src/vmime/security/cert/certificateChain.cpp b/src/vmime/security/cert/certificateChain.cpp new file mode 100644 index 00000000..3cb4e360 --- /dev/null +++ b/src/vmime/security/cert/certificateChain.cpp @@ -0,0 +1,53 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 >& certs) + : m_certs(certs) +{ +} + + +unsigned int certificateChain::getCount() const +{ + return static_cast (m_certs.size()); +} + + +shared_ptr certificateChain::getAt(const unsigned int index) +{ + return m_certs[index]; +} + + +} // cert +} // security +} // vmime + diff --git a/src/vmime/security/cert/certificateChain.hpp b/src/vmime/security/cert/certificateChain.hpp new file mode 100644 index 00000000..0ce6bda3 --- /dev/null +++ b/src/vmime/security/cert/certificateChain.hpp @@ -0,0 +1,79 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 >& certs); + + /** Return the number of certificates in the chain. + * + * @return number of certificates in the chain + */ + unsigned int 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 + */ + shared_ptr getAt(const unsigned int index); + +protected: + + std::vector > m_certs; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_SECURITY_CERT_CERTIFICATECHAIN_HPP_INCLUDED + diff --git a/src/vmime/security/cert/certificateVerifier.hpp b/src/vmime/security/cert/certificateVerifier.hpp new file mode 100644 index 00000000..c72c84cb --- /dev/null +++ b/src/vmime/security/cert/certificateVerifier.hpp @@ -0,0 +1,62 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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" + + +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 exceptions::certificate_verification_exception if one + * or more certificates can not be trusted, or the server identity + * cannot be verified + */ + virtual void verify(shared_ptr chain, const string& hostname) = 0; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_SECURITY_CERT_CERTIFICATEVERIFIER_HPP_INCLUDED + diff --git a/src/vmime/security/cert/defaultCertificateVerifier.cpp b/src/vmime/security/cert/defaultCertificateVerifier.cpp new file mode 100644 index 00000000..1a95b353 --- /dev/null +++ b/src/vmime/security/cert/defaultCertificateVerifier.cpp @@ -0,0 +1,178 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_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 + (shared_ptr 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 exceptions::unsupported_certificate_type(type); +} + + +void defaultCertificateVerifier::verifyX509 + (shared_ptr 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 (unsigned int i = 0 ; i < chain->getCount() - 1 ; ++i) + { + shared_ptr cert = + dynamicCast (chain->getAt(i)); + + shared_ptr next = + dynamicCast (chain->getAt(i + 1)); + + if (!cert->checkIssuer(next)) + { + throw exceptions::certificate_verification_exception + ("Subject/issuer verification failed."); + } + } + } + + // For every certificate in the chain, verify that the certificate + // is valid at the current time + const datetime now = datetime::now(); + + for (unsigned int i = 0 ; i < chain->getCount() ; ++i) + { + shared_ptr cert = + dynamicCast (chain->getAt(i)); + + const datetime begin = cert->getActivationDate(); + const datetime end = cert->getExpirationDate(); + + if (now < begin || now > end) + { + throw exceptions::certificate_verification_exception + ("Validity date check failed."); + } + } + + // 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 lastCert = + dynamicCast (chain->getAt(chain->getCount() - 1)); + + bool trusted = false; + + for (unsigned int i = 0 ; !trusted && i < m_x509RootCAs.size() ; ++i) + { + shared_ptr rootCa = m_x509RootCAs[i]; + + if (lastCert->verify(rootCa)) + trusted = true; + } + + // -- Next, if the issuer certificate cannot be verified against + // -- root CAs, compare the subject's certificate against the + // -- trusted certificates + shared_ptr firstCert = + dynamicCast (chain->getAt(0)); + + for (unsigned int i = 0 ; !trusted && i < m_x509TrustedCerts.size() ; ++i) + { + shared_ptr cert = m_x509TrustedCerts[i]; + + if (firstCert->equals(cert)) + trusted = true; + } + + if (!trusted) + { + throw exceptions::certificate_verification_exception + ("Cannot verify certificate against trusted certificates."); + } + + // Ensure the first certificate's subject name matches server hostname + if (!firstCert->verifyHostName(hostname)) + { + throw exceptions::certificate_verification_exception + ("Server identity cannot be verified."); + } +} + + +void defaultCertificateVerifier::setX509RootCAs + (const std::vector >& caCerts) +{ + m_x509RootCAs = caCerts; +} + + +void defaultCertificateVerifier::setX509TrustedCerts + (const std::vector >& trustedCerts) +{ + m_x509TrustedCerts = trustedCerts; +} + + +} // cert +} // security +} // vmime + +#endif diff --git a/src/vmime/security/cert/defaultCertificateVerifier.hpp b/src/vmime/security/cert/defaultCertificateVerifier.hpp new file mode 100644 index 00000000..fddcc4f5 --- /dev/null +++ b/src/vmime/security/cert/defaultCertificateVerifier.hpp @@ -0,0 +1,89 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/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 >& trustedCerts); + + /** Sets the X.509 root CAs used for certificate verification. + * + * @param caCerts list of root CAs + */ + void setX509RootCAs(const std::vector >& caCerts); + + + // Implementation of 'certificateVerifier' + void verify(shared_ptr 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(shared_ptr chain, const string& hostname); + + + std::vector > m_x509RootCAs; + std::vector > m_x509TrustedCerts; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_SECURITY_CERT_DEFAULTCERTIFICATEVERIFIER_HPP_INCLUDED + diff --git a/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp b/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp new file mode 100644 index 00000000..f96ddddb --- /dev/null +++ b/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp @@ -0,0 +1,290 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + +#include + +#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); + } + + + gnutls_x509_crt 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::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::import + (const byte_t* data, const size_t length) +{ + gnutls_datum buffer; + buffer.data = const_cast (data); + buffer.size = static_cast (length); + + // Try DER format + shared_ptr derCert = make_shared (); + + if (gnutls_x509_crt_import(derCert->m_data->cert, &buffer, GNUTLS_X509_FMT_DER) >= 0) + return derCert; + + // Try PEM format + shared_ptr pemCert = make_shared (); + + if (gnutls_x509_crt_import(pemCert->m_data->cert, &buffer, GNUTLS_X509_FMT_PEM) >= 0) + return pemCert; + + return null; +} + + +void X509Certificate_GnuTLS::write + (utility::outputStream& os, const Format format) const +{ + size_t dataSize = 0; + gnutls_x509_crt_fmt 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 data(dataSize); + + gnutls_x509_crt_export(m_data->cert, fmt, &data[0], &dataSize); + + os.write(reinterpret_cast (&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(shared_ptr issuer_) const +{ + shared_ptr issuer = + dynamicCast (issuer_); + + return (gnutls_x509_crt_check_issuer + (m_data->cert, issuer->m_data->cert) >= 1); +} + + +bool X509Certificate_GnuTLS::verify(shared_ptr caCert_) const +{ + shared_ptr caCert = + dynamicCast (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) const +{ + return gnutls_x509_crt_check_hostname(m_data->cert, hostname.c_str()) != 0; +} + + +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 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 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::getType() const +{ + return "X.509"; +} + + +int X509Certificate_GnuTLS::getVersion() const +{ + return gnutls_x509_crt_get_version(m_data->cert); +} + + +bool X509Certificate_GnuTLS::equals(shared_ptr other) const +{ + shared_ptr otherX509 = + dynamicCast (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/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp b/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp new file mode 100644 index 00000000..76ee6d4d --- /dev/null +++ b/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp @@ -0,0 +1,92 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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; + + bool checkIssuer(shared_ptr issuer) const; + + bool verify(shared_ptr caCert) const; + + bool verifyHostName(const string& hostname) 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(shared_ptr 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/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp b/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp new file mode 100644 index 00000000..5f81b2bf --- /dev/null +++ b/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp @@ -0,0 +1,574 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include +#include +#include + +#include "vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp" + +#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp" + +#include "vmime/utility/outputStreamByteArrayAdapter.hpp" + +#include "vmime/exception.hpp" + +#include +#include +#include +#include +#include +#include + + +#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 ::const_iterator + c_it = m_monthMap.find(mstr); + + if (c_it != m_monthMap.end()) + return c_it->second; + + return -1; + } + +private: + + std::map m_monthMap; +}; + +static monthMap sg_monthMap; + + + +struct OpenSSLX509CertificateInternalData +{ + OpenSSLX509CertificateInternalData() + { + cert = 0; + } + + ~OpenSSLX509CertificateInternalData() + { + if (cert) + X509_free(cert); + } + + X509* cert; +}; + +#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_OpenSSL::importInternal(X509* cert) +{ + if (cert) + return make_shared (reinterpret_cast (cert)); + + return null; +} + + +// static +shared_ptr 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::import + (const byte_t* data, const size_t length) +{ + shared_ptr cert = make_shared (); + + BIO* membio = BIO_new_mem_buf(const_cast (data), static_cast (length)); + + if (!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0)) + { + BIO_vfree(membio); + return null; + } + + BIO_vfree(membio); + + return cert; +} + + +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 (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 (out), dataSize); + os.flush(); + BIO_vfree(membio); + } + else + { + throw vmime::exceptions::unsupported_certificate_type("Unknown cert type"); + } + + 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 vmime::exceptions::certificate_exception( + "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(shared_ptr cert_) const +{ + shared_ptr cert = + dynamicCast (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(shared_ptr caCert_) const +{ + shared_ptr caCert = + dynamicCast (caCert_); + + + 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) 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; + } + + // Now, look in subject alternative names + for (int i = 0, extCount = X509_get_ext_count(m_data->cert) ; i < extCount ; ++i) + { + X509_EXTENSION* ext = X509_get_ext(m_data->cert, i); + const char* extStr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); + + if (strcmp(extStr, "subjectAltName") == 0) + { +#ifdef _WIN32 + X509V3_EXT_METHOD* method; +#else + const X509V3_EXT_METHOD* method; +#endif + + if ((method = X509V3_EXT_get(ext)) != NULL) + { + const unsigned char* extVal = ext->value->data; + void *extValStr; + + if (method->it) + { + extValStr = ASN1_item_d2i + (NULL, &extVal, ext->value->length, ASN1_ITEM_ptr(method->it)); + } + else + { + extValStr = method->d2i + (NULL, &extVal, ext->value->length); + } + + if (extValStr && method->i2v) + { + STACK_OF(CONF_VALUE)* val = method->i2v(method, extValStr, NULL); + + for (int j = 0 ; j < sk_CONF_VALUE_num(val) ; ++j) + { + CONF_VALUE* cnf = sk_CONF_VALUE_value(val, j); + + if ((strcasecmp(cnf->name, "DNS") == 0 && + strcasecmp(cnf->value, hostname.c_str()) == 0) + || + (strncasecmp(cnf->name, "IP", 2) == 0 && + strcasecmp(cnf->value, hostname.c_str()) == 0)) + { + return true; + } + } + } + } + } + } + + return false; +} + + +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(time); + ASN1_TIME_print(out, asn1_time); + + int 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, *result; + 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, ":"); + } + } + + n = BIO_get_mem_data(out, &fingerprint); + result = new unsigned char[n]; + memcpy (result, fingerprint, n); + BIO_free(out); + + byteArray res; + res.insert(res.end(), &result[0], &result[0] + n); + + 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::getType() const +{ + return "X.509"; +} + + +int X509Certificate_OpenSSL::getVersion() const +{ + return (int)X509_get_version(m_data->cert); +} + + +bool X509Certificate_OpenSSL::equals(shared_ptr other) const +{ + shared_ptr otherX509 = + dynamicCast (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/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp b/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp new file mode 100644 index 00000000..bddb4b6c --- /dev/null +++ b/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp @@ -0,0 +1,115 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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; + + bool checkIssuer(shared_ptr issuer) const; + + bool verify(shared_ptr caCert) const; + + bool verifyHostName(const string& hostname) const; + + const datetime getExpirationDate() const; + const datetime getActivationDate() const; + + const byteArray getFingerprint(const DigestAlgorithm algo) const; + + + static shared_ptr importInternal(X509* cert); + + + // Implementation of 'certificate' + const byteArray getEncoded() const; + const string getType() const; + int getVersion() const; + bool equals(shared_ptr 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/src/vmime/security/defaultAuthenticator.cpp b/src/vmime/security/defaultAuthenticator.cpp new file mode 100644 index 00000000..790196d2 --- /dev/null +++ b/src/vmime/security/defaultAuthenticator.cpp @@ -0,0 +1,115 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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 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::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(shared_ptr serv) +{ + m_service = serv; +} + + +weak_ptr defaultAuthenticator::getService() const +{ + return m_service; +} + + +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + diff --git a/src/vmime/security/defaultAuthenticator.hpp b/src/vmime/security/defaultAuthenticator.hpp new file mode 100644 index 00000000..eead3d14 --- /dev/null +++ b/src/vmime/security/defaultAuthenticator.hpp @@ -0,0 +1,73 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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; + + void setService(shared_ptr serv); + weak_ptr getService() const; + +private: + + weak_ptr m_service; +}; + + +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + +#endif // VMIME_SECURITY_DEFAULTAUTHENTICATOR_HPP_INCLUDED + diff --git a/src/vmime/security/digest/md5/md5MessageDigest.cpp b/src/vmime/security/digest/md5/md5MessageDigest.cpp new file mode 100644 index 00000000..a83f0623 --- /dev/null +++ b/src/vmime/security/digest/md5/md5MessageDigest.cpp @@ -0,0 +1,347 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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 (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 (m_byteCount << 3); + m_block.b32[15] = static_cast (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<>(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 (m_hash); +} + + +} // md5 +} // digest +} // security +} // vmime + diff --git a/src/vmime/security/digest/md5/md5MessageDigest.hpp b/src/vmime/security/digest/md5/md5MessageDigest.hpp new file mode 100644 index 00000000..ef94f5c8 --- /dev/null +++ b/src/vmime/security/digest/md5/md5MessageDigest.hpp @@ -0,0 +1,86 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/security/digest/messageDigest.cpp b/src/vmime/security/digest/messageDigest.cpp new file mode 100644 index 00000000..18fc8628 --- /dev/null +++ b/src/vmime/security/digest/messageDigest.cpp @@ -0,0 +1,57 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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/src/vmime/security/digest/messageDigest.hpp b/src/vmime/security/digest/messageDigest.hpp new file mode 100644 index 00000000..d17dfbc2 --- /dev/null +++ b/src/vmime/security/digest/messageDigest.hpp @@ -0,0 +1,138 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/security/digest/messageDigestFactory.cpp b/src/vmime/security/digest/messageDigestFactory.cpp new file mode 100644 index 00000000..2831c5a1 --- /dev/null +++ b/src/vmime/security/digest/messageDigestFactory.cpp @@ -0,0 +1,84 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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"); + registerAlgorithm ("sha1"); +} + + +messageDigestFactory::~messageDigestFactory() +{ +} + + +messageDigestFactory* messageDigestFactory::getInstance() +{ + static messageDigestFactory instance; + return (&instance); +} + + +shared_ptr 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 messageDigestFactory::getSupportedAlgorithms() const +{ + std::vector 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/src/vmime/security/digest/messageDigestFactory.hpp b/src/vmime/security/digest/messageDigestFactory.hpp new file mode 100644 index 00000000..15fd8a28 --- /dev/null +++ b/src/vmime/security/digest/messageDigestFactory.hpp @@ -0,0 +1,112 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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: + + class digestAlgorithmFactory : public object + { + public: + + virtual shared_ptr create() const = 0; + }; + + template + class digestAlgorithmFactoryImpl : public digestAlgorithmFactory + { + public: + + shared_ptr create() const + { + return vmime::make_shared (); + } + }; + + + typedef std::map > MapType; + MapType m_algos; + +public: + + /** Register a new digest algorithm by its name. + * + * @param name algorithm name + */ + template + void registerAlgorithm(const string& name) + { + m_algos.insert(MapType::value_type(utility::stringUtils::toLower(name), + vmime::make_shared >())); + } + + /** 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 create(const string& name); + + /** Return a list of supported digest algorithms. + * + * @return list of supported digest algorithms + */ + const std::vector getSupportedAlgorithms() const; +}; + + +} // digest +} // security +} // vmime + + +#endif // VMIME_SECURITY_DIGEST_MESSAGEDIGESTFACTORY_HPP_INCLUDED + diff --git a/src/vmime/security/digest/sha1/sha1MessageDigest.cpp b/src/vmime/security/digest/sha1/sha1MessageDigest.cpp new file mode 100644 index 00000000..aa055af5 --- /dev/null +++ b/src/vmime/security/digest/sha1/sha1MessageDigest.cpp @@ -0,0 +1,271 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +// 100% public domain. + +#include "vmime/security/digest/sha1/sha1MessageDigest.hpp" + +#include +#include + + +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 (s.data()), s.length()); +} + + +void sha1MessageDigest::update(const byte_t* buffer, const size_t offset, + const unsigned long 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 (len << 3)) < static_cast (len << 3)) + m_count[1]++; + + m_count[1] += static_cast (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 + ((m_count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); // Endian independent + } + + update(reinterpret_cast ("\200"), 1); + + while ((m_count[0] & 504) != 448) + update(reinterpret_cast ("\0"), 1); + + update(finalcount, 8); // Should cause a transform() + + for (i = 0 ; i < 20 ; i++) + { + m_digest[i] = static_cast + ((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 (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 (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/src/vmime/security/digest/sha1/sha1MessageDigest.hpp b/src/vmime/security/digest/sha1/sha1MessageDigest.hpp new file mode 100644 index 00000000..1eb09c2f --- /dev/null +++ b/src/vmime/security/digest/sha1/sha1MessageDigest.hpp @@ -0,0 +1,79 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/security/sasl/SASLAuthenticator.hpp b/src/vmime/security/sasl/SASLAuthenticator.hpp new file mode 100644 index 00000000..9f1881f5 --- /dev/null +++ b/src/vmime/security/sasl/SASLAuthenticator.hpp @@ -0,0 +1,96 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 > getAcceptableMechanisms + (const std::vector >& available, + shared_ptr suggested) const = 0; + + /** Set the SASL session which is using this authenticator. + * + * @param sess SASL session + */ + virtual void setSASLSession(shared_ptr 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(shared_ptr mech) = 0; +}; + + +} // sasl +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT + +#endif // VMIME_SECURITY_SASL_SASLAUTHENTICATOR_HPP_INCLUDED + diff --git a/src/vmime/security/sasl/SASLContext.cpp b/src/vmime/security/sasl/SASLContext.cpp new file mode 100644 index 00000000..3474cbeb --- /dev/null +++ b/src/vmime/security/sasl/SASLContext.cpp @@ -0,0 +1,208 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#include + +#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); +} + + +shared_ptr SASLContext::createSession + (const string& serviceName, + shared_ptr auth, shared_ptr mech) +{ + return make_shared + (serviceName, dynamicCast (shared_from_this()), auth, mech); +} + + +shared_ptr SASLContext::createMechanism(const string& name) +{ + return SASLMechanismFactory::getInstance()->create + (dynamicCast (shared_from_this()), name); +} + + +shared_ptr SASLContext::suggestMechanism + (const std::vector >& 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 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 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/src/vmime/security/sasl/SASLContext.hpp b/src/vmime/security/sasl/SASLContext.hpp new file mode 100644 index 00000000..200f78db --- /dev/null +++ b/src/vmime/security/sasl/SASLContext.hpp @@ -0,0 +1,128 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +{ + friend class SASLSession; + friend class builtinSASLMechanism; + +public: + + ~SASLContext(); + + /** Construct and initialize a new SASL context. + */ + SASLContext(); + + /** 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 createSession + (const string& serviceName, + shared_ptr auth, shared_ptr 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 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 suggestMechanism + (const std::vector >& 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: + + 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/src/vmime/security/sasl/SASLMechanism.hpp b/src/vmime/security/sasl/SASLMechanism.hpp new file mode 100644 index 00000000..5492e48c --- /dev/null +++ b/src/vmime/security/sasl/SASLMechanism.hpp @@ -0,0 +1,131 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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. + * + * @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 occured during + * authentication (in this case, the values in 'response' and + * 'responseLen' are undetermined) + */ + virtual bool step + (shared_ptr 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; + + /** 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 occured during + * the encoding of data (in this case, the values in 'output' and + * 'outputLen' are undetermined) + */ + virtual void encode(shared_ptr 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 occured during + * the encoding of data (in this case, the values in 'output' and + * 'outputLen' are undetermined) + */ + virtual void decode(shared_ptr 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/src/vmime/security/sasl/SASLMechanismFactory.cpp b/src/vmime/security/sasl/SASLMechanismFactory.cpp new file mode 100644 index 00000000..255a13f1 --- /dev/null +++ b/src/vmime/security/sasl/SASLMechanismFactory.cpp @@ -0,0 +1,144 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + +#include + +#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 SASLMechanismFactory::create + (shared_ptr ctx, const string& name_) +{ + const string name(utility::stringUtils::toUpper(name_)); + + // Check for built-in mechanisms + if (isMechanismSupported(name)) + { + return make_shared (ctx, name); + } + // Check for registered mechanisms + else + { + MapType::iterator it = m_mechs.find(name); + + if (it != m_mechs.end()) + return (*it).second->create(ctx, name); + } + + throw exceptions::no_such_mechanism(name); + return null; +} + + +const std::vector SASLMechanismFactory::getSupportedMechanisms() const +{ + std::vector 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 (gsasl_client_support_p(m_gsaslContext, name.c_str()) != 0 || + m_mechs.find(name) != m_mechs.end()); +} + + +} // sasl +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT + diff --git a/src/vmime/security/sasl/SASLMechanismFactory.hpp b/src/vmime/security/sasl/SASLMechanismFactory.hpp new file mode 100644 index 00000000..3503f71b --- /dev/null +++ b/src/vmime/security/sasl/SASLMechanismFactory.hpp @@ -0,0 +1,143 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +namespace vmime { +namespace security { +namespace sasl { + + +class SASLContext; + + +/** Constructs SASL mechanism objects. + */ +class VMIME_EXPORT SASLMechanismFactory : public object +{ +private: + + SASLMechanismFactory(); + ~SASLMechanismFactory(); + + + class registeredMechanism : public object + { + public: + + virtual shared_ptr create + (shared_ptr ctx, const string& name) = 0; + }; + + template + class registeredMechanismImpl : public registeredMechanism + { + public: + + shared_ptr create(shared_ptr ctx, const string& name) + { + return vmime::make_shared (ctx, name); + } + }; + + typedef std::map > 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 + void registerMechanism(const string& name) + { + m_mechs.insert(MapType::value_type(name, + vmime::make_shared >())); + } + + /** 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 create(shared_ptr 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 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; + +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/src/vmime/security/sasl/SASLSession.cpp b/src/vmime/security/sasl/SASLSession.cpp new file mode 100644 index 00000000..087ef27b --- /dev/null +++ b/src/vmime/security/sasl/SASLSession.cpp @@ -0,0 +1,192 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#include + +#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, shared_ptr ctx, + shared_ptr auth, shared_ptr 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; +} + + +void SASLSession::init() +{ + shared_ptr saslAuth = dynamicCast (m_auth); + + if (saslAuth) + { + saslAuth->setSASLMechanism(m_mech); + saslAuth->setSASLSession(dynamicCast (shared_from_this())); + } +} + + +shared_ptr SASLSession::getAuthenticator() +{ + return m_auth; +} + + +shared_ptr SASLSession::getMechanism() +{ + return m_mech; +} + + +shared_ptr 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 (shared_from_this()), + challenge, challengeLen, response, responseLen); +} + + +shared_ptr SASLSession::getSecuredSocket(shared_ptr sok) +{ + return make_shared (dynamicCast (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 (gsasl_callback_hook_get(ctx)); + if (!sess) return GSASL_AUTHENTICATION_ERROR; + + shared_ptr 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 (exceptions::no_auth_information&) + catch (...) + { + return GSASL_NO_CALLBACK; + } +} + + +} // sasl +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT + diff --git a/src/vmime/security/sasl/SASLSession.hpp b/src/vmime/security/sasl/SASLSession.hpp new file mode 100644 index 00000000..ccf181cb --- /dev/null +++ b/src/vmime/security/sasl/SASLSession.hpp @@ -0,0 +1,162 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/security/sasl/SASLAuthenticator.hpp" +#include "vmime/security/sasl/SASLMechanism.hpp" +#include "vmime/security/sasl/SASLSocket.hpp" + + +namespace vmime { +namespace security { +namespace sasl { + + +class SASLContext; + + +/** An SASL client session. + */ +class VMIME_EXPORT SASLSession : public object +{ + 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 + */ + SASLSession(const string& serviceName, shared_ptr ctx, + shared_ptr auth, shared_ptr 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 getAuthenticator(); + + /** Return the mechanism used for this session. + * + * @return SASL mechanism + */ + shared_ptr getMechanism(); + + /** Return the SASL context. + * + * @return SASL context + */ + shared_ptr 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. + * + * @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 occured 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 getSecuredSocket(shared_ptr 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: + + const string m_serviceName; + + shared_ptr m_context; + shared_ptr m_auth; + shared_ptr 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/src/vmime/security/sasl/SASLSocket.cpp b/src/vmime/security/sasl/SASLSocket.cpp new file mode 100644 index 00000000..12d634c2 --- /dev/null +++ b/src/vmime/security/sasl/SASLSocket.cpp @@ -0,0 +1,236 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include + +#include + + +namespace vmime { +namespace security { +namespace sasl { + + + +SASLSocket::SASLSocket(shared_ptr sess, shared_ptr 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(); +} + + +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 (buffer.data()), buffer.length()); +} + + +void SASLSocket::send(const char* str) +{ + sendRaw(reinterpret_cast (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/src/vmime/security/sasl/SASLSocket.hpp b/src/vmime/security/sasl/SASLSocket.hpp new file mode 100644 index 00000000..e52911b4 --- /dev/null +++ b/src/vmime/security/sasl/SASLSocket.hpp @@ -0,0 +1,97 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr wrapped); + ~SASLSocket(); + + void connect(const string& address, const port_t port); + void disconnect(); + + bool isConnected() const; + + 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; + +private: + + shared_ptr m_session; + shared_ptr 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/src/vmime/security/sasl/builtinSASLMechanism.cpp b/src/vmime/security/sasl/builtinSASLMechanism.cpp new file mode 100644 index 00000000..e179e715 --- /dev/null +++ b/src/vmime/security/sasl/builtinSASLMechanism.cpp @@ -0,0 +1,195 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#include "vmime/security/sasl/builtinSASLMechanism.hpp" + +#include "vmime/security/sasl/SASLContext.hpp" +#include "vmime/security/sasl/SASLSession.hpp" + +#include "vmime/exception.hpp" + +#include +#include + + +namespace vmime { +namespace security { +namespace sasl { + + +builtinSASLMechanism::builtinSASLMechanism(shared_ptr 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 + (shared_ptr 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 (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; +} + + +void builtinSASLMechanism::encode + (shared_ptr 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 (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 (coutputLen); + } + catch (...) + { + gsasl_free(coutput); + throw; + } + + gsasl_free(coutput); +} + + +void builtinSASLMechanism::decode + (shared_ptr 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 (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 (coutputLen); + } + catch (...) + { + gsasl_free(coutput); + throw; + } + + gsasl_free(coutput); +} + + +} // sasl +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT + diff --git a/src/vmime/security/sasl/builtinSASLMechanism.hpp b/src/vmime/security/sasl/builtinSASLMechanism.hpp new file mode 100644 index 00000000..09b46f00 --- /dev/null +++ b/src/vmime/security/sasl/builtinSASLMechanism.hpp @@ -0,0 +1,93 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr ctx, const string& name); + ~builtinSASLMechanism(); + + + const string getName() const; + + bool step(shared_ptr sess, + const byte_t* challenge, const size_t challengeLen, + byte_t** response, size_t* responseLen); + + bool isComplete() const; + + void encode(shared_ptr sess, + const byte_t* input, const size_t inputLen, + byte_t** output, size_t* outputLen); + + void decode(shared_ptr sess, + const byte_t* input, const size_t inputLen, + byte_t** output, size_t* outputLen); + +private: + + /** SASL context */ + shared_ptr 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/src/vmime/security/sasl/defaultSASLAuthenticator.cpp b/src/vmime/security/sasl/defaultSASLAuthenticator.cpp new file mode 100644 index 00000000..7fe9b3eb --- /dev/null +++ b/src/vmime/security/sasl/defaultSASLAuthenticator.cpp @@ -0,0 +1,153 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 > + defaultSASLAuthenticator::getAcceptableMechanisms + (const std::vector >& available, + shared_ptr suggested) const +{ + if (suggested) + { + std::vector > 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::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(shared_ptr serv) +{ + m_service = serv; + m_default.setService(serv); +} + + +weak_ptr defaultSASLAuthenticator::getService() const +{ + return m_service; +} + + +void defaultSASLAuthenticator::setSASLSession(shared_ptr sess) +{ + m_saslSession = sess; +} + + +shared_ptr defaultSASLAuthenticator::getSASLSession() const +{ + return constCast (m_saslSession.lock()); +} + + +void defaultSASLAuthenticator::setSASLMechanism(shared_ptr mech) +{ + m_saslMech = mech; +} + + +shared_ptr defaultSASLAuthenticator::getSASLMechanism() const +{ + return m_saslMech; +} + + +} // sasl +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT + diff --git a/src/vmime/security/sasl/defaultSASLAuthenticator.hpp b/src/vmime/security/sasl/defaultSASLAuthenticator.hpp new file mode 100644 index 00000000..6ea9af80 --- /dev/null +++ b/src/vmime/security/sasl/defaultSASLAuthenticator.hpp @@ -0,0 +1,90 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 > getAcceptableMechanisms + (const std::vector >& available, + shared_ptr suggested) const; + + const string getUsername() const; + const string getPassword() const; + const string getHostname() const; + const string getAnonymousToken() const; + const string getServiceName() const; + + void setService(shared_ptr serv); + weak_ptr getService() const; + + void setSASLSession(shared_ptr sess); + shared_ptr getSASLSession() const; + + void setSASLMechanism(shared_ptr mech); + shared_ptr getSASLMechanism() const; + +private: + + defaultAuthenticator m_default; + + weak_ptr m_service; + weak_ptr m_saslSession; + shared_ptr m_saslMech; +}; + + +} // sasl +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_SASL_SUPPORT + +#endif // VMIME_SECURITY_SASL_DEFAULTSASLAUTHENTICATOR_HPP_INCLUDED + diff --git a/src/vmime/streamContentHandler.cpp b/src/vmime/streamContentHandler.cpp new file mode 100644 index 00000000..8676cc34 --- /dev/null +++ b/src/vmime/streamContentHandler.cpp @@ -0,0 +1,234 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(shared_ptr 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 streamContentHandler::clone() const +{ + return make_shared (*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(shared_ptr 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 theDecoder = m_encoding.getEncoder(); + shared_ptr 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 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 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 (m_stream) != NULL) + 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/src/vmime/streamContentHandler.hpp b/src/vmime/streamContentHandler.hpp new file mode 100644 index 00000000..9b72c073 --- /dev/null +++ b/src/vmime/streamContentHandler.hpp @@ -0,0 +1,122 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + (shared_ptr is, + const size_t length, + const vmime::encoding& enc = NO_ENCODING); + + ~streamContentHandler(); + + streamContentHandler(const streamContentHandler& cts); + streamContentHandler& operator=(const streamContentHandler& cts); + + shared_ptr 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 + (shared_ptr 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 m_stream; + size_t m_length; +}; + + +} // vmime + + +#endif // VMIME_STREAMCONTENTHANDLER_HPP_INCLUDED diff --git a/src/vmime/stringContentHandler.cpp b/src/vmime/stringContentHandler.cpp new file mode 100644 index 00000000..9a66663c --- /dev/null +++ b/src/vmime/stringContentHandler.cpp @@ -0,0 +1,236 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/inputStreamStringProxyAdapter.hpp" +#include "vmime/utility/outputStreamAdapter.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(const utility::stringProxy& str, const vmime::encoding& enc) + : m_encoding(enc), m_string(str) +{ +} + + +stringContentHandler::stringContentHandler(const string& buffer, const size_t start, + const size_t end, const vmime::encoding& enc) + : m_encoding(enc), m_string(buffer, start, end) +{ +} + + +stringContentHandler::~stringContentHandler() +{ +} + + +shared_ptr stringContentHandler::clone() const +{ + return make_shared (*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 utility::stringProxy& str, const vmime::encoding& enc) +{ + m_encoding = enc; + m_string = str; +} + + +void stringContentHandler::setData(const string& buffer, const vmime::encoding& enc) +{ + m_encoding = enc; + m_string.set(buffer); +} + + +void stringContentHandler::setData(const string& buffer, const size_t start, + const size_t end, const vmime::encoding& enc) +{ + m_encoding = enc; + m_string.set(buffer, start, end); +} + + +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 theDecoder = m_encoding.getEncoder(); + shared_ptr theEncoder = enc.getEncoder(); + + theEncoder->getProperties()["maxlinelength"] = maxLineLength; + theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT); + + utility::inputStreamStringProxyAdapter 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 + { + m_string.extract(os); + } + } + // Need to encode data before + else + { + shared_ptr theEncoder = enc.getEncoder(); + theEncoder->getProperties()["maxlinelength"] = maxLineLength; + theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT); + + utility::inputStreamStringProxyAdapter in(m_string); + + theEncoder->encode(in, os); + } +} + + +void stringContentHandler::extract(utility::outputStream& os, + utility::progressListener* progress) const +{ + // No decoding to perform + if (!isEncoded()) + { + m_string.extract(os, 0, m_string.length(), progress); + } + // Need to decode data + else + { + shared_ptr theDecoder = m_encoding.getEncoder(); + + utility::inputStreamStringProxyAdapter in(m_string); + utility::progressListenerSizeAdapter plsa(progress, getLength()); + + theDecoder->decode(in, os, &plsa); + } +} + + +void stringContentHandler::extractRaw(utility::outputStream& os, + utility::progressListener* progress) const +{ + m_string.extract(os, 0, 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/src/vmime/stringContentHandler.hpp b/src/vmime/stringContentHandler.hpp new file mode 100644 index 00000000..e9d34405 --- /dev/null +++ b/src/vmime/stringContentHandler.hpp @@ -0,0 +1,101 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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(const utility::stringProxy& str, const vmime::encoding& enc = NO_ENCODING); + stringContentHandler(const string& buffer, const size_t start, const size_t end, const vmime::encoding& enc = NO_ENCODING); + + ~stringContentHandler(); + + stringContentHandler(const stringContentHandler& cts); + stringContentHandler& operator=(const stringContentHandler& cts); + + shared_ptr clone() const; + + // Set the data contained in the body. + // + // The two first functions take advantage of the COW (copy-on-write) system that + // might be implemented into std::string. This is done using "stringProxy" object. + // + // Set "enc" parameter 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 utility::stringProxy& str, const vmime::encoding& enc = NO_ENCODING); + void setData(const string& buffer, const vmime::encoding& enc = NO_ENCODING); + void setData(const string& buffer, const size_t start, const size_t end, 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 + utility::stringProxy m_string; +}; + + +} // vmime + + +#endif // VMIME_STRINGCONTENTHANDLER_HPP_INCLUDED diff --git a/src/vmime/text.cpp b/src/vmime/text.cpp new file mode 100644 index 00000000..08fc9ba9 --- /dev/null +++ b/src/vmime/text.cpp @@ -0,0 +1,435 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 (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 > 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 (other); + + removeAllWords(); + + for (std::vector >::const_iterator i = t.m_words.begin() ; i != t.m_words.end() ; ++i) + m_words.push_back(make_shared (**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 >::const_iterator i = m_words.begin(); + std::vector >::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 >::const_iterator i = m_words.begin() ; i != m_words.end() ; ++i) + out += (*i)->getConvertedText(dest, opts); + + return (out); +} + + +void text::appendWord(shared_ptr w) +{ + m_words.push_back(w); +} + + +void text::insertWordBefore(const size_t pos, shared_ptr w) +{ + m_words.insert(m_words.begin() + pos, w); +} + + +void text::insertWordAfter(const size_t pos, shared_ptr w) +{ + m_words.insert(m_words.begin() + pos + 1, w); +} + + +void text::removeWord(const size_t pos) +{ + const std::vector >::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 text::getWordAt(const size_t pos) +{ + return (m_words[pos]); +} + + +const shared_ptr text::getWordAt(const size_t pos) const +{ + return (m_words[pos]); +} + + +const std::vector > text::getWordList() const +{ + std::vector > list; + + list.reserve(m_words.size()); + + for (std::vector >::const_iterator it = m_words.begin() ; + it != m_words.end() ; ++it) + { + list.push_back(*it); + } + + return (list); +} + + +const std::vector > text::getWordList() +{ + return (m_words); +} + + +shared_ptr text::clone() const +{ + return make_shared (*this); +} + + +shared_ptr text::newFromString(const string& in, const charset& ch) +{ + shared_ptr t = make_shared (); + + 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 (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 w = getWordAt(getWordCount() - 1); + w->getBuffer() += " " + chunk; + } + else + { + if (count) + { + shared_ptr w = getWordAt(getWordCount() - 1); + w->getBuffer() += ' '; + } + + appendWord(make_shared (chunk, ch)); + + prevIs8bit = true; + ++count; + } + } + else + { + if (count && !prevIs8bit) + { + shared_ptr w = getWordAt(getWordCount() - 1); + w->getBuffer() += " " + chunk; + } + else + { + appendWord(make_shared + (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::decodeAndUnfold(const string& in) +{ + shared_ptr t = make_shared (); + + decodeAndUnfold(parsingContext::getDefaultContext(), in, t.get()); + + return t; +} + + +shared_ptr text::decodeAndUnfold(const parsingContext& ctx, const string& in) +{ + shared_ptr t = make_shared (); + + 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 != NULL) ? generateInExisting : new text(); + + out->removeAllWords(); + + const std::vector > words = word::parseMultiple(ctx, in, 0, in.length(), NULL); + + copy_vector(words, out->m_words); + + return (out); +} + + +const std::vector > text::getChildComponents() +{ + std::vector > list; + + copy_vector(m_words, list); + + return (list); +} + + +const string text::getWholeBuffer() const +{ + string res; + + for (std::vector >::const_iterator it = m_words.begin() ; + it != m_words.end() ; ++it) + { + res += (*it)->getBuffer(); + } + + return res; +} + + +} // vmime diff --git a/src/vmime/text.hpp b/src/vmime/text.hpp new file mode 100644 index 00000000..b7e25669 --- /dev/null +++ b/src/vmime/text.hpp @@ -0,0 +1,277 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 clone() const; + void copyFrom(const component& other); + text& operator=(const component& other); + text& operator=(const text& other); + + const std::vector > getChildComponents(); + + /** Add a word at the end of the list. + * + * @param w word to append + */ + void appendWord(shared_ptr 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, shared_ptr 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, shared_ptr 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 getWordAt(const size_t pos); + + /** Return the word at the specified position. + * + * @param pos position + * @return word at position 'pos' + */ + const shared_ptr getWordAt(const size_t pos) const; + + /** Return the word list. + * + * @return list of words + */ + const std::vector > getWordList() const; + + /** Return the word list. + * + * @return list of words + */ + const std::vector > 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. + * + *

Eg: giving:

+ *
   <iso-8859-1> "Linux dans un t'el'ephone mobile"
+	  *    ("=?iso-8859-1?Q?Linux_dans_un_t=E9l=E9phone_mobile?=")
+	  * 

it will return:

+ *
   <us-ascii>   "Linux dans un "
+	  *    <iso-8859-1> "t'el'ephone "
+	  *    <us-ascii>   "mobile"
+	  *    ("Linux dans un =?iso-8859-1?Q?t=E9l=E9phone_?= mobile")
+	  * 
+ * + * @param in input string + * @param ch input charset + * @return new text object + */ + static shared_ptr 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. + * + *

Eg: giving:

+ *
   <iso-8859-1> "Linux dans un t'el'ephone mobile"
+	  *    ("=?iso-8859-1?Q?Linux_dans_un_t=E9l=E9phone_mobile?=")
+	  * 

it will return:

+ *
   <us-ascii>   "Linux dans un "
+	  *    <iso-8859-1> "t'el'ephone "
+	  *    <us-ascii>   "mobile"
+	  *    ("Linux dans un =?iso-8859-1?Q?t=E9l=E9phone_?= mobile")
+	  * 
+ * + * @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 decodeAndUnfold(const string& in); + + /** Decode and unfold text (RFC-2047). + * + * @param ctx parsingContext + * @param in input string + * @return new text object + */ + static shared_ptr 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: + + // 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 > m_words; +}; + + +} // vmime + + +#endif // VMIME_TEXT_HPP_INCLUDED diff --git a/src/vmime/textPart.hpp b/src/vmime/textPart.hpp new file mode 100644 index 00000000..6348f8d7 --- /dev/null +++ b/src/vmime/textPart.hpp @@ -0,0 +1,112 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 getText() const = 0; + + /** Set the text contained in the part. + * + * @param text text of the part + */ + virtual void setText(shared_ptr 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(shared_ptr message, shared_ptr 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(shared_ptr message, shared_ptr parent, shared_ptr textPart) = 0; +}; + + +} // vmime + + +#endif // VMIME_TEXTPART_HPP_INCLUDED diff --git a/src/vmime/textPartFactory.cpp b/src/vmime/textPartFactory.cpp new file mode 100644 index 00000000..85fea6e4 --- /dev/null +++ b/src/vmime/textPartFactory.cpp @@ -0,0 +1,69 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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() +{ + // Register some default names + registerType (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); + registerType (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML)); +} + + +textPartFactory::~textPartFactory() +{ +} + + +textPartFactory* textPartFactory::getInstance() +{ + static textPartFactory instance; + return (&instance); +} + + +shared_ptr 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(); +} + + +} // vmime diff --git a/src/vmime/textPartFactory.hpp b/src/vmime/textPartFactory.hpp new file mode 100644 index 00000000..f5ce3774 --- /dev/null +++ b/src/vmime/textPartFactory.hpp @@ -0,0 +1,79 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 (*AllocFunc)(void); + typedef std::vector > MapType; + + MapType m_map; + +#ifndef VMIME_BUILDING_DOC + template + class registerer + { + public: + + static shared_ptr creator() + { + // Allocate a new object + return vmime::make_shared (); + } + }; +#endif // VMIME_BUILDING_DOC + +public: + + static textPartFactory* getInstance(); + + template + void registerType(const mediaType& type) + { + m_map.push_back(MapType::value_type(type, ®isterer::creator)); + } + + shared_ptr create(const mediaType& type); +}; + + +} // vmime + + +#endif // VMIME_TEXTPARTFACTORY_HPP_INCLUDED diff --git a/src/vmime/types.hpp b/src/vmime/types.hpp new file mode 100644 index 00000000..12e5bf71 --- /dev/null +++ b/src/vmime/types.hpp @@ -0,0 +1,115 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 +#include +#include +#include +#include +#include + +#include "vmime/config.hpp" + + +#ifndef VMIME_BUILDING_DOC + +#if VMIME_SHARED_PTR_USE_CXX + // If we are compiling with C++11, use shared_ptr<> from the standard lib + #include + + #define VMIME_SHARED_PTR_NAMESPACE std +#elif VMIME_SHARED_PTR_USE_BOOST + // Else, use boost's shared_ptr<> + #include + #include + #include + #include + #include + + #define VMIME_SHARED_PTR_NAMESPACE boost +#else + #error Either VMIME_SHAREDPTR_USE_CXX or VMIME_SHAREDPTR_USE_BOOST must be set to ON +#endif + +namespace vmime +{ + using VMIME_SHARED_PTR_NAMESPACE::shared_ptr; + using VMIME_SHARED_PTR_NAMESPACE::weak_ptr; + using VMIME_SHARED_PTR_NAMESPACE::make_shared; + using VMIME_SHARED_PTR_NAMESPACE::enable_shared_from_this; + using VMIME_SHARED_PTR_NAMESPACE::dynamic_pointer_cast; + using VMIME_SHARED_PTR_NAMESPACE::const_pointer_cast; + + /** Custom deleter to be used with shared_ptr. + * This is does not actually delete the pointer, and is used + * only for the singleton classes allocated on the stack. + */ + template + struct noop_shared_ptr_deleter + { + void operator()(T*) const {} + }; +} + +#undef VMIME_SHARED_PTR_NAMESPACE + +#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 byteArray; + + typedef std::size_t size_t; + + // For compatibility with versions <= 0.7.1 (deprecated) + namespace net { } + namespace messaging = net; + + // For (minimal) compatibility with legacy smart pointers (<= 0.9.1) + // Your compiler must have support for C++11 +#if VMIME_COMPAT_LEGACY_SMART_POINTERS + template using ref = shared_ptr ; + class creator {}; // unused + template + inline shared_ptr create(Args&&... args) { return make_shared (args...); } +#endif + +} + + +#include "vmime/object.hpp" + + +#endif // VMIME_TYPES_HPP_INCLUDED diff --git a/src/vmime/utility/childProcess.hpp b/src/vmime/utility/childProcess.hpp new file mode 100644 index 00000000..ebefcf0a --- /dev/null +++ b/src/vmime/utility/childProcess.hpp @@ -0,0 +1,107 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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 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 getStdIn() = 0; + + /** Return a wrapper to the child process standard output. + * + * @return input stream wrapper for child's stdout + */ + virtual shared_ptr 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 create(const utility::file::path& path) const = 0; +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_CHILDPROCESS_HPP_INCLUDED + diff --git a/src/vmime/utility/datetimeUtils.cpp b/src/vmime/utility/datetimeUtils.cpp new file mode 100644 index 00000000..2b55177e --- /dev/null +++ b/src/vmime/utility/datetimeUtils.cpp @@ -0,0 +1,333 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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/src/vmime/utility/datetimeUtils.hpp b/src/vmime/utility/datetimeUtils.hpp new file mode 100644 index 00000000..a7291bb8 --- /dev/null +++ b/src/vmime/utility/datetimeUtils.hpp @@ -0,0 +1,99 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/encoder/b64Encoder.cpp b/src/vmime/utility/encoder/b64Encoder.cpp new file mode 100644 index 00000000..274c23c0 --- /dev/null +++ b/src/vmime/utility/encoder/b64Encoder.cpp @@ -0,0 +1,330 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 b64Encoder::getAvailableProperties() const +{ + std::vector 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 (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 ("maxlinelength", static_cast (-1)); + + const bool cutLines = (propMaxLineLength != static_cast (-1)); + const size_t maxLineLength = std::min(propMaxLineLength, static_cast (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; + } + } + } + + // Decode the bytes + byte_t c1 = bytes[0]; + byte_t c2 = bytes[1]; + + if (c1 == '=' || c2 == '=') // end + break; + + output[0] = static_cast ((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 (((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 (((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 ("maxlinelength", static_cast (-1)); + + const bool cutLines = (propMaxLineLength != static_cast (-1)); + const size_t maxLineLength = std::min(propMaxLineLength, static_cast (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/src/vmime/utility/encoder/b64Encoder.hpp b/src/vmime/utility/encoder/b64Encoder.hpp new file mode 100644 index 00000000..2d23d9e3 --- /dev/null +++ b/src/vmime/utility/encoder/b64Encoder.hpp @@ -0,0 +1,65 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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/src/vmime/utility/encoder/binaryEncoder.cpp b/src/vmime/utility/encoder/binaryEncoder.cpp new file mode 100644 index 00000000..7d7c40d1 --- /dev/null +++ b/src/vmime/utility/encoder/binaryEncoder.cpp @@ -0,0 +1,39 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/encoder/binaryEncoder.hpp b/src/vmime/utility/encoder/binaryEncoder.hpp new file mode 100644 index 00000000..1c831939 --- /dev/null +++ b/src/vmime/utility/encoder/binaryEncoder.hpp @@ -0,0 +1,52 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/encoder/eightBitEncoder.cpp b/src/vmime/utility/encoder/eightBitEncoder.cpp new file mode 100644 index 00000000..4ab07f06 --- /dev/null +++ b/src/vmime/utility/encoder/eightBitEncoder.cpp @@ -0,0 +1,39 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/encoder/eightBitEncoder.hpp b/src/vmime/utility/encoder/eightBitEncoder.hpp new file mode 100644 index 00000000..ee50ca95 --- /dev/null +++ b/src/vmime/utility/encoder/eightBitEncoder.hpp @@ -0,0 +1,52 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/encoder/encoder.cpp b/src/vmime/utility/encoder/encoder.cpp new file mode 100644 index 00000000..b4b13249 --- /dev/null +++ b/src/vmime/utility/encoder/encoder.cpp @@ -0,0 +1,76 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 encoder::getAvailableProperties() const +{ + std::vector list; + return (list); +} + + +} // encoder +} // utility +} // vmime diff --git a/src/vmime/utility/encoder/encoder.hpp b/src/vmime/utility/encoder/encoder.hpp new file mode 100644 index 00000000..34cd10b7 --- /dev/null +++ b/src/vmime/utility/encoder/encoder.hpp @@ -0,0 +1,128 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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/src/vmime/utility/encoder/encoderFactory.cpp b/src/vmime/utility/encoder/encoderFactory.cpp new file mode 100644 index 00000000..098a810a --- /dev/null +++ b/src/vmime/utility/encoder/encoderFactory.cpp @@ -0,0 +1,120 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 ("base64"); + registerName ("quoted-printable"); + registerName ("uuencode"); + registerName ("7bit"); + registerName ("8bit"); + registerName ("binary"); + + // Also register some non-standard encoding names + registerName ("7-bit"); + registerName ("8-bit"); + + // Finally, register some bogus encoding names, for compatibility + registerName ("bmoted-printable"); +} + + +encoderFactory::~encoderFactory() +{ +} + + +shared_ptr encoderFactory::getInstance() +{ + static encoderFactory instance; + return shared_ptr (&instance, noop_shared_ptr_deleter ()); +} + + +shared_ptr encoderFactory::create(const string& name) +{ + return (getEncoderByName(name)->create()); +} + + +const shared_ptr encoderFactory::getEncoderByName(const string& name) const +{ + const string lcName(utility::stringUtils::toLower(name)); + + for (std::vector >::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 encoderFactory::getEncoderAt(const size_t pos) const +{ + return (m_encoders[pos]); +} + + +const std::vector > encoderFactory::getEncoderList() const +{ + std::vector > res; + + for (std::vector >::const_iterator it = m_encoders.begin() ; + it != m_encoders.end() ; ++it) + { + res.push_back(*it); + } + + return (res); +} + + +} // encoder +} // utility +} // vmime diff --git a/src/vmime/utility/encoder/encoderFactory.hpp b/src/vmime/utility/encoder/encoderFactory.hpp new file mode 100644 index 00000000..763cbd5c --- /dev/null +++ b/src/vmime/utility/encoder/encoderFactory.hpp @@ -0,0 +1,148 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 getInstance(); + + /** Information about a registered encoder. */ + class VMIME_EXPORT registeredEncoder : public object + { + protected: + + virtual ~registeredEncoder() { } + + public: + + virtual shared_ptr create() const = 0; + + virtual const string& getName() const = 0; + }; + +private: + + template + class registeredEncoderImpl : public registeredEncoder + { + public: + + registeredEncoderImpl(const string& name) : m_name(name) { } + + shared_ptr create() const + { + return vmime::make_shared (); + } + + const string& getName() const + { + return (m_name); + } + + private: + + const string m_name; + }; + + + std::vector > m_encoders; + +public: + + /** Register a new encoder by its encoding name. + * + * @param name encoding name + */ + template + void registerName(const string& name) + { + m_encoders.push_back(vmime::make_shared >(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 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 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 getEncoderAt(const size_t pos) const; + + /** Return a list of all registered encoders. + * + * @return list of registered encoders + */ + const std::vector > getEncoderList() const; +}; + + +} // encoder +} // utility +} // vmime + + +#endif // VMIME_UTILITY_ENCODER_ENCODERFACTORY_HPP_INCLUDED diff --git a/src/vmime/utility/encoder/noopEncoder.cpp b/src/vmime/utility/encoder/noopEncoder.cpp new file mode 100644 index 00000000..3d991b5d --- /dev/null +++ b/src/vmime/utility/encoder/noopEncoder.cpp @@ -0,0 +1,87 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/encoder/noopEncoder.hpp b/src/vmime/utility/encoder/noopEncoder.hpp new file mode 100644 index 00000000..6314812b --- /dev/null +++ b/src/vmime/utility/encoder/noopEncoder.hpp @@ -0,0 +1,58 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/encoder/qpEncoder.cpp b/src/vmime/utility/encoder/qpEncoder.cpp new file mode 100644 index 00000000..c77b5163 --- /dev/null +++ b/src/vmime/utility/encoder/qpEncoder.cpp @@ -0,0 +1,558 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 qpEncoder::getAvailableProperties() const +{ + std::vector 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: . " +// +// 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 (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 ("maxlinelength", static_cast (-1)); + + const bool rfc2047 = getProperties().getProperty ("rfc2047", false); + const bool text = getProperties().getProperty ("text", false); // binary mode by default + + const bool cutLines = (propMaxLineLength != static_cast (-1)); + const size_t maxLineLength = std::min(propMaxLineLength, static_cast (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 (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; + } + // 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 ("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 + (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; + } + + // no break here... + } + default: + { + outBuffer[outBufferPos++] = c; + } + + } + + 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 ("maxlinelength", static_cast (-1)); + + const bool cutLines = (propMaxLineLength != static_cast (-1)); + const size_t maxLineLength = std::min(propMaxLineLength, static_cast (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/src/vmime/utility/encoder/qpEncoder.hpp b/src/vmime/utility/encoder/qpEncoder.hpp new file mode 100644 index 00000000..c666795b --- /dev/null +++ b/src/vmime/utility/encoder/qpEncoder.hpp @@ -0,0 +1,69 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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/src/vmime/utility/encoder/sevenBitEncoder.cpp b/src/vmime/utility/encoder/sevenBitEncoder.cpp new file mode 100644 index 00000000..7c76d73f --- /dev/null +++ b/src/vmime/utility/encoder/sevenBitEncoder.cpp @@ -0,0 +1,39 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/encoder/sevenBitEncoder.hpp b/src/vmime/utility/encoder/sevenBitEncoder.hpp new file mode 100644 index 00000000..d260cc7b --- /dev/null +++ b/src/vmime/utility/encoder/sevenBitEncoder.hpp @@ -0,0 +1,52 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/encoder/uuEncoder.cpp b/src/vmime/utility/encoder/uuEncoder.cpp new file mode 100644 index 00000000..0375a397 --- /dev/null +++ b/src/vmime/utility/encoder/uuEncoder.cpp @@ -0,0 +1,344 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 uuEncoder::getAvailableProperties() const +{ + std::vector 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 ((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 ("filename", ""); + const string propMode = getProperties().getProperty ("mode", "644"); + + const size_t maxLineLength = + std::min(getProperties().getProperty ("maxlinelength", 46), static_cast (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 (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 (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 (3)); + + switch (n) + { + default: + case 3: outBuffer[j + 2] = static_cast (UUDECODE(c3) << 6 | UUDECODE(c4)); + case 2: outBuffer[j + 1] = static_cast (UUDECODE(c2) << 4 | UUDECODE(c3) >> 2); + case 1: outBuffer[j] = static_cast (UUDECODE(c1) << 2 | UUDECODE(c2) >> 4); + case 0: break; + } + + 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/src/vmime/utility/encoder/uuEncoder.hpp b/src/vmime/utility/encoder/uuEncoder.hpp new file mode 100644 index 00000000..7365263c --- /dev/null +++ b/src/vmime/utility/encoder/uuEncoder.hpp @@ -0,0 +1,60 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 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/src/vmime/utility/file.hpp b/src/vmime/utility/file.hpp new file mode 100644 index 00000000..c0ba2c5b --- /dev/null +++ b/src/vmime/utility/file.hpp @@ -0,0 +1,269 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 nextElement() = 0; +}; + + +/** Write to a file. + */ + +class VMIME_EXPORT fileWriter : public object +{ +public: + + virtual ~fileWriter() { } + + virtual shared_ptr getOutputStream() = 0; +}; + + +/** Read from a file. + */ + +class VMIME_EXPORT fileReader : public object +{ +public: + + virtual ~fileReader() { } + + virtual shared_ptr 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 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 getFileWriter() = 0; + + /** Return an object capable of reading from this file. + * + * @return file reader object + */ + virtual shared_ptr 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 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 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/src/vmime/utility/filteredStream.cpp b/src/vmime/utility/filteredStream.cpp new file mode 100644 index 00000000..bb705162 --- /dev/null +++ b/src/vmime/utility/filteredStream.cpp @@ -0,0 +1,391 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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; + + // Replace "\n.." with "\n." + while (readPtr < end) + { + if (*readPtr == '.') + { + const byte_t prevChar2 = + (readPtr == data + 1 ? m_previousChar1 : + readPtr == data ? m_previousChar2 : *(readPtr - 2)); + const byte_t prevChar1 = + (readPtr == data ? m_previousChar1 : *(readPtr - 1)); + + if (prevChar2 == '\n' && prevChar1 == '.') + { + // Ignore last dot + } + else + { + *writePtr = *readPtr; + + ++writePtr; + ++written; + } + } + else + { + *writePtr = *readPtr; + + ++writePtr; + ++written; + } + + ++readPtr; + } + + m_previousChar2 = (read >= 2 ? data[read - 2] : m_previousChar1); + m_previousChar1 = (read >= 1 ? data[read - 1] : '\0'); + + 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 + 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) // 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(); +} + + +// 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 +} + + +// 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(); +} + + +// 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/src/vmime/utility/filteredStream.hpp b/src/vmime/utility/filteredStream.hpp new file mode 100644 index 00000000..c60373b9 --- /dev/null +++ b/src/vmime/utility/filteredStream.hpp @@ -0,0 +1,406 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + +#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(); + +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(); + +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(); + +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 +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 (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); + + 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); + + +template +size_t stopSequenceFilteredInputStream ::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; +} + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_FILTEREDSTREAM_HPP_INCLUDED + diff --git a/src/vmime/utility/inputStream.cpp b/src/vmime/utility/inputStream.cpp new file mode 100644 index 00000000..a7d6bc0f --- /dev/null +++ b/src/vmime/utility/inputStream.cpp @@ -0,0 +1,33 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/inputStream.hpp b/src/vmime/utility/inputStream.hpp new file mode 100644 index 00000000..809996ce --- /dev/null +++ b/src/vmime/utility/inputStream.hpp @@ -0,0 +1,76 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/inputStreamAdapter.cpp b/src/vmime/utility/inputStreamAdapter.cpp new file mode 100644 index 00000000..c0b06be4 --- /dev/null +++ b/src/vmime/utility/inputStreamAdapter.cpp @@ -0,0 +1,83 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 (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/src/vmime/utility/inputStreamAdapter.hpp b/src/vmime/utility/inputStreamAdapter.hpp new file mode 100644 index 00000000..dd761736 --- /dev/null +++ b/src/vmime/utility/inputStreamAdapter.hpp @@ -0,0 +1,66 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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/src/vmime/utility/inputStreamByteBufferAdapter.cpp b/src/vmime/utility/inputStreamByteBufferAdapter.cpp new file mode 100644 index 00000000..c270ea56 --- /dev/null +++ b/src/vmime/utility/inputStreamByteBufferAdapter.cpp @@ -0,0 +1,103 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/inputStreamByteBufferAdapter.hpp b/src/vmime/utility/inputStreamByteBufferAdapter.hpp new file mode 100644 index 00000000..f201f433 --- /dev/null +++ b/src/vmime/utility/inputStreamByteBufferAdapter.hpp @@ -0,0 +1,65 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/inputStreamPointerAdapter.cpp b/src/vmime/utility/inputStreamPointerAdapter.cpp new file mode 100644 index 00000000..6bf0461a --- /dev/null +++ b/src/vmime/utility/inputStreamPointerAdapter.cpp @@ -0,0 +1,46 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/src/vmime/utility/inputStreamPointerAdapter.hpp b/src/vmime/utility/inputStreamPointerAdapter.hpp new file mode 100644 index 00000000..4fc606a9 --- /dev/null +++ b/src/vmime/utility/inputStreamPointerAdapter.hpp @@ -0,0 +1,63 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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 + + +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/src/vmime/utility/inputStreamSocketAdapter.cpp b/src/vmime/utility/inputStreamSocketAdapter.cpp new file mode 100644 index 00000000..d78855eb --- /dev/null +++ b/src/vmime/utility/inputStreamSocketAdapter.cpp @@ -0,0 +1,82 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/inputStreamSocketAdapter.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES + + +#include "vmime/net/socket.hpp" + + +namespace vmime { +namespace utility { + + +inputStreamSocketAdapter::inputStreamSocketAdapter(net::socket& sok) + : m_socket(sok) +{ +} + + +bool inputStreamSocketAdapter::eof() const +{ + // Can't know... + return false; +} + + +void inputStreamSocketAdapter::reset() +{ + // Not supported +} + + +size_t inputStreamSocketAdapter::read + (byte_t* const data, const size_t count) +{ + return m_socket.receiveRaw(data, count); +} + + +size_t inputStreamSocketAdapter::skip + (const size_t /* count */) +{ + // Not supported + return 0; +} + + +size_t inputStreamSocketAdapter::getBlockSize() +{ + return m_socket.getBlockSize(); +} + + +} // utility +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + diff --git a/src/vmime/utility/inputStreamSocketAdapter.hpp b/src/vmime/utility/inputStreamSocketAdapter.hpp new file mode 100644 index 00000000..a990f628 --- /dev/null +++ b/src/vmime/utility/inputStreamSocketAdapter.hpp @@ -0,0 +1,77 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_INPUTSTREAMSOCKETADAPTER_HPP_INCLUDED +#define VMIME_UTILITY_INPUTSTREAMSOCKETADAPTER_HPP_INCLUDED + + +#include "vmime/utility/inputStream.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES + + +namespace vmime { +namespace net { + class socket; // forward reference +} // net +} // vmime + + +namespace vmime { +namespace utility { + + +/** An input stream that is connected to a socket. + */ + +class VMIME_EXPORT inputStreamSocketAdapter : public inputStream +{ +public: + + inputStreamSocketAdapter(net::socket& sok); + + 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 getBlockSize(); + +private: + + inputStreamSocketAdapter(const inputStreamSocketAdapter&); + + net::socket& m_socket; +}; + + +} // utility +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + + +#endif // VMIME_UTILITY_INPUTSTREAMSOCKETADAPTER_HPP_INCLUDED + diff --git a/src/vmime/utility/inputStreamStringAdapter.cpp b/src/vmime/utility/inputStreamStringAdapter.cpp new file mode 100644 index 00000000..9b897b97 --- /dev/null +++ b/src/vmime/utility/inputStreamStringAdapter.cpp @@ -0,0 +1,107 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/inputStreamStringAdapter.hpp" + + +namespace vmime { +namespace utility { + + +inputStreamStringAdapter::inputStreamStringAdapter(const string& buffer) + : m_buffer(buffer), m_begin(0), m_end(buffer.length()), m_pos(0) +{ +} + + +inputStreamStringAdapter::inputStreamStringAdapter(const string& buffer, + const size_t begin, const size_t end) + : m_buffer(buffer), m_begin(begin), m_end(end), m_pos(begin) +{ +} + + +bool inputStreamStringAdapter::eof() const +{ + return (m_pos >= m_end); +} + + +void inputStreamStringAdapter::reset() +{ + m_pos = m_begin; +} + + +size_t inputStreamStringAdapter::read + (byte_t* const data, const size_t count) +{ + if (m_pos + count >= m_end) + { + const size_t remaining = m_end - m_pos; + + std::copy(m_buffer.begin() + m_pos, m_buffer.end(), data); + m_pos = m_end; + return (remaining); + } + else + { + std::copy(m_buffer.begin() + m_pos, m_buffer.begin() + m_pos + count, data); + m_pos += count; + return (count); + } +} + + +size_t inputStreamStringAdapter::skip(const size_t count) +{ + if (m_pos + count >= m_end) + { + const size_t remaining = m_end - m_pos; + m_pos = m_end; + return (remaining); + } + else + { + m_pos += count; + return (count); + } +} + + +size_t inputStreamStringAdapter::getPosition() const +{ + return m_pos - m_begin; +} + + +void inputStreamStringAdapter::seek(const size_t pos) +{ + if (m_begin + pos <= m_end) + m_pos = m_begin + pos; +} + + +} // utility +} // vmime + diff --git a/src/vmime/utility/inputStreamStringAdapter.hpp b/src/vmime/utility/inputStreamStringAdapter.hpp new file mode 100644 index 00000000..4ee597e6 --- /dev/null +++ b/src/vmime/utility/inputStreamStringAdapter.hpp @@ -0,0 +1,68 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_INPUTSTREAMSTRINGADAPTER_HPP_INCLUDED +#define VMIME_UTILITY_INPUTSTREAMSTRINGADAPTER_HPP_INCLUDED + + +#include "vmime/utility/seekableInputStream.hpp" + + +namespace vmime { +namespace utility { + + +/** An adapter class for string input. + */ + +class VMIME_EXPORT inputStreamStringAdapter : public seekableInputStream +{ +public: + + inputStreamStringAdapter(const string& buffer); + inputStreamStringAdapter(const string& buffer, const size_t begin, const size_t end); + + 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: + + inputStreamStringAdapter(const inputStreamStringAdapter&); + + const string m_buffer; // do _NOT_ keep a reference... + const size_t m_begin; + const size_t m_end; + size_t m_pos; +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_INPUTSTREAMSTRINGADAPTER_HPP_INCLUDED + diff --git a/src/vmime/utility/inputStreamStringProxyAdapter.cpp b/src/vmime/utility/inputStreamStringProxyAdapter.cpp new file mode 100644 index 00000000..5513de80 --- /dev/null +++ b/src/vmime/utility/inputStreamStringProxyAdapter.cpp @@ -0,0 +1,102 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/inputStreamStringProxyAdapter.hpp" +#include "vmime/utility/stringProxy.hpp" + + +namespace vmime { +namespace utility { + + +inputStreamStringProxyAdapter::inputStreamStringProxyAdapter(const stringProxy& buffer) + : m_buffer(buffer), m_pos(0) +{ +} + + +bool inputStreamStringProxyAdapter::eof() const +{ + return (m_pos >= m_buffer.length()); +} + + +void inputStreamStringProxyAdapter::reset() +{ + m_pos = 0; +} + + +size_t inputStreamStringProxyAdapter::read + (byte_t* const data, const size_t count) +{ + const size_t remaining = m_buffer.length() - m_pos; + + if (count > remaining) + { + std::copy(m_buffer.it_begin() + m_pos, m_buffer.it_end(), data); + m_pos = m_buffer.length(); + return (remaining); + } + else + { + std::copy(m_buffer.it_begin() + m_pos, m_buffer.it_begin() + m_pos + count, data); + m_pos += count; + return (count); + } +} + + +size_t inputStreamStringProxyAdapter::skip(const size_t count) +{ + const size_t remaining = m_buffer.length() - m_pos; + + if (count > remaining) + { + m_pos = m_buffer.length(); + return (remaining); + } + else + { + m_pos += count; + return (count); + } +} + + +size_t inputStreamStringProxyAdapter::getPosition() const +{ + return m_pos; +} + + +void inputStreamStringProxyAdapter::seek(const size_t pos) +{ + if (pos <= m_buffer.length()) + m_pos = pos; +} + + +} // utility +} // vmime + diff --git a/src/vmime/utility/inputStreamStringProxyAdapter.hpp b/src/vmime/utility/inputStreamStringProxyAdapter.hpp new file mode 100644 index 00000000..02dc2056 --- /dev/null +++ b/src/vmime/utility/inputStreamStringProxyAdapter.hpp @@ -0,0 +1,70 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_INPUTSTREAMSTRINGPROXYADAPTER_HPP_INCLUDED +#define VMIME_UTILITY_INPUTSTREAMSTRINGPROXYADAPTER_HPP_INCLUDED + + +#include "vmime/utility/seekableInputStream.hpp" + + +namespace vmime { +namespace utility { + + +class stringProxy; + + +/** An adapter class for stringProxy input. + */ + +class VMIME_EXPORT inputStreamStringProxyAdapter : public seekableInputStream +{ +public: + + /** @param buffer stringProxy object to wrap + */ + inputStreamStringProxyAdapter(const stringProxy& buffer); + + 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: + + inputStreamStringProxyAdapter(const inputStreamStringProxyAdapter&); + + const stringProxy& m_buffer; + size_t m_pos; +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_INPUTSTREAMSTRINGPROXYADAPTER_HPP_INCLUDED + diff --git a/src/vmime/utility/outputStream.cpp b/src/vmime/utility/outputStream.cpp new file mode 100644 index 00000000..070e28c5 --- /dev/null +++ b/src/vmime/utility/outputStream.cpp @@ -0,0 +1,45 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/outputStream.hpp" + + +namespace vmime { +namespace utility { + + +void outputStream::write(const byte_t* const data, const size_t count) +{ + writeImpl(data, count); +} + + +void outputStream::write(const char* const data, const size_t count) +{ + writeImpl(reinterpret_cast (data), count); +} + + +} // utility +} // vmime + diff --git a/src/vmime/utility/outputStream.hpp b/src/vmime/utility/outputStream.hpp new file mode 100644 index 00000000..62ee7336 --- /dev/null +++ b/src/vmime/utility/outputStream.hpp @@ -0,0 +1,136 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_OUTPUTSTREAM_HPP_INCLUDED +#define VMIME_UTILITY_OUTPUTSTREAM_HPP_INCLUDED + + +#include "vmime/utility/stream.hpp" + + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) // VC++6 +# include +#endif + + +namespace vmime { +namespace utility { + + +/** Simple output stream. + */ + +class VMIME_EXPORT outputStream : public stream +{ +public: + + /** Write data to the stream. + * + * @param data buffer containing data to write + * @param count number of bytes to write + */ + void write(const byte_t* const data, const size_t count); + + /** Write data to the stream. + * + * @param data buffer containing data to write + * @param count number of bytes to write + */ + void write(const char* const data, const size_t count); + + /** Write data to the stream. + * + * @param data buffer containing data to write + * @param N number of bytes to write, including terminating + * null (value is induced by compiler) + */ + template + void write(const char (&data)[N]) + { + write(data, N - 1); + } + + /** Flush this output stream and forces any buffered output + * bytes to be written out to the stream. + */ + virtual void flush() = 0; + +protected: + + /** Write data to the stream. + * This is the method to be implemented is subclasses. + * + * @param data buffer containing data to write + * @param count number of bytes to write + */ + virtual void writeImpl(const byte_t* const data, const size_t count) = 0; +}; + + +// Helpers functions + +VMIME_EXPORT outputStream& operator<<(outputStream& os, const string& str); +VMIME_EXPORT outputStream& operator<<(outputStream& os, const byte_t c); + + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) // Internal compiler error with VC++6 + +inline outputStream& operator<<(outputStream& os, const char* str) +{ + os.write(reinterpret_cast (str), ::strlen(str)); + return (os); +} + +#else + +template +outputStream& operator<<(outputStream& os, const char (&str)[N]) +{ + os.write(reinterpret_cast (str), N - 1); + return (os); +} + +#endif // defined(_MSC_VER) && (_MSC_VER <= 1200) + + +template +outputStream& operator<<(outputStream& os, const T& t) +{ + std::ostringstream oss; + oss.imbue(std::locale::classic()); // no formatting + + oss << t; + + os << oss.str(); + + return (os); +} + + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_OUTPUTSTREAM_HPP_INCLUDED + diff --git a/src/vmime/utility/outputStreamAdapter.cpp b/src/vmime/utility/outputStreamAdapter.cpp new file mode 100644 index 00000000..ed90c7d3 --- /dev/null +++ b/src/vmime/utility/outputStreamAdapter.cpp @@ -0,0 +1,54 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/outputStreamAdapter.hpp" + + +namespace vmime { +namespace utility { + + +outputStreamAdapter::outputStreamAdapter(std::ostream& os) + : m_stream(os) +{ +} + + +void outputStreamAdapter::writeImpl + (const byte_t* const data, const size_t count) +{ + m_stream.exceptions(std::ios_base::badbit); + m_stream.write(reinterpret_cast (data), count); +} + + +void outputStreamAdapter::flush() +{ + m_stream.exceptions(std::ios_base::badbit); + m_stream.flush(); +} + + +} // utility +} // vmime + diff --git a/src/vmime/utility/outputStreamAdapter.hpp b/src/vmime/utility/outputStreamAdapter.hpp new file mode 100644 index 00000000..f0125584 --- /dev/null +++ b/src/vmime/utility/outputStreamAdapter.hpp @@ -0,0 +1,65 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_OUTPUTSTREAMADAPTER_HPP_INCLUDED +#define VMIME_UTILITY_OUTPUTSTREAMADAPTER_HPP_INCLUDED + + +#include "vmime/utility/outputStream.hpp" + +#include + + +namespace vmime { +namespace utility { + + +/** An adapter class for C++ standard output streams. + */ + +class VMIME_EXPORT outputStreamAdapter : public outputStream +{ +public: + + /** @param os output stream to wrap + */ + outputStreamAdapter(std::ostream& os); + + void flush(); + +protected: + + void writeImpl(const byte_t* const data, const size_t count); + +private: + + std::ostream& m_stream; +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_OUTPUTSTREAMADAPTER_HPP_INCLUDED + diff --git a/src/vmime/utility/outputStreamByteArrayAdapter.cpp b/src/vmime/utility/outputStreamByteArrayAdapter.cpp new file mode 100644 index 00000000..1bed735b --- /dev/null +++ b/src/vmime/utility/outputStreamByteArrayAdapter.cpp @@ -0,0 +1,52 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/outputStreamByteArrayAdapter.hpp" + + +namespace vmime { +namespace utility { + + +outputStreamByteArrayAdapter::outputStreamByteArrayAdapter(byteArray& array) + : m_array(array) +{ +} + + +void outputStreamByteArrayAdapter::writeImpl + (const byte_t* const data, const size_t count) +{ + m_array.insert(m_array.end(), data, data + count); +} + + +void outputStreamByteArrayAdapter::flush() +{ + // Do nothing +} + + +} // utility +} // vmime + diff --git a/src/vmime/utility/outputStreamByteArrayAdapter.hpp b/src/vmime/utility/outputStreamByteArrayAdapter.hpp new file mode 100644 index 00000000..a2178a9c --- /dev/null +++ b/src/vmime/utility/outputStreamByteArrayAdapter.hpp @@ -0,0 +1,61 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_OUTPUTSTREAMBYTEARRAYADAPTER_HPP_INCLUDED +#define VMIME_UTILITY_OUTPUTSTREAMBYTEARRAYADAPTER_HPP_INCLUDED + + +#include "vmime/utility/outputStream.hpp" + + +namespace vmime { +namespace utility { + + +/** An adapter class for byte array output. + */ + +class VMIME_EXPORT outputStreamByteArrayAdapter : public outputStream +{ +public: + + outputStreamByteArrayAdapter(byteArray& array); + + void flush(); + +protected: + + void writeImpl(const byte_t* const data, const size_t count); + +private: + + byteArray& m_array; +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_OUTPUTSTREAMBYTEARRAYADAPTER_HPP_INCLUDED + diff --git a/src/vmime/utility/outputStreamSocketAdapter.cpp b/src/vmime/utility/outputStreamSocketAdapter.cpp new file mode 100644 index 00000000..03194497 --- /dev/null +++ b/src/vmime/utility/outputStreamSocketAdapter.cpp @@ -0,0 +1,68 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/outputStreamSocketAdapter.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES + + +#include "vmime/net/socket.hpp" + + +namespace vmime { +namespace utility { + + +outputStreamSocketAdapter::outputStreamSocketAdapter(net::socket& sok) + : m_socket(sok) +{ +} + + +void outputStreamSocketAdapter::writeImpl + (const byte_t* const data, const size_t count) +{ + m_socket.sendRaw(data, count); +} + + +void outputStreamSocketAdapter::flush() +{ + // Do nothing +} + + +size_t outputStreamSocketAdapter::getBlockSize() +{ + return m_socket.getBlockSize(); +} + + + +} // utility +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + diff --git a/src/vmime/utility/outputStreamSocketAdapter.hpp b/src/vmime/utility/outputStreamSocketAdapter.hpp new file mode 100644 index 00000000..6cd00626 --- /dev/null +++ b/src/vmime/utility/outputStreamSocketAdapter.hpp @@ -0,0 +1,78 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_OUTPUTSTREAMSOCKETADAPTER_HPP_INCLUDED +#define VMIME_UTILITY_OUTPUTSTREAMSOCKETADAPTER_HPP_INCLUDED + + +#include "vmime/utility/outputStream.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES + + +namespace vmime { +namespace net { + class socket; // forward reference +} // net +} // vmime + + +namespace vmime { +namespace utility { + + +/** An output stream that is connected to a socket. + */ + +class VMIME_EXPORT outputStreamSocketAdapter : public outputStream +{ +public: + + outputStreamSocketAdapter(net::socket& sok); + + void flush(); + + size_t getBlockSize(); + +protected: + + void writeImpl(const byte_t* const data, const size_t count); + +private: + + outputStreamSocketAdapter(const outputStreamSocketAdapter&); + + net::socket& m_socket; +}; + + +} // utility +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES + + +#endif // VMIME_UTILITY_OUTPUTSTREAMSOCKETADAPTER_HPP_INCLUDED + diff --git a/src/vmime/utility/outputStreamStringAdapter.cpp b/src/vmime/utility/outputStreamStringAdapter.cpp new file mode 100644 index 00000000..7105480c --- /dev/null +++ b/src/vmime/utility/outputStreamStringAdapter.cpp @@ -0,0 +1,54 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/outputStreamStringAdapter.hpp" + +#include "vmime/utility/stringUtils.hpp" + + +namespace vmime { +namespace utility { + + +outputStreamStringAdapter::outputStreamStringAdapter(string& buffer) + : m_buffer(buffer) +{ +} + + +void outputStreamStringAdapter::writeImpl + (const byte_t* const data, const size_t count) +{ + vmime::utility::stringUtils::appendBytesToString(m_buffer, data, count); +} + + +void outputStreamStringAdapter::flush() +{ + // Do nothing +} + + +} // utility +} // vmime + diff --git a/src/vmime/utility/outputStreamStringAdapter.hpp b/src/vmime/utility/outputStreamStringAdapter.hpp new file mode 100644 index 00000000..89516827 --- /dev/null +++ b/src/vmime/utility/outputStreamStringAdapter.hpp @@ -0,0 +1,61 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_OUTPUTSTREAMSTRINGADAPTER_HPP_INCLUDED +#define VMIME_UTILITY_OUTPUTSTREAMSTRINGADAPTER_HPP_INCLUDED + + +#include "vmime/utility/outputStream.hpp" + + +namespace vmime { +namespace utility { + + +/** An adapter class for string output. + */ + +class VMIME_EXPORT outputStreamStringAdapter : public outputStream +{ +public: + + outputStreamStringAdapter(string& buffer); + + void flush(); + +protected: + + void writeImpl(const byte_t* const data, const size_t count); + +private: + + string& m_buffer; +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_OUTPUTSTREAMSTRINGADAPTER_HPP_INCLUDED + diff --git a/src/vmime/utility/parserInputStreamAdapter.cpp b/src/vmime/utility/parserInputStreamAdapter.cpp new file mode 100644 index 00000000..5ab26ef0 --- /dev/null +++ b/src/vmime/utility/parserInputStreamAdapter.cpp @@ -0,0 +1,176 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/parserInputStreamAdapter.hpp" + + +namespace vmime { +namespace utility { + + +parserInputStreamAdapter::parserInputStreamAdapter(shared_ptr stream) + : m_stream(stream) +{ +} + + +bool parserInputStreamAdapter::eof() const +{ + return m_stream->eof(); +} + + +void parserInputStreamAdapter::reset() +{ + m_stream->reset(); +} + + +size_t parserInputStreamAdapter::read + (byte_t* const data, const size_t count) +{ + return m_stream->read(data, count); +} + + +shared_ptr parserInputStreamAdapter::getUnderlyingStream() +{ + return m_stream; +} + + +const string parserInputStreamAdapter::extract(const size_t begin, const size_t end) const +{ + const size_t initialPos = m_stream->getPosition(); + + byte_t *buffer = NULL; + + try + { + buffer = new byte_t[end - begin + 1]; + + m_stream->seek(begin); + + const size_t readBytes = m_stream->read(buffer, end - begin); + buffer[readBytes] = '\0'; + + m_stream->seek(initialPos); + + string str(buffer, buffer + readBytes); + delete [] buffer; + + return str; + } + catch (...) + { + delete [] buffer; + + m_stream->seek(initialPos); + throw; + } +} + + +size_t parserInputStreamAdapter::findNext + (const string& token, const size_t startPosition) +{ + static const unsigned int BUFFER_SIZE = 4096; + + // Token must not be longer than BUFFER_SIZE/2 + if (token.empty() || token.length() > BUFFER_SIZE / 2) + return npos; + + const size_t initialPos = getPosition(); + + seek(startPosition); + + try + { + byte_t findBuffer[BUFFER_SIZE]; + byte_t* findBuffer1 = findBuffer; + byte_t* findBuffer2 = findBuffer + (BUFFER_SIZE / 2); + + size_t findBufferLen = 0; + size_t findBufferOffset = 0; + + bool isEOF = false; + + // Fill in initial buffer + findBufferLen = read(findBuffer, BUFFER_SIZE); + + while (findBufferLen != 0) + { + // Find token + for (byte_t *begin = findBuffer, *end = findBuffer + findBufferLen - token.length() ; + begin <= end ; ++begin) + { + if (begin[0] == token[0] && + (token.length() == 1 || + memcmp(static_cast (&begin[1]), + static_cast (token.data() + 1), + token.length() - 1) == 0)) + { + seek(initialPos); + return startPosition + findBufferOffset + (begin - findBuffer); + } + } + + // Rotate buffer + memcpy(findBuffer1, findBuffer2, (BUFFER_SIZE / 2)); + + // Read more bytes + if (findBufferLen < BUFFER_SIZE && (eof() || isEOF)) + { + break; + } + else + { + const size_t bytesRead = read(findBuffer2, BUFFER_SIZE / 2); + + if (bytesRead == 0) + { + isEOF = true; + } + else + { + findBufferLen = (BUFFER_SIZE / 2) + bytesRead; + findBufferOffset += (BUFFER_SIZE / 2); + } + } + } + + seek(initialPos); + } + catch (...) + { + seek(initialPos); + throw; + } + + return npos; +} + + +} // utility +} // vmime + diff --git a/src/vmime/utility/parserInputStreamAdapter.hpp b/src/vmime/utility/parserInputStreamAdapter.hpp new file mode 100644 index 00000000..9b0639b1 --- /dev/null +++ b/src/vmime/utility/parserInputStreamAdapter.hpp @@ -0,0 +1,174 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_PARSERINPUTSTREAMADAPTER_HPP_INCLUDED +#define VMIME_UTILITY_PARSERINPUTSTREAMADAPTER_HPP_INCLUDED + + +#include "vmime/utility/seekableInputStream.hpp" + +#include + + +namespace vmime { +namespace utility { + + +/** An adapter class used for parsing from an input stream. + */ + +class VMIME_EXPORT parserInputStreamAdapter : public seekableInputStream +{ +public: + + /** @param stream input stream to wrap + */ + parserInputStreamAdapter(shared_ptr stream); + + shared_ptr getUnderlyingStream(); + + bool eof() const; + void reset(); + size_t read(byte_t* const data, const size_t count); + + void seek(const size_t pos) + { + m_stream->seek(pos); + } + + size_t skip(const size_t count) + { + return m_stream->skip(count); + } + + size_t getPosition() const + { + return m_stream->getPosition(); + } + + /** Get the byte at the current position without updating the + * current position. + * + * @return byte at the current position + */ + byte_t peekByte() const + { + const size_t initialPos = m_stream->getPosition(); + + try + { + byte_t buffer[1]; + const size_t readBytes = m_stream->read(buffer, 1); + + m_stream->seek(initialPos); + + return (readBytes == 1 ? buffer[0] : static_cast (0)); + } + catch (...) + { + m_stream->seek(initialPos); + throw; + } + } + + /** Get the byte at the current position and advance current + * position by one byte. + * + * @return byte at the current position + */ + byte_t getByte() + { + byte_t buffer[1]; + const size_t readBytes = m_stream->read(buffer, 1); + + return (readBytes == 1 ? buffer[0] : static_cast (0)); + } + + /** Check whether the bytes following the current position match + * the specified bytes. Position is not updated. + * + * @param bytes bytes to compare + * @param length number of bytes + * @return true if the next bytes match the pattern, false otherwise + */ + template + bool matchBytes(const T* bytes, const size_t length) const + { + const size_t initialPos = m_stream->getPosition(); + + try + { + byte_t buffer[32]; + const size_t readBytes = m_stream->read(buffer, length); + + m_stream->seek(initialPos); + + return readBytes == length && + ::memcmp(bytes, buffer, length) == 0; + } + catch (...) + { + m_stream->seek(initialPos); + throw; + } + } + + const string extract(const size_t begin, const size_t end) const; + + /** Skips bytes matching a predicate from the current position. + * The current position is updated to the next following byte + * which does not match the predicate. + * + * @param pred predicate + * @param endPosition stop at this position (or at end of the stream, + * whichever comes first) + * @return number of bytes skipped + */ + template + size_t skipIf(PREDICATE pred, const size_t endPosition) + { + const size_t initialPos = getPosition(); + size_t pos = initialPos; + + while (!m_stream->eof() && pos < endPosition && pred(getByte())) + ++pos; + + m_stream->seek(pos); + + return pos - initialPos; + } + + size_t findNext(const string& token, const size_t startPosition = 0); + +private: + + mutable shared_ptr m_stream; +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_PARSERINPUTSTREAMADAPTER_HPP_INCLUDED + diff --git a/src/vmime/utility/path.cpp b/src/vmime/utility/path.cpp new file mode 100644 index 00000000..9f746d54 --- /dev/null +++ b/src/vmime/utility/path.cpp @@ -0,0 +1,266 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/path.hpp" + +#include + + +namespace vmime { +namespace utility { + + +path::path() +{ +} + + +path::path(const component& c) +{ + m_list.push_back(c); +} + + +path::path(const path& p) + : object() +{ + m_list.resize(p.m_list.size()); + std::copy(p.m_list.begin(), p.m_list.end(), m_list.begin()); +} + + +path::path(const string& s) +{ + m_list.push_back(component(s)); +} + + +path path::operator/(const path& p) const +{ + path pr(*this); + pr /= p; + + return (pr); +} + + +path path::operator/(const component& c) const +{ + path pr(*this); + pr /= c; + + return (pr); +} + + +path& path::operator/=(const path& p) +{ + const list::size_type size = m_list.size(); + + m_list.resize(size + p.m_list.size()); + std::copy(p.m_list.begin(), p.m_list.end(), m_list.begin() + size); + + return (*this); +} + + +path& path::operator/=(const component& c) +{ + m_list.push_back(c); + return (*this); +} + + +path path::getParent() const +{ + path p; + + if (!isEmpty()) + { + p.m_list.resize(m_list.size() - 1); + std::copy(m_list.begin(), m_list.end() - 1, p.m_list.begin()); + } + + return (p); +} + + +path& path::operator=(const path& p) +{ + m_list.resize(p.m_list.size()); + std::copy(p.m_list.begin(), p.m_list.end(), m_list.begin()); + + return (*this); +} + + +path& path::operator=(const component& c) +{ + m_list.resize(1); + m_list[0] = c; + + return (*this); +} + + +bool path::operator==(const path& p) const +{ + if (m_list.size() != p.m_list.size()) + return (false); + + list::const_iterator i = m_list.begin(); + list::const_iterator j = p.m_list.begin(); + + bool equal = true; + + for ( ; equal && i != m_list.end() ; ++i, ++j) + //equal = (*i == *j); + equal = ((*i).getBuffer() == (*j).getBuffer()); + + return (equal); +} + + +bool path::operator!=(const path& p) const +{ + return (!(*this == p)); +} + + +bool path::isEmpty() const +{ + return (m_list.empty()); +} + + +bool path::isRoot() const +{ + return (m_list.empty()); +} + + +const path::component path::getLastComponent() const +{ + return (m_list[m_list.size() - 1]); +} + + +path::component& path::getLastComponent() +{ + return (m_list[m_list.size() - 1]); +} + + +size_t path::getSize() const +{ + return (m_list.size()); +} + + +const path::component& path::operator[](const size_t x) const +{ + return (m_list[x]); +} + + +path::component& path::operator[](const size_t x) +{ + return (m_list[x]); +} + + +bool path::isDirectParentOf(const path& p) const +{ + if (p.getSize() != getSize() + 1) + return (false); + + bool equal = true; + + for (list::size_type i = 0 ; equal && i < m_list.size() ; ++i) + equal = (m_list[i] == p.m_list[i]); + + return (equal); +} + + +bool path::isParentOf(const path& p) const +{ + if (p.getSize() < getSize() + 1) + return (false); + + bool equal = true; + + for (list::size_type i = 0 ; equal && i < m_list.size() ; ++i) + equal = (m_list[i] == p.m_list[i]); + + return (equal); +} + + +void path::renameParent(const path& oldPath, const path& newPath) +{ + if (isEmpty() || oldPath.getSize() > getSize()) + return; + + bool equal = true; + list::size_type i; + + for (i = 0 ; equal && i < oldPath.m_list.size() ; ++i) + equal = (m_list[i] == oldPath.m_list[i]); + + if (i != oldPath.m_list.size()) + return; + + list newList; + + for (list::size_type j = 0 ; j < newPath.m_list.size() ; ++j) + newList.push_back(newPath.m_list[j]); + + for (list::size_type j = i ; j < m_list.size() ; ++j) + newList.push_back(m_list[j]); + + m_list.resize(newList.size()); + std::copy(newList.begin(), newList.end(), m_list.begin()); +} + + +void path::appendComponent(const path::component& c) +{ + m_list.push_back(c); +} + + +const path::component& path::getComponentAt(const size_t pos) const +{ + return (m_list[pos]); +} + + +path::component& path::getComponentAt(const size_t pos) +{ + return (m_list[pos]); +} + + +} // utility +} // vmime diff --git a/src/vmime/utility/path.hpp b/src/vmime/utility/path.hpp new file mode 100644 index 00000000..203da246 --- /dev/null +++ b/src/vmime/utility/path.hpp @@ -0,0 +1,171 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_PATH_HPP_INCLUDED +#define VMIME_UTILITY_PATH_HPP_INCLUDED + + +#include + +#include "vmime/types.hpp" +#include "vmime/word.hpp" + + +namespace vmime { +namespace utility { + + +/** Abstract representation of a path (filesystem, mailbox, etc). + */ + +class VMIME_EXPORT path : public object +{ +public: + + typedef vmime::word component; + typedef std::vector list; + + // Construct a path + path(); + path(const component& c); + path(const path& p); + explicit path(const string& s); + + // Append a component to a path + path operator/(const path& p) const; + path operator/(const component& c) const; + + path& operator/=(const path& p); + path& operator/=(const component& c); + + // Return the parent path + path getParent() const; + + // Assignment + path& operator=(const path& p); + path& operator=(const component& c); + + // Path comparison + bool operator==(const path& p) const; + bool operator!=(const path& p) const; + + /** Append a component to the path. + * + * @param c component to add + */ + void appendComponent(const component& c); + + /** Return the component at the specified position. + * + * @param pos position + * @return component at position 'pos' + */ + const component& getComponentAt(const size_t pos) const; + + /** Return the component at the specified position. + * + * @param pos position + * @return component at position 'pos' + */ + component& getComponentAt(const size_t pos); + + /** Test whether this path is empty (root). + * + * @return true if the path is empty (no components = root) + */ + bool isEmpty() const; + + /** Test whether this path is the root (alias for isEmpty()). + * + * @return true if the path is the root + */ + bool isRoot() const; + + /** Return the last component of this path (const version). + * + * @return last component + */ + const component getLastComponent() const; + + /** Return the last component of this path (non-const version). + * + * @return last component + */ + component& getLastComponent(); + + /** Return the number of components in this path. + * + * @return number of components + */ + size_t getSize() const; + + /** Return the specified component of the path (const version). + * + * @param x index of the component + * @return component at the specified index + */ + const component& operator[](const size_t x) const; + + /** Return the specified component of the path (non-const version). + * + * @param x index of the component + * @return component at the specified index + */ + component& operator[](const size_t x); + + /** Test whether this path is a direct parent of another one. + * + * @param p other path + * @return true if the specified path is a child + * of this path, false otherwise + */ + bool isDirectParentOf(const path& p) const; + + /** Test whether this path is a parent of another one. + * + * @param p other path + * @return true if the specified path is a child (direct or + * indirect) of this path, false otherwise + */ + bool isParentOf(const path& p) const; + + /** Rename a parent component in the path. + * Example: path("a/b/c/d").renameParent("a/b", "x/y/z") + * will return path("x/y/z/c/d"). + * + * @param oldPath old parent path + * @param newPath new parent path + */ + void renameParent(const path& oldPath, const path& newPath); + +private: + + list m_list; +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_PATH_HPP_INCLUDED diff --git a/src/vmime/utility/progressListener.cpp b/src/vmime/utility/progressListener.cpp new file mode 100644 index 00000000..cef074e5 --- /dev/null +++ b/src/vmime/utility/progressListener.cpp @@ -0,0 +1,79 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/progressListener.hpp" + + +namespace vmime { +namespace utility { + + +// progressListenerSizeAdapter + +progressListenerSizeAdapter::progressListenerSizeAdapter + (progressListener* list, const size_t total) + : m_wrapped(list), m_total(total) +{ +} + + +bool progressListenerSizeAdapter::cancel() const +{ + return (m_wrapped ? m_wrapped->cancel() : false); +} + + +void progressListenerSizeAdapter::start(const size_t predictedTotal) +{ + if (m_wrapped) + m_wrapped->start(predictedTotal); +} + + +void progressListenerSizeAdapter::progress(const size_t current, const size_t currentTotal) +{ + if (m_wrapped) + { + if (currentTotal > m_total) + m_total = currentTotal; + + m_wrapped->progress(current, m_total); + } +} + + +void progressListenerSizeAdapter::stop(const size_t total) +{ + if (m_wrapped) + { + if (total > m_total) + m_total = total; + + m_wrapped->stop(m_total); + } +} + + +} // utility +} // vmime + diff --git a/src/vmime/utility/progressListener.hpp b/src/vmime/utility/progressListener.hpp new file mode 100644 index 00000000..4d0e9bf8 --- /dev/null +++ b/src/vmime/utility/progressListener.hpp @@ -0,0 +1,113 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_PROGRESSLISTENER_HPP_INCLUDED +#define VMIME_UTILITY_PROGRESSLISTENER_HPP_INCLUDED + + +#include "vmime/config.hpp" +#include "vmime/types.hpp" + + +namespace vmime { +namespace utility { + + +/** An interface to implement if you want to be notified + * of a state of progress by some objects. + */ + +class VMIME_EXPORT progressListener +{ +protected: + + virtual ~progressListener() { } + +public: + + /** Allow the caller object to cancel the current operation. + * + * @warning WARNING: this is implementation-dependent: cancelling + * may not be supported by the notifier object. + * + * @return true to cancel the operation, false otherwise + */ + virtual bool cancel() const = 0; + + /** Called at the beginning of the operation. + * + * @param predictedTotal predicted amount of units (this has + * no concrete meaning: these are not bytes, nor percentage...) + */ + virtual void start(const size_t predictedTotal) = 0; + + /** Called during the operation (can be called several times). + * + * @param current current position + * @param currentTotal adjusted total amount of units + */ + virtual void progress(const size_t current, const size_t currentTotal) = 0; + + /** Called at the end of the operation. + * + * @param total final total amount of units + */ + virtual void stop(const size_t total) = 0; +}; + + + +/** A progress listener used when total size is known by the + * receiver, but not by the notifier. + */ + +class VMIME_EXPORT progressListenerSizeAdapter : public progressListener +{ +public: + + /** Construct a new progressListenerSizeAdapter object. + * + * @param list wrapped progress listener (can be NULL) + * @param total predicted total + */ + progressListenerSizeAdapter(progressListener* list, const size_t total); + + bool cancel() const; + + void start(const size_t predictedTotal); + void progress(const size_t current, const size_t currentTotal); + void stop(const size_t total); + +private: + + progressListener* m_wrapped; + size_t m_total; +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_PROGRESSLISTENER_HPP_INCLUDED + diff --git a/src/vmime/utility/random.cpp b/src/vmime/utility/random.cpp new file mode 100644 index 00000000..97d12ddc --- /dev/null +++ b/src/vmime/utility/random.cpp @@ -0,0 +1,90 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/random.hpp" +#include "vmime/platform.hpp" + +#include + + +namespace vmime { +namespace utility { + + +static unsigned int getRandomSeed() +{ + unsigned int seed; + + platform::getHandler()->generateRandomBytes + (reinterpret_cast (&seed), sizeof(seed)); + + return seed; +} + + +unsigned int random::getNext() +{ + static unsigned int next = getRandomSeed(); + + // Park and Miller's minimal standard generator: + // xn+1 = (a * xn + b) mod c + // xn+1 = (16807 * xn) mod (2^31 - 1) + next = static_cast((16807 * next) % 2147483647ul); + return next; +} + + +unsigned int random::getTime() +{ + return static_cast ((platform::getHandler()->getUnixTime())); +} + + +unsigned int random::getProcess() +{ + return (platform::getHandler()->getProcessId()); +} + + +const string random::getString(const size_t length, const string& randomChars) +{ + string res; + res.resize(length); + + const unsigned int x = static_cast (randomChars.length()); + size_t c = 0; + + while (c < length) + { + for (unsigned int n = random::getNext() ; n != 0 && c < length ; n /= x) + { + res[c++] = randomChars[n % x]; + } + } + + return (res); +} + + +} // utility +} // vmime diff --git a/src/vmime/utility/random.hpp b/src/vmime/utility/random.hpp new file mode 100644 index 00000000..b667c3a2 --- /dev/null +++ b/src/vmime/utility/random.hpp @@ -0,0 +1,77 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_RANDOM_HPP_INCLUDED +#define VMIME_UTILITY_RANDOM_HPP_INCLUDED + + +#include "vmime/types.hpp" + + +namespace vmime { +namespace utility { + + +/** Pseudo-random number generator. + */ + +class random +{ +public: + + /** Return a new random number. + * + * @return random number + */ + static unsigned int getNext(); + + /** Return the current time as a number (may be used to + * build "random" strings). + * + * @return time as a number + */ + static unsigned int getTime(); + + /** Return the current process number (may be user to + * build "random" strings). + * + * @return process number + */ + static unsigned int getProcess(); + + /** Return a random character string with the specified length. + * + * @param length length of the string to generate + * @param randomChars list of characters to use + * @return random string + */ + static const string getString(const size_t length, const string& randomChars + = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_RANDOM_HPP_INCLUDED diff --git a/src/vmime/utility/seekableInputStream.hpp b/src/vmime/utility/seekableInputStream.hpp new file mode 100644 index 00000000..f56af9c4 --- /dev/null +++ b/src/vmime/utility/seekableInputStream.hpp @@ -0,0 +1,64 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_SEEKABLEINPUTSTREAM_HPP_INCLUDED +#define VMIME_UTILITY_SEEKABLEINPUTSTREAM_HPP_INCLUDED + + +#include "vmime/utility/inputStream.hpp" + + +namespace vmime { +namespace utility { + + +/** An input stream that allows seeking within the input. + */ + +class VMIME_EXPORT seekableInputStream : public inputStream +{ +public: + + /** Returns the current position in this stream. + * + * @return the offset from the beginning of the stream, in bytes, + * at which the next read occurs + */ + virtual size_t getPosition() const = 0; + + /** Sets the position, measured from the beginning of this stream, + * at which the next read occurs. + * + * @param pos the offset position, measured in bytes from the + * beginning of the stream, at which to set the stream pointer. + */ + virtual void seek(const size_t pos) = 0; +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_SEEKABLEINPUTSTREAM_HPP_INCLUDED + diff --git a/src/vmime/utility/seekableInputStreamRegionAdapter.cpp b/src/vmime/utility/seekableInputStreamRegionAdapter.cpp new file mode 100644 index 00000000..cede1ba9 --- /dev/null +++ b/src/vmime/utility/seekableInputStreamRegionAdapter.cpp @@ -0,0 +1,106 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/seekableInputStreamRegionAdapter.hpp" + + +namespace vmime { +namespace utility { + + +seekableInputStreamRegionAdapter::seekableInputStreamRegionAdapter + (shared_ptr stream, const size_t begin, const size_t length) + : m_stream(stream), m_begin(begin), m_length(length), m_position(0) +{ +} + + +bool seekableInputStreamRegionAdapter::eof() const +{ + return m_position >= m_length; +} + + +void seekableInputStreamRegionAdapter::reset() +{ + m_position = 0; +} + + +size_t seekableInputStreamRegionAdapter::read + (byte_t* const data, const size_t count) +{ + m_stream->seek(m_begin + m_position); + + size_t readBytes = 0; + + if (m_position + count >= m_length) + { + const size_t remaining = m_length - m_position; + readBytes = m_stream->read(data, remaining); + } + else + { + readBytes = m_stream->read(data, count); + } + + m_position += readBytes; + + return readBytes; +} + + +size_t seekableInputStreamRegionAdapter::skip(const size_t count) +{ + if (m_position + count >= m_length) + { + const size_t remaining = m_length - m_position; + m_position += remaining; + return remaining; + } + else + { + m_position += count; + return count; + } +} + + +size_t seekableInputStreamRegionAdapter::getPosition() const +{ + return m_position; +} + + +void seekableInputStreamRegionAdapter::seek(const size_t pos) +{ + if (pos > m_length) + m_position = m_length; + else + m_position = pos; +} + + +} // utility +} // vmime + diff --git a/src/vmime/utility/seekableInputStreamRegionAdapter.hpp b/src/vmime/utility/seekableInputStreamRegionAdapter.hpp new file mode 100644 index 00000000..4716d2de --- /dev/null +++ b/src/vmime/utility/seekableInputStreamRegionAdapter.hpp @@ -0,0 +1,72 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_SEEKABLEINPUTSTREAMREGIONADAPTER_HPP_INCLUDED +#define VMIME_UTILITY_SEEKABLEINPUTSTREAMREGIONADAPTER_HPP_INCLUDED + + +#include "vmime/utility/seekableInputStream.hpp" + + +namespace vmime { +namespace utility { + + +/** An adapter for reading a limited region of a seekable input stream. + */ + +class VMIME_EXPORT seekableInputStreamRegionAdapter : public seekableInputStream +{ +public: + + /** Creates a new adapter for a seekableInputStream. + * + * @param stream source stream + * @param begin start position in source stream + * @param length region length in source stream + */ + seekableInputStreamRegionAdapter(shared_ptr stream, + const size_t begin, const 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: + + shared_ptr m_stream; + size_t m_begin; + size_t m_length; + size_t m_position; +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_SEEKABLEINPUTSTREAMREGIONADAPTER_HPP_INCLUDED + diff --git a/src/vmime/utility/stream.cpp b/src/vmime/utility/stream.cpp new file mode 100644 index 00000000..232b23c7 --- /dev/null +++ b/src/vmime/utility/stream.cpp @@ -0,0 +1,40 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/stream.hpp" + + + +namespace vmime { +namespace utility { + + +size_t stream::getBlockSize() +{ + return 32768; // 32 KB +} + + +} // utility +} // vmime + diff --git a/src/vmime/utility/stream.hpp b/src/vmime/utility/stream.hpp new file mode 100644 index 00000000..980a2407 --- /dev/null +++ b/src/vmime/utility/stream.hpp @@ -0,0 +1,62 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_STREAM_HPP_INCLUDED +#define VMIME_UTILITY_STREAM_HPP_INCLUDED + + +#include + +#include "vmime/config.hpp" +#include "vmime/types.hpp" +#include "vmime/base.hpp" + + +namespace vmime { +namespace utility { + + + +/** Base class for input/output stream. + */ + +class VMIME_EXPORT stream : public object, private noncopyable +{ +public: + + virtual ~stream() { } + + /** Return the preferred maximum block size when reading + * from or writing to this stream. + * + * @return block size, in bytes + */ + virtual size_t getBlockSize(); +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_STREAM_HPP_INCLUDED diff --git a/src/vmime/utility/streamUtils.cpp b/src/vmime/utility/streamUtils.cpp new file mode 100644 index 00000000..f3cc69ef --- /dev/null +++ b/src/vmime/utility/streamUtils.cpp @@ -0,0 +1,121 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/streamUtils.hpp" + +#include // for std::copy +#include // for std::back_inserter + + + +namespace vmime { +namespace utility { + + +outputStream& operator<<(outputStream& os, const byte_t c) +{ + os.write(&c, 1); + return (os); +} + + +outputStream& operator<<(outputStream& os, const string& str) +{ + os.write(str.data(), str.length()); + return (os); +} + + +size_t bufferedStreamCopy(inputStream& is, outputStream& os) +{ + return bufferedStreamCopy(is, os, 0, NULL); +} + + +size_t bufferedStreamCopyRange(inputStream& is, outputStream& os, + const size_t start, const size_t length) +{ + const size_t blockSize = + std::min(is.getBlockSize(), os.getBlockSize()); + + is.skip(start); + + std::vector vbuffer(blockSize); + + byte_t* buffer = &vbuffer.front(); + size_t total = 0; + + while (!is.eof() && total < length) + { + const size_t remaining = std::min(length - total, blockSize); + const size_t read = is.read(buffer, remaining); + + if (read != 0) + { + os.write(buffer, read); + total += read; + } + } + + return total; +} + + +size_t bufferedStreamCopy(inputStream& is, outputStream& os, + const size_t length, progressListener* progress) +{ + const size_t blockSize = + std::min(is.getBlockSize(), os.getBlockSize()); + + std::vector vbuffer(blockSize); + + byte_t* buffer = &vbuffer.front(); + size_t total = 0; + + if (progress != NULL) + progress->start(length); + + while (!is.eof()) + { + const size_t read = is.read(buffer, blockSize); + + if (read != 0) + { + os.write(buffer, read); + total += read; + + if (progress != NULL) + progress->progress(total, std::max(total, length)); + } + } + + if (progress != NULL) + progress->stop(total); + + return (total); +} + + +} // utility +} // vmime + diff --git a/src/vmime/utility/streamUtils.hpp b/src/vmime/utility/streamUtils.hpp new file mode 100644 index 00000000..406b6b64 --- /dev/null +++ b/src/vmime/utility/streamUtils.hpp @@ -0,0 +1,79 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_STREAMUTILS_HPP_INCLUDED +#define VMIME_UTILITY_STREAMUTILS_HPP_INCLUDED + + +#include "vmime/utility/inputStream.hpp" +#include "vmime/utility/outputStream.hpp" + +#include "vmime/utility/progressListener.hpp" + + +namespace vmime { +namespace utility { + + +/** Copy data from one stream into another stream using a buffered method. + * + * @param is input stream (source data) + * @param os output stream (destination for data) + * @return number of bytes copied + */ + +VMIME_EXPORT size_t bufferedStreamCopy(inputStream& is, outputStream& os); + +/** Copy data from one stream into another stream using a buffered method + * and copying only a specified range of data. + * + * @param is input stream (source data) + * @param os output stream (destination for data) + * @param start number of bytes to ignore before starting copying + * @param length maximum number of bytes to copy + * @return number of bytes copied + */ + +VMIME_EXPORT size_t bufferedStreamCopyRange(inputStream& is, outputStream& os, + const size_t start, const size_t length); + +/** Copy data from one stream into another stream using a buffered method + * and notify progress state of the operation. + * + * @param is input stream (source data) + * @param os output stream (destination for data) + * @param length predicted number of bytes to copy + * @param progress listener to notify + * @return number of bytes copied + */ + +VMIME_EXPORT size_t bufferedStreamCopy(inputStream& is, outputStream& os, + const size_t length, progressListener* progress); + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_STREAMUTILS_HPP_INCLUDED + diff --git a/src/vmime/utility/stringProxy.cpp b/src/vmime/utility/stringProxy.cpp new file mode 100644 index 00000000..67c96816 --- /dev/null +++ b/src/vmime/utility/stringProxy.cpp @@ -0,0 +1,151 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/stringProxy.hpp" + +#include "vmime/utility/outputStreamAdapter.hpp" + +#include +#include + + +namespace vmime { +namespace utility { + + +stringProxy::stringProxy() + : m_start(0), m_end(0) +{ +} + + +stringProxy::stringProxy(const stringProxy& s) + : m_buffer(s.m_buffer), m_start(s.m_start), m_end(s.m_end) +{ +} + + +stringProxy::stringProxy(const string& s, const size_t start, const size_t end) + : m_buffer(s), m_start(start), + m_end(end == std::numeric_limits ::max() ? s.length() : end) +{ +} + + +void stringProxy::set(const string& s, const size_t start, const size_t end) +{ + m_buffer = s; + m_start = start; + + if (end == std::numeric_limits ::max()) + m_end = s.length(); + else + m_end = end; +} + + +void stringProxy::detach() +{ + m_buffer.clear(); + m_start = m_end = 0; +} + + +stringProxy& stringProxy::operator=(const stringProxy& s) +{ + m_buffer = s.m_buffer; + m_start = s.m_start; + m_end = s.m_end; + + return (*this); +} + + +stringProxy& stringProxy::operator=(const string& s) +{ + m_buffer = s; + m_start = 0; + m_end = s.length(); + + return (*this); +} + + +void stringProxy::extract(outputStream& os, const size_t start, const size_t end, + utility::progressListener* progress) const +{ + size_t len = 0; + + if (end == std::numeric_limits ::max()) + len = m_end - start - m_start; + else if (end > start) + len = end - start; + + if (progress) + progress->start(len); + + os.write(m_buffer.data() + m_start + start, len); + + if (progress) + { + progress->progress(len, len); + progress->stop(len); + } +} + + +size_t stringProxy::length() const +{ + return (m_end - m_start); +} + + +size_t stringProxy::start() const +{ + return (m_start); +} + + +size_t stringProxy::end() const +{ + return (m_end); +} + + +std::ostream& operator<<(std::ostream& os, const stringProxy& s) +{ + outputStreamAdapter adapter(os); + s.extract(adapter); + return (os); +} + + +outputStream& operator<<(outputStream& os, const stringProxy& s) +{ + s.extract(os); + return (os); +} + + +} // utility +} // vmime diff --git a/src/vmime/utility/stringProxy.hpp b/src/vmime/utility/stringProxy.hpp new file mode 100644 index 00000000..e5efa135 --- /dev/null +++ b/src/vmime/utility/stringProxy.hpp @@ -0,0 +1,92 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_STRINGPROXY_HPP_INCLUDED +#define VMIME_UTILITY_STRINGPROXY_HPP_INCLUDED + + +#include + +#include "vmime/types.hpp" +#include "vmime/utility/stream.hpp" +#include "vmime/utility/outputStream.hpp" +#include "vmime/utility/progressListener.hpp" + + +namespace vmime { +namespace utility { + + +/** This class is a proxy for the string class. This takes + * advantage of the COW (copy-on-write) system that might + * be used in "std::string" implementation. + */ + +class VMIME_EXPORT stringProxy +{ +public: + + // Consruction + stringProxy(); + stringProxy(const stringProxy& s); + stringProxy(const string& s, const size_t start = 0, const size_t end = std::numeric_limits ::max()); + + // Assignment + void set(const string& s, const size_t start = 0, const size_t end = std::numeric_limits ::max()); + void detach(); + + stringProxy& operator=(const stringProxy& s); + stringProxy& operator=(const string& s); + + // Extract some portion (or whole) of the string + // and output it into a stream. + void extract(outputStream& os, const size_t start = 0, const size_t end = std::numeric_limits ::max(), utility::progressListener* progress = NULL) const; + + // Return the "virtual" length of the string + size_t length() const; + + // Return the boundaries of the "virtual" string + size_t start() const; + size_t end() const; + + string::const_iterator it_begin() const { return (m_buffer.begin() + m_start); } + string::const_iterator it_end() const { return (m_buffer.begin() + m_end); } + +private: + + string m_buffer; + + size_t m_start; + size_t m_end; +}; + + +VMIME_EXPORT std::ostream& operator<<(std::ostream& os, const stringProxy& s); +VMIME_EXPORT outputStream& operator<<(outputStream& os, const stringProxy& s); + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_STRINGPROXY_HPP_INCLUDED diff --git a/src/vmime/utility/stringUtils.cpp b/src/vmime/utility/stringUtils.cpp new file mode 100644 index 00000000..dd99d845 --- /dev/null +++ b/src/vmime/utility/stringUtils.cpp @@ -0,0 +1,242 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/stringUtils.hpp" +#include "vmime/parserHelpers.hpp" + + +namespace vmime { +namespace utility { + + +bool stringUtils::isStringEqualNoCase + (const string& s1, const char* s2, const size_t n) +{ + // 'n' is the number of characters to compare + // 's2' must be in lowercase letters only + if (s1.length() < n) + return (false); + + const std::ctype & fac = + std::use_facet >(std::locale::classic()); + + bool equal = true; + + for (size_t i = 0 ; equal && i < n ; ++i) + equal = (fac.tolower(static_cast (s1[i])) == s2[i]); + + return (equal); +} + + +bool stringUtils::isStringEqualNoCase(const string& s1, const string& s2) +{ + if (s1.length() != s2.length()) + return (false); + + const std::ctype & fac = + std::use_facet >(std::locale::classic()); + + bool equal = true; + const string::const_iterator end = s1.end(); + + for (string::const_iterator i = s1.begin(), j = s2.begin(); i != end ; ++i, ++j) + equal = (fac.tolower(static_cast (*i)) == fac.tolower(static_cast (*j))); + + return (equal); +} + + +bool stringUtils::isStringEqualNoCase + (const string::const_iterator begin, const string::const_iterator end, + const char* s, const size_t n) +{ + if (static_cast (end - begin) < n) + return (false); + + const std::ctype & fac = + std::use_facet >(std::locale::classic()); + + bool equal = true; + char* c = const_cast(s); + size_t r = n; + + for (string::const_iterator i = begin ; equal && r && *c ; ++i, ++c, --r) + equal = (fac.tolower(static_cast (*i)) == static_cast (*c)); + + return (r == 0 && equal); +} + + +const string stringUtils::toLower(const string& str) +{ + const std::ctype & fac = + std::use_facet >(std::locale::classic()); + + string out; + out.resize(str.size()); + + for (size_t i = 0, len = str.length() ; i < len ; ++i) + out[i] = fac.tolower(static_cast (str[i])); + + return out; +} + + +const string stringUtils::toUpper(const string& str) +{ + const std::ctype & fac = + std::use_facet >(std::locale::classic()); + + string out; + out.resize(str.size()); + + for (size_t i = 0, len = str.length() ; i < len ; ++i) + out[i] = fac.toupper(static_cast (str[i])); + + return out; +} + + +const string stringUtils::trim(const string& str) +{ + string::const_iterator b = str.begin(); + string::const_iterator e = str.end(); + + if (b != e) + { + for ( ; b != e && parserHelpers::isSpace(*b) ; ++b) {} + for ( ; e != b && parserHelpers::isSpace(*(e - 1)) ; --e) {} + } + + return (string(b, e)); +} + + +size_t stringUtils::countASCIIchars + (const string::const_iterator begin, const string::const_iterator end) +{ + size_t count = 0; + + for (string::const_iterator i = begin ; i != end ; ++i) + { + if (parserHelpers::isAscii(*i)) + { + if (*i != '=' || ((i + 1) != end && *(i + 1) != '?')) // To avoid bad behaviour... + ++count; + } + } + + return (count); +} + + +bool stringUtils::is7bit(const string& str) +{ + return countASCIIchars(str.begin(), str.end()) == str.length(); +} + + +size_t stringUtils::findFirstNonASCIIchar + (const string::const_iterator begin, const string::const_iterator end) +{ + size_t pos = string::npos; + + for (string::const_iterator i = begin ; i != end ; ++i) + { + if (!parserHelpers::isAscii(*i)) + { + pos = i - begin; + break; + } + } + + return pos; +} + + +const string stringUtils::unquote(const string& str) +{ + if (str.length() < 2) + return str; + + if (str[0] != '"' || str[str.length() - 1] != '"') + return str; + + string res; + res.reserve(str.length()); + + bool escaped = false; + + for (string::const_iterator it = str.begin() + 1, end = str.end() - 1 ; it != end ; ++it) + { + const char c = *it; + + if (escaped) + { + res += c; + escaped = false; + } + else if (!escaped && c == '\\') + { + escaped = true; + } + else + { + res += c; + } + } + + return res; +} + + +bool stringUtils::needQuoting(const string& str, const string& specialChars) +{ + return str.find_first_of(specialChars.c_str()) != string::npos; +} + + +string stringUtils::quote + (const string& str, const string& escapeSpecialChars, const string& escapeChar) +{ + std::ostringstream oss; + size_t lastPos = 0, pos = 0; + + while ((pos = str.find_first_of(escapeSpecialChars, lastPos)) != string::npos) + { + oss << str.substr(lastPos, pos - lastPos) + << escapeChar + << str[pos]; + + lastPos = pos + 1; + } + + oss << str.substr(lastPos); + + return oss.str(); +} + + +} // utility +} // vmime diff --git a/src/vmime/utility/stringUtils.hpp b/src/vmime/utility/stringUtils.hpp new file mode 100644 index 00000000..7d9925e2 --- /dev/null +++ b/src/vmime/utility/stringUtils.hpp @@ -0,0 +1,214 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_STRINGUTILS_HPP_INCLUDED +#define VMIME_UTILITY_STRINGUTILS_HPP_INCLUDED + + +#include "vmime/types.hpp" +#include "vmime/base.hpp" + +#include + + +namespace vmime { +namespace utility { + + +/** Miscellaneous functions related to strings. + */ + +class VMIME_EXPORT stringUtils +{ +public: + + /** Makes a string from bytes. + * + * @param data pointer to buffer containing data + * @param count number of bytes to use from buffer + * @return a string object containing a copy of the specified data + */ + static const string makeStringFromBytes(const byte_t* data, const size_t count) + { + return string(reinterpret_cast (data), count); + } + + /** Appends bytes to a string. + * + * @param str string to which append data + * @param data pointer to buffer containing data + * @param count number of bytes to use from buffer + * @return a reference to modified string + */ + static string& appendBytesToString(string& str, const byte_t* data, const size_t count) + { + str.append(reinterpret_cast (data), count); + return str; + } + + /** Test two strings for equality (case insensitive). + * \warning Use this with ASCII-only strings. + * + * @param s1 first string + * @param s2 second string (must be in lower-case!) + * @param n length of the second string + * @return true if the two strings compare equally, false otherwise + */ + static bool isStringEqualNoCase(const string& s1, const char* s2, const size_t n); + + /** Test two strings for equality (case insensitive). + * \warning Use this with ASCII-only strings. + * + * @param s1 first string + * @param s2 second string + * @return true if the two strings compare equally, false otherwise + */ + static bool isStringEqualNoCase(const string& s1, const string& s2); + + /** Test two strings for equality (case insensitive). + * \warning Use this with ASCII-only strings. + * + * @param begin start position of the first string + * @param end end position of the first string + * @param s second string (must be in lower-case!) + * @param n length of the second string + * @return true if the two strings compare equally, false otherwise + */ + static bool isStringEqualNoCase(const string::const_iterator begin, const string::const_iterator end, const char* s, const size_t n); + + /** Transform all the characters in a string to lower-case. + * \warning Use this with ASCII-only strings. + * + * @param str the string to transform + * @return a new string in lower-case + */ + static const string toLower(const string& str); + + /** Transform all the characters in a string to upper-case. + * \warning Use this with ASCII-only strings. + * + * @param str the string to transform + * @return a new string in upper-case + */ + static const string toUpper(const string& str); + + /** Strip the space characters (SPC, TAB, CR, LF) at the beginning + * and at the end of the specified string. + * + * @param str string in which to strip spaces + * @return a new string with space characters removed + */ + static const string trim(const string& str); + + /** Return the number of 7-bit US-ASCII characters in a string. + * + * @param begin start position + * @param end end position + * @return number of ASCII characters + */ + static size_t countASCIIchars(const string::const_iterator begin, const string::const_iterator end); + + /** Returns whether the specified string is composed exclusively + * of 7-bit ASCII characters. + * + * @param str string to test + * @return true if the string is ASCII-only, false otherwise + */ + static bool is7bit(const string& str); + + /** Returns the position of the first non 7-bit US-ASCII character in a string. + * + * @param begin start position + * @param end end position + * @return position since begin, or string::npos + */ + static size_t findFirstNonASCIIchar(const string::const_iterator begin, const string::const_iterator end); + + /** Convert the specified value to a string value. + * + * @param value to convert + * @return value converted from type 'TYPE' + */ + template + static const string toString(const TYPE& value) + { + std::ostringstream oss; + oss.imbue(std::locale::classic()); + + oss << value; + + return (oss.str()); + } + + /** Convert the specified string value to a value of + * the specified type. + * + * @param value value to convert + * @return value converted into type 'TYPE' + */ + template + static const TYPE fromString(const string& value) + { + TYPE ret; + + std::istringstream iss(value); + iss.imbue(std::locale::classic()); + + iss >> ret; + + return (ret); + } + + /** Unquote the specified string and transform escaped characters. + * + * @param str string from which to remove quotes + * @return unquoted string + */ + static const string unquote(const string& str); + + /** Determines whether the specified string needs to be quoted. + * + * @param str string to test + * @param specialChars list of characters that will cause the + * string to be quoted + * @return true if the string needs to be quoted, false otherwise + */ + static bool needQuoting(const string& str, + const string& specialChars = " \t\"(),:;<>@[\\]"); + + /** Quotes the specified string. + * + * @param str string to quote + * @param escapeSpecialChars list of characters that will be escaped + * @param escapeChar character that will be used for escaping (eg. '\') + * @return quoted string + */ + static string quote(const string& str, const string& escapeSpecialChars, const string& escapeChar); +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_STRINGUTILS_HPP_INCLUDED diff --git a/src/vmime/utility/sync/autoLock.hpp b/src/vmime/utility/sync/autoLock.hpp new file mode 100644 index 00000000..c058429d --- /dev/null +++ b/src/vmime/utility/sync/autoLock.hpp @@ -0,0 +1,66 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_SYNC_AUTOLOCK_HPP_INCLUDED +#define VMIME_UTILITY_SYNC_AUTOLOCK_HPP_INCLUDED + + +#include "vmime/base.hpp" + + +namespace vmime { +namespace utility { +namespace sync { + + +/** Critical section wrapper class + */ + +template +class VMIME_EXPORT autoLock : public object +{ +public: + + autoLock(shared_ptr mutex) + : m_mutex(mutex) + { + m_mutex->lock(); + } + + ~autoLock() + { + m_mutex->unlock(); + } + +private: + + shared_ptr m_mutex; +}; + + +} // sync +} // utility +} // vmime + + +#endif // VMIME_UTILITY_SYNC_AUTOLOCK_HPP_INCLUDED diff --git a/src/vmime/utility/sync/criticalSection.cpp b/src/vmime/utility/sync/criticalSection.cpp new file mode 100644 index 00000000..f2512d14 --- /dev/null +++ b/src/vmime/utility/sync/criticalSection.cpp @@ -0,0 +1,44 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/sync/criticalSection.hpp" + + +namespace vmime { +namespace utility { +namespace sync { + + +criticalSection::criticalSection() +{ +} + + +criticalSection::~criticalSection() +{ +} + + +} // sync +} // utility +} // vmime diff --git a/src/vmime/utility/sync/criticalSection.hpp b/src/vmime/utility/sync/criticalSection.hpp new file mode 100644 index 00000000..9703d73c --- /dev/null +++ b/src/vmime/utility/sync/criticalSection.hpp @@ -0,0 +1,65 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_SYNC_CRITICALSECTION_HPP_INCLUDED +#define VMIME_UTILITY_SYNC_CRITICALSECTION_HPP_INCLUDED + + +#include "vmime/base.hpp" + + +namespace vmime { +namespace utility { +namespace sync { + + +/** Critical section class. + */ + +class VMIME_EXPORT criticalSection : public object +{ +public: + + virtual ~criticalSection(); + + /** Enters the critical section. + */ + virtual void lock() = 0; + + /** Leaves the critical section. + */ + virtual void unlock() = 0; + +protected: + + criticalSection(); + criticalSection(criticalSection&); +}; + + +} // sync +} // utility +} // vmime + + +#endif // VMIME_UTILITY_SYNC_CRITICALSECTION_HPP_INCLUDED diff --git a/src/vmime/utility/url.cpp b/src/vmime/utility/url.cpp new file mode 100644 index 00000000..ce0dc39a --- /dev/null +++ b/src/vmime/utility/url.cpp @@ -0,0 +1,406 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/url.hpp" + +#include "vmime/parserHelpers.hpp" +#include "vmime/utility/urlUtils.hpp" +#include "vmime/exception.hpp" + +#include + + +namespace vmime { +namespace utility { + + +// Unspecified port +const port_t url::UNSPECIFIED_PORT = static_cast (-1); + +// Known protocols +const string url::PROTOCOL_FILE = "file"; +const string url::PROTOCOL_HTTP = "http"; +const string url::PROTOCOL_FTP = "ftp"; + + + +url::url(const string& s) +{ + parse(s); +} + + +url::url(const url& u) +{ + operator=(u); +} + + +url::url(const string& protocol, const string& host, const port_t port, + const string& path, const string& username, const string& password) + : m_protocol(protocol), m_username(username), m_password(password), + m_host(host), m_port(port), m_path(path) +{ +} + + +url& url::operator=(const url& u) +{ + m_protocol = u.m_protocol; + + m_username = u.m_username; + m_password = u.m_password; + + m_host = u.m_host; + m_port = u.m_port; + + m_path = u.m_path; + + m_params = u.m_params; + + return (*this); +} + + +url& url::operator=(const string& s) +{ + parse(s); + + return (*this); +} + + +url::operator string() const +{ + return build(); +} + + +const string url::build() const +{ + std::ostringstream oss; + oss.imbue(std::locale::classic()); + + oss << m_protocol << "://"; + + if (!m_username.empty()) + { + oss << urlUtils::encode(m_username); + + if (!m_password.empty()) + { + oss << ":"; + oss << urlUtils::encode(m_password); + } + + oss << "@"; + } + + oss << urlUtils::encode(m_host); + + if (m_port != UNSPECIFIED_PORT) + { + oss << ":"; + oss << m_port; + } + + if (!m_path.empty()) + { + oss << "/"; + oss << urlUtils::encode(m_path); + } + + + if (!m_params.empty()) + { + if (m_path.empty()) + oss << "/"; + + oss << "?"; + + for (std::map ::const_iterator it = m_params.begin() ; + it != m_params.end() ; ++it) + { + if (it != m_params.begin()) + oss << "&"; + + oss << urlUtils::encode((*it).first); + oss << "="; + oss << urlUtils::encode((*it).second); + } + } + + return (oss.str()); +} + + +void url::parse(const string& str) +{ + // Protocol + const size_t protoEnd = str.find("://"); + if (protoEnd == string::npos) throw exceptions::malformed_url("No protocol separator"); + + const string proto = + utility::stringUtils::toLower(string(str.begin(), str.begin() + protoEnd)); + + // Username/password + size_t slashPos = str.find('/', protoEnd + 3); + if (slashPos == string::npos) slashPos = str.length(); + + size_t atPos = str.rfind('@', slashPos); + string hostPart; + + string username; + string password; + + if (proto == PROTOCOL_FILE) + { + // No user name, password and host part. + slashPos = protoEnd + 3; + } + else + { + if (atPos != string::npos && atPos < slashPos) + { + const string userPart(str.begin() + protoEnd + 3, str.begin() + atPos); + const size_t colonPos = userPart.find(':'); + + if (colonPos == string::npos) + { + username = userPart; + } + else + { + username = string(userPart.begin(), userPart.begin() + colonPos); + password = string(userPart.begin() + colonPos + 1, userPart.end()); + } + + hostPart = string(str.begin() + atPos + 1, str.begin() + slashPos); + } + else + { + hostPart = string(str.begin() + protoEnd + 3, str.begin() + slashPos); + } + } + + // Host/port + const size_t colonPos = hostPart.find(':'); + + string host; + string port; + + if (colonPos == string::npos) + { + host = utility::stringUtils::trim(hostPart); + } + else + { + host = utility::stringUtils::trim(string(hostPart.begin(), hostPart.begin() + colonPos)); + port = utility::stringUtils::trim(string(hostPart.begin() + colonPos + 1, hostPart.end())); + } + + // Path + string path = utility::stringUtils::trim(string(str.begin() + slashPos, str.end())); + string params; + + size_t paramSep = path.find_first_of('?'); + + if (paramSep != string::npos) + { + params = string(path.begin() + paramSep + 1, path.end()); + path.erase(path.begin() + paramSep, path.end()); + } + + if (path == "/") + path.clear(); + + // Some sanity check + if (proto.empty()) + throw exceptions::malformed_url("No protocol specified"); + else if (host.empty()) + { + // Accept empty host (eg. "file:///home/vincent/mydoc") + if (proto != PROTOCOL_FILE) + throw exceptions::malformed_url("No host specified"); + } + + bool onlyDigit = true; + + for (string::const_iterator it = port.begin() ; + onlyDigit && it != port.end() ; ++it) + { + onlyDigit = parserHelpers::isDigit(*it); + } + + if (!onlyDigit) + throw exceptions::malformed_url("Port can only contain digits"); + + std::istringstream iss(port); + port_t portNum = 0; + + iss >> portNum; + + if (portNum == 0) + portNum = UNSPECIFIED_PORT; + + // Extract parameters + m_params.clear(); + + if (!params.empty()) + { + size_t pos = 0; + + do + { + const size_t start = pos; + + pos = params.find_first_of('&', pos); + + const size_t equal = params.find_first_of('=', start); + const size_t end = + (pos == string::npos ? params.length() : pos); + + string name; + string value; + + if (equal == string::npos || equal > pos) // no value + { + name = string(params.begin() + start, params.begin() + end); + value = name; + } + else + { + name = string(params.begin() + start, params.begin() + equal); + value = string(params.begin() + equal + 1, params.begin() + end); + } + + name = urlUtils::decode(name); + value = urlUtils::decode(value); + + m_params[name] = value; + + if (pos != string::npos) + ++pos; + } + while (pos != string::npos); + } + + // Now, save URL parts + m_protocol = proto; + + m_username = urlUtils::decode(username); + m_password = urlUtils::decode(password); + + m_host = urlUtils::decode(host); + m_port = portNum; + + m_path = urlUtils::decode(path); +} + + +const string& url::getProtocol() const +{ + return (m_protocol); +} + + +void url::setProtocol(const string& protocol) +{ + m_protocol = protocol; +} + + +const string& url::getUsername() const +{ + return (m_username); +} + + +void url::setUsername(const string& username) +{ + m_username = username; +} + + +const string& url::getPassword() const +{ + return (m_password); +} + + +void url::setPassword(const string& password) +{ + m_password = password; +} + + +const string& url::getHost() const +{ + return (m_host); +} + + +void url::setHost(const string& host) +{ + m_host = host; +} + + +port_t url::getPort() const +{ + return (m_port); +} + + +void url::setPort(const port_t port) +{ + m_port = port; +} + + +const string& url::getPath() const +{ + return (m_path); +} + + +void url::setPath(const string& path) +{ + m_path = path; +} + + +const std::map & url::getParams() const +{ + return (m_params); +} + + +std::map & url::getParams() +{ + return (m_params); +} + + +} // utility +} // vmime diff --git a/src/vmime/utility/url.hpp b/src/vmime/utility/url.hpp new file mode 100644 index 00000000..84aba618 --- /dev/null +++ b/src/vmime/utility/url.hpp @@ -0,0 +1,207 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_URL_HPP_INCLUDED +#define VMIME_UTILITY_URL_HPP_INCLUDED + + +#include "vmime/types.hpp" +#include "vmime/base.hpp" +#include "vmime/propertySet.hpp" + + +namespace vmime { +namespace utility { + + +/** This class represents a Uniform Resource Locator (a pointer + * to a "resource" on the World Wide Web). + */ + +class VMIME_EXPORT url +{ +public: + + /** Means "port not specified" (use default port). */ + static const port_t UNSPECIFIED_PORT; + + /** Standard name for FILE protocol (local file-system). */ + static const string PROTOCOL_FILE; + + /** Standard name for HTTP protocol. */ + static const string PROTOCOL_HTTP; + + /** Standard name for FTP protocol. */ + static const string PROTOCOL_FTP; + + + /** Construct an URL from a string (parse the URL components). + * + * @param s full URL string (eg. http://www.vmime.org:80/download.html) + * @throw exceptions::malformed_url if URL is malformed + */ + url(const string& s); + + /** Construct an URL from another URL object. + * + * @param u other URL object + */ + url(const url& u); + + /** Construct an URL from the components. + * + * @param protocol protocol (eg. "http", "ftp"...) + * @param host host name (eg. "www.vmime.org", "123.45.67.89") + * @param port optional port number (eg. 80, 110 or UNSPECIFIED_PORT to mean "default") + * @param path optional full path (eg. "download.html") + * @param username optional user name + * @param password optional user password + */ + url(const string& protocol, const string& host, const port_t port = UNSPECIFIED_PORT, + const string& path = "", const string& username = "", const string& password = ""); + + + /** Return the protocol of the URL (eg: "http"). + * + * @return protocol of the URL + */ + const string& getProtocol() const; + + /** Set the protocol of the URL. + * + * @param protocol new protocol (eg: "http") + */ + void setProtocol(const string& protocol); + + /** Return the username specified in the URL + * or empty if not specified. + * + * @return user name + */ + const string& getUsername() const; + + /** Set the username of the URL. + * + * @param username user name + */ + void setUsername(const string& username); + + /** Return the password specified in the URL + * or empty if not specified. + * + * @return user password + */ + const string& getPassword() const; + + /** Set the password of the URL. + * + * @param password user password + */ + void setPassword(const string& password); + + /** Return the host name of the URL (server name or IP address). + * + * @return host name + */ + const string& getHost() const; + + /** Set the host name of the URL. + * + * @param host server name or IP address + */ + void setHost(const string& host); + + /** Return the port of the URL, or url::UNSPECIFIED_PORT if + * the default port if used. + * + * @return server port + */ + port_t getPort() const; + + /** Set the port of the URL. + * + * @param port server port or url::UNSPECIFIED_PORT to + * use the default port of the protocol + */ + void setPort(const port_t port); + + /** Return the path portion of the URL, + * or empty if not specified. + * + * @return path + */ + const string& getPath() const; + + /** Set the part portion of the URL. + * + * @param path path + */ + void setPath(const string& path); + + /** Return the parameters of the URL (read-only). + * + * @return parameters + */ + const std::map & getParams() const; + + /** Return the parameters of the URL. + * + * @return parameters + */ + std::map & getParams(); + + /** Build a string URL from this object. + */ + operator string() const; + + url& operator=(const url& u); + url& operator=(const string& s); + +private: + + const string build() const; + void parse(const string& str); + + // Format: + // "protocol://[username[:password]@]host[:port][/path]" + + string m_protocol; + + string m_username; + string m_password; + + string m_host; + + port_t m_port; + + string m_path; + + std::map m_params; +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_URL_HPP_INCLUDED diff --git a/src/vmime/utility/urlUtils.cpp b/src/vmime/utility/urlUtils.cpp new file mode 100644 index 00000000..20818764 --- /dev/null +++ b/src/vmime/utility/urlUtils.cpp @@ -0,0 +1,133 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/urlUtils.hpp" +#include "vmime/parserHelpers.hpp" + + +namespace vmime { +namespace utility { + + +const string urlUtils::encode(const string& s) +{ + static const string RESERVED_CHARS = + /* reserved */ "$&+,/:;=?@" + /* unsafe */ "<>#%{}[]|\\^\"~`"; + + string result; + result.reserve(s.length()); + + for (string::const_iterator it = s.begin() ; it != s.end() ; ++it) + { + const char c = *it; + + if (parserHelpers::isPrint(c) && !parserHelpers::isSpace(c) && + static_cast (c) <= 127 && + RESERVED_CHARS.find(c) == string::npos) + { + result += c; + } + else + { + char hex[4]; + const unsigned char k = static_cast (c); + + hex[0] = '%'; + hex[1] = "0123456789ABCDEF"[k / 16]; + hex[2] = "0123456789ABCDEF"[k % 16]; + hex[3] = 0; + + result += hex; + } + } + + return (result); +} + + +const string urlUtils::decode(const string& s) +{ + string result; + result.reserve(s.length()); + + for (string::const_iterator it = s.begin() ; it != s.end() ; ) + { + const char c = *it; + + switch (c) + { + case '%': + { + ++it; // skip '%' + + const char_t p = (it != s.end() ? *(it++) : 0); + const char_t q = (it != s.end() ? *(it++) : 0); + + unsigned int r = 0; + + switch (p) + { + case 0: r = '%'; break; + case 'a': case 'A': r = 10; break; + case 'b': case 'B': r = 11; break; + case 'c': case 'C': r = 12; break; + case 'd': case 'D': r = 13; break; + case 'e': case 'E': r = 14; break; + case 'f': case 'F': r = 15; break; + default: r = p - '0'; break; + } + + if (q != 0) + { + r *= 16; + + switch (q) + { + case 'a': case 'A': r += 10; break; + case 'b': case 'B': r += 11; break; + case 'c': case 'C': r += 12; break; + case 'd': case 'D': r += 13; break; + case 'e': case 'E': r += 14; break; + case 'f': case 'F': r += 15; break; + default: r += q - '0'; break; + } + } + + result += static_cast (r); + break; + } + default: + + result += c; + ++it; + break; + } + } + + return (result); +} + + +} // utility +} // vmime diff --git a/src/vmime/utility/urlUtils.hpp b/src/vmime/utility/urlUtils.hpp new file mode 100644 index 00000000..c21e7aa4 --- /dev/null +++ b/src/vmime/utility/urlUtils.hpp @@ -0,0 +1,58 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_URLUTILS_HPP_INCLUDED +#define VMIME_UTILITY_URLUTILS_HPP_INCLUDED + + +#include "vmime/types.hpp" +#include "vmime/base.hpp" + + +namespace vmime { +namespace utility { + + +/** Miscellaneous functions related to URLs. + */ + +class VMIME_EXPORT urlUtils +{ +public: + + /** Encode extended characters in a URL string (ASCII characters + * are unmodified, other are encoded as '%' followed by hex code). + */ + static const string encode(const string& s); + + /** Decode an hex-encoded URL (see encode()). + */ + static const string decode(const string& s); +}; + + +} // utility +} // vmime + + +#endif // VMIME_UTILITY_URLUTILS_HPP_INCLUDED diff --git a/src/vmime/vmime.hpp b/src/vmime/vmime.hpp new file mode 100644 index 00000000..9bb017e3 --- /dev/null +++ b/src/vmime/vmime.hpp @@ -0,0 +1,161 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should.have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_INCLUDED +#define VMIME_INCLUDED + + +// Configuration +#include "vmime/config.hpp" + +// Base definitions +#include "vmime/base.hpp" +#include "vmime/exception.hpp" +#include "vmime/platform.hpp" + +// Base components +#include "vmime/dateTime.hpp" +#include "vmime/message.hpp" +#include "vmime/bodyPart.hpp" +#include "vmime/charset.hpp" +#include "vmime/text.hpp" +#include "vmime/encoding.hpp" +#include "vmime/contentDisposition.hpp" +#include "vmime/emailAddress.hpp" +#include "vmime/mailbox.hpp" +#include "vmime/mailboxGroup.hpp" +#include "vmime/mailboxList.hpp" +#include "vmime/addressList.hpp" +#include "vmime/mediaType.hpp" +#include "vmime/messageId.hpp" +#include "vmime/messageIdSequence.hpp" +#include "vmime/relay.hpp" +#include "vmime/disposition.hpp" +#include "vmime/path.hpp" + +#include "vmime/emptyContentHandler.hpp" +#include "vmime/fileContentHandler.hpp" +#include "vmime/stringContentHandler.hpp" +#include "vmime/streamContentHandler.hpp" + +#include "vmime/generationContext.hpp" +#include "vmime/parsingContext.hpp" + +// Message components +#include "vmime/message.hpp" + +// Header fields +#include "vmime/headerFieldFactory.hpp" +#include "vmime/mailboxField.hpp" +#include "vmime/parameterizedHeaderField.hpp" + +// Encoders +#include "vmime/utility/encoder/encoderFactory.hpp" + +// Streams +#include "vmime/utility/filteredStream.hpp" +#include "vmime/utility/inputStream.hpp" +#include "vmime/utility/inputStreamAdapter.hpp" +#include "vmime/utility/inputStreamByteBufferAdapter.hpp" +#include "vmime/utility/inputStreamPointerAdapter.hpp" +#include "vmime/utility/inputStreamSocketAdapter.hpp" +#include "vmime/utility/inputStreamStringAdapter.hpp" +#include "vmime/utility/inputStreamStringProxyAdapter.hpp" +#include "vmime/utility/outputStream.hpp" +#include "vmime/utility/outputStreamAdapter.hpp" +#include "vmime/utility/outputStreamByteArrayAdapter.hpp" +#include "vmime/utility/outputStreamSocketAdapter.hpp" +#include "vmime/utility/outputStreamStringAdapter.hpp" +#include "vmime/utility/streamUtils.hpp" + +// Message builder/parser +#include "vmime/messageBuilder.hpp" +#include "vmime/messageParser.hpp" + +#include "vmime/fileAttachment.hpp" +#include "vmime/defaultAttachment.hpp" +#include "vmime/messageAttachment.hpp" + +#include "vmime/plainTextPart.hpp" +#include "vmime/htmlTextPart.hpp" + +#include "vmime/attachmentHelper.hpp" + +// MDN +#include "vmime/mdn/MDNHelper.hpp" + +// Misc +#include "vmime/misc/importanceHelper.hpp" + +// Property set +#include "vmime/propertySet.hpp" + +// Utilities +#include "vmime/utility/datetimeUtils.hpp" +#include "vmime/utility/filteredStream.hpp" +#include "vmime/charsetConverter.hpp" + +// Security +#include "vmime/security/authenticator.hpp" +#include "vmime/security/defaultAuthenticator.hpp" + +// Security/digest +#include "vmime/security/digest/messageDigestFactory.hpp" + +// Security/SASL +#if VMIME_HAVE_SASL_SUPPORT + #include "vmime/security/sasl/SASLAuthenticator.hpp" + #include "vmime/security/sasl/defaultSASLAuthenticator.hpp" + #include "vmime/security/sasl/SASLContext.hpp" + #include "vmime/security/sasl/SASLSession.hpp" +#endif // VMIME_HAVE_SASL_SUPPORT + +// Messaging features +#if VMIME_HAVE_MESSAGING_FEATURES + #include "vmime/net/socket.hpp" + + #include "vmime/net/serviceFactory.hpp" + #include "vmime/net/store.hpp" + #include "vmime/net/transport.hpp" + + #include "vmime/net/session.hpp" + + #include "vmime/net/folder.hpp" + #include "vmime/net/message.hpp" +#endif // VMIME_HAVE_MESSAGING_FEATURES + +// Net/TLS +#if VMIME_HAVE_TLS_SUPPORT + #include "vmime/security/cert/certificate.hpp" + #include "vmime/security/cert/certificateChain.hpp" + #include "vmime/security/cert/certificateVerifier.hpp" + + #include "vmime/security/cert/X509Certificate.hpp" + + #include "vmime/security/cert/defaultCertificateVerifier.hpp" + + #include "vmime/net/tls/TLSSession.hpp" +#endif // VMIME_HAVE_TLS_SUPPORT + + +#endif // VMIME_INCLUDED diff --git a/src/vmime/word.cpp b/src/vmime/word.cpp new file mode 100644 index 00000000..2ee4d3e7 --- /dev/null +++ b/src/vmime/word.cpp @@ -0,0 +1,793 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/word.hpp" +#include "vmime/text.hpp" + +#include "vmime/utility/stringUtils.hpp" +#include "vmime/parserHelpers.hpp" + +#include "vmime/utility/outputStreamStringAdapter.hpp" +#include "vmime/utility/inputStreamStringAdapter.hpp" + +#include "vmime/utility/encoder/encoder.hpp" +#include "vmime/utility/encoder/b64Encoder.hpp" +#include "vmime/utility/encoder/qpEncoder.hpp" + +#include "vmime/wordEncoder.hpp" + + +namespace vmime +{ + + +word::word() + : m_charset(charset::getLocalCharset()) +{ +} + + +word::word(const word& w) + : headerFieldValue(), m_buffer(w.m_buffer), m_charset(w.m_charset) +{ +} + + +word::word(const string& buffer) // Defaults to local charset + : m_buffer(buffer), m_charset(charset::getLocalCharset()) +{ +} + + +word::word(const string& buffer, const charset& charset) + : m_buffer(buffer), m_charset(charset) +{ +} + + +shared_ptr word::parseNext + (const parsingContext& ctx, const string& buffer, const size_t position, + const size_t end, size_t* newPosition, + bool prevIsEncoded, bool* isEncoded, bool isFirst) +{ + size_t pos = position; + + // Ignore white-spaces: + // - before the first word + // - between two encoded words + // - after the last word + string whiteSpaces; + + while (pos < end && parserHelpers::isSpace(buffer[pos])) + { + whiteSpaces += buffer[pos]; + ++pos; + } + + size_t startPos = pos; + string unencoded; + + const charset defaultCharset = ctx.getInternationalizedEmailSupport() + ? charset(charsets::UTF_8) : charset(charsets::US_ASCII); + + while (pos < end) + { + // End of line: does not occur in the middle of an encoded word. This is + // used to remove folding white-spaces from unencoded text. + if (buffer[pos] == '\n') + { + size_t endPos = pos; + + if (pos > position && buffer[pos - 1] == '\r') + { + ++pos; + --endPos; + } + + while (pos != end && parserHelpers::isSpace(buffer[pos])) + ++pos; + + unencoded += buffer.substr(startPos, endPos - startPos); + + if (pos != end) // ignore white-spaces at end + unencoded += ' '; + + startPos = pos; + continue; + } + // Start of an encoded word + else if (pos + 8 < end && // 8 = "=?(.+)?(.+)?(.*)?=" + buffer[pos] == '=' && buffer[pos + 1] == '?') + { + // Check whether there is some unencoded text before + unencoded += buffer.substr(startPos, pos - startPos); + + if (!unencoded.empty()) + { + if (prevIsEncoded && !isFirst) + unencoded = whiteSpaces + unencoded; + + shared_ptr w = make_shared (unencoded, defaultCharset); + w->setParsedBounds(position, pos); + + if (newPosition) + *newPosition = pos; + + if (isEncoded) + *isEncoded = false; + + return (w); + } + + // ...else find the finish sequence '?=' and return an encoded word + const size_t wordStart = pos; + + pos += 2; + + while (pos < end && buffer[pos] != '?') + ++pos; + + if (pos < end) + { + ++pos; // skip '?' between charset and encoding + + while (pos < end && buffer[pos] != '?') + ++pos; + + if (pos < end) + { + ++pos; // skip '?' between encoding and encoded data + } + } + + while (pos < end) + { + if (buffer[pos] == '\n') + { + // End of line not allowed in the middle of an encoded word: + // treat this text as unencoded text (see *). + break; + } + else if (buffer[pos] == '?' && pos + 1 < end && buffer[pos + 1] == '=') + { + // Found the finish sequence + break; + } + + ++pos; + } + + if (pos == end) // not a valid word (no finish sequence) + continue; + else if (buffer[pos] == '\n') // (*) + continue; + + pos += 2; // ?= + + shared_ptr w = make_shared (); + w->parse(ctx, buffer, wordStart, pos, NULL); + + if (newPosition) + *newPosition = pos; + + if (isEncoded) + *isEncoded = true; + + return (w); + } + + ++pos; + } + + if (startPos != end) + { + if (prevIsEncoded && !isFirst) + unencoded = whiteSpaces + unencoded; + + unencoded += buffer.substr(startPos, end - startPos); + } + + // Treat unencoded text at the end of the buffer + if (!unencoded.empty()) + { + shared_ptr w = make_shared (unencoded, defaultCharset); + w->setParsedBounds(position, end); + + if (newPosition) + *newPosition = end; + + if (isEncoded) + *isEncoded = false; + + return (w); + } + + return (null); +} + + +const std::vector > word::parseMultiple + (const parsingContext& ctx, const string& buffer, const size_t position, + const size_t end, size_t* newPosition) +{ + std::vector > res; + shared_ptr w; + + size_t pos = position; + + bool prevIsEncoded = false; + + while ((w = word::parseNext(ctx, buffer, pos, end, &pos, prevIsEncoded, &prevIsEncoded, (w == NULL))) != NULL) + res.push_back(w); + + if (newPosition) + *newPosition = pos; + + return (res); +} + + +void word::parseImpl + (const parsingContext& ctx, const string& buffer, const size_t position, + const size_t end, size_t* newPosition) +{ + if (position + 6 < end && // 6 = "=?(.+)?(.*)?=" + buffer[position] == '=' && buffer[position + 1] == '?') + { + string::const_iterator p = buffer.begin() + position + 2; + const string::const_iterator pend = buffer.begin() + end; + + const string::const_iterator charsetPos = p; + + for ( ; p != pend && *p != '?' ; ++p) {} + + if (p != pend) // a charset is specified + { + const string::const_iterator charsetEnd = p; + const string::const_iterator encPos = ++p; // skip '?' + + for ( ; p != pend && *p != '?' ; ++p) {} + + if (p != pend) // an encoding is specified + { + //const string::const_iterator encEnd = p; + const string::const_iterator dataPos = ++p; // skip '?' + + for ( ; p != pend && !(*p == '?' && *(p + 1) == '=') ; ++p) {} + + if (p != pend) // some data is specified + { + const string::const_iterator dataEnd = p; + p += 2; // skip '?=' + + utility::encoder::encoder* theEncoder = NULL; + + // Base-64 encoding + if (*encPos == 'B' || *encPos == 'b') + { + theEncoder = new utility::encoder::b64Encoder(); + } + // Quoted-Printable encoding + else if (*encPos == 'Q' || *encPos == 'q') + { + theEncoder = new utility::encoder::qpEncoder(); + theEncoder->getProperties()["rfc2047"] = true; + } + + if (theEncoder) + { + // Decode text + string decodedBuffer; + + utility::inputStreamStringAdapter ein(string(dataPos, dataEnd)); + utility::outputStreamStringAdapter eout(decodedBuffer); + + theEncoder->decode(ein, eout); + delete (theEncoder); + + m_buffer = decodedBuffer; + m_charset = charset(string(charsetPos, charsetEnd)); + + setParsedBounds(position, p - buffer.begin()); + + if (newPosition) + *newPosition = (p - buffer.begin()); + + return; + } + } + } + } + } + + // Unknown encoding or malformed encoded word: treat the buffer as ordinary text (RFC-2047, Page 9). + m_buffer = string(buffer.begin() + position, buffer.begin() + end); + m_charset = ctx.getInternationalizedEmailSupport() + ? charset(charsets::UTF_8) : charset(charsets::US_ASCII); + + setParsedBounds(position, end); + + if (newPosition) + *newPosition = end; +} + + +void word::generateImpl(const generationContext& ctx, utility::outputStream& os, + const size_t curLinePos, size_t* newLinePos) const +{ + generate(ctx, os, curLinePos, newLinePos, 0, NULL); +} + + +void word::generate(const generationContext& ctx, utility::outputStream& os, + const size_t curLinePos, size_t* newLinePos, const int flags, + generatorState* state) const +{ + size_t curLineLength = curLinePos; + + generatorState defaultGeneratorState; + + if (state == NULL) + state = &defaultGeneratorState; + + // Find out if encoding is forced or required by contents + charset + bool encodingNeeded = false; + + if ((flags & text::FORCE_NO_ENCODING) != 0) + encodingNeeded = false; + else if ((flags & text::FORCE_ENCODING) != 0) + encodingNeeded = true; + else // auto-detect + encodingNeeded = wordEncoder::isEncodingNeeded(ctx, m_buffer, m_charset); + + // If text does not need to be encoded, quote the buffer (no folding is performed). + if (!encodingNeeded && + (flags & text::QUOTE_IF_NEEDED) && + utility::stringUtils::needQuoting(m_buffer)) + { + const string quoted = utility::stringUtils::quote(m_buffer, "\\\"", "\\"); + + os << '"' << quoted << '"'; + curLineLength += 1 + quoted.length() + 1; + } + // If possible and requested (with flag), quote the buffer (no folding is performed). + // Quoting is possible if and only if: + // - the buffer does not need to be encoded + // - the buffer does not contain quoting character (") + // - there is enough remaining space on the current line to hold the whole buffer + else if (!encodingNeeded && + (flags & text::QUOTE_IF_POSSIBLE) && + m_buffer.find('"') == string::npos && + (curLineLength + 2 /* 2 x " */ + m_buffer.length()) < ctx.getMaxLineLength()) + { + os << '"' << m_buffer << '"'; + curLineLength += 2 + m_buffer.length(); + } + // We will fold lines without encoding them. + else if (!encodingNeeded) + { + string buffer; + + if (ctx.getInternationalizedEmailSupport()) + { + // Convert the buffer to UTF-8 + charset::convert(m_buffer, buffer, m_charset, charsets::UTF_8); + } + else + { + // Leave the buffer as-is + buffer = m_buffer; + } + + // Here, we could have the following conditions: + // + // * a maximum line length of N bytes + // * a buffer containing N+1 bytes, with no whitespace + // + // Look in the buffer for any run (ie. whitespace-separated sequence) which + // is longer than the maximum line length. If there is one, then force encoding, + // so that no generated line is longer than the maximum line length. + size_t maxRunLength = 0; + size_t curRunLength = 0; + + for (string::const_iterator p = buffer.begin(), end = buffer.end() ; p != end ; ++p) + { + if (parserHelpers::isSpace(*p)) + { + maxRunLength = std::max(maxRunLength, curRunLength); + curRunLength = 0; + } + else + { + curRunLength++; + } + } + + maxRunLength = std::max(maxRunLength, curRunLength); + + if (((flags & text::FORCE_NO_ENCODING) == 0) && maxRunLength >= ctx.getMaxLineLength() - 3) + { + // Generate with encoding forced + generate(ctx, os, curLinePos, newLinePos, flags | text::FORCE_ENCODING, state); + return; + } + + // Output runs, and fold line when a whitespace is encountered + string::const_iterator lastWSpos = buffer.end(); // last white-space position + string::const_iterator curLineStart = buffer.begin(); // current line start + + string::const_iterator p = buffer.begin(); + const string::const_iterator end = buffer.end(); + + bool finished = false; + bool newLine = false; + + while (!finished) + { + for ( ; p != end ; ++p, ++curLineLength) + { + // Exceeded maximum line length, but we have found a white-space + // where we can cut the line... + if (curLineLength >= ctx.getMaxLineLength() && lastWSpos != end) + break; + + if (*p == ' ' || *p == '\t') + { + // Remember the position of this white-space character + lastWSpos = p; + } + } + + if (p != end) + ++curLineLength; + + if (p == end || lastWSpos == end) + { + // If we are here, it means that we have found no whitespace + // before the first "maxLineLength" characters. In this case, + // we write the full line no matter of the max line length... + + if (!newLine && p != end && lastWSpos == end && + !state->isFirstWord && curLineStart == buffer.begin()) + { + // Here, we are continuing on the line of previous encoded + // word, but there is not even enough space to put the + // first word of this line, so we start a new line. + if (flags & text::NO_NEW_LINE_SEQUENCE) + { + os << CRLF; + curLineLength = 0; + + state->lastCharIsSpace = true; + } + else + { + os << NEW_LINE_SEQUENCE; + curLineLength = NEW_LINE_SEQUENCE_LENGTH; + + state->lastCharIsSpace = true; + } + + p = curLineStart; + lastWSpos = end; + newLine = true; + } + else + { + if (!state->isFirstWord && state->prevWordIsEncoded && !state->lastCharIsSpace && !parserHelpers::isSpace(*curLineStart)) + os << " "; // Separate from previous word + + os << string(curLineStart, p); + + if (p != buffer.begin() && parserHelpers::isSpace(*(p - 1))) + state->lastCharIsSpace = true; + else + state->lastCharIsSpace = false; + + if (p == end) + { + finished = true; + } + else + { + if (flags & text::NO_NEW_LINE_SEQUENCE) + { + os << CRLF; + curLineLength = 0; + } + else + { + os << NEW_LINE_SEQUENCE; + curLineLength = NEW_LINE_SEQUENCE_LENGTH; + } + + curLineStart = p; + lastWSpos = end; + newLine = true; + } + } + } + else + { + // In this case, there will not be enough space on the line for all the + // characters _after_ the last white-space; so we cut the line at this + // last white-space. + +#if 1 + if (curLineLength != NEW_LINE_SEQUENCE_LENGTH && !state->isFirstWord && state->prevWordIsEncoded) + os << " "; // Separate from previous word +#endif + + os << string(curLineStart, lastWSpos); + + if (lastWSpos > curLineStart && parserHelpers::isSpace(*(lastWSpos - 1))) + state->lastCharIsSpace = true; + else + state->lastCharIsSpace = false; + + if (flags & text::NO_NEW_LINE_SEQUENCE) + { + os << CRLF; + curLineLength = 0; + + state->lastCharIsSpace = true; + } + else + { + os << NEW_LINE_SEQUENCE; + curLineLength = NEW_LINE_SEQUENCE_LENGTH; + + state->lastCharIsSpace = true; + } + + curLineStart = lastWSpos + 1; + + p = lastWSpos + 1; + lastWSpos = end; + newLine = true; + } + } + } + /* + RFC #2047: + 4. Encodings + + Initially, the legal values for "encoding" are "Q" and "B". These + encodings are described below. The "Q" encoding is recommended for + use when most of the characters to be encoded are in the ASCII + character set; otherwise, the "B" encoding should be used. + Nevertheless, a mail reader which claims to recognize 'encoded-word's + MUST be able to accept either encoding for any character set which it + supports. + */ + else + { + // We will encode _AND_ fold lines + + /* + RFC #2047: + 2. Syntax of encoded-words + + " While there is no limit to the length of a multiple-line header + field, each line of a header field that contains one or more + 'encoded-word's is limited to 76 characters. " + */ + + const size_t maxLineLength3 = + (ctx.getMaxLineLength() == lineLengthLimits::infinite) + ? ctx.getMaxLineLength() + : std::min(ctx.getMaxLineLength(), static_cast (76)); + + wordEncoder wordEnc(m_buffer, m_charset); + + const string wordStart("=?" + m_charset.getName() + "?" + + (wordEnc.getEncoding() == wordEncoder::ENCODING_B64 ? 'B' : 'Q') + "?"); + const string wordEnd("?="); + + const size_t minWordLength = wordStart.length() + wordEnd.length(); + const size_t maxLineLength2 = (maxLineLength3 < minWordLength + 1) + ? maxLineLength3 + minWordLength + 1 : maxLineLength3; + + // Checks whether remaining space on this line is usable. If too few + // characters can be encoded, start a new line. + bool startNewLine = true; + + if (curLineLength + 2 < maxLineLength2) + { + const size_t remainingSpaceOnLine = maxLineLength2 - curLineLength - 2; + + if (remainingSpaceOnLine < minWordLength + 10) + { + // Space for no more than 10 encoded chars! + // It is not worth while to continue on this line... + startNewLine = true; + } + else + { + // OK, there is enough usable space on the current line. + startNewLine = false; + } + } + + if (startNewLine) + { + os << NEW_LINE_SEQUENCE; + curLineLength = NEW_LINE_SEQUENCE_LENGTH; + + state->lastCharIsSpace = true; + } + + // Encode and fold input buffer + if (!startNewLine && !state->isFirstWord && !state->lastCharIsSpace) + { + os << " "; // Separate from previous word + ++curLineLength; + + state->lastCharIsSpace = true; + } + + for (unsigned int i = 0 ; ; ++i) + { + // Compute the number of encoded chars that will fit on this line + const size_t fit = maxLineLength2 - minWordLength + - (i == 0 ? curLineLength : NEW_LINE_SEQUENCE_LENGTH); + + // Get the next encoded chunk + const string chunk = wordEnc.getNextChunk(fit); + + if (chunk.empty()) + break; + + // Start a new encoded word + if (i != 0) + { + os << NEW_LINE_SEQUENCE; + curLineLength = NEW_LINE_SEQUENCE_LENGTH; + } + + os << wordStart; + curLineLength += minWordLength; + + os << chunk; + curLineLength += chunk.length(); + + // End of the encoded word + os << wordEnd; + + state->prevWordIsEncoded = true; + state->lastCharIsSpace = false; + } + } + + if (newLinePos) + *newLinePos = curLineLength; + + state->isFirstWord = false; +} + + +word& word::operator=(const word& w) +{ + m_buffer = w.m_buffer; + m_charset = w.m_charset; + return (*this); +} + + +word& word::operator=(const string& s) +{ + m_buffer = s; + m_charset = charset::getLocalCharset(); + return (*this); +} + + +void word::copyFrom(const component& other) +{ + const word& w = dynamic_cast (other); + + m_buffer = w.m_buffer; + m_charset = w.m_charset; +} + + +bool word::operator==(const word& w) const +{ + return (m_charset == w.m_charset && m_buffer == w.m_buffer); +} + + +bool word::operator!=(const word& w) const +{ + return (m_charset != w.m_charset || m_buffer != w.m_buffer); +} + + +const string word::getConvertedText(const charset& dest, const charsetConverterOptions& opts) const +{ + string out; + + try + { + charset::convert(m_buffer, out, m_charset, dest, opts); + } + catch (vmime::exceptions::charset_conv_error& e) + { + // Do not fail if charset is not recognized: + // copy 'word' as raw text + out = m_buffer; + } + + return (out); +} + + +shared_ptr word::clone() const +{ + return make_shared (m_buffer, m_charset); +} + + +const charset& word::getCharset() const +{ + return (m_charset); +} + + +void word::setCharset(const charset& ch) +{ + m_charset = ch; +} + + +const string& word::getBuffer() const +{ + return (m_buffer); +} + + +string& word::getBuffer() +{ + return (m_buffer); +} + + +bool word::isEmpty() const +{ + return m_buffer.empty(); +} + + +void word::setBuffer(const string& buffer) +{ + m_buffer = buffer; +} + + +const std::vector > word::getChildComponents() +{ + return std::vector >(); +} + + +} // vmime diff --git a/src/vmime/word.hpp b/src/vmime/word.hpp new file mode 100644 index 00000000..a6e2402e --- /dev/null +++ b/src/vmime/word.hpp @@ -0,0 +1,195 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_WORD_HPP_INCLUDED +#define VMIME_WORD_HPP_INCLUDED + + +#include "vmime/headerFieldValue.hpp" +#include "vmime/charset.hpp" +#include "vmime/charsetConverterOptions.hpp" + + +namespace vmime +{ + + +/** A class that encapsulates an encoded-word (RFC-2047): + * some text encoded into one specified charset. + */ + +class VMIME_EXPORT word : public headerFieldValue +{ + friend class text; + +public: + + word(); + word(const word& w); + word(const string& buffer); // Defaults to local charset + word(const string& buffer, const charset& charset); + + /** Return the raw data for this encoded word. + * + * @return raw data buffer + */ + const string& getBuffer() const; + + /** Return the raw data for this encoded word. + * + * @return raw data buffer + */ + string& getBuffer(); + + /** Tests whether this word is empty. + * + * @return true if the buffer is empty, false otherwise + */ + bool isEmpty() const; + + /** Set the raw data for this encoded word. + * + * @param buffer raw data buffer + */ + void setBuffer(const string& buffer); + + /** Return the charset of this word. + * + * @return charset for this word + */ + const charset& getCharset() const; + + /** Set the charset of this word. + * + * @param ch charset of this word + */ + void setCharset(const charset& ch); + + + word& operator=(const word& w); + word& operator=(const string& s); + + bool operator==(const word& w) const; + bool operator!=(const word& w) const; + + /** Return the contained text converted to the specified charset. + * + * @param dest output charset + * @param opts options for charset conversion + * @return word converted to the specified charset + */ + const string getConvertedText(const charset& dest, + const charsetConverterOptions& opts = charsetConverterOptions()) const; + + /** Replace data in this word by data in other word. + * + * @param other other word to copy data from + */ + void copyFrom(const component& other); + + /** Clone this word. + * + * @return a copy of this word + */ + shared_ptr clone() const; + + +#ifndef VMIME_BUILDING_DOC + class generatorState + { + public: + + generatorState() + : isFirstWord(true), prevWordIsEncoded(false), lastCharIsSpace(false) + { + } + + bool isFirstWord; + bool prevWordIsEncoded; + bool lastCharIsSpace; + }; +#endif + + +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; + +public: + + using component::generate; + +#ifndef VMIME_BUILDING_DOC + void generate + (const generationContext& ctx, + utility::outputStream& os, + const size_t curLinePos, + size_t* newLinePos, + const int flags, + generatorState* state) const; +#endif + + const std::vector > getChildComponents(); + +private: + + static shared_ptr parseNext + (const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition, + bool prevIsEncoded, + bool* isEncoded, + bool isFirst); + + static const std::vector > parseMultiple + (const parsingContext& ctx, + const string& buffer, + const size_t position, + const size_t end, + size_t* newPosition); + + + // The "m_buffer" of this word holds the data, and this data is encoded + // in the specified "m_charset". + string m_buffer; + charset m_charset; +}; + + +} // vmime + + +#endif // VMIME_WORD_HPP_INCLUDED diff --git a/src/vmime/wordEncoder.cpp b/src/vmime/wordEncoder.cpp new file mode 100644 index 00000000..421a9ecd --- /dev/null +++ b/src/vmime/wordEncoder.cpp @@ -0,0 +1,287 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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/wordEncoder.hpp" + +#include "vmime/exception.hpp" +#include "vmime/charsetConverter.hpp" + +#include "vmime/encoding.hpp" + +#include "vmime/utility/encoder/b64Encoder.hpp" +#include "vmime/utility/encoder/qpEncoder.hpp" + +#include "vmime/utility/stringUtils.hpp" + +#include "vmime/utility/outputStreamStringAdapter.hpp" +#include "vmime/utility/inputStreamStringAdapter.hpp" + + +namespace vmime +{ + + +wordEncoder::wordEncoder(const string& buffer, const charset& charset, const Encoding encoding) + : m_buffer(buffer), m_pos(0), m_length(buffer.length()), m_charset(charset), m_encoding(encoding) +{ + try + { + string utf8Buffer; + + vmime::charset::convert + (buffer, utf8Buffer, charset, vmime::charset(charsets::UTF_8)); + + m_buffer = utf8Buffer; + m_length = utf8Buffer.length(); + + m_simple = false; + } + catch (exceptions::charset_conv_error&) + { + // Ignore exception. + // We will fall back on simple encoding. + m_simple = true; + } + + if (m_encoding == ENCODING_AUTO) + m_encoding = guessBestEncoding(buffer, charset); + + if (m_encoding == ENCODING_B64) + { + m_encoder = make_shared (); + } + else // ENCODING_QP + { + m_encoder = make_shared (); + m_encoder->getProperties()["rfc2047"] = true; + } +} + + +static size_t getUTF8CharLength + (const string& buffer, const size_t pos, const size_t length) +{ + // Gives the number of extra bytes in a UTF8 char, given the leading char + static const unsigned char UTF8_EXTRA_BYTES[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, 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, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 + }; + + const unsigned char c = buffer[pos]; + const unsigned char n = UTF8_EXTRA_BYTES[c]; + + if (n < length - pos) + return n + 1; + else + return 1; +} + + +const string wordEncoder::getNextChunk(const size_t maxLength) +{ + const size_t remaining = m_length - m_pos; + + if (remaining == 0) + return string(); + + vmime::string chunk; + vmime::utility::outputStreamStringAdapter chunkStream(chunk); + + // Simple encoding + if (m_simple) + { + // WARNING! Simple encoding can encode a non-integral number of + // characters and then may generate incorrectly-formed words! + + if (m_encoding == ENCODING_B64) + { + // Here, we have a formula to compute the maximum number of source + // bytes to encode knowing the maximum number of encoded chars. In + // Base64 encoding, 3 bytes of input provide 4 bytes of output. + const size_t inputCount = + std::min(remaining, (maxLength > 1) ? ((maxLength - 1) * 3) / 4 : 1); + + // Encode chunk + utility::inputStreamStringAdapter in(m_buffer, m_pos, m_pos + inputCount); + + m_encoder->encode(in, chunkStream); + m_pos += inputCount; + } + else // ENCODING_QP + { + // Compute exactly how much input bytes are needed to have an output + // string length of less than 'maxLength' bytes. In Quoted-Printable + // encoding, encoded bytes take 3 bytes. + size_t inputCount = 0; + size_t outputCount = 0; + + while ((inputCount == 0 || outputCount < maxLength) && (inputCount < remaining)) + { + const unsigned char c = m_buffer[m_pos + inputCount]; + + inputCount++; + outputCount += utility::encoder::qpEncoder::RFC2047_getEncodedLength(c); + } + + // Encode chunk + utility::inputStreamStringAdapter in(m_buffer, m_pos, m_pos + inputCount); + + m_encoder->encode(in, chunkStream); + m_pos += inputCount; + } + } + // Fully RFC-compliant encoding + else + { + shared_ptr conv = charsetConverter::create(charsets::UTF_8, m_charset); + + size_t inputCount = 0; + size_t outputCount = 0; + string encodeBuffer; + + while ((inputCount == 0 || outputCount < maxLength) && (inputCount < remaining)) + { + // Get the next UTF8 character + const size_t inputCharLength = + getUTF8CharLength(m_buffer, m_pos + inputCount, m_length); + + const string inputChar(m_buffer.begin() + m_pos + inputCount, + m_buffer.begin() + m_pos + inputCount + inputCharLength); + + // Convert back to original encoding + string encodeBytes; + conv->convert(inputChar, encodeBytes); + + encodeBuffer += encodeBytes; + + // Compute number of output bytes + if (m_encoding == ENCODING_B64) + { + outputCount = std::max(static_cast (4), + (encodeBuffer.length() * 4) / 3); + } + else // ENCODING_QP + { + for (size_t i = 0, n = encodeBytes.length() ; i < n ; ++i) + { + const unsigned char c = encodeBytes[i]; + outputCount += utility::encoder::qpEncoder::RFC2047_getEncodedLength(c); + } + } + + inputCount += inputCharLength; + } + + // Encode chunk + utility::inputStreamStringAdapter in(encodeBuffer); + + m_encoder->encode(in, chunkStream); + m_pos += inputCount; + } + + return chunk; +} + + +wordEncoder::Encoding wordEncoder::getEncoding() const +{ + return m_encoding; +} + + +// static +bool wordEncoder::isEncodingNeeded + (const generationContext& ctx, const string& buffer, const charset& charset) +{ + if (!ctx.getInternationalizedEmailSupport()) + { + // Charset-specific encoding + encoding recEncoding; + + if (charset.getRecommendedEncoding(recEncoding)) + return true; + + // No encoding is needed if the buffer only contains ASCII chars + if (utility::stringUtils::findFirstNonASCIIchar(buffer.begin(), buffer.end()) != string::npos) + return true; + } + + // Force encoding when there are only ASCII chars, but there is + // also at least one of '\n' or '\r' (header fields) + if (buffer.find_first_of("\n\r") != string::npos) + return true; + + // If any RFC-2047 sequence is found in the buffer, encode it + if (buffer.find("=?") != string::npos || buffer.find("?=") != string::npos) + return true; + + return false; +} + + +// static +wordEncoder::Encoding wordEncoder::guessBestEncoding + (const string& buffer, const charset& charset) +{ + // Charset-specific encoding + encoding recEncoding; + + if (charset.getRecommendedEncoding(recEncoding)) + { + if (recEncoding == encoding(encodingTypes::QUOTED_PRINTABLE)) + return ENCODING_QP; + else + return ENCODING_B64; + } + + // Use Base64 if more than 40% non-ASCII, or Quoted-Printable else (default) + const size_t asciiCount = + utility::stringUtils::countASCIIchars(buffer.begin(), buffer.end()); + + const size_t asciiPercent = + (buffer.length() == 0 ? 100 : (100 * asciiCount) / buffer.length()); + + if (asciiPercent < 60) + return ENCODING_B64; + else + return ENCODING_QP; +} + + +} // vmime + diff --git a/src/vmime/wordEncoder.hpp b/src/vmime/wordEncoder.hpp new file mode 100644 index 00000000..6f652fa2 --- /dev/null +++ b/src/vmime/wordEncoder.hpp @@ -0,0 +1,112 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules 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_WORDENCODER_HPP_INCLUDED +#define VMIME_WORDENCODER_HPP_INCLUDED + + +#include "vmime/charset.hpp" + + +namespace vmime +{ + + +namespace utility { +namespace encoder { + +class encoder; + +} // encoder +} // utility + + +/** Encodes words following RFC-2047. + */ + +class VMIME_EXPORT wordEncoder +{ +public: + + /** Available encodings for RFC-2047. */ + enum Encoding + { + ENCODING_AUTO, + ENCODING_QP, + ENCODING_B64 + }; + + + wordEncoder(const string& buffer, const charset& charset, const Encoding encoding = ENCODING_AUTO); + + + /** Return the next chunk in the word. + * + * @param maxLength maximal length of the chunk + * @return next chunk, of maximal length 'maxLength' if possible + */ + const string getNextChunk(const size_t maxLength); + + /** Return the encoding used. + * + * @return encoding + */ + Encoding getEncoding() const; + + /** Test whether RFC-2047 encoding is needed. + * + * @param ctx generation context + * @param buffer buffer to analyze + * @param charset charset of the buffer + * @return true if encoding is needed, false otherwise. + */ + static bool isEncodingNeeded(const generationContext& ctx, const string& buffer, const charset& charset); + + /** Guess the best RFC-2047 encoding to use for the specified buffer. + * + * @param buffer buffer to analyze + * @param charset charset of the buffer + * @return RFC-2047 encoding + */ + static Encoding guessBestEncoding(const string& buffer, const charset& charset); + +private: + + string m_buffer; + size_t m_pos; + size_t m_length; + + bool m_simple; + + charset m_charset; + Encoding m_encoding; + + shared_ptr m_encoder; +}; + + +} // vmime + + +#endif // VMIME_WORDENCODER_HPP_INCLUDED + diff --git a/src/word.cpp b/src/word.cpp deleted file mode 100644 index 2ee4d3e7..00000000 --- a/src/word.cpp +++ /dev/null @@ -1,793 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/word.hpp" -#include "vmime/text.hpp" - -#include "vmime/utility/stringUtils.hpp" -#include "vmime/parserHelpers.hpp" - -#include "vmime/utility/outputStreamStringAdapter.hpp" -#include "vmime/utility/inputStreamStringAdapter.hpp" - -#include "vmime/utility/encoder/encoder.hpp" -#include "vmime/utility/encoder/b64Encoder.hpp" -#include "vmime/utility/encoder/qpEncoder.hpp" - -#include "vmime/wordEncoder.hpp" - - -namespace vmime -{ - - -word::word() - : m_charset(charset::getLocalCharset()) -{ -} - - -word::word(const word& w) - : headerFieldValue(), m_buffer(w.m_buffer), m_charset(w.m_charset) -{ -} - - -word::word(const string& buffer) // Defaults to local charset - : m_buffer(buffer), m_charset(charset::getLocalCharset()) -{ -} - - -word::word(const string& buffer, const charset& charset) - : m_buffer(buffer), m_charset(charset) -{ -} - - -shared_ptr word::parseNext - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition, - bool prevIsEncoded, bool* isEncoded, bool isFirst) -{ - size_t pos = position; - - // Ignore white-spaces: - // - before the first word - // - between two encoded words - // - after the last word - string whiteSpaces; - - while (pos < end && parserHelpers::isSpace(buffer[pos])) - { - whiteSpaces += buffer[pos]; - ++pos; - } - - size_t startPos = pos; - string unencoded; - - const charset defaultCharset = ctx.getInternationalizedEmailSupport() - ? charset(charsets::UTF_8) : charset(charsets::US_ASCII); - - while (pos < end) - { - // End of line: does not occur in the middle of an encoded word. This is - // used to remove folding white-spaces from unencoded text. - if (buffer[pos] == '\n') - { - size_t endPos = pos; - - if (pos > position && buffer[pos - 1] == '\r') - { - ++pos; - --endPos; - } - - while (pos != end && parserHelpers::isSpace(buffer[pos])) - ++pos; - - unencoded += buffer.substr(startPos, endPos - startPos); - - if (pos != end) // ignore white-spaces at end - unencoded += ' '; - - startPos = pos; - continue; - } - // Start of an encoded word - else if (pos + 8 < end && // 8 = "=?(.+)?(.+)?(.*)?=" - buffer[pos] == '=' && buffer[pos + 1] == '?') - { - // Check whether there is some unencoded text before - unencoded += buffer.substr(startPos, pos - startPos); - - if (!unencoded.empty()) - { - if (prevIsEncoded && !isFirst) - unencoded = whiteSpaces + unencoded; - - shared_ptr w = make_shared (unencoded, defaultCharset); - w->setParsedBounds(position, pos); - - if (newPosition) - *newPosition = pos; - - if (isEncoded) - *isEncoded = false; - - return (w); - } - - // ...else find the finish sequence '?=' and return an encoded word - const size_t wordStart = pos; - - pos += 2; - - while (pos < end && buffer[pos] != '?') - ++pos; - - if (pos < end) - { - ++pos; // skip '?' between charset and encoding - - while (pos < end && buffer[pos] != '?') - ++pos; - - if (pos < end) - { - ++pos; // skip '?' between encoding and encoded data - } - } - - while (pos < end) - { - if (buffer[pos] == '\n') - { - // End of line not allowed in the middle of an encoded word: - // treat this text as unencoded text (see *). - break; - } - else if (buffer[pos] == '?' && pos + 1 < end && buffer[pos + 1] == '=') - { - // Found the finish sequence - break; - } - - ++pos; - } - - if (pos == end) // not a valid word (no finish sequence) - continue; - else if (buffer[pos] == '\n') // (*) - continue; - - pos += 2; // ?= - - shared_ptr w = make_shared (); - w->parse(ctx, buffer, wordStart, pos, NULL); - - if (newPosition) - *newPosition = pos; - - if (isEncoded) - *isEncoded = true; - - return (w); - } - - ++pos; - } - - if (startPos != end) - { - if (prevIsEncoded && !isFirst) - unencoded = whiteSpaces + unencoded; - - unencoded += buffer.substr(startPos, end - startPos); - } - - // Treat unencoded text at the end of the buffer - if (!unencoded.empty()) - { - shared_ptr w = make_shared (unencoded, defaultCharset); - w->setParsedBounds(position, end); - - if (newPosition) - *newPosition = end; - - if (isEncoded) - *isEncoded = false; - - return (w); - } - - return (null); -} - - -const std::vector > word::parseMultiple - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ - std::vector > res; - shared_ptr w; - - size_t pos = position; - - bool prevIsEncoded = false; - - while ((w = word::parseNext(ctx, buffer, pos, end, &pos, prevIsEncoded, &prevIsEncoded, (w == NULL))) != NULL) - res.push_back(w); - - if (newPosition) - *newPosition = pos; - - return (res); -} - - -void word::parseImpl - (const parsingContext& ctx, const string& buffer, const size_t position, - const size_t end, size_t* newPosition) -{ - if (position + 6 < end && // 6 = "=?(.+)?(.*)?=" - buffer[position] == '=' && buffer[position + 1] == '?') - { - string::const_iterator p = buffer.begin() + position + 2; - const string::const_iterator pend = buffer.begin() + end; - - const string::const_iterator charsetPos = p; - - for ( ; p != pend && *p != '?' ; ++p) {} - - if (p != pend) // a charset is specified - { - const string::const_iterator charsetEnd = p; - const string::const_iterator encPos = ++p; // skip '?' - - for ( ; p != pend && *p != '?' ; ++p) {} - - if (p != pend) // an encoding is specified - { - //const string::const_iterator encEnd = p; - const string::const_iterator dataPos = ++p; // skip '?' - - for ( ; p != pend && !(*p == '?' && *(p + 1) == '=') ; ++p) {} - - if (p != pend) // some data is specified - { - const string::const_iterator dataEnd = p; - p += 2; // skip '?=' - - utility::encoder::encoder* theEncoder = NULL; - - // Base-64 encoding - if (*encPos == 'B' || *encPos == 'b') - { - theEncoder = new utility::encoder::b64Encoder(); - } - // Quoted-Printable encoding - else if (*encPos == 'Q' || *encPos == 'q') - { - theEncoder = new utility::encoder::qpEncoder(); - theEncoder->getProperties()["rfc2047"] = true; - } - - if (theEncoder) - { - // Decode text - string decodedBuffer; - - utility::inputStreamStringAdapter ein(string(dataPos, dataEnd)); - utility::outputStreamStringAdapter eout(decodedBuffer); - - theEncoder->decode(ein, eout); - delete (theEncoder); - - m_buffer = decodedBuffer; - m_charset = charset(string(charsetPos, charsetEnd)); - - setParsedBounds(position, p - buffer.begin()); - - if (newPosition) - *newPosition = (p - buffer.begin()); - - return; - } - } - } - } - } - - // Unknown encoding or malformed encoded word: treat the buffer as ordinary text (RFC-2047, Page 9). - m_buffer = string(buffer.begin() + position, buffer.begin() + end); - m_charset = ctx.getInternationalizedEmailSupport() - ? charset(charsets::UTF_8) : charset(charsets::US_ASCII); - - setParsedBounds(position, end); - - if (newPosition) - *newPosition = end; -} - - -void word::generateImpl(const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos) const -{ - generate(ctx, os, curLinePos, newLinePos, 0, NULL); -} - - -void word::generate(const generationContext& ctx, utility::outputStream& os, - const size_t curLinePos, size_t* newLinePos, const int flags, - generatorState* state) const -{ - size_t curLineLength = curLinePos; - - generatorState defaultGeneratorState; - - if (state == NULL) - state = &defaultGeneratorState; - - // Find out if encoding is forced or required by contents + charset - bool encodingNeeded = false; - - if ((flags & text::FORCE_NO_ENCODING) != 0) - encodingNeeded = false; - else if ((flags & text::FORCE_ENCODING) != 0) - encodingNeeded = true; - else // auto-detect - encodingNeeded = wordEncoder::isEncodingNeeded(ctx, m_buffer, m_charset); - - // If text does not need to be encoded, quote the buffer (no folding is performed). - if (!encodingNeeded && - (flags & text::QUOTE_IF_NEEDED) && - utility::stringUtils::needQuoting(m_buffer)) - { - const string quoted = utility::stringUtils::quote(m_buffer, "\\\"", "\\"); - - os << '"' << quoted << '"'; - curLineLength += 1 + quoted.length() + 1; - } - // If possible and requested (with flag), quote the buffer (no folding is performed). - // Quoting is possible if and only if: - // - the buffer does not need to be encoded - // - the buffer does not contain quoting character (") - // - there is enough remaining space on the current line to hold the whole buffer - else if (!encodingNeeded && - (flags & text::QUOTE_IF_POSSIBLE) && - m_buffer.find('"') == string::npos && - (curLineLength + 2 /* 2 x " */ + m_buffer.length()) < ctx.getMaxLineLength()) - { - os << '"' << m_buffer << '"'; - curLineLength += 2 + m_buffer.length(); - } - // We will fold lines without encoding them. - else if (!encodingNeeded) - { - string buffer; - - if (ctx.getInternationalizedEmailSupport()) - { - // Convert the buffer to UTF-8 - charset::convert(m_buffer, buffer, m_charset, charsets::UTF_8); - } - else - { - // Leave the buffer as-is - buffer = m_buffer; - } - - // Here, we could have the following conditions: - // - // * a maximum line length of N bytes - // * a buffer containing N+1 bytes, with no whitespace - // - // Look in the buffer for any run (ie. whitespace-separated sequence) which - // is longer than the maximum line length. If there is one, then force encoding, - // so that no generated line is longer than the maximum line length. - size_t maxRunLength = 0; - size_t curRunLength = 0; - - for (string::const_iterator p = buffer.begin(), end = buffer.end() ; p != end ; ++p) - { - if (parserHelpers::isSpace(*p)) - { - maxRunLength = std::max(maxRunLength, curRunLength); - curRunLength = 0; - } - else - { - curRunLength++; - } - } - - maxRunLength = std::max(maxRunLength, curRunLength); - - if (((flags & text::FORCE_NO_ENCODING) == 0) && maxRunLength >= ctx.getMaxLineLength() - 3) - { - // Generate with encoding forced - generate(ctx, os, curLinePos, newLinePos, flags | text::FORCE_ENCODING, state); - return; - } - - // Output runs, and fold line when a whitespace is encountered - string::const_iterator lastWSpos = buffer.end(); // last white-space position - string::const_iterator curLineStart = buffer.begin(); // current line start - - string::const_iterator p = buffer.begin(); - const string::const_iterator end = buffer.end(); - - bool finished = false; - bool newLine = false; - - while (!finished) - { - for ( ; p != end ; ++p, ++curLineLength) - { - // Exceeded maximum line length, but we have found a white-space - // where we can cut the line... - if (curLineLength >= ctx.getMaxLineLength() && lastWSpos != end) - break; - - if (*p == ' ' || *p == '\t') - { - // Remember the position of this white-space character - lastWSpos = p; - } - } - - if (p != end) - ++curLineLength; - - if (p == end || lastWSpos == end) - { - // If we are here, it means that we have found no whitespace - // before the first "maxLineLength" characters. In this case, - // we write the full line no matter of the max line length... - - if (!newLine && p != end && lastWSpos == end && - !state->isFirstWord && curLineStart == buffer.begin()) - { - // Here, we are continuing on the line of previous encoded - // word, but there is not even enough space to put the - // first word of this line, so we start a new line. - if (flags & text::NO_NEW_LINE_SEQUENCE) - { - os << CRLF; - curLineLength = 0; - - state->lastCharIsSpace = true; - } - else - { - os << NEW_LINE_SEQUENCE; - curLineLength = NEW_LINE_SEQUENCE_LENGTH; - - state->lastCharIsSpace = true; - } - - p = curLineStart; - lastWSpos = end; - newLine = true; - } - else - { - if (!state->isFirstWord && state->prevWordIsEncoded && !state->lastCharIsSpace && !parserHelpers::isSpace(*curLineStart)) - os << " "; // Separate from previous word - - os << string(curLineStart, p); - - if (p != buffer.begin() && parserHelpers::isSpace(*(p - 1))) - state->lastCharIsSpace = true; - else - state->lastCharIsSpace = false; - - if (p == end) - { - finished = true; - } - else - { - if (flags & text::NO_NEW_LINE_SEQUENCE) - { - os << CRLF; - curLineLength = 0; - } - else - { - os << NEW_LINE_SEQUENCE; - curLineLength = NEW_LINE_SEQUENCE_LENGTH; - } - - curLineStart = p; - lastWSpos = end; - newLine = true; - } - } - } - else - { - // In this case, there will not be enough space on the line for all the - // characters _after_ the last white-space; so we cut the line at this - // last white-space. - -#if 1 - if (curLineLength != NEW_LINE_SEQUENCE_LENGTH && !state->isFirstWord && state->prevWordIsEncoded) - os << " "; // Separate from previous word -#endif - - os << string(curLineStart, lastWSpos); - - if (lastWSpos > curLineStart && parserHelpers::isSpace(*(lastWSpos - 1))) - state->lastCharIsSpace = true; - else - state->lastCharIsSpace = false; - - if (flags & text::NO_NEW_LINE_SEQUENCE) - { - os << CRLF; - curLineLength = 0; - - state->lastCharIsSpace = true; - } - else - { - os << NEW_LINE_SEQUENCE; - curLineLength = NEW_LINE_SEQUENCE_LENGTH; - - state->lastCharIsSpace = true; - } - - curLineStart = lastWSpos + 1; - - p = lastWSpos + 1; - lastWSpos = end; - newLine = true; - } - } - } - /* - RFC #2047: - 4. Encodings - - Initially, the legal values for "encoding" are "Q" and "B". These - encodings are described below. The "Q" encoding is recommended for - use when most of the characters to be encoded are in the ASCII - character set; otherwise, the "B" encoding should be used. - Nevertheless, a mail reader which claims to recognize 'encoded-word's - MUST be able to accept either encoding for any character set which it - supports. - */ - else - { - // We will encode _AND_ fold lines - - /* - RFC #2047: - 2. Syntax of encoded-words - - " While there is no limit to the length of a multiple-line header - field, each line of a header field that contains one or more - 'encoded-word's is limited to 76 characters. " - */ - - const size_t maxLineLength3 = - (ctx.getMaxLineLength() == lineLengthLimits::infinite) - ? ctx.getMaxLineLength() - : std::min(ctx.getMaxLineLength(), static_cast (76)); - - wordEncoder wordEnc(m_buffer, m_charset); - - const string wordStart("=?" + m_charset.getName() + "?" + - (wordEnc.getEncoding() == wordEncoder::ENCODING_B64 ? 'B' : 'Q') + "?"); - const string wordEnd("?="); - - const size_t minWordLength = wordStart.length() + wordEnd.length(); - const size_t maxLineLength2 = (maxLineLength3 < minWordLength + 1) - ? maxLineLength3 + minWordLength + 1 : maxLineLength3; - - // Checks whether remaining space on this line is usable. If too few - // characters can be encoded, start a new line. - bool startNewLine = true; - - if (curLineLength + 2 < maxLineLength2) - { - const size_t remainingSpaceOnLine = maxLineLength2 - curLineLength - 2; - - if (remainingSpaceOnLine < minWordLength + 10) - { - // Space for no more than 10 encoded chars! - // It is not worth while to continue on this line... - startNewLine = true; - } - else - { - // OK, there is enough usable space on the current line. - startNewLine = false; - } - } - - if (startNewLine) - { - os << NEW_LINE_SEQUENCE; - curLineLength = NEW_LINE_SEQUENCE_LENGTH; - - state->lastCharIsSpace = true; - } - - // Encode and fold input buffer - if (!startNewLine && !state->isFirstWord && !state->lastCharIsSpace) - { - os << " "; // Separate from previous word - ++curLineLength; - - state->lastCharIsSpace = true; - } - - for (unsigned int i = 0 ; ; ++i) - { - // Compute the number of encoded chars that will fit on this line - const size_t fit = maxLineLength2 - minWordLength - - (i == 0 ? curLineLength : NEW_LINE_SEQUENCE_LENGTH); - - // Get the next encoded chunk - const string chunk = wordEnc.getNextChunk(fit); - - if (chunk.empty()) - break; - - // Start a new encoded word - if (i != 0) - { - os << NEW_LINE_SEQUENCE; - curLineLength = NEW_LINE_SEQUENCE_LENGTH; - } - - os << wordStart; - curLineLength += minWordLength; - - os << chunk; - curLineLength += chunk.length(); - - // End of the encoded word - os << wordEnd; - - state->prevWordIsEncoded = true; - state->lastCharIsSpace = false; - } - } - - if (newLinePos) - *newLinePos = curLineLength; - - state->isFirstWord = false; -} - - -word& word::operator=(const word& w) -{ - m_buffer = w.m_buffer; - m_charset = w.m_charset; - return (*this); -} - - -word& word::operator=(const string& s) -{ - m_buffer = s; - m_charset = charset::getLocalCharset(); - return (*this); -} - - -void word::copyFrom(const component& other) -{ - const word& w = dynamic_cast (other); - - m_buffer = w.m_buffer; - m_charset = w.m_charset; -} - - -bool word::operator==(const word& w) const -{ - return (m_charset == w.m_charset && m_buffer == w.m_buffer); -} - - -bool word::operator!=(const word& w) const -{ - return (m_charset != w.m_charset || m_buffer != w.m_buffer); -} - - -const string word::getConvertedText(const charset& dest, const charsetConverterOptions& opts) const -{ - string out; - - try - { - charset::convert(m_buffer, out, m_charset, dest, opts); - } - catch (vmime::exceptions::charset_conv_error& e) - { - // Do not fail if charset is not recognized: - // copy 'word' as raw text - out = m_buffer; - } - - return (out); -} - - -shared_ptr word::clone() const -{ - return make_shared (m_buffer, m_charset); -} - - -const charset& word::getCharset() const -{ - return (m_charset); -} - - -void word::setCharset(const charset& ch) -{ - m_charset = ch; -} - - -const string& word::getBuffer() const -{ - return (m_buffer); -} - - -string& word::getBuffer() -{ - return (m_buffer); -} - - -bool word::isEmpty() const -{ - return m_buffer.empty(); -} - - -void word::setBuffer(const string& buffer) -{ - m_buffer = buffer; -} - - -const std::vector > word::getChildComponents() -{ - return std::vector >(); -} - - -} // vmime diff --git a/src/wordEncoder.cpp b/src/wordEncoder.cpp deleted file mode 100644 index 421a9ecd..00000000 --- a/src/wordEncoder.cpp +++ /dev/null @@ -1,287 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/wordEncoder.hpp" - -#include "vmime/exception.hpp" -#include "vmime/charsetConverter.hpp" - -#include "vmime/encoding.hpp" - -#include "vmime/utility/encoder/b64Encoder.hpp" -#include "vmime/utility/encoder/qpEncoder.hpp" - -#include "vmime/utility/stringUtils.hpp" - -#include "vmime/utility/outputStreamStringAdapter.hpp" -#include "vmime/utility/inputStreamStringAdapter.hpp" - - -namespace vmime -{ - - -wordEncoder::wordEncoder(const string& buffer, const charset& charset, const Encoding encoding) - : m_buffer(buffer), m_pos(0), m_length(buffer.length()), m_charset(charset), m_encoding(encoding) -{ - try - { - string utf8Buffer; - - vmime::charset::convert - (buffer, utf8Buffer, charset, vmime::charset(charsets::UTF_8)); - - m_buffer = utf8Buffer; - m_length = utf8Buffer.length(); - - m_simple = false; - } - catch (exceptions::charset_conv_error&) - { - // Ignore exception. - // We will fall back on simple encoding. - m_simple = true; - } - - if (m_encoding == ENCODING_AUTO) - m_encoding = guessBestEncoding(buffer, charset); - - if (m_encoding == ENCODING_B64) - { - m_encoder = make_shared (); - } - else // ENCODING_QP - { - m_encoder = make_shared (); - m_encoder->getProperties()["rfc2047"] = true; - } -} - - -static size_t getUTF8CharLength - (const string& buffer, const size_t pos, const size_t length) -{ - // Gives the number of extra bytes in a UTF8 char, given the leading char - static const unsigned char UTF8_EXTRA_BYTES[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, 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, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 - }; - - const unsigned char c = buffer[pos]; - const unsigned char n = UTF8_EXTRA_BYTES[c]; - - if (n < length - pos) - return n + 1; - else - return 1; -} - - -const string wordEncoder::getNextChunk(const size_t maxLength) -{ - const size_t remaining = m_length - m_pos; - - if (remaining == 0) - return string(); - - vmime::string chunk; - vmime::utility::outputStreamStringAdapter chunkStream(chunk); - - // Simple encoding - if (m_simple) - { - // WARNING! Simple encoding can encode a non-integral number of - // characters and then may generate incorrectly-formed words! - - if (m_encoding == ENCODING_B64) - { - // Here, we have a formula to compute the maximum number of source - // bytes to encode knowing the maximum number of encoded chars. In - // Base64 encoding, 3 bytes of input provide 4 bytes of output. - const size_t inputCount = - std::min(remaining, (maxLength > 1) ? ((maxLength - 1) * 3) / 4 : 1); - - // Encode chunk - utility::inputStreamStringAdapter in(m_buffer, m_pos, m_pos + inputCount); - - m_encoder->encode(in, chunkStream); - m_pos += inputCount; - } - else // ENCODING_QP - { - // Compute exactly how much input bytes are needed to have an output - // string length of less than 'maxLength' bytes. In Quoted-Printable - // encoding, encoded bytes take 3 bytes. - size_t inputCount = 0; - size_t outputCount = 0; - - while ((inputCount == 0 || outputCount < maxLength) && (inputCount < remaining)) - { - const unsigned char c = m_buffer[m_pos + inputCount]; - - inputCount++; - outputCount += utility::encoder::qpEncoder::RFC2047_getEncodedLength(c); - } - - // Encode chunk - utility::inputStreamStringAdapter in(m_buffer, m_pos, m_pos + inputCount); - - m_encoder->encode(in, chunkStream); - m_pos += inputCount; - } - } - // Fully RFC-compliant encoding - else - { - shared_ptr conv = charsetConverter::create(charsets::UTF_8, m_charset); - - size_t inputCount = 0; - size_t outputCount = 0; - string encodeBuffer; - - while ((inputCount == 0 || outputCount < maxLength) && (inputCount < remaining)) - { - // Get the next UTF8 character - const size_t inputCharLength = - getUTF8CharLength(m_buffer, m_pos + inputCount, m_length); - - const string inputChar(m_buffer.begin() + m_pos + inputCount, - m_buffer.begin() + m_pos + inputCount + inputCharLength); - - // Convert back to original encoding - string encodeBytes; - conv->convert(inputChar, encodeBytes); - - encodeBuffer += encodeBytes; - - // Compute number of output bytes - if (m_encoding == ENCODING_B64) - { - outputCount = std::max(static_cast (4), - (encodeBuffer.length() * 4) / 3); - } - else // ENCODING_QP - { - for (size_t i = 0, n = encodeBytes.length() ; i < n ; ++i) - { - const unsigned char c = encodeBytes[i]; - outputCount += utility::encoder::qpEncoder::RFC2047_getEncodedLength(c); - } - } - - inputCount += inputCharLength; - } - - // Encode chunk - utility::inputStreamStringAdapter in(encodeBuffer); - - m_encoder->encode(in, chunkStream); - m_pos += inputCount; - } - - return chunk; -} - - -wordEncoder::Encoding wordEncoder::getEncoding() const -{ - return m_encoding; -} - - -// static -bool wordEncoder::isEncodingNeeded - (const generationContext& ctx, const string& buffer, const charset& charset) -{ - if (!ctx.getInternationalizedEmailSupport()) - { - // Charset-specific encoding - encoding recEncoding; - - if (charset.getRecommendedEncoding(recEncoding)) - return true; - - // No encoding is needed if the buffer only contains ASCII chars - if (utility::stringUtils::findFirstNonASCIIchar(buffer.begin(), buffer.end()) != string::npos) - return true; - } - - // Force encoding when there are only ASCII chars, but there is - // also at least one of '\n' or '\r' (header fields) - if (buffer.find_first_of("\n\r") != string::npos) - return true; - - // If any RFC-2047 sequence is found in the buffer, encode it - if (buffer.find("=?") != string::npos || buffer.find("?=") != string::npos) - return true; - - return false; -} - - -// static -wordEncoder::Encoding wordEncoder::guessBestEncoding - (const string& buffer, const charset& charset) -{ - // Charset-specific encoding - encoding recEncoding; - - if (charset.getRecommendedEncoding(recEncoding)) - { - if (recEncoding == encoding(encodingTypes::QUOTED_PRINTABLE)) - return ENCODING_QP; - else - return ENCODING_B64; - } - - // Use Base64 if more than 40% non-ASCII, or Quoted-Printable else (default) - const size_t asciiCount = - utility::stringUtils::countASCIIchars(buffer.begin(), buffer.end()); - - const size_t asciiPercent = - (buffer.length() == 0 ? 100 : (100 * asciiCount) / buffer.length()); - - if (asciiPercent < 60) - return ENCODING_B64; - else - return ENCODING_QP; -} - - -} // vmime - diff --git a/test-outsourced-build.sh b/test-outsourced-build.sh index 11d6732c..1700a30b 100755 --- a/test-outsourced-build.sh +++ b/test-outsourced-build.sh @@ -2,10 +2,10 @@ rm -rf _build _install mkdir _build _install cd _build -rm -f ../CMakeCache.txt ../vmime/config.hpp ../vmime/export-static.hpp ../vmime/export-shared.hpp +rm -f ../CMakeCache.txt ../src/vmime/config.hpp ../src/vmime/export-static.hpp ../src/vmime/export-shared.hpp #cmake .. -DCMAKE_INSTALL_PREFIX=../_install -DVMIME_BUILD_SHARED_LIBRARY=NO #cmake .. -DCMAKE_INSTALL_PREFIX=../_install -DVMIME_BUILD_TESTS=YES -cmake .. -DCMAKE_INSTALL_PREFIX=../_install -DVMIME_BUILD_TESTS=YES -DVMIME_BUILD_SAMPLES=YES -DVMIME_TLS_SUPPORT_LIB_IS_OPENSSL=ON -DVMIME_TLS_SUPPORT_LIB_IS_GNUTLS=OFF -DCMAKE_BUILD_TYPE=Release +cmake .. -DCMAKE_INSTALL_PREFIX=../_install -DVMIME_BUILD_TESTS=YES -DVMIME_BUILD_SAMPLES=YES -DVMIME_TLS_SUPPORT_LIB_IS_OPENSSL=ON -DVMIME_TLS_SUPPORT_LIB_IS_GNUTLS=OFF -DCMAKE_BUILD_TYPE=Debug cmake .. -L make make install diff --git a/vmime/address.hpp b/vmime/address.hpp deleted file mode 100644 index 5eb510f9..00000000 --- a/vmime/address.hpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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
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/addressList.hpp b/vmime/addressList.hpp deleted file mode 100644 index 0df657d3..00000000 --- a/vmime/addressList.hpp +++ /dev/null @@ -1,192 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - void copyFrom(const component& other); - addressList& operator=(const addressList& other); - addressList& operator=(const mailboxList& other); - - const std::vector > getChildComponents(); - - - /** Add a address at the end of the list. - * - * @param addr address to append - */ - void appendAddress(shared_ptr
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(shared_ptr
beforeAddress, shared_ptr
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, shared_ptr
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(shared_ptr
afterAddress, shared_ptr
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, shared_ptr
addr); - - /** Remove the specified address from the list. - * - * @param addr address to remove - * @throw std::out_of_range if the address is not in the list - */ - void removeAddress(shared_ptr
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
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 getAddressAt(const size_t pos) const; - - /** Return the address list. - * - * @return list of addresses - */ - const std::vector > getAddressList() const; - - /** Return the address list. - * - * @return list of addresses - */ - const std::vector > 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 toMailboxList() const; - -private: - - std::vector > 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/attachment.hpp b/vmime/attachment.hpp deleted file mode 100644 index 9730bc6c..00000000 --- a/vmime/attachment.hpp +++ /dev/null @@ -1,118 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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 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 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(shared_ptr parent) const = 0; -}; - - -} // vmime - - -#endif // VMIME_ATTACHMENT_HPP_INCLUDED diff --git a/vmime/attachmentHelper.hpp b/vmime/attachmentHelper.hpp deleted file mode 100644 index e03a4f7d..00000000 --- a/vmime/attachmentHelper.hpp +++ /dev/null @@ -1,121 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr 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 - getBodyPartAttachment(shared_ptr 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 > - findAttachmentsInBodyPart(shared_ptr 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 > - findAttachmentsInMessage(shared_ptr msg, const unsigned int options = 0); - - /** Add an attachment to the specified message. - * - * @param msg message into which to add the attachment - * @param att attachment to add - */ - static void addAttachment(shared_ptr msg, shared_ptr att); - - /** Add a message attachment to the specified message. - * - * @param msg message into which to add the attachment - * @param amsg message to attach - */ - static void addAttachment(shared_ptr msg, shared_ptr amsg); - -protected: - - static shared_ptr findBodyPart - (shared_ptr part, const mediaType& type); -}; - - -} // vmime - - -#endif // VMIME_ATTACHMENTHELPER_HPP_INCLUDED - diff --git a/vmime/base.hpp b/vmime/base.hpp deleted file mode 100644 index f6515794..00000000 --- a/vmime/base.hpp +++ /dev/null @@ -1,258 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include -#include -#include -#include -#include - -#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 - operator shared_ptr () { return shared_ptr (); } - }; - - 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 - inline T const* cbegin(T const (&array)[N]) - { - return (array); - } - - template - inline T const* cend(T const (&array)[N]) - { - return (array + N); - } - - template - inline T* begin(T (&array)[N]) - { - return (array); - } - - template - inline T* end(T (&array)[N]) - { - return (array + N); - } - - template - inline size_t count(T const (&/* array */)[N]) - { - return (N); - } - - - // Copy one vector to another, with type conversion - - template - 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 (obj->clone()). - */ - template - shared_ptr clone(shared_ptr obj) - { - return dynamic_pointer_cast (obj->clone()); - } - - /** Clone helper (using a const shared_ptr). - * This is an alias for dynamic_pointer_cast (obj->clone()). - */ - template - shared_ptr clone(shared_ptr obj) - { - return dynamic_pointer_cast (obj->clone()); - } - - /** Clone helper (using a const reference). - * This is an alias for dynamic_pointer_cast (obj.clone()). - */ - template - shared_ptr clone(const T& obj) - { - return dynamic_pointer_cast (obj.clone()); - } - - /** Downcast helper. - * Usage: vmime::dynamicCast (obj), where 'obj' is of - * type Type, and DerivedType is derived from Type. - */ - template - shared_ptr dynamicCast(shared_ptr obj) - { - return dynamic_pointer_cast (obj); - } - - /** Const cast helper. - */ - template - shared_ptr constCast(const shared_ptr & obj) - { - return const_pointer_cast (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/body.hpp b/vmime/body.hpp deleted file mode 100644 index e47f97e9..00000000 --- a/vmime/body.hpp +++ /dev/null @@ -1,344 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr 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(shared_ptr beforePart, shared_ptr 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, shared_ptr 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(shared_ptr afterPart, shared_ptr part); - - /** Insert a new part after the specified position. - * - * @param pos position of the part before the new part - * @param part part to insert - */ - void insertPartAfter(const size_t pos, shared_ptr part); - - /** Remove the specified part from the list. - * - * @param part part to remove - * @throw exceptions::no_such_part if the part is not in the list - */ - void removePart(shared_ptr 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 getPartAt(const size_t pos); - - /** Return the part at the specified position. - * - * @param pos position - * @return part at position 'pos' - */ - const shared_ptr getPartAt(const size_t pos) const; - - /** Return the part list. - * - * @return list of parts - */ - const std::vector > getPartList() const; - - /** Return the part list. - * - * @return list of parts - */ - const std::vector > 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 getContents() const; - - /** Set the body contents. - * - * @param contents new body contents - */ - void setContents(shared_ptr contents); - - /** Set the body contents and type. - * - * @param contents new body contents - * @param type type of contents - */ - void setContents(shared_ptr 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(shared_ptr 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(shared_ptr 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 clone() const; - void copyFrom(const component& other); - body& operator=(const body& other); - - const std::vector > 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 m_contents; - - bodyPart* m_part; - - std::vector > m_parts; - - bool isRootPart() const; - - void initNewPart(shared_ptr 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 - (shared_ptr parser, const string& boundary, - const size_t position, const size_t end, - size_t* boundaryStart, size_t* boundaryEnd); - - // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - shared_ptr 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/bodyPart.hpp b/vmime/bodyPart.hpp deleted file mode 100644 index 214cb208..00000000 --- a/vmime/bodyPart.hpp +++ /dev/null @@ -1,155 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 getHeader() const; - - /** Return the header section of this part. - * - * @return header section - */ - shared_ptr
getHeader(); - - /** Replaces the header section of this part. - * - * @param header the new header of this part - */ - void setHeader(shared_ptr
header); - - /** Return the body section of this part. - * - * @return body section - */ - const shared_ptr getBody() const; - - /** Return the body section of this part. - * - * @return body section - */ - shared_ptr getBody(); - - /** Replaces the body section of this part. - * - * @param body new body section - */ - void setBody(shared_ptr 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 clone() const; - void copyFrom(const component& other); - bodyPart& operator=(const bodyPart& other); - - const std::vector > getChildComponents(); - - size_t getGeneratedSize(const generationContext& ctx); - -private: - - shared_ptr
m_header; - mutable shared_ptr 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 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(shared_ptr part); - - // Component parsing & assembling - void parseImpl - (const parsingContext& ctx, - shared_ptr 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/bodyPartAttachment.hpp b/vmime/bodyPartAttachment.hpp deleted file mode 100644 index e1a4a89a..00000000 --- a/vmime/bodyPartAttachment.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr part); - - const mediaType getType() const; - const word getName() const; - const text getDescription() const; - const encoding getEncoding() const; - - const shared_ptr getData() const; - - shared_ptr getPart() const; - shared_ptr getHeader() const; - -private: - - void generateIn(shared_ptr parent) const; - - shared_ptr getContentDisposition() const; - shared_ptr getContentType() const; - - - shared_ptr m_part; -}; - - -} // vmime - - -#endif // VMIME_BUILDING_DOC - - -#endif // VMIME_BODYPARTATTACHMENT_HPP_INCLUDED - diff --git a/vmime/charset.hpp b/vmime/charset.hpp deleted file mode 100644 index 5bd50fdf..00000000 --- a/vmime/charset.hpp +++ /dev/null @@ -1,148 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 > 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 platformHandler::getLocalCharset() - * 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::charset_conv_error if an error occured 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::charset_conv_error if an error occured during - * the conversion - */ - static void convert(utility::inputStream& in, utility::outputStream& out, - const charset& source, const charset& dest, - const charsetConverterOptions& opts = charsetConverterOptions()); - - shared_ptr 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/charsetConverter.hpp b/vmime/charsetConverter.hpp deleted file mode 100644 index 07f38d8f..00000000 --- a/vmime/charsetConverter.hpp +++ /dev/null @@ -1,119 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 error - * occured when initializing convert, or during charset conversion. - */ - -class VMIME_EXPORT charsetFilteredOutputStream : public filteredOutputStream -{ -}; - - -} // utility - - -/** Convert between charsets. - */ - -class VMIME_EXPORT charsetConverter : public object -{ -public: - - /** Construct and initialize an iconv charset converter. - * - * @param source input charset - * @param dest output charset - * @param opts conversion options - */ - static shared_ptr 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 - * @throws exceptions::charset_conv_error if an error occured during - * the conversion - */ - virtual void convert(const string& in, string& out) = 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 - * @throws exceptions::charset_conv_error if an error occured during - * the conversion - */ - virtual void convert(utility::inputStream& in, utility::outputStream& out) = 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 - * @return a filtered output stream, or NULL if not supported - */ - virtual shared_ptr getFilteredOutputStream(utility::outputStream& os) = 0; - -private: - - static shared_ptr createGenericConverter - (const charset& source, const charset& dest, - const charsetConverterOptions& opts); -}; - - -} // vmime - - -#endif // VMIME_CHARSETCONVERTER_HPP_INCLUDED diff --git a/vmime/charsetConverterOptions.hpp b/vmime/charsetConverterOptions.hpp deleted file mode 100644 index 07e7a138..00000000 --- a/vmime/charsetConverterOptions.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(); - - - /** Replace invalid sequences with this string. */ - string invalidSequence; -}; - - -} // vmime - - -#endif // VMIME_CHARSETCONVERTEROPTIONS_HPP_INCLUDED diff --git a/vmime/charsetConverter_iconv.hpp b/vmime/charsetConverter_iconv.hpp deleted file mode 100644 index 4167dc4e..00000000 --- a/vmime/charsetConverter_iconv.hpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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); - void convert(utility::inputStream& in, utility::outputStream& out); - - shared_ptr getFilteredOutputStream(utility::outputStream& os); - -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 - */ - charsetFilteredOutputStream_iconv - (const charset& source, const charset& dest, outputStream* os); - - ~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]; -}; - - -} // utility - - -} // vmime - - -#endif // VMIME_CHARSETCONV_LIB_IS_ICONV - -#endif // VMIME_CHARSETCONVERTER_ICONV_HPP_INCLUDED diff --git a/vmime/charsetConverter_icu.hpp b/vmime/charsetConverter_icu.hpp deleted file mode 100644 index 5d054413..00000000 --- a/vmime/charsetConverter_icu.hpp +++ /dev/null @@ -1,126 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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); - void convert(utility::inputStream& in, utility::outputStream& out); - - shared_ptr getFilteredOutputStream(utility::outputStream& os); - -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 - */ - charsetFilteredOutputStream_icu - (const charset& source, const charset& dest, outputStream* os); - - ~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; -}; - - -} // utility - - -} // vmime - - -#endif // VMIME_CHARSETCONV_LIB_IS_ICU - -#endif // VMIME_CHARSETCONVERTER_ICU_HPP_INCLUDED diff --git a/vmime/charsetConverter_idna.hpp b/vmime/charsetConverter_idna.hpp deleted file mode 100644 index 874d6bf1..00000000 --- a/vmime/charsetConverter_idna.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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); - void convert(utility::inputStream& in, utility::outputStream& out); - - shared_ptr getFilteredOutputStream(utility::outputStream& os); - -private: - - charset m_source; - charset m_dest; - - charsetConverterOptions m_options; -}; - - -} // vmime - - -#endif // VMIME_CHARSETCONVERTER_IDNA_HPP_INCLUDED diff --git a/vmime/component.hpp b/vmime/component.hpp deleted file mode 100644 index 87d465e8..00000000 --- a/vmime/component.hpp +++ /dev/null @@ -1,257 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr 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 - (shared_ptr 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, - shared_ptr 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 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 > 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, - shared_ptr 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/constants.hpp b/vmime/constants.hpp deleted file mode 100644 index 8e6e3f83..00000000 --- a/vmime/constants.hpp +++ /dev/null @@ -1,256 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free SOFTWARE; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software FOUNDATION; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A 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 - -#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 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; - } -} - - -#endif // VMIME_CONSTANTS_HPP_INCLUDED diff --git a/vmime/contentDisposition.hpp b/vmime/contentDisposition.hpp deleted file mode 100644 index c934b81d..00000000 --- a/vmime/contentDisposition.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - void copyFrom(const component& other); - contentDisposition& operator=(const contentDisposition& other); - - const std::vector > 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/contentDispositionField.hpp b/vmime/contentDispositionField.hpp deleted file mode 100644 index aac4c5de..00000000 --- a/vmime/contentDispositionField.hpp +++ /dev/null @@ -1,148 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/contentHandler.hpp b/vmime/contentHandler.hpp deleted file mode 100644 index f62af166..00000000 --- a/vmime/contentHandler.hpp +++ /dev/null @@ -1,139 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#include "vmime/base.hpp" -#include "vmime/utility/stringProxy.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 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/contentTypeField.hpp b/vmime/contentTypeField.hpp deleted file mode 100644 index 8604c4a3..00000000 --- a/vmime/contentTypeField.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/context.hpp b/vmime/context.hpp deleted file mode 100644 index 767ec05a..00000000 --- a/vmime/context.hpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - 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/dateTime.hpp b/vmime/dateTime.hpp deleted file mode 100644 index 7af63040..00000000 --- a/vmime/dateTime.hpp +++ /dev/null @@ -1,263 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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 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 > 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/defaultAttachment.hpp b/vmime/defaultAttachment.hpp deleted file mode 100644 index 6eb0c5b6..00000000 --- a/vmime/defaultAttachment.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr data, const encoding& enc, const mediaType& type, const text& desc = NULL_TEXT, const word& name = NULL_WORD); - defaultAttachment(shared_ptr 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 getData() const; - const encoding getEncoding() const; - - shared_ptr getPart() const; - - shared_ptr getHeader() const; - -protected: - - mediaType m_type; /**< Media type (eg. "application/octet-stream") */ - text m_desc; /**< Description (eg. "The image you requested") */ - shared_ptr 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(shared_ptr parent) const; - -protected: - - virtual void generatePart(shared_ptr part) const; -}; - - -} // vmime - - -#endif // VMIME_DEFAULTATTACHMENT_HPP_INCLUDED diff --git a/vmime/disposition.hpp b/vmime/disposition.hpp deleted file mode 100644 index 7322c21d..00000000 --- a/vmime/disposition.hpp +++ /dev/null @@ -1,159 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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 clone() const; - void copyFrom(const component& other); - disposition& operator=(const disposition& other); - - const std::vector > 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 getModifierList() const; - -private: - - string m_actionMode; - string m_sendingMode; - string m_type; - - std::vector 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/emailAddress.hpp b/vmime/emailAddress.hpp deleted file mode 100644 index 30ee24ab..00000000 --- a/vmime/emailAddress.hpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - emailAddress& operator=(const emailAddress& other); - - const std::vector > 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/emptyContentHandler.hpp b/vmime/emptyContentHandler.hpp deleted file mode 100644 index 369a4206..00000000 --- a/vmime/emptyContentHandler.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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/encoding.hpp b/vmime/encoding.hpp deleted file mode 100644 index 3148f899..00000000 --- a/vmime/encoding.hpp +++ /dev/null @@ -1,172 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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); - -public: - - /** 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 > 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(shared_ptr 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(shared_ptr data, const charset& chset, const EncodingUsage usage = USAGE_BINARY_DATA); - - - shared_ptr 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 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/exception.hpp b/vmime/exception.hpp deleted file mode 100644 index e2afcc62..00000000 --- a/vmime/exception.hpp +++ /dev/null @@ -1,906 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#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::exception -{ -private: - - string m_what; - exception* m_other; - - exception(); - -public: - - exception(const string& what, const exception& other = NO_EXCEPTION); - exception(const exception& e); - - virtual ~exception() throw(); - - /** Return a description of the error. - * - * @return error message - */ - const char* what() const throw(); - - /** Return a description of the error. - * - * @return error message - */ - const char* what() throw(); - - /** Return the next exception in the chain (encapsulated exception). - * - * @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(); -}; - - -/** 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(); - -}; - - -/** 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(); -}; - - -class VMIME_EXPORT certificate_exception : public tls_exception -{ -public: - - certificate_exception(const string& what, const exception& other = NO_EXCEPTION); - ~certificate_exception() throw(); - - exception* clone() const; - const char* name() const throw(); -}; - - -class VMIME_EXPORT certificate_verification_exception : public certificate_exception -{ -public: - - certificate_verification_exception(const string& what, const exception& other = NO_EXCEPTION); - ~certificate_verification_exception() throw (); - - exception* clone() const; - const char* name() const throw (); -}; - - -class VMIME_EXPORT unsupported_certificate_type : public certificate_exception -{ -public: - - unsupported_certificate_type(const string& type, const exception& other = NO_EXCEPTION); - ~unsupported_certificate_type() 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/export.hpp b/vmime/export.hpp deleted file mode 100644 index 90f0cc3a..00000000 --- a/vmime/export.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/fileAttachment.hpp b/vmime/fileAttachment.hpp deleted file mode 100644 index 1e7a808a..00000000 --- a/vmime/fileAttachment.hpp +++ /dev/null @@ -1,197 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr cts, const word& filename, const mediaType& type); - fileAttachment(shared_ptr cts, const word& filename, const mediaType& type, const text& desc); - fileAttachment(shared_ptr cts, const word& filename, const mediaType& type, const text& desc, const encoding& enc); - - /** Stores information about a file attachment. - */ - class 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(shared_ptr cts); - - fileInfo m_fileInfo; - - void generatePart(shared_ptr part) const; -}; - - -} // vmime - - -#endif // VMIME_HAVE_FILESYSTEM_FEATURES - -#endif // VMIME_FILEATTACHMENT_HPP_INCLUDED diff --git a/vmime/fileContentHandler.hpp b/vmime/fileContentHandler.hpp deleted file mode 100644 index 68b4d396..00000000 --- a/vmime/fileContentHandler.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/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 - (shared_ptr file, - const vmime::encoding& enc = NO_ENCODING); - - ~fileContentHandler(); - - fileContentHandler(const fileContentHandler& cts); - fileContentHandler& operator=(const fileContentHandler& cts); - - shared_ptr 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 - (shared_ptr 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 m_file; -}; - - -} // vmime - - -#endif // VMIME_FILECONTENTHANDLER_HPP_INCLUDED diff --git a/vmime/generatedMessageAttachment.hpp b/vmime/generatedMessageAttachment.hpp deleted file mode 100644 index 7137b22b..00000000 --- a/vmime/generatedMessageAttachment.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr part); - - const mediaType getType() const; - const text getDescription() const; - const word getName() const; - - const shared_ptr getData() const; - - const encoding getEncoding() const; - - shared_ptr getPart() const; - - shared_ptr getHeader() const; - - shared_ptr getMessage() const; - -protected: - - void generateIn(shared_ptr parent) const; - -private: - - shared_ptr m_bpa; - mutable shared_ptr m_msg; -}; - - -} // vmime - - -#endif // !VMIME_BUILDING_DOC - - -#endif // VMIME_GENERATEDMESSAGEATTACHMENT_HPP_INCLUDED - diff --git a/vmime/generationContext.hpp b/vmime/generationContext.hpp deleted file mode 100644 index 949f06ac..00000000 --- a/vmime/generationContext.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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; -}; - - -} // vmime - - -#endif // VMIME_GENERATIONCONTEXT_HPP_INCLUDED diff --git a/vmime/header.hpp b/vmime/header.hpp deleted file mode 100644 index d2d20727..00000000 --- a/vmime/header.hpp +++ /dev/null @@ -1,346 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 methodName() { return getField(fields::fieldName); } \ - shared_ptr 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 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 - shared_ptr findField(const string& fieldName) const - { - return dynamicCast (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 - shared_ptr findFieldValue(const string& fieldName) const - { - shared_ptr field = findField(fieldName); - - if (field) - return dynamicCast (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 > 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 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 - shared_ptr getField(const string& fieldName) - { - return dynamicCast (getField(fieldName)); - } - - /** Add a field at the end of the list. - * - * @param field field to append - */ - void appendField(shared_ptr 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(shared_ptr beforeField, shared_ptr 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, shared_ptr 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(shared_ptr afterField, shared_ptr 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, shared_ptr 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(shared_ptr 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(shared_ptr field, shared_ptr 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 getFieldAt(const size_t pos); - - /** Return the field at the specified position. - * - * @param pos position - * @return field at position 'pos' - */ - const shared_ptr getFieldAt(const size_t pos) const; - - /** Return the field list. - * - * @return list of fields - */ - const std::vector > getFieldList() const; - - /** Return the field list. - * - * @return list of fields - */ - const std::vector > getFieldList(); - - shared_ptr clone() const; - void copyFrom(const component& other); - header& operator=(const header& other); - - const std::vector > getChildComponents(); - - size_t getGeneratedSize(const generationContext& ctx); - -private: - - std::vector > m_fields; - - - class fieldHasName - { - public: - - fieldHasName(const string& name); - bool operator() (const shared_ptr & field); - - private: - - string m_name; - }; - - class fieldHasNotName - { - public: - - fieldHasNotName(const string& name); - bool operator() (const shared_ptr & 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/headerField.hpp b/vmime/headerField.hpp deleted file mode 100644 index 555805db..00000000 --- a/vmime/headerField.hpp +++ /dev/null @@ -1,190 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - void copyFrom(const component& other); - headerField& operator=(const headerField& other); - - const std::vector > 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 getValue() const; - - /** Return the read-only value object attached to this field, - * casted to the specified type. - * - * @return value object - */ - template - shared_ptr getValue() const - { - return dynamicCast (m_value); - } - - /** Return the value object attached to this field. - * - * @return value object - */ - virtual shared_ptr getValue(); - - /** Return the value object attached to this field, - * casted to the specified type. - * - * @return value object - */ - template - shared_ptr getValue() - { - return dynamicCast (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(shared_ptr 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(shared_ptr 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 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 m_value; -}; - - -} // vmime - - -#endif // VMIME_HEADERFIELD_HPP_INCLUDED diff --git a/vmime/headerFieldFactory.hpp b/vmime/headerFieldFactory.hpp deleted file mode 100644 index 960f27b7..00000000 --- a/vmime/headerFieldFactory.hpp +++ /dev/null @@ -1,152 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 (*AllocFunc)(void); - typedef std::map NameMap; - - NameMap m_nameMap; - - - struct ValueInfo - { - typedef shared_ptr (*ValueAllocFunc)(void); - typedef bool (*ValueTypeCheckFunc)(const object&); - - ValueAllocFunc allocFunc; - ValueTypeCheckFunc checkTypeFunc; - }; - - typedef std::map ValueMap; - - ValueMap m_valueMap; - -public: - - static shared_ptr getInstance(); - -#ifndef VMIME_BUILDING_DOC - // TYPE must inherit from BASE_TYPE - template - class registerer - { - public: - - static bool checkType(const object& obj) - { - const TYPE* typedObj = dynamic_cast (&obj); - return typedObj != NULL; - } - - static shared_ptr creator() - { - // Allocate a new object - return shared_ptr (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 - void registerField(const string& name) - { - m_nameMap.insert(NameMap::value_type - (utility::stringUtils::toLower(name), - ®isterer ::creator)); - } - - /** Register a field value type. - * - * @param T value class (must inherit from 'headerFieldValue') - * @param name field name - */ - template - void registerFieldValue(const string& name) - { - ValueInfo vi; - vi.allocFunc = ®isterer ::creator; - vi.checkTypeFunc = ®isterer ::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 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 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/headerFieldValue.hpp b/vmime/headerFieldValue.hpp deleted file mode 100644 index a3681953..00000000 --- a/vmime/headerFieldValue.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/htmlTextPart.hpp b/vmime/htmlTextPart.hpp deleted file mode 100644 index 4c1a8632..00000000 --- a/vmime/htmlTextPart.hpp +++ /dev/null @@ -1,237 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 getPlainText() const; - void setPlainText(shared_ptr plainText); - - const shared_ptr getText() const; - void setText(shared_ptr text); - - /** Embedded object (eg: image for <IMG> tag). - */ - class 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(shared_ptr 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 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 <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 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 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 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 <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 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 <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 addObject(shared_ptr 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 <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 addObject(shared_ptr data, const encoding& enc, const mediaType& type); - - - size_t getPartCount() const; - - void generateIn(shared_ptr message, shared_ptr parent) const; - void parse(shared_ptr message, shared_ptr parent, shared_ptr textPart); - -private: - - shared_ptr m_plainText; - shared_ptr m_text; - charset m_charset; - - std::vector > m_objects; - - void findEmbeddedParts(const bodyPart& part, std::vector >& cidParts, std::vector >& 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/mailbox.hpp b/vmime/mailbox.hpp deleted file mode 100644 index 88abc0f5..00000000 --- a/vmime/mailbox.hpp +++ /dev/null @@ -1,123 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - mailbox& operator=(const mailbox& other); - - bool isEmpty() const; - - void clear(); - - const std::vector > 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/mailboxField.hpp b/vmime/mailboxField.hpp deleted file mode 100644 index ca6863c0..00000000 --- a/vmime/mailboxField.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/mailboxGroup.hpp b/vmime/mailboxGroup.hpp deleted file mode 100644 index b264cf60..00000000 --- a/vmime/mailboxGroup.hpp +++ /dev/null @@ -1,194 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - mailboxGroup& operator=(const component& other); - - const std::vector > 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(shared_ptr 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(shared_ptr beforeMailbox, shared_ptr 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, shared_ptr 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(shared_ptr afterMailbox, shared_ptr 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, shared_ptr 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(shared_ptr 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 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 getMailboxAt(const size_t pos) const; - - /** Return the mailbox list. - * - * @return list of mailboxes - */ - const std::vector > getMailboxList() const; - - /** Return the mailbox list. - * - * @return list of mailboxes - */ - const std::vector > getMailboxList(); - - bool isGroup() const; - -private: - - text m_name; - std::vector > 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/mailboxList.hpp b/vmime/mailboxList.hpp deleted file mode 100644 index 125c238e..00000000 --- a/vmime/mailboxList.hpp +++ /dev/null @@ -1,184 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - void copyFrom(const component& other); - mailboxList& operator=(const mailboxList& other); - - const std::vector > getChildComponents(); - - /** Add a mailbox at the end of the list. - * - * @param mbox mailbox to append - */ - void appendMailbox(shared_ptr 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(shared_ptr beforeMailbox, shared_ptr 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, shared_ptr 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(shared_ptr afterMailbox, shared_ptr 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, shared_ptr 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(shared_ptr 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 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 getMailboxAt(const size_t pos) const; - - /** Return the mailbox list. - * - * @return list of mailboxes - */ - const std::vector > getMailboxList() const; - - /** Return the mailbox list. - * - * @return list of mailboxes - */ - const std::vector > getMailboxList(); - - /** Return a list of addresses. - * - * @return list of addresses - */ - shared_ptr 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/mdn/MDNHelper.hpp b/vmime/mdn/MDNHelper.hpp deleted file mode 100644 index 2584978f..00000000 --- a/vmime/mdn/MDNHelper.hpp +++ /dev/null @@ -1,139 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr 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(shared_ptr 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 getPossibleMDNs(const shared_ptr 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 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 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 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 buildMDN(const sendableMDNInfos& mdnInfos, - const string& text, - const charset& ch, - const mailbox& expeditor, - const disposition& dispo, - const string& reportingUA = NULL_STRING, - const std::vector & reportingUAProducts - = std::vector (), - const std::map & fields - = (std::map ())); - -private: - - static shared_ptr createFirstMDNPart(const sendableMDNInfos& mdnInfos, - const string& text, const charset& ch); - - static shared_ptr createSecondMDNPart(const sendableMDNInfos& mdnInfos, - const disposition& dispo, - const string& reportingUA, - const std::vector & reportingUAProducts, - const std::map & fields); - - - static shared_ptr createThirdMDNPart(const sendableMDNInfos& mdnInfos); -}; - - -} // mdn -} // vmime - - -#endif // VMIME_MDN_MDNHELPER_HPP_INCLUDED diff --git a/vmime/mdn/MDNInfos.hpp b/vmime/mdn/MDNInfos.hpp deleted file mode 100644 index 030aa23e..00000000 --- a/vmime/mdn/MDNInfos.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 getMessage() const = 0; -}; - - -} // mdn -} // vmime - - -#endif // VMIME_MDN_MDNINFOS_HPP_INCLUDED diff --git a/vmime/mdn/receivedMDNInfos.hpp b/vmime/mdn/receivedMDNInfos.hpp deleted file mode 100644 index c6953a24..00000000 --- a/vmime/mdn/receivedMDNInfos.hpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 msg); - receivedMDNInfos(const receivedMDNInfos& other); - - receivedMDNInfos& operator=(const receivedMDNInfos& other); - - - const shared_ptr 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 m_msg; - - disposition m_disp; - messageId m_omid; - string m_contentMIC; -}; - - -} // mdn -} // vmime - - -#endif // VMIME_MDN_RECEIVEDMDNINFOS_HPP_INCLUDED diff --git a/vmime/mdn/sendableMDNInfos.hpp b/vmime/mdn/sendableMDNInfos.hpp deleted file mode 100644 index e4f6d20d..00000000 --- a/vmime/mdn/sendableMDNInfos.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 msg, const mailbox& mbox); - sendableMDNInfos(const sendableMDNInfos& other); - - sendableMDNInfos& operator=(const sendableMDNInfos& other); - - const shared_ptr 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 m_msg; - mailbox m_mailbox; -}; - - -} // mdn -} // vmime - - -#endif // VMIME_MDN_SENDABLEMDNINFOS_HPP_INCLUDED diff --git a/vmime/mediaType.hpp b/vmime/mediaType.hpp deleted file mode 100644 index a7d6f4e4..00000000 --- a/vmime/mediaType.hpp +++ /dev/null @@ -1,119 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - void copyFrom(const component& other); - mediaType& operator=(const mediaType& other); - - const std::vector > 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/message.hpp b/vmime/message.hpp deleted file mode 100644 index 62ff77e1..00000000 --- a/vmime/message.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/messageAttachment.hpp b/vmime/messageAttachment.hpp deleted file mode 100644 index 641fd3e1..00000000 --- a/vmime/messageAttachment.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 getMessage() const = 0; -}; - - -} // vmime - - -#endif // VMIME_MESSAGEATTACHMENT_HPP_INCLUDED - diff --git a/vmime/messageBuilder.hpp b/vmime/messageBuilder.hpp deleted file mode 100644 index af86e826..00000000 --- a/vmime/messageBuilder.hpp +++ /dev/null @@ -1,223 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr attach); - - /** Attach a new object to the message. - * - * @param attach new attachment - */ - void appendAttachment(shared_ptr 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 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 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 > getAttachmentList() const; - - /** Return the list of attachments. - * - * @return list of attachments - */ - const std::vector > 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 getTextPart(); - - /** Construct a new message based on the information specified - * in this object. - * - * @return a new message - */ - shared_ptr construct() const; - -private: - - mailbox m_from; - - addressList m_to; - addressList m_cc; - addressList m_bcc; - - text m_subject; - - shared_ptr m_textPart; - - std::vector > m_attach; -}; - - -} // vmime - - -#endif // VMIME_MESSAGEBUILDER_HPP_INCLUDED diff --git a/vmime/messageId.hpp b/vmime/messageId.hpp deleted file mode 100644 index 83527468..00000000 --- a/vmime/messageId.hpp +++ /dev/null @@ -1,143 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - void copyFrom(const component& other); - messageId& operator=(const messageId& other); - - const std::vector > 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 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/messageIdSequence.hpp b/vmime/messageIdSequence.hpp deleted file mode 100644 index 07f0c422..00000000 --- a/vmime/messageIdSequence.hpp +++ /dev/null @@ -1,172 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - void copyFrom(const component& other); - messageIdSequence& operator=(const messageIdSequence& other); - - const std::vector > getChildComponents(); - - - /** Add a message-id at the end of the list. - * - * @param mid message-id to append - */ - void appendMessageId(shared_ptr 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(shared_ptr beforeMid, shared_ptr 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, shared_ptr 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(shared_ptr afterMid, shared_ptr 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, shared_ptr 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(shared_ptr 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 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 getMessageIdAt(const size_t pos) const; - - /** Return the message-id list. - * - * @return list of message-ids - */ - const std::vector > getMessageIdList() const; - - /** Return the message-id list. - * - * @return list of message-ids - */ - const std::vector > getMessageIdList(); - -private: - - std::vector > 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/messageParser.hpp b/vmime/messageParser.hpp deleted file mode 100644 index c3a48f11..00000000 --- a/vmime/messageParser.hpp +++ /dev/null @@ -1,159 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr 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 getAttachmentAt(const size_t pos) const; - - /** Return the attachments of the message. - * - * @return list of attachments in the message - */ - const std::vector > getAttachmentList() const; - - /** Return the text parts of the message. - * - * @return list of text parts in the message - */ - const std::vector > 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 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 > m_attach; - - std::vector > m_textParts; - - void parse(shared_ptr msg); - - void findAttachments(shared_ptr msg); - - void findTextParts(shared_ptr msg, shared_ptr part); - bool findSubTextParts(shared_ptr msg, shared_ptr part); -}; - - -} // vmime - - -#endif // VMIME_MESSAGEPARSER_HPP_INCLUDED diff --git a/vmime/misc/importanceHelper.hpp b/vmime/misc/importanceHelper.hpp deleted file mode 100644 index ae8297fc..00000000 --- a/vmime/misc/importanceHelper.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr msg); - - /** Reset the importance of a message to the default importance. - * - * @param hdr message header on which to reset importance - */ - static void resetImportanceHeader(shared_ptr
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(shared_ptr 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(shared_ptr hdr); - - /** Set the importance of the specified message. - * - * @param msg message on which to set importance - * @param i new message importance - */ - static void setImportance(shared_ptr 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(shared_ptr
hdr, const Importance i); -}; - - -} // misc -} // vmime - - -#endif // VMIME_MISC_IMPORTANCEHELPER_HPP_INCLUDED diff --git a/vmime/net/connectionInfos.hpp b/vmime/net/connectionInfos.hpp deleted file mode 100644 index 6c86eeab..00000000 --- a/vmime/net/connectionInfos.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/net/defaultConnectionInfos.hpp b/vmime/net/defaultConnectionInfos.hpp deleted file mode 100644 index 50673bbc..00000000 --- a/vmime/net/defaultConnectionInfos.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/net/events.hpp b/vmime/net/events.hpp deleted file mode 100644 index a3e952d4..00000000 --- a/vmime/net/events.hpp +++ /dev/null @@ -1,273 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#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: - - 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(shared_ptr folder, const Types type, const std::vector & nums); - - /** Return the folder in which messages have been added/removed. - * - * @return folder in which message count changed - */ - shared_ptr 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 & 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 m_folder; - const Types m_type; - std::vector m_nums; -}; - - -/** Listener for events about the message count in a folder. - */ - -class VMIME_EXPORT messageCountListener -{ -protected: - - virtual ~messageCountListener() { } - -public: - - virtual void messagesAdded(shared_ptr event) = 0; - virtual void messagesRemoved(shared_ptr 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(shared_ptr folder, const Types type, const std::vector & nums); - - /** Return the folder in which messages have changed. - * - * @return folder in which message count changed - */ - shared_ptr 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 & 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 m_folder; - const Types m_type; - std::vector m_nums; -}; - - -/** Listener for events occuring on a message. - */ - -class VMIME_EXPORT messageChangedListener -{ -protected: - - virtual ~messageChangedListener() { } - -public: - - virtual void messageChanged(shared_ptr 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(shared_ptr folder, const Types type, const utility::path& oldPath, const utility::path& newPath); - - /** Return the folder on which the event occured. - * - * @return folder on which the event occured - */ - shared_ptr 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 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(shared_ptr event) = 0; - virtual void folderRenamed(shared_ptr event) = 0; - virtual void folderDeleted(shared_ptr event) = 0; -}; - - -} // events -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_NET_EVENTS_HPP_INCLUDED diff --git a/vmime/net/fetchAttributes.hpp b/vmime/net/fetchAttributes.hpp deleted file mode 100644 index d01e9f50..00000000 --- a/vmime/net/fetchAttributes.hpp +++ /dev/null @@ -1,142 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#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 getHeaderFields() const; - -private: - - int m_predefinedAttribs; - std::vector m_headers; -}; - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - - -#endif // VMIME_NET_FETCHATTRIBUTES_HPP_INCLUDED diff --git a/vmime/net/folder.hpp b/vmime/net/folder.hpp deleted file mode 100644 index 38ba4597..00000000 --- a/vmime/net/folder.hpp +++ /dev/null @@ -1,399 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#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/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 -{ -protected: - - folder(const folder&) : object() { } - folder() { } - -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). */ - }; - - /** Folder types. - */ - enum Types - { - TYPE_CONTAINS_FOLDERS = (1 << 0), /**< Folder can contain folders. */ - TYPE_CONTAINS_MESSAGES = (1 << 1), /**< Folder can contain messages. */ - - TYPE_UNDEFINED = 9999 /**< Used internally (this should not be returned - by the type() function). */ - }; - - /** Folder flags. - */ - enum Flags - { - FLAG_CHILDREN = (1 << 0), /**< Folder contains subfolders. */ - FLAG_NO_OPEN = (1 << 1), /**< Folder cannot be open. */ - - FLAG_UNDEFINED = 9999 /**< Used internally (this should not be returned - by the type() function). */ - }; - - /** Return the type of this folder. - * - * @return folder type (see folder::Types) - */ - virtual int getType() = 0; - - /** Return the flags of this folder. - * - * @return folder flags (see folder::Flags) - */ - virtual int getFlags() = 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 type folder type (see folder::Types) - * @throw exceptions::net_exception if an error occurs - */ - virtual void create(const int type) = 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 getMessage(const int 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 > getMessages(const messageSet& msgs) = 0; - - /** Return the number of messages in this folder. - * - * @return number of messages in the folder - */ - virtual int 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 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 > 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 - * @param date date/time for the new message (if NULL, the current time is used) - * @param progress progress listener, or NULL if not used - * @throw exceptions::net_exception if an error occurs - */ - virtual void addMessage(shared_ptr msg, const int flags = message::FLAG_UNDEFINED, 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 - * @param date date/time for the new message (if NULL, the current time is used) - * @param progress progress listener, or NULL if not used - * @throw exceptions::net_exception if an error occurs - */ - virtual void addMessage(utility::inputStream& is, const size_t size, const int flags = message::FLAG_UNDEFINED, 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 - * @throw exceptions::net_exception if an error occurs - */ - virtual void 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(int& count, int& unseen) = 0; - - /** Request folder status without opening it. - * - * @return current folder status - * @throw exceptions::net_exception if an error occurs - */ - virtual shared_ptr 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 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 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 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 >& 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(shared_ptr msg, 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 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(shared_ptr event); - void notifyMessageCount(shared_ptr event); - void notifyFolder(shared_ptr event); - void notifyEvent(shared_ptr event); - -private: - - std::list m_messageChangedListeners; - std::list m_messageCountListeners; - std::list m_folderListeners; -}; - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_NET_FOLDER_HPP_INCLUDED diff --git a/vmime/net/folderStatus.hpp b/vmime/net/folderStatus.hpp deleted file mode 100644 index b94db052..00000000 --- a/vmime/net/folderStatus.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 unsigned int getMessageCount() const = 0; - - /** Returns the number of unseen messages in the folder. - * - * @return number of unseen messages - */ - virtual unsigned int getUnseenCount() const = 0; - - /** Clones this object. - * - * @return a copy of this object - */ - virtual shared_ptr clone() const = 0; -}; - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_NET_FOLDERSTATUS_HPP_INCLUDED diff --git a/vmime/net/imap/IMAPConnection.hpp b/vmime/net/imap/IMAPConnection.hpp deleted file mode 100644 index b38d0c27..00000000 --- a/vmime/net/imap/IMAPConnection.hpp +++ /dev/null @@ -1,163 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/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 VMIME_EXPORT IMAPConnection : public object -{ -public: - - IMAPConnection(shared_ptr store, shared_ptr 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 send(bool tag, const string& what, bool end); - void sendRaw(const byte_t* buffer, const size_t count); - - IMAPParser::response* readResponse(IMAPParser::literalHandler* lh = NULL); - - - shared_ptr getStore() const; - shared_ptr getStore(); - - shared_ptr getSession(); - - void fetchCapabilities(); - void invalidateCapabilities(); - const std::vector getCapabilities(); - bool hasCapability(const string& capa); - - shared_ptr getAuthenticator(); - - bool isSecuredConnection() const; - shared_ptr getConnectionInfos() const; - - shared_ptr getSocket() const; - - 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 m_store; - - shared_ptr m_auth; - - shared_ptr m_socket; - - shared_ptr m_parser; - - shared_ptr m_tag; - - char m_hierarchySeparator; - - ProtocolStates m_state; - - shared_ptr m_timeoutHandler; - - bool m_secured; - shared_ptr m_cntInfos; - - bool m_firstTag; - - std::vector m_capabilities; - bool m_capabilitiesFetched; - - bool m_noModSeq; - - - 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/net/imap/IMAPFolder.hpp b/vmime/net/imap/IMAPFolder.hpp deleted file mode 100644 index cc7334ff..00000000 --- a/vmime/net/imap/IMAPFolder.hpp +++ /dev/null @@ -1,204 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - -#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, shared_ptr store, const int type = TYPE_UNDEFINED, const int flags = FLAG_UNDEFINED); - - ~IMAPFolder(); - - int getMode() const; - - int getType(); - - int getFlags(); - - 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 int type); - - bool exists(); - - void destroy(); - - bool isOpen() const; - - shared_ptr getMessage(const int num); - std::vector > getMessages(const messageSet& msgs); - - std::vector getMessageNumbersStartingOnUID(const message::uid& uid); - - int getMessageCount(); - - shared_ptr getFolder(const folder::path::component& name); - std::vector > 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); - - void addMessage(shared_ptr msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); - void addMessage(utility::inputStream& is, const size_t size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); - - void copyMessages(const folder::path& dest, const messageSet& msgs); - - void status(int& count, int& unseen); - shared_ptr getStatus(); - - void noop(); - - void expunge(); - - shared_ptr getParent(); - - shared_ptr getStore() const; - shared_ptr getStore(); - - - void fetchMessages(std::vector >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL); - void fetchMessage(shared_ptr msg, const fetchAttributes& options); - - 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 m_store; - shared_ptr m_connection; - - folder::path m_path; - folder::path::component m_name; - - int m_mode; - bool m_open; - - int m_type; - int m_flags; - - shared_ptr m_status; - - std::vector 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/net/imap/IMAPFolderStatus.hpp b/vmime/net/imap/IMAPFolderStatus.hpp deleted file mode 100644 index 03ca5937..00000000 --- a/vmime/net/imap/IMAPFolderStatus.hpp +++ /dev/null @@ -1,124 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - unsigned int getMessageCount() const; - unsigned int getUnseenCount() const; - - shared_ptr clone() const; - - /** Returns the the number of messages with the Recent flag set. - * - * @return number of messages flagged Recent - */ - unsigned int 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: - - unsigned int m_count; - unsigned int m_unseen; - unsigned int 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/net/imap/IMAPMessage.hpp b/vmime/net/imap/IMAPMessage.hpp deleted file mode 100644 index 92903d69..00000000 --- a/vmime/net/imap/IMAPMessage.hpp +++ /dev/null @@ -1,191 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr folder, const int num); - IMAPMessage(shared_ptr folder, const int num, const uid& uid); - - ~IMAPMessage(); - - int 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 getStructure() const; - shared_ptr getStructure(); - - shared_ptr 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 - (shared_ptr 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(shared_ptr p); - - shared_ptr getParsedMessage(); - -private: - - /** Renumbers the message. - * - * @param number new sequence number - */ - void renumber(const int 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(shared_ptr 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(shared_ptr parentPart, shared_ptr str, int level = 0); - - - enum ExtractFlags - { - EXTRACT_HEADER = 0x1, - EXTRACT_BODY = 0x2, - EXTRACT_PEEK = 0x10 - }; - - void extractImpl - (shared_ptr p, - utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const int extractFlags) const; - - - shared_ptr
getOrCreateHeader(); - - - void onFolderClosed(); - - weak_ptr m_folder; - - int m_num; - size_t m_size; - int m_flags; - bool m_expunged; - uid m_uid; - vmime_uint64 m_modseq; - - shared_ptr
m_header; - shared_ptr 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/net/imap/IMAPMessagePart.hpp b/vmime/net/imap/IMAPMessagePart.hpp deleted file mode 100644 index af8581d7..00000000 --- a/vmime/net/imap/IMAPMessagePart.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const int number, const IMAPParser::body_type_mpart* mpart); - IMAPMessagePart(shared_ptr parent, const int number, const IMAPParser::body_type_1part* part); - - shared_ptr getStructure() const; - shared_ptr getStructure(); - - shared_ptr getParent() const; - - const mediaType& getType() const; - size_t getSize() const; - int getNumber() const; - - shared_ptr getHeader() const; - - - static shared_ptr create - (shared_ptr parent, const int number, const IMAPParser::body* body); - - - header& getOrCreateHeader(); - -private: - - shared_ptr m_structure; - weak_ptr m_parent; - shared_ptr
m_header; - - int m_number; - size_t m_size; - mediaType m_mediaType; -}; - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - -#endif // VMIME_NET_IMAP_IMAPMESSAGEPART_HPP_INCLUDED - diff --git a/vmime/net/imap/IMAPMessagePartContentHandler.hpp b/vmime/net/imap/IMAPMessagePartContentHandler.hpp deleted file mode 100644 index cb52b2e3..00000000 --- a/vmime/net/imap/IMAPMessagePartContentHandler.hpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr msg, shared_ptr part, const vmime::encoding& encoding); - - shared_ptr 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 m_message; - weak_ptr 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/net/imap/IMAPMessageStructure.hpp b/vmime/net/imap/IMAPMessageStructure.hpp deleted file mode 100644 index 44b6d6f0..00000000 --- a/vmime/net/imap/IMAPMessageStructure.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const std::vector & list); - - shared_ptr getPartAt(const size_t x) const; - shared_ptr getPartAt(const size_t x); - size_t getPartCount() const; - - static shared_ptr emptyStructure(); - -private: - - std::vector > 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/net/imap/IMAPParser.hpp b/vmime/net/imap/IMAPParser.hpp deleted file mode 100644 index 8c7fcb60..00000000 --- a/vmime/net/imap/IMAPParser.hpp +++ /dev/null @@ -1,5617 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/imap/IMAPTag.hpp" - -#include -#include -#include - - -//#define DEBUG_RESPONSE 1 - - -#if DEBUG_RESPONSE -# include -#endif - - -namespace vmime { -namespace net { -namespace imap { - - -#if DEBUG_RESPONSE - static int IMAPParserDebugResponse_level = 0; - static std::vector IMAPParserDebugResponse_stack; - - class IMAPParserDebugResponse - { - public: - - IMAPParserDebugResponse(const string& name, string& line, const size_t currentPos) - : m_name(name), m_line(line), m_pos(currentPos) - { - ++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 ::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 << (std::uncaught_exception() ? "FALSE" : "TRUE") << ", 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; - }; - - - #define DEBUG_ENTER_COMPONENT(x) \ - IMAPParserDebugResponse dbg(x, line, *currentPos) - - #define DEBUG_FOUND(x, y) \ - std::cout << "FOUND: " << x << ": " << y << std::endl; -#else - #define DEBUG_ENTER_COMPONENT(x) - #define DEBUG_FOUND(x, y) -#endif - - -class VMIME_EXPORT IMAPParser : public object -{ -public: - - IMAPParser(weak_ptr tag, weak_ptr sok, weak_ptr _timeoutHandler) - : m_tag(tag), m_socket(sok), m_progress(NULL), m_strict(false), - m_literalHandler(NULL), m_timeoutHandler(_timeoutHandler) - { - } - - - shared_ptr getTag() const - { - return m_tag.lock(); - } - - void setSocket(shared_ptr sok) - { - m_socket = sok; - } - - /** 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; - - 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) { } - - const vmime::string& string() const { return (m_string); } - vmime::string& string() { return (m_string); } - - - void putData(const vmime::string& chunk) - { - m_string += chunk; - } - - private: - - vmime::string& m_string; - }; - - - // Target: redirect to an output stream - class targetStream : public target - { - public: - - targetStream(utility::progressListener* progress, utility::outputStream& stream) - : target(progress), m_stream(stream) { } - - 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()); - } - - private: - - utility::outputStream& m_stream; - }; - - - // 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 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 void go(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 \ - { \ - void go(IMAPParser& parser, string& line, size_t* currentPos) \ - { \ - DEBUG_ENTER_COMPONENT(#name); \ - parent::go(parser, line, currentPos); \ - } \ - } - - - // - // Parse one character - // - - template - class one_char : public component - { - public: - - void go(IMAPParser& /* parser */, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT(string("one_char <") + C + ">: current='" + ((*currentPos < line.length() ? line[*currentPos] : '?')) + "'"); - - const size_t pos = *currentPos; - - if (pos < line.length() && line[pos] == C) - *currentPos = pos + 1; - else - throw exceptions::invalid_response("", makeResponseLine("", line, pos)); - } - }; - - - // - // SPACE ::= - // - - class SPACE : public component - { - public: - - void go(IMAPParser& /* parser */, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("SPACE"); - - size_t pos = *currentPos; - - while (pos < line.length() && (line[pos] == ' ' || line[pos] == '\t')) - ++pos; - - if (pos > *currentPos) - *currentPos = pos; - else - throw exceptions::invalid_response("", makeResponseLine("SPACE", line, pos)); - } - }; - - - // - // CR ::= - // LF ::= - // CRLF ::= CR LF - // - - class CRLF : public component - { - public: - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("CRLF"); - - size_t pos = *currentPos; - - parser.check (line, &pos, true); - - if (pos + 1 < line.length() && - line[pos] == 0x0d && line[pos + 1] == 0x0a) - { - *currentPos = pos + 2; - } - else - { - throw exceptions::invalid_response("", makeResponseLine("CRLF", line, pos)); - } - } - }; - - - // - // SPACE ::= - // CTL ::= - // CHAR ::= - // ATOM_CHAR ::= - // atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / quoted_specials - // list_wildcards ::= "%" / "*" - // quoted_specials ::= <"> / "\" - // - // tag ::= 1* (named "xtag") - // - - class xtag : public component - { - public: - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("tag"); - - size_t pos = *currentPos; - - bool end = false; - - string tagString; - 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; - } - } - - if (tagString == string(*parser.getTag())) - { - *currentPos = pos; - } - else - { - // Invalid tag - throw exceptions::invalid_response("", makeResponseLine("tag", line, pos)); - } - } - }; - - - // - // 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) - // - - class number : public component - { - public: - - number(const bool nonZero = false) - : m_nonZero(nonZero), m_value(0) - { - } - - void go(IMAPParser& /* parser */, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("number"); - - 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) - { - m_value = val; - *currentPos = pos; - } - else - { - throw exceptions::invalid_response("", makeResponseLine("number", line, pos)); - } - } - - private: - - const bool m_nonZero; - unsigned long m_value; - - public: - - unsigned long value() const { return (m_value); } - }; - - - // 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) - { - } - }; - - - // - // text ::= 1*TEXT_CHAR - // - // CHAR ::= - // TEXT_CHAR ::= - // - - class text : public component - { - public: - - text(bool allow8bits = false, const char except = 0) - : m_allow8bits(allow8bits), m_except(except) - { - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("text"); - - 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) - { - m_value.resize(len); - std::copy(line.begin() + *currentPos, line.begin() + pos, m_value.begin()); - - *currentPos = pos; - } - else - { - throw exceptions::invalid_response("", makeResponseLine("text", line, pos)); - } - } - - private: - - string m_value; - const bool m_allow8bits; - const char m_except; - - public: - - const string& value() const { return (m_value); } - }; - - - class text8 : public text - { - public: - - text8() : text(true) - { - } - }; - - - template - class text_except : public text - { - public: - - text_except() : text(false, C) - { - } - }; - - - template - class text8_except : public text - { - public: - - text8_except() : text(true, C) - { - } - }; - - - // - // QUOTED_CHAR ::= / "\" quoted_specials - // quoted_specials ::= <"> / "\" - // TEXT_CHAR ::= - // CHAR ::= - // - - class QUOTED_CHAR : public component - { - public: - - void go(IMAPParser& /* parser */, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("quoted_char"); - - size_t pos = *currentPos; - - const unsigned char c = static_cast (pos < line.length() ? line[pos] : 0); - - if (c >= 0x01 && c <= 0x7f && // 0x01 - 0x7f - c != '"' && c != '\\' && // quoted_specials - c != '\r' && c != '\n') // CR and LF - { - m_value = c; - *currentPos = pos + 1; - } - else if (c == '\\' && pos + 1 < line.length() && - (line[pos + 1] == '"' || line[pos + 1] == '\\')) - { - m_value = line[pos + 1]; - *currentPos = pos + 2; - } - else - { - throw exceptions::invalid_response("", makeResponseLine("QUOTED_CHAR", line, pos)); - } - } - - private: - - char m_value; - - public: - - char value() const { return (m_value); } - }; - - - // - // quoted ::= <"> *QUOTED_CHAR <"> - // QUOTED_CHAR ::= / "\" quoted_specials - // quoted_specials ::= <"> / "\" - // TEXT_CHAR ::= - // CHAR ::= - // - - class quoted_text : public component - { - public: - - void go(IMAPParser& /* parser */, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("quoted_text"); - - size_t pos = *currentPos; - size_t len = 0; - bool valid = false; - - m_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 == '\\') - m_value += c; - else - { - m_value += '\\'; - m_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 - { - m_value += c; - - ++pos; - ++len; - } - else - { - valid = false; - end = true; - } - } - } - - if (valid) - { - *currentPos = pos; - } - else - { - throw exceptions::invalid_response("", makeResponseLine("quoted_text", line, pos)); - } - } - - private: - - string m_value; - - public: - - const string& value() const { return (m_value); } - }; - - - // - // nil ::= "NIL" - // - - class NIL : public component - { - public: - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("NIL"); - - size_t pos = *currentPos; - - parser.checkWithArg (line, &pos, "nil"); - - *currentPos = pos; - } - }; - - - // - // string ::= quoted / literal ----> named 'xstring' - // - // nil ::= "NIL" - // quoted ::= <"> *QUOTED_CHAR <"> - // QUOTED_CHAR ::= / "\" quoted_specials - // quoted_specials ::= <"> / "\" - // TEXT_CHAR ::= - // CHAR ::= - // literal ::= "{" number "}" CRLF *CHAR8 - // ;; Number represents the number of CHAR8 octets - // CHAR8 ::= - // - - class xstring : public component - { - public: - - xstring(const bool canBeNIL = false, component* comp = NULL, const int data = 0) - : m_canBeNIL(canBeNIL), m_component(comp), m_data(data) - { - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("string"); - - size_t pos = *currentPos; - - if (m_canBeNIL && - parser.checkWithArg (line, &pos, "nil", true)) - { - // NIL - } - else - { - pos = *currentPos; - - // quoted ::= <"> *QUOTED_CHAR <"> - if (parser.check >(line, &pos, true)) - { - std::auto_ptr text(parser.get (line, &pos)); - parser.check >(line, &pos); - - if (parser.m_literalHandler != NULL) - { - literalHandler::target* target = - parser.m_literalHandler->targetFor(*m_component, m_data); - - if (target != NULL) - { - m_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); - } - - delete (target); - } - else - { - m_value = text->value(); - } - } - else - { - m_value = text->value(); - } - - DEBUG_FOUND("string[quoted]", ""); - } - // literal ::= "{" number "}" CRLF *CHAR8 - else - { - parser.check >(line, &pos); - - number* num = parser.get (line, &pos); - - const size_t length = num->value(); - delete (num); - - parser.check >(line, &pos); - - parser.check (line, &pos); - - - if (parser.m_literalHandler != NULL) - { - literalHandler::target* target = - parser.m_literalHandler->targetFor(*m_component, m_data); - - if (target != NULL) - { - m_value = "[literal-handler]"; - - parser.m_progress = target->progressListener(); - parser.readLiteral(*target, length); - parser.m_progress = NULL; - - delete (target); - } - else - { - literalHandler::targetString target(NULL, m_value); - parser.readLiteral(target, length); - } - } - else - { - literalHandler::targetString target(NULL, m_value); - parser.readLiteral(target, length); - } - - line += parser.readLine(); - - DEBUG_FOUND("string[literal]", ""); - } - } - - *currentPos = pos; - } - - private: - - bool m_canBeNIL; - string m_value; - - component* m_component; - const int m_data; - - public: - - const string& value() const { return (m_value); } - void setValue(const string& val) { m_value = val; } - }; - - - // - // nstring ::= string / nil - // - - class nstring : public xstring - { - public: - - nstring(component* comp = NULL, const int data = 0) - : xstring(true, comp, data) - { - } - }; - - - // - // astring ::= atom / string - // - - class astring : public component - { - public: - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("astring"); - - size_t pos = *currentPos; - - xstring* str = NULL; - - if ((str = parser.get (line, &pos, true))) - { - m_value = str->value(); - delete (str); - } - else - { - atom* at = parser.get (line, &pos); - m_value = at->value(); - delete (at); - } - - *currentPos = pos; - } - - private: - - string m_value; - - public: - - const string& value() const { return (m_value); } - }; - - - // - // atom ::= 1*ATOM_CHAR - // - // ATOM_CHAR ::= - // atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / quoted_specials - // CHAR ::= - // CTL ::= - // list_wildcards ::= "%" / "*" - // quoted_specials ::= <"> / "\" - // SPACE ::= - // - - class atom : public component - { - public: - - void go(IMAPParser& /* parser */, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("atom"); - - 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) - { - m_value.resize(len); - std::copy(line.begin() + *currentPos, line.begin() + pos, m_value.begin()); - - *currentPos = pos; - } - else - { - throw exceptions::invalid_response("", makeResponseLine("atom", line, pos)); - } - } - - private: - - string m_value; - - public: - - const string& value() const { return (m_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: - - special_atom(const char* str) - : m_string(str) // 'string' must be in lower-case - { - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT(string("special_atom(") + m_string + ")"); - - size_t pos = *currentPos; - - atom::go(parser, line, &pos); - - 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) - { - throw exceptions::invalid_response("", makeResponseLine(string("special_atom <") + m_string + ">", line, pos)); - } - else - { - *currentPos = pos; - } - } - - private: - - const char* m_string; - }; - - - // - // text_mime2 ::= "=?" "?" "?" "?=" - // ;; Syntax defined in [MIME-HDRS] - // - - class text_mime2 : public component - { - public: - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("text_mime2"); - - size_t pos = *currentPos; - - atom* theCharset = NULL, *theEncoding = NULL; - text* theText = NULL; - - try - { - parser.check >(line, &pos); - - theCharset = parser.get (line, &pos); - - parser.check >(line, &pos); - - theEncoding = parser.get (line, &pos); - - parser.check >(line, &pos); - - theText = parser.get >(line, &pos); - - parser.check >(line, &pos); - parser.check value()[0] == 'Q') - { - // Quoted-printable - theEncoder = new utility::encoder::qpEncoder(); - theEncoder->getProperties()["rfc2047"] = true; - } - else if (theEncoding->value()[0] == 'b' || theEncoding->value()[0] == 'B') - { - // Base64 - theEncoder = new utility::encoder::b64Encoder(); - } - - if (theEncoder) - { - utility::inputStreamStringAdapter in(theText->value()); - utility::outputStreamStringAdapter out(m_value); - - theEncoder->decode(in, out); - delete (theEncoder); - } - // No decoder available - else - { - m_value = theText->value(); - } - - delete (theEncoding); - delete (theText); - - *currentPos = pos; - } - - private: - - vmime::charset m_charset; - string m_value; - - public: - - const vmime::charset& charset() const { return (m_charset); } - const string& value() const { return (m_value); } - }; - - - // seq-number = nz-number / "*" - // ; message sequence number (COPY, FETCH, STORE - // ; commands) or unique identifier (UID COPY, - // ; UID FETCH, UID STORE commands). - - class seq_number : public component - { - public: - - seq_number() - : m_number(NULL), m_star(false) - { - } - - ~seq_number() - { - delete m_number; - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("seq_number"); - - size_t pos = *currentPos; - - if (parser.check >(line, &pos, true)) - { - m_star = true; - m_number = NULL; - } - else - { - m_star = false; - m_number = parser.get (line, &pos); - } - - *currentPos = pos; - } - - private: - - IMAPParser::number* m_number; - bool m_star; - - public: - - const IMAPParser::number* number() const { return m_number; } - bool star() const { return m_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. - - class seq_range : public component - { - public: - - seq_range() - : m_first(NULL), m_last(NULL) - { - } - - ~seq_range() - { - delete m_first; - delete m_last; - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("seq_range"); - - size_t pos = *currentPos; - - m_first = parser.get (line, &pos); - - parser.check >(line, &pos); - - m_last = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::seq_number* m_first; - IMAPParser::seq_number* m_last; - - public: - - const IMAPParser::seq_number* first() const { return m_first; } - const IMAPParser::seq_number* last() const { return m_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 - - class sequence_set : public component - { - public: - - sequence_set() - : m_number(NULL), m_range(NULL), m_nextSet(NULL) - { - } - - ~sequence_set() - { - delete m_number; - delete m_range; - delete m_nextSet; - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("sequence_set"); - - size_t pos = *currentPos; - - if ((m_range = parser.get (line, &pos, true)) == NULL) - m_number = parser.get (line, &pos); - - if (parser.check >(line, &pos, true)) - m_nextSet = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::seq_number* m_number; - IMAPParser::seq_range* m_range; - IMAPParser::sequence_set* m_nextSet; - - public: - - const IMAPParser::seq_number* seq_number() const { return m_number; } - const IMAPParser::seq_range* seq_range() const { return m_range; } - const IMAPParser::sequence_set* next_sequence_set() const { return m_nextSet; } - }; - - - // mod-sequence-value = 1*DIGIT - // ;; Positive unsigned 64-bit integer - // ;; (mod-sequence) - // ;; (1 <= n < 18,446,744,073,709,551,615) - - class mod_sequence_value : public component - { - public: - - mod_sequence_value() - : m_value(0) - { - } - - void go(IMAPParser& /* parser */, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("mod_sequence_value"); - - 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; - } - } - - m_value = val; - - *currentPos = pos; - } - - private: - - vmime_uint64 m_value; - - public: - - vmime_uint64 value() const { return m_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 - // - - class flag : public component - { - public: - - flag() - : m_type(UNKNOWN), m_flag_keyword(NULL) - { - } - - ~flag() - { - delete (m_flag_keyword); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("flag_keyword"); - - size_t pos = *currentPos; - - if (parser.check >(line, &pos, true)) - { - if (parser.check >(line, &pos, true)) - { - m_type = STAR; - } - else - { - atom* at = parser.get (line, &pos); - const string name = utility::stringUtils::toLower(at->value()); - delete (at); - - if (name == "answered") - m_type = ANSWERED; - else if (name == "flagged") - m_type = FLAGGED; - else if (name == "deleted") - m_type = DELETED; - else if (name == "seen") - m_type = SEEN; - else if (name == "draft") - m_type = DRAFT; - else - { - m_type = UNKNOWN; - m_name = name; - } - } - } - else - { - m_type = KEYWORD_OR_EXTENSION; - m_flag_keyword = parser.get (line, &pos); - } - - *currentPos = pos; - } - - - enum Type - { - UNKNOWN, - ANSWERED, - FLAGGED, - DELETED, - SEEN, - DRAFT, - KEYWORD_OR_EXTENSION, - STAR // * = custom flags allowed - }; - - private: - - Type m_type; - string m_name; - - IMAPParser::atom* m_flag_keyword; - - public: - - Type type() const { return (m_type); } - const string& name() const { return (m_name); } - - const IMAPParser::atom* flag_keyword() const { return (m_flag_keyword); } - }; - - - // - // flag_list ::= "(" #flag ")" - // - - class flag_list : public component - { - public: - - ~flag_list() - { - for (std::vector ::iterator it = m_flags.begin() ; - it != m_flags.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("flag_list"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - - while (!parser.check >(line, &pos, true)) - { - m_flags.push_back(parser.get (line, &pos)); - parser.check (line, &pos, true); - } - - *currentPos = pos; - } - - private: - - std::vector m_flags; - - public: - - const std::vector & flags() const { return (m_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. - // - - class mailbox : public component - { - public: - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("mailbox"); - - size_t pos = *currentPos; - - if (parser.checkWithArg (line, &pos, "inbox", true)) - { - m_type = INBOX; - m_name = "INBOX"; - } - else - { - m_type = OTHER; - - astring* astr = parser.get (line, &pos); - m_name = astr->value(); - delete (astr); - } - - *currentPos = pos; - } - - - enum Type - { - INBOX, - OTHER - }; - - private: - - Type m_type; - string m_name; - - public: - - Type type() const { return (m_type); } - const string& name() const { return (m_name); } - }; - - - // - // mailbox_flag := "\Marked" / "\Noinferiors" / - // "\Noselect" / "\Unmarked" / flag_extension - // - - class mailbox_flag : public component - { - public: - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("mailbox_flag"); - - size_t pos = *currentPos; - - if (parser.check >(line, &pos, true)) - { - atom* at = parser.get (line, &pos); - const string name = utility::stringUtils::toLower(at->value()); - delete (at); - - if (name == "marked") - m_type = MARKED; - else if (name == "noinferiors") - m_type = NOINFERIORS; - else if (name == "noselect") - m_type = NOSELECT; - else if (name == "unmarked") - m_type = UNMARKED; - else - { - m_type = UNKNOWN; - m_name = "\\" + name; - } - } - else - { - atom* at = parser.get (line, &pos); - const string name = utility::stringUtils::toLower(at->value()); - delete (at); - - m_type = UNKNOWN; - m_name = name; - } - - *currentPos = pos; - } - - - enum Type - { - UNKNOWN, - MARKED, - NOINFERIORS, - NOSELECT, - UNMARKED - }; - - private: - - Type m_type; - string m_name; - - public: - - Type type() const { return (m_type); } - const string& name() const { return (m_name); } - }; - - - // - // mailbox_flag_list ::= "(" #(mailbox_flag) ")" - // - - class mailbox_flag_list : public component - { - public: - - ~mailbox_flag_list() - { - for (std::vector ::iterator it = m_flags.begin() ; - it != m_flags.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("mailbox_flag_list"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - - while (!parser.check >(line, &pos, true)) - { - m_flags.push_back(parser.get (line, &pos)); - parser.check (line, &pos, true); - } - - *currentPos = pos; - } - - private: - - std::vector m_flags; - - public: - - const std::vector & flags() const { return (m_flags); } - }; - - - // - // mailbox_list ::= mailbox_flag_list SPACE - // (<"> QUOTED_CHAR <"> / nil) SPACE mailbox - // - - class mailbox_list : public component - { - public: - - mailbox_list() - : m_mailbox_flag_list(NULL), - m_mailbox(NULL), m_quoted_char('\0') - { - } - - ~mailbox_list() - { - delete (m_mailbox_flag_list); - delete (m_mailbox); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("mailbox_list"); - - size_t pos = *currentPos; - - m_mailbox_flag_list = parser.get (line, &pos); - - parser.check (line, &pos); - - if (!parser.check (line, &pos, true)) - { - parser.check >(line, &pos); - - QUOTED_CHAR* qc = parser.get (line, &pos); - m_quoted_char = qc->value(); - delete (qc); - - parser.check >(line, &pos); - } - - parser.check (line, &pos); - - m_mailbox = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::mailbox_flag_list* m_mailbox_flag_list; - IMAPParser::mailbox* m_mailbox; - char m_quoted_char; - - public: - - const IMAPParser::mailbox_flag_list* mailbox_flag_list() const { return (m_mailbox_flag_list); } - const IMAPParser::mailbox* mailbox() const { return (m_mailbox); } - char quoted_char() const { return (m_quoted_char); } - }; - - - // - // auth_type ::= atom - // ;; Defined by [IMAP-AUTH] - // - - class auth_type : public component - { - public: - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("auth_type"); - - atom* at = parser.get (line, currentPos); - m_name = utility::stringUtils::toLower(at->value()); - delete (at); - - if (m_name == "kerberos_v4") - m_type = KERBEROS_V4; - else if (m_name == "gssapi") - m_type = GSSAPI; - else if (m_name == "skey") - m_type = SKEY; - else - m_type = UNKNOWN; - } - - - enum Type - { - UNKNOWN, - - // RFC 1731 - IMAP4 Authentication Mechanisms - KERBEROS_V4, - GSSAPI, - SKEY - }; - - private: - - Type m_type; - string m_name; - - public: - - Type type() const { return (m_type); } - const string name() const { return (m_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 - // - - class status_att_val : public component - { - public: - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("status_att"); - - size_t pos = *currentPos; - - // "HIGHESTMODSEQ" SP mod-sequence-valzer - if (parser.checkWithArg (line, &pos, "highestmodseq", true)) - { - m_type = HIGHESTMODSEQ; - - parser.check (line, &pos); - m_value = parser.get (line, &pos); - } - else - { - if (parser.checkWithArg (line, &pos, "messages", true)) - { - m_type = MESSAGES; - } - else if (parser.checkWithArg (line, &pos, "recent", true)) - { - m_type = RECENT; - } - else if (parser.checkWithArg (line, &pos, "uidnext", true)) - { - m_type = UIDNEXT; - } - else if (parser.checkWithArg (line, &pos, "uidvalidity", true)) - { - m_type = UIDVALIDITY; - } - else - { - parser.checkWithArg (line, &pos, "unseen"); - m_type = UNSEEN; - } - - parser.check (line, &pos); - m_value = parser.get (line, &pos); - } - - *currentPos = pos; - } - - - enum Type - { - // Extensions - HIGHESTMODSEQ, - - // Standard IMAP - MESSAGES, - RECENT, - UIDNEXT, - UIDVALIDITY, - UNSEEN - }; - - private: - - Type m_type; - IMAPParser::component* m_value; - - public: - - Type type() const { return (m_type); } - - const IMAPParser::number* value_as_number() const - { - return dynamic_cast (m_value); - } - - const IMAPParser::mod_sequence_value* value_as_mod_sequence_value() const - { - return dynamic_cast (m_value); - } - }; - - - // status-att-list = status-att-val *(SP status-att-val) - - class status_att_list : public component - { - public: - - ~status_att_list() - { - for (std::vector ::iterator it = m_values.begin() ; - it != m_values.end() ; ++it) - { - delete *it; - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("status_att_list"); - - size_t pos = *currentPos; - - m_values.push_back(parser.get (line, &pos)); - - while (parser.check (line, &pos, true)) - m_values.push_back(parser.get (line, &pos)); - - *currentPos = pos; - } - - private: - - std::vector m_values; - - public: - - const std::vector & values() const { return m_values; } - }; - - - // - // capability ::= "AUTH=" auth_type / atom - // ;; New capabilities MUST begin with "X" or be - // ;; registered with IANA as standard or standards-track - // - - class capability : public component - { - public: - - capability() - : m_auth_type(NULL), m_atom(NULL) - { - } - - ~capability() - { - delete (m_auth_type); - delete (m_atom); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("capability"); - - size_t pos = *currentPos; - - class atom* at = parser.get (line, &pos); - - string value = at->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; - m_auth_type = parser.get (value, &pos); - delete (at); - } - else - { - m_atom = at; - } - - *currentPos = pos; - } - - private: - - IMAPParser::auth_type* m_auth_type; - IMAPParser::atom* m_atom; - - public: - - const IMAPParser::auth_type* auth_type() const { return (m_auth_type); } - const IMAPParser::atom* atom() const { return (m_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. - // - - class capability_data : public component - { - public: - - ~capability_data() - { - for (std::vector ::iterator it = m_capabilities.begin() ; - it != m_capabilities.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("capability_data"); - - size_t pos = *currentPos; - - parser.checkWithArg (line, &pos, "capability"); - - while (parser.check (line, &pos, true)) - { - capability* cap; - - if (parser.isStrict() || m_capabilities.empty()) - cap = parser.get (line, &pos); - else - cap = parser.get (line, &pos, /* noThrow */ true); // allow SPACE at end of line (Apple iCloud IMAP server) - - if (cap == NULL) break; - - m_capabilities.push_back(cap); - } - - *currentPos = pos; - } - - private: - - std::vector m_capabilities; - - public: - - const std::vector & capabilities() const { return (m_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 <"> - // - - class date_time : public component - { - public: - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("date_time"); - - size_t pos = *currentPos; - - // <"> date_day_fixed "-" date_month "-" date_year - parser.check >(line, &pos); - parser.check (line, &pos, true); - - std::auto_ptr nd(parser.get (line, &pos)); - - parser.check >(line, &pos); - - std::auto_ptr amo(parser.get (line, &pos)); - - parser.check >(line, &pos); - - std::auto_ptr ny(parser.get (line, &pos)); - - parser.check (line, &pos, true); - - // 2digit ":" 2digit ":" 2digit - std::auto_ptr nh(parser.get (line, &pos)); - - parser.check >(line, &pos); - - std::auto_ptr nmi(parser.get (line, &pos)); - - parser.check >(line, &pos); - - std::auto_ptr ns(parser.get (line, &pos)); - - parser.check (line, &pos, true); - - // ("+" / "-") 4digit - int sign = 1; - - if (!(parser.check >(line, &pos, true))) - parser.check >(line, &pos); - - std::auto_ptr nz(parser.get (line, &pos)); - - parser.check >(line, &pos); - - - m_datetime.setHour(static_cast (std::min(std::max(nh->value(), 0ul), 23ul))); - m_datetime.setMinute(static_cast (std::min(std::max(nmi->value(), 0ul), 59ul))); - m_datetime.setSecond(static_cast (std::min(std::max(ns->value(), 0ul), 59ul))); - - const int zone = static_cast (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 (std::min(std::max(nd->value(), 1ul), 31ul))); - m_datetime.setYear(static_cast (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; - } - - private: - - vmime::datetime m_datetime; - }; - - - // - // header_fld_name ::= astring - // - - typedef astring header_fld_name; - - - // - // header_list ::= "(" 1#header_fld_name ")" - // - - class header_list : public component - { - public: - - ~header_list() - { - for (std::vector ::iterator it = m_fld_names.begin() ; - it != m_fld_names.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("header_list"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - - while (!parser.check >(line, &pos, true)) - { - m_fld_names.push_back(parser.get (line, &pos)); - parser.check (line, &pos, true); - } - - *currentPos = pos; - } - - private: - - std::vector m_fld_names; - - public: - - const std::vector & fld_names() const { return (m_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. - // - - class body_extension : public component - { - public: - - body_extension() - : m_nstring(NULL), m_number(NULL) - { - } - - ~body_extension() - { - delete (m_nstring); - delete (m_number); - - for (std::vector ::iterator it = m_body_extensions.begin() ; - it != m_body_extensions.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - size_t pos = *currentPos; - - if (parser.check >(line, &pos, true)) - { - m_body_extensions.push_back - (parser.get (line, &pos)); - - while (!parser.check >(line, &pos, true)) - { - m_body_extensions.push_back(parser.get (line, &pos)); - parser.check (line, &pos, true); - } - } - else - { - if (!(m_nstring = parser.get (line, &pos, true))) - m_number = parser.get (line, &pos); - } - - *currentPos = pos; - } - - private: - - IMAPParser::nstring* m_nstring; - IMAPParser::number* m_number; - - std::vector m_body_extensions; - - public: - - IMAPParser::nstring* nstring() const { return (m_nstring); } - IMAPParser::number* number() const { return (m_number); } - - const std::vector & body_extensions() const { return (m_body_extensions); } - }; - - - // - // section_text ::= "HEADER" / "HEADER.FIELDS" [".NOT"] - // SPACE header_list / "TEXT" / "MIME" - // - - class section_text : public component - { - public: - - section_text() - : m_header_list(NULL) - { - } - - ~section_text() - { - delete (m_header_list); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("section_text"); - - size_t pos = *currentPos; - - // "HEADER.FIELDS" [".NOT"] SPACE header_list - const bool b1 = parser.checkWithArg (line, &pos, "header.fields.not", true); - const bool b2 = (b1 ? false : parser.checkWithArg (line, &pos, "header.fields", true)); - - if (b1 || b2) - { - m_type = b1 ? HEADER_FIELDS_NOT : HEADER_FIELDS; - - parser.check (line, &pos); - m_header_list = parser.get (line, &pos); - } - // "HEADER" - else if (parser.checkWithArg (line, &pos, "header", true)) - { - m_type = HEADER; - } - // "MIME" - else if (parser.checkWithArg (line, &pos, "mime", true)) - { - m_type = MIME; - } - // "TEXT" - else - { - m_type = TEXT; - - parser.checkWithArg (line, &pos, "text"); - } - - *currentPos = pos; - } - - - enum Type - { - HEADER, - HEADER_FIELDS, - HEADER_FIELDS_NOT, - MIME, - TEXT - }; - - private: - - Type m_type; - IMAPParser::header_list* m_header_list; - - public: - - Type type() const { return (m_type); } - const IMAPParser::header_list* header_list() const { return (m_header_list); } - }; - - - // - // section ::= "[" [section_text / (nz_number *["." nz_number] - // ["." (section_text / "MIME")])] "]" - // - - class section : public component - { - public: - - section() - : m_section_text1(NULL), m_section_text2(NULL) - { - } - - ~section() - { - delete (m_section_text1); - delete (m_section_text2); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("section"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - - if (!parser.check >(line, &pos, true)) - { - if (!(m_section_text1 = parser.get (line, &pos, true))) - { - nz_number* num = parser.get (line, &pos); - m_nz_numbers.push_back(static_cast (num->value())); - delete (num); - - while (parser.check >(line, &pos, true)) - { - if ((num = parser.get (line, &pos, true))) - { - m_nz_numbers.push_back(static_cast (num->value())); - delete (num); - } - else - { - m_section_text2 = parser.get (line, &pos); - break; - } - } - } - - parser.check >(line, &pos); - } - - *currentPos = pos; - } - - private: - - section_text* m_section_text1; - section_text* m_section_text2; - std::vector m_nz_numbers; - - public: - - const section_text* section_text1() const { return (m_section_text1); } - const section_text* section_text2() const { return (m_section_text2); } - const std::vector & nz_numbers() const { return (m_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 ")" - // - - class address : public component - { - public: - - address() - : m_addr_name(NULL), m_addr_adl(NULL), - m_addr_mailbox(NULL), m_addr_host(NULL) - { - } - - ~address() - { - delete (m_addr_name); - delete (m_addr_adl); - delete (m_addr_mailbox); - delete (m_addr_host); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("address"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - m_addr_name = parser.get (line, &pos); - parser.check (line, &pos); - m_addr_adl = parser.get (line, &pos); - parser.check (line, &pos); - m_addr_mailbox = parser.get (line, &pos); - parser.check (line, &pos); - m_addr_host = parser.get (line, &pos); - parser.check >(line, &pos); - - *currentPos = pos; - } - - private: - - nstring* m_addr_name; - nstring* m_addr_adl; - nstring* m_addr_mailbox; - nstring* m_addr_host; - - public: - - nstring* addr_name() const { return (m_addr_name); } - nstring* addr_adl() const { return (m_addr_adl); } - nstring* addr_mailbox() const { return (m_addr_mailbox); } - nstring* addr_host() const { return (m_addr_host); } - }; - - - // - // address_list ::= "(" 1*address ")" / nil - // - - class address_list : public component - { - public: - - ~address_list() - { - for (std::vector ::iterator it = m_addresses.begin() ; - it != m_addresses.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("address_list"); - - size_t pos = *currentPos; - - if (!parser.check (line, &pos, true)) - { - parser.check >(line, &pos); - - while (!parser.check >(line, &pos, true)) - { - m_addresses.push_back(parser.get
(line, &pos)); - parser.check (line, &pos, true); - } - } - - *currentPos = pos; - } - - private: - - std::vector m_addresses; - - public: - - const std::vector & addresses() const { return (m_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 ")" - // - - class envelope : public component - { - public: - - envelope() - : m_env_date(NULL), m_env_subject(NULL), - m_env_from(NULL), m_env_sender(NULL), m_env_reply_to(NULL), - m_env_to(NULL), m_env_cc(NULL), m_env_bcc(NULL), - m_env_in_reply_to(NULL), m_env_message_id(NULL) - { - } - - ~envelope() - { - delete (m_env_date); - delete (m_env_subject); - delete (m_env_from); - delete (m_env_sender); - delete (m_env_reply_to); - delete (m_env_to); - delete (m_env_cc); - delete (m_env_bcc); - delete (m_env_in_reply_to); - delete (m_env_message_id); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("envelope"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - - m_env_date = parser.get (line, &pos); - parser.check (line, &pos); - - m_env_subject = parser.get (line, &pos); - parser.check (line, &pos); - - m_env_from = parser.get (line, &pos); - parser.check (line, &pos); - - m_env_sender = parser.get (line, &pos); - parser.check (line, &pos); - - m_env_reply_to = parser.get (line, &pos); - parser.check (line, &pos); - - m_env_to = parser.get (line, &pos); - parser.check (line, &pos); - - m_env_cc = parser.get (line, &pos); - parser.check (line, &pos); - - m_env_bcc = parser.get (line, &pos); - parser.check (line, &pos); - - m_env_in_reply_to = parser.get (line, &pos); - parser.check (line, &pos); - - m_env_message_id = parser.get (line, &pos); - - parser.check >(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::env_date* m_env_date; - IMAPParser::env_subject* m_env_subject; - IMAPParser::env_from* m_env_from; - IMAPParser::env_sender* m_env_sender; - IMAPParser::env_reply_to* m_env_reply_to; - IMAPParser::env_to* m_env_to; - IMAPParser::env_cc* m_env_cc; - IMAPParser::env_bcc* m_env_bcc; - IMAPParser::env_in_reply_to* m_env_in_reply_to; - IMAPParser::env_message_id* m_env_message_id; - - public: - - const IMAPParser::env_date* env_date() const { return (m_env_date); } - const IMAPParser::env_subject* env_subject() const { return (m_env_subject); } - const IMAPParser::env_from* env_from() const { return (m_env_from); } - const IMAPParser::env_sender* env_sender() const { return (m_env_sender); } - const IMAPParser::env_reply_to* env_reply_to() const { return (m_env_reply_to); } - const IMAPParser::env_to* env_to() const { return (m_env_to); } - const IMAPParser::env_cc* env_cc() const { return (m_env_cc); } - const IMAPParser::env_bcc* env_bcc() const { return (m_env_bcc); } - const IMAPParser::env_in_reply_to* env_in_reply_to() const { return (m_env_in_reply_to); } - const IMAPParser::env_message_id* env_message_id() const { return (m_env_message_id); } - }; - - - // - // body_fld_desc ::= nstring - // - - typedef nstring body_fld_desc; - - - // - // body_fld_id ::= nstring - // - - typedef nstring body_fld_id; - - - // - // body_fld_md5 ::= nstring - // - - typedef nstring body_fld_md5; - - - // - // body_fld_octets ::= number - // - - typedef number body_fld_octets; - - - // - // body_fld_lines ::= number - // - - typedef number body_fld_lines; - - - // - // body_fld_enc ::= (<"> ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ - // "QUOTED-PRINTABLE") <">) / string - // - - typedef xstring body_fld_enc; - - - // - // body_fld_param_item ::= string SPACE string - // - - class body_fld_param_item : public component - { - public: - - body_fld_param_item() - : m_string1(NULL), m_string2(NULL) - { - } - - ~body_fld_param_item() - { - delete (m_string1); - delete (m_string2); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body_fld_param_item"); - - size_t pos = *currentPos; - - if (!parser.isStrict()) - { - // Some servers send an instead of a here: - // eg. ... (CHARSET "X-UNKNOWN") ... - if (!(m_string1 = parser.get (line, &pos, true))) - { - std::auto_ptr at(parser.get (line, &pos)); - - m_string1 = new xstring(); - m_string1->setValue(at->value()); - } - } - else - { - m_string1 = parser.get (line, &pos); - } - - parser.check (line, &pos); - m_string2 = parser.get (line, &pos); - - DEBUG_FOUND("body_fld_param_item", "<" << m_string1->value() << ", " << m_string2->value() << ">"); - - *currentPos = pos; - } - - private: - - xstring* m_string1; - xstring* m_string2; - - public: - - const xstring* string1() const { return (m_string1); } - const xstring* string2() const { return (m_string2); } - }; - - - // - // body_fld_param ::= "(" 1#(body_fld_param_item) ")" / nil - // - - class body_fld_param : public component - { - public: - - ~body_fld_param() - { - for (std::vector ::iterator it = m_items.begin() ; - it != m_items.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body_fld_param"); - - size_t pos = *currentPos; - - if (parser.check >(line, &pos, true)) - { - m_items.push_back(parser.get (line, &pos)); - - while (!parser.check >(line, &pos, true)) - { - parser.check (line, &pos); - m_items.push_back(parser.get (line, &pos)); - } - } - else - { - parser.check (line, &pos); - } - - *currentPos = pos; - } - - private: - - std::vector m_items; - - public: - - const std::vector & items() const { return (m_items); } - }; - - - // - // body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil - // - - class body_fld_dsp : public component - { - public: - - body_fld_dsp() - : m_string(NULL), m_body_fld_param(NULL) - { - } - - ~body_fld_dsp() - { - delete (m_string); - delete (m_body_fld_param); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body_fld_dsp"); - - size_t pos = *currentPos; - - if (parser.check >(line, &pos, true)) - { - m_string = parser.get (line, &pos); - parser.check (line, &pos); - m_body_fld_param = parser.get (line, &pos); - parser.check >(line, &pos); - } - else - { - parser.check (line, &pos); - } - - *currentPos = pos; - } - - private: - - class xstring* m_string; - class body_fld_param* m_body_fld_param; - - public: - - const class xstring* str() const { return (m_string); } - const class body_fld_param* body_fld_param() const { return (m_body_fld_param); } - }; - - - // - // body_fld_lang ::= nstring / "(" 1#string ")" - // - - class body_fld_lang : public component - { - public: - - ~body_fld_lang() - { - for (std::vector ::iterator it = m_strings.begin() ; - it != m_strings.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body_fld_lang"); - - size_t pos = *currentPos; - - if (parser.check >(line, &pos, true)) - { - m_strings.push_back(parser.get (line, &pos)); - - while (!parser.check >(line, &pos, true)) - { - parser.check (line, &pos); - m_strings.push_back(parser.get (line, &pos)); - } - } - else - { - m_strings.push_back(parser.get (line, &pos)); - } - - *currentPos = pos; - } - - private: - - std::vector m_strings; - - public: - - const std::vector & strings() const { return (m_strings); } - }; - - - // - // body_fields ::= body_fld_param SPACE body_fld_id SPACE - // body_fld_desc SPACE body_fld_enc SPACE - // body_fld_octets - // - - class body_fields : public component - { - public: - - body_fields() - : m_body_fld_param(NULL), m_body_fld_id(NULL), - m_body_fld_desc(NULL), m_body_fld_enc(NULL), m_body_fld_octets(NULL) - { - } - - ~body_fields() - { - delete (m_body_fld_param); - delete (m_body_fld_id); - delete (m_body_fld_desc); - delete (m_body_fld_enc); - delete (m_body_fld_octets); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body_fields"); - - size_t pos = *currentPos; - - m_body_fld_param = parser.get (line, &pos); - parser.check (line, &pos); - m_body_fld_id = parser.get (line, &pos); - parser.check (line, &pos); - m_body_fld_desc = parser.get (line, &pos); - parser.check (line, &pos); - m_body_fld_enc = parser.get (line, &pos); - parser.check (line, &pos); - m_body_fld_octets = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::body_fld_param* m_body_fld_param; - IMAPParser::body_fld_id* m_body_fld_id; - IMAPParser::body_fld_desc* m_body_fld_desc; - IMAPParser::body_fld_enc* m_body_fld_enc; - IMAPParser::body_fld_octets* m_body_fld_octets; - - public: - - const IMAPParser::body_fld_param* body_fld_param() const { return (m_body_fld_param); } - const IMAPParser::body_fld_id* body_fld_id() const { return (m_body_fld_id); } - const IMAPParser::body_fld_desc* body_fld_desc() const { return (m_body_fld_desc); } - const IMAPParser::body_fld_enc* body_fld_enc() const { return (m_body_fld_enc); } - const IMAPParser::body_fld_octets* body_fld_octets() const { return (m_body_fld_octets); } - }; - - - // - // media_subtype ::= string - // ;; Defined in [MIME-IMT] - // - - typedef xstring media_subtype; - - - // - // media_text ::= <"> "TEXT" <"> SPACE media_subtype - // ;; Defined in [MIME-IMT] - // - - class media_text : public component - { - public: - - media_text() - : m_media_subtype(NULL) - { - } - - ~media_text() - { - delete (m_media_subtype); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("media_text"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - parser.checkWithArg (line, &pos, "text"); - parser.check >(line, &pos); - parser.check (line, &pos); - - m_media_subtype = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::media_subtype* m_media_subtype; - - public: - - const IMAPParser::media_subtype* media_subtype() const { return (m_media_subtype); } - }; - - - // - // media_message ::= <"> "MESSAGE" <"> SPACE <"> "RFC822" <"> - // ;; Defined in [MIME-IMT] - // - - class media_message : public component - { - public: - - media_message() - : m_media_subtype(NULL) - { - } - - ~media_message() - { - delete m_media_subtype; - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("media_message"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - parser.checkWithArg (line, &pos, "message"); - parser.check >(line, &pos); - parser.check (line, &pos); - - //parser.check >(line, &pos); - //parser.checkWithArg (line, &pos, "rfc822"); - //parser.check >(line, &pos); - - m_media_subtype = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::media_subtype* m_media_subtype; - - public: - - const IMAPParser::media_subtype* media_subtype() const { return (m_media_subtype); } - }; - - - // - // media_basic ::= (<"> ("APPLICATION" / "AUDIO" / "IMAGE" / - // "MESSAGE" / "VIDEO") <">) / string) - // SPACE media_subtype - // ;; Defined in [MIME-IMT] - - class media_basic : public component - { - public: - - media_basic() - : m_media_type(NULL), m_media_subtype(NULL) - { - } - - ~media_basic() - { - delete (m_media_type); - delete (m_media_subtype); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("media_basic"); - - size_t pos = *currentPos; - - m_media_type = parser.get (line, &pos); - - parser.check (line, &pos); - - m_media_subtype = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::xstring* m_media_type; - IMAPParser::media_subtype* m_media_subtype; - - public: - - const IMAPParser::xstring* media_type() const { return (m_media_type); } - const IMAPParser::media_subtype* media_subtype() const { return (m_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 - // - - class body_ext_1part : public component - { - public: - - body_ext_1part() - : m_body_fld_md5(NULL), m_body_fld_dsp(NULL), m_body_fld_lang(NULL) - { - } - - ~body_ext_1part() - { - delete (m_body_fld_md5); - delete (m_body_fld_dsp); - delete (m_body_fld_lang); - - for (std::vector ::iterator it = m_body_extensions.begin() ; - it != m_body_extensions.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body_ext_1part"); - - size_t pos = *currentPos; - - m_body_fld_md5 = parser.get (line, &pos); - - // [SPACE body_fld_dsp - if (parser.check (line, &pos, true)) - { - m_body_fld_dsp = parser.get (line, &pos); - - // [SPACE body_fld_lang - if (parser.check (line, &pos, true)) - { - m_body_fld_lang = parser.get (line, &pos); - - // [SPACE 1#body_extension] - if (parser.check (line, &pos, true)) - { - m_body_extensions.push_back - (parser.get (line, &pos)); - - parser.check (line, &pos, true); - - body_extension* ext = NULL; - - while ((ext = parser.get (line, &pos, true)) != NULL) - { - m_body_extensions.push_back(ext); - parser.check (line, &pos, true); - } - } - } - } - - *currentPos = pos; - } - - private: - - IMAPParser::body_fld_md5* m_body_fld_md5; - IMAPParser::body_fld_dsp* m_body_fld_dsp; - IMAPParser::body_fld_lang* m_body_fld_lang; - - std::vector m_body_extensions; - - public: - - const IMAPParser::body_fld_md5* body_fld_md5() const { return (m_body_fld_md5); } - const IMAPParser::body_fld_dsp* body_fld_dsp() const { return (m_body_fld_dsp); } - const IMAPParser::body_fld_lang* body_fld_lang() const { return (m_body_fld_lang); } - - const std::vector body_extensions() const { return (m_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 - - class body_ext_mpart : public component - { - public: - - body_ext_mpart() - : m_body_fld_param(NULL), m_body_fld_dsp(NULL), m_body_fld_lang(NULL) - { - } - - ~body_ext_mpart() - { - delete (m_body_fld_param); - delete (m_body_fld_dsp); - delete (m_body_fld_lang); - - for (std::vector ::iterator it = m_body_extensions.begin() ; - it != m_body_extensions.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body_ext_mpart"); - - size_t pos = *currentPos; - - m_body_fld_param = parser.get (line, &pos); - - // [SPACE body_fld_dsp SPACE body_fld_lang [SPACE 1#body_extension]] - if (parser.check (line, &pos, true)) - { - m_body_fld_dsp = parser.get (line, &pos); - parser.check (line, &pos); - m_body_fld_lang = parser.get (line, &pos); - - // [SPACE 1#body_extension] - if (parser.check (line, &pos, true)) - { - m_body_extensions.push_back - (parser.get (line, &pos)); - - parser.check (line, &pos, true); - - body_extension* ext = NULL; - - while ((ext = parser.get (line, &pos, true)) != NULL) - { - m_body_extensions.push_back(ext); - parser.check (line, &pos, true); - } - } - } - - *currentPos = pos; - } - - private: - - IMAPParser::body_fld_param* m_body_fld_param; - IMAPParser::body_fld_dsp* m_body_fld_dsp; - IMAPParser::body_fld_lang* m_body_fld_lang; - - std::vector m_body_extensions; - - public: - - const IMAPParser::body_fld_param* body_fld_param() const { return (m_body_fld_param); } - const IMAPParser::body_fld_dsp* body_fld_dsp() const { return (m_body_fld_dsp); } - const IMAPParser::body_fld_lang* body_fld_lang() const { return (m_body_fld_lang); } - - const std::vector body_extensions() const { return (m_body_extensions); } - }; - - - // - // body_type_basic ::= media_basic SPACE body_fields - // ;; MESSAGE subtype MUST NOT be "RFC822" - // - - class body_type_basic : public component - { - public: - - body_type_basic() - : m_media_basic(NULL), m_body_fields(NULL) - { - } - - ~body_type_basic() - { - delete (m_media_basic); - delete (m_body_fields); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body_type_basic"); - - size_t pos = *currentPos; - - m_media_basic = parser.get (line, &pos); - parser.check (line, &pos); - m_body_fields = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::media_basic* m_media_basic; - IMAPParser::body_fields* m_body_fields; - - public: - - const IMAPParser::media_basic* media_basic() const { return (m_media_basic); } - const IMAPParser::body_fields* body_fields() const { return (m_body_fields); } - }; - - - // - // body_type_msg ::= media_message SPACE body_fields SPACE envelope - // SPACE body SPACE body_fld_lines - // - - class xbody; - typedef xbody body; - - class body_type_msg : public component - { - public: - - body_type_msg() - : m_media_message(NULL), m_body_fields(NULL), - m_envelope(NULL), m_body(NULL), m_body_fld_lines(NULL) - { - } - - ~body_type_msg() - { - delete (m_media_message); - delete (m_body_fields); - delete (m_envelope); - delete (m_body); - delete (m_body_fld_lines); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body_type_msg"); - - size_t pos = *currentPos; - - m_media_message = parser.get (line, &pos); - parser.check (line, &pos); - m_body_fields = parser.get (line, &pos); - parser.check (line, &pos); - - // BUGFIX: made SPACE optional. This is not standard, but some servers - // seem to return responses like that... - m_envelope = parser.get (line, &pos); - parser.check (line, &pos, true); - m_body = parser.get (line, &pos); - parser.check (line, &pos, true); - m_body_fld_lines = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::media_message* m_media_message; - IMAPParser::body_fields* m_body_fields; - IMAPParser::envelope* m_envelope; - IMAPParser::xbody* m_body; - IMAPParser::body_fld_lines* m_body_fld_lines; - - public: - - const IMAPParser::media_message* media_message() const { return (m_media_message); } - const IMAPParser::body_fields* body_fields() const { return (m_body_fields); } - const IMAPParser::envelope* envelope() const { return (m_envelope); } - const IMAPParser::xbody* body() const { return (m_body); } - const IMAPParser::body_fld_lines* body_fld_lines() const { return (m_body_fld_lines); } - }; - - - // - // body_type_text ::= media_text SPACE body_fields SPACE body_fld_lines - // - - class body_type_text : public component - { - public: - - body_type_text() - : m_media_text(NULL), - m_body_fields(NULL), m_body_fld_lines(NULL) - { - } - - ~body_type_text() - { - delete (m_media_text); - delete (m_body_fields); - delete (m_body_fld_lines); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body_type_text"); - - size_t pos = *currentPos; - - m_media_text = parser.get (line, &pos); - parser.check (line, &pos); - m_body_fields = parser.get (line, &pos); - parser.check (line, &pos); - m_body_fld_lines = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::media_text* m_media_text; - IMAPParser::body_fields* m_body_fields; - IMAPParser::body_fld_lines* m_body_fld_lines; - - public: - - const IMAPParser::media_text* media_text() const { return (m_media_text); } - const IMAPParser::body_fields* body_fields() const { return (m_body_fields); } - const IMAPParser::body_fld_lines* body_fld_lines() const { return (m_body_fld_lines); } - }; - - - // - // body_type_1part ::= (body_type_basic / body_type_msg / body_type_text) - // [SPACE body_ext_1part] - // - - class body_type_1part : public component - { - public: - - body_type_1part() - : m_body_type_basic(NULL), m_body_type_msg(NULL), - m_body_type_text(NULL), m_body_ext_1part(NULL) - { - } - - ~body_type_1part() - { - delete (m_body_type_basic); - delete (m_body_type_msg); - delete (m_body_type_text); - - delete (m_body_ext_1part); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body_type_1part"); - - size_t pos = *currentPos; - - if (!(m_body_type_text = parser.get (line, &pos, true))) - if (!(m_body_type_msg = parser.get (line, &pos, true))) - m_body_type_basic = parser.get (line, &pos); - - if (parser.check (line, &pos, true)) - { - m_body_ext_1part = parser.get (line, &pos, true); - - if (!m_body_ext_1part) - --pos; - } - - *currentPos = pos; - } - - private: - - IMAPParser::body_type_basic* m_body_type_basic; - IMAPParser::body_type_msg* m_body_type_msg; - IMAPParser::body_type_text* m_body_type_text; - - IMAPParser::body_ext_1part* m_body_ext_1part; - - public: - - const IMAPParser::body_type_basic* body_type_basic() const { return (m_body_type_basic); } - const IMAPParser::body_type_msg* body_type_msg() const { return (m_body_type_msg); } - const IMAPParser::body_type_text* body_type_text() const { return (m_body_type_text); } - - const IMAPParser::body_ext_1part* body_ext_1part() const { return (m_body_ext_1part); } - }; - - - // - // body_type_mpart ::= 1*body SPACE media_subtype - // [SPACE body_ext_mpart] - // - - class body_type_mpart : public component - { - public: - - body_type_mpart() - : m_media_subtype(NULL), m_body_ext_mpart(NULL) - { - } - - ~body_type_mpart() - { - delete (m_media_subtype); - delete (m_body_ext_mpart); - - for (std::vector ::iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body_type_mpart"); - - size_t pos = *currentPos; - - m_list.push_back(parser.get (line, &pos)); - - for (xbody* b ; (b = parser.get (line, &pos, true)) ; ) - m_list.push_back(b); - - parser.check (line, &pos); - - m_media_subtype = parser.get (line, &pos); - - if (parser.check (line, &pos, true)) - m_body_ext_mpart = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::media_subtype* m_media_subtype; - IMAPParser::body_ext_mpart* m_body_ext_mpart; - - std::vector m_list; - - public: - - const std::vector & list() const { return (m_list); } - - const IMAPParser::media_subtype* media_subtype() const { return (m_media_subtype); } - const IMAPParser::body_ext_mpart* body_ext_mpart() const { return (m_body_ext_mpart); } - }; - - - // - // xbody ::= "(" body_type_1part / body_type_mpart ")" - // - - class xbody : public component - { - public: - - xbody() - : m_body_type_1part(NULL), m_body_type_mpart(NULL) - { - } - - ~xbody() - { - delete (m_body_type_1part); - delete (m_body_type_mpart); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("body"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - - if (!(m_body_type_mpart = parser.get (line, &pos, true))) - m_body_type_1part = parser.get (line, &pos); - - parser.check >(line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::body_type_1part* m_body_type_1part; - IMAPParser::body_type_mpart* m_body_type_mpart; - - public: - - const IMAPParser::body_type_1part* body_type_1part() const { return (m_body_type_1part); } - const IMAPParser::body_type_mpart* body_type_mpart() const { return (m_body_type_mpart); } - }; - - - // - // uniqueid ::= nz_number - // ;; Strictly ascending - // - // 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 ")" - - class msg_att_item : public component - { - public: - - msg_att_item() - : m_date_time(NULL), m_number(NULL), m_envelope(NULL), - m_uniqueid(NULL), m_nstring(NULL), m_body(NULL), m_flag_list(NULL), - m_section(NULL), m_mod_sequence_value(NULL) - - { - } - - ~msg_att_item() - { - delete (m_date_time); - delete (m_number); - delete (m_envelope); - delete (m_uniqueid); - delete (m_nstring); - delete (m_body); - delete (m_flag_list); - delete (m_section); - delete m_mod_sequence_value; - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("msg_att_item"); - - size_t pos = *currentPos; - - // "ENVELOPE" SPACE envelope - if (parser.checkWithArg (line, &pos, "envelope", true)) - { - m_type = ENVELOPE; - - parser.check (line, &pos); - m_envelope = parser.get (line, &pos); - } - // "FLAGS" SPACE "(" #(flag / "\Recent") ")" - else if (parser.checkWithArg (line, &pos, "flags", true)) - { - m_type = FLAGS; - - parser.check (line, &pos); - - m_flag_list = parser.get (line, &pos); - } - // "INTERNALDATE" SPACE date_time - else if (parser.checkWithArg (line, &pos, "internaldate", true)) - { - m_type = INTERNALDATE; - - parser.check (line, &pos); - m_date_time = parser.get (line, &pos); - } - // "RFC822" ".HEADER" SPACE nstring - else if (parser.checkWithArg (line, &pos, "rfc822.header", true)) - { - m_type = RFC822_HEADER; - - parser.check (line, &pos); - - m_nstring = parser.get (line, &pos); - } - // "RFC822" ".TEXT" SPACE nstring - else if (parser.checkWithArg (line, &pos, "rfc822.text", true)) - { - m_type = RFC822_TEXT; - - parser.check (line, &pos); - - m_nstring = parser.getWithArgs - (line, &pos, this, RFC822_TEXT); - } - // "RFC822.SIZE" SPACE number - else if (parser.checkWithArg (line, &pos, "rfc822.size", true)) - { - m_type = RFC822_SIZE; - - parser.check (line, &pos); - m_number = parser.get (line, &pos); - } - // "RFC822" SPACE nstring - else if (parser.checkWithArg (line, &pos, "rfc822", true)) - { - m_type = RFC822; - - parser.check (line, &pos); - - m_nstring = parser.get (line, &pos); - } - // "BODY" "STRUCTURE" SPACE body - else if (parser.checkWithArg (line, &pos, "bodystructure", true)) - { - m_type = BODY_STRUCTURE; - - parser.check (line, &pos); - - m_body = parser.get (line, &pos); - } - // "BODY" section ["<" number ">"] SPACE nstring - // "BODY" SPACE body - else if (parser.checkWithArg (line, &pos, "body", true)) - { - m_section = parser.get (line, &pos, true); - - // "BODY" section ["<" number ">"] SPACE nstring - if (m_section != NULL) - { - m_type = BODY_SECTION; - - if (parser.check >(line, &pos, true)) - { - m_number = parser.get (line, &pos); - parser.check '> >(line, &pos); - } - - parser.check (line, &pos); - - m_nstring = parser.getWithArgs - (line, &pos, this, BODY_SECTION); - } - // "BODY" SPACE body - else - { - m_type = BODY; - - parser.check (line, &pos); - - m_body = parser.get (line, &pos); - } - } - // "MODSEQ" SP "(" mod_sequence_value ")" - else if (parser.checkWithArg (line, &pos, "modseq", true)) - { - m_type = MODSEQ; - - parser.check (line, &pos); - parser.check >(line, &pos); - - m_mod_sequence_value = parser.get (line, &pos); - - parser.check >(line, &pos); - } - // "UID" SPACE uniqueid - else - { - m_type = UID; - - parser.checkWithArg (line, &pos, "uid"); - parser.check (line, &pos); - - m_uniqueid = parser.get (line, &pos); - } - - *currentPos = pos; - } - - - enum Type - { - ENVELOPE, - FLAGS, - INTERNALDATE, - RFC822, - RFC822_SIZE, - RFC822_HEADER, - RFC822_TEXT, - BODY, - BODY_SECTION, - BODY_STRUCTURE, - UID, - MODSEQ - }; - - private: - - Type m_type; - - IMAPParser::date_time* m_date_time; - IMAPParser::number* m_number; - IMAPParser::envelope* m_envelope; - IMAPParser::nz_number* m_uniqueid; - IMAPParser::nstring* m_nstring; - IMAPParser::xbody* m_body; - IMAPParser::flag_list* m_flag_list; - IMAPParser::section* m_section; - IMAPParser::mod_sequence_value* m_mod_sequence_value; - - public: - - Type type() const { return (m_type); } - - const IMAPParser::date_time* date_time() const { return (m_date_time); } - const IMAPParser::number* number() const { return (m_number); } - const IMAPParser::envelope* envelope() const { return (m_envelope); } - const IMAPParser::nz_number* unique_id() const { return (m_uniqueid); } - const IMAPParser::nstring* nstring() const { return (m_nstring); } - const IMAPParser::xbody* body() const { return (m_body); } - const IMAPParser::flag_list* flag_list() const { return (m_flag_list); } - const IMAPParser::section* section() const { return (m_section); } - const IMAPParser::mod_sequence_value* mod_sequence_value() { return m_mod_sequence_value; } - }; - - - // - // msg_att ::= "(" 1#(msg_att_item) ")" - // - - class msg_att : public component - { - public: - - ~msg_att() - { - for (std::vector ::iterator it = m_items.begin() ; - it != m_items.end() ; ++it) - { - delete (*it); - } - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("msg_att"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - - m_items.push_back(parser.get (line, &pos)); - - while (!parser.check >(line, &pos, true)) - { - parser.check (line, &pos); - m_items.push_back(parser.get (line, &pos)); - } - - *currentPos = pos; - } - - private: - - std::vector m_items; - - public: - - const std::vector & items() const { return (m_items); } - }; - - - // - // message_data ::= nz_number SPACE ("EXPUNGE" / - // ("FETCH" SPACE msg_att)) - // - - class message_data : public component - { - public: - - message_data() - : m_number(0), m_msg_att(NULL) - { - } - - ~message_data() - { - delete (m_msg_att); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("message_data"); - - size_t pos = *currentPos; - - nz_number* num = parser.get (line, &pos); - m_number = static_cast (num->value()); - delete (num); - - parser.check (line, &pos); - - if (parser.checkWithArg (line, &pos, "expunge", true)) - { - m_type = EXPUNGE; - } - else - { - parser.checkWithArg (line, &pos, "fetch"); - - parser.check (line, &pos); - - m_type = FETCH; - m_msg_att = parser.get (line, &pos); - } - - *currentPos = pos; - } - - - enum Type - { - EXPUNGE, - FETCH - }; - - private: - - Type m_type; - unsigned int m_number; - IMAPParser::msg_att* m_msg_att; - - public: - - Type type() const { return (m_type); } - unsigned int number() const { return (m_number); } - const IMAPParser::msg_att* msg_att() const { return (m_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 / - // atom [SPACE 1*] - // - // IMAP Extension for Conditional STORE (RFC-4551): - // - // resp-text-code =/ "HIGHESTMODSEQ" SP mod-sequence-value / - // "NOMODSEQ" / - // "MODIFIED" SP set - - class resp_text_code : public component - { - public: - - resp_text_code() - : m_nz_number(NULL), m_atom(NULL), m_flag_list(NULL), - m_text(NULL), m_capability_data(NULL) - { - } - - ~resp_text_code() - { - delete (m_nz_number); - delete (m_atom); - delete (m_flag_list); - delete (m_text); - delete m_capability_data; - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("resp_text_code"); - - size_t pos = *currentPos; - - // "ALERT" - if (parser.checkWithArg (line, &pos, "alert", true)) - { - m_type = ALERT; - } - // "PARSE" - else if (parser.checkWithArg (line, &pos, "parse", true)) - { - m_type = PARSE; - } - // capability_data - else if ((m_capability_data = parser.get (line, &pos, true))) - { - m_type = CAPABILITY; - } - // "PERMANENTFLAGS" SPACE flag_list - else if (parser.checkWithArg (line, &pos, "permanentflags", true)) - { - m_type = PERMANENTFLAGS; - - parser.check (line, &pos); - - m_flag_list = parser.get (line, &pos); - } - // "READ-ONLY" - else if (parser.checkWithArg (line, &pos, "read-only", true)) - { - m_type = READ_ONLY; - } - // "READ-WRITE" - else if (parser.checkWithArg (line, &pos, "read-write", true)) - { - m_type = READ_WRITE; - } - // "TRYCREATE" - else if (parser.checkWithArg (line, &pos, "trycreate", true)) - { - m_type = TRYCREATE; - } - // "UIDVALIDITY" SPACE nz_number - else if (parser.checkWithArg (line, &pos, "uidvalidity", true)) - { - m_type = UIDVALIDITY; - - parser.check (line, &pos); - m_nz_number = parser.get (line, &pos); - } - // "UIDNEXT" SPACE nz_number - else if (parser.checkWithArg (line, &pos, "uidnext", true)) - { - m_type = UIDNEXT; - - parser.check (line, &pos); - m_nz_number = parser.get (line, &pos); - } - // "UNSEEN" SPACE nz_number - else if (parser.checkWithArg (line, &pos, "unseen", true)) - { - m_type = UNSEEN; - - parser.check (line, &pos); - m_nz_number = parser.get (line, &pos); - } - // "HIGHESTMODSEQ" SP mod-sequence-value - else if (parser.checkWithArg (line, &pos, "highestmodseq", true)) - { - m_type = HIGHESTMODSEQ; - - parser.check (line, &pos); - m_mod_sequence_value = parser.get (line, &pos); - } - // "NOMODSEQ" - else if (parser.checkWithArg (line, &pos, "nomodseq", true)) - { - m_type = NOMODSEQ; - } - // "MODIFIED" SP sequence-set - else if (parser.checkWithArg (line, &pos, "modified", true)) - { - m_type = MODIFIED; - - parser.check (line, &pos); - - m_sequence_set = parser.get (line, &pos); - } - // atom [SPACE 1*] - else - { - m_type = OTHER; - - m_atom = parser.get (line, &pos); - - if (parser.check (line, &pos, true)) - m_text = parser.get >(line, &pos); - } - - *currentPos = pos; - } - - - enum Type - { - // Extensions - HIGHESTMODSEQ, - NOMODSEQ, - MODIFIED, - - // Standard IMAP - ALERT, - PARSE, - CAPABILITY, - PERMANENTFLAGS, - READ_ONLY, - READ_WRITE, - TRYCREATE, - UIDVALIDITY, - UIDNEXT, - UNSEEN, - OTHER - }; - - private: - - Type m_type; - - IMAPParser::nz_number* m_nz_number; - IMAPParser::atom* m_atom; - IMAPParser::flag_list* m_flag_list; - IMAPParser::text* m_text; - IMAPParser::mod_sequence_value* m_mod_sequence_value; - IMAPParser::sequence_set* m_sequence_set; - IMAPParser::capability_data* m_capability_data; - - public: - - Type type() const { return (m_type); } - - const IMAPParser::nz_number* nz_number() const { return (m_nz_number); } - const IMAPParser::atom* atom() const { return (m_atom); } - const IMAPParser::flag_list* flag_list() const { return (m_flag_list); } - const IMAPParser::text* text() const { return (m_text); } - const IMAPParser::mod_sequence_value* mod_sequence_value() const { return m_mod_sequence_value; } - const IMAPParser::sequence_set* sequence_set() const { return m_sequence_set; } - const IMAPParser::capability_data* capability_data() const { return m_capability_data; } - }; - - - // - // resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text) - // ;; text SHOULD NOT begin with "[" or "=" - - class resp_text : public component - { - public: - - resp_text() - : m_resp_text_code(NULL) - { - } - - ~resp_text() - { - delete (m_resp_text_code); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("resp_text"); - - size_t pos = *currentPos; - - if (parser.check >(line, &pos, true)) - { - m_resp_text_code = parser.get (line, &pos); - - parser.check >(line, &pos); - parser.check (line, &pos, true); - } - - text_mime2* text1 = parser.get (line, &pos, true); - - if (text1 != NULL) - { - m_text = text1->value(); - delete (text1); - } - else - { - IMAPParser::text* text2 = - parser.get (line, &pos, true); - - if (text2 != NULL) - { - m_text = text2->value(); - delete (text2); - } - else - { - // Empty response text - } - } - - *currentPos = pos; - } - - private: - - IMAPParser::resp_text_code* m_resp_text_code; - string m_text; - - public: - - const IMAPParser::resp_text_code* resp_text_code() const { return (m_resp_text_code); } - const string& text() const { return (m_text); } - }; - - - // - // continue_req ::= "+" SPACE (resp_text / base64) - // - - class continue_req : public component - { - public: - - continue_req() - : m_resp_text(NULL) - { - } - - ~continue_req() - { - delete (m_resp_text); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("continue_req"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - - if (!parser.isStrict()) - { - // Some servers do not send SPACE when response text is empty - if (parser.check (line, &pos, true)) - m_resp_text = parser.get (line, &pos); - else - m_resp_text = new IMAPParser::resp_text(); // empty - } - else - { - parser.check (line, &pos); - - m_resp_text = parser.get (line, &pos); - } - - parser.check (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::resp_text* m_resp_text; - - public: - - const IMAPParser::resp_text* resp_text() const { return (m_resp_text); } - }; - - - // - // resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text - // ;; Status condition - // - - class resp_cond_state : public component - { - public: - - resp_cond_state() - : m_resp_text(NULL), m_status(BAD) - { - } - - ~resp_cond_state() - { - delete (m_resp_text); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("resp_cond_state"); - - size_t pos = *currentPos; - - if (parser.checkWithArg (line, &pos, "ok", true)) - { - m_status = OK; - } - else if (parser.checkWithArg (line, &pos, "no", true)) - { - m_status = NO; - } - else - { - parser.checkWithArg (line, &pos, "bad"); - m_status = BAD; - } - - parser.check (line, &pos); - - m_resp_text = parser.get (line, &pos); - - *currentPos = pos; - } - - - enum Status - { - OK, - NO, - BAD - }; - - private: - - IMAPParser::resp_text* m_resp_text; - Status m_status; - - public: - - const IMAPParser::resp_text* resp_text() const { return (m_resp_text); } - Status status() const { return (m_status); } - }; - - - // - // resp_cond_bye ::= "BYE" SPACE resp_text - // - - class resp_cond_bye : public component - { - public: - - resp_cond_bye() - : m_resp_text(NULL) - { - } - - ~resp_cond_bye() - { - delete (m_resp_text); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("resp_cond_bye"); - - size_t pos = *currentPos; - - parser.checkWithArg (line, &pos, "bye"); - - parser.check (line, &pos); - - m_resp_text = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::resp_text* m_resp_text; - - public: - - const IMAPParser::resp_text* resp_text() const { return (m_resp_text); } - }; - - - // - // resp_cond_auth ::= ("OK" / "PREAUTH") SPACE resp_text - // ;; Authentication condition - // - - class resp_cond_auth : public component - { - public: - - resp_cond_auth() - : m_resp_text(NULL) - { - } - - ~resp_cond_auth() - { - delete (m_resp_text); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("resp_cond_auth"); - - size_t pos = *currentPos; - - if (parser.checkWithArg (line, &pos, "ok", true)) - { - m_cond = OK; - } - else - { - parser.checkWithArg (line, &pos, "preauth"); - - m_cond = PREAUTH; - } - - parser.check (line, &pos); - - m_resp_text = parser.get (line, &pos); - - *currentPos = pos; - } - - - enum Condition - { - OK, - PREAUTH - }; - - private: - - Condition m_cond; - IMAPParser::resp_text* m_resp_text; - - public: - - Condition condition() const { return (m_cond); } - const IMAPParser::resp_text* resp_text() const { return (m_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" - // - - class mailbox_data : public component - { - public: - - mailbox_data() - : m_number(NULL), m_mailbox_flag_list(NULL), m_mailbox_list(NULL), - m_mailbox(NULL), m_text(NULL), m_status_att_list(NULL) - { - } - - ~mailbox_data() - { - delete (m_number); - delete (m_mailbox_flag_list); - delete (m_mailbox_list); - delete (m_mailbox); - delete (m_text); - - for (std::vector ::iterator it = m_search_nz_number_list.begin() ; - it != m_search_nz_number_list.end() ; ++it) - { - delete (*it); - } - - delete m_status_att_list; - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("mailbox_data"); - - size_t pos = *currentPos; - - m_number = parser.get (line, &pos, true); - - if (m_number) - { - parser.check (line, &pos); - - if (parser.checkWithArg (line, &pos, "exists", true)) - { - m_type = EXISTS; - } - else - { - parser.checkWithArg (line, &pos, "recent"); - - m_type = RECENT; - } - } - else - { - // "FLAGS" SPACE mailbox_flag_list - if (parser.checkWithArg (line, &pos, "flags", true)) - { - parser.check (line, &pos); - - m_mailbox_flag_list = parser.get (line, &pos); - - m_type = FLAGS; - } - // "LIST" SPACE mailbox_list - else if (parser.checkWithArg (line, &pos, "list", true)) - { - parser.check (line, &pos); - - m_mailbox_list = parser.get (line, &pos); - - m_type = LIST; - } - // "LSUB" SPACE mailbox_list - else if (parser.checkWithArg (line, &pos, "lsub", true)) - { - parser.check (line, &pos); - - m_mailbox_list = parser.get (line, &pos); - - m_type = LSUB; - } - // "MAILBOX" SPACE text - else if (parser.checkWithArg (line, &pos, "mailbox", true)) - { - parser.check (line, &pos); - - m_text = parser.get (line, &pos); - - m_type = MAILBOX; - } - // "SEARCH" [SPACE 1#nz_number] - else if (parser.checkWithArg (line, &pos, "search", true)) - { - if (parser.check (line, &pos, true)) - { - m_search_nz_number_list.push_back - (parser.get (line, &pos)); - - while (parser.check (line, &pos, true)) - { - m_search_nz_number_list.push_back - (parser.get (line, &pos)); - } - } - - m_type = SEARCH; - } - // "STATUS" SPACE mailbox SPACE - // "(" [status_att_list] ")" - else - { - parser.checkWithArg (line, &pos, "status"); - parser.check (line, &pos); - - m_mailbox = parser.get (line, &pos); - - parser.check (line, &pos); - - parser.check >(line, &pos); - - m_status_att_list = parser.get (line, &pos, true); - - parser.check >(line, &pos); - - m_type = STATUS; - } - } - - *currentPos = pos; - } - - - enum Type - { - FLAGS, - LIST, - LSUB, - MAILBOX, - SEARCH, - STATUS, - EXISTS, - RECENT - }; - - private: - - Type m_type; - - IMAPParser::number* m_number; - IMAPParser::mailbox_flag_list* m_mailbox_flag_list; - IMAPParser::mailbox_list* m_mailbox_list; - IMAPParser::mailbox* m_mailbox; - IMAPParser::text* m_text; - std::vector m_search_nz_number_list; - IMAPParser::status_att_list* m_status_att_list; - - public: - - Type type() const { return (m_type); } - - const IMAPParser::number* number() const { return (m_number); } - const IMAPParser::mailbox_flag_list* mailbox_flag_list() const { return (m_mailbox_flag_list); } - const IMAPParser::mailbox_list* mailbox_list() const { return (m_mailbox_list); } - const IMAPParser::mailbox* mailbox() const { return (m_mailbox); } - const IMAPParser::text* text() const { return (m_text); } - const std::vector & search_nz_number_list() const { return (m_search_nz_number_list); } - const IMAPParser::status_att_list* status_att_list() const { return m_status_att_list; } - }; - - - // - // response_data ::= "*" SPACE (resp_cond_state / resp_cond_bye / - // mailbox_data / message_data / capability_data) CRLF - // - - class response_data : public component - { - public: - - response_data() - : m_resp_cond_state(NULL), m_resp_cond_bye(NULL), - m_mailbox_data(NULL), m_message_data(NULL), m_capability_data(NULL) - { - } - - ~response_data() - { - delete (m_resp_cond_state); - delete (m_resp_cond_bye); - delete (m_mailbox_data); - delete (m_message_data); - delete (m_capability_data); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("response_data"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - parser.check (line, &pos); - - if (!(m_resp_cond_state = parser.get (line, &pos, true))) - if (!(m_resp_cond_bye = parser.get (line, &pos, true))) - if (!(m_mailbox_data = parser.get (line, &pos, true))) - if (!(m_message_data = parser.get (line, &pos, true))) - m_capability_data = parser.get (line, &pos); - - if (!parser.isStrict()) - { - // Allow SPACEs at end of line - while (parser.check (line, &pos, /* noThrow */ true)) - ; - } - - parser.check (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::resp_cond_state* m_resp_cond_state; - IMAPParser::resp_cond_bye* m_resp_cond_bye; - IMAPParser::mailbox_data* m_mailbox_data; - IMAPParser::message_data* m_message_data; - IMAPParser::capability_data* m_capability_data; - - public: - - const IMAPParser::resp_cond_state* resp_cond_state() const { return (m_resp_cond_state); } - const IMAPParser::resp_cond_bye* resp_cond_bye() const { return (m_resp_cond_bye); } - const IMAPParser::mailbox_data* mailbox_data() const { return (m_mailbox_data); } - const IMAPParser::message_data* message_data() const { return (m_message_data); } - const IMAPParser::capability_data* capability_data() const { return (m_capability_data); } - }; - - - class continue_req_or_response_data : public component - { - public: - - continue_req_or_response_data() - : m_continue_req(NULL), m_response_data(NULL) - { - } - - ~continue_req_or_response_data() - { - delete (m_continue_req); - delete (m_response_data); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("continue_req_or_response_data"); - - size_t pos = *currentPos; - - if (!(m_continue_req = parser.get (line, &pos, true))) - m_response_data = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::continue_req* m_continue_req; - IMAPParser::response_data* m_response_data; - - public: - - const IMAPParser::continue_req* continue_req() const { return (m_continue_req); } - const IMAPParser::response_data* response_data() const { return (m_response_data); } - }; - - - // - // response_fatal ::= "*" SPACE resp_cond_bye CRLF - // ;; Server closes connection immediately - // - - class response_fatal : public component - { - public: - - response_fatal() - : m_resp_cond_bye(NULL) - { - } - - ~response_fatal() - { - delete (m_resp_cond_bye); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("response_fatal"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - parser.check (line, &pos); - - m_resp_cond_bye = parser.get (line, &pos); - - if (!parser.isStrict()) - { - // Allow SPACEs at end of line - while (parser.check (line, &pos, /* noThrow */ true)) - ; - } - - parser.check (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::resp_cond_bye* m_resp_cond_bye; - - public: - - const IMAPParser::resp_cond_bye* resp_cond_bye() const { return (m_resp_cond_bye); } - }; - - - // - // response_tagged ::= tag SPACE resp_cond_state CRLF - // - - class response_tagged : public component - { - public: - - response_tagged() - : m_resp_cond_state(NULL) - { - } - - ~response_tagged() - { - delete (m_resp_cond_state); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("response_tagged"); - - size_t pos = *currentPos; - - parser.check (line, &pos); - parser.check (line, &pos); - m_resp_cond_state = parser.get (line, &pos); - - if (!parser.isStrict()) - { - // Allow SPACEs at end of line - while (parser.check (line, &pos, /* noThrow */ true)) - ; - } - - parser.check (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::resp_cond_state* m_resp_cond_state; - - public: - - const IMAPParser::resp_cond_state* resp_cond_state() const { return (m_resp_cond_state); } - }; - - - // - // response_done ::= response_tagged / response_fatal - // - - class response_done : public component - { - public: - - response_done() - : m_response_tagged(NULL), m_response_fatal(NULL) - { - } - - ~response_done() - { - delete (m_response_tagged); - delete (m_response_fatal); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("response_done"); - - size_t pos = *currentPos; - - if (!(m_response_tagged = parser.get (line, &pos, true))) - m_response_fatal = parser.get (line, &pos); - - *currentPos = pos; - } - - private: - - IMAPParser::response_tagged* m_response_tagged; - IMAPParser::response_fatal* m_response_fatal; - - public: - - const IMAPParser::response_tagged* response_tagged() const { return (m_response_tagged); } - const IMAPParser::response_fatal* response_fatal() const { return (m_response_fatal); } - }; - - - // - // response ::= *(continue_req / response_data) response_done - // - - class response : public component - { - public: - - response() - : m_response_done(NULL) - { - } - - ~response() - { - for (std::vector ::iterator - it = m_continue_req_or_response_data.begin() ; - it != m_continue_req_or_response_data.end() ; ++it) - { - delete (*it); - } - - delete (m_response_done); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("response"); - - size_t pos = *currentPos; - string curLine = line; - bool partial = false; // partial response - - IMAPParser::continue_req_or_response_data* resp = NULL; - - while ((resp = parser.get (curLine, &pos, true)) != NULL) - { - m_continue_req_or_response_data.push_back(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) - m_response_done = parser.get (curLine, &pos); - - *currentPos = pos; - } - - - 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; - } - - private: - - std::vector m_continue_req_or_response_data; - IMAPParser::response_done* m_response_done; - - string m_errorLog; - - public: - - const std::vector & continue_req_or_response_data() const { return (m_continue_req_or_response_data); } - const IMAPParser::response_done* response_done() const { return (m_response_done); } - }; - - - // - // greeting ::= "*" SPACE (resp_cond_auth / resp_cond_bye) CRLF - // - - class greeting : public component - { - public: - - greeting() - : m_resp_cond_auth(NULL), m_resp_cond_bye(NULL) - { - } - - ~greeting() - { - delete (m_resp_cond_auth); - delete (m_resp_cond_bye); - } - - void go(IMAPParser& parser, string& line, size_t* currentPos) - { - DEBUG_ENTER_COMPONENT("greeting"); - - size_t pos = *currentPos; - - parser.check >(line, &pos); - parser.check (line, &pos); - - if (!(m_resp_cond_auth = parser.get (line, &pos, true))) - m_resp_cond_bye = parser.get (line, &pos); - - parser.check (line, &pos); - - *currentPos = pos; - } - - void setErrorLog(const string& errorLog) - { - m_errorLog = errorLog; - } - - const string& getErrorLog() const - { - return m_errorLog; - } - - private: - - IMAPParser::resp_cond_auth* m_resp_cond_auth; - IMAPParser::resp_cond_bye* m_resp_cond_bye; - - string m_errorLog; - - public: - - const IMAPParser::resp_cond_auth* resp_cond_auth() const { return (m_resp_cond_auth); } - const IMAPParser::resp_cond_bye* resp_cond_bye() const { return (m_resp_cond_bye); } - }; - - - - // - // The main functions used to parse a response - // - - response* readResponse(literalHandler* lh = NULL) - { - size_t pos = 0; - string line = readLine(); - - m_literalHandler = lh; - response* resp = get (line, &pos); - m_literalHandler = NULL; - - resp->setErrorLog(lastLine()); - - return (resp); - } - - - greeting* readGreeting() - { - size_t pos = 0; - string line = readLine(); - - greeting* greet = get (line, &pos); - - greet->setErrorLog(lastLine()); - - return greet; - } - - - // - // Get a token and advance - // - - template - TYPE* get(string& line, size_t* currentPos, - const bool noThrow = false) - { - component* resp = new TYPE; - return internalGet (resp, line, currentPos, noThrow); - } - - - template - TYPE* getWithArgs(string& line, size_t* currentPos, - ARG1_TYPE arg1, ARG2_TYPE arg2, const bool noThrow = false) - { - component* resp = new TYPE(arg1, arg2); - return internalGet (resp, line, currentPos, noThrow); - } - - -private: - - template - TYPE* internalGet(component* resp, string& line, size_t* currentPos, - const bool noThrow = false) - { - const size_t oldPos = *currentPos; - - try - { - resp->go(*this, line, currentPos); - } - catch (exceptions::operation_timed_out&) - { - // Always rethrow - throw; - } - catch (exception&) - { - *currentPos = oldPos; - - delete (resp); - if (!noThrow) throw; - return (NULL); - } - - return static_cast (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 a token and advance - // - - template - bool check(string& line, size_t* currentPos, - const bool noThrow = false) - { - const size_t oldPos = *currentPos; - - try - { - TYPE term; - term.go(*this, line, currentPos); - } - catch (exceptions::operation_timed_out&) - { - // Always rethrow - throw; - } - catch (exception&) - { - *currentPos = oldPos; - - if (!noThrow) throw; - return false; - } - - return true; - } - - template - bool checkWithArg(string& line, size_t* currentPos, - const ARG_TYPE arg, const bool noThrow = false) - { - const size_t oldPos = *currentPos; - - try - { - TYPE term(arg); - term.go(*this, line, currentPos); - } - catch (exceptions::operation_timed_out&) - { - // Always rethrow - throw; - } - catch (exception&) - { - *currentPos = oldPos; - - if (!noThrow) throw; - return false; - } - - return true; - } - - -private: - - weak_ptr m_tag; - weak_ptr m_socket; - - utility::progressListener* m_progress; - - bool m_strict; - - literalHandler* m_literalHandler; - - weak_ptr m_timeoutHandler; - - - string m_buffer; - - string m_lastLine; - -public: - - // - // Read one 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 - - return (line); - } - - - // - // Read available data from socket stream - // - - void read() - { - string receiveBuffer; - - shared_ptr toh = m_timeoutHandler.lock(); - shared_ptr 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 - { - platform::getHandler()->wait(); - 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 toh = m_timeoutHandler.lock(); - shared_ptr 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 - { - platform::getHandler()->wait(); - 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_progress) - m_progress->stop(count); - } -}; - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - -#endif // VMIME_NET_IMAP_IMAPPARSER_HPP_INCLUDED diff --git a/vmime/net/imap/IMAPSStore.hpp b/vmime/net/imap/IMAPSStore.hpp deleted file mode 100644 index 9d27bdd0..00000000 --- a/vmime/net/imap/IMAPSStore.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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/net/imap/IMAPServiceInfos.hpp b/vmime/net/imap/IMAPServiceInfos.hpp deleted file mode 100644 index 376f4476..00000000 --- a/vmime/net/imap/IMAPServiceInfos.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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/net/imap/IMAPStore.hpp b/vmime/net/imap/IMAPStore.hpp deleted file mode 100644 index f854fadf..00000000 --- a/vmime/net/imap/IMAPStore.hpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr auth, const bool secured = false); - ~IMAPStore(); - - const string getProtocolName() const; - - shared_ptr getDefaultFolder(); - shared_ptr getRootFolder(); - shared_ptr 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 getConnectionInfos() const; - shared_ptr getConnection(); - -protected: - - // Connection - shared_ptr m_connection; - - - - shared_ptr connection(); - - - void registerFolder(IMAPFolder* folder); - void unregisterFolder(IMAPFolder* folder); - - std::list 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/net/imap/IMAPTag.hpp b/vmime/net/imap/IMAPTag.hpp deleted file mode 100644 index 430a3b10..00000000 --- a/vmime/net/imap/IMAPTag.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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); - IMAPTag(const IMAPTag& tag); - -public: - - IMAPTag(); - - IMAPTag& operator++(); // ++IMAPTag - const IMAPTag operator++(int); // IMAPTag++ - - int maximumNumber() const; - int number() const; - - operator string() 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/net/imap/IMAPUtils.hpp b/vmime/net/imap/IMAPUtils.hpp deleted file mode 100644 index 988b6a2c..00000000 --- a/vmime/net/imap/IMAPUtils.hpp +++ /dev/null @@ -1,129 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/mailboxList.hpp" - -#include - - -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); - - static int folderTypeFromFlags(const IMAPParser::mailbox_flag_list* list); - static int folderFlagsFromFlags(const IMAPParser::mailbox_flag_list* list); - - static int messageFlagsFromFlags(const IMAPParser::flag_list* list); - - static const 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 const string buildFetchRequest - (shared_ptr 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); - - /** Returns a list of message sequence numbers given a message set. - * - * @param msgs message set - * @return list of message numbers - */ - static const std::vector messageSetToNumberList(const messageSet& msgs); - -private: - - static const string buildFetchRequestImpl - (shared_ptr 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/net/imap/imap.hpp b/vmime/net/imap/imap.hpp deleted file mode 100644 index 5e10619a..00000000 --- a/vmime/net/imap/imap.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/net/maildir/format/courierMaildirFormat.hpp b/vmime/net/maildir/format/courierMaildirFormat.hpp deleted file mode 100644 index b8443426..00000000 --- a/vmime/net/maildir/format/courierMaildirFormat.hpp +++ /dev/null @@ -1,121 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr 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 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 & 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/net/maildir/format/kmailMaildirFormat.hpp b/vmime/net/maildir/format/kmailMaildirFormat.hpp deleted file mode 100644 index 98ca212e..00000000 --- a/vmime/net/maildir/format/kmailMaildirFormat.hpp +++ /dev/null @@ -1,109 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr 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 listFolders - (const folder::path& root, const bool recursive) const; - -protected: - - bool supports() const; - - - /** Recursive implementation of listFolders(). - */ - void listFoldersImpl(std::vector & 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/net/maildir/maildir.hpp b/vmime/net/maildir/maildir.hpp deleted file mode 100644 index 42bbbea4..00000000 --- a/vmime/net/maildir/maildir.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/net/maildir/maildirFolder.hpp b/vmime/net/maildir/maildirFolder.hpp deleted file mode 100644 index 5cff53fc..00000000 --- a/vmime/net/maildir/maildirFolder.hpp +++ /dev/null @@ -1,190 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - -#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() { } - -public: - - maildirFolder(const folder::path& path, shared_ptr store); - - ~maildirFolder(); - - - int getMode() const; - - int getType(); - - int getFlags(); - - 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 int type); - - bool exists(); - - void destroy(); - - bool isOpen() const; - - shared_ptr getMessage(const int num); - std::vector > getMessages(const messageSet& msgs); - - int getMessageCount(); - - shared_ptr getFolder(const folder::path::component& name); - std::vector > 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); - - void addMessage(shared_ptr msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); - void addMessage(utility::inputStream& is, const size_t size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); - - void copyMessages(const folder::path& dest, const messageSet& msgs); - - void status(int& count, int& unseen); - shared_ptr getStatus(); - - void expunge(); - - shared_ptr getParent(); - - shared_ptr getStore() const; - shared_ptr getStore(); - - - void fetchMessages(std::vector >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL); - void fetchMessage(shared_ptr msg, const fetchAttributes& options); - - int getFetchCapabilities() const; - - std::vector getMessageNumbersStartingOnUID(const message::uid& uid); - -private: - - void scanFolder(); - - void listFolders(std::vector >& list, const bool recursive); - - void registerMessage(maildirMessage* msg); - void unregisterMessage(maildirMessage* msg); - - const utility::file::path getMessageFSPath(const int number) const; - - void onStoreDisconnected(); - - void onClose(); - - void deleteMessagesImpl(const std::vector & nums); - void setMessageFlagsImpl(const std::vector & nums, const int flags, const int mode); - - void copyMessagesImpl(const folder::path& dest, const std::vector & 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 m_store; - - folder::path m_path; - folder::path::component m_name; - - int m_mode; - bool m_open; - - int m_unreadMessageCount; - int 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 m_messageInfos; - - // Instanciated message objects - std::vector 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/net/maildir/maildirFolderStatus.hpp b/vmime/net/maildir/maildirFolderStatus.hpp deleted file mode 100644 index 155fb20f..00000000 --- a/vmime/net/maildir/maildirFolderStatus.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - unsigned int getMessageCount() const; - unsigned int getUnseenCount() const; - - shared_ptr clone() const; - - - void setMessageCount(const unsigned int count); - void setUnseenCount(const unsigned int unseen); - -private: - - unsigned int m_count; - unsigned int 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/net/maildir/maildirFormat.hpp b/vmime/net/maildir/maildirFormat.hpp deleted file mode 100644 index c0daf288..00000000 --- a/vmime/net/maildir/maildirFormat.hpp +++ /dev/null @@ -1,195 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr store); - - shared_ptr getStore() const; - - private: - - weak_ptr 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 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 detect(shared_ptr 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(shared_ptr ctx); - - - /** Returns the current context. - * - * @return current context - */ - shared_ptr getContext(); - - /** Returns the current context (const version). - * - * @return current context - */ - shared_ptr 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 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/net/maildir/maildirMessage.hpp b/vmime/net/maildir/maildirMessage.hpp deleted file mode 100644 index 7480d49c..00000000 --- a/vmime/net/maildir/maildirMessage.hpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr folder, const int num); - - ~maildirMessage(); - - - int getNumber() const; - - const uid getUID() const; - - size_t getSize() const; - - bool isExpunged() const; - - shared_ptr getStructure() const; - shared_ptr getStructure(); - - shared_ptr 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(shared_ptr 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(shared_ptr p); - - shared_ptr getParsedMessage(); - -private: - - void fetch(shared_ptr folder, const fetchAttributes& options); - - void onFolderClosed(); - - shared_ptr
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 m_folder; - - int m_num; - size_t m_size; - int m_flags; - bool m_expunged; - uid m_uid; - - shared_ptr
m_header; - shared_ptr 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/net/maildir/maildirMessagePart.hpp b/vmime/net/maildir/maildirMessagePart.hpp deleted file mode 100644 index 3a4be0f3..00000000 --- a/vmime/net/maildir/maildirMessagePart.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const int number, const bodyPart& part); - ~maildirMessagePart(); - - - shared_ptr getStructure() const; - shared_ptr getStructure(); - - weak_ptr getParent() const { return (m_parent); } - - const mediaType& getType() const; - size_t getSize() const; - int getNumber() const; - - shared_ptr 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 m_structure; - weak_ptr m_parent; - shared_ptr
m_header; - - int m_number; - size_t m_size; - mediaType m_mediaType; - - 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/net/maildir/maildirMessageStructure.hpp b/vmime/net/maildir/maildirMessageStructure.hpp deleted file mode 100644 index a43fc15c..00000000 --- a/vmime/net/maildir/maildirMessageStructure.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr parent, const bodyPart& part); - maildirMessageStructure(shared_ptr parent, const std::vector >& list); - - - shared_ptr getPartAt(const size_t x) const; - shared_ptr getPartAt(const size_t x); - - size_t getPartCount() const; - - static shared_ptr emptyStructure(); - -private: - - static shared_ptr m_emptyStructure; - - std::vector > 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/net/maildir/maildirServiceInfos.hpp b/vmime/net/maildir/maildirServiceInfos.hpp deleted file mode 100644 index 70ddc6dc..00000000 --- a/vmime/net/maildir/maildirServiceInfos.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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/net/maildir/maildirStore.hpp b/vmime/net/maildir/maildirStore.hpp deleted file mode 100644 index efadfdfe..00000000 --- a/vmime/net/maildir/maildirStore.hpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace net { -namespace maildir { - - -class maildirFolder; - - -/** maildir store service. - */ - -class VMIME_EXPORT maildirStore : public store -{ - friend class maildirFolder; - -public: - - maildirStore(shared_ptr sess, shared_ptr auth); - ~maildirStore(); - - const string getProtocolName() const; - - shared_ptr getDefaultFolder(); - shared_ptr getRootFolder(); - shared_ptr 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 getConnectionInfos() const; - - shared_ptr getFormat(); - shared_ptr getFormat() const; - -private: - - void registerFolder(maildirFolder* folder); - void unregisterFolder(maildirFolder* folder); - - - std::list m_folders; - - shared_ptr 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/net/maildir/maildirUtils.hpp b/vmime/net/maildir/maildirUtils.hpp deleted file mode 100644 index 82deefbb..00000000 --- a/vmime/net/maildir/maildirUtils.hpp +++ /dev/null @@ -1,151 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr dir); - - /** Returns a list of message numbers given a message set. - * - * @param msgs message set - * @return list of message numbers - */ - static const std::vector messageSetToNumberList(const messageSet& msgs); -}; - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - -#endif // VMIME_NET_MAILDIR_MAILDIRUTILS_HPP_INCLUDED diff --git a/vmime/net/message.hpp b/vmime/net/message.hpp deleted file mode 100644 index 5bb62c53..00000000 --- a/vmime/net/message.hpp +++ /dev/null @@ -1,355 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/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 -{ -protected: - - messagePart() { } - messagePart(const messagePart&) : object() { } - - virtual ~messagePart() { } - -public: - - /** Return the structure of this part. - * - * @return structure of the part - */ - virtual shared_ptr getStructure() const = 0; - - /** Return the structure of this part. - * - * @return structure of the part - */ - virtual shared_ptr 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 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 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 int getNumber() const = 0; - - /** 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 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 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 -{ -protected: - - messageStructure() { } - messageStructure(const messageStructure&) : object() { } - -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 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 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 -{ -protected: - - message() { } - message(const message&) : object() { } - -public: - - virtual ~message() { } - - /** 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 getStructure() const = 0; - - /** Return the MIME structure of the message (must fetch before). - * - * @return MIME structure of the message - */ - virtual shared_ptr getStructure() = 0; - - /** Return a reference to the header fields of the message (must fetch before). - * - * @return header section of the message - */ - virtual shared_ptr 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 int 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'. */ - - FLAG_UNDEFINED = 9999 /**< Used internally (this should not be returned - by the flags() function). */ - }; - - /** 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 - (shared_ptr 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(shared_ptr 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 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/net/messageSet.hpp b/vmime/net/messageSet.hpp deleted file mode 100644 index 6c7d7f44..00000000 --- a/vmime/net/messageSet.hpp +++ /dev/null @@ -1,335 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/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 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 int 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 int first, const int 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 - */ - int 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 - */ - int getLast() const; - - void enumerate(messageSetEnumerator& en) const; - - messageRange* clone() const; - -private: - - int 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 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 int 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 int first, const int 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 & 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 & 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; - -private: - - messageSet(); - - std::vector m_ranges; -}; - - -} // net -} // vmime - - -#endif // VMIME_NET_MESSAGESET_HPP_INCLUDED diff --git a/vmime/net/pop3/POP3Command.hpp b/vmime/net/pop3/POP3Command.hpp deleted file mode 100644 index cc3c4fd5..00000000 --- a/vmime/net/pop3/POP3Command.hpp +++ /dev/null @@ -1,113 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 CAPA(); - static shared_ptr NOOP(); - static shared_ptr AUTH(const string& mechName); - static shared_ptr STLS(); - static shared_ptr APOP(const string& username, const string& digest); - static shared_ptr USER(const string& username); - static shared_ptr PASS(const string& password); - static shared_ptr STAT(); - static shared_ptr LIST(); - static shared_ptr LIST(const unsigned long msg); - static shared_ptr UIDL(); - static shared_ptr UIDL(const unsigned long msg); - static shared_ptr DELE(const unsigned long msg); - static shared_ptr RETR(const unsigned long msg); - static shared_ptr TOP(const unsigned long msg, const unsigned long lines); - static shared_ptr RSET(); - static shared_ptr QUIT(); - - /** Creates a new POP3 command with the specified text. - * - * @param text command text - * @return a new POP3Command object - */ - static shared_ptr createCommand(const string& text); - - /** Sends this command over the specified connection. - * - * @param conn connection onto which the command will be sent - */ - virtual void send(shared_ptr 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; - -protected: - - POP3Command(const string& text); - POP3Command(const POP3Command&); - -private: - - string m_text; -}; - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 - -#endif // VMIME_NET_POP3_POP3COMMAND_HPP_INCLUDED diff --git a/vmime/net/pop3/POP3Connection.hpp b/vmime/net/pop3/POP3Connection.hpp deleted file mode 100644 index 3622f745..00000000 --- a/vmime/net/pop3/POP3Connection.hpp +++ /dev/null @@ -1,125 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/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: - - POP3Connection(shared_ptr store, shared_ptr auth); - virtual ~POP3Connection(); - - - virtual void connect(); - virtual bool isConnected() const; - virtual void disconnect(); - - bool isSecuredConnection() const; - shared_ptr getConnectionInfos() const; - - virtual shared_ptr getStore(); - virtual shared_ptr getSocket(); - virtual shared_ptr getTimeoutHandler(); - virtual shared_ptr getAuthenticator(); - virtual shared_ptr getSession(); - -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 getCapabilities(); - - void internalDisconnect(); - - - weak_ptr m_store; - - shared_ptr m_auth; - shared_ptr m_socket; - shared_ptr m_timeoutHandler; - - bool m_authenticated; - bool m_secured; - - shared_ptr m_cntInfos; - - std::vector 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/net/pop3/POP3Folder.hpp b/vmime/net/pop3/POP3Folder.hpp deleted file mode 100644 index 27ea6e5f..00000000 --- a/vmime/net/pop3/POP3Folder.hpp +++ /dev/null @@ -1,157 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - -#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&); - -public: - - POP3Folder(const folder::path& path, shared_ptr store); - - ~POP3Folder(); - - int getMode() const; - - int getType(); - - int getFlags(); - - 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 int type); - - bool exists(); - - void destroy(); - - bool isOpen() const; - - shared_ptr getMessage(const int num); - std::vector > getMessages(const messageSet& msgs); - - int getMessageCount(); - - shared_ptr getFolder(const folder::path::component& name); - std::vector > 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); - - void addMessage(shared_ptr msg, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); - void addMessage(utility::inputStream& is, const size_t size, const int flags = message::FLAG_UNDEFINED, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); - - void copyMessages(const folder::path& dest, const messageSet& msgs); - - void status(int& count, int& unseen); - shared_ptr getStatus(); - - void expunge(); - - shared_ptr getParent(); - - shared_ptr getStore() const; - shared_ptr getStore(); - - - void fetchMessages(std::vector >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL); - void fetchMessage(shared_ptr msg, const fetchAttributes& options); - - int getFetchCapabilities() const; - - std::vector getMessageNumbersStartingOnUID(const message::uid& uid); - -private: - - void registerMessage(POP3Message* msg); - void unregisterMessage(POP3Message* msg); - - void onStoreDisconnected(); - - void onClose(); - - - weak_ptr m_store; - - folder::path m_path; - folder::path::component m_name; - - int m_mode; - bool m_open; - - int m_messageCount; - - typedef std::map 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/net/pop3/POP3FolderStatus.hpp b/vmime/net/pop3/POP3FolderStatus.hpp deleted file mode 100644 index 70ba48b6..00000000 --- a/vmime/net/pop3/POP3FolderStatus.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - unsigned int getMessageCount() const; - unsigned int getUnseenCount() const; - - shared_ptr clone() const; - - - void setMessageCount(const unsigned int count); - void setUnseenCount(const unsigned int unseen); - -private: - - unsigned int m_count; - unsigned int 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/net/pop3/POP3Message.hpp b/vmime/net/pop3/POP3Message.hpp deleted file mode 100644 index 87e71ba7..00000000 --- a/vmime/net/pop3/POP3Message.hpp +++ /dev/null @@ -1,121 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr folder, const int num); - - ~POP3Message(); - - - int getNumber() const; - - const uid getUID() const; - - size_t getSize() const; - - bool isExpunged() const; - - shared_ptr getStructure() const; - shared_ptr getStructure(); - - shared_ptr 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 - (shared_ptr 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(shared_ptr p); - - shared_ptr getParsedMessage(); - -private: - - void fetch(shared_ptr folder, const fetchAttributes& options); - - void onFolderClosed(); - - weak_ptr m_folder; - int m_num; - uid m_uid; - size_t m_size; - - bool m_deleted; - - shared_ptr
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/net/pop3/POP3Response.hpp b/vmime/net/pop3/POP3Response.hpp deleted file mode 100644 index 20477b5e..00000000 --- a/vmime/net/pop3/POP3Response.hpp +++ /dev/null @@ -1,182 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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" - - -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 readResponse(shared_ptr 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 readMultilineResponse(shared_ptr 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 readLargeResponse - (shared_ptr 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(shared_ptr sok, shared_ptr toh); - - void readResponseImpl(string& buffer, const bool multiLine); - void 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 m_socket; - shared_ptr m_timeoutHandler; - - string m_firstLine; - ResponseCode m_code; - string m_text; - - std::vector 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/net/pop3/POP3SStore.hpp b/vmime/net/pop3/POP3SStore.hpp deleted file mode 100644 index e60b4ef8..00000000 --- a/vmime/net/pop3/POP3SStore.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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/net/pop3/POP3ServiceInfos.hpp b/vmime/net/pop3/POP3ServiceInfos.hpp deleted file mode 100644 index 710d8be3..00000000 --- a/vmime/net/pop3/POP3ServiceInfos.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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/net/pop3/POP3Store.hpp b/vmime/net/pop3/POP3Store.hpp deleted file mode 100644 index b35659a0..00000000 --- a/vmime/net/pop3/POP3Store.hpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr auth, const bool secured = false); - ~POP3Store(); - - const string getProtocolName() const; - - shared_ptr getDefaultFolder(); - shared_ptr getRootFolder(); - shared_ptr 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 getConnectionInfos() const; - shared_ptr getConnection(); - - bool isPOP3S() const; - -private: - - shared_ptr m_connection; - - - void registerFolder(POP3Folder* folder); - void unregisterFolder(POP3Folder* folder); - - std::list 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/net/pop3/POP3Utils.hpp b/vmime/net/pop3/POP3Utils.hpp deleted file mode 100644 index c7459efe..00000000 --- a/vmime/net/pop3/POP3Utils.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#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 - (shared_ptr response, std::map & result); - - /** Returns a list of message numbers given a message set. - * - * @param msgs message set - * @return list of message numbers - */ - static const std::vector messageSetToNumberList(const messageSet& msgs); -}; - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 - -#endif // VMIME_NET_POP3_POP3UTILS_HPP_INCLUDED - diff --git a/vmime/net/pop3/pop3.hpp b/vmime/net/pop3/pop3.hpp deleted file mode 100644 index 366b1e4a..00000000 --- a/vmime/net/pop3/pop3.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/net/securedConnectionInfos.hpp b/vmime/net/securedConnectionInfos.hpp deleted file mode 100644 index 8ed8b138..00000000 --- a/vmime/net/securedConnectionInfos.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/net/sendmail/sendmail.hpp b/vmime/net/sendmail/sendmail.hpp deleted file mode 100644 index b3692526..00000000 --- a/vmime/net/sendmail/sendmail.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/net/sendmail/sendmailServiceInfos.hpp b/vmime/net/sendmail/sendmailServiceInfos.hpp deleted file mode 100644 index de94e392..00000000 --- a/vmime/net/sendmail/sendmailServiceInfos.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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/net/sendmail/sendmailTransport.hpp b/vmime/net/sendmail/sendmailTransport.hpp deleted file mode 100644 index d1c6aec0..00000000 --- a/vmime/net/sendmail/sendmailTransport.hpp +++ /dev/null @@ -1,103 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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()); - - bool isSecuredConnection() const; - shared_ptr getConnectionInfos() const; - -private: - - void internalDisconnect(); - - void internalSend(const std::vector 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/net/service.hpp b/vmime/net/service.hpp deleted file mode 100644 index 6969ac20..00000000 --- a/vmime/net/service.hpp +++ /dev/null @@ -1,233 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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" - -#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 -{ -protected: - - service(shared_ptr sess, const serviceInfos& infos, shared_ptr 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 getSession() const; - - /** Return the session object associated with this service instance. - * - * @return session object - */ - shared_ptr 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 getAuthenticator() const; - - /** Return the authenticator object used with this service instance. - * - * @return authenticator object - */ - shared_ptr getAuthenticator(); - - /** Set the authenticator object used with this service instance. - * - * @param auth authenticator object - */ - void setAuthenticator(shared_ptr auth); - -#if VMIME_HAVE_TLS_SUPPORT - - /** Set the object responsible for verifying certificates when - * using secured connections (TLS/SSL). - */ - void setCertificateVerifier(shared_ptr cv); - - /** Get the object responsible for verifying certificates when - * using secured connections (TLS/SSL). - */ - shared_ptr getCertificateVerifier(); - -#endif // VMIME_HAVE_TLS_SUPPORT - - /** Set the factory used to create socket objects for this - * service. - * - * @param sf socket factory - */ - void setSocketFactory(shared_ptr sf); - - /** Return the factory used to create socket objects for this - * service. - * - * @return socket factory - */ - shared_ptr getSocketFactory(); - - /** Set the factory used to create timeoutHandler objects for - * this service. By default, no timeout handler is used. Not all - * services support timeout handling. - * - * @param thf timeoutHandler factory - */ - void setTimeoutHandlerFactory(shared_ptr thf); - - /** Return the factory used to create timeoutHandler objects for - * this service. - * - * @return timeoutHandler factory - */ - shared_ptr getTimeoutHandlerFactory(); - - /** 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 - 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 getConnectionInfos() const = 0; - -private: - - shared_ptr m_session; - shared_ptr m_auth; - -#if VMIME_HAVE_TLS_SUPPORT - shared_ptr m_certVerifier; -#endif // VMIME_HAVE_TLS_SUPPORT - - shared_ptr m_socketFactory; - - shared_ptr m_toHandlerFactory; -}; - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_NET_SERVICE_HPP_INCLUDED diff --git a/vmime/net/serviceFactory.hpp b/vmime/net/serviceFactory.hpp deleted file mode 100644 index 9295b345..00000000 --- a/vmime/net/serviceFactory.hpp +++ /dev/null @@ -1,165 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#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 getInstance(); - - /** Information about a registered service. */ - class registeredService : public object - { - friend class serviceFactory; - - protected: - - virtual ~registeredService() { } - - public: - - virtual shared_ptr create - (shared_ptr sess, - shared_ptr 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(shared_ptr 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 create - (shared_ptr sess, - const string& protocol, - shared_ptr 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 create - (shared_ptr sess, - const utility::url& u, - shared_ptr 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 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 getServiceAt(const size_t pos) const; - - /** Return a list of all registered services. - * - * @return list of registered services - */ - const std::vector > getServiceList() const; - -private: - - std::vector > m_services; -}; - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_NET_SERVICEFACTORY_HPP_INCLUDED diff --git a/vmime/net/serviceInfos.hpp b/vmime/net/serviceInfos.hpp deleted file mode 100644 index 6e3209ca..00000000 --- a/vmime/net/serviceInfos.hpp +++ /dev/null @@ -1,246 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#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 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; - -#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 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 - const TYPE getPropertyValue(shared_ptr s, const property& p) const - { - if (p.getFlags() & property::FLAG_REQUIRED) - return s->getProperties()[getPropertyPrefix() + p.getName()].template getValue (); - - return s->getProperties().template getProperty (getPropertyPrefix() + p.getName(), - propertySet::valueFromString (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(shared_ptr s, const property& p) const; -}; - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_NET_SERVICEINFOS_HPP_INCLUDED diff --git a/vmime/net/session.hpp b/vmime/net/session.hpp deleted file mode 100644 index a7e0ea1a..00000000 --- a/vmime/net/session.hpp +++ /dev/null @@ -1,178 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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" - -#include "vmime/net/tls/TLSProperties.hpp" - -#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: - - session(); - session(const session& sess); - session(const propertySet& props); - - virtual ~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 getTransport - (shared_ptr 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 getTransport - (const string& protocol, - shared_ptr 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 getTransport - (const utility::url& url, - shared_ptr 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 getStore(shared_ptr 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 getStore - (const string& protocol, - shared_ptr 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 getStore - (const utility::url& url, - shared_ptr auth = null); - - /** Properties for the session and for the services. - */ - const propertySet& getProperties() const; - - /** Properties for the session and for the services. - */ - propertySet& getProperties(); - - /** Set properties for SSL/TLS secured connections in this session. - * - * @param tlsProps SSL/TLS properties - */ - void setTLSProperties(shared_ptr tlsProps); - - /** Get properties for SSL/TLS secured connections in this session. - * - * @return SSL/TLS properties - */ - shared_ptr getTLSProperties() const; - -private: - - propertySet m_props; - - shared_ptr m_tlsProps; -}; - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_NET_SESSION_HPP_INCLUDED diff --git a/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp b/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp deleted file mode 100644 index cfb3f50f..00000000 --- a/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp +++ /dev/null @@ -1,85 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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" - - -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(shared_ptr conn); - - 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 m_connection; - - byte_t m_buffer[262144]; // 256 KB - size_t m_bufferSize; - - unsigned int m_chunkCount; -}; - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP - -#endif // VMIME_NET_SMTP_SMTPCHUNKINGOUTPUTSTREAMADAPTER_HPP_INCLUDED diff --git a/vmime/net/smtp/SMTPCommand.hpp b/vmime/net/smtp/SMTPCommand.hpp deleted file mode 100644 index dbb0888b..00000000 --- a/vmime/net/smtp/SMTPCommand.hpp +++ /dev/null @@ -1,111 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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; - - -namespace smtp { - - -/** A SMTP command, as sent to server. - */ -class VMIME_EXPORT SMTPCommand : public object -{ -public: - - static shared_ptr HELO(const string& hostname); - static shared_ptr EHLO(const string& hostname); - static shared_ptr AUTH(const string& mechName); - static shared_ptr STARTTLS(); - static shared_ptr MAIL(const mailbox& mbox, const bool utf8); - static shared_ptr MAIL(const mailbox& mbox, const bool utf8, const size_t size); - static shared_ptr RCPT(const mailbox& mbox, const bool utf8); - static shared_ptr RSET(); - static shared_ptr DATA(); - static shared_ptr BDAT(const size_t chunkSize, const bool last); - static shared_ptr NOOP(); - static shared_ptr QUIT(); - - /** Creates a new SMTP command with the specified text. - * - * @param text command text - * @return a new SMTPCommand object - */ - static shared_ptr createCommand(const string& text); - - /** Sends this command to the specified socket. - * - * @param sok socket to which the command will be written - */ - virtual void writeToSocket(shared_ptr sok); - - /** Returns the full text of the command, including command name - * and parameters (if any). - * - * @return command text (eg. "RCPT TO:") - */ - virtual const string getText() const; - -protected: - - SMTPCommand(const string& text); - SMTPCommand(const SMTPCommand&); - -private: - - string m_text; -}; - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP - -#endif // VMIME_NET_SMTP_SMTPCOMMAND_HPP_INCLUDED diff --git a/vmime/net/smtp/SMTPCommandSet.hpp b/vmime/net/smtp/SMTPCommandSet.hpp deleted file mode 100644 index 8e744c2b..00000000 --- a/vmime/net/smtp/SMTPCommandSet.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#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 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(shared_ptr 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 getLastCommandSent() const; - - - void writeToSocket(shared_ptr sok); - - const string getText() const; - -private: - - SMTPCommandSet(const bool pipeline); - SMTPCommandSet(const SMTPCommandSet&); - - - bool m_pipeline; - bool m_started; - std::list > m_commands; - shared_ptr 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/net/smtp/SMTPConnection.hpp b/vmime/net/smtp/SMTPConnection.hpp deleted file mode 100644 index cc59ef34..00000000 --- a/vmime/net/smtp/SMTPConnection.hpp +++ /dev/null @@ -1,129 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/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(shared_ptr transport, shared_ptr auth); - virtual ~SMTPConnection(); - - - virtual void connect(); - virtual bool isConnected() const; - virtual void disconnect(); - - bool isSecuredConnection() const; - shared_ptr getConnectionInfos() const; - - virtual shared_ptr getTransport(); - virtual shared_ptr getSocket(); - virtual shared_ptr getTimeoutHandler(); - virtual shared_ptr getAuthenticator(); - virtual shared_ptr getSession(); - - void sendRequest(shared_ptr cmd); - shared_ptr readResponse(); - - bool hasExtension(const std::string& extName, std::vector * 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 m_transport; - - shared_ptr m_auth; - shared_ptr m_socket; - shared_ptr m_timeoutHandler; - - SMTPResponse::state m_responseState; - - bool m_authenticated; - bool m_secured; - - shared_ptr m_cntInfos; - - bool m_extendedSMTP; - std::map > 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/net/smtp/SMTPExceptions.hpp b/vmime/net/smtp/SMTPExceptions.hpp deleted file mode 100644 index 75842042..00000000 --- a/vmime/net/smtp/SMTPExceptions.hpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP - -#endif // VMIME_NET_SMTP_SMTPEXCEPTIONS_HPP_INCLUDED - diff --git a/vmime/net/smtp/SMTPResponse.hpp b/vmime/net/smtp/SMTPResponse.hpp deleted file mode 100644 index 000448ac..00000000 --- a/vmime/net/smtp/SMTPResponse.hpp +++ /dev/null @@ -1,186 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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; - - -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 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 readResponse(shared_ptr sok, shared_ptr 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(shared_ptr sok, shared_ptr 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 m_lines; - - shared_ptr m_socket; - shared_ptr m_timeoutHandler; - - 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/net/smtp/SMTPSTransport.hpp b/vmime/net/smtp/SMTPSTransport.hpp deleted file mode 100644 index 7782f711..00000000 --- a/vmime/net/smtp/SMTPSTransport.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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/net/smtp/SMTPServiceInfos.hpp b/vmime/net/smtp/SMTPServiceInfos.hpp deleted file mode 100644 index f783194d..00000000 --- a/vmime/net/smtp/SMTPServiceInfos.hpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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/net/smtp/SMTPTransport.hpp b/vmime/net/smtp/SMTPTransport.hpp deleted file mode 100644 index a0f02418..00000000 --- a/vmime/net/smtp/SMTPTransport.hpp +++ /dev/null @@ -1,131 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr 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()); - - void send - (shared_ptr msg, - const mailbox& expeditor, - const mailboxList& recipients, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()); - - bool isSecuredConnection() const; - shared_ptr getConnectionInfos() const; - shared_ptr getConnection(); - - bool isSMTPS() const; - -private: - - /** 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) - */ - void sendEnvelope - (const mailbox& expeditor, - const mailboxList& recipients, - const mailbox& sender, - bool sendDATACommand, - const size_t size); - - - shared_ptr 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/net/smtp/smtp.hpp b/vmime/net/smtp/smtp.hpp deleted file mode 100644 index 2a9ee312..00000000 --- a/vmime/net/smtp/smtp.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/net/socket.hpp b/vmime/net/socket.hpp deleted file mode 100644 index 537c34bb..00000000 --- a/vmime/net/socket.hpp +++ /dev/null @@ -1,184 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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" - - -namespace vmime { -namespace net { - - -/** Interface for connecting to servers. - */ - -class VMIME_EXPORT socket : public object -{ -public: - - enum Status - { - STATUS_WOULDBLOCK = 0x1 /**< The receive operation would block. */ - }; - - - 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; - - /** 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; - -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 create() = 0; - - /** Creates a socket with the specified timeout handler. - * - * @param th timeout handler - * @return a new socket - */ - virtual shared_ptr create(shared_ptr th) = 0; -}; - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_NET_SOCKET_HPP_INCLUDED diff --git a/vmime/net/store.hpp b/vmime/net/store.hpp deleted file mode 100644 index 37dcadbc..00000000 --- a/vmime/net/store.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, const serviceInfos& infos, shared_ptr auth) - : service(sess, infos, auth) { } - -public: - - /** Return the default folder. This is protocol dependent - * and usually is the INBOX folder. - * - * @return default folder - */ - virtual shared_ptr 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 getRootFolder() = 0; - - /** Return the folder specified by the path. - * - * @param path absolute folder path - * @return folder at the specified path - */ - virtual shared_ptr 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 { return (TYPE_STORE); } -}; - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_NET_STORE_HPP_INCLUDED diff --git a/vmime/net/timeoutHandler.hpp b/vmime/net/timeoutHandler.hpp deleted file mode 100644 index 24129701..00000000 --- a/vmime/net/timeoutHandler.hpp +++ /dev/null @@ -1,89 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 time-out in messaging services. - */ - -class VMIME_EXPORT timeoutHandler : public object -{ -public: - - virtual ~timeoutHandler() { } - - /** Called to test if the time limit has been reached. - * - * @return true if the time-out delay is elapsed - */ - virtual bool isTimeOut() = 0; - - /** Called to reset the time-out counter. - */ - virtual void resetTimeOut() = 0; - - /** Called when the time limit has been reached (when - * isTimeOut() returned true). - * - * @return true to continue (and reset the time-out) - * 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 create() = 0; -}; - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_NET_TIMEOUTHANDLER_HPP_INCLUDED diff --git a/vmime/net/tls/TLSProperties.hpp b/vmime/net/tls/TLSProperties.hpp deleted file mode 100644 index 0dbc8f05..00000000 --- a/vmime/net/tls/TLSProperties.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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/net/tls/TLSSecuredConnectionInfos.hpp b/vmime/net/tls/TLSSecuredConnectionInfos.hpp deleted file mode 100644 index e552d6f9..00000000 --- a/vmime/net/tls/TLSSecuredConnectionInfos.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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, - shared_ptr tlsSession, shared_ptr 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 getPeerCertificates() const; - -private: - - string m_host; - port_t m_port; - - shared_ptr m_tlsSession; - shared_ptr m_tlsSocket; -}; - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT - -#endif // VMIME_NET_TLSSECUREDCONNECTIONINFOS_HPP_INCLUDED - diff --git a/vmime/net/tls/TLSSession.hpp b/vmime/net/tls/TLSSession.hpp deleted file mode 100644 index 9e061f89..00000000 --- a/vmime/net/tls/TLSSession.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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: - - /** 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 create(shared_ptr cv, shared_ptr 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 getSocket(shared_ptr sok) = 0; - - /** Get the object responsible for verifying certificates when - * using secured connections (TLS/SSL). - */ - virtual shared_ptr 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/net/tls/TLSSocket.hpp b/vmime/net/tls/TLSSocket.hpp deleted file mode 100644 index e2668ad4..00000000 --- a/vmime/net/tls/TLSSocket.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 wrap(shared_ptr session, shared_ptr 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(shared_ptr toHandler = null) = 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 getPeerCertificates() const = 0; -}; - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT - -#endif // VMIME_NET_TLS_TLSSOCKET_HPP_INCLUDED diff --git a/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp b/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp deleted file mode 100644 index 2038778a..00000000 --- a/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/net/tls/gnutls/TLSSession_GnuTLS.hpp b/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp deleted file mode 100644 index 7f762b58..00000000 --- a/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr cv, shared_ptr props); - ~TLSSession_GnuTLS(); - - - shared_ptr getSocket(shared_ptr sok); - - shared_ptr getCertificateVerifier(); - -private: - - TLSSession_GnuTLS(const TLSSession_GnuTLS&); - - static void throwTLSException(const string& fname, const int code); - - -#ifdef LIBGNUTLS_VERSION - gnutls_session* m_gnutlsSession; -#else - void* m_gnutlsSession; -#endif // LIBGNUTLS_VERSION - - shared_ptr m_certVerifier; - shared_ptr 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/net/tls/gnutls/TLSSocket_GnuTLS.hpp b/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp deleted file mode 100644 index 885fac13..00000000 --- a/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr session, shared_ptr sok); - ~TLSSocket_GnuTLS(); - - - void handshake(shared_ptr toHandler = null); - - shared_ptr getPeerCertificates() const; - - // Implementation of 'socket' - void connect(const string& address, const port_t port); - void disconnect(); - bool isConnected() const; - - 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; - -private: - - void internalThrow(); - -#ifdef LIBGNUTLS_VERSION - static ssize_t gnutlsPushFunc(gnutls_transport_ptr trspt, const void* data, size_t len); - static ssize_t gnutlsPullFunc(gnutls_transport_ptr trspt, void* data, size_t len); -#else - static int gnutlsPushFunc(void* trspt, const void* data, size_t len); - static int gnutlsPullFunc(void* trspt, void* data, size_t len); -#endif // LIBGNUTLS_VERSION - - - shared_ptr m_session; - shared_ptr m_wrapped; - - bool m_connected; - - byte_t m_buffer[65536]; - - bool m_handshaking; - shared_ptr m_toHandler; - - exception* m_ex; - - unsigned int m_status; -}; - - -} // 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/net/tls/openssl/OpenSSLInitializer.hpp b/vmime/net/tls/openssl/OpenSSLInitializer.hpp deleted file mode 100644 index d7595aa8..00000000 --- a/vmime/net/tls/openssl/OpenSSLInitializer.hpp +++ /dev/null @@ -1,111 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -#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 - */ - class autoInitializer - { - public: - - autoInitializer(); - ~autoInitializer(); - }; - -protected: - - class oneTimeInitializer - { - public: - - oneTimeInitializer(); - ~oneTimeInitializer(); - }; - - - /** Initializes the OpenSSL lib - */ - static void initialize(); - - /** Shutdown the OpenSSL lib - */ - static void uninitialize(); - - - static shared_ptr getMutex(); - - enum - { - SEEDSIZE = 256 - }; - - - // OpenSSL multithreading support - static void lock(int mode, int n, const char* file, int line); - static unsigned long id(); - -private: - - static shared_ptr * sm_mutexes; -}; - - -} // 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/net/tls/openssl/TLSProperties_OpenSSL.hpp b/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp deleted file mode 100644 index 5d2f075a..00000000 --- a/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/net/tls/openssl/TLSSession_OpenSSL.hpp b/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp deleted file mode 100644 index 5a2b60a8..00000000 --- a/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace net { -namespace tls { - - -class TLSSession_OpenSSL : public TLSSession -{ - friend class TLSSocket_OpenSSL; - -public: - - TLSSession_OpenSSL(const shared_ptr cv, shared_ptr props); - ~TLSSession_OpenSSL(); - - - shared_ptr getSocket(shared_ptr sok); - - shared_ptr getCertificateVerifier(); - - - /** Set the private key to use if server requires a client certificate. - * - * @param keyfile Path to the private key in PEM format - * @param passwd_callback If the private key is stored encrypted the - */ - 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 m_certVerifier; - shared_ptr 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/net/tls/openssl/TLSSocket_OpenSSL.hpp b/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp deleted file mode 100644 index 410fffcf..00000000 --- a/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp +++ /dev/null @@ -1,132 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#include - - -namespace vmime { -namespace net { -namespace tls { - - -class TLSSession; -class TLSSession_OpenSSL; - - -class TLSSocket_OpenSSL : public TLSSocket -{ -public: - - TLSSocket_OpenSSL(shared_ptr session, shared_ptr sok); - ~TLSSocket_OpenSSL(); - - - void handshake(shared_ptr toHandler = null); - - shared_ptr getPeerCertificates() const; - - // Implementation of 'socket' - void connect(const string& address, const port_t port); - void disconnect(); - bool isConnected() const; - - 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; - -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 m_session; - - shared_ptr m_wrapped; - - bool m_connected; - - byte_t m_buffer[65536]; - - shared_ptr m_toHandler; - - SSL* m_ssl; - - unsigned long m_status; - - // Last exception thrown from C BIO functions - std::auto_ptr 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/net/transport.hpp b/vmime/net/transport.hpp deleted file mode 100644 index 6c405cbb..00000000 --- a/vmime/net/transport.hpp +++ /dev/null @@ -1,137 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/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(shared_ptr sess, const serviceInfos& infos, shared_ptr 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 - */ - virtual void send(shared_ptr msg, utility::progressListener* progress = NULL); - - /** 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) - */ - virtual void send - (const mailbox& expeditor, - const mailboxList& recipients, - utility::inputStream& is, - const size_t size, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()) = 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) - */ - virtual void send - (shared_ptr msg, - const mailbox& expeditor, - const mailboxList& recipients, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()); - - - 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 processHeaderField(shared_ptr 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(shared_ptr
header); -}; - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_NET_TRANSPORT_HPP_INCLUDED diff --git a/vmime/object.hpp b/vmime/object.hpp deleted file mode 100644 index 0b12df3c..00000000 --- a/vmime/object.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 : public enable_shared_from_this -{ -protected: - - object(); - object(const object&); - - object& operator=(const object&); - - virtual ~object(); -}; - - -} // vmime - - -#endif // VMIME_OBJECT_HPP_INCLUDED - diff --git a/vmime/parameter.hpp b/vmime/parameter.hpp deleted file mode 100644 index 682c391b..00000000 --- a/vmime/parameter.hpp +++ /dev/null @@ -1,153 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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: - - parameter(const string& name); - parameter(const string& name, const word& 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 clone() const; - void copyFrom(const component& other); - parameter& operator=(const parameter& other); - - const std::vector > 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: - * - *
-	  *    getParameter("creation-date")->getValueAs ()
-	  * 
- * - * is equivalent to: - * - *
-	  *    shared_ptr  rawValue = getParameter("creation-date");
-	  *
-	  *    vmime::dateTime theDate;
-	  *    theDate.parse(rawValue->getBuffer());
-	  * 
- * - * @param T type to which convert the value - * @return value - */ - template - 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 & chunks); - - - string m_name; - shared_ptr m_value; -}; - - -} // vmime - - -#endif // VMIME_PARAMETER_HPP_INCLUDED diff --git a/vmime/parameterizedHeaderField.hpp b/vmime/parameterizedHeaderField.hpp deleted file mode 100644 index 509506a9..00000000 --- a/vmime/parameterizedHeaderField.hpp +++ /dev/null @@ -1,208 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 : virtual 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 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 getParameter(const string& paramName); - - /** Add a parameter at the end of the list. - * - * @param param parameter to append - */ - void appendParameter(shared_ptr 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(shared_ptr beforeParam, shared_ptr 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, shared_ptr 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(shared_ptr afterParam, shared_ptr 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, shared_ptr 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(shared_ptr 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 getParameterAt(const size_t pos); - - /** Return the parameter at the specified position. - * - * @param pos position - * @return parameter at position 'pos' - */ - const shared_ptr getParameterAt(const size_t pos) const; - - /** Return the parameter list. - * - * @return list of parameters - */ - const std::vector > getParameterList() const; - - /** Return the parameter list. - * - * @return list of parameters - */ - const std::vector > getParameterList(); - - const std::vector > getChildComponents(); - -private: - - std::vector > 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/parsedMessageAttachment.hpp b/vmime/parsedMessageAttachment.hpp deleted file mode 100644 index 6c96f80a..00000000 --- a/vmime/parsedMessageAttachment.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr msg); - - const mediaType getType() const; - const text getDescription() const; - const word getName() const; - - const shared_ptr getData() const; - - const encoding getEncoding() const; - - shared_ptr getPart() const; - - shared_ptr getHeader() const; - - shared_ptr getMessage() const; - -protected: - - void generateIn(shared_ptr parent) const; - -private: - - shared_ptr m_msg; - mutable shared_ptr m_data; -}; - - -} // vmime - - -#endif // !VMIME_BUILDING_DOC - - -#endif // VMIME_PARSEDMESSAGEATTACHMENT_HPP_INCLUDED - diff --git a/vmime/parserHelpers.hpp b/vmime/parserHelpers.hpp deleted file mode 100644 index ce3f422a..00000000 --- a/vmime/parserHelpers.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - - -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 (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 (c); - return (x >= 0x20 && x <= 0x7E); - } -}; - - -} // vmime - - -#endif // VMIME_PARSERHELPERS_HPP_INCLUDED diff --git a/vmime/parsingContext.hpp b/vmime/parsingContext.hpp deleted file mode 100644 index 27d14a60..00000000 --- a/vmime/parsingContext.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -{ - - -/** 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(); - -protected: - -}; - - -} // vmime - - -#endif // VMIME_PARSINGCONTEXT_HPP_INCLUDED diff --git a/vmime/path.hpp b/vmime/path.hpp deleted file mode 100644 index 2ffa3c22..00000000 --- a/vmime/path.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - path& operator=(const path& other); - - const std::vector > 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/plainTextPart.hpp b/vmime/plainTextPart.hpp deleted file mode 100644 index 72a8a71c..00000000 --- a/vmime/plainTextPart.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 getText() const; - void setText(shared_ptr text); - - size_t getPartCount() const; - - void generateIn(shared_ptr message, shared_ptr parent) const; - void parse(shared_ptr message, shared_ptr parent, shared_ptr textPart); - -private: - - shared_ptr m_text; - charset m_charset; -}; - - -} // vmime - - -#endif // VMIME_PLAINTEXTPART_HPP_INCLUDED diff --git a/vmime/platform.hpp b/vmime/platform.hpp deleted file mode 100644 index c72f160e..00000000 --- a/vmime/platform.hpp +++ /dev/null @@ -1,170 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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; - - /** This function is called when VMime library is waiting for - * something (for example, it is called when there is no data - * available in a socket). On POSIX-compliant systems, a - * simple call to sched_yield() should suffice. - */ - virtual void wait() const = 0; - -#if VMIME_HAVE_MESSAGING_FEATURES - /** Return a pointer to the default socket factory for - * this platform. - * - * @return socket factory - */ - virtual shared_ptr 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 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 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 createCriticalSection() = 0; - }; - - - template - static void setHandler() - { - sm_handler = vmime::make_shared (); - } - - static shared_ptr getDefaultHandler(); - static shared_ptr getHandler(); - -private: - - static shared_ptr sm_handler; -}; - - -} // vmime - - -#endif // VMIME_PLATFORM_HPP_INCLUDED - diff --git a/vmime/platforms/posix/posixChildProcess.hpp b/vmime/platforms/posix/posixChildProcess.hpp deleted file mode 100644 index 5b9fa021..00000000 --- a/vmime/platforms/posix/posixChildProcess.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - - -namespace vmime { -namespace platforms { -namespace posix { - - -class posixChildProcess : public utility::childProcess -{ -public: - - posixChildProcess(const utility::file::path& path); - ~posixChildProcess(); - - void start(const std::vector args, const int flags = 0); - - shared_ptr getStdIn(); - shared_ptr getStdOut(); - - void waitForFinish(); - -private: - - utility::file::path m_processPath; - bool m_started; - - shared_ptr m_stdIn; - shared_ptr m_stdOut; - - sigset_t m_oldProcMask; - pid_t m_pid; - int m_pipe[2]; - - std::vector m_argVector; - const char** m_argArray; -}; - - -class posixChildProcessFactory : public utility::childProcessFactory -{ -public: - - shared_ptr 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/platforms/posix/posixCriticalSection.hpp b/vmime/platforms/posix/posixCriticalSection.hpp deleted file mode 100644 index 150799cd..00000000 --- a/vmime/platforms/posix/posixCriticalSection.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include - - -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/platforms/posix/posixFile.hpp b/vmime/platforms/posix/posixFile.hpp deleted file mode 100644 index 20a56699..00000000 --- a/vmime/platforms/posix/posixFile.hpp +++ /dev/null @@ -1,220 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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 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 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 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 getParent() const; - - void rename(const path& newName); - - void remove(); - - shared_ptr getFileWriter(); - shared_ptr getFileReader(); - - shared_ptr 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 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/platforms/posix/posixHandler.hpp b/vmime/platforms/posix/posixHandler.hpp deleted file mode 100644 index 0bba372b..00000000 --- a/vmime/platforms/posix/posixHandler.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 getSocketFactory(); -#endif - -#if VMIME_HAVE_FILESYSTEM_FEATURES - shared_ptr getFileSystemFactory(); - - shared_ptr getChildProcessFactory(); -#endif - - void wait() const; - - void generateRandomBytes(unsigned char* buffer, const unsigned int count); - - shared_ptr createCriticalSection(); - -private: - -#if VMIME_HAVE_MESSAGING_FEATURES - shared_ptr m_socketFactory; -#endif - -#if VMIME_HAVE_FILESYSTEM_FEATURES - shared_ptr m_fileSysFactory; - shared_ptr m_childProcFactory; -#endif -}; - - -} // posix -} // platforms -} // vmime - - -#endif // VMIME_PLATFORM_IS_POSIX - -#endif // VMIME_PLATFORMS_POSIX_HANDLER_HPP_INCLUDED diff --git a/vmime/platforms/posix/posixSocket.hpp b/vmime/platforms/posix/posixSocket.hpp deleted file mode 100644 index 4ec3edec..00000000 --- a/vmime/platforms/posix/posixSocket.hpp +++ /dev/null @@ -1,102 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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" - - -namespace vmime { -namespace platforms { -namespace posix { - - -class posixSocket : public vmime::net::socket -{ -public: - - posixSocket(shared_ptr th); - ~posixSocket(); - - void connect(const vmime::string& address, const vmime::port_t port); - bool isConnected() const; - void disconnect(); - - 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; - -protected: - - static void throwSocketError(const int err); - -private: - - shared_ptr m_timeoutHandler; - - byte_t m_buffer[65536]; - int m_desc; - - unsigned int m_status; - - string m_serverAddress; -}; - - - -class posixSocketFactory : public vmime::net::socketFactory -{ -public: - - shared_ptr create(); - shared_ptr create(shared_ptr th); -}; - - -} // posix -} // platforms -} // vmime - - -#endif // VMIME_PLATFORM_IS_POSIX && VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_PLATFORMS_POSIX_SOCKET_HPP_INCLUDED diff --git a/vmime/platforms/windows/windowsCriticalSection.hpp b/vmime/platforms/windows/windowsCriticalSection.hpp deleted file mode 100644 index 7ed07835..00000000 --- a/vmime/platforms/windows/windowsCriticalSection.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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/platforms/windows/windowsFile.hpp b/vmime/platforms/windows/windowsFile.hpp deleted file mode 100644 index 3543ee8a..00000000 --- a/vmime/platforms/windows/windowsFile.hpp +++ /dev/null @@ -1,221 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace platforms { -namespace windows { - - -class windowsFileSystemFactory : public vmime::utility::fileSystemFactory -{ -public: - - shared_ptr 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 getParent() const; - - void rename(const path& newName); - void remove(); - - shared_ptr getFileWriter(); - - shared_ptr getFileReader(); - - shared_ptr 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 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 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 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/platforms/windows/windowsHandler.hpp b/vmime/platforms/windows/windowsHandler.hpp deleted file mode 100644 index 4a3678eb..00000000 --- a/vmime/platforms/windows/windowsHandler.hpp +++ /dev/null @@ -1,103 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 getSocketFactory(); -#endif - -#if VMIME_HAVE_FILESYSTEM_FEATURES - shared_ptr getFileSystemFactory(); - - shared_ptr getChildProcessFactory(); -#endif - - void wait() const; - - void generateRandomBytes(unsigned char* buffer, const unsigned int count); - - shared_ptr createCriticalSection(); - -private: - -#if VMIME_HAVE_MESSAGING_FEATURES - shared_ptr m_socketFactory; -#endif - -#if VMIME_HAVE_FILESYSTEM_FEATURES - shared_ptr m_fileSysFactory; -#endif -}; - - -} // windows -} // platforms -} // vmime - - -#endif // VMIME_PLATFORM_IS_WINDOWS - -#endif // VMIME_PLATFORMS_WINDOWS_HANDLER_HPP_INCLUDED diff --git a/vmime/platforms/windows/windowsSocket.hpp b/vmime/platforms/windows/windowsSocket.hpp deleted file mode 100644 index e3f43b7c..00000000 --- a/vmime/platforms/windows/windowsSocket.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include "vmime/net/socket.hpp" - - -namespace vmime { -namespace platforms { -namespace windows { - - -class windowsSocket : public vmime::net::socket -{ -public: - - windowsSocket(); - windowsSocket(shared_ptr th); - ~windowsSocket(); - -public: - - void connect(const vmime::string& address, const vmime::port_t port); - bool isConnected() const; - void disconnect(); - - void receive(vmime::string& buffer); - size_t receiveRaw(char* buffer, const size_t count); - - void send(const vmime::string& buffer); - void sendRaw(const char* buffer, const size_t count); - size_t sendRawNonBlocking(const char* buffer, const size_t count); - - size_t getBlockSize() const; - - unsigned int getStatus() const; - - const string getPeerName() const; - const string getPeerAddress() const; - -protected: - - void throwSocketError(const int err); - - enum WaitOpType - { - READ = 1, - WRITE = 2, - BOTH = 4 - }; - - void waitForData(const WaitOpType t, bool& timedOut); - -private: - - shared_ptr m_timeoutHandler; - - char m_buffer[65536]; - SOCKET m_desc; - - unsigned int m_status; - - string m_serverAddress; -}; - - - -class windowsSocketFactory : public vmime::net::socketFactory -{ -public: - - shared_ptr create(); - shared_ptr create(shared_ptr th); -}; - - -} // windows -} // platforms -} // vmime - - -#endif // VMIME_PLATFORM_IS_WINDOWS && VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_PLATFORMS_WINDOWS_SOCKET_HPP_INCLUDED diff --git a/vmime/propertySet.hpp b/vmime/propertySet.hpp deleted file mode 100644 index bf1c39bf..00000000 --- a/vmime/propertySet.hpp +++ /dev/null @@ -1,460 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include -#include -#include - -#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 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 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 - propertyProxy& operator=(const TYPE& value) - { - m_set->setProperty(m_name, value); - return (*this); - } - - template - void setValue(const TYPE& value) - { - m_set->setProperty(m_name, value); - } - - template - const TYPE getValue() const - { - return (m_set->getProperty (m_name)); - } - - operator string() const - { - return (m_set->getProperty (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 - const TYPE getValue() const - { - return (m_set->getProperty (m_name)); - } - - operator string() const - { - return (m_set->getProperty (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 - const TYPE getProperty(const string& name) const - { - const shared_ptr prop = find(name); - if (!prop) throw exceptions::no_such_property(name); - - //return (prop->getValue ()); // BUG: with g++ < 3.4 - return (prop->template getValue ()); - } - - /** 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 - const TYPE getProperty(const string& name, const TYPE defaultValue) const - { - const shared_ptr prop = find(name); - //return (prop ? prop->getValue () : defaultValue); // BUG: with g++ < 3.4 - return (prop ? prop->template getValue () : 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 - 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 , bool> - { - public: - - propFinder(const string& name) : m_name(utility::stringUtils::toLower(name)) { } - - bool operator()(shared_ptr p) const - { - return (utility::stringUtils::toLower(p->getName()) == m_name); - } - - private: - - const string m_name; - }; - - shared_ptr find(const string& name) const; - shared_ptr findOrCreate(const string& name); - - typedef std::list > list_type; - list_type m_props; - -public: - - template - 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 - 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 > getPropertyList() const; - - /** Return the property list. - * - * @return list of properties - */ - const std::vector > getPropertyList(); -}; - - -#ifndef VMIME_INLINE_TEMPLATE_SPECIALIZATION - -template <> VMIME_EXPORT void propertySet::property::setValue (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/relay.hpp b/vmime/relay.hpp deleted file mode 100644 index 35949ff1..00000000 --- a/vmime/relay.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - void copyFrom(const component& other); - relay& operator=(const relay& other); - - const std::vector > 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 & getWithList() const; - std::vector & getWithList(); - -private: - - string m_from; - string m_via; - string m_by; - string m_id; - string m_for; - std::vector 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/security/authenticator.hpp b/vmime/security/authenticator.hpp deleted file mode 100644 index bef07b4a..00000000 --- a/vmime/security/authenticator.hpp +++ /dev/null @@ -1,128 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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(shared_ptr serv) = 0; -}; - - -} // security -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_SECURITY_AUTHENTICATOR_HPP_INCLUDED - diff --git a/vmime/security/cert/X509Certificate.hpp b/vmime/security/cert/X509Certificate.hpp deleted file mode 100644 index 215a86cf..00000000 --- a/vmime/security/cert/X509Certificate.hpp +++ /dev/null @@ -1,156 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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 import(const byte_t* data, const size_t length); - - /** 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; - - /** 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(shared_ptr 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(shared_ptr caCert) const = 0; - - /** Verify certificate's subject name against the given hostname. - * - * @param hostname DNS name of the server - * @return true if the match is successful, false otherwise - */ - virtual bool verifyHostName(const string& hostname) 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; -}; - - -} // cert -} // security -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT - -#endif // VMIME_SECURITY_CERT_X509CERTIFICATE_HPP_INCLUDED - diff --git a/vmime/security/cert/certificate.hpp b/vmime/security/cert/certificate.hpp deleted file mode 100644 index aef1f1f9..00000000 --- a/vmime/security/cert/certificate.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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: - - /** 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(shared_ptr 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/security/cert/certificateChain.hpp b/vmime/security/cert/certificateChain.hpp deleted file mode 100644 index 0ce6bda3..00000000 --- a/vmime/security/cert/certificateChain.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 >& certs); - - /** Return the number of certificates in the chain. - * - * @return number of certificates in the chain - */ - unsigned int 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 - */ - shared_ptr getAt(const unsigned int index); - -protected: - - std::vector > m_certs; -}; - - -} // cert -} // security -} // vmime - - -#endif // VMIME_SECURITY_CERT_CERTIFICATECHAIN_HPP_INCLUDED - diff --git a/vmime/security/cert/certificateVerifier.hpp b/vmime/security/cert/certificateVerifier.hpp deleted file mode 100644 index c72c84cb..00000000 --- a/vmime/security/cert/certificateVerifier.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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" - - -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 exceptions::certificate_verification_exception if one - * or more certificates can not be trusted, or the server identity - * cannot be verified - */ - virtual void verify(shared_ptr chain, const string& hostname) = 0; -}; - - -} // cert -} // security -} // vmime - - -#endif // VMIME_SECURITY_CERT_CERTIFICATEVERIFIER_HPP_INCLUDED - diff --git a/vmime/security/cert/defaultCertificateVerifier.hpp b/vmime/security/cert/defaultCertificateVerifier.hpp deleted file mode 100644 index fddcc4f5..00000000 --- a/vmime/security/cert/defaultCertificateVerifier.hpp +++ /dev/null @@ -1,89 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/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 >& trustedCerts); - - /** Sets the X.509 root CAs used for certificate verification. - * - * @param caCerts list of root CAs - */ - void setX509RootCAs(const std::vector >& caCerts); - - - // Implementation of 'certificateVerifier' - void verify(shared_ptr 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(shared_ptr chain, const string& hostname); - - - std::vector > m_x509RootCAs; - std::vector > m_x509TrustedCerts; -}; - - -} // cert -} // security -} // vmime - - -#endif // VMIME_SECURITY_CERT_DEFAULTCERTIFICATEVERIFIER_HPP_INCLUDED - diff --git a/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp b/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp deleted file mode 100644 index 76ee6d4d..00000000 --- a/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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; - - bool checkIssuer(shared_ptr issuer) const; - - bool verify(shared_ptr caCert) const; - - bool verifyHostName(const string& hostname) 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(shared_ptr 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/security/cert/openssl/X509Certificate_OpenSSL.hpp b/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp deleted file mode 100644 index bddb4b6c..00000000 --- a/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp +++ /dev/null @@ -1,115 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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; - - bool checkIssuer(shared_ptr issuer) const; - - bool verify(shared_ptr caCert) const; - - bool verifyHostName(const string& hostname) const; - - const datetime getExpirationDate() const; - const datetime getActivationDate() const; - - const byteArray getFingerprint(const DigestAlgorithm algo) const; - - - static shared_ptr importInternal(X509* cert); - - - // Implementation of 'certificate' - const byteArray getEncoded() const; - const string getType() const; - int getVersion() const; - bool equals(shared_ptr 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/security/defaultAuthenticator.hpp b/vmime/security/defaultAuthenticator.hpp deleted file mode 100644 index eead3d14..00000000 --- a/vmime/security/defaultAuthenticator.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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; - - void setService(shared_ptr serv); - weak_ptr getService() const; - -private: - - weak_ptr m_service; -}; - - -} // security -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -#endif // VMIME_SECURITY_DEFAULTAUTHENTICATOR_HPP_INCLUDED - diff --git a/vmime/security/digest/md5/md5MessageDigest.hpp b/vmime/security/digest/md5/md5MessageDigest.hpp deleted file mode 100644 index ef94f5c8..00000000 --- a/vmime/security/digest/md5/md5MessageDigest.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/security/digest/messageDigest.hpp b/vmime/security/digest/messageDigest.hpp deleted file mode 100644 index d17dfbc2..00000000 --- a/vmime/security/digest/messageDigest.hpp +++ /dev/null @@ -1,138 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/security/digest/messageDigestFactory.hpp b/vmime/security/digest/messageDigestFactory.hpp deleted file mode 100644 index 15fd8a28..00000000 --- a/vmime/security/digest/messageDigestFactory.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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: - - class digestAlgorithmFactory : public object - { - public: - - virtual shared_ptr create() const = 0; - }; - - template - class digestAlgorithmFactoryImpl : public digestAlgorithmFactory - { - public: - - shared_ptr create() const - { - return vmime::make_shared (); - } - }; - - - typedef std::map > MapType; - MapType m_algos; - -public: - - /** Register a new digest algorithm by its name. - * - * @param name algorithm name - */ - template - void registerAlgorithm(const string& name) - { - m_algos.insert(MapType::value_type(utility::stringUtils::toLower(name), - vmime::make_shared >())); - } - - /** 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 create(const string& name); - - /** Return a list of supported digest algorithms. - * - * @return list of supported digest algorithms - */ - const std::vector getSupportedAlgorithms() const; -}; - - -} // digest -} // security -} // vmime - - -#endif // VMIME_SECURITY_DIGEST_MESSAGEDIGESTFACTORY_HPP_INCLUDED - diff --git a/vmime/security/digest/sha1/sha1MessageDigest.hpp b/vmime/security/digest/sha1/sha1MessageDigest.hpp deleted file mode 100644 index 1eb09c2f..00000000 --- a/vmime/security/digest/sha1/sha1MessageDigest.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/security/sasl/SASLAuthenticator.hpp b/vmime/security/sasl/SASLAuthenticator.hpp deleted file mode 100644 index 9f1881f5..00000000 --- a/vmime/security/sasl/SASLAuthenticator.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 > getAcceptableMechanisms - (const std::vector >& available, - shared_ptr suggested) const = 0; - - /** Set the SASL session which is using this authenticator. - * - * @param sess SASL session - */ - virtual void setSASLSession(shared_ptr 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(shared_ptr 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/security/sasl/SASLContext.hpp b/vmime/security/sasl/SASLContext.hpp deleted file mode 100644 index 200f78db..00000000 --- a/vmime/security/sasl/SASLContext.hpp +++ /dev/null @@ -1,128 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -{ - friend class SASLSession; - friend class builtinSASLMechanism; - -public: - - ~SASLContext(); - - /** Construct and initialize a new SASL context. - */ - SASLContext(); - - /** 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 createSession - (const string& serviceName, - shared_ptr auth, shared_ptr 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 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 suggestMechanism - (const std::vector >& 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: - - 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/security/sasl/SASLMechanism.hpp b/vmime/security/sasl/SASLMechanism.hpp deleted file mode 100644 index 5492e48c..00000000 --- a/vmime/security/sasl/SASLMechanism.hpp +++ /dev/null @@ -1,131 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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. - * - * @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 occured during - * authentication (in this case, the values in 'response' and - * 'responseLen' are undetermined) - */ - virtual bool step - (shared_ptr 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; - - /** 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 occured during - * the encoding of data (in this case, the values in 'output' and - * 'outputLen' are undetermined) - */ - virtual void encode(shared_ptr 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 occured during - * the encoding of data (in this case, the values in 'output' and - * 'outputLen' are undetermined) - */ - virtual void decode(shared_ptr 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/security/sasl/SASLMechanismFactory.hpp b/vmime/security/sasl/SASLMechanismFactory.hpp deleted file mode 100644 index 3503f71b..00000000 --- a/vmime/security/sasl/SASLMechanismFactory.hpp +++ /dev/null @@ -1,143 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -namespace vmime { -namespace security { -namespace sasl { - - -class SASLContext; - - -/** Constructs SASL mechanism objects. - */ -class VMIME_EXPORT SASLMechanismFactory : public object -{ -private: - - SASLMechanismFactory(); - ~SASLMechanismFactory(); - - - class registeredMechanism : public object - { - public: - - virtual shared_ptr create - (shared_ptr ctx, const string& name) = 0; - }; - - template - class registeredMechanismImpl : public registeredMechanism - { - public: - - shared_ptr create(shared_ptr ctx, const string& name) - { - return vmime::make_shared (ctx, name); - } - }; - - typedef std::map > 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 - void registerMechanism(const string& name) - { - m_mechs.insert(MapType::value_type(name, - vmime::make_shared >())); - } - - /** 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 create(shared_ptr 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 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; - -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/security/sasl/SASLSession.hpp b/vmime/security/sasl/SASLSession.hpp deleted file mode 100644 index ccf181cb..00000000 --- a/vmime/security/sasl/SASLSession.hpp +++ /dev/null @@ -1,162 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/security/sasl/SASLAuthenticator.hpp" -#include "vmime/security/sasl/SASLMechanism.hpp" -#include "vmime/security/sasl/SASLSocket.hpp" - - -namespace vmime { -namespace security { -namespace sasl { - - -class SASLContext; - - -/** An SASL client session. - */ -class VMIME_EXPORT SASLSession : public object -{ - 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 - */ - SASLSession(const string& serviceName, shared_ptr ctx, - shared_ptr auth, shared_ptr 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 getAuthenticator(); - - /** Return the mechanism used for this session. - * - * @return SASL mechanism - */ - shared_ptr getMechanism(); - - /** Return the SASL context. - * - * @return SASL context - */ - shared_ptr 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. - * - * @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 occured 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 getSecuredSocket(shared_ptr 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: - - const string m_serviceName; - - shared_ptr m_context; - shared_ptr m_auth; - shared_ptr 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/security/sasl/SASLSocket.hpp b/vmime/security/sasl/SASLSocket.hpp deleted file mode 100644 index e52911b4..00000000 --- a/vmime/security/sasl/SASLSocket.hpp +++ /dev/null @@ -1,97 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr sess, shared_ptr wrapped); - ~SASLSocket(); - - void connect(const string& address, const port_t port); - void disconnect(); - - bool isConnected() const; - - 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; - -private: - - shared_ptr m_session; - shared_ptr 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/security/sasl/builtinSASLMechanism.hpp b/vmime/security/sasl/builtinSASLMechanism.hpp deleted file mode 100644 index 09b46f00..00000000 --- a/vmime/security/sasl/builtinSASLMechanism.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(shared_ptr ctx, const string& name); - ~builtinSASLMechanism(); - - - const string getName() const; - - bool step(shared_ptr sess, - const byte_t* challenge, const size_t challengeLen, - byte_t** response, size_t* responseLen); - - bool isComplete() const; - - void encode(shared_ptr sess, - const byte_t* input, const size_t inputLen, - byte_t** output, size_t* outputLen); - - void decode(shared_ptr sess, - const byte_t* input, const size_t inputLen, - byte_t** output, size_t* outputLen); - -private: - - /** SASL context */ - shared_ptr 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/security/sasl/defaultSASLAuthenticator.hpp b/vmime/security/sasl/defaultSASLAuthenticator.hpp deleted file mode 100644 index 6ea9af80..00000000 --- a/vmime/security/sasl/defaultSASLAuthenticator.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 > getAcceptableMechanisms - (const std::vector >& available, - shared_ptr suggested) const; - - const string getUsername() const; - const string getPassword() const; - const string getHostname() const; - const string getAnonymousToken() const; - const string getServiceName() const; - - void setService(shared_ptr serv); - weak_ptr getService() const; - - void setSASLSession(shared_ptr sess); - shared_ptr getSASLSession() const; - - void setSASLMechanism(shared_ptr mech); - shared_ptr getSASLMechanism() const; - -private: - - defaultAuthenticator m_default; - - weak_ptr m_service; - weak_ptr m_saslSession; - shared_ptr 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/streamContentHandler.hpp b/vmime/streamContentHandler.hpp deleted file mode 100644 index 9b72c073..00000000 --- a/vmime/streamContentHandler.hpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - (shared_ptr is, - const size_t length, - const vmime::encoding& enc = NO_ENCODING); - - ~streamContentHandler(); - - streamContentHandler(const streamContentHandler& cts); - streamContentHandler& operator=(const streamContentHandler& cts); - - shared_ptr 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 - (shared_ptr 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 m_stream; - size_t m_length; -}; - - -} // vmime - - -#endif // VMIME_STREAMCONTENTHANDLER_HPP_INCLUDED diff --git a/vmime/stringContentHandler.hpp b/vmime/stringContentHandler.hpp deleted file mode 100644 index e9d34405..00000000 --- a/vmime/stringContentHandler.hpp +++ /dev/null @@ -1,101 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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(const utility::stringProxy& str, const vmime::encoding& enc = NO_ENCODING); - stringContentHandler(const string& buffer, const size_t start, const size_t end, const vmime::encoding& enc = NO_ENCODING); - - ~stringContentHandler(); - - stringContentHandler(const stringContentHandler& cts); - stringContentHandler& operator=(const stringContentHandler& cts); - - shared_ptr clone() const; - - // Set the data contained in the body. - // - // The two first functions take advantage of the COW (copy-on-write) system that - // might be implemented into std::string. This is done using "stringProxy" object. - // - // Set "enc" parameter 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 utility::stringProxy& str, const vmime::encoding& enc = NO_ENCODING); - void setData(const string& buffer, const vmime::encoding& enc = NO_ENCODING); - void setData(const string& buffer, const size_t start, const size_t end, 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 - utility::stringProxy m_string; -}; - - -} // vmime - - -#endif // VMIME_STRINGCONTENTHANDLER_HPP_INCLUDED diff --git a/vmime/text.hpp b/vmime/text.hpp deleted file mode 100644 index b7e25669..00000000 --- a/vmime/text.hpp +++ /dev/null @@ -1,277 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 clone() const; - void copyFrom(const component& other); - text& operator=(const component& other); - text& operator=(const text& other); - - const std::vector > getChildComponents(); - - /** Add a word at the end of the list. - * - * @param w word to append - */ - void appendWord(shared_ptr 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, shared_ptr 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, shared_ptr 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 getWordAt(const size_t pos); - - /** Return the word at the specified position. - * - * @param pos position - * @return word at position 'pos' - */ - const shared_ptr getWordAt(const size_t pos) const; - - /** Return the word list. - * - * @return list of words - */ - const std::vector > getWordList() const; - - /** Return the word list. - * - * @return list of words - */ - const std::vector > 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. - * - *

Eg: giving:

- *
   <iso-8859-1> "Linux dans un t'el'ephone mobile"
-	  *    ("=?iso-8859-1?Q?Linux_dans_un_t=E9l=E9phone_mobile?=")
-	  * 

it will return:

- *
   <us-ascii>   "Linux dans un "
-	  *    <iso-8859-1> "t'el'ephone "
-	  *    <us-ascii>   "mobile"
-	  *    ("Linux dans un =?iso-8859-1?Q?t=E9l=E9phone_?= mobile")
-	  * 
- * - * @param in input string - * @param ch input charset - * @return new text object - */ - static shared_ptr 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. - * - *

Eg: giving:

- *
   <iso-8859-1> "Linux dans un t'el'ephone mobile"
-	  *    ("=?iso-8859-1?Q?Linux_dans_un_t=E9l=E9phone_mobile?=")
-	  * 

it will return:

- *
   <us-ascii>   "Linux dans un "
-	  *    <iso-8859-1> "t'el'ephone "
-	  *    <us-ascii>   "mobile"
-	  *    ("Linux dans un =?iso-8859-1?Q?t=E9l=E9phone_?= mobile")
-	  * 
- * - * @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 decodeAndUnfold(const string& in); - - /** Decode and unfold text (RFC-2047). - * - * @param ctx parsingContext - * @param in input string - * @return new text object - */ - static shared_ptr 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: - - // 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 > m_words; -}; - - -} // vmime - - -#endif // VMIME_TEXT_HPP_INCLUDED diff --git a/vmime/textPart.hpp b/vmime/textPart.hpp deleted file mode 100644 index 6348f8d7..00000000 --- a/vmime/textPart.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 getText() const = 0; - - /** Set the text contained in the part. - * - * @param text text of the part - */ - virtual void setText(shared_ptr 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(shared_ptr message, shared_ptr 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(shared_ptr message, shared_ptr parent, shared_ptr textPart) = 0; -}; - - -} // vmime - - -#endif // VMIME_TEXTPART_HPP_INCLUDED diff --git a/vmime/textPartFactory.hpp b/vmime/textPartFactory.hpp deleted file mode 100644 index f5ce3774..00000000 --- a/vmime/textPartFactory.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 (*AllocFunc)(void); - typedef std::vector > MapType; - - MapType m_map; - -#ifndef VMIME_BUILDING_DOC - template - class registerer - { - public: - - static shared_ptr creator() - { - // Allocate a new object - return vmime::make_shared (); - } - }; -#endif // VMIME_BUILDING_DOC - -public: - - static textPartFactory* getInstance(); - - template - void registerType(const mediaType& type) - { - m_map.push_back(MapType::value_type(type, ®isterer::creator)); - } - - shared_ptr create(const mediaType& type); -}; - - -} // vmime - - -#endif // VMIME_TEXTPARTFACTORY_HPP_INCLUDED diff --git a/vmime/types.hpp b/vmime/types.hpp deleted file mode 100644 index 12e5bf71..00000000 --- a/vmime/types.hpp +++ /dev/null @@ -1,115 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 -#include -#include -#include -#include -#include - -#include "vmime/config.hpp" - - -#ifndef VMIME_BUILDING_DOC - -#if VMIME_SHARED_PTR_USE_CXX - // If we are compiling with C++11, use shared_ptr<> from the standard lib - #include - - #define VMIME_SHARED_PTR_NAMESPACE std -#elif VMIME_SHARED_PTR_USE_BOOST - // Else, use boost's shared_ptr<> - #include - #include - #include - #include - #include - - #define VMIME_SHARED_PTR_NAMESPACE boost -#else - #error Either VMIME_SHAREDPTR_USE_CXX or VMIME_SHAREDPTR_USE_BOOST must be set to ON -#endif - -namespace vmime -{ - using VMIME_SHARED_PTR_NAMESPACE::shared_ptr; - using VMIME_SHARED_PTR_NAMESPACE::weak_ptr; - using VMIME_SHARED_PTR_NAMESPACE::make_shared; - using VMIME_SHARED_PTR_NAMESPACE::enable_shared_from_this; - using VMIME_SHARED_PTR_NAMESPACE::dynamic_pointer_cast; - using VMIME_SHARED_PTR_NAMESPACE::const_pointer_cast; - - /** Custom deleter to be used with shared_ptr. - * This is does not actually delete the pointer, and is used - * only for the singleton classes allocated on the stack. - */ - template - struct noop_shared_ptr_deleter - { - void operator()(T*) const {} - }; -} - -#undef VMIME_SHARED_PTR_NAMESPACE - -#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 byteArray; - - typedef std::size_t size_t; - - // For compatibility with versions <= 0.7.1 (deprecated) - namespace net { } - namespace messaging = net; - - // For (minimal) compatibility with legacy smart pointers (<= 0.9.1) - // Your compiler must have support for C++11 -#if VMIME_COMPAT_LEGACY_SMART_POINTERS - template using ref = shared_ptr ; - class creator {}; // unused - template - inline shared_ptr create(Args&&... args) { return make_shared (args...); } -#endif - -} - - -#include "vmime/object.hpp" - - -#endif // VMIME_TYPES_HPP_INCLUDED diff --git a/vmime/utility/childProcess.hpp b/vmime/utility/childProcess.hpp deleted file mode 100644 index ebefcf0a..00000000 --- a/vmime/utility/childProcess.hpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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 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 getStdIn() = 0; - - /** Return a wrapper to the child process standard output. - * - * @return input stream wrapper for child's stdout - */ - virtual shared_ptr 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 create(const utility::file::path& path) const = 0; -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_CHILDPROCESS_HPP_INCLUDED - diff --git a/vmime/utility/datetimeUtils.hpp b/vmime/utility/datetimeUtils.hpp deleted file mode 100644 index a7291bb8..00000000 --- a/vmime/utility/datetimeUtils.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/utility/encoder/b64Encoder.hpp b/vmime/utility/encoder/b64Encoder.hpp deleted file mode 100644 index 2d23d9e3..00000000 --- a/vmime/utility/encoder/b64Encoder.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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/utility/encoder/binaryEncoder.hpp b/vmime/utility/encoder/binaryEncoder.hpp deleted file mode 100644 index 1c831939..00000000 --- a/vmime/utility/encoder/binaryEncoder.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/utility/encoder/eightBitEncoder.hpp b/vmime/utility/encoder/eightBitEncoder.hpp deleted file mode 100644 index ee50ca95..00000000 --- a/vmime/utility/encoder/eightBitEncoder.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/utility/encoder/encoder.hpp b/vmime/utility/encoder/encoder.hpp deleted file mode 100644 index 34cd10b7..00000000 --- a/vmime/utility/encoder/encoder.hpp +++ /dev/null @@ -1,128 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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/utility/encoder/encoderFactory.hpp b/vmime/utility/encoder/encoderFactory.hpp deleted file mode 100644 index 763cbd5c..00000000 --- a/vmime/utility/encoder/encoderFactory.hpp +++ /dev/null @@ -1,148 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 getInstance(); - - /** Information about a registered encoder. */ - class VMIME_EXPORT registeredEncoder : public object - { - protected: - - virtual ~registeredEncoder() { } - - public: - - virtual shared_ptr create() const = 0; - - virtual const string& getName() const = 0; - }; - -private: - - template - class registeredEncoderImpl : public registeredEncoder - { - public: - - registeredEncoderImpl(const string& name) : m_name(name) { } - - shared_ptr create() const - { - return vmime::make_shared (); - } - - const string& getName() const - { - return (m_name); - } - - private: - - const string m_name; - }; - - - std::vector > m_encoders; - -public: - - /** Register a new encoder by its encoding name. - * - * @param name encoding name - */ - template - void registerName(const string& name) - { - m_encoders.push_back(vmime::make_shared >(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 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 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 getEncoderAt(const size_t pos) const; - - /** Return a list of all registered encoders. - * - * @return list of registered encoders - */ - const std::vector > getEncoderList() const; -}; - - -} // encoder -} // utility -} // vmime - - -#endif // VMIME_UTILITY_ENCODER_ENCODERFACTORY_HPP_INCLUDED diff --git a/vmime/utility/encoder/noopEncoder.hpp b/vmime/utility/encoder/noopEncoder.hpp deleted file mode 100644 index 6314812b..00000000 --- a/vmime/utility/encoder/noopEncoder.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/utility/encoder/qpEncoder.hpp b/vmime/utility/encoder/qpEncoder.hpp deleted file mode 100644 index c666795b..00000000 --- a/vmime/utility/encoder/qpEncoder.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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/utility/encoder/sevenBitEncoder.hpp b/vmime/utility/encoder/sevenBitEncoder.hpp deleted file mode 100644 index d260cc7b..00000000 --- a/vmime/utility/encoder/sevenBitEncoder.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/utility/encoder/uuEncoder.hpp b/vmime/utility/encoder/uuEncoder.hpp deleted file mode 100644 index 7365263c..00000000 --- a/vmime/utility/encoder/uuEncoder.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 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/utility/file.hpp b/vmime/utility/file.hpp deleted file mode 100644 index c0ba2c5b..00000000 --- a/vmime/utility/file.hpp +++ /dev/null @@ -1,269 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 nextElement() = 0; -}; - - -/** Write to a file. - */ - -class VMIME_EXPORT fileWriter : public object -{ -public: - - virtual ~fileWriter() { } - - virtual shared_ptr getOutputStream() = 0; -}; - - -/** Read from a file. - */ - -class VMIME_EXPORT fileReader : public object -{ -public: - - virtual ~fileReader() { } - - virtual shared_ptr 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 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 getFileWriter() = 0; - - /** Return an object capable of reading from this file. - * - * @return file reader object - */ - virtual shared_ptr 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 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 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/utility/filteredStream.hpp b/vmime/utility/filteredStream.hpp deleted file mode 100644 index c60373b9..00000000 --- a/vmime/utility/filteredStream.hpp +++ /dev/null @@ -1,406 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - -#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(); - -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(); - -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(); - -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 -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 (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); - - 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); - - -template -size_t stopSequenceFilteredInputStream ::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; -} - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_FILTEREDSTREAM_HPP_INCLUDED - diff --git a/vmime/utility/inputStream.hpp b/vmime/utility/inputStream.hpp deleted file mode 100644 index 809996ce..00000000 --- a/vmime/utility/inputStream.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/utility/inputStreamAdapter.hpp b/vmime/utility/inputStreamAdapter.hpp deleted file mode 100644 index dd761736..00000000 --- a/vmime/utility/inputStreamAdapter.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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/utility/inputStreamByteBufferAdapter.hpp b/vmime/utility/inputStreamByteBufferAdapter.hpp deleted file mode 100644 index f201f433..00000000 --- a/vmime/utility/inputStreamByteBufferAdapter.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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/utility/inputStreamPointerAdapter.hpp b/vmime/utility/inputStreamPointerAdapter.hpp deleted file mode 100644 index 4fc606a9..00000000 --- a/vmime/utility/inputStreamPointerAdapter.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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 - - -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/utility/inputStreamSocketAdapter.hpp b/vmime/utility/inputStreamSocketAdapter.hpp deleted file mode 100644 index a990f628..00000000 --- a/vmime/utility/inputStreamSocketAdapter.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_INPUTSTREAMSOCKETADAPTER_HPP_INCLUDED -#define VMIME_UTILITY_INPUTSTREAMSOCKETADAPTER_HPP_INCLUDED - - -#include "vmime/utility/inputStream.hpp" - - -#if VMIME_HAVE_MESSAGING_FEATURES - - -namespace vmime { -namespace net { - class socket; // forward reference -} // net -} // vmime - - -namespace vmime { -namespace utility { - - -/** An input stream that is connected to a socket. - */ - -class VMIME_EXPORT inputStreamSocketAdapter : public inputStream -{ -public: - - inputStreamSocketAdapter(net::socket& sok); - - 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 getBlockSize(); - -private: - - inputStreamSocketAdapter(const inputStreamSocketAdapter&); - - net::socket& m_socket; -}; - - -} // utility -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - - -#endif // VMIME_UTILITY_INPUTSTREAMSOCKETADAPTER_HPP_INCLUDED - diff --git a/vmime/utility/inputStreamStringAdapter.hpp b/vmime/utility/inputStreamStringAdapter.hpp deleted file mode 100644 index 4ee597e6..00000000 --- a/vmime/utility/inputStreamStringAdapter.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_INPUTSTREAMSTRINGADAPTER_HPP_INCLUDED -#define VMIME_UTILITY_INPUTSTREAMSTRINGADAPTER_HPP_INCLUDED - - -#include "vmime/utility/seekableInputStream.hpp" - - -namespace vmime { -namespace utility { - - -/** An adapter class for string input. - */ - -class VMIME_EXPORT inputStreamStringAdapter : public seekableInputStream -{ -public: - - inputStreamStringAdapter(const string& buffer); - inputStreamStringAdapter(const string& buffer, const size_t begin, const size_t end); - - 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: - - inputStreamStringAdapter(const inputStreamStringAdapter&); - - const string m_buffer; // do _NOT_ keep a reference... - const size_t m_begin; - const size_t m_end; - size_t m_pos; -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_INPUTSTREAMSTRINGADAPTER_HPP_INCLUDED - diff --git a/vmime/utility/inputStreamStringProxyAdapter.hpp b/vmime/utility/inputStreamStringProxyAdapter.hpp deleted file mode 100644 index 02dc2056..00000000 --- a/vmime/utility/inputStreamStringProxyAdapter.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_INPUTSTREAMSTRINGPROXYADAPTER_HPP_INCLUDED -#define VMIME_UTILITY_INPUTSTREAMSTRINGPROXYADAPTER_HPP_INCLUDED - - -#include "vmime/utility/seekableInputStream.hpp" - - -namespace vmime { -namespace utility { - - -class stringProxy; - - -/** An adapter class for stringProxy input. - */ - -class VMIME_EXPORT inputStreamStringProxyAdapter : public seekableInputStream -{ -public: - - /** @param buffer stringProxy object to wrap - */ - inputStreamStringProxyAdapter(const stringProxy& buffer); - - 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: - - inputStreamStringProxyAdapter(const inputStreamStringProxyAdapter&); - - const stringProxy& m_buffer; - size_t m_pos; -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_INPUTSTREAMSTRINGPROXYADAPTER_HPP_INCLUDED - diff --git a/vmime/utility/outputStream.hpp b/vmime/utility/outputStream.hpp deleted file mode 100644 index 62ee7336..00000000 --- a/vmime/utility/outputStream.hpp +++ /dev/null @@ -1,136 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_OUTPUTSTREAM_HPP_INCLUDED -#define VMIME_UTILITY_OUTPUTSTREAM_HPP_INCLUDED - - -#include "vmime/utility/stream.hpp" - - -#if defined(_MSC_VER) && (_MSC_VER <= 1200) // VC++6 -# include -#endif - - -namespace vmime { -namespace utility { - - -/** Simple output stream. - */ - -class VMIME_EXPORT outputStream : public stream -{ -public: - - /** Write data to the stream. - * - * @param data buffer containing data to write - * @param count number of bytes to write - */ - void write(const byte_t* const data, const size_t count); - - /** Write data to the stream. - * - * @param data buffer containing data to write - * @param count number of bytes to write - */ - void write(const char* const data, const size_t count); - - /** Write data to the stream. - * - * @param data buffer containing data to write - * @param N number of bytes to write, including terminating - * null (value is induced by compiler) - */ - template - void write(const char (&data)[N]) - { - write(data, N - 1); - } - - /** Flush this output stream and forces any buffered output - * bytes to be written out to the stream. - */ - virtual void flush() = 0; - -protected: - - /** Write data to the stream. - * This is the method to be implemented is subclasses. - * - * @param data buffer containing data to write - * @param count number of bytes to write - */ - virtual void writeImpl(const byte_t* const data, const size_t count) = 0; -}; - - -// Helpers functions - -VMIME_EXPORT outputStream& operator<<(outputStream& os, const string& str); -VMIME_EXPORT outputStream& operator<<(outputStream& os, const byte_t c); - - -#if defined(_MSC_VER) && (_MSC_VER <= 1200) // Internal compiler error with VC++6 - -inline outputStream& operator<<(outputStream& os, const char* str) -{ - os.write(reinterpret_cast (str), ::strlen(str)); - return (os); -} - -#else - -template -outputStream& operator<<(outputStream& os, const char (&str)[N]) -{ - os.write(reinterpret_cast (str), N - 1); - return (os); -} - -#endif // defined(_MSC_VER) && (_MSC_VER <= 1200) - - -template -outputStream& operator<<(outputStream& os, const T& t) -{ - std::ostringstream oss; - oss.imbue(std::locale::classic()); // no formatting - - oss << t; - - os << oss.str(); - - return (os); -} - - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_OUTPUTSTREAM_HPP_INCLUDED - diff --git a/vmime/utility/outputStreamAdapter.hpp b/vmime/utility/outputStreamAdapter.hpp deleted file mode 100644 index f0125584..00000000 --- a/vmime/utility/outputStreamAdapter.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_OUTPUTSTREAMADAPTER_HPP_INCLUDED -#define VMIME_UTILITY_OUTPUTSTREAMADAPTER_HPP_INCLUDED - - -#include "vmime/utility/outputStream.hpp" - -#include - - -namespace vmime { -namespace utility { - - -/** An adapter class for C++ standard output streams. - */ - -class VMIME_EXPORT outputStreamAdapter : public outputStream -{ -public: - - /** @param os output stream to wrap - */ - outputStreamAdapter(std::ostream& os); - - void flush(); - -protected: - - void writeImpl(const byte_t* const data, const size_t count); - -private: - - std::ostream& m_stream; -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_OUTPUTSTREAMADAPTER_HPP_INCLUDED - diff --git a/vmime/utility/outputStreamByteArrayAdapter.hpp b/vmime/utility/outputStreamByteArrayAdapter.hpp deleted file mode 100644 index a2178a9c..00000000 --- a/vmime/utility/outputStreamByteArrayAdapter.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_OUTPUTSTREAMBYTEARRAYADAPTER_HPP_INCLUDED -#define VMIME_UTILITY_OUTPUTSTREAMBYTEARRAYADAPTER_HPP_INCLUDED - - -#include "vmime/utility/outputStream.hpp" - - -namespace vmime { -namespace utility { - - -/** An adapter class for byte array output. - */ - -class VMIME_EXPORT outputStreamByteArrayAdapter : public outputStream -{ -public: - - outputStreamByteArrayAdapter(byteArray& array); - - void flush(); - -protected: - - void writeImpl(const byte_t* const data, const size_t count); - -private: - - byteArray& m_array; -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_OUTPUTSTREAMBYTEARRAYADAPTER_HPP_INCLUDED - diff --git a/vmime/utility/outputStreamSocketAdapter.hpp b/vmime/utility/outputStreamSocketAdapter.hpp deleted file mode 100644 index 6cd00626..00000000 --- a/vmime/utility/outputStreamSocketAdapter.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_OUTPUTSTREAMSOCKETADAPTER_HPP_INCLUDED -#define VMIME_UTILITY_OUTPUTSTREAMSOCKETADAPTER_HPP_INCLUDED - - -#include "vmime/utility/outputStream.hpp" - - -#if VMIME_HAVE_MESSAGING_FEATURES - - -namespace vmime { -namespace net { - class socket; // forward reference -} // net -} // vmime - - -namespace vmime { -namespace utility { - - -/** An output stream that is connected to a socket. - */ - -class VMIME_EXPORT outputStreamSocketAdapter : public outputStream -{ -public: - - outputStreamSocketAdapter(net::socket& sok); - - void flush(); - - size_t getBlockSize(); - -protected: - - void writeImpl(const byte_t* const data, const size_t count); - -private: - - outputStreamSocketAdapter(const outputStreamSocketAdapter&); - - net::socket& m_socket; -}; - - -} // utility -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - - -#endif // VMIME_UTILITY_OUTPUTSTREAMSOCKETADAPTER_HPP_INCLUDED - diff --git a/vmime/utility/outputStreamStringAdapter.hpp b/vmime/utility/outputStreamStringAdapter.hpp deleted file mode 100644 index 89516827..00000000 --- a/vmime/utility/outputStreamStringAdapter.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_OUTPUTSTREAMSTRINGADAPTER_HPP_INCLUDED -#define VMIME_UTILITY_OUTPUTSTREAMSTRINGADAPTER_HPP_INCLUDED - - -#include "vmime/utility/outputStream.hpp" - - -namespace vmime { -namespace utility { - - -/** An adapter class for string output. - */ - -class VMIME_EXPORT outputStreamStringAdapter : public outputStream -{ -public: - - outputStreamStringAdapter(string& buffer); - - void flush(); - -protected: - - void writeImpl(const byte_t* const data, const size_t count); - -private: - - string& m_buffer; -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_OUTPUTSTREAMSTRINGADAPTER_HPP_INCLUDED - diff --git a/vmime/utility/parserInputStreamAdapter.hpp b/vmime/utility/parserInputStreamAdapter.hpp deleted file mode 100644 index 9b0639b1..00000000 --- a/vmime/utility/parserInputStreamAdapter.hpp +++ /dev/null @@ -1,174 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_PARSERINPUTSTREAMADAPTER_HPP_INCLUDED -#define VMIME_UTILITY_PARSERINPUTSTREAMADAPTER_HPP_INCLUDED - - -#include "vmime/utility/seekableInputStream.hpp" - -#include - - -namespace vmime { -namespace utility { - - -/** An adapter class used for parsing from an input stream. - */ - -class VMIME_EXPORT parserInputStreamAdapter : public seekableInputStream -{ -public: - - /** @param stream input stream to wrap - */ - parserInputStreamAdapter(shared_ptr stream); - - shared_ptr getUnderlyingStream(); - - bool eof() const; - void reset(); - size_t read(byte_t* const data, const size_t count); - - void seek(const size_t pos) - { - m_stream->seek(pos); - } - - size_t skip(const size_t count) - { - return m_stream->skip(count); - } - - size_t getPosition() const - { - return m_stream->getPosition(); - } - - /** Get the byte at the current position without updating the - * current position. - * - * @return byte at the current position - */ - byte_t peekByte() const - { - const size_t initialPos = m_stream->getPosition(); - - try - { - byte_t buffer[1]; - const size_t readBytes = m_stream->read(buffer, 1); - - m_stream->seek(initialPos); - - return (readBytes == 1 ? buffer[0] : static_cast (0)); - } - catch (...) - { - m_stream->seek(initialPos); - throw; - } - } - - /** Get the byte at the current position and advance current - * position by one byte. - * - * @return byte at the current position - */ - byte_t getByte() - { - byte_t buffer[1]; - const size_t readBytes = m_stream->read(buffer, 1); - - return (readBytes == 1 ? buffer[0] : static_cast (0)); - } - - /** Check whether the bytes following the current position match - * the specified bytes. Position is not updated. - * - * @param bytes bytes to compare - * @param length number of bytes - * @return true if the next bytes match the pattern, false otherwise - */ - template - bool matchBytes(const T* bytes, const size_t length) const - { - const size_t initialPos = m_stream->getPosition(); - - try - { - byte_t buffer[32]; - const size_t readBytes = m_stream->read(buffer, length); - - m_stream->seek(initialPos); - - return readBytes == length && - ::memcmp(bytes, buffer, length) == 0; - } - catch (...) - { - m_stream->seek(initialPos); - throw; - } - } - - const string extract(const size_t begin, const size_t end) const; - - /** Skips bytes matching a predicate from the current position. - * The current position is updated to the next following byte - * which does not match the predicate. - * - * @param pred predicate - * @param endPosition stop at this position (or at end of the stream, - * whichever comes first) - * @return number of bytes skipped - */ - template - size_t skipIf(PREDICATE pred, const size_t endPosition) - { - const size_t initialPos = getPosition(); - size_t pos = initialPos; - - while (!m_stream->eof() && pos < endPosition && pred(getByte())) - ++pos; - - m_stream->seek(pos); - - return pos - initialPos; - } - - size_t findNext(const string& token, const size_t startPosition = 0); - -private: - - mutable shared_ptr m_stream; -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_PARSERINPUTSTREAMADAPTER_HPP_INCLUDED - diff --git a/vmime/utility/path.hpp b/vmime/utility/path.hpp deleted file mode 100644 index 203da246..00000000 --- a/vmime/utility/path.hpp +++ /dev/null @@ -1,171 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_PATH_HPP_INCLUDED -#define VMIME_UTILITY_PATH_HPP_INCLUDED - - -#include - -#include "vmime/types.hpp" -#include "vmime/word.hpp" - - -namespace vmime { -namespace utility { - - -/** Abstract representation of a path (filesystem, mailbox, etc). - */ - -class VMIME_EXPORT path : public object -{ -public: - - typedef vmime::word component; - typedef std::vector list; - - // Construct a path - path(); - path(const component& c); - path(const path& p); - explicit path(const string& s); - - // Append a component to a path - path operator/(const path& p) const; - path operator/(const component& c) const; - - path& operator/=(const path& p); - path& operator/=(const component& c); - - // Return the parent path - path getParent() const; - - // Assignment - path& operator=(const path& p); - path& operator=(const component& c); - - // Path comparison - bool operator==(const path& p) const; - bool operator!=(const path& p) const; - - /** Append a component to the path. - * - * @param c component to add - */ - void appendComponent(const component& c); - - /** Return the component at the specified position. - * - * @param pos position - * @return component at position 'pos' - */ - const component& getComponentAt(const size_t pos) const; - - /** Return the component at the specified position. - * - * @param pos position - * @return component at position 'pos' - */ - component& getComponentAt(const size_t pos); - - /** Test whether this path is empty (root). - * - * @return true if the path is empty (no components = root) - */ - bool isEmpty() const; - - /** Test whether this path is the root (alias for isEmpty()). - * - * @return true if the path is the root - */ - bool isRoot() const; - - /** Return the last component of this path (const version). - * - * @return last component - */ - const component getLastComponent() const; - - /** Return the last component of this path (non-const version). - * - * @return last component - */ - component& getLastComponent(); - - /** Return the number of components in this path. - * - * @return number of components - */ - size_t getSize() const; - - /** Return the specified component of the path (const version). - * - * @param x index of the component - * @return component at the specified index - */ - const component& operator[](const size_t x) const; - - /** Return the specified component of the path (non-const version). - * - * @param x index of the component - * @return component at the specified index - */ - component& operator[](const size_t x); - - /** Test whether this path is a direct parent of another one. - * - * @param p other path - * @return true if the specified path is a child - * of this path, false otherwise - */ - bool isDirectParentOf(const path& p) const; - - /** Test whether this path is a parent of another one. - * - * @param p other path - * @return true if the specified path is a child (direct or - * indirect) of this path, false otherwise - */ - bool isParentOf(const path& p) const; - - /** Rename a parent component in the path. - * Example: path("a/b/c/d").renameParent("a/b", "x/y/z") - * will return path("x/y/z/c/d"). - * - * @param oldPath old parent path - * @param newPath new parent path - */ - void renameParent(const path& oldPath, const path& newPath); - -private: - - list m_list; -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_PATH_HPP_INCLUDED diff --git a/vmime/utility/progressListener.hpp b/vmime/utility/progressListener.hpp deleted file mode 100644 index 4d0e9bf8..00000000 --- a/vmime/utility/progressListener.hpp +++ /dev/null @@ -1,113 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_PROGRESSLISTENER_HPP_INCLUDED -#define VMIME_UTILITY_PROGRESSLISTENER_HPP_INCLUDED - - -#include "vmime/config.hpp" -#include "vmime/types.hpp" - - -namespace vmime { -namespace utility { - - -/** An interface to implement if you want to be notified - * of a state of progress by some objects. - */ - -class VMIME_EXPORT progressListener -{ -protected: - - virtual ~progressListener() { } - -public: - - /** Allow the caller object to cancel the current operation. - * - * @warning WARNING: this is implementation-dependent: cancelling - * may not be supported by the notifier object. - * - * @return true to cancel the operation, false otherwise - */ - virtual bool cancel() const = 0; - - /** Called at the beginning of the operation. - * - * @param predictedTotal predicted amount of units (this has - * no concrete meaning: these are not bytes, nor percentage...) - */ - virtual void start(const size_t predictedTotal) = 0; - - /** Called during the operation (can be called several times). - * - * @param current current position - * @param currentTotal adjusted total amount of units - */ - virtual void progress(const size_t current, const size_t currentTotal) = 0; - - /** Called at the end of the operation. - * - * @param total final total amount of units - */ - virtual void stop(const size_t total) = 0; -}; - - - -/** A progress listener used when total size is known by the - * receiver, but not by the notifier. - */ - -class VMIME_EXPORT progressListenerSizeAdapter : public progressListener -{ -public: - - /** Construct a new progressListenerSizeAdapter object. - * - * @param list wrapped progress listener (can be NULL) - * @param total predicted total - */ - progressListenerSizeAdapter(progressListener* list, const size_t total); - - bool cancel() const; - - void start(const size_t predictedTotal); - void progress(const size_t current, const size_t currentTotal); - void stop(const size_t total); - -private: - - progressListener* m_wrapped; - size_t m_total; -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_PROGRESSLISTENER_HPP_INCLUDED - diff --git a/vmime/utility/random.hpp b/vmime/utility/random.hpp deleted file mode 100644 index b667c3a2..00000000 --- a/vmime/utility/random.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_RANDOM_HPP_INCLUDED -#define VMIME_UTILITY_RANDOM_HPP_INCLUDED - - -#include "vmime/types.hpp" - - -namespace vmime { -namespace utility { - - -/** Pseudo-random number generator. - */ - -class random -{ -public: - - /** Return a new random number. - * - * @return random number - */ - static unsigned int getNext(); - - /** Return the current time as a number (may be used to - * build "random" strings). - * - * @return time as a number - */ - static unsigned int getTime(); - - /** Return the current process number (may be user to - * build "random" strings). - * - * @return process number - */ - static unsigned int getProcess(); - - /** Return a random character string with the specified length. - * - * @param length length of the string to generate - * @param randomChars list of characters to use - * @return random string - */ - static const string getString(const size_t length, const string& randomChars - = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_RANDOM_HPP_INCLUDED diff --git a/vmime/utility/seekableInputStream.hpp b/vmime/utility/seekableInputStream.hpp deleted file mode 100644 index f56af9c4..00000000 --- a/vmime/utility/seekableInputStream.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_SEEKABLEINPUTSTREAM_HPP_INCLUDED -#define VMIME_UTILITY_SEEKABLEINPUTSTREAM_HPP_INCLUDED - - -#include "vmime/utility/inputStream.hpp" - - -namespace vmime { -namespace utility { - - -/** An input stream that allows seeking within the input. - */ - -class VMIME_EXPORT seekableInputStream : public inputStream -{ -public: - - /** Returns the current position in this stream. - * - * @return the offset from the beginning of the stream, in bytes, - * at which the next read occurs - */ - virtual size_t getPosition() const = 0; - - /** Sets the position, measured from the beginning of this stream, - * at which the next read occurs. - * - * @param pos the offset position, measured in bytes from the - * beginning of the stream, at which to set the stream pointer. - */ - virtual void seek(const size_t pos) = 0; -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_SEEKABLEINPUTSTREAM_HPP_INCLUDED - diff --git a/vmime/utility/seekableInputStreamRegionAdapter.hpp b/vmime/utility/seekableInputStreamRegionAdapter.hpp deleted file mode 100644 index 4716d2de..00000000 --- a/vmime/utility/seekableInputStreamRegionAdapter.hpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_SEEKABLEINPUTSTREAMREGIONADAPTER_HPP_INCLUDED -#define VMIME_UTILITY_SEEKABLEINPUTSTREAMREGIONADAPTER_HPP_INCLUDED - - -#include "vmime/utility/seekableInputStream.hpp" - - -namespace vmime { -namespace utility { - - -/** An adapter for reading a limited region of a seekable input stream. - */ - -class VMIME_EXPORT seekableInputStreamRegionAdapter : public seekableInputStream -{ -public: - - /** Creates a new adapter for a seekableInputStream. - * - * @param stream source stream - * @param begin start position in source stream - * @param length region length in source stream - */ - seekableInputStreamRegionAdapter(shared_ptr stream, - const size_t begin, const 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: - - shared_ptr m_stream; - size_t m_begin; - size_t m_length; - size_t m_position; -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_SEEKABLEINPUTSTREAMREGIONADAPTER_HPP_INCLUDED - diff --git a/vmime/utility/stream.hpp b/vmime/utility/stream.hpp deleted file mode 100644 index 980a2407..00000000 --- a/vmime/utility/stream.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_STREAM_HPP_INCLUDED -#define VMIME_UTILITY_STREAM_HPP_INCLUDED - - -#include - -#include "vmime/config.hpp" -#include "vmime/types.hpp" -#include "vmime/base.hpp" - - -namespace vmime { -namespace utility { - - - -/** Base class for input/output stream. - */ - -class VMIME_EXPORT stream : public object, private noncopyable -{ -public: - - virtual ~stream() { } - - /** Return the preferred maximum block size when reading - * from or writing to this stream. - * - * @return block size, in bytes - */ - virtual size_t getBlockSize(); -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_STREAM_HPP_INCLUDED diff --git a/vmime/utility/streamUtils.hpp b/vmime/utility/streamUtils.hpp deleted file mode 100644 index 406b6b64..00000000 --- a/vmime/utility/streamUtils.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_STREAMUTILS_HPP_INCLUDED -#define VMIME_UTILITY_STREAMUTILS_HPP_INCLUDED - - -#include "vmime/utility/inputStream.hpp" -#include "vmime/utility/outputStream.hpp" - -#include "vmime/utility/progressListener.hpp" - - -namespace vmime { -namespace utility { - - -/** Copy data from one stream into another stream using a buffered method. - * - * @param is input stream (source data) - * @param os output stream (destination for data) - * @return number of bytes copied - */ - -VMIME_EXPORT size_t bufferedStreamCopy(inputStream& is, outputStream& os); - -/** Copy data from one stream into another stream using a buffered method - * and copying only a specified range of data. - * - * @param is input stream (source data) - * @param os output stream (destination for data) - * @param start number of bytes to ignore before starting copying - * @param length maximum number of bytes to copy - * @return number of bytes copied - */ - -VMIME_EXPORT size_t bufferedStreamCopyRange(inputStream& is, outputStream& os, - const size_t start, const size_t length); - -/** Copy data from one stream into another stream using a buffered method - * and notify progress state of the operation. - * - * @param is input stream (source data) - * @param os output stream (destination for data) - * @param length predicted number of bytes to copy - * @param progress listener to notify - * @return number of bytes copied - */ - -VMIME_EXPORT size_t bufferedStreamCopy(inputStream& is, outputStream& os, - const size_t length, progressListener* progress); - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_STREAMUTILS_HPP_INCLUDED - diff --git a/vmime/utility/stringProxy.hpp b/vmime/utility/stringProxy.hpp deleted file mode 100644 index e5efa135..00000000 --- a/vmime/utility/stringProxy.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_STRINGPROXY_HPP_INCLUDED -#define VMIME_UTILITY_STRINGPROXY_HPP_INCLUDED - - -#include - -#include "vmime/types.hpp" -#include "vmime/utility/stream.hpp" -#include "vmime/utility/outputStream.hpp" -#include "vmime/utility/progressListener.hpp" - - -namespace vmime { -namespace utility { - - -/** This class is a proxy for the string class. This takes - * advantage of the COW (copy-on-write) system that might - * be used in "std::string" implementation. - */ - -class VMIME_EXPORT stringProxy -{ -public: - - // Consruction - stringProxy(); - stringProxy(const stringProxy& s); - stringProxy(const string& s, const size_t start = 0, const size_t end = std::numeric_limits ::max()); - - // Assignment - void set(const string& s, const size_t start = 0, const size_t end = std::numeric_limits ::max()); - void detach(); - - stringProxy& operator=(const stringProxy& s); - stringProxy& operator=(const string& s); - - // Extract some portion (or whole) of the string - // and output it into a stream. - void extract(outputStream& os, const size_t start = 0, const size_t end = std::numeric_limits ::max(), utility::progressListener* progress = NULL) const; - - // Return the "virtual" length of the string - size_t length() const; - - // Return the boundaries of the "virtual" string - size_t start() const; - size_t end() const; - - string::const_iterator it_begin() const { return (m_buffer.begin() + m_start); } - string::const_iterator it_end() const { return (m_buffer.begin() + m_end); } - -private: - - string m_buffer; - - size_t m_start; - size_t m_end; -}; - - -VMIME_EXPORT std::ostream& operator<<(std::ostream& os, const stringProxy& s); -VMIME_EXPORT outputStream& operator<<(outputStream& os, const stringProxy& s); - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_STRINGPROXY_HPP_INCLUDED diff --git a/vmime/utility/stringUtils.hpp b/vmime/utility/stringUtils.hpp deleted file mode 100644 index 7d9925e2..00000000 --- a/vmime/utility/stringUtils.hpp +++ /dev/null @@ -1,214 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_STRINGUTILS_HPP_INCLUDED -#define VMIME_UTILITY_STRINGUTILS_HPP_INCLUDED - - -#include "vmime/types.hpp" -#include "vmime/base.hpp" - -#include - - -namespace vmime { -namespace utility { - - -/** Miscellaneous functions related to strings. - */ - -class VMIME_EXPORT stringUtils -{ -public: - - /** Makes a string from bytes. - * - * @param data pointer to buffer containing data - * @param count number of bytes to use from buffer - * @return a string object containing a copy of the specified data - */ - static const string makeStringFromBytes(const byte_t* data, const size_t count) - { - return string(reinterpret_cast (data), count); - } - - /** Appends bytes to a string. - * - * @param str string to which append data - * @param data pointer to buffer containing data - * @param count number of bytes to use from buffer - * @return a reference to modified string - */ - static string& appendBytesToString(string& str, const byte_t* data, const size_t count) - { - str.append(reinterpret_cast (data), count); - return str; - } - - /** Test two strings for equality (case insensitive). - * \warning Use this with ASCII-only strings. - * - * @param s1 first string - * @param s2 second string (must be in lower-case!) - * @param n length of the second string - * @return true if the two strings compare equally, false otherwise - */ - static bool isStringEqualNoCase(const string& s1, const char* s2, const size_t n); - - /** Test two strings for equality (case insensitive). - * \warning Use this with ASCII-only strings. - * - * @param s1 first string - * @param s2 second string - * @return true if the two strings compare equally, false otherwise - */ - static bool isStringEqualNoCase(const string& s1, const string& s2); - - /** Test two strings for equality (case insensitive). - * \warning Use this with ASCII-only strings. - * - * @param begin start position of the first string - * @param end end position of the first string - * @param s second string (must be in lower-case!) - * @param n length of the second string - * @return true if the two strings compare equally, false otherwise - */ - static bool isStringEqualNoCase(const string::const_iterator begin, const string::const_iterator end, const char* s, const size_t n); - - /** Transform all the characters in a string to lower-case. - * \warning Use this with ASCII-only strings. - * - * @param str the string to transform - * @return a new string in lower-case - */ - static const string toLower(const string& str); - - /** Transform all the characters in a string to upper-case. - * \warning Use this with ASCII-only strings. - * - * @param str the string to transform - * @return a new string in upper-case - */ - static const string toUpper(const string& str); - - /** Strip the space characters (SPC, TAB, CR, LF) at the beginning - * and at the end of the specified string. - * - * @param str string in which to strip spaces - * @return a new string with space characters removed - */ - static const string trim(const string& str); - - /** Return the number of 7-bit US-ASCII characters in a string. - * - * @param begin start position - * @param end end position - * @return number of ASCII characters - */ - static size_t countASCIIchars(const string::const_iterator begin, const string::const_iterator end); - - /** Returns whether the specified string is composed exclusively - * of 7-bit ASCII characters. - * - * @param str string to test - * @return true if the string is ASCII-only, false otherwise - */ - static bool is7bit(const string& str); - - /** Returns the position of the first non 7-bit US-ASCII character in a string. - * - * @param begin start position - * @param end end position - * @return position since begin, or string::npos - */ - static size_t findFirstNonASCIIchar(const string::const_iterator begin, const string::const_iterator end); - - /** Convert the specified value to a string value. - * - * @param value to convert - * @return value converted from type 'TYPE' - */ - template - static const string toString(const TYPE& value) - { - std::ostringstream oss; - oss.imbue(std::locale::classic()); - - oss << value; - - return (oss.str()); - } - - /** Convert the specified string value to a value of - * the specified type. - * - * @param value value to convert - * @return value converted into type 'TYPE' - */ - template - static const TYPE fromString(const string& value) - { - TYPE ret; - - std::istringstream iss(value); - iss.imbue(std::locale::classic()); - - iss >> ret; - - return (ret); - } - - /** Unquote the specified string and transform escaped characters. - * - * @param str string from which to remove quotes - * @return unquoted string - */ - static const string unquote(const string& str); - - /** Determines whether the specified string needs to be quoted. - * - * @param str string to test - * @param specialChars list of characters that will cause the - * string to be quoted - * @return true if the string needs to be quoted, false otherwise - */ - static bool needQuoting(const string& str, - const string& specialChars = " \t\"(),:;<>@[\\]"); - - /** Quotes the specified string. - * - * @param str string to quote - * @param escapeSpecialChars list of characters that will be escaped - * @param escapeChar character that will be used for escaping (eg. '\') - * @return quoted string - */ - static string quote(const string& str, const string& escapeSpecialChars, const string& escapeChar); -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_STRINGUTILS_HPP_INCLUDED diff --git a/vmime/utility/sync/autoLock.hpp b/vmime/utility/sync/autoLock.hpp deleted file mode 100644 index c058429d..00000000 --- a/vmime/utility/sync/autoLock.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_SYNC_AUTOLOCK_HPP_INCLUDED -#define VMIME_UTILITY_SYNC_AUTOLOCK_HPP_INCLUDED - - -#include "vmime/base.hpp" - - -namespace vmime { -namespace utility { -namespace sync { - - -/** Critical section wrapper class - */ - -template -class VMIME_EXPORT autoLock : public object -{ -public: - - autoLock(shared_ptr mutex) - : m_mutex(mutex) - { - m_mutex->lock(); - } - - ~autoLock() - { - m_mutex->unlock(); - } - -private: - - shared_ptr m_mutex; -}; - - -} // sync -} // utility -} // vmime - - -#endif // VMIME_UTILITY_SYNC_AUTOLOCK_HPP_INCLUDED diff --git a/vmime/utility/sync/criticalSection.hpp b/vmime/utility/sync/criticalSection.hpp deleted file mode 100644 index 9703d73c..00000000 --- a/vmime/utility/sync/criticalSection.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_SYNC_CRITICALSECTION_HPP_INCLUDED -#define VMIME_UTILITY_SYNC_CRITICALSECTION_HPP_INCLUDED - - -#include "vmime/base.hpp" - - -namespace vmime { -namespace utility { -namespace sync { - - -/** Critical section class. - */ - -class VMIME_EXPORT criticalSection : public object -{ -public: - - virtual ~criticalSection(); - - /** Enters the critical section. - */ - virtual void lock() = 0; - - /** Leaves the critical section. - */ - virtual void unlock() = 0; - -protected: - - criticalSection(); - criticalSection(criticalSection&); -}; - - -} // sync -} // utility -} // vmime - - -#endif // VMIME_UTILITY_SYNC_CRITICALSECTION_HPP_INCLUDED diff --git a/vmime/utility/url.hpp b/vmime/utility/url.hpp deleted file mode 100644 index 84aba618..00000000 --- a/vmime/utility/url.hpp +++ /dev/null @@ -1,207 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_URL_HPP_INCLUDED -#define VMIME_UTILITY_URL_HPP_INCLUDED - - -#include "vmime/types.hpp" -#include "vmime/base.hpp" -#include "vmime/propertySet.hpp" - - -namespace vmime { -namespace utility { - - -/** This class represents a Uniform Resource Locator (a pointer - * to a "resource" on the World Wide Web). - */ - -class VMIME_EXPORT url -{ -public: - - /** Means "port not specified" (use default port). */ - static const port_t UNSPECIFIED_PORT; - - /** Standard name for FILE protocol (local file-system). */ - static const string PROTOCOL_FILE; - - /** Standard name for HTTP protocol. */ - static const string PROTOCOL_HTTP; - - /** Standard name for FTP protocol. */ - static const string PROTOCOL_FTP; - - - /** Construct an URL from a string (parse the URL components). - * - * @param s full URL string (eg. http://www.vmime.org:80/download.html) - * @throw exceptions::malformed_url if URL is malformed - */ - url(const string& s); - - /** Construct an URL from another URL object. - * - * @param u other URL object - */ - url(const url& u); - - /** Construct an URL from the components. - * - * @param protocol protocol (eg. "http", "ftp"...) - * @param host host name (eg. "www.vmime.org", "123.45.67.89") - * @param port optional port number (eg. 80, 110 or UNSPECIFIED_PORT to mean "default") - * @param path optional full path (eg. "download.html") - * @param username optional user name - * @param password optional user password - */ - url(const string& protocol, const string& host, const port_t port = UNSPECIFIED_PORT, - const string& path = "", const string& username = "", const string& password = ""); - - - /** Return the protocol of the URL (eg: "http"). - * - * @return protocol of the URL - */ - const string& getProtocol() const; - - /** Set the protocol of the URL. - * - * @param protocol new protocol (eg: "http") - */ - void setProtocol(const string& protocol); - - /** Return the username specified in the URL - * or empty if not specified. - * - * @return user name - */ - const string& getUsername() const; - - /** Set the username of the URL. - * - * @param username user name - */ - void setUsername(const string& username); - - /** Return the password specified in the URL - * or empty if not specified. - * - * @return user password - */ - const string& getPassword() const; - - /** Set the password of the URL. - * - * @param password user password - */ - void setPassword(const string& password); - - /** Return the host name of the URL (server name or IP address). - * - * @return host name - */ - const string& getHost() const; - - /** Set the host name of the URL. - * - * @param host server name or IP address - */ - void setHost(const string& host); - - /** Return the port of the URL, or url::UNSPECIFIED_PORT if - * the default port if used. - * - * @return server port - */ - port_t getPort() const; - - /** Set the port of the URL. - * - * @param port server port or url::UNSPECIFIED_PORT to - * use the default port of the protocol - */ - void setPort(const port_t port); - - /** Return the path portion of the URL, - * or empty if not specified. - * - * @return path - */ - const string& getPath() const; - - /** Set the part portion of the URL. - * - * @param path path - */ - void setPath(const string& path); - - /** Return the parameters of the URL (read-only). - * - * @return parameters - */ - const std::map & getParams() const; - - /** Return the parameters of the URL. - * - * @return parameters - */ - std::map & getParams(); - - /** Build a string URL from this object. - */ - operator string() const; - - url& operator=(const url& u); - url& operator=(const string& s); - -private: - - const string build() const; - void parse(const string& str); - - // Format: - // "protocol://[username[:password]@]host[:port][/path]" - - string m_protocol; - - string m_username; - string m_password; - - string m_host; - - port_t m_port; - - string m_path; - - std::map m_params; -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_URL_HPP_INCLUDED diff --git a/vmime/utility/urlUtils.hpp b/vmime/utility/urlUtils.hpp deleted file mode 100644 index c21e7aa4..00000000 --- a/vmime/utility/urlUtils.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_URLUTILS_HPP_INCLUDED -#define VMIME_UTILITY_URLUTILS_HPP_INCLUDED - - -#include "vmime/types.hpp" -#include "vmime/base.hpp" - - -namespace vmime { -namespace utility { - - -/** Miscellaneous functions related to URLs. - */ - -class VMIME_EXPORT urlUtils -{ -public: - - /** Encode extended characters in a URL string (ASCII characters - * are unmodified, other are encoded as '%' followed by hex code). - */ - static const string encode(const string& s); - - /** Decode an hex-encoded URL (see encode()). - */ - static const string decode(const string& s); -}; - - -} // utility -} // vmime - - -#endif // VMIME_UTILITY_URLUTILS_HPP_INCLUDED diff --git a/vmime/vmime.hpp b/vmime/vmime.hpp deleted file mode 100644 index 9bb017e3..00000000 --- a/vmime/vmime.hpp +++ /dev/null @@ -1,161 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should.have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_INCLUDED -#define VMIME_INCLUDED - - -// Configuration -#include "vmime/config.hpp" - -// Base definitions -#include "vmime/base.hpp" -#include "vmime/exception.hpp" -#include "vmime/platform.hpp" - -// Base components -#include "vmime/dateTime.hpp" -#include "vmime/message.hpp" -#include "vmime/bodyPart.hpp" -#include "vmime/charset.hpp" -#include "vmime/text.hpp" -#include "vmime/encoding.hpp" -#include "vmime/contentDisposition.hpp" -#include "vmime/emailAddress.hpp" -#include "vmime/mailbox.hpp" -#include "vmime/mailboxGroup.hpp" -#include "vmime/mailboxList.hpp" -#include "vmime/addressList.hpp" -#include "vmime/mediaType.hpp" -#include "vmime/messageId.hpp" -#include "vmime/messageIdSequence.hpp" -#include "vmime/relay.hpp" -#include "vmime/disposition.hpp" -#include "vmime/path.hpp" - -#include "vmime/emptyContentHandler.hpp" -#include "vmime/fileContentHandler.hpp" -#include "vmime/stringContentHandler.hpp" -#include "vmime/streamContentHandler.hpp" - -#include "vmime/generationContext.hpp" -#include "vmime/parsingContext.hpp" - -// Message components -#include "vmime/message.hpp" - -// Header fields -#include "vmime/headerFieldFactory.hpp" -#include "vmime/mailboxField.hpp" -#include "vmime/parameterizedHeaderField.hpp" - -// Encoders -#include "vmime/utility/encoder/encoderFactory.hpp" - -// Streams -#include "vmime/utility/filteredStream.hpp" -#include "vmime/utility/inputStream.hpp" -#include "vmime/utility/inputStreamAdapter.hpp" -#include "vmime/utility/inputStreamByteBufferAdapter.hpp" -#include "vmime/utility/inputStreamPointerAdapter.hpp" -#include "vmime/utility/inputStreamSocketAdapter.hpp" -#include "vmime/utility/inputStreamStringAdapter.hpp" -#include "vmime/utility/inputStreamStringProxyAdapter.hpp" -#include "vmime/utility/outputStream.hpp" -#include "vmime/utility/outputStreamAdapter.hpp" -#include "vmime/utility/outputStreamByteArrayAdapter.hpp" -#include "vmime/utility/outputStreamSocketAdapter.hpp" -#include "vmime/utility/outputStreamStringAdapter.hpp" -#include "vmime/utility/streamUtils.hpp" - -// Message builder/parser -#include "vmime/messageBuilder.hpp" -#include "vmime/messageParser.hpp" - -#include "vmime/fileAttachment.hpp" -#include "vmime/defaultAttachment.hpp" -#include "vmime/messageAttachment.hpp" - -#include "vmime/plainTextPart.hpp" -#include "vmime/htmlTextPart.hpp" - -#include "vmime/attachmentHelper.hpp" - -// MDN -#include "vmime/mdn/MDNHelper.hpp" - -// Misc -#include "vmime/misc/importanceHelper.hpp" - -// Property set -#include "vmime/propertySet.hpp" - -// Utilities -#include "vmime/utility/datetimeUtils.hpp" -#include "vmime/utility/filteredStream.hpp" -#include "vmime/charsetConverter.hpp" - -// Security -#include "vmime/security/authenticator.hpp" -#include "vmime/security/defaultAuthenticator.hpp" - -// Security/digest -#include "vmime/security/digest/messageDigestFactory.hpp" - -// Security/SASL -#if VMIME_HAVE_SASL_SUPPORT - #include "vmime/security/sasl/SASLAuthenticator.hpp" - #include "vmime/security/sasl/defaultSASLAuthenticator.hpp" - #include "vmime/security/sasl/SASLContext.hpp" - #include "vmime/security/sasl/SASLSession.hpp" -#endif // VMIME_HAVE_SASL_SUPPORT - -// Messaging features -#if VMIME_HAVE_MESSAGING_FEATURES - #include "vmime/net/socket.hpp" - - #include "vmime/net/serviceFactory.hpp" - #include "vmime/net/store.hpp" - #include "vmime/net/transport.hpp" - - #include "vmime/net/session.hpp" - - #include "vmime/net/folder.hpp" - #include "vmime/net/message.hpp" -#endif // VMIME_HAVE_MESSAGING_FEATURES - -// Net/TLS -#if VMIME_HAVE_TLS_SUPPORT - #include "vmime/security/cert/certificate.hpp" - #include "vmime/security/cert/certificateChain.hpp" - #include "vmime/security/cert/certificateVerifier.hpp" - - #include "vmime/security/cert/X509Certificate.hpp" - - #include "vmime/security/cert/defaultCertificateVerifier.hpp" - - #include "vmime/net/tls/TLSSession.hpp" -#endif // VMIME_HAVE_TLS_SUPPORT - - -#endif // VMIME_INCLUDED diff --git a/vmime/word.hpp b/vmime/word.hpp deleted file mode 100644 index a6e2402e..00000000 --- a/vmime/word.hpp +++ /dev/null @@ -1,195 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_WORD_HPP_INCLUDED -#define VMIME_WORD_HPP_INCLUDED - - -#include "vmime/headerFieldValue.hpp" -#include "vmime/charset.hpp" -#include "vmime/charsetConverterOptions.hpp" - - -namespace vmime -{ - - -/** A class that encapsulates an encoded-word (RFC-2047): - * some text encoded into one specified charset. - */ - -class VMIME_EXPORT word : public headerFieldValue -{ - friend class text; - -public: - - word(); - word(const word& w); - word(const string& buffer); // Defaults to local charset - word(const string& buffer, const charset& charset); - - /** Return the raw data for this encoded word. - * - * @return raw data buffer - */ - const string& getBuffer() const; - - /** Return the raw data for this encoded word. - * - * @return raw data buffer - */ - string& getBuffer(); - - /** Tests whether this word is empty. - * - * @return true if the buffer is empty, false otherwise - */ - bool isEmpty() const; - - /** Set the raw data for this encoded word. - * - * @param buffer raw data buffer - */ - void setBuffer(const string& buffer); - - /** Return the charset of this word. - * - * @return charset for this word - */ - const charset& getCharset() const; - - /** Set the charset of this word. - * - * @param ch charset of this word - */ - void setCharset(const charset& ch); - - - word& operator=(const word& w); - word& operator=(const string& s); - - bool operator==(const word& w) const; - bool operator!=(const word& w) const; - - /** Return the contained text converted to the specified charset. - * - * @param dest output charset - * @param opts options for charset conversion - * @return word converted to the specified charset - */ - const string getConvertedText(const charset& dest, - const charsetConverterOptions& opts = charsetConverterOptions()) const; - - /** Replace data in this word by data in other word. - * - * @param other other word to copy data from - */ - void copyFrom(const component& other); - - /** Clone this word. - * - * @return a copy of this word - */ - shared_ptr clone() const; - - -#ifndef VMIME_BUILDING_DOC - class generatorState - { - public: - - generatorState() - : isFirstWord(true), prevWordIsEncoded(false), lastCharIsSpace(false) - { - } - - bool isFirstWord; - bool prevWordIsEncoded; - bool lastCharIsSpace; - }; -#endif - - -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; - -public: - - using component::generate; - -#ifndef VMIME_BUILDING_DOC - void generate - (const generationContext& ctx, - utility::outputStream& os, - const size_t curLinePos, - size_t* newLinePos, - const int flags, - generatorState* state) const; -#endif - - const std::vector > getChildComponents(); - -private: - - static shared_ptr parseNext - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition, - bool prevIsEncoded, - bool* isEncoded, - bool isFirst); - - static const std::vector > parseMultiple - (const parsingContext& ctx, - const string& buffer, - const size_t position, - const size_t end, - size_t* newPosition); - - - // The "m_buffer" of this word holds the data, and this data is encoded - // in the specified "m_charset". - string m_buffer; - charset m_charset; -}; - - -} // vmime - - -#endif // VMIME_WORD_HPP_INCLUDED diff --git a/vmime/wordEncoder.hpp b/vmime/wordEncoder.hpp deleted file mode 100644 index 6f652fa2..00000000 --- a/vmime/wordEncoder.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 3 of -// the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Linking this library statically or dynamically with other modules 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_WORDENCODER_HPP_INCLUDED -#define VMIME_WORDENCODER_HPP_INCLUDED - - -#include "vmime/charset.hpp" - - -namespace vmime -{ - - -namespace utility { -namespace encoder { - -class encoder; - -} // encoder -} // utility - - -/** Encodes words following RFC-2047. - */ - -class VMIME_EXPORT wordEncoder -{ -public: - - /** Available encodings for RFC-2047. */ - enum Encoding - { - ENCODING_AUTO, - ENCODING_QP, - ENCODING_B64 - }; - - - wordEncoder(const string& buffer, const charset& charset, const Encoding encoding = ENCODING_AUTO); - - - /** Return the next chunk in the word. - * - * @param maxLength maximal length of the chunk - * @return next chunk, of maximal length 'maxLength' if possible - */ - const string getNextChunk(const size_t maxLength); - - /** Return the encoding used. - * - * @return encoding - */ - Encoding getEncoding() const; - - /** Test whether RFC-2047 encoding is needed. - * - * @param ctx generation context - * @param buffer buffer to analyze - * @param charset charset of the buffer - * @return true if encoding is needed, false otherwise. - */ - static bool isEncodingNeeded(const generationContext& ctx, const string& buffer, const charset& charset); - - /** Guess the best RFC-2047 encoding to use for the specified buffer. - * - * @param buffer buffer to analyze - * @param charset charset of the buffer - * @return RFC-2047 encoding - */ - static Encoding guessBestEncoding(const string& buffer, const charset& charset); - -private: - - string m_buffer; - size_t m_pos; - size_t m_length; - - bool m_simple; - - charset m_charset; - Encoding m_encoding; - - shared_ptr m_encoder; -}; - - -} // vmime - - -#endif // VMIME_WORDENCODER_HPP_INCLUDED - -- cgit v1.2.3