summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrédéric Guillot <fred@kanboard.net>2014-08-15 17:23:41 -0700
committerFrédéric Guillot <fred@kanboard.net>2014-08-15 17:23:41 -0700
commit9eeded33f68872515954a2fc177fcb47a9273ae9 (patch)
treef3ef9507e087ca6bf3ce624232da240a8689b051
parentc539bdc8ab746c5afd48cf87de057dc38d50adac (diff)
Add email notifications
-rw-r--r--app/Controller/Base.php7
-rw-r--r--app/Controller/Board.php2
-rw-r--r--app/Controller/Config.php13
-rw-r--r--app/Core/Tool.php7
-rw-r--r--app/Event/BaseNotificationListener.php76
-rw-r--r--app/Event/CommentNotificationListener.php30
-rw-r--r--app/Event/FileNotificationListener.php30
-rw-r--r--app/Event/SubTaskNotificationListener.php30
-rw-r--r--app/Event/TaskNotificationListener.php29
-rw-r--r--app/Locales/de_DE/translations.php27
-rw-r--r--app/Locales/es_ES/translations.php27
-rw-r--r--app/Locales/fi_FI/translations.php27
-rw-r--r--app/Locales/fr_FR/translations.php27
-rw-r--r--app/Locales/pl_PL/translations.php27
-rw-r--r--app/Locales/pt_BR/translations.php27
-rw-r--r--app/Locales/sv_SE/translations.php27
-rw-r--r--app/Locales/zh_CN/translations.php26
-rw-r--r--app/Model/Acl.php2
-rw-r--r--app/Model/Action.php14
-rw-r--r--app/Model/Base.php47
-rw-r--r--app/Model/Board.php16
-rw-r--r--app/Model/Comment.php23
-rw-r--r--app/Model/File.php9
-rw-r--r--app/Model/GitHub.php25
-rw-r--r--app/Model/Google.php20
-rw-r--r--app/Model/Ldap.php3
-rw-r--r--app/Model/Notification.php215
-rw-r--r--app/Model/Project.php36
-rw-r--r--app/Model/RememberMe.php7
-rw-r--r--app/Model/ReverseProxyAuth.php18
-rw-r--r--app/Model/SubTask.php44
-rw-r--r--app/Model/Task.php152
-rw-r--r--app/Model/User.php11
-rw-r--r--app/Model/Webhook.php8
-rw-r--r--app/Schema/Mysql.php17
-rw-r--r--app/Schema/Postgres.php17
-rw-r--r--app/Schema/Sqlite.php17
-rw-r--r--app/Templates/comment_edit.php1
-rw-r--r--app/Templates/config_index.php27
-rw-r--r--app/Templates/notification_comment_creation.php8
-rw-r--r--app/Templates/notification_comment_update.php8
-rw-r--r--app/Templates/notification_file_creation.php6
-rw-r--r--app/Templates/notification_subtask_creation.php18
-rw-r--r--app/Templates/notification_subtask_update.php22
-rw-r--r--app/Templates/notification_task_close.php6
-rw-r--r--app/Templates/notification_task_creation.php44
-rw-r--r--app/Templates/notification_task_due.php10
-rw-r--r--app/Templates/notification_task_open.php6
-rw-r--r--app/Templates/notification_task_update.php44
-rw-r--r--app/common.php33
-rw-r--r--assets/css/app.css4
-rw-r--r--assets/js/app.js7
-rw-r--r--config.default.php15
-rw-r--r--jsonrpc.php30
-rwxr-xr-xkanboard35
-rw-r--r--tests/units/AclTest.php8
-rw-r--r--tests/units/ActionTaskAssignColorCategoryTest.php10
-rw-r--r--tests/units/ActionTaskAssignColorUserTest.php8
-rw-r--r--tests/units/ActionTaskAssignCurrentUserTest.php12
-rw-r--r--tests/units/ActionTaskAssignSpecificUserTest.php10
-rw-r--r--tests/units/ActionTaskCloseTest.php10
-rw-r--r--tests/units/ActionTaskDuplicateAnotherProjectTest.php10
-rw-r--r--tests/units/ActionTest.php46
-rw-r--r--tests/units/Base.php7
-rw-r--r--tests/units/BoardTest.php4
-rw-r--r--tests/units/CommentTest.php22
-rw-r--r--tests/units/ProjectTest.php18
-rw-r--r--tests/units/TaskTest.php44
-rw-r--r--vendor/PicoDb/Table.php6
-rw-r--r--vendor/swiftmailer/classes/Swift.php80
-rw-r--r--vendor/swiftmailer/classes/Swift/Attachment.php71
-rw-r--r--vendor/swiftmailer/classes/Swift/ByteStream/AbstractFilterableInputStream.php179
-rw-r--r--vendor/swiftmailer/classes/Swift/ByteStream/ArrayByteStream.php184
-rw-r--r--vendor/swiftmailer/classes/Swift/ByteStream/FileByteStream.php229
-rw-r--r--vendor/swiftmailer/classes/Swift/ByteStream/TemporaryFileByteStream.php42
-rw-r--r--vendor/swiftmailer/classes/Swift/CharacterReader.php67
-rw-r--r--vendor/swiftmailer/classes/Swift/CharacterReader/GenericFixedWidthReader.php97
-rw-r--r--vendor/swiftmailer/classes/Swift/CharacterReader/UsAsciiReader.php83
-rw-r--r--vendor/swiftmailer/classes/Swift/CharacterReader/Utf8Reader.php179
-rw-r--r--vendor/swiftmailer/classes/Swift/CharacterReaderFactory.php26
-rw-r--r--vendor/swiftmailer/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php124
-rw-r--r--vendor/swiftmailer/classes/Swift/CharacterStream.php89
-rw-r--r--vendor/swiftmailer/classes/Swift/CharacterStream/ArrayCharacterStream.php294
-rw-r--r--vendor/swiftmailer/classes/Swift/CharacterStream/NgCharacterStream.php275
-rw-r--r--vendor/swiftmailer/classes/Swift/ConfigurableSpool.php63
-rw-r--r--vendor/swiftmailer/classes/Swift/DependencyContainer.php370
-rw-r--r--vendor/swiftmailer/classes/Swift/DependencyException.php27
-rw-r--r--vendor/swiftmailer/classes/Swift/EmbeddedFile.php69
-rw-r--r--vendor/swiftmailer/classes/Swift/Encoder.php27
-rw-r--r--vendor/swiftmailer/classes/Swift/Encoder/Base64Encoder.php58
-rw-r--r--vendor/swiftmailer/classes/Swift/Encoder/QpEncoder.php282
-rw-r--r--vendor/swiftmailer/classes/Swift/Encoder/Rfc2231Encoder.php84
-rw-r--r--vendor/swiftmailer/classes/Swift/Encoding.php64
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/CommandEvent.php65
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/CommandListener.php24
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/Event.php38
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/EventDispatcher.php83
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/EventListener.php18
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/EventObject.php63
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/ResponseEvent.php66
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/ResponseListener.php24
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/SendEvent.php126
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/SendListener.php31
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/SimpleEventDispatcher.php157
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/TransportChangeEvent.php27
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/TransportChangeListener.php45
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/TransportExceptionEvent.php46
-rw-r--r--vendor/swiftmailer/classes/Swift/Events/TransportExceptionListener.php24
-rw-r--r--vendor/swiftmailer/classes/Swift/FailoverTransport.php45
-rw-r--r--vendor/swiftmailer/classes/Swift/FileSpool.php208
-rw-r--r--vendor/swiftmailer/classes/Swift/FileStream.php24
-rw-r--r--vendor/swiftmailer/classes/Swift/Filterable.php32
-rw-r--r--vendor/swiftmailer/classes/Swift/Image.php61
-rw-r--r--vendor/swiftmailer/classes/Swift/InputByteStream.php75
-rw-r--r--vendor/swiftmailer/classes/Swift/IoException.php27
-rw-r--r--vendor/swiftmailer/classes/Swift/KeyCache.php105
-rw-r--r--vendor/swiftmailer/classes/Swift/KeyCache/ArrayKeyCache.php206
-rw-r--r--vendor/swiftmailer/classes/Swift/KeyCache/DiskKeyCache.php324
-rw-r--r--vendor/swiftmailer/classes/Swift/KeyCache/KeyCacheInputStream.php51
-rw-r--r--vendor/swiftmailer/classes/Swift/KeyCache/NullKeyCache.php115
-rw-r--r--vendor/swiftmailer/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php127
-rw-r--r--vendor/swiftmailer/classes/Swift/LoadBalancedTransport.php45
-rw-r--r--vendor/swiftmailer/classes/Swift/MailTransport.php45
-rw-r--r--vendor/swiftmailer/classes/Swift/Mailer.php114
-rw-r--r--vendor/swiftmailer/classes/Swift/Mailer/ArrayRecipientIterator.php55
-rw-r--r--vendor/swiftmailer/classes/Swift/Mailer/RecipientIterator.php32
-rw-r--r--vendor/swiftmailer/classes/Swift/MemorySpool.php83
-rw-r--r--vendor/swiftmailer/classes/Swift/Message.php272
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/Attachment.php153
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/CharsetObserver.php24
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/ContentEncoder.php34
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php67
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php123
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php163
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php123
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php88
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php63
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/EmbeddedFile.php45
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/EncodingObserver.php24
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/Grammar.php176
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/Header.php93
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/HeaderEncoder.php24
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php55
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php65
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/HeaderFactory.php78
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/HeaderSet.php169
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/Headers/AbstractHeader.php502
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/Headers/DateHeader.php125
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/Headers/IdentificationHeader.php181
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/Headers/MailboxHeader.php354
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/Headers/OpenDKIMHeader.php137
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/Headers/ParameterizedHeader.php260
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/Headers/PathHeader.php144
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/Headers/UnstructuredHeader.php112
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/Message.php223
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/MimeEntity.php115
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/MimePart.php214
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/ParameterizedHeader.php34
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/SimpleHeaderFactory.php188
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/SimpleHeaderSet.php383
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/SimpleMessage.php651
-rw-r--r--vendor/swiftmailer/classes/Swift/Mime/SimpleMimeEntity.php853
-rw-r--r--vendor/swiftmailer/classes/Swift/MimePart.php59
-rw-r--r--vendor/swiftmailer/classes/Swift/NullTransport.php39
-rw-r--r--vendor/swiftmailer/classes/Swift/OutputByteStream.php46
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/AntiFloodPlugin.php141
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/BandwidthMonitorPlugin.php164
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/Decorator/Replacements.php31
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/DecoratorPlugin.php207
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/ImpersonatePlugin.php68
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/Logger.php36
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/LoggerPlugin.php141
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/Loggers/ArrayLogger.php72
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/Loggers/EchoLogger.php58
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/MessageLogger.php75
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/Pop/Pop3Connection.php31
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/Pop/Pop3Exception.php27
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/PopBeforeSmtpPlugin.php274
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php205
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/Reporter.php32
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/ReporterPlugin.php73
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/Reporters/HitReporter.php59
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/Reporters/HtmlReporter.php39
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/Sleeper.php24
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/ThrottlerPlugin.php200
-rw-r--r--vendor/swiftmailer/classes/Swift/Plugins/Timer.php24
-rw-r--r--vendor/swiftmailer/classes/Swift/Preferences.php103
-rw-r--r--vendor/swiftmailer/classes/Swift/ReplacementFilterFactory.php27
-rw-r--r--vendor/swiftmailer/classes/Swift/RfcComplianceException.php27
-rw-r--r--vendor/swiftmailer/classes/Swift/SendmailTransport.php45
-rw-r--r--vendor/swiftmailer/classes/Swift/SignedMessage.php23
-rw-r--r--vendor/swiftmailer/classes/Swift/Signer.php20
-rw-r--r--vendor/swiftmailer/classes/Swift/Signers/BodySigner.php33
-rw-r--r--vendor/swiftmailer/classes/Swift/Signers/DKIMSigner.php689
-rw-r--r--vendor/swiftmailer/classes/Swift/Signers/DomainKeySigner.php512
-rw-r--r--vendor/swiftmailer/classes/Swift/Signers/HeaderSigner.php65
-rw-r--r--vendor/swiftmailer/classes/Swift/Signers/OpenDKIMSigner.php186
-rw-r--r--vendor/swiftmailer/classes/Swift/Signers/SMimeSigner.php428
-rw-r--r--vendor/swiftmailer/classes/Swift/SmtpTransport.php57
-rw-r--r--vendor/swiftmailer/classes/Swift/Spool.php53
-rw-r--r--vendor/swiftmailer/classes/Swift/SpoolTransport.php47
-rw-r--r--vendor/swiftmailer/classes/Swift/StreamFilter.php35
-rw-r--r--vendor/swiftmailer/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php170
-rw-r--r--vendor/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilter.php66
-rw-r--r--vendor/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilterFactory.php45
-rw-r--r--vendor/swiftmailer/classes/Swift/SwiftException.php27
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport.php54
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/AbstractSmtpTransport.php502
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php81
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php51
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php699
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php50
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php69
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/Esmtp/AuthHandler.php264
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/Esmtp/Authenticator.php35
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/EsmtpHandler.php86
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/EsmtpTransport.php387
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/FailoverTransport.php86
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/IoBuffer.php67
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/LoadBalancedTransport.php167
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/MailInvoker.php32
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/MailTransport.php227
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/NullTransport.php93
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/SendmailTransport.php159
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/SimpleMailInvoker.php39
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/SmtpAgent.php36
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/SpoolTransport.php117
-rw-r--r--vendor/swiftmailer/classes/Swift/Transport/StreamBuffer.php321
-rw-r--r--vendor/swiftmailer/classes/Swift/TransportException.php27
-rw-r--r--vendor/swiftmailer/classes/Swift/Validate.php42
-rw-r--r--vendor/swiftmailer/dependency_maps/cache_deps.php23
-rw-r--r--vendor/swiftmailer/dependency_maps/message_deps.php9
-rw-r--r--vendor/swiftmailer/dependency_maps/mime_deps.php123
-rw-r--r--vendor/swiftmailer/dependency_maps/transport_deps.php76
-rw-r--r--vendor/swiftmailer/mime_types.php1007
-rw-r--r--vendor/swiftmailer/preferences.php35
-rw-r--r--vendor/swiftmailer/swift_init.php28
-rw-r--r--vendor/swiftmailer/swift_required.php30
-rw-r--r--vendor/swiftmailer/swift_required_pear.php30
-rwxr-xr-xvendor/swiftmailer/swiftmailer_generate_mimes_config.php201
240 files changed, 23403 insertions, 301 deletions
diff --git a/app/Controller/Base.php b/app/Controller/Base.php
index 7b1cfd85..11841e09 100644
--- a/app/Controller/Base.php
+++ b/app/Controller/Base.php
@@ -2,6 +2,7 @@
namespace Controller;
+use Core\Tool;
use Core\Registry;
use Core\Security;
use Core\Translator;
@@ -24,6 +25,7 @@ use Model\LastLogin;
* @property \Model\GitHub $gitHub
* @property \Model\LastLogin $lastLogin
* @property \Model\Ldap $ldap
+ * @property \Model\Notification $notification
* @property \Model\Project $project
* @property \Model\RememberMe $rememberMe
* @property \Model\ReverseProxyAuth $reverseProxyAuth
@@ -93,9 +95,7 @@ abstract class Base
*/
public function __get($name)
{
- $class = '\Model\\'.ucfirst($name);
- $this->registry->$name = new $class($this->registry->shared('db'), $this->registry->shared('event'));
- return $this->registry->shared($name);
+ return Tool::loadModel($this->registry, $name);
}
/**
@@ -157,6 +157,7 @@ abstract class Base
$this->action->attachEvents();
$this->project->attachEvents();
$this->webhook->attachEvents();
+ $this->notification->attachEvents();
}
/**
diff --git a/app/Controller/Board.php b/app/Controller/Board.php
index 14b1c02c..7fe9c4ae 100644
--- a/app/Controller/Board.php
+++ b/app/Controller/Board.php
@@ -373,7 +373,7 @@ class Board extends Base
}
if (isset($values['positions'])) {
- $this->board->saveTasksPosition($values['positions']);
+ $this->board->saveTasksPosition($values['positions'], $values['selected_task_id']);
}
$this->response->html(
diff --git a/app/Controller/Config.php b/app/Controller/Config.php
index daa57790..498f3214 100644
--- a/app/Controller/Config.php
+++ b/app/Controller/Config.php
@@ -20,7 +20,8 @@ class Config extends Base
$this->response->html($this->template->layout('config_index', array(
'db_size' => $this->config->getDatabaseSize(),
'user' => $_SESSION['user'],
- 'projects' => $this->project->getList(),
+ 'user_projects' => $this->project->getAvailableList($this->acl->getUserId()),
+ 'notifications' => $this->notification->readSettings($this->acl->getUserId()),
'languages' => $this->config->getLanguages(),
'values' => $this->config->getAll(),
'errors' => array(),
@@ -32,6 +33,13 @@ class Config extends Base
)));
}
+ public function notifications()
+ {
+ $values = $this->request->getValues();
+ $this->notification->saveSettings($this->acl->getUserId(), $values);
+ $this->response->redirect('?controller=config#notifications');
+ }
+
/**
* Validate and save settings
*
@@ -57,7 +65,8 @@ class Config extends Base
$this->response->html($this->template->layout('config_index', array(
'db_size' => $this->config->getDatabaseSize(),
'user' => $_SESSION['user'],
- 'projects' => $this->project->getList(),
+ 'user_projects' => $this->project->getAvailableList($this->acl->getUserId()),
+ 'notifications' => $this->notification->readSettings($this->acl->getUserId()),
'languages' => $this->config->getLanguages(),
'values' => $values,
'errors' => $errors,
diff --git a/app/Core/Tool.php b/app/Core/Tool.php
index ade99cad..1a2e9904 100644
--- a/app/Core/Tool.php
+++ b/app/Core/Tool.php
@@ -31,4 +31,11 @@ class Tool
fclose($fp);
}
}
+
+ public static function loadModel(Registry $registry, $name)
+ {
+ $class = '\Model\\'.ucfirst($name);
+ $registry->$name = new $class($registry);
+ return $registry->shared($name);
+ }
}
diff --git a/app/Event/BaseNotificationListener.php b/app/Event/BaseNotificationListener.php
new file mode 100644
index 00000000..6c1728cb
--- /dev/null
+++ b/app/Event/BaseNotificationListener.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Event;
+
+use Core\Listener;
+use Model\Notification;
+
+/**
+ * Base notification listener
+ *
+ * @package event
+ * @author Frederic Guillot
+ */
+abstract class BaseNotificationListener implements Listener
+{
+ /**
+ * Notification model
+ *
+ * @accesss protected
+ * @var Model\Notification
+ */
+ protected $notification;
+
+ /**
+ * Template name
+ *
+ * @accesss private
+ * @var string
+ */
+ private $template = '';
+
+ /**
+ * Fetch data for the mail template
+ *
+ * @access public
+ * @param array $data Event data
+ * @return array
+ */
+ abstract public function getTemplateData(array $data);
+
+ /**
+ * Constructor
+ *
+ * @access public
+ * @param \Model\Notification $notification Notification model instance
+ * @param string $template Template name
+ */
+ public function __construct(Notification $notification, $template)
+ {
+ $this->template = $template;
+ $this->notification = $notification;
+ }
+
+ /**
+ * Execute the action
+ *
+ * @access public
+ * @param array $data Event data dictionary
+ * @return bool True if the action was executed or false when not executed
+ */
+ public function execute(array $data)
+ {
+ $values = $this->getTemplateData($data);
+
+ // Get the list of users to be notified
+ $users = $this->notification->getUsersList($values['task']['project_id']);
+
+ // Send notifications
+ if ($users) {
+ $this->notification->sendEmails($this->template, $users, $values);
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/app/Event/CommentNotificationListener.php b/app/Event/CommentNotificationListener.php
new file mode 100644
index 00000000..3771ea7e
--- /dev/null
+++ b/app/Event/CommentNotificationListener.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Event;
+
+use Event\BaseNotificationListener;
+
+/**
+ * Comment notification listener
+ *
+ * @package event
+ * @author Frederic Guillot
+ */
+class CommentNotificationListener extends BaseNotificationListener
+{
+ /**
+ * Fetch data for the mail template
+ *
+ * @access public
+ * @param array $data Event data
+ * @return array
+ */
+ public function getTemplateData(array $data)
+ {
+ $values = array();
+ $values['comment'] = $this->notification->comment->getById($data['id']);
+ $values['task'] = $this->notification->task->getById($data['task_id'], true);
+
+ return $values;
+ }
+}
diff --git a/app/Event/FileNotificationListener.php b/app/Event/FileNotificationListener.php
new file mode 100644
index 00000000..98fc4260
--- /dev/null
+++ b/app/Event/FileNotificationListener.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Event;
+
+use Event\BaseNotificationListener;
+
+/**
+ * File notification listener
+ *
+ * @package event
+ * @author Frederic Guillot
+ */
+class FileNotificationListener extends BaseNotificationListener
+{
+ /**
+ * Fetch data for the mail template
+ *
+ * @access public
+ * @param array $data Event data
+ * @return array
+ */
+ public function getTemplateData(array $data)
+ {
+ $values = array();
+ $values['file'] = $data;
+ $values['task'] = $this->notification->task->getById($data['task_id'], true);
+
+ return $values;
+ }
+}
diff --git a/app/Event/SubTaskNotificationListener.php b/app/Event/SubTaskNotificationListener.php
new file mode 100644
index 00000000..0a239421
--- /dev/null
+++ b/app/Event/SubTaskNotificationListener.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Event;
+
+use Event\BaseNotificationListener;
+
+/**
+ * SubTask notification listener
+ *
+ * @package event
+ * @author Frederic Guillot
+ */
+class SubTaskNotificationListener extends BaseNotificationListener
+{
+ /**
+ * Fetch data for the mail template
+ *
+ * @access public
+ * @param array $data Event data
+ * @return array
+ */
+ public function getTemplateData(array $data)
+ {
+ $values = array();
+ $values['subtask'] = $this->notification->subtask->getById($data['id'], true);
+ $values['task'] = $this->notification->task->getById($data['task_id'], true);
+
+ return $values;
+ }
+}
diff --git a/app/Event/TaskNotificationListener.php b/app/Event/TaskNotificationListener.php
new file mode 100644
index 00000000..ffbe7a8c
--- /dev/null
+++ b/app/Event/TaskNotificationListener.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Event;
+
+use Event\BaseNotificationListener;
+
+/**
+ * Task notification listener
+ *
+ * @package event
+ * @author Frederic Guillot
+ */
+class TaskNotificationListener extends BaseNotificationListener
+{
+ /**
+ * Fetch data for the mail template
+ *
+ * @access public
+ * @param array $data Event data
+ * @return array
+ */
+ public function getTemplateData(array $data)
+ {
+ $values = array();
+ $values['task'] = $this->notification->task->getById($data['task_id'], true);
+
+ return $values;
+ }
+}
diff --git a/app/Locales/de_DE/translations.php b/app/Locales/de_DE/translations.php
index 73aed160..df5a359f 100644
--- a/app/Locales/de_DE/translations.php
+++ b/app/Locales/de_DE/translations.php
@@ -402,4 +402,31 @@ return array(
// 'Clone Project' => '',
// 'Project cloned successfully.' => '',
// 'Unable to clone this project.' => '',
+ // 'Email notifications' => '',
+ // 'Enable email notifications' => '',
+ // 'Task position:' => '',
+ // 'The task #%d have been opened.' => '',
+ // 'The task #%d have been closed.' => '',
+ // 'Sub-task updated' => '',
+ // 'Title:' => '',
+ // 'Status:' => '',
+ // 'Assignee:' => '',
+ // 'Time tracking:' => '',
+ // 'New sub-task' => '',
+ // 'New attachment added "%s"' => '',
+ // 'Comment updated' => '',
+ // 'New comment posted by %s' => '',
+ // 'List of due tasks for the project "%s"' => '',
+ // '[%s][New attachment] %s (#%d)' => '',
+ // '[%s][New comment] %s (#%d)' => '',
+ // '[%s][Comment updated] %s (#%d)' => '',
+ // '[%s][New subtask] %s (#%d)' => '',
+ // '[%s][Subtask updated] %s (#%d)' => '',
+ // '[%s][New task] %s (#%d)' => '',
+ // '[%s][Task updated] %s (#%d)' => '',
+ // '[%s][Task closed] %s (#%d)' => '',
+ // '[%s][Task opened] %s (#%d)' => '',
+ // '[%s][Due tasks]' => '',
+ // '[Kanboard] Notification' => '',
+ // 'I want to receive notifications only for those projects:' => '',
);
diff --git a/app/Locales/es_ES/translations.php b/app/Locales/es_ES/translations.php
index a8a8024c..b91e95c3 100644
--- a/app/Locales/es_ES/translations.php
+++ b/app/Locales/es_ES/translations.php
@@ -401,4 +401,31 @@ return array(
// 'Clone Project' => '',
// 'Project cloned successfully.' => '',
// 'Unable to clone this project.' => '',
+ // 'Email notifications' => '',
+ // 'Enable email notifications' => '',
+ // 'Task position:' => '',
+ // 'The task #%d have been opened.' => '',
+ // 'The task #%d have been closed.' => '',
+ // 'Sub-task updated' => '',
+ // 'Title:' => '',
+ // 'Status:' => '',
+ // 'Assignee:' => '',
+ // 'Time tracking:' => '',
+ // 'New sub-task' => '',
+ // 'New attachment added "%s"' => '',
+ // 'Comment updated' => '',
+ // 'New comment posted by %s' => '',
+ // 'List of due tasks for the project "%s"' => '',
+ // '[%s][New attachment] %s (#%d)' => '',
+ // '[%s][New comment] %s (#%d)' => '',
+ // '[%s][Comment updated] %s (#%d)' => '',
+ // '[%s][New subtask] %s (#%d)' => '',
+ // '[%s][Subtask updated] %s (#%d)' => '',
+ // '[%s][New task] %s (#%d)' => '',
+ // '[%s][Task updated] %s (#%d)' => '',
+ // '[%s][Task closed] %s (#%d)' => '',
+ // '[%s][Task opened] %s (#%d)' => '',
+ // '[%s][Due tasks]' => '',
+ // '[Kanboard] Notification' => '',
+ // 'I want to receive notifications only for those projects:' => '',
);
diff --git a/app/Locales/fi_FI/translations.php b/app/Locales/fi_FI/translations.php
index 801ec5c1..2b228960 100644
--- a/app/Locales/fi_FI/translations.php
+++ b/app/Locales/fi_FI/translations.php
@@ -401,4 +401,31 @@ return array(
// 'Clone Project' => '',
// 'Project cloned successfully.' => '',
// 'Unable to clone this project.' => '',
+ // 'Email notifications' => '',
+ // 'Enable email notifications' => '',
+ // 'Task position:' => '',
+ // 'The task #%d have been opened.' => '',
+ // 'The task #%d have been closed.' => '',
+ // 'Sub-task updated' => '',
+ // 'Title:' => '',
+ // 'Status:' => '',
+ // 'Assignee:' => '',
+ // 'Time tracking:' => '',
+ // 'New sub-task' => '',
+ // 'New attachment added "%s"' => '',
+ // 'Comment updated' => '',
+ // 'New comment posted by %s' => '',
+ // 'List of due tasks for the project "%s"' => '',
+ // '[%s][New attachment] %s (#%d)' => '',
+ // '[%s][New comment] %s (#%d)' => '',
+ // '[%s][Comment updated] %s (#%d)' => '',
+ // '[%s][New subtask] %s (#%d)' => '',
+ // '[%s][Subtask updated] %s (#%d)' => '',
+ // '[%s][New task] %s (#%d)' => '',
+ // '[%s][Task updated] %s (#%d)' => '',
+ // '[%s][Task closed] %s (#%d)' => '',
+ // '[%s][Task opened] %s (#%d)' => '',
+ // '[%s][Due tasks]' => '',
+ // '[Kanboard] Notification' => '',
+ // 'I want to receive notifications only for those projects:' => '',
);
diff --git a/app/Locales/fr_FR/translations.php b/app/Locales/fr_FR/translations.php
index 552060c5..4bb4359e 100644
--- a/app/Locales/fr_FR/translations.php
+++ b/app/Locales/fr_FR/translations.php
@@ -399,4 +399,31 @@ return array(
'Clone Project' => 'Cloner le projet',
'Project cloned successfully.' => 'Projet cloné avec succès.',
'Unable to clone this project.' => 'Impossible de cloner ce projet.',
+ 'Email notifications' => 'Notifications par email',
+ 'Enable email notifications' => 'Activer les notifications par emails',
+ 'Task position:' => 'Position de la tâche :',
+ 'The task #%d have been opened.' => 'La tâche #%d a été ouverte.',
+ 'The task #%d have been closed.' => 'La tâche #%d a été fermée.',
+ 'Sub-task updated' => 'Sous-tâche mise à jour',
+ 'Title:' => 'Titre :',
+ 'Status:' => 'État :',
+ 'Assignee:' => 'Assigné :',
+ 'Time tracking:' => 'Gestion du temps :',
+ 'New sub-task' => 'Nouvelle sous-tâche',
+ 'New attachment added "%s"' => 'Nouvelle pièce-jointe ajoutée « %s »',
+ 'Comment updated' => 'Commentaire ajouté',
+ 'New comment posted by %s' => 'Nouveau commentaire ajouté par « %s »',
+ 'List of due tasks for the project "%s"' => 'Liste des tâches expirées pour le projet « %s »',
+ '[%s][New attachment] %s (#%d)' => '[%s][Pièce-jointe] %s (#%d)',
+ '[%s][New comment] %s (#%d)' => '[%s][Nouveau commentaire] %s (#%d)',
+ '[%s][Comment updated] %s (#%d)' => '[%s][Commentaire mis à jour] %s (#%d)',
+ '[%s][New subtask] %s (#%d)' => '[%s][Nouvelle sous-tâche] %s (#%d)',
+ '[%s][Subtask updated] %s (#%d)' => '[%s][Sous-tâche mise à jour] %s (#%d)',
+ '[%s][New task] %s (#%d)' => '[%s][Nouvelle tâche] %s (#%d)',
+ '[%s][Task updated] %s (#%d)' => '[%s][Tâche mise à jour] %s (#%d)',
+ '[%s][Task closed] %s (#%d)' => '[%s][Tâche fermée] %s (#%d)',
+ '[%s][Task opened] %s (#%d)' => '[%s][Tâche ouverte] %s (#%d)',
+ '[%s][Due tasks]' => '[%s][Tâches expirées]',
+ '[Kanboard] Notification' => '[Kanboard] Notification',
+ 'I want to receive notifications only for those projects:' => 'Je souhaite reçevoir les notifications uniquement pour les projets sélectionnés :',
);
diff --git a/app/Locales/pl_PL/translations.php b/app/Locales/pl_PL/translations.php
index 41e7f80a..53d57974 100644
--- a/app/Locales/pl_PL/translations.php
+++ b/app/Locales/pl_PL/translations.php
@@ -402,4 +402,31 @@ return array(
// 'Clone Project' => '',
// 'Project cloned successfully.' => '',
// 'Unable to clone this project.' => '',
+ // 'Email notifications' => '',
+ // 'Enable email notifications' => '',
+ // 'Task position:' => '',
+ // 'The task #%d have been opened.' => '',
+ // 'The task #%d have been closed.' => '',
+ // 'Sub-task updated' => '',
+ // 'Title:' => '',
+ // 'Status:' => '',
+ // 'Assignee:' => '',
+ // 'Time tracking:' => '',
+ // 'New sub-task' => '',
+ // 'New attachment added "%s"' => '',
+ // 'Comment updated' => '',
+ // 'New comment posted by %s' => '',
+ // 'List of due tasks for the project "%s"' => '',
+ // '[%s][New attachment] %s (#%d)' => '',
+ // '[%s][New comment] %s (#%d)' => '',
+ // '[%s][Comment updated] %s (#%d)' => '',
+ // '[%s][New subtask] %s (#%d)' => '',
+ // '[%s][Subtask updated] %s (#%d)' => '',
+ // '[%s][New task] %s (#%d)' => '',
+ // '[%s][Task updated] %s (#%d)' => '',
+ // '[%s][Task closed] %s (#%d)' => '',
+ // '[%s][Task opened] %s (#%d)' => '',
+ // '[%s][Due tasks]' => '',
+ // '[Kanboard] Notification' => '',
+ // 'I want to receive notifications only for those projects:' => '',
);
diff --git a/app/Locales/pt_BR/translations.php b/app/Locales/pt_BR/translations.php
index 6ebb78c9..04117b50 100644
--- a/app/Locales/pt_BR/translations.php
+++ b/app/Locales/pt_BR/translations.php
@@ -404,4 +404,31 @@ return array(
'Clone Project' => 'Clonar Projeto',
'Project cloned successfully.' => 'Projeto clonado com sucesso.',
'Unable to clone this project.' => 'Impossível clonar este projeto.',
+ // 'Email notifications' => '',
+ // 'Enable email notifications' => '',
+ // 'Task position:' => '',
+ // 'The task #%d have been opened.' => '',
+ // 'The task #%d have been closed.' => '',
+ // 'Sub-task updated' => '',
+ // 'Title:' => '',
+ // 'Status:' => '',
+ // 'Assignee:' => '',
+ // 'Time tracking:' => '',
+ // 'New sub-task' => '',
+ // 'New attachment added "%s"' => '',
+ // 'Comment updated' => '',
+ // 'New comment posted by %s' => '',
+ // 'List of due tasks for the project "%s"' => '',
+ // '[%s][New attachment] %s (#%d)' => '',
+ // '[%s][New comment] %s (#%d)' => '',
+ // '[%s][Comment updated] %s (#%d)' => '',
+ // '[%s][New subtask] %s (#%d)' => '',
+ // '[%s][Subtask updated] %s (#%d)' => '',
+ // '[%s][New task] %s (#%d)' => '',
+ // '[%s][Task updated] %s (#%d)' => '',
+ // '[%s][Task closed] %s (#%d)' => '',
+ // '[%s][Task opened] %s (#%d)' => '',
+ // '[%s][Due tasks]' => '',
+ // '[Kanboard] Notification' => '',
+ // 'I want to receive notifications only for those projects:' => '',
);
diff --git a/app/Locales/sv_SE/translations.php b/app/Locales/sv_SE/translations.php
index 68248b72..dddccc2f 100644
--- a/app/Locales/sv_SE/translations.php
+++ b/app/Locales/sv_SE/translations.php
@@ -401,4 +401,31 @@ return array(
// 'Clone Project' => '',
// 'Project cloned successfully.' => '',
// 'Unable to clone this project.' => '',
+ // 'Email notifications' => '',
+ // 'Enable email notifications' => '',
+ // 'Task position:' => '',
+ // 'The task #%d have been opened.' => '',
+ // 'The task #%d have been closed.' => '',
+ // 'Sub-task updated' => '',
+ // 'Title:' => '',
+ // 'Status:' => '',
+ // 'Assignee:' => '',
+ // 'Time tracking:' => '',
+ // 'New sub-task' => '',
+ // 'New attachment added "%s"' => '',
+ // 'Comment updated' => '',
+ // 'New comment posted by %s' => '',
+ // 'List of due tasks for the project "%s"' => '',
+ // '[%s][New attachment] %s (#%d)' => '',
+ // '[%s][New comment] %s (#%d)' => '',
+ // '[%s][Comment updated] %s (#%d)' => '',
+ // '[%s][New subtask] %s (#%d)' => '',
+ // '[%s][Subtask updated] %s (#%d)' => '',
+ // '[%s][New task] %s (#%d)' => '',
+ // '[%s][Task updated] %s (#%d)' => '',
+ // '[%s][Task closed] %s (#%d)' => '',
+ // '[%s][Task opened] %s (#%d)' => '',
+ // '[%s][Due tasks]' => '',
+ // '[Kanboard] Notification' => '',
+ // 'I want to receive notifications only for those projects:' => '',
);
diff --git a/app/Locales/zh_CN/translations.php b/app/Locales/zh_CN/translations.php
index 1d759336..823075fe 100644
--- a/app/Locales/zh_CN/translations.php
+++ b/app/Locales/zh_CN/translations.php
@@ -407,4 +407,30 @@ return array(
// 'Clone Project' => '',
// 'Project cloned successfully.' => '',
// 'Unable to clone this project.' => '',
+ // 'Email notifications' => '',
+ // 'Enable email notifications' => '',
+ // 'Task position:' => '',
+ // 'The task #%d have been opened.' => '',
+ // 'The task #%d have been closed.' => '',
+ // 'Sub-task updated' => '',
+ // 'Title:' => '',
+ // 'Status:' => '',
+ // 'Assignee:' => '',
+ // 'Time tracking:' => '',
+ // 'New sub-task' => '',
+ // 'New attachment added "%s"' => '',
+ // 'Comment updated' => '',
+ // 'New comment posted by %s' => '',
+ // 'List of due tasks for the project "%s"' => '',
+ // '[%s][New attachment] %s (#%d)' => '',
+ // '[%s][New comment] %s (#%d)' => '',
+ // '[%s][Comment updated] %s (#%d)' => '',
+ // '[%s][New subtask] %s (#%d)' => '',
+ // '[%s][Subtask updated] %s (#%d)' => '',
+ // '[%s][New task] %s (#%d)' => '',
+ // '[%s][Task updated] %s (#%d)' => '',
+ // '[%s][Task closed] %s (#%d)' => '',
+ // '[%s][Task opened] %s (#%d)' => '',
+ // '[%s][Due tasks]' => '',
+ // '[Kanboard] Notification' => '',
);
diff --git a/app/Model/Acl.php b/app/Model/Acl.php
index 8a87a6b2..c4b31079 100644
--- a/app/Model/Acl.php
+++ b/app/Model/Acl.php
@@ -33,7 +33,7 @@ class Acl extends Base
'board' => array('index', 'show', 'assign', 'assigntask', 'save', 'check'),
'project' => array('tasks', 'index', 'forbidden', 'search'),
'user' => array('index', 'edit', 'update', 'forbidden', 'logout', 'index', 'unlinkgoogle', 'unlinkgithub'),
- 'config' => array('index', 'removeremembermetoken'),
+ 'config' => array('index', 'removeremembermetoken', 'notifications'),
'comment' => array('create', 'save', 'confirm', 'remove', 'update', 'edit', 'forbidden'),
'file' => array('create', 'save', 'download', 'confirm', 'remove', 'open', 'image'),
'subtask' => array('create', 'save', 'edit', 'update', 'confirm', 'remove'),
diff --git a/app/Model/Action.php b/app/Model/Action.php
index 25e72f58..effe8707 100644
--- a/app/Model/Action.php
+++ b/app/Model/Action.php
@@ -224,25 +224,25 @@ class Action extends Base
switch ($name) {
case 'TaskClose':
$className = '\Action\TaskClose';
- return new $className($project_id, new Task($this->db, $this->event));
+ return new $className($project_id, new Task($this->registry));
case 'TaskAssignCurrentUser':
$className = '\Action\TaskAssignCurrentUser';
- return new $className($project_id, new Task($this->db, $this->event), new Acl($this->db, $this->event));
+ return new $className($project_id, new Task($this->registry), new Acl($this->registry));
case 'TaskAssignSpecificUser':
$className = '\Action\TaskAssignSpecificUser';
- return new $className($project_id, new Task($this->db, $this->event));
+ return new $className($project_id, new Task($this->registry));
case 'TaskDuplicateAnotherProject':
$className = '\Action\TaskDuplicateAnotherProject';
- return new $className($project_id, new Task($this->db, $this->event));
+ return new $className($project_id, new Task($this->registry));
case 'TaskAssignColorUser':
$className = '\Action\TaskAssignColorUser';
- return new $className($project_id, new Task($this->db, $this->event));
+ return new $className($project_id, new Task($this->registry));
case 'TaskAssignColorCategory':
$className = '\Action\TaskAssignColorCategory';
- return new $className($project_id, new Task($this->db, $this->event));
+ return new $className($project_id, new Task($this->registry));
case 'TaskAssignCategoryColor':
$className = '\Action\TaskAssignCategoryColor';
- return new $className($project_id, new Task($this->db, $this->event));
+ return new $className($project_id, new Task($this->registry));
default:
throw new LogicException('Action not found: '.$name);
}
diff --git a/app/Model/Base.php b/app/Model/Base.php
index 66185aeb..92578ffc 100644
--- a/app/Model/Base.php
+++ b/app/Model/Base.php
@@ -17,6 +17,8 @@ require __DIR__.'/../../vendor/SimpleValidator/Validators/Email.php';
require __DIR__.'/../../vendor/SimpleValidator/Validators/Numeric.php';
use Core\Event;
+use Core\Tool;
+use Core\Registry;
use PicoDb\Database;
/**
@@ -24,6 +26,21 @@ use PicoDb\Database;
*
* @package model
* @author Frederic Guillot
+ *
+ * @property \Model\Acl $acl
+ * @property \Model\Action $action
+ * @property \Model\Board $board
+ * @property \Model\Category $category
+ * @property \Model\Comment $comment
+ * @property \Model\Config $config
+ * @property \Model\File $file
+ * @property \Model\LastLogin $lastLogin
+ * @property \Model\Ldap $ldap
+ * @property \Model\Notification $notification
+ * @property \Model\Project $project
+ * @property \Model\SubTask $subTask
+ * @property \Model\Task $task
+ * @property \Model\User $user
*/
abstract class Base
{
@@ -44,15 +61,35 @@ abstract class Base
protected $event;
/**
+ * Registry instance
+ *
+ * @access protected
+ * @var \Core\Registry
+ */
+ protected $registry;
+
+ /**
* Constructor
*
* @access public
- * @param \PicoDb\Database $db Database instance
- * @param \Core\Event $event Event dispatcher instance
+ * @param \Core\Registry $registry Registry instance
+ */
+ public function __construct(Registry $registry)
+ {
+ $this->registry = $registry;
+ $this->db = $this->registry->shared('db');
+ $this->event = $this->registry->shared('event');
+ }
+
+ /**
+ * Load automatically models
+ *
+ * @access public
+ * @param string $name Model name
+ * @return mixed
*/
- public function __construct(Database $db, Event $event)
+ public function __get($name)
{
- $this->db = $db;
- $this->event = $event;
+ return Tool::loadModel($this->registry, $name);
}
}
diff --git a/app/Model/Board.php b/app/Model/Board.php
index a4e0a345..168b185f 100644
--- a/app/Model/Board.php
+++ b/app/Model/Board.php
@@ -24,17 +24,18 @@ class Board extends Base
* Save task positions for each column
*
* @access public
- * @param array $values [['task_id' => X, 'column_id' => X, 'position' => X], ...]
+ * @param array $positions [['task_id' => X, 'column_id' => X, 'position' => X], ...]
+ * @param integer $selected_task_id The selected task id
* @return boolean
*/
- public function saveTasksPosition(array $values)
+ public function saveTasksPosition(array $positions, $selected_task_id)
{
- $taskModel = new Task($this->db, $this->event);
-
$this->db->startTransaction();
- foreach ($values as $value) {
- if (! $taskModel->move($value['task_id'], $value['column_id'], $value['position'])) {
+ foreach ($positions as $value) {
+
+ // We trigger events only for the selected task
+ if (! $this->task->move($value['task_id'], $value['column_id'], $value['position'], $value['task_id'] == $selected_task_id)) {
$this->db->cancelTransaction();
return false;
}
@@ -201,8 +202,7 @@ class Board extends Base
$filters[] = array('column' => 'project_id', 'operator' => 'eq', 'value' => $project_id);
$filters[] = array('column' => 'is_active', 'operator' => 'eq', 'value' => Task::STATUS_OPEN);
- $taskModel = new Task($this->db, $this->event);
- $tasks = $taskModel->find($filters);
+ $tasks = $this->task->find($filters);
foreach ($columns as &$column) {
diff --git a/app/Model/Comment.php b/app/Model/Comment.php
index b5102070..b849fc23 100644
--- a/app/Model/Comment.php
+++ b/app/Model/Comment.php
@@ -21,6 +21,14 @@ class Comment extends Base
const TABLE = 'comments';
/**
+ * Events
+ *
+ * @var string
+ */
+ const EVENT_UPDATE = 'comment.update';
+ const EVENT_CREATE = 'comment.create';
+
+ /**
* Get all comments for a given task
*
* @access public
@@ -95,7 +103,14 @@ class Comment extends Base
{
$values['date'] = time();
- return $this->db->table(self::TABLE)->save($values);
+ if ($this->db->table(self::TABLE)->save($values)) {
+
+ $values['id'] = $this->db->getConnection()->getLastId();
+ $this->event->trigger(self::EVENT_CREATE, $values);
+ return true;
+ }
+
+ return false;
}
/**
@@ -107,10 +122,14 @@ class Comment extends Base
*/
public function update(array $values)
{
- return $this->db
+ $result = $this->db
->table(self::TABLE)
->eq('id', $values['id'])
->update(array('comment' => $values['comment']));
+
+ $this->event->trigger(self::EVENT_UPDATE, $values);
+
+ return $result;
}
/**
diff --git a/app/Model/File.php b/app/Model/File.php
index 2a793217..d5a0c7cd 100644
--- a/app/Model/File.php
+++ b/app/Model/File.php
@@ -25,6 +25,13 @@ class File extends Base
const BASE_PATH = 'data/files/';
/**
+ * Events
+ *
+ * @var string
+ */
+ const EVENT_CREATE = 'file.create';
+
+ /**
* Get a file by the id
*
* @access public
@@ -82,6 +89,8 @@ class File extends Base
*/
public function create($task_id, $name, $path, $is_image)
{
+ $this->event->trigger(self::EVENT_CREATE, array('task_id' => $task_id, 'name' => $name));
+
return $this->db->table(self::TABLE)->save(array(
'task_id' => $task_id,
'name' => $name,
diff --git a/app/Model/GitHub.php b/app/Model/GitHub.php
index 3380218d..bf4f4c51 100644
--- a/app/Model/GitHub.php
+++ b/app/Model/GitHub.php
@@ -26,22 +26,19 @@ class GitHub extends Base
*/
public function authenticate($github_id)
{
- $userModel = new User($this->db, $this->event);
-
- $user = $userModel->getByGitHubId($github_id);
+ $user = $this->user->getByGitHubId($github_id);
if ($user) {
// Create the user session
- $userModel->updateSession($user);
+ $this->user->updateSession($user);
// Update login history
- $lastLogin = new LastLogin($this->db, $this->event);
- $lastLogin->create(
+ $this->lastLogin->create(
LastLogin::AUTH_GITHUB,
$user['id'],
- $userModel->getIpAddress(),
- $userModel->getUserAgent()
+ $this->user->getIpAddress(),
+ $this->user->getUserAgent()
);
return true;
@@ -59,9 +56,7 @@ class GitHub extends Base
*/
public function unlink($user_id)
{
- $userModel = new User($this->db, $this->event);
-
- return $userModel->update(array(
+ return $this->user->update(array(
'id' => $user_id,
'github_id' => '',
));
@@ -78,9 +73,7 @@ class GitHub extends Base
*/
public function updateUser($user_id, array $profile)
{
- $userModel = new User($this->db, $this->event);
-
- return $userModel->update(array(
+ return $this->user->update(array(
'id' => $user_id,
'github_id' => $profile['id'],
'email' => $profile['email'],
@@ -141,7 +134,7 @@ class GitHub extends Base
try {
$gitHubService = $this->getService();
$gitHubService->requestAccessToken($code);
-
+
return json_decode($gitHubService->request('user'), true);
}
catch (TokenResponseException $e) {
@@ -150,7 +143,7 @@ class GitHub extends Base
return false;
}
-
+
/**
* Revokes this user's GitHub tokens for Kanboard
*
diff --git a/app/Model/Google.php b/app/Model/Google.php
index f5beb8f8..cca4f668 100644
--- a/app/Model/Google.php
+++ b/app/Model/Google.php
@@ -27,21 +27,19 @@ class Google extends Base
*/
public function authenticate($google_id)
{
- $userModel = new User($this->db, $this->event);
- $user = $userModel->getByGoogleId($google_id);
+ $user = $this->user->getByGoogleId($google_id);
if ($user) {
// Create the user session
- $userModel->updateSession($user);
+ $this->user->updateSession($user);
// Update login history
- $lastLogin = new LastLogin($this->db, $this->event);
- $lastLogin->create(
+ $this->lastLogin->create(
LastLogin::AUTH_GOOGLE,
$user['id'],
- $userModel->getIpAddress(),
- $userModel->getUserAgent()
+ $this->user->getIpAddress(),
+ $this->user->getUserAgent()
);
return true;
@@ -59,9 +57,7 @@ class Google extends Base
*/
public function unlink($user_id)
{
- $userModel = new User($this->db, $this->event);
-
- return $userModel->update(array(
+ return $this->user->update(array(
'id' => $user_id,
'google_id' => '',
));
@@ -77,9 +73,7 @@ class Google extends Base
*/
public function updateUser($user_id, array $profile)
{
- $userModel = new User($this->db, $this->event);
-
- return $userModel->update(array(
+ return $this->user->update(array(
'id' => $user_id,
'google_id' => $profile['id'],
'email' => $profile['email'],
diff --git a/app/Model/Ldap.php b/app/Model/Ldap.php
index dabcd5ff..007f7171 100644
--- a/app/Model/Ldap.php
+++ b/app/Model/Ldap.php
@@ -73,8 +73,7 @@ class Ldap extends Base
*/
public function create($username, $name, $email)
{
- $userModel = new User($this->db, $this->event);
- $user = $userModel->getByUsername($username);
+ $user = $this->user->getByUsername($username);
// There is an existing user account
if ($user) {
diff --git a/app/Model/Notification.php b/app/Model/Notification.php
new file mode 100644
index 00000000..e0f932a4
--- /dev/null
+++ b/app/Model/Notification.php
@@ -0,0 +1,215 @@
+<?php
+
+namespace Model;
+
+use Core\Template;
+use Event\TaskNotificationListener;
+use Event\CommentNotificationListener;
+use Event\FileNotificationListener;
+use Event\SubTaskNotificationListener;
+use Swift_Message;
+use Swift_Mailer;
+
+/**
+ * Notification model
+ *
+ * @package model
+ * @author Frederic Guillot
+ */
+class Notification extends Base
+{
+ /**
+ * SQL table name
+ *
+ * @var string
+ */
+ const TABLE = 'user_has_notifications';
+
+ /**
+ * Get the list of users to send the notification for a given project
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @return array
+ */
+ public function getUsersList($project_id)
+ {
+ $users = $this->db->table(User::TABLE)
+ ->columns('id', 'username', 'name', 'email')
+ ->eq('notifications_enabled', '1')
+ ->neq('email', '')
+ ->findAll();
+
+ foreach ($users as $index => $user) {
+
+ $projects = $this->db->table(self::TABLE)
+ ->eq('user_id', $user['id'])
+ ->findAllByColumn('project_id');
+
+ // The user have selected only some projects
+ if (! empty($projects)) {
+
+ // If the user didn't select this project we remove that guy from the list
+ if (! in_array($project_id, $projects)) {
+ unset($users[$index]);
+ }
+ }
+ }
+
+ return $users;
+ }
+
+ /**
+ * Attach events
+ *
+ * @access public
+ */
+ public function attachEvents()
+ {
+ $this->event->attach(File::EVENT_CREATE, new FileNotificationListener($this, 'notification_file_creation'));
+
+ $this->event->attach(Comment::EVENT_CREATE, new CommentNotificationListener($this, 'notification_comment_creation'));
+ $this->event->attach(Comment::EVENT_UPDATE, new CommentNotificationListener($this, 'notification_comment_update'));
+
+ $this->event->attach(SubTask::EVENT_CREATE, new SubTaskNotificationListener($this, 'notification_subtask_creation'));
+ $this->event->attach(SubTask::EVENT_UPDATE, new SubTaskNotificationListener($this, 'notification_subtask_update'));
+
+ $this->event->attach(Task::EVENT_CREATE, new TaskNotificationListener($this, 'notification_task_creation'));
+ $this->event->attach(Task::EVENT_UPDATE, new TaskNotificationListener($this, 'notification_task_update'));
+ $this->event->attach(Task::EVENT_CLOSE, new TaskNotificationListener($this, 'notification_task_close'));
+ $this->event->attach(Task::EVENT_OPEN, new TaskNotificationListener($this, 'notification_task_open'));
+ }
+
+ /**
+ * Send the email notifications
+ *
+ * @access public
+ * @param string $template Template name
+ * @param array $users List of users
+ * @param array $data Template data
+ */
+ public function sendEmails($template, array $users, array $data)
+ {
+ $transport = $this->registry->shared('mailer');
+ $mailer = Swift_Mailer::newInstance($transport);
+
+ $message = Swift_Message::newInstance()
+ ->setSubject($this->getMailSubject($template, $data))
+ ->setFrom(array(MAIL_FROM => 'Kanboard'))
+ //->setTo(array($user['email'] => $user['name']))
+ ->setBody($this->getMailContent($template, $data), 'text/html');
+
+ foreach ($users as $user) {
+ $message->setTo(array($user['email'] => $user['name'] ?: $user['username']));
+ $mailer->send($message);
+ }
+ }
+
+ /**
+ * Get the mail subject for a given template name
+ *
+ * @access public
+ * @param string $template Template name
+ * @param array $data Template data
+ */
+ public function getMailSubject($template, array $data)
+ {
+ switch ($template) {
+ case 'notification_file_creation':
+ return t('[%s][New attachment] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
+ case 'notification_comment_creation':
+ return t('[%s][New comment] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
+ case 'notification_comment_update':
+ return t('[%s][Comment updated] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
+ case 'notification_subtask_creation':
+ return t('[%s][New subtask] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
+ case 'notification_subtask_update':
+ return t('[%s][Subtask updated] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
+ case 'notification_task_creation':
+ return t('[%s][New task] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
+ case 'notification_task_update':
+ return t('[%s][Task updated] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
+ case 'notification_task_close':
+ return t('[%s][Task closed] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
+ case 'notification_task_open':
+ return t('[%s][Task opened] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']);
+ case 'notification_task_due':
+ return t('[%s][Due tasks]', $data['project']);
+ }
+
+ return t('[Kanboard] Notification');
+ }
+
+ /**
+ * Get the mail content for a given template name
+ *
+ * @access public
+ * @param string $template Template name
+ * @param array $data Template data
+ */
+ public function getMailContent($template, array $data)
+ {
+ $tpl = new Template;
+ return $tpl->load($template, $data);
+ }
+
+ /**
+ * Save settings for the given user
+ *
+ * @access public
+ * @param integer $user_id User id
+ * @param array $values Form values
+ */
+ public function saveSettings($user_id, array $values)
+ {
+ // Delete all selected projects
+ $this->db->table(self::TABLE)->eq('user_id', $user_id)->remove();
+
+ if (isset($values['notifications_enabled']) && $values['notifications_enabled'] == 1) {
+
+ // Activate notifications
+ $this->db->table(User::TABLE)->eq('id', $user_id)->update(array(
+ 'notifications_enabled' => '1'
+ ));
+
+ // Save selected projects
+ if (! empty($values['projects'])) {
+
+ foreach ($values['projects'] as $project_id => $checkbox_value) {
+ $this->db->table(self::TABLE)->insert(array(
+ 'user_id' => $user_id,
+ 'project_id' => $project_id,
+ ));
+ }
+ }
+ }
+ else {
+
+ // Disable notifications
+ $this->db->table(User::TABLE)->eq('id', $user_id)->update(array(
+ 'notifications_enabled' => '0'
+ ));
+ }
+ }
+
+ /**
+ * Read user settings to display the form
+ *
+ * @access public
+ * @param integer $user_id User id
+ * @return array
+ */
+ public function readSettings($user_id)
+ {
+ $values = array();
+ $values['notifications_enabled'] = $this->db->table(User::TABLE)->eq('id', $user_id)->findOneColumn('notifications_enabled');
+
+ $projects = $this->db->table(self::TABLE)->eq('user_id', $user_id)->findAllByColumn('project_id');
+
+ foreach ($projects as $project_id) {
+ $values['project_'.$project_id] = true;
+ }
+
+ return $values;
+ }
+}
diff --git a/app/Model/Project.php b/app/Model/Project.php
index f598c96f..63458fa3 100644
--- a/app/Model/Project.php
+++ b/app/Model/Project.php
@@ -55,10 +55,9 @@ class Project extends Base
public function getUsersList($project_id, $prepend_unassigned = true, $prepend_everybody = false)
{
$allowed_users = $this->getAllowedUsers($project_id);
- $userModel = new User($this->db, $this->event);
if (empty($allowed_users)) {
- $allowed_users = $userModel->getList();
+ $allowed_users = $this->user->getList();
}
if ($prepend_unassigned) {
@@ -103,8 +102,7 @@ class Project extends Base
'not_allowed' => array(),
);
- $userModel = new User($this->db, $this->event);
- $all_users = $userModel->getList();
+ $all_users = $this->user->getList();
$users['allowed'] = $this->getAllowedUsers($project_id);
@@ -253,27 +251,23 @@ class Project extends Base
->asc('name')
->findAll();
- $boardModel = new Board($this->db, $this->event);
- $taskModel = new Task($this->db, $this->event);
- $aclModel = new Acl($this->db, $this->event);
-
foreach ($projects as $pkey => &$project) {
- if ($check_permissions && ! $this->isUserAllowed($project['id'], $aclModel->getUserId())) {
+ if ($check_permissions && ! $this->isUserAllowed($project['id'], $this->acl->getUserId())) {
unset($projects[$pkey]);
}
else {
- $columns = $boardModel->getcolumns($project['id']);
+ $columns = $this->board->getcolumns($project['id']);
$project['nb_active_tasks'] = 0;
foreach ($columns as &$column) {
- $column['nb_active_tasks'] = $taskModel->countByColumnId($project['id'], $column['id']);
+ $column['nb_active_tasks'] = $this->task->countByColumnId($project['id'], $column['id']);
$project['nb_active_tasks'] += $column['nb_active_tasks'];
}
$project['columns'] = $columns;
- $project['nb_tasks'] = $taskModel->countByProjectId($project['id']);
+ $project['nb_tasks'] = $this->task->countByProjectId($project['id']);
$project['nb_inactive_tasks'] = $project['nb_tasks'] - $project['nb_active_tasks'];
}
}
@@ -416,9 +410,8 @@ class Project extends Base
*/
public function copyBoardFromAnotherProject($project_from, $project_to)
{
- $boardModel = new Board($this->db, $this->event);
$columns = $this->db->table(Board::TABLE)->eq('project_id', $project_from)->asc('position')->findAllByColumn('title');
- return $boardModel->create($project_to, $columns);
+ return $this->board->create($project_to, $columns);
}
/**
@@ -431,8 +424,7 @@ class Project extends Base
*/
public function copyCategoriesFromAnotherProject($project_from, $project_to)
{
- $categoryModel = new Category($this->db, $this->event);
- $categoriesTemplate = $categoryModel->getAll($project_from);
+ $categoriesTemplate = $this->category->getAll($project_from);
foreach ($categoriesTemplate as $category) {
@@ -478,8 +470,7 @@ class Project extends Base
*/
public function copyActionsFromAnotherProject($project_from, $project_to)
{
- $actionModel = new Action($this->db, $this->event);
- $actionTemplate = $actionModel->getAllByProject($project_from);
+ $actionTemplate = $this->action->getAllByProject($project_from);
foreach ($actionTemplate as $action) {
@@ -522,13 +513,11 @@ class Project extends Base
case 'project_id':
return $project_to;
case 'category_id':
- $categoryModel = new Category($this->db, $this->event);
- $categoryTemplate = $categoryModel->getById($param['value']);
+ $categoryTemplate = $this->category->getById($param['value']);
$categoryFromNewProject = $this->db->table(Category::TABLE)->eq('project_id', $project_to)->eq('name', $categoryTemplate['name'])->findOne();
return $categoryFromNewProject['id'];
case 'column_id':
- $boardModel = new Board($this->db, $this->event);
- $boardTemplate = $boardModel->getColumn($param['value']);
+ $boardTemplate = $this->board->getColumn($param['value']);
$boardFromNewProject = $this->db->table(Board::TABLE)->eq('project_id', $project_to)->eq('title', $boardTemplate['title'])->findOne();
return $boardFromNewProject['id'];
default:
@@ -603,8 +592,7 @@ class Project extends Base
$project_id = $this->db->getConnection()->getLastId();
- $boardModel = new Board($this->db, $this->event);
- $boardModel->create($project_id, array(
+ $this->board->create($project_id, array(
t('Backlog'),
t('Ready'),
t('Work in progress'),
diff --git a/app/Model/RememberMe.php b/app/Model/RememberMe.php
index 272b4916..e23ed887 100644
--- a/app/Model/RememberMe.php
+++ b/app/Model/RememberMe.php
@@ -92,11 +92,8 @@ class RememberMe extends Base
);
// Create the session
- $user = new User($this->db, $this->event);
- $acl = new Acl($this->db, $this->event);
-
- $user->updateSession($user->getById($record['user_id']));
- $acl->isRememberMe(true);
+ $this->user->updateSession($this->user->getById($record['user_id']));
+ $this->acl->isRememberMe(true);
return true;
}
diff --git a/app/Model/ReverseProxyAuth.php b/app/Model/ReverseProxyAuth.php
index 1b9ed06c..14d18ba3 100644
--- a/app/Model/ReverseProxyAuth.php
+++ b/app/Model/ReverseProxyAuth.php
@@ -23,24 +23,22 @@ class ReverseProxyAuth extends Base
if (isset($_SERVER[REVERSE_PROXY_USER_HEADER])) {
$login = $_SERVER[REVERSE_PROXY_USER_HEADER];
- $userModel = new User($this->db, $this->event);
- $user = $userModel->getByUsername($login);
+ $user = $this->user->getByUsername($login);
if (! $user) {
$this->createUser($login);
- $user = $userModel->getByUsername($login);
+ $user = $this->user->getByUsername($login);
}
// Create the user session
- $userModel->updateSession($user);
+ $this->user->updateSession($user);
// Update login history
- $lastLogin = new LastLogin($this->db, $this->event);
- $lastLogin->create(
+ $this->lastLogin->create(
LastLogin::AUTH_REVERSE_PROXY,
$user['id'],
- $userModel->getIpAddress(),
- $userModel->getUserAgent()
+ $this->user->getIpAddress(),
+ $this->user->getUserAgent()
);
return true;
@@ -58,9 +56,7 @@ class ReverseProxyAuth extends Base
*/
private function createUser($login)
{
- $userModel = new User($this->db, $this->event);
-
- return $userModel->create(array(
+ return $this->user->create(array(
'email' => strpos($login, '@') !== false ? $login : '',
'username' => $login,
'is_admin' => REVERSE_PROXY_DEFAULT_ADMIN === $login,
diff --git a/app/Model/SubTask.php b/app/Model/SubTask.php
index 21ccdaac..c7bab44b 100644
--- a/app/Model/SubTask.php
+++ b/app/Model/SubTask.php
@@ -42,6 +42,14 @@ class SubTask extends Base
const STATUS_TODO = 0;
/**
+ * Events
+ *
+ * @var string
+ */
+ const EVENT_UPDATE = 'subtask.update';
+ const EVENT_CREATE = 'subtask.create';
+
+ /**
* Get available status
*
* @access public
@@ -88,10 +96,27 @@ class SubTask extends Base
*
* @access public
* @param integer $subtask_id Subtask id
+ * @param bool $more Fetch more data
* @return array
*/
- public function getById($subtask_id)
+ public function getById($subtask_id, $more = false)
{
+ if ($more) {
+
+ $subtask = $this->db->table(self::TABLE)
+ ->eq(self::TABLE.'.id', $subtask_id)
+ ->columns(self::TABLE.'.*', User::TABLE.'.username', User::TABLE.'.name')
+ ->join(User::TABLE, 'id', 'user_id')
+ ->findOne();
+
+ if ($subtask) {
+ $status = $this->getStatusList();
+ $subtask['status_name'] = $status[$subtask['status']];
+ }
+
+ return $subtask;
+ }
+
return $this->db->table(self::TABLE)->eq('id', $subtask_id)->findOne();
}
@@ -116,7 +141,14 @@ class SubTask extends Base
$values['time_spent'] = 0;
}
- return $this->db->table(self::TABLE)->save($values);
+ $result = $this->db->table(self::TABLE)->save($values);
+
+ if ($result) {
+ $values['id'] = $this->db->getConnection()->getLastId();
+ $this->event->trigger(self::EVENT_CREATE, $values);
+ }
+
+ return $result;
}
/**
@@ -136,7 +168,13 @@ class SubTask extends Base
$values['time_spent'] = 0;
}
- return $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values);
+ $result = $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values);
+
+ if ($result) {
+ $this->event->trigger(self::EVENT_UPDATE, $values);
+ }
+
+ return $result;
}
/**
diff --git a/app/Model/Task.php b/app/Model/Task.php
index 0b2b9cf9..6647f041 100644
--- a/app/Model/Task.php
+++ b/app/Model/Task.php
@@ -63,6 +63,35 @@ class Task extends Base
}
/**
+ * Get a list of due tasks for all projects
+ *
+ * @access public
+ * @return array
+ */
+ public function getTasksDue()
+ {
+ $tasks = $this->db->table(self::TABLE)
+ ->columns(
+ self::TABLE.'.id',
+ self::TABLE.'.title',
+ self::TABLE.'.date_due',
+ self::TABLE.'.project_id',
+ Project::TABLE.'.name AS project_name',
+ User::TABLE.'.username AS assignee_username',
+ User::TABLE.'.name AS assignee_name'
+ )
+ ->join(Project::TABLE, 'id', 'project_id')
+ ->join(User::TABLE, 'id', 'owner_id')
+ ->eq(Project::TABLE.'.is_active', 1)
+ ->eq(self::TABLE.'.is_active', 1)
+ ->neq(self::TABLE.'.date_due', '')
+ ->lte(self::TABLE.'.date_due', mktime(23, 59, 59))
+ ->findAll();
+
+ return $tasks;
+ }
+
+ /**
* Fetch one task
*
* @access public
@@ -182,7 +211,7 @@ class Task extends Base
'tasks.category_id',
'users.username'
)
- ->join('users', 'id', 'owner_id');
+ ->join(User::TABLE, 'id', 'owner_id');
foreach ($filters as $key => $filter) {
@@ -282,8 +311,6 @@ class Task extends Base
{
$this->db->startTransaction();
- $boardModel = new Board($this->db, $this->event);
-
// Get the original task
$task = $this->getById($task_id);
@@ -296,7 +323,7 @@ class Task extends Base
$task['owner_id'] = 0;
$task['category_id'] = 0;
$task['is_active'] = 1;
- $task['column_id'] = $boardModel->getFirstColumn($project_id);
+ $task['column_id'] = $this->board->getFirstColumn($project_id);
$task['project_id'] = $project_id;
$task['position'] = $this->countByColumnId($task['project_id'], $task['column_id']);
@@ -318,17 +345,13 @@ class Task extends Base
}
/**
- * Create a task
+ * Prepare data before task creation or modification
*
* @access public
- * @param array $values Form values
- * @return boolean
+ * @param array $values Form values
*/
- public function create(array $values)
+ public function prepare(array &$values)
{
- $this->db->startTransaction();
-
- // Prepare data
if (isset($values['another_task'])) {
unset($values['another_task']);
}
@@ -336,14 +359,30 @@ class Task extends Base
if (! empty($values['date_due']) && ! is_numeric($values['date_due'])) {
$values['date_due'] = $this->parseDate($values['date_due']);
}
- else {
+
+ // Force integer fields at 0 (for Postgresql)
+ if (isset($values['date_due']) && empty($values['date_due'])) {
$values['date_due'] = 0;
}
- if (empty($values['score'])) {
+ if (isset($values['score']) && empty($values['score'])) {
$values['score'] = 0;
}
+ }
+ /**
+ * Create a task
+ *
+ * @access public
+ * @param array $values Form values
+ * @return boolean
+ */
+ public function create(array $values)
+ {
+ $this->db->startTransaction();
+
+ // Prepare data
+ $this->prepare($values);
$values['date_creation'] = time();
$values['position'] = $this->countByColumnId($values['project_id'], $values['column_id']);
@@ -368,31 +407,21 @@ class Task extends Base
* Update a task
*
* @access public
- * @param array $values Form values
+ * @param array $values Form values
+ * @param boolean $trigger_events Flag to trigger events
* @return boolean
*/
- public function update(array $values)
+ public function update(array $values, $trigger_events = true)
{
- // Prepare data
- if (! empty($values['date_due']) && ! is_numeric($values['date_due'])) {
- $values['date_due'] = $this->parseDate($values['date_due']);
- }
-
- // Force integer fields at 0 (for Postgresql)
- if (isset($values['date_due']) && empty($values['date_due'])) {
- $values['date_due'] = 0;
- }
-
- if (isset($values['score']) && empty($values['score'])) {
- $values['score'] = 0;
- }
-
+ // Fetch original task
$original_task = $this->getById($values['id']);
if ($original_task === false) {
return false;
}
+ // Prepare data
+ $this->prepare($values);
$updated_task = $values;
$updated_task['date_modification'] = time();
unset($updated_task['id']);
@@ -400,29 +429,40 @@ class Task extends Base
$result = $this->db->table(self::TABLE)->eq('id', $values['id'])->update($updated_task);
// Trigger events
- if ($result) {
-
- $events = array(
- self::EVENT_CREATE_UPDATE,
- self::EVENT_UPDATE,
- );
+ if ($result && $trigger_events) {
+ $this->triggerUpdateEvents($original_task, $updated_task);
+ }
- if (isset($values['column_id']) && $original_task['column_id'] != $values['column_id']) {
- $events[] = self::EVENT_MOVE_COLUMN;
- }
- else if (isset($values['position']) && $original_task['position'] != $values['position']) {
- $events[] = self::EVENT_MOVE_POSITION;
- }
+ return $result;
+ }
- $event_data = array_merge($original_task, $values);
- $event_data['task_id'] = $original_task['id'];
+ /**
+ * Trigger events for task modification
+ *
+ * @access public
+ * @param array $original_task Original task data
+ * @param array $updated_task Updated task data
+ */
+ public function triggerUpdateEvents(array $original_task, array $updated_task)
+ {
+ $events = array(
+ self::EVENT_CREATE_UPDATE,
+ self::EVENT_UPDATE,
+ );
- foreach ($events as $event) {
- $this->event->trigger($event, $event_data);
- }
+ if (isset($updated_task['column_id']) && $original_task['column_id'] != $updated_task['column_id']) {
+ $events[] = self::EVENT_MOVE_COLUMN;
+ }
+ else if (isset($updated_task['position']) && $original_task['position'] != $updated_task['position']) {
+ $events[] = self::EVENT_MOVE_POSITION;
}
- return $result;
+ $event_data = array_merge($original_task, $updated_task);
+ $event_data['task_id'] = $original_task['id'];
+
+ foreach ($events as $event) {
+ $this->event->trigger($event, $event_data);
+ }
}
/**
@@ -482,8 +522,7 @@ class Task extends Base
*/
public function remove($task_id)
{
- $file = new File($this->db, $this->event);
- $file->removeAll($task_id);
+ $this->file->removeAll($task_id);
return $this->db->table(self::TABLE)->eq('id', $task_id)->remove();
}
@@ -492,20 +531,23 @@ class Task extends Base
* Move a task to another column or to another position
*
* @access public
- * @param integer $task_id Task id
- * @param integer $column_id Column id
- * @param integer $position Position (must be greater than 1)
+ * @param integer $task_id Task id
+ * @param integer $column_id Column id
+ * @param integer $position Position (must be greater than 1)
+ * @param boolean $trigger_events Flag to trigger events
* @return boolean
*/
- public function move($task_id, $column_id, $position)
+ public function move($task_id, $column_id, $position, $trigger_events = true)
{
$this->event->clearTriggeredEvents();
- return $this->update(array(
+ $values = array(
'id' => $task_id,
'column_id' => $column_id,
'position' => $position,
- ));
+ );
+
+ return $this->update($values, $trigger_events);
}
/**
diff --git a/app/Model/User.php b/app/Model/User.php
index b5744c44..d0e33fd0 100644
--- a/app/Model/User.php
+++ b/app/Model/User.php
@@ -340,8 +340,7 @@ class User extends Base
$this->updateSession($user);
// Update login history
- $lastLogin = new LastLogin($this->db, $this->event);
- $lastLogin->create(
+ $this->lastLogin->create(
$method,
$user['id'],
$this->getIpAddress(),
@@ -350,9 +349,8 @@ class User extends Base
// Setup the remember me feature
if (! empty($values['remember_me'])) {
- $rememberMe = new RememberMe($this->db, $this->event);
- $credentials = $rememberMe->create($user['id'], $this->getIpAddress(), $this->getUserAgent());
- $rememberMe->writeCookie($credentials['token'], $credentials['sequence'], $credentials['expiration']);
+ $credentials = $this->rememberMe->create($user['id'], $this->getIpAddress(), $this->getUserAgent());
+ $this->rememberMe->writeCookie($credentials['token'], $credentials['sequence'], $credentials['expiration']);
}
}
else {
@@ -384,8 +382,7 @@ class User extends Base
// LDAP authentication
if (! $authenticated && LDAP_AUTH) {
- $ldap = new Ldap($this->db, $this->event);
- $authenticated = $ldap->authenticate($username, $password);
+ $authenticated = $this->ldap->authenticate($username, $password);
$method = LastLogin::AUTH_LDAP;
}
diff --git a/app/Model/Webhook.php b/app/Model/Webhook.php
index 679d3edc..872031cc 100644
--- a/app/Model/Webhook.php
+++ b/app/Model/Webhook.php
@@ -64,11 +64,9 @@ class Webhook extends Base
*/
public function attachEvents()
{
- $config = new Config($this->db, $this->event);
-
- $this->url_task_creation = $config->get('webhooks_url_task_creation');
- $this->url_task_modification = $config->get('webhooks_url_task_modification');
- $this->token = $config->get('webhooks_token');
+ $this->url_task_creation = $this->config->get('webhooks_url_task_creation');
+ $this->url_task_modification = $this->config->get('webhooks_url_task_modification');
+ $this->token = $this->config->get('webhooks_token');
if ($this->url_task_creation) {
$this->attachCreateEvents();
diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php
index 46fc6d43..8f3ae5a1 100644
--- a/app/Schema/Mysql.php
+++ b/app/Schema/Mysql.php
@@ -4,7 +4,22 @@ namespace Schema;
use Core\Security;
-const VERSION = 22;
+const VERSION = 23;
+
+function version_23($pdo)
+{
+ $pdo->exec("ALTER TABLE users ADD COLUMN notifications_enabled TINYINT(1) DEFAULT '0'");
+
+ $pdo->exec("
+ CREATE TABLE user_has_notifications (
+ user_id INT,
+ project_id INT,
+ FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
+ FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
+ UNIQUE(project_id, user_id)
+ );
+ ");
+}
function version_22($pdo)
{
diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php
index a9eea531..ce77a4ed 100644
--- a/app/Schema/Postgres.php
+++ b/app/Schema/Postgres.php
@@ -4,7 +4,22 @@ namespace Schema;
use Core\Security;
-const VERSION = 3;
+const VERSION = 4;
+
+function version_4($pdo)
+{
+ $pdo->exec("ALTER TABLE users ADD COLUMN notifications_enabled BOOLEAN DEFAULT '0'");
+
+ $pdo->exec("
+ CREATE TABLE user_has_notifications (
+ user_id INTEGER,
+ project_id INTEGER,
+ FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
+ FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
+ UNIQUE(project_id, user_id)
+ );
+ ");
+}
function version_3($pdo)
{
diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php
index 4660251f..c3a3f10e 100644
--- a/app/Schema/Sqlite.php
+++ b/app/Schema/Sqlite.php
@@ -4,7 +4,22 @@ namespace Schema;
use Core\Security;
-const VERSION = 22;
+const VERSION = 23;
+
+function version_23($pdo)
+{
+ $pdo->exec("ALTER TABLE users ADD COLUMN notifications_enabled INTEGER DEFAULT '0'");
+
+ $pdo->exec("
+ CREATE TABLE user_has_notifications (
+ user_id INTEGER,
+ project_id INTEGER,
+ FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
+ FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
+ UNIQUE(project_id, user_id)
+ );
+ ");
+}
function version_22($pdo)
{
diff --git a/app/Templates/comment_edit.php b/app/Templates/comment_edit.php
index 52695f00..4ce48964 100644
--- a/app/Templates/comment_edit.php
+++ b/app/Templates/comment_edit.php
@@ -6,6 +6,7 @@
<?= Helper\form_csrf() ?>
<?= Helper\form_hidden('id', $values) ?>
+ <?= Helper\form_hidden('task_id', $values) ?>
<?= Helper\form_textarea('comment', $values, $errors, array('autofocus', 'required', 'placeholder="'.t('Leave a comment').'"'), 'comment-textarea') ?><br/>
<div class="form-actions">
diff --git a/app/Templates/config_index.php b/app/Templates/config_index.php
index 91919776..11662c87 100644
--- a/app/Templates/config_index.php
+++ b/app/Templates/config_index.php
@@ -31,14 +31,25 @@
<div class="page-header">
<h2><?= t('User settings') ?></h2>
</div>
- <section class="settings">
- <ul>
- <li>
- <strong><?= t('My default project:') ?> </strong>
- <?= (isset($user['default_project_id']) && isset($projects[$user['default_project_id']])) ? Helper\escape($projects[$user['default_project_id']]) : t('None') ?>,
- <a href="?controller=user&amp;action=edit&amp;user_id=<?= $user['id'] ?>"><?= t('edit') ?></a>
- </li>
- </ul>
+ <section>
+ <h3 id="notifications"><?= t('Email notifications') ?></h3>
+ <form method="post" action="?controller=config&amp;action=notifications" autocomplete="off">
+
+ <?= Helper\form_csrf() ?>
+
+ <?= Helper\form_checkbox('notifications_enabled', t('Enable email notifications'), '1', $notifications['notifications_enabled'] == 1) ?><br/>
+
+ <p><?= t('I want to receive notifications only for those projects:') ?><br/><br/></p>
+
+ <div class="form-checkbox-group">
+ <?php foreach ($user_projects as $project_id => $project_name): ?>
+ <?= Helper\form_checkbox('projects['.$project_id.']', $project_name, '1', isset($notifications['project_'.$project_id])) ?>
+ <?php endforeach ?>
+ </div>
+ <div class="form-actions">
+ <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
+ </div>
+ </form>
</section>
<?php if ($user['is_admin']): ?>
diff --git a/app/Templates/notification_comment_creation.php b/app/Templates/notification_comment_creation.php
new file mode 100644
index 00000000..ff286790
--- /dev/null
+++ b/app/Templates/notification_comment_creation.php
@@ -0,0 +1,8 @@
+<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
+
+<h3><?= t('New comment posted by %s', $comment['username']) ?></h3>
+
+<?= Helper\parse($comment['comment']) ?>
+
+<hr/>
+<p>Kanboard</p> \ No newline at end of file
diff --git a/app/Templates/notification_comment_update.php b/app/Templates/notification_comment_update.php
new file mode 100644
index 00000000..9dbd2332
--- /dev/null
+++ b/app/Templates/notification_comment_update.php
@@ -0,0 +1,8 @@
+<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
+
+<h3><?= t('Comment updated') ?></h3>
+
+<?= Helper\parse($comment['comment']) ?>
+
+<hr/>
+<p>Kanboard</p> \ No newline at end of file
diff --git a/app/Templates/notification_file_creation.php b/app/Templates/notification_file_creation.php
new file mode 100644
index 00000000..57d69f51
--- /dev/null
+++ b/app/Templates/notification_file_creation.php
@@ -0,0 +1,6 @@
+<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
+
+<h3><?= t('New attachment added "%s"', $file['name']) ?></h3>
+
+<hr/>
+<p>Kanboard</p> \ No newline at end of file
diff --git a/app/Templates/notification_subtask_creation.php b/app/Templates/notification_subtask_creation.php
new file mode 100644
index 00000000..e02ceaf0
--- /dev/null
+++ b/app/Templates/notification_subtask_creation.php
@@ -0,0 +1,18 @@
+<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
+
+<h3><?= t('New sub-task') ?></h3>
+
+<ul>
+ <li><?= t('Title:') ?> <?= Helper\escape($subtask['title']) ?></li>
+ <li><?= t('Status:') ?> <?= Helper\escape($subtask['status_name']) ?></li>
+ <li><?= t('Assignee:') ?> <?= Helper\escape($subtask['name'] ?: $subtask['username'] ?: '?') ?></li>
+ <li>
+ <?= t('Time tracking:') ?>
+ <?php if (! empty($subtask['time_estimated'])): ?>
+ <strong><?= Helper\escape($subtask['time_estimated']).'h' ?></strong> <?= t('estimated') ?>
+ <?php endif ?>
+ </li>
+</ul>
+
+<hr/>
+<p>Kanboard</p>
diff --git a/app/Templates/notification_subtask_update.php b/app/Templates/notification_subtask_update.php
new file mode 100644
index 00000000..5ec5ed05
--- /dev/null
+++ b/app/Templates/notification_subtask_update.php
@@ -0,0 +1,22 @@
+<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
+
+<h3><?= t('Sub-task updated') ?></h3>
+
+<ul>
+ <li><?= t('Title:') ?> <?= Helper\escape($subtask['title']) ?></li>
+ <li><?= t('Status:') ?> <?= Helper\escape($subtask['status_name']) ?></li>
+ <li><?= t('Assignee:') ?> <?= Helper\escape($subtask['name'] ?: $subtask['username'] ?: '?') ?></li>
+ <li>
+ <?= t('Time tracking:') ?>
+ <?php if (! empty($subtask['time_spent'])): ?>
+ <strong><?= Helper\escape($subtask['time_spent']).'h' ?></strong> <?= t('spent') ?>
+ <?php endif ?>
+
+ <?php if (! empty($subtask['time_estimated'])): ?>
+ <strong><?= Helper\escape($subtask['time_estimated']).'h' ?></strong> <?= t('estimated') ?>
+ <?php endif ?>
+ </li>
+</ul>
+
+<hr/>
+<p>Kanboard</p> \ No newline at end of file
diff --git a/app/Templates/notification_task_close.php b/app/Templates/notification_task_close.php
new file mode 100644
index 00000000..8b8cedb3
--- /dev/null
+++ b/app/Templates/notification_task_close.php
@@ -0,0 +1,6 @@
+<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
+
+<p><?= t('The task #%d have been closed.', $task['id']) ?></p>
+
+<hr/>
+<p>Kanboard</p> \ No newline at end of file
diff --git a/app/Templates/notification_task_creation.php b/app/Templates/notification_task_creation.php
new file mode 100644
index 00000000..9515e889
--- /dev/null
+++ b/app/Templates/notification_task_creation.php
@@ -0,0 +1,44 @@
+<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
+
+<ul>
+ <li>
+ <?= dt('Created on %B %e, %Y at %k:%M %p', $task['date_creation']) ?>
+ </li>
+ <?php if ($task['date_due']): ?>
+ <li>
+ <strong><?= dt('Must be done before %B %e, %Y', $task['date_due']) ?></strong>
+ </li>
+ <?php endif ?>
+ <?php if ($task['creator_username']): ?>
+ <li>
+ <?= t('Created by %s', $task['creator_username']) ?>
+ </li>
+ <?php endif ?>
+ <li>
+ <strong>
+ <?php if ($task['assignee_username']): ?>
+ <?= t('Assigned to %s', $task['assignee_username']) ?>
+ <?php else: ?>
+ <?= t('There is nobody assigned') ?>
+ <?php endif ?>
+ </strong>
+ </li>
+ <li>
+ <?= t('Column on the board:') ?>
+ <strong><?= Helper\escape($task['column_title']) ?></strong>
+ </li>
+ <li><?= t('Task position:').' '.Helper\escape($task['position']) ?></li>
+ <?php if ($task['category_name']): ?>
+ <li>
+ <?= t('Category:') ?> <strong><?= Helper\escape($task['category_name']) ?></strong>
+ </li>
+ <?php endif ?>
+</ul>
+
+<?php if (! empty($task['description'])): ?>
+ <h2><?= t('Description') ?></h2>
+ <?= Helper\parse($task['description']) ?>
+<?php endif ?>
+
+<hr/>
+<p>Kanboard</p> \ No newline at end of file
diff --git a/app/Templates/notification_task_due.php b/app/Templates/notification_task_due.php
new file mode 100644
index 00000000..1686c7de
--- /dev/null
+++ b/app/Templates/notification_task_due.php
@@ -0,0 +1,10 @@
+<h2><?= t('List of due tasks for the project "%s"', $project) ?></h2>
+
+<ul>
+ <?php foreach ($tasks as $task): ?>
+ <li>(<strong>#<?= $task['id'] ?></strong>) <?= Helper\escape($task['title']) ?> (<strong><?= t('Assigned to %s', $task['assignee_name'] ?: $task['assignee_username']) ?></strong>)</li>
+ <?php endforeach ?>
+</ul>
+
+<hr/>
+<p>Kanboard</p> \ No newline at end of file
diff --git a/app/Templates/notification_task_open.php b/app/Templates/notification_task_open.php
new file mode 100644
index 00000000..2ef0f04f
--- /dev/null
+++ b/app/Templates/notification_task_open.php
@@ -0,0 +1,6 @@
+<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
+
+<p><?= t('The task #%d have been opened.', $task['id']) ?></p>
+
+<hr/>
+<p>Kanboard</p> \ No newline at end of file
diff --git a/app/Templates/notification_task_update.php b/app/Templates/notification_task_update.php
new file mode 100644
index 00000000..28be9db2
--- /dev/null
+++ b/app/Templates/notification_task_update.php
@@ -0,0 +1,44 @@
+<h2><?= Helper\escape($task['title']) ?> (#<?= $task['id'] ?>)</h2>
+
+<ul>
+ <li>
+ <?= dt('Created on %B %e, %Y at %k:%M %p', $task['date_creation']) ?>
+ </li>
+ <?php if ($task['date_due']): ?>
+ <li>
+ <strong><?= dt('Must be done before %B %e, %Y', $task['date_due']) ?></strong>
+ </li>
+ <?php endif ?>
+ <?php if ($task['creator_username']): ?>
+ <li>
+ <?= t('Created by %s', $task['creator_username']) ?>
+ </li>
+ <?php endif ?>
+ <li>
+ <strong>
+ <?php if ($task['assignee_username']): ?>
+ <?= t('Assigned to %s', $task['assignee_username']) ?>
+ <?php else: ?>
+ <?= t('There is nobody assigned') ?>
+ <?php endif ?>
+ </strong>
+ </li>
+ <li>
+ <?= t('Column on the board:') ?>
+ <strong><?= Helper\escape($task['column_title']) ?></strong>
+ </li>
+ <li><?= t('Task position:').' '.Helper\escape($task['position']) ?></li>
+ <?php if ($task['category_name']): ?>
+ <li>
+ <?= t('Category:') ?> <strong><?= Helper\escape($task['category_name']) ?></strong>
+ </li>
+ <?php endif ?>
+</ul>
+
+<?php if (! empty($task['description'])): ?>
+ <h2><?= t('Description') ?></h2>
+ <?= Helper\parse($task['description']) ?: t('There is no description.') ?>
+<?php endif ?>
+
+<hr/>
+<p>Kanboard</p> \ No newline at end of file
diff --git a/app/common.php b/app/common.php
index 312b930b..9ce0016a 100644
--- a/app/common.php
+++ b/app/common.php
@@ -4,6 +4,8 @@ require __DIR__.'/Core/Loader.php';
require __DIR__.'/helpers.php';
require __DIR__.'/translator.php';
+require 'vendor/swiftmailer/swift_required.php';
+
use Core\Event;
use Core\Loader;
use Core\Registry;
@@ -63,6 +65,15 @@ defined('REVERSE_PROXY_AUTH') or define('REVERSE_PROXY_AUTH', false);
defined('REVERSE_PROXY_USER_HEADER') or define('REVERSE_PROXY_USER_HEADER', 'REMOTE_USER');
defined('REVERSE_PROXY_DEFAULT_ADMIN') or define('REVERSE_PROXY_DEFAULT_ADMIN', '');
+// Mail configuration
+defined('MAIL_FROM') or define('MAIL_FROM', 'notifications@kanboard.net');
+defined('MAIL_TRANSPORT') or define('MAIL_TRANSPORT', 'mail');
+defined('MAIL_SMTP_HOSTNAME') or define('MAIL_SMTP_HOSTNAME', '');
+defined('MAIL_SMTP_PORT') or define('MAIL_SMTP_PORT', 25);
+defined('MAIL_SMTP_USERNAME') or define('MAIL_SMTP_USERNAME', '');
+defined('MAIL_SMTP_PASSWORD') or define('MAIL_SMTP_PASSWORD', '');
+defined('MAIL_SENDMAIL_COMMAND') or define('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs');
+
$loader = new Loader;
$loader->execute();
@@ -126,3 +137,25 @@ $registry->db = function() use ($registry) {
$registry->event = function() use ($registry) {
return new Event;
};
+
+$registry->mailer = function() use ($registry) {
+
+ require_once 'vendor/swiftmailer/swift_required.php';
+
+ $transport = null;
+
+ switch (MAIL_TRANSPORT) {
+ case 'smtp':
+ $transport = Swift_SmtpTransport::newInstance(MAIL_SMTP_HOSTNAME, MAIL_SMTP_PORT);
+ $transport->setUsername(MAIL_SMTP_USERNAME);
+ $transport->setPassword(MAIL_SMTP_PASSWORD);
+ break;
+ case 'sendmail':
+ $transport = Swift_SendmailTransport::newInstance(MAIL_SENDMAIL_COMMAND);
+ break;
+ default:
+ $transport = Swift_MailTransport::newInstance();
+ }
+
+ return $transport;
+};
diff --git a/assets/css/app.css b/assets/css/app.css
index 3be402b6..fae922ab 100644
--- a/assets/css/app.css
+++ b/assets/css/app.css
@@ -265,6 +265,10 @@ input.form-date {
line-height: 25px;
}
+.form-checkbox-group label {
+ display: inline;
+}
+
/* alerts */
.alert {
padding: 8px 35px 8px 14px;
diff --git a/assets/js/app.js b/assets/js/app.js
index bf98d689..78354dde 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -77,7 +77,8 @@ Kanboard.Board = (function() {
connectWith: ".column",
placeholder: "draggable-placeholder",
stop: function(event, ui) {
- board_save();
+ var task_id = parseInt(ui.item[0].getAttribute("data-task-id"));
+ board_save(task_id);
}
});
@@ -112,7 +113,7 @@ Kanboard.Board = (function() {
}
// Save and refresh the board
- function board_save()
+ function board_save(selected_task_id)
{
var data = [];
var boardSelector = $("#board");
@@ -135,7 +136,7 @@ Kanboard.Board = (function() {
$.ajax({
cache: false,
url: "?controller=board&action=save&project_id=" + projectId,
- data: {"positions": data, "csrf_token": boardSelector.attr("data-csrf-token")},
+ data: {"positions": data, "csrf_token": boardSelector.attr("data-csrf-token"), "selected_task_id": selected_task_id},
type: "POST",
success: function(data) {
$("#board").remove();
diff --git a/config.default.php b/config.default.php
index b1028767..5f8313a9 100644
--- a/config.default.php
+++ b/config.default.php
@@ -1,5 +1,20 @@
<?php
+// E-mail address for the "From" header (notifications)
+define('MAIL_FROM', 'notifications@kanboard.net');
+
+// Mail transport to use: "smtp", "sendmail" or "mail" (PHP mail function)
+define('MAIL_TRANSPORT', 'mail');
+
+// SMTP configuration to use when the "smtp" transport is chosen
+define('MAIL_SMTP_HOSTNAME', '');
+define('MAIL_SMTP_PORT', 25);
+define('MAIL_SMTP_USERNAME', '');
+define('MAIL_SMTP_PASSWORD', '');
+
+// Sendmail command to use when the transport is "sendmail"
+define('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs');
+
// Auto-refresh frequency in seconds for the public board view (60 seconds by default)
define('BOARD_PUBLIC_CHECK_INTERVAL', 60);
diff --git a/jsonrpc.php b/jsonrpc.php
index 9ec51c94..c645650f 100644
--- a/jsonrpc.php
+++ b/jsonrpc.php
@@ -3,6 +3,7 @@
require __DIR__.'/app/common.php';
require __DIR__.'/vendor/JsonRPC/Server.php';
+use Core\Translator;
use JsonRPC\Server;
use Model\Project;
use Model\Task;
@@ -14,21 +15,28 @@ use Model\SubTask;
use Model\Board;
use Model\Action;
use Model\Webhook;
-
-$config = new Config($registry->shared('db'), $registry->shared('event'));
-$project = new Project($registry->shared('db'), $registry->shared('event'));
-$task = new Task($registry->shared('db'), $registry->shared('event'));
-$user = new User($registry->shared('db'), $registry->shared('event'));
-$category = new Category($registry->shared('db'), $registry->shared('event'));
-$comment = new Comment($registry->shared('db'), $registry->shared('event'));
-$subtask = new SubTask($registry->shared('db'), $registry->shared('event'));
-$board = new Board($registry->shared('db'), $registry->shared('event'));
-$action = new Action($registry->shared('db'), $registry->shared('event'));
-$webhook = new Webhook($registry->shared('db'), $registry->shared('event'));
+use Model\Notification;
+
+$config = new Config($registry);
+$project = new Project($registry);
+$task = new Task($registry);
+$user = new User($registry);
+$category = new Category($registry);
+$comment = new Comment($registry);
+$subtask = new SubTask($registry);
+$board = new Board($registry);
+$action = new Action($registry);
+$webhook = new Webhook($registry);
+$notification = new Notification($registry);
$action->attachEvents();
$project->attachEvents();
$webhook->attachEvents();
+$notification->attachEvents();
+
+// Load translations
+$language = $config->get('language', 'en_US');
+if ($language !== 'en_US') Translator::load($language);
$server = new Server;
$server->authentication(array('jsonrpc' => $config->get('api_token')));
diff --git a/kanboard b/kanboard
index 95a977bd..34e183e4 100755
--- a/kanboard
+++ b/kanboard
@@ -8,8 +8,9 @@ use Core\Tool;
use Core\Translator;
use Model\Config;
use Model\Task;
+use Model\Notification;
-$config = new Config($registry->shared('db'), $registry->shared('event'));
+$config = new Config($registry);
// Load translations
$language = $config->get('language', 'en_US');
@@ -25,6 +26,7 @@ $cli = new Cli;
$cli->register('help', function() {
echo 'Kanboard command line interface'.PHP_EOL.'==============================='.PHP_EOL.PHP_EOL;
echo '- Task export to stdout (CSV format): '.$GLOBALS['argv'][0].' export-csv <project_id> <start_date> <end_date>'.PHP_EOL;
+ echo '- Send notifications for tasks due: '.$GLOBALS['argv'][0].' send-notifications-tasks-due'.PHP_EOL;
});
// CSV Export
@@ -40,12 +42,39 @@ $cli->register('export-csv', function() use ($cli, $registry) {
Translator::disableEscaping();
- $task = new Task($registry->shared('db'), $registry->shared('event'));
- $data = $task->export($project_id, $start_date, $end_date);
+ $taskModel = new Task($registry);
+ $data = $taskModel->export($project_id, $start_date, $end_date);
if (is_array($data)) {
Tool::csv($data);
}
});
+// Send notification for tasks due
+$cli->register('send-notifications-tasks-due', function() use ($cli, $registry) {
+
+ $notificationModel = new Notification($registry);
+ $taskModel = new Task($registry);
+ $tasks = $taskModel->getTasksDue();
+
+ // Group tasks by project
+ $projects = array();
+
+ foreach ($tasks as $task) {
+ $projects[$task['project_id']][] = $task;
+ }
+
+ // Send notifications for each project
+ foreach ($projects as $project_id => $project_tasks) {
+
+ $users = $notificationModel->getUsersList($project_id);
+
+ $notificationModel->sendEmails(
+ 'notification_task_due',
+ $users,
+ array('tasks' => $project_tasks, 'project' => $project_tasks[0]['project_name'])
+ );
+ }
+});
+
$cli->execute();
diff --git a/tests/units/AclTest.php b/tests/units/AclTest.php
index a2c1c111..7dff0a69 100644
--- a/tests/units/AclTest.php
+++ b/tests/units/AclTest.php
@@ -12,7 +12,7 @@ class AclTest extends Base
'controller1' => array('action1', 'action3'),
);
- $acl = new Acl($this->db, $this->event);
+ $acl = new Acl($this->registry);
$this->assertTrue($acl->isAllowedAction($acl_rules, 'controller1', 'action1'));
$this->assertTrue($acl->isAllowedAction($acl_rules, 'controller1', 'action3'));
$this->assertFalse($acl->isAllowedAction($acl_rules, 'controller1', 'action2'));
@@ -22,7 +22,7 @@ class AclTest extends Base
public function testIsAdmin()
{
- $acl = new Acl($this->db, $this->event);
+ $acl = new Acl($this->registry);
$_SESSION = array();
$this->assertFalse($acl->isAdminUser());
@@ -45,7 +45,7 @@ class AclTest extends Base
public function testIsUser()
{
- $acl = new Acl($this->db, $this->event);
+ $acl = new Acl($this->registry);
$_SESSION = array();
$this->assertFalse($acl->isRegularUser());
@@ -68,7 +68,7 @@ class AclTest extends Base
public function testIsPageAllowed()
{
- $acl = new Acl($this->db, $this->event);
+ $acl = new Acl($this->registry);
// Public access
$_SESSION = array();
diff --git a/tests/units/ActionTaskAssignColorCategoryTest.php b/tests/units/ActionTaskAssignColorCategoryTest.php
index 18b4311e..84334dc5 100644
--- a/tests/units/ActionTaskAssignColorCategoryTest.php
+++ b/tests/units/ActionTaskAssignColorCategoryTest.php
@@ -10,7 +10,7 @@ class ActionTaskAssignColorCategory extends Base
{
public function testBadProject()
{
- $action = new Action\TaskAssignColorCategory(3, new Task($this->db, $this->event));
+ $action = new Action\TaskAssignColorCategory(3, new Task($this->registry));
$event = array(
'project_id' => 2,
@@ -24,14 +24,14 @@ class ActionTaskAssignColorCategory extends Base
public function testExecute()
{
- $action = new Action\TaskAssignColorCategory(1, new Task($this->db, $this->event));
+ $action = new Action\TaskAssignColorCategory(1, new Task($this->registry));
$action->setParam('category_id', 1);
$action->setParam('color_id', 'blue');
// We create a task in the first column
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
- $c = new Category($this->db, $this->event);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
+ $c = new Category($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'test')));
$this->assertEquals(1, $c->create(array('name' => 'c1')));
diff --git a/tests/units/ActionTaskAssignColorUserTest.php b/tests/units/ActionTaskAssignColorUserTest.php
index 04e3172f..ee71e87c 100644
--- a/tests/units/ActionTaskAssignColorUserTest.php
+++ b/tests/units/ActionTaskAssignColorUserTest.php
@@ -9,7 +9,7 @@ class ActionTaskAssignColorUser extends Base
{
public function testBadProject()
{
- $action = new Action\TaskAssignColorUser(3, new Task($this->db, $this->event));
+ $action = new Action\TaskAssignColorUser(3, new Task($this->registry));
$event = array(
'project_id' => 2,
@@ -23,13 +23,13 @@ class ActionTaskAssignColorUser extends Base
public function testExecute()
{
- $action = new Action\TaskAssignColorUser(1, new Task($this->db, $this->event));
+ $action = new Action\TaskAssignColorUser(1, new Task($this->registry));
$action->setParam('user_id', 1);
$action->setParam('color_id', 'blue');
// We create a task in the first column
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'test')));
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1, 'color_id' => 'green')));
diff --git a/tests/units/ActionTaskAssignCurrentUserTest.php b/tests/units/ActionTaskAssignCurrentUserTest.php
index 0780b603..f67c1e28 100644
--- a/tests/units/ActionTaskAssignCurrentUserTest.php
+++ b/tests/units/ActionTaskAssignCurrentUserTest.php
@@ -10,7 +10,7 @@ class ActionTaskAssignCurrentUser extends Base
{
public function testBadProject()
{
- $action = new Action\TaskAssignCurrentUser(3, new Task($this->db, $this->event), new Acl($this->db, $this->event));
+ $action = new Action\TaskAssignCurrentUser(3, new Task($this->registry), new Acl($this->registry));
$action->setParam('column_id', 5);
$event = array(
@@ -25,7 +25,7 @@ class ActionTaskAssignCurrentUser extends Base
public function testBadColumn()
{
- $action = new Action\TaskAssignCurrentUser(3, new Task($this->db, $this->event), new Acl($this->db, $this->event));
+ $action = new Action\TaskAssignCurrentUser(3, new Task($this->registry), new Acl($this->registry));
$action->setParam('column_id', 5);
$event = array(
@@ -39,16 +39,16 @@ class ActionTaskAssignCurrentUser extends Base
public function testExecute()
{
- $action = new Action\TaskAssignCurrentUser(1, new Task($this->db, $this->event), new Acl($this->db, $this->event));
+ $action = new Action\TaskAssignCurrentUser(1, new Task($this->registry), new Acl($this->registry));
$action->setParam('column_id', 2);
$_SESSION = array(
'user' => array('id' => 5)
);
// We create a task in the first column
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
- $a = new Acl($this->db, $this->event);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
+ $a = new Acl($this->registry);
$this->assertEquals(5, $a->getUserId());
$this->assertEquals(1, $p->create(array('name' => 'test')));
diff --git a/tests/units/ActionTaskAssignSpecificUserTest.php b/tests/units/ActionTaskAssignSpecificUserTest.php
index 3a919978..6fd454d5 100644
--- a/tests/units/ActionTaskAssignSpecificUserTest.php
+++ b/tests/units/ActionTaskAssignSpecificUserTest.php
@@ -9,7 +9,7 @@ class ActionTaskAssignSpecificUser extends Base
{
public function testBadProject()
{
- $action = new Action\TaskAssignSpecificUser(3, new Task($this->db, $this->event));
+ $action = new Action\TaskAssignSpecificUser(3, new Task($this->registry));
$action->setParam('column_id', 5);
$event = array(
@@ -24,7 +24,7 @@ class ActionTaskAssignSpecificUser extends Base
public function testBadColumn()
{
- $action = new Action\TaskAssignSpecificUser(3, new Task($this->db, $this->event));
+ $action = new Action\TaskAssignSpecificUser(3, new Task($this->registry));
$action->setParam('column_id', 5);
$event = array(
@@ -38,13 +38,13 @@ class ActionTaskAssignSpecificUser extends Base
public function testExecute()
{
- $action = new Action\TaskAssignSpecificUser(1, new Task($this->db, $this->event));
+ $action = new Action\TaskAssignSpecificUser(1, new Task($this->registry));
$action->setParam('column_id', 2);
$action->setParam('user_id', 1);
// We create a task in the first column
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'test')));
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1)));
diff --git a/tests/units/ActionTaskCloseTest.php b/tests/units/ActionTaskCloseTest.php
index 0c864f42..a3a1eecc 100644
--- a/tests/units/ActionTaskCloseTest.php
+++ b/tests/units/ActionTaskCloseTest.php
@@ -9,7 +9,7 @@ class ActionTaskCloseTest extends Base
{
public function testBadProject()
{
- $action = new Action\TaskClose(3, new Task($this->db, $this->event));
+ $action = new Action\TaskClose(3, new Task($this->registry));
$action->setParam('column_id', 5);
$event = array(
@@ -24,7 +24,7 @@ class ActionTaskCloseTest extends Base
public function testBadColumn()
{
- $action = new Action\TaskClose(3, new Task($this->db, $this->event));
+ $action = new Action\TaskClose(3, new Task($this->registry));
$action->setParam('column_id', 5);
$event = array(
@@ -38,12 +38,12 @@ class ActionTaskCloseTest extends Base
public function testExecute()
{
- $action = new Action\TaskClose(1, new Task($this->db, $this->event));
+ $action = new Action\TaskClose(1, new Task($this->registry));
$action->setParam('column_id', 2);
// We create a task in the first column
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'test')));
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1)));
diff --git a/tests/units/ActionTaskDuplicateAnotherProjectTest.php b/tests/units/ActionTaskDuplicateAnotherProjectTest.php
index 0b2e4bd5..4d995b64 100644
--- a/tests/units/ActionTaskDuplicateAnotherProjectTest.php
+++ b/tests/units/ActionTaskDuplicateAnotherProjectTest.php
@@ -9,7 +9,7 @@ class ActionTaskDuplicateAnotherProject extends Base
{
public function testBadProject()
{
- $action = new Action\TaskDuplicateAnotherProject(3, new Task($this->db, $this->event));
+ $action = new Action\TaskDuplicateAnotherProject(3, new Task($this->registry));
$action->setParam('column_id', 5);
$event = array(
@@ -24,7 +24,7 @@ class ActionTaskDuplicateAnotherProject extends Base
public function testBadColumn()
{
- $action = new Action\TaskDuplicateAnotherProject(3, new Task($this->db, $this->event));
+ $action = new Action\TaskDuplicateAnotherProject(3, new Task($this->registry));
$action->setParam('column_id', 5);
$event = array(
@@ -38,11 +38,11 @@ class ActionTaskDuplicateAnotherProject extends Base
public function testExecute()
{
- $action = new Action\TaskDuplicateAnotherProject(1, new Task($this->db, $this->event));
+ $action = new Action\TaskDuplicateAnotherProject(1, new Task($this->registry));
// We create a task in the first column
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'project 1')));
$this->assertEquals(2, $p->create(array('name' => 'project 2')));
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1)));
diff --git a/tests/units/ActionTest.php b/tests/units/ActionTest.php
index 2eb12784..8108767d 100644
--- a/tests/units/ActionTest.php
+++ b/tests/units/ActionTest.php
@@ -12,9 +12,9 @@ class ActionTest extends Base
{
public function testFetchActions()
{
- $action = new Action($this->db, $this->event);
- $board = new Board($this->db, $this->event);
- $project = new Project($this->db, $this->event);
+ $action = new Action($this->registry);
+ $board = new Board($this->registry);
+ $project = new Project($this->registry);
$this->assertEquals(1, $project->create(array('name' => 'unit_test')));
@@ -48,10 +48,10 @@ class ActionTest extends Base
public function testEventMoveColumn()
{
- $task = new Task($this->db, $this->event);
- $board = new Board($this->db, $this->event);
- $project = new Project($this->db, $this->event);
- $action = new Action($this->db, $this->event);
+ $task = new Task($this->registry);
+ $board = new Board($this->registry);
+ $project = new Project($this->registry);
+ $action = new Action($this->registry);
// We create a project
$this->assertEquals(1, $project->create(array('name' => 'unit_test')));
@@ -86,8 +86,8 @@ class ActionTest extends Base
// We move our task
$task->move(1, 4, 1);
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_UPDATE));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_UPDATE));
// Our task should be closed
$t1 = $task->getById(1);
@@ -97,10 +97,10 @@ class ActionTest extends Base
public function testEventMovePosition()
{
- $task = new Task($this->db, $this->event);
- $board = new Board($this->db, $this->event);
- $project = new Project($this->db, $this->event);
- $action = new Action($this->db, $this->event);
+ $task = new Task($this->registry);
+ $board = new Board($this->registry);
+ $project = new Project($this->registry);
+ $action = new Action($this->registry);
// We create a project
$this->assertEquals(1, $project->create(array('name' => 'unit_test')));
@@ -138,7 +138,7 @@ class ActionTest extends Base
// We bind events
$action->attachEvents();
- $this->assertTrue($this->event->hasListener(Task::EVENT_MOVE_POSITION, 'Action\TaskAssignColorCategory'));
+ $this->assertTrue($this->registry->event->hasListener(Task::EVENT_MOVE_POSITION, 'Action\TaskAssignColorCategory'));
// Our task should have the color red and position=0
$t1 = $task->getById(1);
@@ -155,7 +155,7 @@ class ActionTest extends Base
$task->move(1, 1, 1); // task #1 to position 1
$task->move(2, 1, 0); // task #2 to position 0
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_MOVE_POSITION));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_POSITION));
// Both tasks should be green
$t1 = $task->getById(1);
@@ -171,10 +171,10 @@ class ActionTest extends Base
public function testExecuteMultipleActions()
{
- $task = new Task($this->db, $this->event);
- $board = new Board($this->db, $this->event);
- $project = new Project($this->db, $this->event);
- $action = new Action($this->db, $this->event);
+ $task = new Task($this->registry);
+ $board = new Board($this->registry);
+ $project = new Project($this->registry);
+ $action = new Action($this->registry);
// We create 2 projects
$this->assertEquals(1, $project->create(array('name' => 'unit_test1')));
@@ -213,8 +213,8 @@ class ActionTest extends Base
$action->attachEvents();
// Events should be attached
- $this->assertTrue($this->event->hasListener(Task::EVENT_CLOSE, 'Action\TaskDuplicateAnotherProject'));
- $this->assertTrue($this->event->hasListener(Task::EVENT_MOVE_COLUMN, 'Action\TaskClose'));
+ $this->assertTrue($this->registry->event->hasListener(Task::EVENT_CLOSE, 'Action\TaskDuplicateAnotherProject'));
+ $this->assertTrue($this->registry->event->hasListener(Task::EVENT_MOVE_COLUMN, 'Action\TaskClose'));
// Our task should be open, linked to the first project and in the first column
$t1 = $task->getById(1);
@@ -225,8 +225,8 @@ class ActionTest extends Base
// We move our task
$task->move(1, 4, 1);
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_CLOSE));
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CLOSE));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
// Our task should be closed
$t1 = $task->getById(1);
diff --git a/tests/units/Base.php b/tests/units/Base.php
index 1f8109ed..313e6f43 100644
--- a/tests/units/Base.php
+++ b/tests/units/Base.php
@@ -9,6 +9,8 @@ require_once __DIR__.'/../../app/Core/Security.php';
require_once __DIR__.'/../../vendor/PicoDb/Database.php';
require_once __DIR__.'/../../app/Schema/Sqlite.php';
+require_once __DIR__.'/../../app/Core/Registry.php';
+require_once __DIR__.'/../../app/Core/Tool.php';
require_once __DIR__.'/../../app/Core/Listener.php';
require_once __DIR__.'/../../app/Core/Event.php';
require_once __DIR__.'/../../app/Core/Translator.php';
@@ -36,8 +38,9 @@ abstract class Base extends PHPUnit_Framework_TestCase
{
public function setUp()
{
- $this->db = $this->getDbConnection();
- $this->event = new \Core\Event;
+ $this->registry = new \Core\Registry;
+ $this->registry->db = $this->getDbConnection();
+ $this->registry->event = new \Core\Event;
}
public function getDbConnection()
diff --git a/tests/units/BoardTest.php b/tests/units/BoardTest.php
index d5686b3f..23ea8808 100644
--- a/tests/units/BoardTest.php
+++ b/tests/units/BoardTest.php
@@ -9,8 +9,8 @@ class BoardTest extends Base
{
public function testMoveColumns()
{
- $p = new Project($this->db, $this->event);
- $b = new Board($this->db, $this->event);
+ $p = new Project($this->registry);
+ $b = new Board($this->registry);
// We create 2 projects
$this->assertEquals(1, $p->create(array('name' => 'UnitTest1')));
diff --git a/tests/units/CommentTest.php b/tests/units/CommentTest.php
index 46f05abc..fa790555 100644
--- a/tests/units/CommentTest.php
+++ b/tests/units/CommentTest.php
@@ -10,9 +10,9 @@ class CommentTest extends Base
{
public function testCreate()
{
- $c = new Comment($this->db, $this->event);
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
+ $c = new Comment($this->registry);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'test1')));
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
@@ -30,9 +30,9 @@ class CommentTest extends Base
public function testGetAll()
{
- $c = new Comment($this->db, $this->event);
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
+ $c = new Comment($this->registry);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'test1')));
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
@@ -51,9 +51,9 @@ class CommentTest extends Base
public function testUpdate()
{
- $c = new Comment($this->db, $this->event);
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
+ $c = new Comment($this->registry);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'test1')));
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
@@ -67,7 +67,7 @@ class CommentTest extends Base
public function testValidateCreation()
{
- $c = new Comment($this->db, $this->event);
+ $c = new Comment($this->registry);
$result = $c->validateCreation(array('user_id' => 1, 'task_id' => 1, 'comment' => 'bla'));
$this->assertTrue($result[0]);
@@ -96,7 +96,7 @@ class CommentTest extends Base
public function testValidateModification()
{
- $c = new Comment($this->db, $this->event);
+ $c = new Comment($this->registry);
$result = $c->validateModification(array('id' => 1, 'comment' => 'bla'));
$this->assertTrue($result[0]);
diff --git a/tests/units/ProjectTest.php b/tests/units/ProjectTest.php
index 5ca8177c..cb7aee36 100644
--- a/tests/units/ProjectTest.php
+++ b/tests/units/ProjectTest.php
@@ -12,7 +12,7 @@ class ProjectTest extends Base
{
public function testCreation()
{
- $p = new Project($this->db, $this->event);
+ $p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'UnitTest')));
$this->assertNotEmpty($p->getById(1));
@@ -21,10 +21,10 @@ class ProjectTest extends Base
public function testAllowEverybody()
{
// We create a regular user
- $user = new User($this->db, $this->event);
+ $user = new User($this->registry);
$user->create(array('username' => 'unittest', 'password' => 'unittest'));
- $p = new Project($this->db, $this->event);
+ $p = new Project($this->registry);
$this->assertEmpty($p->getAllowedUsers(1)); // Nobody is specified for the given project
$this->assertTrue($p->isUserAllowed(1, 1)); // Everybody should be allowed
$this->assertTrue($p->isUserAllowed(1, 2)); // Everybody should be allowed
@@ -32,8 +32,8 @@ class ProjectTest extends Base
public function testAllowUser()
{
- $p = new Project($this->db, $this->event);
- $user = new User($this->db, $this->event);
+ $p = new Project($this->registry);
+ $user = new User($this->registry);
$user->create(array('username' => 'unittest', 'password' => 'unittest'));
// We create a project
@@ -58,9 +58,9 @@ class ProjectTest extends Base
public function testRevokeUser()
{
- $p = new Project($this->db, $this->event);
+ $p = new Project($this->registry);
- $user = new User($this->db, $this->event);
+ $user = new User($this->registry);
$user->create(array('username' => 'unittest', 'password' => 'unittest'));
// We create a project
@@ -113,9 +113,9 @@ class ProjectTest extends Base
public function testUsersList()
{
- $p = new Project($this->db, $this->event);
+ $p = new Project($this->registry);
- $user = new User($this->db, $this->event);
+ $user = new User($this->registry);
$user->create(array('username' => 'unittest', 'password' => 'unittest'));
// We create project
diff --git a/tests/units/TaskTest.php b/tests/units/TaskTest.php
index b8b3cf46..1ea03fca 100644
--- a/tests/units/TaskTest.php
+++ b/tests/units/TaskTest.php
@@ -10,9 +10,9 @@ class TaskTest extends Base
{
public function testExport()
{
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
- $c = new Category($this->db, $this->event);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
+ $c = new Category($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'Export Project')));
$this->assertNotFalse($c->create(array('name' => 'Category #1', 'project_id' => 1)));
@@ -45,8 +45,8 @@ class TaskTest extends Base
public function testFilter()
{
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
$this->assertEquals(1, $p->create(array('name' => 'test1')));
$this->assertEquals(1, $t->create(array('title' => 'test a', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1, 'description' => 'biloute')));
@@ -114,7 +114,7 @@ class TaskTest extends Base
public function testDateFormat()
{
- $t = new Task($this->db, $this->event);
+ $t = new Task($this->registry);
$this->assertEquals('2014-03-05', date('Y-m-d', $t->getValidDate('2014-03-05', 'Y-m-d')));
$this->assertEquals('2014-03-05', date('Y-m-d', $t->getValidDate('2014_03_05', 'Y_m_d')));
@@ -133,8 +133,8 @@ class TaskTest extends Base
public function testDuplicateTask()
{
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
// We create a task and a project
$this->assertEquals(1, $p->create(array('name' => 'test1')));
@@ -146,7 +146,7 @@ class TaskTest extends Base
// We duplicate our task
$this->assertEquals(2, $t->duplicate(1));
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_CREATE));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE));
// Check the values of the duplicated task
$task = $t->getById(2);
@@ -160,8 +160,8 @@ class TaskTest extends Base
public function testDuplicateToAnotherProject()
{
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
// We create 2 projects
$this->assertEquals(1, $p->create(array('name' => 'test1')));
@@ -172,7 +172,7 @@ class TaskTest extends Base
// We duplicate our task to the 2nd project
$this->assertEquals(2, $t->duplicateToAnotherProject(1, 2));
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_CREATE));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE));
// Check the values of the duplicated task
$task = $t->getById(2);
@@ -185,39 +185,39 @@ class TaskTest extends Base
public function testEvents()
{
- $t = new Task($this->db, $this->event);
- $p = new Project($this->db, $this->event);
+ $t = new Task($this->registry);
+ $p = new Project($this->registry);
// We create a project
$this->assertEquals(1, $p->create(array('name' => 'test')));
// We create task
$this->assertEquals(1, $t->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1)));
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_CREATE));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE));
// We update a task
$this->assertTrue($t->update(array('title' => 'test2', 'id' => 1)));
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_UPDATE));
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_CREATE_UPDATE));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_UPDATE));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CREATE_UPDATE));
// We close our task
$this->assertTrue($t->close(1));
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_CLOSE));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_CLOSE));
// We open our task
$this->assertTrue($t->open(1));
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_OPEN));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_OPEN));
// We change the column of our task
$this->assertTrue($t->move(1, 2, 1));
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
// We change the position of our task
$this->assertTrue($t->move(1, 2, 2));
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_MOVE_POSITION));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_POSITION));
// We change the column and the position of our task
$this->assertTrue($t->move(1, 1, 3));
- $this->assertTrue($this->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
+ $this->assertTrue($this->registry->event->isEventTriggered(Task::EVENT_MOVE_COLUMN));
}
}
diff --git a/vendor/PicoDb/Table.php b/vendor/PicoDb/Table.php
index 8a0ce644..60a1280c 100644
--- a/vendor/PicoDb/Table.php
+++ b/vendor/PicoDb/Table.php
@@ -379,6 +379,12 @@ class Table
$sql = sprintf('%s = ?', $this->db->escapeIdentifier($column));
break;
+ case 'neq':
+ case 'notequal':
+ case 'notequals':
+ $sql = sprintf('%s != ?', $this->db->escapeIdentifier($column));
+ break;
+
case 'gt':
case 'greaterthan':
$sql = sprintf('%s > ?', $this->db->escapeIdentifier($column));
diff --git a/vendor/swiftmailer/classes/Swift.php b/vendor/swiftmailer/classes/Swift.php
new file mode 100644
index 00000000..77145fdc
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift.php
@@ -0,0 +1,80 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * General utility class in Swift Mailer, not to be instantiated.
+ *
+ *
+ * @author Chris Corbyn
+ */
+abstract class Swift
+{
+ public static $initialized = false;
+ public static $inits = array();
+
+ /** Swift Mailer Version number generated during dist release process */
+ const VERSION = '@SWIFT_VERSION_NUMBER@';
+
+ /**
+ * Registers an initializer callable that will be called the first time
+ * a SwiftMailer class is autoloaded.
+ *
+ * This enables you to tweak the default configuration in a lazy way.
+ *
+ * @param mixed $callable A valid PHP callable that will be called when autoloading the first Swift class
+ */
+ public static function init($callable)
+ {
+ self::$inits[] = $callable;
+ }
+
+ /**
+ * Internal autoloader for spl_autoload_register().
+ *
+ * @param string $class
+ */
+ public static function autoload($class)
+ {
+ // Don't interfere with other autoloaders
+ if (0 !== strpos($class, 'Swift_')) {
+ return;
+ }
+
+ $path = dirname(__FILE__).'/'.str_replace('_', '/', $class).'.php';
+
+ if (!file_exists($path)) {
+ return;
+ }
+
+ require $path;
+
+ if (self::$inits && !self::$initialized) {
+ self::$initialized = true;
+ foreach (self::$inits as $init) {
+ call_user_func($init);
+ }
+ }
+ }
+
+ /**
+ * Configure autoloading using Swift Mailer.
+ *
+ * This is designed to play nicely with other autoloaders.
+ *
+ * @param mixed $callable A valid PHP callable that will be called when autoloading the first Swift class
+ */
+ public static function registerAutoload($callable = null)
+ {
+ if (null !== $callable) {
+ self::$inits[] = $callable;
+ }
+ spl_autoload_register(array('Swift', 'autoload'));
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Attachment.php b/vendor/swiftmailer/classes/Swift/Attachment.php
new file mode 100644
index 00000000..32759e0d
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Attachment.php
@@ -0,0 +1,71 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Attachment class for attaching files to a {@link Swift_Mime_Message}.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Attachment extends Swift_Mime_Attachment
+{
+ /**
+ * Create a new Attachment.
+ *
+ * Details may be optionally provided to the constructor.
+ *
+ * @param string|Swift_OutputByteStream $data
+ * @param string $filename
+ * @param string $contentType
+ */
+ public function __construct($data = null, $filename = null, $contentType = null)
+ {
+ call_user_func_array(
+ array($this, 'Swift_Mime_Attachment::__construct'),
+ Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('mime.attachment')
+ );
+
+ $this->setBody($data);
+ $this->setFilename($filename);
+ if ($contentType) {
+ $this->setContentType($contentType);
+ }
+ }
+
+ /**
+ * Create a new Attachment.
+ *
+ * @param string|Swift_OutputByteStream $data
+ * @param string $filename
+ * @param string $contentType
+ *
+ * @return Swift_Mime_Attachment
+ */
+ public static function newInstance($data = null, $filename = null, $contentType = null)
+ {
+ return new self($data, $filename, $contentType);
+ }
+
+ /**
+ * Create a new Attachment from a filesystem path.
+ *
+ * @param string $path
+ * @param string $contentType optional
+ *
+ * @return Swift_Mime_Attachment
+ */
+ public static function fromPath($path, $contentType = null)
+ {
+ return self::newInstance()->setFile(
+ new Swift_ByteStream_FileByteStream($path),
+ $contentType
+ );
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/ByteStream/AbstractFilterableInputStream.php b/vendor/swiftmailer/classes/Swift/ByteStream/AbstractFilterableInputStream.php
new file mode 100644
index 00000000..3e597d17
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/ByteStream/AbstractFilterableInputStream.php
@@ -0,0 +1,179 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Provides the base functionality for an InputStream supporting filters.
+ *
+ * @author Chris Corbyn
+ */
+abstract class Swift_ByteStream_AbstractFilterableInputStream implements Swift_InputByteStream, Swift_Filterable
+{
+ /**
+ * Write sequence.
+ */
+ protected $_sequence = 0;
+
+ /**
+ * StreamFilters.
+ */
+ private $_filters = array();
+
+ /**
+ * A buffer for writing.
+ */
+ private $_writeBuffer = '';
+
+ /**
+ * Bound streams.
+ *
+ * @var Swift_InputByteStream[]
+ */
+ private $_mirrors = array();
+
+ /**
+ * Commit the given bytes to the storage medium immediately.
+ *
+ * @param string $bytes
+ */
+ abstract protected function _commit($bytes);
+
+ /**
+ * Flush any buffers/content with immediate effect.
+ */
+ abstract protected function _flush();
+
+ /**
+ * Add a StreamFilter to this InputByteStream.
+ *
+ * @param Swift_StreamFilter $filter
+ * @param string $key
+ */
+ public function addFilter(Swift_StreamFilter $filter, $key)
+ {
+ $this->_filters[$key] = $filter;
+ }
+
+ /**
+ * Remove an already present StreamFilter based on its $key.
+ *
+ * @param string $key
+ */
+ public function removeFilter($key)
+ {
+ unset($this->_filters[$key]);
+ }
+
+ /**
+ * Writes $bytes to the end of the stream.
+ *
+ * @param string $bytes
+ *
+ * @return int
+ *
+ * @throws Swift_IoException
+ */
+ public function write($bytes)
+ {
+ $this->_writeBuffer .= $bytes;
+ foreach ($this->_filters as $filter) {
+ if ($filter->shouldBuffer($this->_writeBuffer)) {
+ return;
+ }
+ }
+ $this->_doWrite($this->_writeBuffer);
+
+ return ++$this->_sequence;
+ }
+
+ /**
+ * For any bytes that are currently buffered inside the stream, force them
+ * off the buffer.
+ *
+ * @throws Swift_IoException
+ */
+ public function commit()
+ {
+ $this->_doWrite($this->_writeBuffer);
+ }
+
+ /**
+ * Attach $is to this stream.
+ *
+ * The stream acts as an observer, receiving all data that is written.
+ * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function bind(Swift_InputByteStream $is)
+ {
+ $this->_mirrors[] = $is;
+ }
+
+ /**
+ * Remove an already bound stream.
+ *
+ * If $is is not bound, no errors will be raised.
+ * If the stream currently has any buffered data it will be written to $is
+ * before unbinding occurs.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function unbind(Swift_InputByteStream $is)
+ {
+ foreach ($this->_mirrors as $k => $stream) {
+ if ($is === $stream) {
+ if ($this->_writeBuffer !== '') {
+ $stream->write($this->_writeBuffer);
+ }
+ unset($this->_mirrors[$k]);
+ }
+ }
+ }
+
+ /**
+ * Flush the contents of the stream (empty it) and set the internal pointer
+ * to the beginning.
+ *
+ * @throws Swift_IoException
+ */
+ public function flushBuffers()
+ {
+ if ($this->_writeBuffer !== '') {
+ $this->_doWrite($this->_writeBuffer);
+ }
+ $this->_flush();
+
+ foreach ($this->_mirrors as $stream) {
+ $stream->flushBuffers();
+ }
+ }
+
+ /** Run $bytes through all filters */
+ private function _filter($bytes)
+ {
+ foreach ($this->_filters as $filter) {
+ $bytes = $filter->filter($bytes);
+ }
+
+ return $bytes;
+ }
+
+ /** Just write the bytes to the stream */
+ private function _doWrite($bytes)
+ {
+ $this->_commit($this->_filter($bytes));
+
+ foreach ($this->_mirrors as $stream) {
+ $stream->write($bytes);
+ }
+
+ $this->_writeBuffer = '';
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/ByteStream/ArrayByteStream.php b/vendor/swiftmailer/classes/Swift/ByteStream/ArrayByteStream.php
new file mode 100644
index 00000000..043a5179
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/ByteStream/ArrayByteStream.php
@@ -0,0 +1,184 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Allows reading and writing of bytes to and from an array.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_ByteStream_ArrayByteStream implements Swift_InputByteStream, Swift_OutputByteStream
+{
+ /**
+ * The internal stack of bytes.
+ *
+ * @var string[]
+ */
+ private $_array = array();
+
+ /**
+ * The size of the stack
+ *
+ * @var int
+ */
+ private $_arraySize = 0;
+
+ /**
+ * The internal pointer offset.
+ *
+ * @var int
+ */
+ private $_offset = 0;
+
+ /**
+ * Bound streams.
+ *
+ * @var Swift_InputByteStream[]
+ */
+ private $_mirrors = array();
+
+ /**
+ * Create a new ArrayByteStream.
+ *
+ * If $stack is given the stream will be populated with the bytes it contains.
+ *
+ * @param mixed $stack of bytes in string or array form, optional
+ */
+ public function __construct($stack = null)
+ {
+ if (is_array($stack)) {
+ $this->_array = $stack;
+ $this->_arraySize = count($stack);
+ } elseif (is_string($stack)) {
+ $this->write($stack);
+ } else {
+ $this->_array = array();
+ }
+ }
+
+ /**
+ * Reads $length bytes from the stream into a string and moves the pointer
+ * through the stream by $length.
+ *
+ * If less bytes exist than are requested the
+ * remaining bytes are given instead. If no bytes are remaining at all, boolean
+ * false is returned.
+ *
+ * @param int $length
+ *
+ * @return string
+ */
+ public function read($length)
+ {
+ if ($this->_offset == $this->_arraySize) {
+ return false;
+ }
+
+ // Don't use array slice
+ $end = $length + $this->_offset;
+ $end = $this->_arraySize<$end
+ ?$this->_arraySize
+ :$end;
+ $ret = '';
+ for (; $this->_offset < $end; ++$this->_offset) {
+ $ret .= $this->_array[$this->_offset];
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Writes $bytes to the end of the stream.
+ *
+ * @param string $bytes
+ */
+ public function write($bytes)
+ {
+ $to_add = str_split($bytes);
+ foreach ($to_add as $value) {
+ $this->_array[] = $value;
+ }
+ $this->_arraySize = count($this->_array);
+
+ foreach ($this->_mirrors as $stream) {
+ $stream->write($bytes);
+ }
+ }
+
+ /**
+ * Not used.
+ */
+ public function commit()
+ {
+ }
+
+ /**
+ * Attach $is to this stream.
+ *
+ * The stream acts as an observer, receiving all data that is written.
+ * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function bind(Swift_InputByteStream $is)
+ {
+ $this->_mirrors[] = $is;
+ }
+
+ /**
+ * Remove an already bound stream.
+ *
+ * If $is is not bound, no errors will be raised.
+ * If the stream currently has any buffered data it will be written to $is
+ * before unbinding occurs.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function unbind(Swift_InputByteStream $is)
+ {
+ foreach ($this->_mirrors as $k => $stream) {
+ if ($is === $stream) {
+ unset($this->_mirrors[$k]);
+ }
+ }
+ }
+
+ /**
+ * Move the internal read pointer to $byteOffset in the stream.
+ *
+ * @param int $byteOffset
+ *
+ * @return bool
+ */
+ public function setReadPointer($byteOffset)
+ {
+ if ($byteOffset > $this->_arraySize) {
+ $byteOffset = $this->_arraySize;
+ } elseif ($byteOffset < 0) {
+ $byteOffset = 0;
+ }
+
+ $this->_offset = $byteOffset;
+ }
+
+ /**
+ * Flush the contents of the stream (empty it) and set the internal pointer
+ * to the beginning.
+ */
+ public function flushBuffers()
+ {
+ $this->_offset = 0;
+ $this->_array = array();
+ $this->_arraySize = 0;
+
+ foreach ($this->_mirrors as $stream) {
+ $stream->flushBuffers();
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/ByteStream/FileByteStream.php b/vendor/swiftmailer/classes/Swift/ByteStream/FileByteStream.php
new file mode 100644
index 00000000..9f3218f7
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/ByteStream/FileByteStream.php
@@ -0,0 +1,229 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Allows reading and writing of bytes to and from a file.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_ByteStream_FileByteStream extends Swift_ByteStream_AbstractFilterableInputStream implements Swift_FileStream
+{
+ /** The internal pointer offset */
+ private $_offset = 0;
+
+ /** The path to the file */
+ private $_path;
+
+ /** The mode this file is opened in for writing */
+ private $_mode;
+
+ /** A lazy-loaded resource handle for reading the file */
+ private $_reader;
+
+ /** A lazy-loaded resource handle for writing the file */
+ private $_writer;
+
+ /** If magic_quotes_runtime is on, this will be true */
+ private $_quotes = false;
+
+ /** If stream is seekable true/false, or null if not known */
+ private $_seekable = null;
+
+ /**
+ * Create a new FileByteStream for $path.
+ *
+ * @param string $path
+ * @param bool $writable if true
+ */
+ public function __construct($path, $writable = false)
+ {
+ if (empty($path)) {
+ throw new Swift_IoException('The path cannot be empty');
+ }
+ $this->_path = $path;
+ $this->_mode = $writable ? 'w+b' : 'rb';
+
+ if (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime() == 1) {
+ $this->_quotes = true;
+ }
+ }
+
+ /**
+ * Get the complete path to the file.
+ *
+ * @return string
+ */
+ public function getPath()
+ {
+ return $this->_path;
+ }
+
+ /**
+ * Reads $length bytes from the stream into a string and moves the pointer
+ * through the stream by $length.
+ *
+ * If less bytes exist than are requested the
+ * remaining bytes are given instead. If no bytes are remaining at all, boolean
+ * false is returned.
+ *
+ * @param int $length
+ *
+ * @return string|bool
+ *
+ * @throws Swift_IoException
+ */
+ public function read($length)
+ {
+ $fp = $this->_getReadHandle();
+ if (!feof($fp)) {
+ if ($this->_quotes) {
+ ini_set('magic_quotes_runtime', 0);
+ }
+ $bytes = fread($fp, $length);
+ if ($this->_quotes) {
+ ini_set('magic_quotes_runtime', 1);
+ }
+ $this->_offset = ftell($fp);
+
+ // If we read one byte after reaching the end of the file
+ // feof() will return false and an empty string is returned
+ if ($bytes === '' && feof($fp)) {
+ $this->_resetReadHandle();
+
+ return false;
+ }
+
+ return $bytes;
+ }
+
+ $this->_resetReadHandle();
+
+ return false;
+ }
+
+ /**
+ * Move the internal read pointer to $byteOffset in the stream.
+ *
+ * @param int $byteOffset
+ *
+ * @return bool
+ */
+ public function setReadPointer($byteOffset)
+ {
+ if (isset($this->_reader)) {
+ $this->_seekReadStreamToPosition($byteOffset);
+ }
+ $this->_offset = $byteOffset;
+ }
+
+ /** Just write the bytes to the file */
+ protected function _commit($bytes)
+ {
+ fwrite($this->_getWriteHandle(), $bytes);
+ $this->_resetReadHandle();
+ }
+
+ /** Not used */
+ protected function _flush()
+ {
+ }
+
+ /** Get the resource for reading */
+ private function _getReadHandle()
+ {
+ if (!isset($this->_reader)) {
+ if (!$this->_reader = fopen($this->_path, 'rb')) {
+ throw new Swift_IoException(
+ 'Unable to open file for reading [' . $this->_path . ']'
+ );
+ }
+ if ($this->_offset <> 0) {
+ $this->_getReadStreamSeekableStatus();
+ $this->_seekReadStreamToPosition($this->_offset);
+ }
+ }
+
+ return $this->_reader;
+ }
+
+ /** Get the resource for writing */
+ private function _getWriteHandle()
+ {
+ if (!isset($this->_writer)) {
+ if (!$this->_writer = fopen($this->_path, $this->_mode)) {
+ throw new Swift_IoException(
+ 'Unable to open file for writing [' . $this->_path . ']'
+ );
+ }
+ }
+
+ return $this->_writer;
+ }
+
+ /** Force a reload of the resource for reading */
+ private function _resetReadHandle()
+ {
+ if (isset($this->_reader)) {
+ fclose($this->_reader);
+ $this->_reader = null;
+ }
+ }
+
+ /** Check if ReadOnly Stream is seekable */
+ private function _getReadStreamSeekableStatus()
+ {
+ $metas = stream_get_meta_data($this->_reader);
+ $this->_seekable = $metas['seekable'];
+ }
+
+ /** Streams in a readOnly stream ensuring copy if needed */
+ private function _seekReadStreamToPosition($offset)
+ {
+ if ($this->_seekable===null) {
+ $this->_getReadStreamSeekableStatus();
+ }
+ if ($this->_seekable === false) {
+ $currentPos = ftell($this->_reader);
+ if ($currentPos<$offset) {
+ $toDiscard = $offset-$currentPos;
+ fread($this->_reader, $toDiscard);
+
+ return;
+ }
+ $this->_copyReadStream();
+ }
+ fseek($this->_reader, $offset, SEEK_SET);
+ }
+
+ /** Copy a readOnly Stream to ensure seekability */
+ private function _copyReadStream()
+ {
+ if ($tmpFile = fopen('php://temp/maxmemory:4096', 'w+b')) {
+ /* We have opened a php:// Stream Should work without problem */
+ } elseif (function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile())) {
+ /* We have opened a tmpfile */
+ } else {
+ throw new Swift_IoException('Unable to copy the file to make it seekable, sys_temp_dir is not writable, php://memory not available');
+ }
+ $currentPos = ftell($this->_reader);
+ fclose($this->_reader);
+ $source = fopen($this->_path, 'rb');
+ if (!$source) {
+ throw new Swift_IoException('Unable to open file for copying [' . $this->_path . ']');
+ }
+ fseek($tmpFile, 0, SEEK_SET);
+ while (!feof($source)) {
+ fwrite($tmpFile, fread($source, 4096));
+ }
+ fseek($tmpFile, $currentPos, SEEK_SET);
+ fclose($source);
+ $this->_reader = $tmpFile;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/ByteStream/TemporaryFileByteStream.php b/vendor/swiftmailer/classes/Swift/ByteStream/TemporaryFileByteStream.php
new file mode 100644
index 00000000..eb33151b
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/ByteStream/TemporaryFileByteStream.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+* This file is part of SwiftMailer.
+* (c) 2004-2009 Chris Corbyn
+*
+* For the full copyright and license information, please view the LICENSE
+* file that was distributed with this source code.
+*/
+
+/**
+ * @author Romain-Geissler
+ */
+class Swift_ByteStream_TemporaryFileByteStream extends Swift_ByteStream_FileByteStream
+{
+ public function __construct()
+ {
+ $filePath = tempnam(sys_get_temp_dir(), 'FileByteStream');
+
+ if ($filePath === false) {
+ throw new Swift_IoException('Failed to retrieve temporary file name.');
+ }
+
+ parent::__construct($filePath, true);
+ }
+
+ public function getContent()
+ {
+ if (($content = file_get_contents($this->getPath())) === false) {
+ throw new Swift_IoException('Failed to get temporary file content.');
+ }
+
+ return $content;
+ }
+
+ public function __destruct()
+ {
+ if (file_exists($this->getPath())) {
+ @unlink($this->getPath());
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/CharacterReader.php b/vendor/swiftmailer/classes/Swift/CharacterReader.php
new file mode 100644
index 00000000..febd77eb
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/CharacterReader.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Analyzes characters for a specific character set.
+ *
+ * @author Chris Corbyn
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+interface Swift_CharacterReader
+{
+ const MAP_TYPE_INVALID = 0x01;
+ const MAP_TYPE_FIXED_LEN = 0x02;
+ const MAP_TYPE_POSITIONS = 0x03;
+
+ /**
+ * Returns the complete character map
+ *
+ * @param string $string
+ * @param int $startOffset
+ * @param array $currentMap
+ * @param mixed $ignoredChars
+ *
+ * @return int
+ */
+ public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars);
+
+ /**
+ * Returns the mapType, see constants.
+ *
+ * @return int
+ */
+ public function getMapType();
+
+ /**
+ * Returns an integer which specifies how many more bytes to read.
+ *
+ * A positive integer indicates the number of more bytes to fetch before invoking
+ * this method again.
+ *
+ * A value of zero means this is already a valid character.
+ * A value of -1 means this cannot possibly be a valid character.
+ *
+ * @param integer[] $bytes
+ * @param int $size
+ *
+ * @return int
+ */
+ public function validateByteSequence($bytes, $size);
+
+ /**
+ * Returns the number of bytes which should be read to start each character.
+ *
+ * For fixed width character sets this should be the number of octets-per-character.
+ * For multibyte character sets this will probably be 1.
+ *
+ * @return int
+ */
+ public function getInitialByteSize();
+}
diff --git a/vendor/swiftmailer/classes/Swift/CharacterReader/GenericFixedWidthReader.php b/vendor/swiftmailer/classes/Swift/CharacterReader/GenericFixedWidthReader.php
new file mode 100644
index 00000000..d0c8698d
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/CharacterReader/GenericFixedWidthReader.php
@@ -0,0 +1,97 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Provides fixed-width byte sizes for reading fixed-width character sets.
+ *
+ * @author Chris Corbyn
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+class Swift_CharacterReader_GenericFixedWidthReader implements Swift_CharacterReader
+{
+ /**
+ * The number of bytes in a single character.
+ *
+ * @var int
+ */
+ private $_width;
+
+ /**
+ * Creates a new GenericFixedWidthReader using $width bytes per character.
+ *
+ * @param int $width
+ */
+ public function __construct($width)
+ {
+ $this->_width = $width;
+ }
+
+ /**
+ * Returns the complete character map.
+ *
+ * @param string $string
+ * @param int $startOffset
+ * @param array $currentMap
+ * @param mixed $ignoredChars
+ *
+ * @return int
+ */
+ public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars)
+ {
+ $strlen = strlen($string);
+ // % and / are CPU intensive, so, maybe find a better way
+ $ignored = $strlen % $this->_width;
+ $ignoredChars = substr($string, - $ignored);
+ $currentMap = $this->_width;
+
+ return ($strlen - $ignored) / $this->_width;
+ }
+
+ /**
+ * Returns the mapType.
+ *
+ * @return int
+ */
+ public function getMapType()
+ {
+ return self::MAP_TYPE_FIXED_LEN;
+ }
+
+ /**
+ * Returns an integer which specifies how many more bytes to read.
+ *
+ * A positive integer indicates the number of more bytes to fetch before invoking
+ * this method again.
+ *
+ * A value of zero means this is already a valid character.
+ * A value of -1 means this cannot possibly be a valid character.
+ *
+ * @param string $bytes
+ * @param int $size
+ *
+ * @return int
+ */
+ public function validateByteSequence($bytes, $size)
+ {
+ $needed = $this->_width - $size;
+
+ return ($needed > -1) ? $needed : -1;
+ }
+
+ /**
+ * Returns the number of bytes which should be read to start each character.
+ *
+ * @return int
+ */
+ public function getInitialByteSize()
+ {
+ return $this->_width;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/CharacterReader/UsAsciiReader.php b/vendor/swiftmailer/classes/Swift/CharacterReader/UsAsciiReader.php
new file mode 100644
index 00000000..a06ffe0a
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/CharacterReader/UsAsciiReader.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Analyzes US-ASCII characters.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_CharacterReader_UsAsciiReader implements Swift_CharacterReader
+{
+ /**
+ * Returns the complete character map.
+ *
+ * @param string $string
+ * @param int $startOffset
+ * @param array $currentMap
+ * @param string $ignoredChars
+ *
+ * @return int
+ */
+ public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars)
+ {
+ $strlen=strlen($string);
+ $ignoredChars='';
+ for ($i = 0; $i < $strlen; ++$i) {
+ if ($string[$i]>"\x07F") { // Invalid char
+ $currentMap[$i+$startOffset]=$string[$i];
+ }
+ }
+
+ return $strlen;
+ }
+
+ /**
+ * Returns mapType
+ *
+ * @return int mapType
+ */
+ public function getMapType()
+ {
+ return self::MAP_TYPE_INVALID;
+ }
+
+ /**
+ * Returns an integer which specifies how many more bytes to read.
+ *
+ * A positive integer indicates the number of more bytes to fetch before invoking
+ * this method again.
+ * A value of zero means this is already a valid character.
+ * A value of -1 means this cannot possibly be a valid character.
+ *
+ * @param string $bytes
+ * @param int $size
+ *
+ * @return int
+ */
+ public function validateByteSequence($bytes, $size)
+ {
+ $byte = reset($bytes);
+ if (1 == count($bytes) && $byte >= 0x00 && $byte <= 0x7F) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * Returns the number of bytes which should be read to start each character.
+ *
+ * @return int
+ */
+ public function getInitialByteSize()
+ {
+ return 1;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/CharacterReader/Utf8Reader.php b/vendor/swiftmailer/classes/Swift/CharacterReader/Utf8Reader.php
new file mode 100644
index 00000000..79c6f729
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/CharacterReader/Utf8Reader.php
@@ -0,0 +1,179 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Analyzes UTF-8 characters.
+ *
+ * @author Chris Corbyn
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+class Swift_CharacterReader_Utf8Reader implements Swift_CharacterReader
+{
+ /** Pre-computed for optimization */
+ private static $length_map=array(
+ // N=0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x0N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x2N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x4N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x6N
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7N
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x8N
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9N
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xAN
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBN
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xCN
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDN
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEN
+ 4,4,4,4,4,4,4,4,5,5,5,5,6,6,0,0 // 0xFN
+ );
+
+ private static $s_length_map=array(
+ "\x00"=>1, "\x01"=>1, "\x02"=>1, "\x03"=>1, "\x04"=>1, "\x05"=>1, "\x06"=>1, "\x07"=>1,
+ "\x08"=>1, "\x09"=>1, "\x0a"=>1, "\x0b"=>1, "\x0c"=>1, "\x0d"=>1, "\x0e"=>1, "\x0f"=>1,
+ "\x10"=>1, "\x11"=>1, "\x12"=>1, "\x13"=>1, "\x14"=>1, "\x15"=>1, "\x16"=>1, "\x17"=>1,
+ "\x18"=>1, "\x19"=>1, "\x1a"=>1, "\x1b"=>1, "\x1c"=>1, "\x1d"=>1, "\x1e"=>1, "\x1f"=>1,
+ "\x20"=>1, "\x21"=>1, "\x22"=>1, "\x23"=>1, "\x24"=>1, "\x25"=>1, "\x26"=>1, "\x27"=>1,
+ "\x28"=>1, "\x29"=>1, "\x2a"=>1, "\x2b"=>1, "\x2c"=>1, "\x2d"=>1, "\x2e"=>1, "\x2f"=>1,
+ "\x30"=>1, "\x31"=>1, "\x32"=>1, "\x33"=>1, "\x34"=>1, "\x35"=>1, "\x36"=>1, "\x37"=>1,
+ "\x38"=>1, "\x39"=>1, "\x3a"=>1, "\x3b"=>1, "\x3c"=>1, "\x3d"=>1, "\x3e"=>1, "\x3f"=>1,
+ "\x40"=>1, "\x41"=>1, "\x42"=>1, "\x43"=>1, "\x44"=>1, "\x45"=>1, "\x46"=>1, "\x47"=>1,
+ "\x48"=>1, "\x49"=>1, "\x4a"=>1, "\x4b"=>1, "\x4c"=>1, "\x4d"=>1, "\x4e"=>1, "\x4f"=>1,
+ "\x50"=>1, "\x51"=>1, "\x52"=>1, "\x53"=>1, "\x54"=>1, "\x55"=>1, "\x56"=>1, "\x57"=>1,
+ "\x58"=>1, "\x59"=>1, "\x5a"=>1, "\x5b"=>1, "\x5c"=>1, "\x5d"=>1, "\x5e"=>1, "\x5f"=>1,
+ "\x60"=>1, "\x61"=>1, "\x62"=>1, "\x63"=>1, "\x64"=>1, "\x65"=>1, "\x66"=>1, "\x67"=>1,
+ "\x68"=>1, "\x69"=>1, "\x6a"=>1, "\x6b"=>1, "\x6c"=>1, "\x6d"=>1, "\x6e"=>1, "\x6f"=>1,
+ "\x70"=>1, "\x71"=>1, "\x72"=>1, "\x73"=>1, "\x74"=>1, "\x75"=>1, "\x76"=>1, "\x77"=>1,
+ "\x78"=>1, "\x79"=>1, "\x7a"=>1, "\x7b"=>1, "\x7c"=>1, "\x7d"=>1, "\x7e"=>1, "\x7f"=>1,
+ "\x80"=>0, "\x81"=>0, "\x82"=>0, "\x83"=>0, "\x84"=>0, "\x85"=>0, "\x86"=>0, "\x87"=>0,
+ "\x88"=>0, "\x89"=>0, "\x8a"=>0, "\x8b"=>0, "\x8c"=>0, "\x8d"=>0, "\x8e"=>0, "\x8f"=>0,
+ "\x90"=>0, "\x91"=>0, "\x92"=>0, "\x93"=>0, "\x94"=>0, "\x95"=>0, "\x96"=>0, "\x97"=>0,
+ "\x98"=>0, "\x99"=>0, "\x9a"=>0, "\x9b"=>0, "\x9c"=>0, "\x9d"=>0, "\x9e"=>0, "\x9f"=>0,
+ "\xa0"=>0, "\xa1"=>0, "\xa2"=>0, "\xa3"=>0, "\xa4"=>0, "\xa5"=>0, "\xa6"=>0, "\xa7"=>0,
+ "\xa8"=>0, "\xa9"=>0, "\xaa"=>0, "\xab"=>0, "\xac"=>0, "\xad"=>0, "\xae"=>0, "\xaf"=>0,
+ "\xb0"=>0, "\xb1"=>0, "\xb2"=>0, "\xb3"=>0, "\xb4"=>0, "\xb5"=>0, "\xb6"=>0, "\xb7"=>0,
+ "\xb8"=>0, "\xb9"=>0, "\xba"=>0, "\xbb"=>0, "\xbc"=>0, "\xbd"=>0, "\xbe"=>0, "\xbf"=>0,
+ "\xc0"=>2, "\xc1"=>2, "\xc2"=>2, "\xc3"=>2, "\xc4"=>2, "\xc5"=>2, "\xc6"=>2, "\xc7"=>2,
+ "\xc8"=>2, "\xc9"=>2, "\xca"=>2, "\xcb"=>2, "\xcc"=>2, "\xcd"=>2, "\xce"=>2, "\xcf"=>2,
+ "\xd0"=>2, "\xd1"=>2, "\xd2"=>2, "\xd3"=>2, "\xd4"=>2, "\xd5"=>2, "\xd6"=>2, "\xd7"=>2,
+ "\xd8"=>2, "\xd9"=>2, "\xda"=>2, "\xdb"=>2, "\xdc"=>2, "\xdd"=>2, "\xde"=>2, "\xdf"=>2,
+ "\xe0"=>3, "\xe1"=>3, "\xe2"=>3, "\xe3"=>3, "\xe4"=>3, "\xe5"=>3, "\xe6"=>3, "\xe7"=>3,
+ "\xe8"=>3, "\xe9"=>3, "\xea"=>3, "\xeb"=>3, "\xec"=>3, "\xed"=>3, "\xee"=>3, "\xef"=>3,
+ "\xf0"=>4, "\xf1"=>4, "\xf2"=>4, "\xf3"=>4, "\xf4"=>4, "\xf5"=>4, "\xf6"=>4, "\xf7"=>4,
+ "\xf8"=>5, "\xf9"=>5, "\xfa"=>5, "\xfb"=>5, "\xfc"=>6, "\xfd"=>6, "\xfe"=>0, "\xff"=>0,
+ );
+
+ /**
+ * Returns the complete character map.
+ *
+ * @param string $string
+ * @param int $startOffset
+ * @param array $currentMap
+ * @param mixed $ignoredChars
+ *
+ * @return int
+ */
+ public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars)
+ {
+ if (!isset($currentMap['i']) || ! isset($currentMap['p'])) {
+ $currentMap['p'] = $currentMap['i'] = array();
+ }
+
+ $strlen=strlen($string);
+ $charPos=count($currentMap['p']);
+ $foundChars=0;
+ $invalid=false;
+ for ($i = 0; $i < $strlen; ++$i) {
+ $char = $string[$i];
+ $size = self::$s_length_map[$char];
+ if ($size == 0) {
+ /* char is invalid, we must wait for a resync */
+ $invalid = true;
+ continue;
+ } else {
+ if ($invalid == true) {
+ /* We mark the chars as invalid and start a new char */
+ $currentMap['p'][$charPos + $foundChars] = $startOffset + $i;
+ $currentMap['i'][$charPos + $foundChars] = true;
+ ++$foundChars;
+ $invalid = false;
+ }
+ if (($i + $size) > $strlen) {
+ $ignoredChars = substr($string, $i);
+ break;
+ }
+ for ($j = 1; $j < $size; ++$j) {
+ $char = $string[$i + $j];
+ if ($char > "\x7F" && $char < "\xC0") {
+ // Valid - continue parsing
+ } else {
+ /* char is invalid, we must wait for a resync */
+ $invalid = true;
+ continue 2;
+ }
+ }
+ /* Ok we got a complete char here */
+ $currentMap['p'][$charPos + $foundChars] = $startOffset + $i + $size;
+ $i += $j - 1;
+ ++$foundChars;
+ }
+ }
+
+ return $foundChars;
+ }
+
+ /**
+ * Returns mapType.
+ *
+ * @return int mapType
+ */
+ public function getMapType()
+ {
+ return self::MAP_TYPE_POSITIONS;
+ }
+
+ /**
+ * Returns an integer which specifies how many more bytes to read.
+ *
+ * A positive integer indicates the number of more bytes to fetch before invoking
+ * this method again.
+ * A value of zero means this is already a valid character.
+ * A value of -1 means this cannot possibly be a valid character.
+ *
+ * @param string $bytes
+ * @param int $size
+ *
+ * @return int
+ */
+ public function validateByteSequence($bytes, $size)
+ {
+ if ($size<1) {
+ return -1;
+ }
+ $needed = self::$length_map[$bytes[0]] - $size;
+
+ return ($needed > -1)
+ ? $needed
+ : -1
+ ;
+ }
+
+ /**
+ * Returns the number of bytes which should be read to start each character.
+ *
+ * @return int
+ */
+ public function getInitialByteSize()
+ {
+ return 1;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/CharacterReaderFactory.php b/vendor/swiftmailer/classes/Swift/CharacterReaderFactory.php
new file mode 100644
index 00000000..5bf38b8b
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/CharacterReaderFactory.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A factory for creating CharacterReaders.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_CharacterReaderFactory
+{
+ /**
+ * Returns a CharacterReader suitable for the charset applied.
+ *
+ * @param string $charset
+ *
+ * @return Swift_CharacterReader
+ */
+ public function getReaderFor($charset);
+}
diff --git a/vendor/swiftmailer/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php b/vendor/swiftmailer/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php
new file mode 100644
index 00000000..a10daf98
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php
@@ -0,0 +1,124 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Standard factory for creating CharacterReaders.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_CharacterReaderFactory_SimpleCharacterReaderFactory implements Swift_CharacterReaderFactory
+{
+ /**
+ * A map of charset patterns to their implementation classes.
+ *
+ * @var array
+ */
+ private static $_map = array();
+
+ /**
+ * Factories which have already been loaded.
+ *
+ * @var Swift_CharacterReaderFactory[]
+ */
+ private static $_loaded = array();
+
+ /**
+ * Creates a new CharacterReaderFactory.
+ */
+ public function __construct()
+ {
+ $this->init();
+ }
+
+ public function __wakeup()
+ {
+ $this->init();
+ }
+
+ public function init()
+ {
+ if (count(self::$_map) > 0) {
+ return;
+ }
+
+ $prefix = 'Swift_CharacterReader_';
+
+ $singleByte = array(
+ 'class' => $prefix . 'GenericFixedWidthReader',
+ 'constructor' => array(1)
+ );
+
+ $doubleByte = array(
+ 'class' => $prefix . 'GenericFixedWidthReader',
+ 'constructor' => array(2)
+ );
+
+ $fourBytes = array(
+ 'class' => $prefix . 'GenericFixedWidthReader',
+ 'constructor' => array(4)
+ );
+
+ // Utf-8
+ self::$_map['utf-?8'] = array(
+ 'class' => $prefix . 'Utf8Reader',
+ 'constructor' => array()
+ );
+
+ //7-8 bit charsets
+ self::$_map['(us-)?ascii'] = $singleByte;
+ self::$_map['(iso|iec)-?8859-?[0-9]+'] = $singleByte;
+ self::$_map['windows-?125[0-9]'] = $singleByte;
+ self::$_map['cp-?[0-9]+'] = $singleByte;
+ self::$_map['ansi'] = $singleByte;
+ self::$_map['macintosh'] = $singleByte;
+ self::$_map['koi-?7'] = $singleByte;
+ self::$_map['koi-?8-?.+'] = $singleByte;
+ self::$_map['mik'] = $singleByte;
+ self::$_map['(cork|t1)'] = $singleByte;
+ self::$_map['v?iscii'] = $singleByte;
+
+ //16 bits
+ self::$_map['(ucs-?2|utf-?16)'] = $doubleByte;
+
+ //32 bits
+ self::$_map['(ucs-?4|utf-?32)'] = $fourBytes;
+
+ // Fallback
+ self::$_map['.*'] = $singleByte;
+ }
+
+ /**
+ * Returns a CharacterReader suitable for the charset applied.
+ *
+ * @param string $charset
+ *
+ * @return Swift_CharacterReader
+ */
+ public function getReaderFor($charset)
+ {
+ $charset = trim(strtolower($charset));
+ foreach (self::$_map as $pattern => $spec) {
+ $re = '/^' . $pattern . '$/D';
+ if (preg_match($re, $charset)) {
+ if (!array_key_exists($pattern, self::$_loaded)) {
+ $reflector = new ReflectionClass($spec['class']);
+ if ($reflector->getConstructor()) {
+ $reader = $reflector->newInstanceArgs($spec['constructor']);
+ } else {
+ $reader = $reflector->newInstance();
+ }
+ self::$_loaded[$pattern] = $reader;
+ }
+
+ return self::$_loaded[$pattern];
+ }
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/CharacterStream.php b/vendor/swiftmailer/classes/Swift/CharacterStream.php
new file mode 100644
index 00000000..aa46779e
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/CharacterStream.php
@@ -0,0 +1,89 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An abstract means of reading and writing data in terms of characters as opposed
+ * to bytes.
+ *
+ * Classes implementing this interface may use a subsystem which requires less
+ * memory than working with large strings of data.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_CharacterStream
+{
+ /**
+ * Set the character set used in this CharacterStream.
+ *
+ * @param string $charset
+ */
+ public function setCharacterSet($charset);
+
+ /**
+ * Set the CharacterReaderFactory for multi charset support.
+ *
+ * @param Swift_CharacterReaderFactory $factory
+ */
+ public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory);
+
+ /**
+ * Overwrite this character stream using the byte sequence in the byte stream.
+ *
+ * @param Swift_OutputByteStream $os output stream to read from
+ */
+ public function importByteStream(Swift_OutputByteStream $os);
+
+ /**
+ * Import a string a bytes into this CharacterStream, overwriting any existing
+ * data in the stream.
+ *
+ * @param string $string
+ */
+ public function importString($string);
+
+ /**
+ * Read $length characters from the stream and move the internal pointer
+ * $length further into the stream.
+ *
+ * @param int $length
+ *
+ * @return string
+ */
+ public function read($length);
+
+ /**
+ * Read $length characters from the stream and return a 1-dimensional array
+ * containing there octet values.
+ *
+ * @param int $length
+ *
+ * @return int[]
+ */
+ public function readBytes($length);
+
+ /**
+ * Write $chars to the end of the stream.
+ *
+ * @param string $chars
+ */
+ public function write($chars);
+
+ /**
+ * Move the internal pointer to $charOffset in the stream.
+ *
+ * @param int $charOffset
+ */
+ public function setPointer($charOffset);
+
+ /**
+ * Empty the stream and reset the internal pointer.
+ */
+ public function flushContents();
+}
diff --git a/vendor/swiftmailer/classes/Swift/CharacterStream/ArrayCharacterStream.php b/vendor/swiftmailer/classes/Swift/CharacterStream/ArrayCharacterStream.php
new file mode 100644
index 00000000..c5378135
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/CharacterStream/ArrayCharacterStream.php
@@ -0,0 +1,294 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A CharacterStream implementation which stores characters in an internal array.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_CharacterStream_ArrayCharacterStream implements Swift_CharacterStream
+{
+ /** A map of byte values and their respective characters */
+ private static $_charMap;
+
+ /** A map of characters and their derivative byte values */
+ private static $_byteMap;
+
+ /** The char reader (lazy-loaded) for the current charset */
+ private $_charReader;
+
+ /** A factory for creating CharacterReader instances */
+ private $_charReaderFactory;
+
+ /** The character set this stream is using */
+ private $_charset;
+
+ /** Array of characters */
+ private $_array = array();
+
+ /** Size of the array of character */
+ private $_array_size = array();
+
+ /** The current character offset in the stream */
+ private $_offset = 0;
+
+ /**
+ * Create a new CharacterStream with the given $chars, if set.
+ *
+ * @param Swift_CharacterReaderFactory $factory for loading validators
+ * @param string $charset used in the stream
+ */
+ public function __construct(Swift_CharacterReaderFactory $factory, $charset)
+ {
+ self::_initializeMaps();
+ $this->setCharacterReaderFactory($factory);
+ $this->setCharacterSet($charset);
+ }
+
+ /**
+ * Set the character set used in this CharacterStream.
+ *
+ * @param string $charset
+ */
+ public function setCharacterSet($charset)
+ {
+ $this->_charset = $charset;
+ $this->_charReader = null;
+ }
+
+ /**
+ * Set the CharacterReaderFactory for multi charset support.
+ *
+ * @param Swift_CharacterReaderFactory $factory
+ */
+ public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
+ {
+ $this->_charReaderFactory = $factory;
+ }
+
+ /**
+ * Overwrite this character stream using the byte sequence in the byte stream.
+ *
+ * @param Swift_OutputByteStream $os output stream to read from
+ */
+ public function importByteStream(Swift_OutputByteStream $os)
+ {
+ if (!isset($this->_charReader)) {
+ $this->_charReader = $this->_charReaderFactory
+ ->getReaderFor($this->_charset);
+ }
+
+ $startLength = $this->_charReader->getInitialByteSize();
+ while (false !== $bytes = $os->read($startLength)) {
+ $c = array();
+ for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) {
+ $c[] = self::$_byteMap[$bytes[$i]];
+ }
+ $size = count($c);
+ $need = $this->_charReader
+ ->validateByteSequence($c, $size);
+ if ($need > 0 &&
+ false !== $bytes = $os->read($need))
+ {
+ for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) {
+ $c[] = self::$_byteMap[$bytes[$i]];
+ }
+ }
+ $this->_array[] = $c;
+ ++$this->_array_size;
+ }
+ }
+
+ /**
+ * Import a string a bytes into this CharacterStream, overwriting any existing
+ * data in the stream.
+ *
+ * @param string $string
+ */
+ public function importString($string)
+ {
+ $this->flushContents();
+ $this->write($string);
+ }
+
+ /**
+ * Read $length characters from the stream and move the internal pointer
+ * $length further into the stream.
+ *
+ * @param int $length
+ *
+ * @return string
+ */
+ public function read($length)
+ {
+ if ($this->_offset == $this->_array_size) {
+ return false;
+ }
+
+ // Don't use array slice
+ $arrays = array();
+ $end = $length + $this->_offset;
+ for ($i = $this->_offset; $i < $end; ++$i) {
+ if (!isset($this->_array[$i])) {
+ break;
+ }
+ $arrays[] = $this->_array[$i];
+ }
+ $this->_offset += $i - $this->_offset; // Limit function calls
+ $chars = false;
+ foreach ($arrays as $array) {
+ $chars .= implode('', array_map('chr', $array));
+ }
+
+ return $chars;
+ }
+
+ /**
+ * Read $length characters from the stream and return a 1-dimensional array
+ * containing there octet values.
+ *
+ * @param int $length
+ *
+ * @return integer[]
+ */
+ public function readBytes($length)
+ {
+ if ($this->_offset == $this->_array_size) {
+ return false;
+ }
+ $arrays = array();
+ $end = $length + $this->_offset;
+ for ($i = $this->_offset; $i < $end; ++$i) {
+ if (!isset($this->_array[$i])) {
+ break;
+ }
+ $arrays[] = $this->_array[$i];
+ }
+ $this->_offset += ($i - $this->_offset); // Limit function calls
+
+ return call_user_func_array('array_merge', $arrays);
+ }
+
+ /**
+ * Write $chars to the end of the stream.
+ *
+ * @param string $chars
+ */
+ public function write($chars)
+ {
+ if (!isset($this->_charReader)) {
+ $this->_charReader = $this->_charReaderFactory->getReaderFor(
+ $this->_charset);
+ }
+
+ $startLength = $this->_charReader->getInitialByteSize();
+
+ $fp = fopen('php://memory', 'w+b');
+ fwrite($fp, $chars);
+ unset($chars);
+ fseek($fp, 0, SEEK_SET);
+
+ $buffer = array(0);
+ $buf_pos = 1;
+ $buf_len = 1;
+ $has_datas = true;
+ do {
+ $bytes = array();
+ // Buffer Filing
+ if ($buf_len - $buf_pos < $startLength) {
+ $buf = array_splice($buffer, $buf_pos);
+ $new = $this->_reloadBuffer($fp, 100);
+ if ($new) {
+ $buffer = array_merge($buf, $new);
+ $buf_len = count($buffer);
+ $buf_pos = 0;
+ } else {
+ $has_datas = false;
+ }
+ }
+ if ($buf_len - $buf_pos > 0) {
+ $size = 0;
+ for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) {
+ ++$size;
+ $bytes[] = $buffer[$buf_pos++];
+ }
+ $need = $this->_charReader->validateByteSequence(
+ $bytes, $size);
+ if ($need > 0) {
+ if ($buf_len - $buf_pos < $need) {
+ $new = $this->_reloadBuffer($fp, $need);
+
+ if ($new) {
+ $buffer = array_merge($buffer, $new);
+ $buf_len = count($buffer);
+ }
+ }
+ for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) {
+ $bytes[] = $buffer[$buf_pos++];
+ }
+ }
+ $this->_array[] = $bytes;
+ ++$this->_array_size;
+ }
+ } while ($has_datas);
+
+ fclose($fp);
+ }
+
+ /**
+ * Move the internal pointer to $charOffset in the stream.
+ *
+ * @param int $charOffset
+ */
+ public function setPointer($charOffset)
+ {
+ if ($charOffset > $this->_array_size) {
+ $charOffset = $this->_array_size;
+ } elseif ($charOffset < 0) {
+ $charOffset = 0;
+ }
+ $this->_offset = $charOffset;
+ }
+
+ /**
+ * Empty the stream and reset the internal pointer.
+ */
+ public function flushContents()
+ {
+ $this->_offset = 0;
+ $this->_array = array();
+ $this->_array_size = 0;
+ }
+
+ private function _reloadBuffer($fp, $len)
+ {
+ if (!feof($fp) && ($bytes = fread($fp, $len)) !== false) {
+ $buf = array();
+ for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) {
+ $buf[] = self::$_byteMap[$bytes[$i]];
+ }
+
+ return $buf;
+ }
+
+ return false;
+ }
+
+ private static function _initializeMaps()
+ {
+ if (!isset(self::$_charMap)) {
+ self::$_charMap = array();
+ for ($byte = 0; $byte < 256; ++$byte) {
+ self::$_charMap[$byte] = chr($byte);
+ }
+ self::$_byteMap = array_flip(self::$_charMap);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/CharacterStream/NgCharacterStream.php b/vendor/swiftmailer/classes/Swift/CharacterStream/NgCharacterStream.php
new file mode 100644
index 00000000..bd44658d
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/CharacterStream/NgCharacterStream.php
@@ -0,0 +1,275 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A CharacterStream implementation which stores characters in an internal array.
+ *
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+
+class Swift_CharacterStream_NgCharacterStream implements Swift_CharacterStream
+{
+ /**
+ * The char reader (lazy-loaded) for the current charset.
+ *
+ * @var Swift_CharacterReader
+ */
+ private $_charReader;
+
+ /**
+ * A factory for creating CharacterReader instances.
+ *
+ * @var Swift_CharacterReaderFactory
+ */
+ private $_charReaderFactory;
+
+ /**
+ * The character set this stream is using.
+ *
+ * @var string
+ */
+ private $_charset;
+
+ /**
+ * The data's stored as-is.
+ *
+ * @var string
+ */
+ private $_datas = '';
+
+ /**
+ * Number of bytes in the stream
+ *
+ * @var int
+ */
+ private $_datasSize = 0;
+
+ /**
+ * Map.
+ *
+ * @var mixed
+ */
+ private $_map;
+
+ /**
+ * Map Type.
+ *
+ * @var int
+ */
+ private $_mapType = 0;
+
+ /**
+ * Number of characters in the stream.
+ *
+ * @var int
+ */
+ private $_charCount = 0;
+
+ /**
+ * Position in the stream.
+ *
+ * @var int
+ */
+ private $_currentPos = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param Swift_CharacterReaderFactory $factory
+ * @param string $charset
+ */
+ public function __construct(Swift_CharacterReaderFactory $factory, $charset)
+ {
+ $this->setCharacterReaderFactory($factory);
+ $this->setCharacterSet($charset);
+ }
+
+ /* -- Changing parameters of the stream -- */
+
+ /**
+ * Set the character set used in this CharacterStream.
+ *
+ * @param string $charset
+ */
+ public function setCharacterSet($charset)
+ {
+ $this->_charset = $charset;
+ $this->_charReader = null;
+ $this->_mapType = 0;
+ }
+
+ /**
+ * Set the CharacterReaderFactory for multi charset support.
+ *
+ * @param Swift_CharacterReaderFactory $factory
+ */
+ public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory)
+ {
+ $this->_charReaderFactory = $factory;
+ }
+
+ /**
+ * @see Swift_CharacterStream::flushContents()
+ */
+ public function flushContents()
+ {
+ $this->_datas = null;
+ $this->_map = null;
+ $this->_charCount = 0;
+ $this->_currentPos = 0;
+ $this->_datasSize = 0;
+ }
+
+ /**
+ * @see Swift_CharacterStream::importByteStream()
+ *
+ * @param Swift_OutputByteStream $os
+ */
+ public function importByteStream(Swift_OutputByteStream $os)
+ {
+ $this->flushContents();
+ $blocks=512;
+ $os->setReadPointer(0);
+ while(false!==($read = $os->read($blocks)))
+ $this->write($read);
+ }
+
+ /**
+ * @see Swift_CharacterStream::importString()
+ *
+ * @param string $string
+ */
+ public function importString($string)
+ {
+ $this->flushContents();
+ $this->write($string);
+ }
+
+ /**
+ * @see Swift_CharacterStream::read()
+ *
+ * @param int $length
+ *
+ * @return string
+ */
+ public function read($length)
+ {
+ if ($this->_currentPos>=$this->_charCount) {
+ return false;
+ }
+ $ret=false;
+ $length = ($this->_currentPos+$length > $this->_charCount)
+ ? $this->_charCount - $this->_currentPos
+ : $length;
+ switch ($this->_mapType) {
+ case Swift_CharacterReader::MAP_TYPE_FIXED_LEN:
+ $len = $length*$this->_map;
+ $ret = substr($this->_datas,
+ $this->_currentPos * $this->_map,
+ $len);
+ $this->_currentPos += $length;
+ break;
+
+ case Swift_CharacterReader::MAP_TYPE_INVALID:
+ $end = $this->_currentPos + $length;
+ $end = $end > $this->_charCount
+ ?$this->_charCount
+ :$end;
+ $ret = '';
+ for (; $this->_currentPos < $length; ++$this->_currentPos) {
+ if (isset ($this->_map[$this->_currentPos])) {
+ $ret .= '?';
+ } else {
+ $ret .= $this->_datas[$this->_currentPos];
+ }
+ }
+ break;
+
+ case Swift_CharacterReader::MAP_TYPE_POSITIONS:
+ $end = $this->_currentPos + $length;
+ $end = $end > $this->_charCount
+ ?$this->_charCount
+ :$end;
+ $ret = '';
+ $start = 0;
+ if ($this->_currentPos>0) {
+ $start = $this->_map['p'][$this->_currentPos-1];
+ }
+ $to = $start;
+ for (; $this->_currentPos < $end; ++$this->_currentPos) {
+ if (isset($this->_map['i'][$this->_currentPos])) {
+ $ret .= substr($this->_datas, $start, $to - $start).'?';
+ $start = $this->_map['p'][$this->_currentPos];
+ } else {
+ $to = $this->_map['p'][$this->_currentPos];
+ }
+ }
+ $ret .= substr($this->_datas, $start, $to - $start);
+ break;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * @see Swift_CharacterStream::readBytes()
+ *
+ * @param int $length
+ *
+ * @return integer[]
+ */
+ public function readBytes($length)
+ {
+ $read=$this->read($length);
+ if ($read!==false) {
+ $ret = array_map('ord', str_split($read, 1));
+
+ return $ret;
+ }
+
+ return false;
+ }
+
+ /**
+ * @see Swift_CharacterStream::setPointer()
+ *
+ * @param int $charOffset
+ */
+ public function setPointer($charOffset)
+ {
+ if ($this->_charCount<$charOffset) {
+ $charOffset=$this->_charCount;
+ }
+ $this->_currentPos = $charOffset;
+ }
+
+ /**
+ * @see Swift_CharacterStream::write()
+ *
+ * @param string $chars
+ */
+ public function write($chars)
+ {
+ if (!isset($this->_charReader)) {
+ $this->_charReader = $this->_charReaderFactory->getReaderFor(
+ $this->_charset);
+ $this->_map = array();
+ $this->_mapType = $this->_charReader->getMapType();
+ }
+ $ignored='';
+ $this->_datas .= $chars;
+ $this->_charCount += $this->_charReader->getCharPositions(substr($this->_datas, $this->_datasSize), $this->_datasSize, $this->_map, $ignored);
+ if ($ignored!==false) {
+ $this->_datasSize=strlen($this->_datas)-strlen($ignored);
+ } else {
+ $this->_datasSize=strlen($this->_datas);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/ConfigurableSpool.php b/vendor/swiftmailer/classes/Swift/ConfigurableSpool.php
new file mode 100644
index 00000000..df87527f
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/ConfigurableSpool.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2009 Fabien Potencier <fabien.potencier@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Base class for Spools (implements time and message limits).
+ *
+ * @author Fabien Potencier
+ */
+abstract class Swift_ConfigurableSpool implements Swift_Spool
+{
+ /** The maximum number of messages to send per flush */
+ private $_message_limit;
+
+ /** The time limit per flush */
+ private $_time_limit;
+
+ /**
+ * Sets the maximum number of messages to send per flush.
+ *
+ * @param int $limit
+ */
+ public function setMessageLimit($limit)
+ {
+ $this->_message_limit = (int) $limit;
+ }
+
+ /**
+ * Gets the maximum number of messages to send per flush.
+ *
+ * @return int The limit
+ */
+ public function getMessageLimit()
+ {
+ return $this->_message_limit;
+ }
+
+ /**
+ * Sets the time limit (in seconds) per flush.
+ *
+ * @param int $limit The limit
+ */
+ public function setTimeLimit($limit)
+ {
+ $this->_time_limit = (int) $limit;
+ }
+
+ /**
+ * Gets the time limit (in seconds) per flush.
+ *
+ * @return int The limit
+ */
+ public function getTimeLimit()
+ {
+ return $this->_time_limit;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/DependencyContainer.php b/vendor/swiftmailer/classes/Swift/DependencyContainer.php
new file mode 100644
index 00000000..adcd27ed
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/DependencyContainer.php
@@ -0,0 +1,370 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Dependency Injection container.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_DependencyContainer
+{
+ /** Constant for literal value types */
+ const TYPE_VALUE = 0x0001;
+
+ /** Constant for new instance types */
+ const TYPE_INSTANCE = 0x0010;
+
+ /** Constant for shared instance types */
+ const TYPE_SHARED = 0x0100;
+
+ /** Constant for aliases */
+ const TYPE_ALIAS = 0x1000;
+
+ /** Singleton instance */
+ private static $_instance = null;
+
+ /** The data container */
+ private $_store = array();
+
+ /** The current endpoint in the data container */
+ private $_endPoint;
+
+ /**
+ * Constructor should not be used.
+ *
+ * Use {@link getInstance()} instead.
+ */
+ public function __construct() { }
+
+ /**
+ * Returns a singleton of the DependencyContainer.
+ *
+ * @return Swift_DependencyContainer
+ */
+ public static function getInstance()
+ {
+ if (!isset(self::$_instance)) {
+ self::$_instance = new self();
+ }
+
+ return self::$_instance;
+ }
+
+ /**
+ * List the names of all items stored in the Container.
+ *
+ * @return array
+ */
+ public function listItems()
+ {
+ return array_keys($this->_store);
+ }
+
+ /**
+ * Test if an item is registered in this container with the given name.
+ *
+ * @see register()
+ *
+ * @param string $itemName
+ *
+ * @return bool
+ */
+ public function has($itemName)
+ {
+ return array_key_exists($itemName, $this->_store)
+ && isset($this->_store[$itemName]['lookupType']);
+ }
+
+ /**
+ * Lookup the item with the given $itemName.
+ *
+ * @see register()
+ *
+ * @param string $itemName
+ *
+ * @return mixed
+ *
+ * @throws Swift_DependencyException If the dependency is not found
+ */
+ public function lookup($itemName)
+ {
+ if (!$this->has($itemName)) {
+ throw new Swift_DependencyException(
+ 'Cannot lookup dependency "' . $itemName . '" since it is not registered.'
+ );
+ }
+
+ switch ($this->_store[$itemName]['lookupType']) {
+ case self::TYPE_ALIAS:
+ return $this->_createAlias($itemName);
+ case self::TYPE_VALUE:
+ return $this->_getValue($itemName);
+ case self::TYPE_INSTANCE:
+ return $this->_createNewInstance($itemName);
+ case self::TYPE_SHARED:
+ return $this->_createSharedInstance($itemName);
+ }
+ }
+
+ /**
+ * Create an array of arguments passed to the constructor of $itemName.
+ *
+ * @param string $itemName
+ *
+ * @return array
+ */
+ public function createDependenciesFor($itemName)
+ {
+ $args = array();
+ if (isset($this->_store[$itemName]['args'])) {
+ $args = $this->_resolveArgs($this->_store[$itemName]['args']);
+ }
+
+ return $args;
+ }
+
+ /**
+ * Register a new dependency with $itemName.
+ *
+ * This method returns the current DependencyContainer instance because it
+ * requires the use of the fluid interface to set the specific details for the
+ * dependency.
+ * @see asNewInstanceOf(), asSharedInstanceOf(), asValue()
+ *
+ * @param string $itemName
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function register($itemName)
+ {
+ $this->_store[$itemName] = array();
+ $this->_endPoint =& $this->_store[$itemName];
+
+ return $this;
+ }
+
+ /**
+ * Specify the previously registered item as a literal value.
+ *
+ * {@link register()} must be called before this will work.
+ *
+ * @param mixed $value
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function asValue($value)
+ {
+ $endPoint =& $this->_getEndPoint();
+ $endPoint['lookupType'] = self::TYPE_VALUE;
+ $endPoint['value'] = $value;
+
+ return $this;
+ }
+
+ /**
+ * Specify the previously registered item as an alias of another item.
+ *
+ * @param string $lookup
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function asAliasOf($lookup)
+ {
+ $endPoint =& $this->_getEndPoint();
+ $endPoint['lookupType'] = self::TYPE_ALIAS;
+ $endPoint['ref'] = $lookup;
+
+ return $this;
+ }
+
+ /**
+ * Specify the previously registered item as a new instance of $className.
+ *
+ * {@link register()} must be called before this will work.
+ * Any arguments can be set with {@link withDependencies()},
+ * {@link addConstructorValue()} or {@link addConstructorLookup()}.
+ *
+ * @see withDependencies(), addConstructorValue(), addConstructorLookup()
+ *
+ * @param string $className
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function asNewInstanceOf($className)
+ {
+ $endPoint =& $this->_getEndPoint();
+ $endPoint['lookupType'] = self::TYPE_INSTANCE;
+ $endPoint['className'] = $className;
+
+ return $this;
+ }
+
+ /**
+ * Specify the previously registered item as a shared instance of $className.
+ *
+ * {@link register()} must be called before this will work.
+ *
+ * @param string $className
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function asSharedInstanceOf($className)
+ {
+ $endPoint =& $this->_getEndPoint();
+ $endPoint['lookupType'] = self::TYPE_SHARED;
+ $endPoint['className'] = $className;
+
+ return $this;
+ }
+
+ /**
+ * Specify a list of injected dependencies for the previously registered item.
+ *
+ * This method takes an array of lookup names.
+ *
+ * @see addConstructorValue(), addConstructorLookup()
+ *
+ * @param array $lookups
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function withDependencies(array $lookups)
+ {
+ $endPoint =& $this->_getEndPoint();
+ $endPoint['args'] = array();
+ foreach ($lookups as $lookup) {
+ $this->addConstructorLookup($lookup);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Specify a literal (non looked up) value for the constructor of the
+ * previously registered item.
+ *
+ * @see withDependencies(), addConstructorLookup()
+ *
+ * @param mixed $value
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function addConstructorValue($value)
+ {
+ $endPoint =& $this->_getEndPoint();
+ if (!isset($endPoint['args'])) {
+ $endPoint['args'] = array();
+ }
+ $endPoint['args'][] = array('type' => 'value', 'item' => $value);
+
+ return $this;
+ }
+
+ /**
+ * Specify a dependency lookup for the constructor of the previously
+ * registered item.
+ *
+ * @see withDependencies(), addConstructorValue()
+ *
+ * @param string $lookup
+ *
+ * @return Swift_DependencyContainer
+ */
+ public function addConstructorLookup($lookup)
+ {
+ $endPoint =& $this->_getEndPoint();
+ if (!isset($this->_endPoint['args'])) {
+ $endPoint['args'] = array();
+ }
+ $endPoint['args'][] = array('type' => 'lookup', 'item' => $lookup);
+
+ return $this;
+ }
+
+ /** Get the literal value with $itemName */
+ private function _getValue($itemName)
+ {
+ return $this->_store[$itemName]['value'];
+ }
+
+ /** Resolve an alias to another item */
+ private function _createAlias($itemName)
+ {
+ return $this->lookup($this->_store[$itemName]['ref']);
+ }
+
+ /** Create a fresh instance of $itemName */
+ private function _createNewInstance($itemName)
+ {
+ $reflector = new ReflectionClass($this->_store[$itemName]['className']);
+ if ($reflector->getConstructor()) {
+ return $reflector->newInstanceArgs(
+ $this->createDependenciesFor($itemName)
+ );
+ } else {
+ return $reflector->newInstance();
+ }
+ }
+
+ /** Create and register a shared instance of $itemName */
+ private function _createSharedInstance($itemName)
+ {
+ if (!isset($this->_store[$itemName]['instance'])) {
+ $this->_store[$itemName]['instance'] = $this->_createNewInstance($itemName);
+ }
+
+ return $this->_store[$itemName]['instance'];
+ }
+
+ /** Get the current endpoint in the store */
+ private function &_getEndPoint()
+ {
+ if (!isset($this->_endPoint)) {
+ throw new BadMethodCallException(
+ 'Component must first be registered by calling register()'
+ );
+ }
+
+ return $this->_endPoint;
+ }
+
+ /** Get an argument list with dependencies resolved */
+ private function _resolveArgs(array $args)
+ {
+ $resolved = array();
+ foreach ($args as $argDefinition) {
+ switch ($argDefinition['type']) {
+ case 'lookup':
+ $resolved[] = $this->_lookupRecursive($argDefinition['item']);
+ break;
+ case 'value':
+ $resolved[] = $argDefinition['item'];
+ break;
+ }
+ }
+
+ return $resolved;
+ }
+
+ /** Resolve a single dependency with an collections */
+ private function _lookupRecursive($item)
+ {
+ if (is_array($item)) {
+ $collection = array();
+ foreach ($item as $k => $v) {
+ $collection[$k] = $this->_lookupRecursive($v);
+ }
+
+ return $collection;
+ } else {
+ return $this->lookup($item);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/DependencyException.php b/vendor/swiftmailer/classes/Swift/DependencyException.php
new file mode 100644
index 00000000..0a96232e
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/DependencyException.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * DependencyException gets thrown when a requested dependency is missing.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_DependencyException extends Swift_SwiftException
+{
+ /**
+ * Create a new DependencyException with $message.
+ *
+ * @param string $message
+ */
+ public function __construct($message)
+ {
+ parent::__construct($message);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/EmbeddedFile.php b/vendor/swiftmailer/classes/Swift/EmbeddedFile.php
new file mode 100644
index 00000000..486ad608
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/EmbeddedFile.php
@@ -0,0 +1,69 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An embedded file, in a multipart message.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_EmbeddedFile extends Swift_Mime_EmbeddedFile
+{
+ /**
+ * Create a new EmbeddedFile.
+ *
+ * Details may be optionally provided to the constructor.
+ *
+ * @param string|Swift_OutputByteStream $data
+ * @param string $filename
+ * @param string $contentType
+ */
+ public function __construct($data = null, $filename = null, $contentType = null)
+ {
+ call_user_func_array(
+ array($this, 'Swift_Mime_EmbeddedFile::__construct'),
+ Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('mime.embeddedfile')
+ );
+
+ $this->setBody($data);
+ $this->setFilename($filename);
+ if ($contentType) {
+ $this->setContentType($contentType);
+ }
+ }
+
+ /**
+ * Create a new EmbeddedFile.
+ *
+ * @param string|Swift_OutputByteStream $data
+ * @param string $filename
+ * @param string $contentType
+ *
+ * @return Swift_Mime_EmbeddedFile
+ */
+ public static function newInstance($data = null, $filename = null, $contentType = null)
+ {
+ return new self($data, $filename, $contentType);
+ }
+
+ /**
+ * Create a new EmbeddedFile from a filesystem path.
+ *
+ * @param string $path
+ *
+ * @return Swift_Mime_EmbeddedFile
+ */
+ public static function fromPath($path)
+ {
+ return self::newInstance()->setFile(
+ new Swift_ByteStream_FileByteStream($path)
+ );
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Encoder.php b/vendor/swiftmailer/classes/Swift/Encoder.php
new file mode 100644
index 00000000..7c656424
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Encoder.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Interface for all Encoder schemes.
+ * @author Chris Corbyn
+ */
+interface Swift_Encoder extends Swift_Mime_CharsetObserver
+{
+ /**
+ * Encode a given string to produce an encoded string.
+ *
+ * @param string $string
+ * @param int $firstLineOffset if first line needs to be shorter
+ * @param int $maxLineLength - 0 indicates the default length for this encoding
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Encoder/Base64Encoder.php b/vendor/swiftmailer/classes/Swift/Encoder/Base64Encoder.php
new file mode 100644
index 00000000..1da107ae
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Encoder/Base64Encoder.php
@@ -0,0 +1,58 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles Base 64 Encoding in Swift Mailer.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Encoder_Base64Encoder implements Swift_Encoder
+{
+ /**
+ * Takes an unencoded string and produces a Base64 encoded string from it.
+ *
+ * Base64 encoded strings have a maximum line length of 76 characters.
+ * If the first line needs to be shorter, indicate the difference with
+ * $firstLineOffset.
+ *
+ * @param string $string to encode
+ * @param int $firstLineOffset
+ * @param int $maxLineLength optional, 0 indicates the default of 76 bytes
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ if (0 >= $maxLineLength || 76 < $maxLineLength) {
+ $maxLineLength = 76;
+ }
+
+ $encodedString = base64_encode($string);
+ $firstLine = '';
+
+ if (0 != $firstLineOffset) {
+ $firstLine = substr(
+ $encodedString, 0, $maxLineLength - $firstLineOffset
+ ) . "\r\n";
+ $encodedString = substr(
+ $encodedString, $maxLineLength - $firstLineOffset
+ );
+ }
+
+ return $firstLine . trim(chunk_split($encodedString, $maxLineLength, "\r\n"));
+ }
+
+ /**
+ * Does nothing.
+ */
+ public function charsetChanged($charset)
+ {
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Encoder/QpEncoder.php b/vendor/swiftmailer/classes/Swift/Encoder/QpEncoder.php
new file mode 100644
index 00000000..e8fc493d
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Encoder/QpEncoder.php
@@ -0,0 +1,282 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles Quoted Printable (QP) Encoding in Swift Mailer.
+ *
+ * Possibly the most accurate RFC 2045 QP implementation found in PHP.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Encoder_QpEncoder implements Swift_Encoder
+{
+ /**
+ * The CharacterStream used for reading characters (as opposed to bytes).
+ *
+ * @var Swift_CharacterStream
+ */
+ protected $_charStream;
+
+ /**
+ * A filter used if input should be canonicalized.
+ *
+ * @var Swift_StreamFilter
+ */
+ protected $_filter;
+
+ /**
+ * Pre-computed QP for HUGE optimization.
+ *
+ * @var string[]
+ */
+ protected static $_qpMap = array(
+ 0 => '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04',
+ 5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09',
+ 10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E',
+ 15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13',
+ 20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18',
+ 25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D',
+ 30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22',
+ 35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27',
+ 40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C',
+ 45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31',
+ 50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36',
+ 55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B',
+ 60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40',
+ 65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45',
+ 70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A',
+ 75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F',
+ 80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54',
+ 85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59',
+ 90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E',
+ 95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63',
+ 100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68',
+ 105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D',
+ 110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72',
+ 115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77',
+ 120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C',
+ 125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81',
+ 130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86',
+ 135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B',
+ 140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90',
+ 145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95',
+ 150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A',
+ 155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F',
+ 160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4',
+ 165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9',
+ 170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE',
+ 175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3',
+ 180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8',
+ 185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD',
+ 190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2',
+ 195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7',
+ 200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC',
+ 205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1',
+ 210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6',
+ 215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB',
+ 220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0',
+ 225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5',
+ 230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA',
+ 235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF',
+ 240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4',
+ 245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9',
+ 250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE',
+ 255 => '=FF'
+ );
+
+ protected static $_safeMapShare = array();
+
+ /**
+ * A map of non-encoded ascii characters.
+ *
+ * @var string[]
+ */
+ protected $_safeMap = array();
+
+ /**
+ * Creates a new QpEncoder for the given CharacterStream.
+ *
+ * @param Swift_CharacterStream $charStream to use for reading characters
+ * @param Swift_StreamFilter $filter if input should be canonicalized
+ */
+ public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null)
+ {
+ $this->_charStream = $charStream;
+ if (!isset(self::$_safeMapShare[$this->getSafeMapShareId()])) {
+ $this->initSafeMap();
+ self::$_safeMapShare[$this->getSafeMapShareId()] = $this->_safeMap;
+ } else {
+ $this->_safeMap = self::$_safeMapShare[$this->getSafeMapShareId()];
+ }
+ $this->_filter = $filter;
+ }
+
+ public function __sleep()
+ {
+ return array('_charStream', '_filter');
+ }
+
+ public function __wakeup()
+ {
+ if (!isset(self::$_safeMapShare[$this->getSafeMapShareId()])) {
+ $this->initSafeMap();
+ self::$_safeMapShare[$this->getSafeMapShareId()] = $this->_safeMap;
+ } else {
+ $this->_safeMap = self::$_safeMapShare[$this->getSafeMapShareId()];
+ }
+ }
+
+ protected function getSafeMapShareId()
+ {
+ return get_class($this);
+ }
+
+ protected function initSafeMap()
+ {
+ foreach (array_merge(
+ array(0x09, 0x20), range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte)
+ {
+ $this->_safeMap[$byte] = chr($byte);
+ }
+ }
+
+ /**
+ * Takes an unencoded string and produces a QP encoded string from it.
+ *
+ * QP encoded strings have a maximum line length of 76 characters.
+ * If the first line needs to be shorter, indicate the difference with
+ * $firstLineOffset.
+ *
+ * @param string $string to encode
+ * @param int $firstLineOffset, optional
+ * @param int $maxLineLength, optional 0 indicates the default of 76 chars
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ if ($maxLineLength > 76 || $maxLineLength <= 0) {
+ $maxLineLength = 76;
+ }
+
+ $thisLineLength = $maxLineLength - $firstLineOffset;
+
+ $lines = array();
+ $lNo = 0;
+ $lines[$lNo] = '';
+ $currentLine =& $lines[$lNo++];
+ $size=$lineLen=0;
+
+ $this->_charStream->flushContents();
+ $this->_charStream->importString($string);
+
+ // Fetching more than 4 chars at one is slower, as is fetching fewer bytes
+ // Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6
+ // bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes
+ while (false !== $bytes = $this->_nextSequence()) {
+ // If we're filtering the input
+ if (isset($this->_filter)) {
+ // If we can't filter because we need more bytes
+ while ($this->_filter->shouldBuffer($bytes)) {
+ // Then collect bytes into the buffer
+ if (false === $moreBytes = $this->_nextSequence(1)) {
+ break;
+ }
+
+ foreach ($moreBytes as $b) {
+ $bytes[] = $b;
+ }
+ }
+ // And filter them
+ $bytes = $this->_filter->filter($bytes);
+ }
+
+ $enc = $this->_encodeByteSequence($bytes, $size);
+ if ($currentLine && $lineLen+$size >= $thisLineLength) {
+ $lines[$lNo] = '';
+ $currentLine =& $lines[$lNo++];
+ $thisLineLength = $maxLineLength;
+ $lineLen=0;
+ }
+ $lineLen+=$size;
+ $currentLine .= $enc;
+ }
+
+ return $this->_standardize(implode("=\r\n", $lines));
+ }
+
+ /**
+ * Updates the charset used.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->_charStream->setCharacterSet($charset);
+ }
+
+ /**
+ * Encode the given byte array into a verbatim QP form.
+ *
+ * @param integer[] $bytes
+ * @param int $size
+ *
+ * @return string
+ */
+ protected function _encodeByteSequence(array $bytes, &$size)
+ {
+ $ret = '';
+ $size=0;
+ foreach ($bytes as $b) {
+ if (isset($this->_safeMap[$b])) {
+ $ret .= $this->_safeMap[$b];
+ ++$size;
+ } else {
+ $ret .= self::$_qpMap[$b];
+ $size+=3;
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Get the next sequence of bytes to read from the char stream.
+ *
+ * @param int $size number of bytes to read
+ *
+ * @return integer[]
+ */
+ protected function _nextSequence($size = 4)
+ {
+ return $this->_charStream->readBytes($size);
+ }
+
+ /**
+ * Make sure CRLF is correct and HT/SPACE are in valid places.
+ *
+ * @param string $string
+ *
+ * @return string
+ */
+ protected function _standardize($string)
+ {
+ $string = str_replace(array("\t=0D=0A", " =0D=0A", "=0D=0A"),
+ array("=09\r\n", "=20\r\n", "\r\n"), $string
+ );
+ switch ($end = ord(substr($string, -1))) {
+ case 0x09:
+ case 0x20:
+ $string = substr_replace($string, self::$_qpMap[$end], -1);
+ }
+
+ return $string;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Encoder/Rfc2231Encoder.php b/vendor/swiftmailer/classes/Swift/Encoder/Rfc2231Encoder.php
new file mode 100644
index 00000000..c03fcc5f
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Encoder/Rfc2231Encoder.php
@@ -0,0 +1,84 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles RFC 2231 specified Encoding in Swift Mailer.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Encoder_Rfc2231Encoder implements Swift_Encoder
+{
+ /**
+ * A character stream to use when reading a string as characters instead of bytes.
+ *
+ * @var Swift_CharacterStream
+ */
+ private $_charStream;
+
+ /**
+ * Creates a new Rfc2231Encoder using the given character stream instance.
+ *
+ * @param Swift_CharacterStream
+ */
+ public function __construct(Swift_CharacterStream $charStream)
+ {
+ $this->_charStream = $charStream;
+ }
+
+ /**
+ * Takes an unencoded string and produces a string encoded according to
+ * RFC 2231 from it.
+ *
+ * @param string $string
+ * @param int $firstLineOffset
+ * @param int $maxLineLength optional, 0 indicates the default of 75 bytes
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ $lines = array(); $lineCount = 0;
+ $lines[] = '';
+ $currentLine =& $lines[$lineCount++];
+
+ if (0 >= $maxLineLength) {
+ $maxLineLength = 75;
+ }
+
+ $this->_charStream->flushContents();
+ $this->_charStream->importString($string);
+
+ $thisLineLength = $maxLineLength - $firstLineOffset;
+
+ while (false !== $char = $this->_charStream->read(4)) {
+ $encodedChar = rawurlencode($char);
+ if (0 != strlen($currentLine)
+ && strlen($currentLine . $encodedChar) > $thisLineLength)
+ {
+ $lines[] = '';
+ $currentLine =& $lines[$lineCount++];
+ $thisLineLength = $maxLineLength;
+ }
+ $currentLine .= $encodedChar;
+ }
+
+ return implode("\r\n", $lines);
+ }
+
+ /**
+ * Updates the charset used.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->_charStream->setCharacterSet($charset);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Encoding.php b/vendor/swiftmailer/classes/Swift/Encoding.php
new file mode 100644
index 00000000..5cbb20fc
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Encoding.php
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Provides quick access to each encoding type.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Encoding
+{
+ /**
+ * Get the Encoder that provides 7-bit encoding.
+ *
+ * @return Swift_Mime_ContentEncoder
+ */
+ public static function get7BitEncoding()
+ {
+ return self::_lookup('mime.7bitcontentencoder');
+ }
+
+ /**
+ * Get the Encoder that provides 8-bit encoding.
+ *
+ * @return Swift_Mime_ContentEncoder
+ */
+ public static function get8BitEncoding()
+ {
+ return self::_lookup('mime.8bitcontentencoder');
+ }
+
+ /**
+ * Get the Encoder that provides Quoted-Printable (QP) encoding.
+ *
+ * @return Swift_Mime_ContentEncoder
+ */
+ public static function getQpEncoding()
+ {
+ return self::_lookup('mime.qpcontentencoder');
+ }
+
+ /**
+ * Get the Encoder that provides Base64 encoding.
+ *
+ * @return Swift_Mime_ContentEncoder
+ */
+ public static function getBase64Encoding()
+ {
+ return self::_lookup('mime.base64contentencoder');
+ }
+
+ // -- Private Static Methods
+
+ private static function _lookup($key)
+ {
+ return Swift_DependencyContainer::getInstance()->lookup($key);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/CommandEvent.php b/vendor/swiftmailer/classes/Swift/Events/CommandEvent.php
new file mode 100644
index 00000000..670f4d3d
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/CommandEvent.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Generated when a command is sent over an SMTP connection.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Events_CommandEvent extends Swift_Events_EventObject
+{
+ /**
+ * The command sent to the server.
+ *
+ * @var string
+ */
+ private $_command;
+
+ /**
+ * An array of codes which a successful response will contain.
+ *
+ * @var integer[]
+ */
+ private $_successCodes = array();
+
+ /**
+ * Create a new CommandEvent for $source with $command.
+ *
+ * @param Swift_Transport $source
+ * @param string $command
+ * @param array $successCodes
+ */
+ public function __construct(Swift_Transport $source, $command, $successCodes = array())
+ {
+ parent::__construct($source);
+ $this->_command = $command;
+ $this->_successCodes = $successCodes;
+ }
+
+ /**
+ * Get the command which was sent to the server.
+ *
+ * @return string
+ */
+ public function getCommand()
+ {
+ return $this->_command;
+ }
+
+ /**
+ * Get the numeric response codes which indicate success for this command.
+ *
+ * @return integer[]
+ */
+ public function getSuccessCodes()
+ {
+ return $this->_successCodes;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/CommandListener.php b/vendor/swiftmailer/classes/Swift/Events/CommandListener.php
new file mode 100644
index 00000000..3465c8d6
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/CommandListener.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Listens for Transports to send commands to the server.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Events_CommandListener extends Swift_Events_EventListener
+{
+ /**
+ * Invoked immediately following a command being sent.
+ *
+ * @param Swift_Events_CommandEvent $evt
+ */
+ public function commandSent(Swift_Events_CommandEvent $evt);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/Event.php b/vendor/swiftmailer/classes/Swift/Events/Event.php
new file mode 100644
index 00000000..ffd9bed1
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/Event.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * The minimum interface for an Event.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Events_Event
+{
+ /**
+ * Get the source object of this event.
+ *
+ * @return object
+ */
+ public function getSource();
+
+ /**
+ * Prevent this Event from bubbling any further up the stack.
+ *
+ * @param bool $cancel, optional
+ */
+ public function cancelBubble($cancel = true);
+
+ /**
+ * Returns true if this Event will not bubble any further up the stack.
+ *
+ * @return bool
+ */
+ public function bubbleCancelled();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/EventDispatcher.php b/vendor/swiftmailer/classes/Swift/Events/EventDispatcher.php
new file mode 100644
index 00000000..c62c5e42
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/EventDispatcher.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Interface for the EventDispatcher which handles the event dispatching layer.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Events_EventDispatcher
+{
+ /**
+ * Create a new SendEvent for $source and $message.
+ *
+ * @param Swift_Transport $source
+ * @param Swift_Mime_Message
+ *
+ * @return Swift_Events_SendEvent
+ */
+ public function createSendEvent(Swift_Transport $source, Swift_Mime_Message $message);
+
+ /**
+ * Create a new CommandEvent for $source and $command.
+ *
+ * @param Swift_Transport $source
+ * @param string $command That will be executed
+ * @param array $successCodes That are needed
+ *
+ * @return Swift_Events_CommandEvent
+ */
+ public function createCommandEvent(Swift_Transport $source, $command, $successCodes = array());
+
+ /**
+ * Create a new ResponseEvent for $source and $response.
+ *
+ * @param Swift_Transport $source
+ * @param string $response
+ * @param bool $valid If the response is valid
+ *
+ * @return Swift_Events_ResponseEvent
+ */
+ public function createResponseEvent(Swift_Transport $source, $response, $valid);
+
+ /**
+ * Create a new TransportChangeEvent for $source.
+ *
+ * @param Swift_Transport $source
+ *
+ * @return Swift_Events_TransportChangeEvent
+ */
+ public function createTransportChangeEvent(Swift_Transport $source);
+
+ /**
+ * Create a new TransportExceptionEvent for $source.
+ *
+ * @param Swift_Transport $source
+ * @param Swift_TransportException $ex
+ *
+ * @return Swift_Events_TransportExceptionEvent
+ */
+ public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex);
+
+ /**
+ * Bind an event listener to this dispatcher.
+ *
+ * @param Swift_Events_EventListener $listener
+ */
+ public function bindEventListener(Swift_Events_EventListener $listener);
+
+ /**
+ * Dispatch the given Event to all suitable listeners.
+ *
+ * @param Swift_Events_EventObject $evt
+ * @param string $target method
+ */
+ public function dispatchEvent(Swift_Events_EventObject $evt, $target);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/EventListener.php b/vendor/swiftmailer/classes/Swift/Events/EventListener.php
new file mode 100644
index 00000000..751ec678
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/EventListener.php
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An identity interface which all EventListeners must extend.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Events_EventListener
+{
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/EventObject.php b/vendor/swiftmailer/classes/Swift/Events/EventObject.php
new file mode 100644
index 00000000..50b6be6a
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/EventObject.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A base Event which all Event classes inherit from.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Events_EventObject implements Swift_Events_Event
+{
+ /** The source of this Event */
+ private $_source;
+
+ /** The state of this Event (should it bubble up the stack?) */
+ private $_bubbleCancelled = false;
+
+ /**
+ * Create a new EventObject originating at $source.
+ *
+ * @param object $source
+ */
+ public function __construct($source)
+ {
+ $this->_source = $source;
+ }
+
+ /**
+ * Get the source object of this event.
+ *
+ * @return object
+ */
+ public function getSource()
+ {
+ return $this->_source;
+ }
+
+ /**
+ * Prevent this Event from bubbling any further up the stack.
+ *
+ * @param bool $cancel, optional
+ */
+ public function cancelBubble($cancel = true)
+ {
+ $this->_bubbleCancelled = $cancel;
+ }
+
+ /**
+ * Returns true if this Event will not bubble any further up the stack.
+ *
+ * @return bool
+ */
+ public function bubbleCancelled()
+ {
+ return $this->_bubbleCancelled;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/ResponseEvent.php b/vendor/swiftmailer/classes/Swift/Events/ResponseEvent.php
new file mode 100644
index 00000000..6ca9b99a
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/ResponseEvent.php
@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Generated when a response is received on a SMTP connection.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Events_ResponseEvent extends Swift_Events_EventObject
+{
+ /**
+ * The overall result.
+ *
+ * @var bool
+ */
+ private $_valid;
+
+ /**
+ * The response received from the server.
+ *
+ * @var string
+ */
+ private $_response;
+
+ /**
+ * Create a new ResponseEvent for $source and $response.
+ *
+ * @param Swift_Transport $source
+ * @param string $response
+ * @param bool $valid
+ */
+ public function __construct(Swift_Transport $source, $response, $valid = false)
+ {
+ parent::__construct($source);
+ $this->_response = $response;
+ $this->_valid = $valid;
+ }
+
+ /**
+ * Get the response which was received from the server.
+ *
+ * @return string
+ */
+ public function getResponse()
+ {
+ return $this->_response;
+ }
+
+ /**
+ * Get the success status of this Event.
+ *
+ * @return bool
+ */
+ public function isValid()
+ {
+ return $this->_valid;
+ }
+
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/ResponseListener.php b/vendor/swiftmailer/classes/Swift/Events/ResponseListener.php
new file mode 100644
index 00000000..9629f1e5
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/ResponseListener.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Listens for responses from a remote SMTP server.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Events_ResponseListener extends Swift_Events_EventListener
+{
+ /**
+ * Invoked immediately following a response coming back.
+ *
+ * @param Swift_Events_ResponseEvent $evt
+ */
+ public function responseReceived(Swift_Events_ResponseEvent $evt);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/SendEvent.php b/vendor/swiftmailer/classes/Swift/Events/SendEvent.php
new file mode 100644
index 00000000..0d3b4141
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/SendEvent.php
@@ -0,0 +1,126 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Generated when a message is being sent.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Events_SendEvent extends Swift_Events_EventObject
+{
+ /** Sending has yet to occur */
+ const RESULT_PENDING = 0x0001;
+
+ /** Sending was successful */
+ const RESULT_SUCCESS = 0x0010;
+
+ /** Sending worked, but there were some failures */
+ const RESULT_TENTATIVE = 0x0100;
+
+ /** Sending failed */
+ const RESULT_FAILED = 0x1000;
+
+ /**
+ * The Message being sent.
+ *
+ * @var Swift_Mime_Message
+ */
+ private $_message;
+
+ /**
+ * Any recipients which failed after sending.
+ *
+ * @var string[]
+ */
+ private $_failedRecipients = array();
+
+ /**
+ * The overall result as a bitmask from the class constants.
+ *
+ * @var int
+ */
+ private $_result;
+
+ /**
+ * Create a new SendEvent for $source and $message.
+ *
+ * @param Swift_Transport $source
+ * @param Swift_Mime_Message $message
+ */
+ public function __construct(Swift_Transport $source, Swift_Mime_Message $message)
+ {
+ parent::__construct($source);
+ $this->_message = $message;
+ $this->_result = self::RESULT_PENDING;
+ }
+
+ /**
+ * Get the Transport used to send the Message.
+ *
+ * @return Swift_Transport
+ */
+ public function getTransport()
+ {
+ return $this->getSource();
+ }
+
+ /**
+ * Get the Message being sent.
+ *
+ * @return Swift_Mime_Message
+ */
+ public function getMessage()
+ {
+ return $this->_message;
+ }
+
+ /**
+ * Set the array of addresses that failed in sending.
+ *
+ * @param array $recipients
+ */
+ public function setFailedRecipients($recipients)
+ {
+ $this->_failedRecipients = $recipients;
+ }
+
+ /**
+ * Get an recipient addresses which were not accepted for delivery.
+ *
+ * @return string[]
+ */
+ public function getFailedRecipients()
+ {
+ return $this->_failedRecipients;
+ }
+
+ /**
+ * Set the result of sending.
+ *
+ * @param int $result
+ */
+ public function setResult($result)
+ {
+ $this->_result = $result;
+ }
+
+ /**
+ * Get the result of this Event.
+ *
+ * The return value is a bitmask from
+ * {@see RESULT_PENDING, RESULT_SUCCESS, RESULT_TENTATIVE, RESULT_FAILED}
+ *
+ * @return int
+ */
+ public function getResult()
+ {
+ return $this->_result;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/SendListener.php b/vendor/swiftmailer/classes/Swift/Events/SendListener.php
new file mode 100644
index 00000000..7d35f18e
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/SendListener.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Listens for Messages being sent from within the Transport system.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Events_SendListener extends Swift_Events_EventListener
+{
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt);
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/SimpleEventDispatcher.php b/vendor/swiftmailer/classes/Swift/Events/SimpleEventDispatcher.php
new file mode 100644
index 00000000..b7f82aed
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/SimpleEventDispatcher.php
@@ -0,0 +1,157 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * The EventDispatcher which handles the event dispatching layer.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Events_SimpleEventDispatcher implements Swift_Events_EventDispatcher
+{
+ /** A map of event types to their associated listener types */
+ private $_eventMap = array();
+
+ /** Event listeners bound to this dispatcher */
+ private $_listeners = array();
+
+ /** Listeners queued to have an Event bubbled up the stack to them */
+ private $_bubbleQueue = array();
+
+ /**
+ * Create a new EventDispatcher.
+ */
+ public function __construct()
+ {
+ $this->_eventMap = array(
+ 'Swift_Events_CommandEvent' => 'Swift_Events_CommandListener',
+ 'Swift_Events_ResponseEvent' => 'Swift_Events_ResponseListener',
+ 'Swift_Events_SendEvent' => 'Swift_Events_SendListener',
+ 'Swift_Events_TransportChangeEvent' => 'Swift_Events_TransportChangeListener',
+ 'Swift_Events_TransportExceptionEvent' => 'Swift_Events_TransportExceptionListener'
+ );
+ }
+
+ /**
+ * Create a new SendEvent for $source and $message.
+ *
+ * @param Swift_Transport $source
+ * @param Swift_Mime_Message
+ *
+ * @return Swift_Events_SendEvent
+ */
+ public function createSendEvent(Swift_Transport $source, Swift_Mime_Message $message)
+ {
+ return new Swift_Events_SendEvent($source, $message);
+ }
+
+ /**
+ * Create a new CommandEvent for $source and $command.
+ *
+ * @param Swift_Transport $source
+ * @param string $command That will be executed
+ * @param array $successCodes That are needed
+ *
+ * @return Swift_Events_CommandEvent
+ */
+ public function createCommandEvent(Swift_Transport $source, $command, $successCodes = array())
+ {
+ return new Swift_Events_CommandEvent($source, $command, $successCodes);
+ }
+
+ /**
+ * Create a new ResponseEvent for $source and $response.
+ *
+ * @param Swift_Transport $source
+ * @param string $response
+ * @param bool $valid If the response is valid
+ *
+ * @return Swift_Events_ResponseEvent
+ */
+ public function createResponseEvent(Swift_Transport $source, $response, $valid)
+ {
+ return new Swift_Events_ResponseEvent($source, $response, $valid);
+ }
+
+ /**
+ * Create a new TransportChangeEvent for $source.
+ *
+ * @param Swift_Transport $source
+ *
+ * @return Swift_Events_TransportChangeEvent
+ */
+ public function createTransportChangeEvent(Swift_Transport $source)
+ {
+ return new Swift_Events_TransportChangeEvent($source);
+ }
+
+ /**
+ * Create a new TransportExceptionEvent for $source.
+ *
+ * @param Swift_Transport $source
+ * @param Swift_TransportException $ex
+ *
+ * @return Swift_Events_TransportExceptionEvent
+ */
+ public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex)
+ {
+ return new Swift_Events_TransportExceptionEvent($source, $ex);
+ }
+
+ /**
+ * Bind an event listener to this dispatcher.
+ *
+ * @param Swift_Events_EventListener $listener
+ */
+ public function bindEventListener(Swift_Events_EventListener $listener)
+ {
+ foreach ($this->_listeners as $l) {
+ // Already loaded
+ if ($l === $listener) {
+ return;
+ }
+ }
+ $this->_listeners[] = $listener;
+ }
+
+ /**
+ * Dispatch the given Event to all suitable listeners.
+ *
+ * @param Swift_Events_EventObject $evt
+ * @param string $target method
+ */
+ public function dispatchEvent(Swift_Events_EventObject $evt, $target)
+ {
+ $this->_prepareBubbleQueue($evt);
+ $this->_bubble($evt, $target);
+ }
+
+ /** Queue listeners on a stack ready for $evt to be bubbled up it */
+ private function _prepareBubbleQueue(Swift_Events_EventObject $evt)
+ {
+ $this->_bubbleQueue = array();
+ $evtClass = get_class($evt);
+ foreach ($this->_listeners as $listener) {
+ if (array_key_exists($evtClass, $this->_eventMap)
+ && ($listener instanceof $this->_eventMap[$evtClass]))
+ {
+ $this->_bubbleQueue[] = $listener;
+ }
+ }
+ }
+
+ /** Bubble $evt up the stack calling $target() on each listener */
+ private function _bubble(Swift_Events_EventObject $evt, $target)
+ {
+ if (!$evt->bubbleCancelled() && $listener = array_shift($this->_bubbleQueue)) {
+ $listener->$target($evt);
+ $this->_bubble($evt, $target);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/TransportChangeEvent.php b/vendor/swiftmailer/classes/Swift/Events/TransportChangeEvent.php
new file mode 100644
index 00000000..23c82970
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/TransportChangeEvent.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Generated when the state of a Transport is changed (i.e. stopped/started).
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Events_TransportChangeEvent extends Swift_Events_EventObject
+{
+ /**
+ * Get the Transport.
+ *
+ * @return Swift_Transport
+ */
+ public function getTransport()
+ {
+ return $this->getSource();
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/TransportChangeListener.php b/vendor/swiftmailer/classes/Swift/Events/TransportChangeListener.php
new file mode 100644
index 00000000..0edfe377
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/TransportChangeListener.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Listens for changes within the Transport system.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Events_TransportChangeListener extends Swift_Events_EventListener
+{
+ /**
+ * Invoked just before a Transport is started.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt);
+
+ /**
+ * Invoked immediately after the Transport is started.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function transportStarted(Swift_Events_TransportChangeEvent $evt);
+
+ /**
+ * Invoked just before a Transport is stopped.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt);
+
+ /**
+ * Invoked immediately after the Transport is stopped.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function transportStopped(Swift_Events_TransportChangeEvent $evt);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/TransportExceptionEvent.php b/vendor/swiftmailer/classes/Swift/Events/TransportExceptionEvent.php
new file mode 100644
index 00000000..b2c72ca1
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/TransportExceptionEvent.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Generated when a TransportException is thrown from the Transport system.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Events_TransportExceptionEvent extends Swift_Events_EventObject
+{
+ /**
+ * The Exception thrown.
+ *
+ * @var Swift_TransportException
+ */
+ private $_exception;
+
+ /**
+ * Create a new TransportExceptionEvent for $transport.
+ *
+ * @param Swift_Transport $transport
+ * @param Swift_TransportException $ex
+ */
+ public function __construct(Swift_Transport $transport, Swift_TransportException $ex)
+ {
+ parent::__construct($transport);
+ $this->_exception = $ex;
+ }
+
+ /**
+ * Get the TransportException thrown.
+ *
+ * @return Swift_TransportException
+ */
+ public function getException()
+ {
+ return $this->_exception;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Events/TransportExceptionListener.php b/vendor/swiftmailer/classes/Swift/Events/TransportExceptionListener.php
new file mode 100644
index 00000000..f153742c
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Events/TransportExceptionListener.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Listens for Exceptions thrown from within the Transport system.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Events_TransportExceptionListener extends Swift_Events_EventListener
+{
+ /**
+ * Invoked as a TransportException is thrown in the Transport system.
+ *
+ * @param Swift_Events_TransportExceptionEvent $evt
+ */
+ public function exceptionThrown(Swift_Events_TransportExceptionEvent $evt);
+}
diff --git a/vendor/swiftmailer/classes/Swift/FailoverTransport.php b/vendor/swiftmailer/classes/Swift/FailoverTransport.php
new file mode 100644
index 00000000..6fa5fc70
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/FailoverTransport.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Contains a list of redundant Transports so when one fails, the next is used.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_FailoverTransport extends Swift_Transport_FailoverTransport
+{
+ /**
+ * Creates a new FailoverTransport with $transports.
+ *
+ * @param Swift_Transport[] $transports
+ */
+ public function __construct($transports = array())
+ {
+ call_user_func_array(
+ array($this, 'Swift_Transport_FailoverTransport::__construct'),
+ Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('transport.failover')
+ );
+
+ $this->setTransports($transports);
+ }
+
+ /**
+ * Create a new FailoverTransport instance.
+ *
+ * @param Swift_Transport[] $transports
+ *
+ * @return Swift_FailoverTransport
+ */
+ public static function newInstance($transports = array())
+ {
+ return new self($transports);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/FileSpool.php b/vendor/swiftmailer/classes/Swift/FileSpool.php
new file mode 100644
index 00000000..89bc13d3
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/FileSpool.php
@@ -0,0 +1,208 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2009 Fabien Potencier <fabien.potencier@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages on the filesystem.
+ *
+ * @author Fabien Potencier
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+class Swift_FileSpool extends Swift_ConfigurableSpool
+{
+ /** The spool directory */
+ private $_path;
+
+ /**
+ * File WriteRetry Limit
+ *
+ * @var int
+ */
+ private $_retryLimit=10;
+
+ /**
+ * Create a new FileSpool.
+ *
+ * @param string $path
+ *
+ * @throws Swift_IoException
+ */
+ public function __construct($path)
+ {
+ $this->_path = $path;
+
+ if (!file_exists($this->_path)) {
+ if (!mkdir($this->_path, 0777, true)) {
+ throw new Swift_IoException('Unable to create Path ['.$this->_path.']');
+ }
+ }
+ }
+
+ /**
+ * Tests if this Spool mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted()
+ {
+ return true;
+ }
+
+ /**
+ * Starts this Spool mechanism.
+ */
+ public function start()
+ {
+ }
+
+ /**
+ * Stops this Spool mechanism.
+ */
+ public function stop()
+ {
+ }
+
+ /**
+ * Allow to manage the enqueuing retry limit.
+ *
+ * Default, is ten and allows over 64^20 different fileNames
+ *
+ * @param int $limit
+ */
+ public function setRetryLimit($limit)
+ {
+ $this->_retryLimit=$limit;
+ }
+
+ /**
+ * Queues a message.
+ *
+ * @param Swift_Mime_Message $message The message to store
+ *
+ * @return bool
+ *
+ * @throws Swift_IoException
+ */
+ public function queueMessage(Swift_Mime_Message $message)
+ {
+ $ser = serialize($message);
+ $fileName = $this->_path . '/' . $this->getRandomString(10);
+ for ($i = 0; $i < $this->_retryLimit; ++$i) {
+ /* We try an exclusive creation of the file. This is an atomic operation, it avoid locking mechanism */
+ $fp = @fopen($fileName . '.message', 'x');
+ if (false !== $fp) {
+ if (false === fwrite($fp, $ser)) {
+ return false;
+ }
+
+ return fclose($fp);
+ } else {
+ /* The file already exists, we try a longer fileName */
+ $fileName .= $this->getRandomString(1);
+ }
+ }
+
+ throw new Swift_IoException('Unable to create a file for enqueuing Message');
+ }
+
+ /**
+ * Execute a recovery if for any reason a process is sending for too long.
+ *
+ * @param int $timeout in second Defaults is for very slow smtp responses
+ */
+ public function recover($timeout = 900)
+ {
+ foreach (new DirectoryIterator($this->_path) as $file) {
+ $file = $file->getRealPath();
+
+ if (substr($file, - 16) == '.message.sending') {
+ $lockedtime = filectime($file);
+ if ((time() - $lockedtime) > $timeout) {
+ rename($file, substr($file, 0, - 8));
+ }
+ }
+ }
+ }
+
+ /**
+ * Sends messages using the given transport instance.
+ *
+ * @param Swift_Transport $transport A transport instance
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int The number of sent e-mail's
+ */
+ public function flushQueue(Swift_Transport $transport, &$failedRecipients = null)
+ {
+ $directoryIterator = new DirectoryIterator($this->_path);
+
+ /* Start the transport only if there are queued files to send */
+ if (!$transport->isStarted()) {
+ foreach ($directoryIterator as $file) {
+ if (substr($file->getRealPath(), -8) == '.message') {
+ $transport->start();
+ break;
+ }
+ }
+ }
+
+ $failedRecipients = (array) $failedRecipients;
+ $count = 0;
+ $time = time();
+ foreach ($directoryIterator as $file) {
+ $file = $file->getRealPath();
+
+ if (substr($file, -8) != '.message') {
+ continue;
+ }
+
+ /* We try a rename, it's an atomic operation, and avoid locking the file */
+ if (rename($file, $file.'.sending')) {
+ $message = unserialize(file_get_contents($file.'.sending'));
+
+ $count += $transport->send($message, $failedRecipients);
+
+ unlink($file.'.sending');
+ } else {
+ /* This message has just been catched by another process */
+ continue;
+ }
+
+ if ($this->getMessageLimit() && $count >= $this->getMessageLimit()) {
+ break;
+ }
+
+ if ($this->getTimeLimit() && (time() - $time) >= $this->getTimeLimit()) {
+ break;
+ }
+ }
+
+ return $count;
+ }
+
+ /**
+ * Returns a random string needed to generate a fileName for the queue.
+ *
+ * @param int $count
+ *
+ * @return string
+ */
+ protected function getRandomString($count)
+ {
+ // This string MUST stay FS safe, avoid special chars
+ $base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.";
+ $ret = '';
+ $strlen = strlen($base);
+ for ($i = 0; $i < $count; ++$i) {
+ $ret .= $base[((int) rand(0, $strlen - 1))];
+ }
+
+ return $ret;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/FileStream.php b/vendor/swiftmailer/classes/Swift/FileStream.php
new file mode 100644
index 00000000..802cb430
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/FileStream.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An OutputByteStream which specifically reads from a file.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_FileStream extends Swift_OutputByteStream
+{
+ /**
+ * Get the complete path to the file.
+ *
+ * @return string
+ */
+ public function getPath();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Filterable.php b/vendor/swiftmailer/classes/Swift/Filterable.php
new file mode 100644
index 00000000..1f664de8
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Filterable.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Allows StreamFilters to operate on a stream.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Filterable
+{
+ /**
+ * Add a new StreamFilter, referenced by $key.
+ *
+ * @param Swift_StreamFilter $filter
+ * @param string $key
+ */
+ public function addFilter(Swift_StreamFilter $filter, $key);
+
+ /**
+ * Remove an existing filter using $key.
+ *
+ * @param string $key
+ */
+ public function removeFilter($key);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Image.php b/vendor/swiftmailer/classes/Swift/Image.php
new file mode 100644
index 00000000..966bee72
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Image.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An image, embedded in a multipart message.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Image extends Swift_EmbeddedFile
+{
+ /**
+ * Create a new EmbeddedFile.
+ *
+ * Details may be optionally provided to the constructor.
+ *
+ * @param string|Swift_OutputByteStream $data
+ * @param string $filename
+ * @param string $contentType
+ */
+ public function __construct($data = null, $filename = null, $contentType = null)
+ {
+ parent::__construct($data, $filename, $contentType);
+ }
+
+ /**
+ * Create a new Image.
+ *
+ * @param string|Swift_OutputByteStream $data
+ * @param string $filename
+ * @param string $contentType
+ *
+ * @return Swift_Image
+ */
+ public static function newInstance($data = null, $filename = null, $contentType = null)
+ {
+ return new self($data, $filename, $contentType);
+ }
+
+ /**
+ * Create a new Image from a filesystem path.
+ *
+ * @param string $path
+ *
+ * @return Swift_Image
+ */
+ public static function fromPath($path)
+ {
+ $image = self::newInstance()->setFile(
+ new Swift_ByteStream_FileByteStream($path)
+ );
+
+ return $image;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/InputByteStream.php b/vendor/swiftmailer/classes/Swift/InputByteStream.php
new file mode 100644
index 00000000..fd45ab93
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/InputByteStream.php
@@ -0,0 +1,75 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An abstract means of writing data.
+ *
+ * Classes implementing this interface may use a subsystem which requires less
+ * memory than working with large strings of data.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_InputByteStream
+{
+ /**
+ * Writes $bytes to the end of the stream.
+ *
+ * Writing may not happen immediately if the stream chooses to buffer. If
+ * you want to write these bytes with immediate effect, call {@link commit()}
+ * after calling write().
+ *
+ * This method returns the sequence ID of the write (i.e. 1 for first, 2 for
+ * second, etc etc).
+ *
+ * @param string $bytes
+ *
+ * @return int
+ *
+ * @throws Swift_IoException
+ */
+ public function write($bytes);
+
+ /**
+ * For any bytes that are currently buffered inside the stream, force them
+ * off the buffer.
+ *
+ * @throws Swift_IoException
+ */
+ public function commit();
+
+ /**
+ * Attach $is to this stream.
+ *
+ * The stream acts as an observer, receiving all data that is written.
+ * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function bind(Swift_InputByteStream $is);
+
+ /**
+ * Remove an already bound stream.
+ *
+ * If $is is not bound, no errors will be raised.
+ * If the stream currently has any buffered data it will be written to $is
+ * before unbinding occurs.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function unbind(Swift_InputByteStream $is);
+
+ /**
+ * Flush the contents of the stream (empty it) and set the internal pointer
+ * to the beginning.
+ *
+ * @throws Swift_IoException
+ */
+ public function flushBuffers();
+}
diff --git a/vendor/swiftmailer/classes/Swift/IoException.php b/vendor/swiftmailer/classes/Swift/IoException.php
new file mode 100644
index 00000000..75698f9a
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/IoException.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * I/O Exception class.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_IoException extends Swift_SwiftException
+{
+ /**
+ * Create a new IoException with $message.
+ *
+ * @param string $message
+ */
+ public function __construct($message)
+ {
+ parent::__construct($message);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/KeyCache.php b/vendor/swiftmailer/classes/Swift/KeyCache.php
new file mode 100644
index 00000000..a16a90bd
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/KeyCache.php
@@ -0,0 +1,105 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Provides a mechanism for storing data using two keys.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_KeyCache
+{
+ /** Mode for replacing existing cached data */
+ const MODE_WRITE = 1;
+
+ /** Mode for appending data to the end of existing cached data */
+ const MODE_APPEND = 2;
+
+ /**
+ * Set a string into the cache under $itemKey for the namespace $nsKey.
+ *
+ * @see MODE_WRITE, MODE_APPEND
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param string $string
+ * @param int $mode
+ */
+ public function setString($nsKey, $itemKey, $string, $mode);
+
+ /**
+ * Set a ByteStream into the cache under $itemKey for the namespace $nsKey.
+ *
+ * @see MODE_WRITE, MODE_APPEND
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_OutputByteStream $os
+ * @param int $mode
+ */
+ public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode);
+
+ /**
+ * Provides a ByteStream which when written to, writes data to $itemKey.
+ *
+ * NOTE: The stream will always write in append mode.
+ * If the optional third parameter is passed all writes will go through $is.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_InputByteStream $is optional input stream
+ *
+ * @return Swift_InputByteStream
+ */
+ public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $is = null);
+
+ /**
+ * Get data back out of the cache as a string.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ *
+ * @return string
+ */
+ public function getString($nsKey, $itemKey);
+
+ /**
+ * Get data back out of the cache as a ByteStream.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_InputByteStream $is stream to write the data to
+ */
+ public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is);
+
+ /**
+ * Check if the given $itemKey exists in the namespace $nsKey.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ *
+ * @return bool
+ */
+ public function hasKey($nsKey, $itemKey);
+
+ /**
+ * Clear data for $itemKey in the namespace $nsKey if it exists.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ */
+ public function clearKey($nsKey, $itemKey);
+
+ /**
+ * Clear all data in the namespace $nsKey if it exists.
+ *
+ * @param string $nsKey
+ */
+ public function clearAll($nsKey);
+}
diff --git a/vendor/swiftmailer/classes/Swift/KeyCache/ArrayKeyCache.php b/vendor/swiftmailer/classes/Swift/KeyCache/ArrayKeyCache.php
new file mode 100644
index 00000000..7a74af07
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/KeyCache/ArrayKeyCache.php
@@ -0,0 +1,206 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A basic KeyCache backed by an array.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_KeyCache_ArrayKeyCache implements Swift_KeyCache
+{
+ /**
+ * Cache contents.
+ *
+ * @var array
+ */
+ private $_contents = array();
+
+ /**
+ * An InputStream for cloning.
+ *
+ * @var Swift_KeyCache_KeyCacheInputStream
+ */
+ private $_stream;
+
+ /**
+ * Create a new ArrayKeyCache with the given $stream for cloning to make
+ * InputByteStreams.
+ *
+ * @param Swift_KeyCache_KeyCacheInputStream $stream
+ */
+ public function __construct(Swift_KeyCache_KeyCacheInputStream $stream)
+ {
+ $this->_stream = $stream;
+ }
+
+ /**
+ * Set a string into the cache under $itemKey for the namespace $nsKey.
+ *
+ * @see MODE_WRITE, MODE_APPEND
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param string $string
+ * @param int $mode
+ */
+ public function setString($nsKey, $itemKey, $string, $mode)
+ {
+ $this->_prepareCache($nsKey);
+ switch ($mode) {
+ case self::MODE_WRITE:
+ $this->_contents[$nsKey][$itemKey] = $string;
+ break;
+ case self::MODE_APPEND:
+ if (!$this->hasKey($nsKey, $itemKey)) {
+ $this->_contents[$nsKey][$itemKey] = '';
+ }
+ $this->_contents[$nsKey][$itemKey] .= $string;
+ break;
+ default:
+ throw new Swift_SwiftException(
+ 'Invalid mode [' . $mode . '] used to set nsKey='.
+ $nsKey . ', itemKey=' . $itemKey
+ );
+ }
+ }
+
+ /**
+ * Set a ByteStream into the cache under $itemKey for the namespace $nsKey.
+ *
+ * @see MODE_WRITE, MODE_APPEND
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_OutputByteStream $os
+ * @param int $mode
+ */
+ public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode)
+ {
+ $this->_prepareCache($nsKey);
+ switch ($mode) {
+ case self::MODE_WRITE:
+ $this->clearKey($nsKey, $itemKey);
+ case self::MODE_APPEND:
+ if (!$this->hasKey($nsKey, $itemKey)) {
+ $this->_contents[$nsKey][$itemKey] = '';
+ }
+ while (false !== $bytes = $os->read(8192)) {
+ $this->_contents[$nsKey][$itemKey] .= $bytes;
+ }
+ break;
+ default:
+ throw new Swift_SwiftException(
+ 'Invalid mode [' . $mode . '] used to set nsKey='.
+ $nsKey . ', itemKey=' . $itemKey
+ );
+ }
+ }
+
+ /**
+ * Provides a ByteStream which when written to, writes data to $itemKey.
+ *
+ * NOTE: The stream will always write in append mode.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_InputByteStream $writeThrough
+ *
+ * @return Swift_InputByteStream
+ */
+ public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null)
+ {
+ $is = clone $this->_stream;
+ $is->setKeyCache($this);
+ $is->setNsKey($nsKey);
+ $is->setItemKey($itemKey);
+ if (isset($writeThrough)) {
+ $is->setWriteThroughStream($writeThrough);
+ }
+
+ return $is;
+ }
+
+ /**
+ * Get data back out of the cache as a string.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ *
+ * @return string
+ */
+ public function getString($nsKey, $itemKey)
+ {
+ $this->_prepareCache($nsKey);
+ if ($this->hasKey($nsKey, $itemKey)) {
+ return $this->_contents[$nsKey][$itemKey];
+ }
+ }
+
+ /**
+ * Get data back out of the cache as a ByteStream.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_InputByteStream $is to write the data to
+ */
+ public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is)
+ {
+ $this->_prepareCache($nsKey);
+ $is->write($this->getString($nsKey, $itemKey));
+ }
+
+ /**
+ * Check if the given $itemKey exists in the namespace $nsKey.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ *
+ * @return bool
+ */
+ public function hasKey($nsKey, $itemKey)
+ {
+ $this->_prepareCache($nsKey);
+
+ return array_key_exists($itemKey, $this->_contents[$nsKey]);
+ }
+
+ /**
+ * Clear data for $itemKey in the namespace $nsKey if it exists.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ */
+ public function clearKey($nsKey, $itemKey)
+ {
+ unset($this->_contents[$nsKey][$itemKey]);
+ }
+
+ /**
+ * Clear all data in the namespace $nsKey if it exists.
+ *
+ * @param string $nsKey
+ */
+ public function clearAll($nsKey)
+ {
+ unset($this->_contents[$nsKey]);
+ }
+
+ /**
+ * Initialize the namespace of $nsKey if needed.
+ *
+ * @param string $nsKey
+ */
+ private function _prepareCache($nsKey)
+ {
+ if (!array_key_exists($nsKey, $this->_contents)) {
+ $this->_contents[$nsKey] = array();
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/KeyCache/DiskKeyCache.php b/vendor/swiftmailer/classes/Swift/KeyCache/DiskKeyCache.php
new file mode 100644
index 00000000..73f434c4
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/KeyCache/DiskKeyCache.php
@@ -0,0 +1,324 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A KeyCache which streams to and from disk.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_KeyCache_DiskKeyCache implements Swift_KeyCache
+{
+ /** Signal to place pointer at start of file */
+ const POSITION_START = 0;
+
+ /** Signal to place pointer at end of file */
+ const POSITION_END = 1;
+
+ /** Signal to leave pointer in whatever position it currently is */
+ const POSITION_CURRENT = 2;
+
+ /**
+ * An InputStream for cloning.
+ *
+ * @var Swift_KeyCache_KeyCacheInputStream
+ */
+ private $_stream;
+
+ /**
+ * A path to write to.
+ *
+ * @var string
+ */
+ private $_path;
+
+ /**
+ * Stored keys.
+ *
+ * @var array
+ */
+ private $_keys = array();
+
+ /**
+ * Will be true if magic_quotes_runtime is turned on.
+ *
+ * @var bool
+ */
+ private $_quotes = false;
+
+ /**
+ * Create a new DiskKeyCache with the given $stream for cloning to make
+ * InputByteStreams, and the given $path to save to.
+ *
+ * @param Swift_KeyCache_KeyCacheInputStream $stream
+ * @param string $path to save to
+ */
+ public function __construct(Swift_KeyCache_KeyCacheInputStream $stream, $path)
+ {
+ $this->_stream = $stream;
+ $this->_path = $path;
+
+ if (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime() == 1) {
+ $this->_quotes = true;
+ }
+ }
+
+ /**
+ * Set a string into the cache under $itemKey for the namespace $nsKey.
+ *
+ * @see MODE_WRITE, MODE_APPEND
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param string $string
+ * @param int $mode
+ *
+ * @throws Swift_IoException
+ */
+ public function setString($nsKey, $itemKey, $string, $mode)
+ {
+ $this->_prepareCache($nsKey);
+ switch ($mode) {
+ case self::MODE_WRITE:
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
+ break;
+ case self::MODE_APPEND:
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_END);
+ break;
+ default:
+ throw new Swift_SwiftException(
+ 'Invalid mode [' . $mode . '] used to set nsKey='.
+ $nsKey . ', itemKey=' . $itemKey
+ );
+ break;
+ }
+ fwrite($fp, $string);
+ $this->_freeHandle($nsKey, $itemKey);
+ }
+
+ /**
+ * Set a ByteStream into the cache under $itemKey for the namespace $nsKey.
+ *
+ * @see MODE_WRITE, MODE_APPEND
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_OutputByteStream $os
+ * @param int $mode
+ *
+ * @throws Swift_IoException
+ */
+ public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode)
+ {
+ $this->_prepareCache($nsKey);
+ switch ($mode) {
+ case self::MODE_WRITE:
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
+ break;
+ case self::MODE_APPEND:
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_END);
+ break;
+ default:
+ throw new Swift_SwiftException(
+ 'Invalid mode [' . $mode . '] used to set nsKey='.
+ $nsKey . ', itemKey=' . $itemKey
+ );
+ break;
+ }
+ while (false !== $bytes = $os->read(8192)) {
+ fwrite($fp, $bytes);
+ }
+ $this->_freeHandle($nsKey, $itemKey);
+ }
+
+ /**
+ * Provides a ByteStream which when written to, writes data to $itemKey.
+ *
+ * NOTE: The stream will always write in append mode.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_InputByteStream $writeThrough
+ *
+ * @return Swift_InputByteStream
+ */
+ public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null)
+ {
+ $is = clone $this->_stream;
+ $is->setKeyCache($this);
+ $is->setNsKey($nsKey);
+ $is->setItemKey($itemKey);
+ if (isset($writeThrough)) {
+ $is->setWriteThroughStream($writeThrough);
+ }
+
+ return $is;
+ }
+
+ /**
+ * Get data back out of the cache as a string.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ *
+ * @return string
+ *
+ * @throws Swift_IoException
+ */
+ public function getString($nsKey, $itemKey)
+ {
+ $this->_prepareCache($nsKey);
+ if ($this->hasKey($nsKey, $itemKey)) {
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
+ if ($this->_quotes) {
+ ini_set('magic_quotes_runtime', 0);
+ }
+ $str = '';
+ while (!feof($fp) && false !== $bytes = fread($fp, 8192)) {
+ $str .= $bytes;
+ }
+ if ($this->_quotes) {
+ ini_set('magic_quotes_runtime', 1);
+ }
+ $this->_freeHandle($nsKey, $itemKey);
+
+ return $str;
+ }
+ }
+
+ /**
+ * Get data back out of the cache as a ByteStream.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_InputByteStream $is to write the data to
+ */
+ public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is)
+ {
+ if ($this->hasKey($nsKey, $itemKey)) {
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
+ if ($this->_quotes) {
+ ini_set('magic_quotes_runtime', 0);
+ }
+ while (!feof($fp) && false !== $bytes = fread($fp, 8192)) {
+ $is->write($bytes);
+ }
+ if ($this->_quotes) {
+ ini_set('magic_quotes_runtime', 1);
+ }
+ $this->_freeHandle($nsKey, $itemKey);
+ }
+ }
+
+ /**
+ * Check if the given $itemKey exists in the namespace $nsKey.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ *
+ * @return bool
+ */
+ public function hasKey($nsKey, $itemKey)
+ {
+ return is_file($this->_path . '/' . $nsKey . '/' . $itemKey);
+ }
+
+ /**
+ * Clear data for $itemKey in the namespace $nsKey if it exists.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ */
+ public function clearKey($nsKey, $itemKey)
+ {
+ if ($this->hasKey($nsKey, $itemKey)) {
+ $this->_freeHandle($nsKey, $itemKey);
+ unlink($this->_path . '/' . $nsKey . '/' . $itemKey);
+ }
+ }
+
+ /**
+ * Clear all data in the namespace $nsKey if it exists.
+ *
+ * @param string $nsKey
+ */
+ public function clearAll($nsKey)
+ {
+ if (array_key_exists($nsKey, $this->_keys)) {
+ foreach ($this->_keys[$nsKey] as $itemKey=>$null) {
+ $this->clearKey($nsKey, $itemKey);
+ }
+ if (is_dir($this->_path . '/' . $nsKey)) {
+ rmdir($this->_path . '/' . $nsKey);
+ }
+ unset($this->_keys[$nsKey]);
+ }
+ }
+
+ /**
+ * Initialize the namespace of $nsKey if needed.
+ *
+ * @param string $nsKey
+ */
+ private function _prepareCache($nsKey)
+ {
+ $cacheDir = $this->_path . '/' . $nsKey;
+ if (!is_dir($cacheDir)) {
+ if (!mkdir($cacheDir)) {
+ throw new Swift_IoException('Failed to create cache directory ' . $cacheDir);
+ }
+ $this->_keys[$nsKey] = array();
+ }
+ }
+
+ /**
+ * Get a file handle on the cache item.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param int $position
+ *
+ * @return resource
+ */
+ private function _getHandle($nsKey, $itemKey, $position)
+ {
+ if (!isset($this->_keys[$nsKey][$itemKey])) {
+ $openMode = $this->hasKey($nsKey, $itemKey)
+ ? 'r+b'
+ : 'w+b'
+ ;
+ $fp = fopen($this->_path . '/' . $nsKey . '/' . $itemKey, $openMode);
+ $this->_keys[$nsKey][$itemKey] = $fp;
+ }
+ if (self::POSITION_START == $position) {
+ fseek($this->_keys[$nsKey][$itemKey], 0, SEEK_SET);
+ } elseif (self::POSITION_END == $position) {
+ fseek($this->_keys[$nsKey][$itemKey], 0, SEEK_END);
+ }
+
+ return $this->_keys[$nsKey][$itemKey];
+ }
+
+ private function _freeHandle($nsKey, $itemKey)
+ {
+ $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_CURRENT);
+ fclose($fp);
+ $this->_keys[$nsKey][$itemKey] = null;
+ }
+
+ /**
+ * Destructor.
+ */
+ public function __destruct()
+ {
+ foreach ($this->_keys as $nsKey=>$null) {
+ $this->clearAll($nsKey);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/KeyCache/KeyCacheInputStream.php b/vendor/swiftmailer/classes/Swift/KeyCache/KeyCacheInputStream.php
new file mode 100644
index 00000000..76039d8a
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/KeyCache/KeyCacheInputStream.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Writes data to a KeyCache using a stream.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_KeyCache_KeyCacheInputStream extends Swift_InputByteStream
+{
+ /**
+ * Set the KeyCache to wrap.
+ *
+ * @param Swift_KeyCache $keyCache
+ */
+ public function setKeyCache(Swift_KeyCache $keyCache);
+
+ /**
+ * Set the nsKey which will be written to.
+ *
+ * @param string $nsKey
+ */
+ public function setNsKey($nsKey);
+
+ /**
+ * Set the itemKey which will be written to.
+ *
+ * @param string $itemKey
+ */
+ public function setItemKey($itemKey);
+
+ /**
+ * Specify a stream to write through for each write().
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function setWriteThroughStream(Swift_InputByteStream $is);
+
+ /**
+ * Any implementation should be cloneable, allowing the clone to access a
+ * separate $nsKey and $itemKey.
+ */
+ public function __clone();
+}
diff --git a/vendor/swiftmailer/classes/Swift/KeyCache/NullKeyCache.php b/vendor/swiftmailer/classes/Swift/KeyCache/NullKeyCache.php
new file mode 100644
index 00000000..79ab89fc
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/KeyCache/NullKeyCache.php
@@ -0,0 +1,115 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A null KeyCache that does not cache at all.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_KeyCache_NullKeyCache implements Swift_KeyCache
+{
+ /**
+ * Set a string into the cache under $itemKey for the namespace $nsKey.
+ *
+ * @see MODE_WRITE, MODE_APPEND
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param string $string
+ * @param int $mode
+ */
+ public function setString($nsKey, $itemKey, $string, $mode)
+ {
+ }
+
+ /**
+ * Set a ByteStream into the cache under $itemKey for the namespace $nsKey.
+ *
+ * @see MODE_WRITE, MODE_APPEND
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_OutputByteStream $os
+ * @param int $mode
+ */
+ public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode)
+ {
+ }
+
+ /**
+ * Provides a ByteStream which when written to, writes data to $itemKey.
+ *
+ * NOTE: The stream will always write in append mode.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_InputByteStream $writeThrough
+ *
+ * @return Swift_InputByteStream
+ */
+ public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null)
+ {
+ }
+
+ /**
+ * Get data back out of the cache as a string.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ *
+ * @return string
+ */
+ public function getString($nsKey, $itemKey)
+ {
+ }
+
+ /**
+ * Get data back out of the cache as a ByteStream.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ * @param Swift_InputByteStream $is to write the data to
+ */
+ public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is)
+ {
+ }
+
+ /**
+ * Check if the given $itemKey exists in the namespace $nsKey.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ *
+ * @return bool
+ */
+ public function hasKey($nsKey, $itemKey)
+ {
+ return false;
+ }
+
+ /**
+ * Clear data for $itemKey in the namespace $nsKey if it exists.
+ *
+ * @param string $nsKey
+ * @param string $itemKey
+ */
+ public function clearKey($nsKey, $itemKey)
+ {
+ }
+
+ /**
+ * Clear all data in the namespace $nsKey if it exists.
+ *
+ * @param string $nsKey
+ */
+ public function clearAll($nsKey)
+ {
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php b/vendor/swiftmailer/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php
new file mode 100644
index 00000000..e829c8fd
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/KeyCache/SimpleKeyCacheInputStream.php
@@ -0,0 +1,127 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Writes data to a KeyCache using a stream.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_KeyCache_SimpleKeyCacheInputStream implements Swift_KeyCache_KeyCacheInputStream
+{
+ /** The KeyCache being written to */
+ private $_keyCache;
+
+ /** The nsKey of the KeyCache being written to */
+ private $_nsKey;
+
+ /** The itemKey of the KeyCache being written to */
+ private $_itemKey;
+
+ /** A stream to write through on each write() */
+ private $_writeThrough = null;
+
+ /**
+ * Set the KeyCache to wrap.
+ *
+ * @param Swift_KeyCache $keyCache
+ */
+ public function setKeyCache(Swift_KeyCache $keyCache)
+ {
+ $this->_keyCache = $keyCache;
+ }
+
+ /**
+ * Specify a stream to write through for each write().
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function setWriteThroughStream(Swift_InputByteStream $is)
+ {
+ $this->_writeThrough = $is;
+ }
+
+ /**
+ * Writes $bytes to the end of the stream.
+ *
+ * @param string $bytes
+ * @param Swift_InputByteStream $is optional
+ */
+ public function write($bytes, Swift_InputByteStream $is = null)
+ {
+ $this->_keyCache->setString(
+ $this->_nsKey, $this->_itemKey, $bytes, Swift_KeyCache::MODE_APPEND
+ );
+ if (isset($is)) {
+ $is->write($bytes);
+ }
+ if (isset($this->_writeThrough)) {
+ $this->_writeThrough->write($bytes);
+ }
+ }
+
+ /**
+ * Not used.
+ */
+ public function commit()
+ {
+ }
+
+ /**
+ * Not used.
+ */
+ public function bind(Swift_InputByteStream $is)
+ {
+ }
+
+ /**
+ * Not used.
+ */
+ public function unbind(Swift_InputByteStream $is)
+ {
+ }
+
+ /**
+ * Flush the contents of the stream (empty it) and set the internal pointer
+ * to the beginning.
+ */
+ public function flushBuffers()
+ {
+ $this->_keyCache->clearKey($this->_nsKey, $this->_itemKey);
+ }
+
+ /**
+ * Set the nsKey which will be written to.
+ *
+ * @param string $nsKey
+ */
+ public function setNsKey($nsKey)
+ {
+ $this->_nsKey = $nsKey;
+ }
+
+ /**
+ * Set the itemKey which will be written to.
+ *
+ * @param string $itemKey
+ */
+ public function setItemKey($itemKey)
+ {
+ $this->_itemKey = $itemKey;
+ }
+
+ /**
+ * Any implementation should be cloneable, allowing the clone to access a
+ * separate $nsKey and $itemKey.
+ */
+ public function __clone()
+ {
+ $this->_writeThrough = null;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/LoadBalancedTransport.php b/vendor/swiftmailer/classes/Swift/LoadBalancedTransport.php
new file mode 100644
index 00000000..6e1080b9
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/LoadBalancedTransport.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Redundantly and rotationally uses several Transport implementations when sending.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_LoadBalancedTransport extends Swift_Transport_LoadBalancedTransport
+{
+ /**
+ * Creates a new LoadBalancedTransport with $transports.
+ *
+ * @param array $transports
+ */
+ public function __construct($transports = array())
+ {
+ call_user_func_array(
+ array($this, 'Swift_Transport_LoadBalancedTransport::__construct'),
+ Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('transport.loadbalanced')
+ );
+
+ $this->setTransports($transports);
+ }
+
+ /**
+ * Create a new LoadBalancedTransport instance.
+ *
+ * @param array $transports
+ *
+ * @return Swift_LoadBalancedTransport
+ */
+ public static function newInstance($transports = array())
+ {
+ return new self($transports);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/MailTransport.php b/vendor/swiftmailer/classes/Swift/MailTransport.php
new file mode 100644
index 00000000..a6d3340d
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/MailTransport.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Sends Messages using the mail() function.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_MailTransport extends Swift_Transport_MailTransport
+{
+ /**
+ * Create a new MailTransport, optionally specifying $extraParams.
+ *
+ * @param string $extraParams
+ */
+ public function __construct($extraParams = '-f%s')
+ {
+ call_user_func_array(
+ array($this, 'Swift_Transport_MailTransport::__construct'),
+ Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('transport.mail')
+ );
+
+ $this->setExtraParams($extraParams);
+ }
+
+ /**
+ * Create a new MailTransport instance.
+ *
+ * @param string $extraParams To be passed to mail()
+ *
+ * @return Swift_MailTransport
+ */
+ public static function newInstance($extraParams = '-f%s')
+ {
+ return new self($extraParams);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mailer.php b/vendor/swiftmailer/classes/Swift/Mailer.php
new file mode 100644
index 00000000..5677fcb4
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mailer.php
@@ -0,0 +1,114 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Swift Mailer class.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mailer
+{
+ /** The Transport used to send messages */
+ private $_transport;
+
+ /**
+ * Create a new Mailer using $transport for delivery.
+ *
+ * @param Swift_Transport $transport
+ */
+ public function __construct(Swift_Transport $transport)
+ {
+ $this->_transport = $transport;
+ }
+
+ /**
+ * Create a new Mailer instance.
+ *
+ * @param Swift_Transport $transport
+ *
+ * @return Swift_Mailer
+ */
+ public static function newInstance(Swift_Transport $transport)
+ {
+ return new self($transport);
+ }
+
+ /**
+ * Create a new class instance of one of the message services.
+ *
+ * For example 'mimepart' would create a 'message.mimepart' instance
+ *
+ * @param string $service
+ *
+ * @return object
+ */
+ public function createMessage($service = 'message')
+ {
+ return Swift_DependencyContainer::getInstance()
+ ->lookup('message.'.$service);
+ }
+
+ /**
+ * Send the given Message like it would be sent in a mail client.
+ *
+ * All recipients (with the exception of Bcc) will be able to see the other
+ * recipients this message was sent to.
+ *
+ * Recipient/sender data will be retrieved from the Message object.
+ *
+ * The return value is the number of recipients who were accepted for
+ * delivery.
+ *
+ * @param Swift_Mime_Message $message
+ * @param array $failedRecipients An array of failures by-reference
+ *
+ * @return int
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ $failedRecipients = (array) $failedRecipients;
+
+ if (!$this->_transport->isStarted()) {
+ $this->_transport->start();
+ }
+
+ $sent = 0;
+
+ try {
+ $sent = $this->_transport->send($message, $failedRecipients);
+ } catch (Swift_RfcComplianceException $e) {
+ foreach ($message->getTo() as $address => $name) {
+ $failedRecipients[] = $address;
+ }
+ }
+
+ return $sent;
+ }
+
+ /**
+ * Register a plugin using a known unique key (e.g. myPlugin).
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ $this->_transport->registerPlugin($plugin);
+ }
+
+ /**
+ * The Transport used to send messages.
+ *
+ * @return Swift_Transport
+ */
+ public function getTransport()
+ {
+ return $this->_transport;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mailer/ArrayRecipientIterator.php b/vendor/swiftmailer/classes/Swift/Mailer/ArrayRecipientIterator.php
new file mode 100644
index 00000000..d02e1846
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mailer/ArrayRecipientIterator.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Wraps a standard PHP array in an iterator.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mailer_ArrayRecipientIterator implements Swift_Mailer_RecipientIterator
+{
+ /**
+ * The list of recipients.
+ *
+ * @var array
+ */
+ private $_recipients = array();
+
+ /**
+ * Create a new ArrayRecipientIterator from $recipients.
+ *
+ * @param array $recipients
+ */
+ public function __construct(array $recipients)
+ {
+ $this->_recipients = $recipients;
+ }
+
+ /**
+ * Returns true only if there are more recipients to send to.
+ *
+ * @return bool
+ */
+ public function hasNext()
+ {
+ return !empty($this->_recipients);
+ }
+
+ /**
+ * Returns an array where the keys are the addresses of recipients and the
+ * values are the names. e.g. ('foo@bar' => 'Foo') or ('foo@bar' => NULL)
+ *
+ * @return array
+ */
+ public function nextRecipient()
+ {
+ return array_splice($this->_recipients, 0, 1);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mailer/RecipientIterator.php b/vendor/swiftmailer/classes/Swift/Mailer/RecipientIterator.php
new file mode 100644
index 00000000..a935c563
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mailer/RecipientIterator.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Provides an abstract way of specifying recipients for batch sending.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Mailer_RecipientIterator
+{
+ /**
+ * Returns true only if there are more recipients to send to.
+ *
+ * @return bool
+ */
+ public function hasNext();
+
+ /**
+ * Returns an array where the keys are the addresses of recipients and the
+ * values are the names. e.g. ('foo@bar' => 'Foo') or ('foo@bar' => NULL)
+ *
+ * @return array
+ */
+ public function nextRecipient();
+}
diff --git a/vendor/swiftmailer/classes/Swift/MemorySpool.php b/vendor/swiftmailer/classes/Swift/MemorySpool.php
new file mode 100644
index 00000000..fb705efc
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/MemorySpool.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2011 Fabien Potencier <fabien.potencier@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages in memory.
+ *
+ * @author Fabien Potencier
+ */
+class Swift_MemorySpool implements Swift_Spool
+{
+ protected $messages = array();
+
+ /**
+ * Tests if this Transport mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted()
+ {
+ return true;
+ }
+
+ /**
+ * Starts this Transport mechanism.
+ */
+ public function start()
+ {
+ }
+
+ /**
+ * Stops this Transport mechanism.
+ */
+ public function stop()
+ {
+ }
+
+ /**
+ * Stores a message in the queue.
+ *
+ * @param Swift_Mime_Message $message The message to store
+ *
+ * @return bool Whether the operation has succeeded
+ */
+ public function queueMessage(Swift_Mime_Message $message)
+ {
+ $this->messages[] = $message;
+
+ return true;
+ }
+
+ /**
+ * Sends messages using the given transport instance.
+ *
+ * @param Swift_Transport $transport A transport instance
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int The number of sent emails
+ */
+ public function flushQueue(Swift_Transport $transport, &$failedRecipients = null)
+ {
+ if (!$this->messages) {
+ return 0;
+ }
+
+ if (!$transport->isStarted()) {
+ $transport->start();
+ }
+
+ $count = 0;
+ while ($message = array_pop($this->messages)) {
+ $count += $transport->send($message, $failedRecipients);
+ }
+
+ return $count;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Message.php b/vendor/swiftmailer/classes/Swift/Message.php
new file mode 100644
index 00000000..7b25cf03
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Message.php
@@ -0,0 +1,272 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * The Message class for building emails.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Message extends Swift_Mime_SimpleMessage
+{
+ /**
+ * @var Swift_Signers_HeaderSigner[]
+ */
+ private $headerSigners = array();
+
+ /**
+ * @var Swift_Signers_BodySigner[]
+ */
+ private $bodySigners = array();
+
+ /**
+ * @var array
+ */
+ private $savedMessage = array();
+
+ /**
+ * Create a new Message.
+ *
+ * Details may be optionally passed into the constructor.
+ *
+ * @param string $subject
+ * @param string $body
+ * @param string $contentType
+ * @param string $charset
+ */
+ public function __construct($subject = null, $body = null, $contentType = null, $charset = null)
+ {
+ call_user_func_array(
+ array($this, 'Swift_Mime_SimpleMessage::__construct'),
+ Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('mime.message')
+ );
+
+ if (!isset($charset)) {
+ $charset = Swift_DependencyContainer::getInstance()
+ ->lookup('properties.charset');
+ }
+ $this->setSubject($subject);
+ $this->setBody($body);
+ $this->setCharset($charset);
+ if ($contentType) {
+ $this->setContentType($contentType);
+ }
+ }
+
+ /**
+ * Create a new Message.
+ *
+ * @param string $subject
+ * @param string $body
+ * @param string $contentType
+ * @param string $charset
+ *
+ * @return Swift_Message
+ */
+ public static function newInstance($subject = null, $body = null, $contentType = null, $charset = null)
+ {
+ return new self($subject, $body, $contentType, $charset);
+ }
+
+ /**
+ * Add a MimePart to this Message.
+ *
+ * @param string|Swift_OutputByteStream $body
+ * @param string $contentType
+ * @param string $charset
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function addPart($body, $contentType = null, $charset = null)
+ {
+ return $this->attach(Swift_MimePart::newInstance(
+ $body, $contentType, $charset
+ ));
+ }
+
+ /**
+ * Attach a new signature handler to the message.
+ *
+ * @param Swift_Signer $signer
+ * @return Swift_Message
+ */
+ public function attachSigner(Swift_Signer $signer)
+ {
+ if ($signer instanceof Swift_Signers_HeaderSigner) {
+ $this->headerSigners[] = $signer;
+ } elseif ($signer instanceof Swift_Signers_BodySigner) {
+ $this->bodySigners[] = $signer;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Attach a new signature handler to the message.
+ *
+ * @param Swift_Signer $signer
+ * @return Swift_Message
+ */
+ public function detachSigner(Swift_Signer $signer)
+ {
+ if ($signer instanceof Swift_Signers_HeaderSigner) {
+ foreach ($this->headerSigners as $k => $headerSigner) {
+ if ($headerSigner === $signer) {
+ unset($this->headerSigners[$k]);
+
+ return $this;
+ }
+ }
+ } elseif ($signer instanceof Swift_Signers_BodySigner) {
+ foreach ($this->bodySigners as $k => $bodySigner) {
+ if ($bodySigner === $signer) {
+ unset($this->bodySigners[$k]);
+
+ return $this;
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get this message as a complete string.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ if (empty($this->headerSigners) && empty($this->bodySigners)) {
+ return parent::toString();
+ }
+
+ $this->saveMessage();
+
+ $this->doSign();
+
+ $string = parent::toString();
+
+ $this->restoreMessage();
+
+ return $string;
+ }
+
+ /**
+ * Write this message to a {@link Swift_InputByteStream}.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function toByteStream(Swift_InputByteStream $is)
+ {
+ if (empty($this->headerSigners) && empty($this->bodySigners)) {
+ parent::toByteStream($is);
+
+ return;
+ }
+
+ $this->saveMessage();
+
+ $this->doSign();
+
+ parent::toByteStream($is);
+
+ $this->restoreMessage();
+
+ }
+
+ public function __wakeup()
+ {
+ Swift_DependencyContainer::getInstance()->createDependenciesFor('mime.message');
+ }
+
+ /**
+ * loops through signers and apply the signatures
+ */
+ protected function doSign()
+ {
+ foreach ($this->bodySigners as $signer) {
+ $altered = $signer->getAlteredHeaders();
+ $this->saveHeaders($altered);
+ $signer->signMessage($this);
+ }
+
+ foreach ($this->headerSigners as $signer) {
+ $altered = $signer->getAlteredHeaders();
+ $this->saveHeaders($altered);
+ $signer->reset();
+
+ $signer->setHeaders($this->getHeaders());
+
+ $signer->startBody();
+ $this->_bodyToByteStream($signer);
+ $signer->endBody();
+
+ $signer->addSignature($this->getHeaders());
+ }
+ }
+
+ /**
+ * save the message before any signature is applied
+ */
+ protected function saveMessage()
+ {
+ $this->savedMessage = array('headers'=> array());
+ $this->savedMessage['body'] = $this->getBody();
+ $this->savedMessage['children'] = $this->getChildren();
+ if (count($this->savedMessage['children']) > 0 && $this->getBody() != '') {
+ $this->setChildren(array_merge(array($this->_becomeMimePart()), $this->savedMessage['children']));
+ $this->setBody('');
+ }
+ }
+
+ /**
+ * save the original headers
+ * @param array $altered
+ */
+ protected function saveHeaders(array $altered)
+ {
+ foreach ($altered as $head) {
+ $lc = strtolower($head);
+
+ if (!isset($this->savedMessage['headers'][$lc])) {
+ $this->savedMessage['headers'][$lc] = $this->getHeaders()->getAll($head);
+ }
+ }
+ }
+
+ /**
+ * Remove or restore altered headers
+ */
+ protected function restoreHeaders()
+ {
+ foreach ($this->savedMessage['headers'] as $name => $savedValue) {
+ $headers = $this->getHeaders()->getAll($name);
+
+ foreach ($headers as $key => $value) {
+ if (!isset($savedValue[$key])) {
+ $this->getHeaders()->remove($name, $key);
+ }
+ }
+ }
+ }
+
+ /**
+ * Restore message body
+ */
+ protected function restoreMessage()
+ {
+ $this->setBody($this->savedMessage['body']);
+ $this->setChildren($this->savedMessage['children']);
+
+ $this->restoreHeaders();
+ $this->savedMessage = array();
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/Attachment.php b/vendor/swiftmailer/classes/Swift/Mime/Attachment.php
new file mode 100644
index 00000000..d9d96529
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/Attachment.php
@@ -0,0 +1,153 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An attachment, in a multipart message.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_Attachment extends Swift_Mime_SimpleMimeEntity
+{
+ /** Recognized MIME types */
+ private $_mimeTypes = array();
+
+ /**
+ * Create a new Attachment with $headers, $encoder and $cache.
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ * @param Swift_Mime_ContentEncoder $encoder
+ * @param Swift_KeyCache $cache
+ * @param Swift_Mime_Grammar $grammar
+ * @param array $mimeTypes optional
+ */
+ public function __construct(Swift_Mime_HeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_Mime_Grammar $grammar, $mimeTypes = array())
+ {
+ parent::__construct($headers, $encoder, $cache, $grammar);
+ $this->setDisposition('attachment');
+ $this->setContentType('application/octet-stream');
+ $this->_mimeTypes = $mimeTypes;
+ }
+
+ /**
+ * Get the nesting level used for this attachment.
+ *
+ * Always returns {@link LEVEL_MIXED}.
+ *
+ * @return int
+ */
+ public function getNestingLevel()
+ {
+ return self::LEVEL_MIXED;
+ }
+
+ /**
+ * Get the Content-Disposition of this attachment.
+ *
+ * By default attachments have a disposition of "attachment".
+ *
+ * @return string
+ */
+ public function getDisposition()
+ {
+ return $this->_getHeaderFieldModel('Content-Disposition');
+ }
+
+ /**
+ * Set the Content-Disposition of this attachment.
+ *
+ * @param string $disposition
+ *
+ * @return Swift_Mime_Attachment
+ */
+ public function setDisposition($disposition)
+ {
+ if (!$this->_setHeaderFieldModel('Content-Disposition', $disposition)) {
+ $this->getHeaders()->addParameterizedHeader(
+ 'Content-Disposition', $disposition
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the filename of this attachment when downloaded.
+ *
+ * @return string
+ */
+ public function getFilename()
+ {
+ return $this->_getHeaderParameter('Content-Disposition', 'filename');
+ }
+
+ /**
+ * Set the filename of this attachment.
+ *
+ * @param string $filename
+ *
+ * @return Swift_Mime_Attachment
+ */
+ public function setFilename($filename)
+ {
+ $this->_setHeaderParameter('Content-Disposition', 'filename', $filename);
+ $this->_setHeaderParameter('Content-Type', 'name', $filename);
+
+ return $this;
+ }
+
+ /**
+ * Get the file size of this attachment.
+ *
+ * @return int
+ */
+ public function getSize()
+ {
+ return $this->_getHeaderParameter('Content-Disposition', 'size');
+ }
+
+ /**
+ * Set the file size of this attachment.
+ *
+ * @param int $size
+ *
+ * @return Swift_Mime_Attachment
+ */
+ public function setSize($size)
+ {
+ $this->_setHeaderParameter('Content-Disposition', 'size', $size);
+
+ return $this;
+ }
+
+ /**
+ * Set the file that this attachment is for.
+ *
+ * @param Swift_FileStream $file
+ * @param string $contentType optional
+ *
+ * @return Swift_Mime_Attachment
+ */
+ public function setFile(Swift_FileStream $file, $contentType = null)
+ {
+ $this->setFilename(basename($file->getPath()));
+ $this->setBody($file, $contentType);
+ if (!isset($contentType)) {
+ $extension = strtolower(substr(
+ $file->getPath(), strrpos($file->getPath(), '.') + 1
+ ));
+
+ if (array_key_exists($extension, $this->_mimeTypes)) {
+ $this->setContentType($this->_mimeTypes[$extension]);
+ }
+ }
+
+ return $this;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/CharsetObserver.php b/vendor/swiftmailer/classes/Swift/Mime/CharsetObserver.php
new file mode 100644
index 00000000..57d8bc46
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/CharsetObserver.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Observes changes in an Mime entity's character set.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Mime_CharsetObserver
+{
+ /**
+ * Notify this observer that the entity's charset has changed.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder.php b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder.php
new file mode 100644
index 00000000..3338b629
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder.php
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Interface for all Transfer Encoding schemes.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Mime_ContentEncoder extends Swift_Encoder
+{
+ /**
+ * Encode $in to $out.
+ *
+ * @param Swift_OutputByteStream $os to read from
+ * @param Swift_InputByteStream $is to write to
+ * @param int $firstLineOffset
+ * @param int $maxLineLength - 0 indicates the default length for this encoding
+ */
+ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0);
+
+ /**
+ * Get the MIME name of this content encoding scheme.
+ *
+ * @return string
+ */
+ public function getName();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php
new file mode 100644
index 00000000..073daaf6
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/Base64ContentEncoder.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles Base 64 Transfer Encoding in Swift Mailer.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_ContentEncoder_Base64ContentEncoder extends Swift_Encoder_Base64Encoder implements Swift_Mime_ContentEncoder
+{
+ /**
+ * Encode stream $in to stream $out.
+ *
+ * @param Swift_OutputByteStream $os
+ * @param Swift_InputByteStream $is
+ * @param int $firstLineOffset
+ * @param int $maxLineLength, optional, 0 indicates the default of 76 bytes
+ */
+ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ if (0 >= $maxLineLength || 76 < $maxLineLength) {
+ $maxLineLength = 76;
+ }
+
+ $remainder = 0;
+
+ while (false !== $bytes = $os->read(8190)) {
+ $encoded = base64_encode($bytes);
+ $encodedTransformed = '';
+ $thisMaxLineLength = $maxLineLength - $remainder - $firstLineOffset;
+
+ while ($thisMaxLineLength < strlen($encoded)) {
+ $encodedTransformed .= substr($encoded, 0, $thisMaxLineLength) . "\r\n";
+ $firstLineOffset = 0;
+ $encoded = substr($encoded, $thisMaxLineLength);
+ $thisMaxLineLength = $maxLineLength;
+ $remainder = 0;
+ }
+
+ if (0 < $remainingLength = strlen($encoded)) {
+ $remainder += $remainingLength;
+ $encodedTransformed .= $encoded;
+ $encoded = null;
+ }
+
+ $is->write($encodedTransformed);
+ }
+ }
+
+ /**
+ * Get the name of this encoding scheme.
+ * Returns the string 'base64'.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return 'base64';
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php
new file mode 100644
index 00000000..e97195a5
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php
@@ -0,0 +1,123 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles Quoted Printable (QP) Transfer Encoding in Swift Mailer using the PHP core function.
+ *
+ * @author Lars Strojny
+ */
+class Swift_Mime_ContentEncoder_NativeQpContentEncoder implements Swift_Mime_ContentEncoder
+{
+ /**
+ * @var null|string
+ */
+ private $charset;
+
+ /**
+ * @param null|string $charset
+ */
+ public function __construct($charset = null)
+ {
+ $this->charset = $charset ? $charset : 'utf-8';
+ }
+
+ /**
+ * Notify this observer that the entity's charset has changed.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->charset = $charset;
+ }
+
+ /**
+ * Encode $in to $out.
+ *
+ * @param Swift_OutputByteStream $os to read from
+ * @param Swift_InputByteStream $is to write to
+ * @param int $firstLineOffset
+ * @param int $maxLineLength 0 indicates the default length for this encoding
+ *
+ * @throws RuntimeException
+ */
+ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ if ($this->charset !== 'utf-8') {
+ throw new RuntimeException(
+ sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset));
+ }
+
+ $string = '';
+
+ while (false !== $bytes = $os->read(8192)) {
+ $string .= $bytes;
+ }
+
+ $is->write($this->encodeString($string));
+ }
+
+ /**
+ * Get the MIME name of this content encoding scheme.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return 'quoted-printable';
+ }
+
+ /**
+ * Encode a given string to produce an encoded string.
+ *
+ * @param string $string
+ * @param int $firstLineOffset if first line needs to be shorter
+ * @param int $maxLineLength 0 indicates the default length for this encoding
+ *
+ * @return string
+ *
+ * @throws RuntimeException
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ if ($this->charset !== 'utf-8') {
+ throw new RuntimeException(
+ sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset));
+ }
+
+ return $this->_standardize(quoted_printable_encode($string));
+ }
+
+ /**
+ * Make sure CRLF is correct and HT/SPACE are in valid places.
+ *
+ * @param string $string
+ *
+ * @return string
+ */
+ protected function _standardize($string)
+ {
+ // transform CR or LF to CRLF
+ $string = preg_replace('~=0D(?!=0A)|(?<!=0D)=0A~', '=0D=0A', $string);
+ // transform =0D=0A to CRLF
+ $string = str_replace(array("\t=0D=0A", " =0D=0A", "=0D=0A"), array("=09\r\n", "=20\r\n", "\r\n"), $string);
+
+ switch ($end = ord(substr($string, -1))) {
+ case 0x09:
+ $string = substr_replace($string, '=09', -1);
+ break;
+ case 0x20:
+ $string = substr_replace($string, '=20', -1);
+ break;
+ }
+
+ return $string;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php
new file mode 100644
index 00000000..818e9af6
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/PlainContentEncoder.php
@@ -0,0 +1,163 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles binary/7/8-bit Transfer Encoding in Swift Mailer.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_ContentEncoder_PlainContentEncoder implements Swift_Mime_ContentEncoder
+{
+ /**
+ * The name of this encoding scheme (probably 7bit or 8bit).
+ *
+ * @var string
+ */
+ private $_name;
+
+ /**
+ * True if canonical transformations should be done.
+ *
+ * @var bool
+ */
+ private $_canonical;
+
+ /**
+ * Creates a new PlainContentEncoder with $name (probably 7bit or 8bit).
+ *
+ * @param string $name
+ * @param bool $canonical If canonicalization transformation should be done.
+ */
+ public function __construct($name, $canonical = false)
+ {
+ $this->_name = $name;
+ $this->_canonical = $canonical;
+ }
+
+ /**
+ * Encode a given string to produce an encoded string.
+ *
+ * @param string $string
+ * @param int $firstLineOffset ignored
+ * @param int $maxLineLength - 0 means no wrapping will occur
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ if ($this->_canonical) {
+ $string = $this->_canonicalize($string);
+ }
+
+ return $this->_safeWordWrap($string, $maxLineLength, "\r\n");
+ }
+
+ /**
+ * Encode stream $in to stream $out.
+ *
+ * @param Swift_OutputByteStream $os
+ * @param Swift_InputByteStream $is
+ * @param int $firstLineOffset ignored
+ * @param int $maxLineLength optional, 0 means no wrapping will occur
+ */
+ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ $leftOver = '';
+ while (false !== $bytes = $os->read(8192)) {
+ $toencode = $leftOver . $bytes;
+ if ($this->_canonical) {
+ $toencode = $this->_canonicalize($toencode);
+ }
+ $wrapped = $this->_safeWordWrap($toencode, $maxLineLength, "\r\n");
+ $lastLinePos = strrpos($wrapped, "\r\n");
+ $leftOver = substr($wrapped, $lastLinePos);
+ $wrapped = substr($wrapped, 0, $lastLinePos);
+
+ $is->write($wrapped);
+ }
+ if (strlen($leftOver)) {
+ $is->write($leftOver);
+ }
+ }
+
+ /**
+ * Get the name of this encoding scheme.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->_name;
+ }
+
+ /**
+ * Not used.
+ */
+ public function charsetChanged($charset)
+ {
+ }
+
+ /**
+ * A safer (but weaker) wordwrap for unicode.
+ *
+ * @param string $string
+ * @param int $length
+ * @param string $le
+ *
+ * @return string
+ */
+ private function _safeWordwrap($string, $length = 75, $le = "\r\n")
+ {
+ if (0 >= $length) {
+ return $string;
+ }
+
+ $originalLines = explode($le, $string);
+
+ $lines = array();
+ $lineCount = 0;
+
+ foreach ($originalLines as $originalLine) {
+ $lines[] = '';
+ $currentLine =& $lines[$lineCount++];
+
+ //$chunks = preg_split('/(?<=[\ \t,\.!\?\-&\+\/])/', $originalLine);
+ $chunks = preg_split('/(?<=\s)/', $originalLine);
+
+ foreach ($chunks as $chunk) {
+ if (0 != strlen($currentLine)
+ && strlen($currentLine . $chunk) > $length)
+ {
+ $lines[] = '';
+ $currentLine =& $lines[$lineCount++];
+ }
+ $currentLine .= $chunk;
+ }
+ }
+
+ return implode("\r\n", $lines);
+ }
+
+ /**
+ * Canonicalize string input (fix CRLF).
+ *
+ * @param string $string
+ *
+ * @return string
+ */
+ private function _canonicalize($string)
+ {
+ return str_replace(
+ array("\r\n", "\r", "\n"),
+ array("\n", "\n", "\r\n"),
+ $string
+ );
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php
new file mode 100644
index 00000000..49ea90e6
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php
@@ -0,0 +1,123 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles Quoted Printable (QP) Transfer Encoding in Swift Mailer.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_ContentEncoder_QpContentEncoder extends Swift_Encoder_QpEncoder implements Swift_Mime_ContentEncoder
+{
+ protected $_dotEscape;
+
+ /**
+ * Creates a new QpContentEncoder for the given CharacterStream.
+ *
+ * @param Swift_CharacterStream $charStream to use for reading characters
+ * @param Swift_StreamFilter $filter if canonicalization should occur
+ * @param bool $dotEscape if dot stuffing workaround must be enabled
+ */
+ public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null, $dotEscape = false)
+ {
+ $this->_dotEscape = $dotEscape;
+ parent::__construct($charStream, $filter);
+ }
+
+ public function __sleep()
+ {
+ return array('_charStream', '_filter', '_dotEscape');
+ }
+
+ protected function getSafeMapShareId()
+ {
+ return get_class($this).($this->_dotEscape ? '.dotEscape' : '');
+ }
+
+ protected function initSafeMap()
+ {
+ parent::initSafeMap();
+ if ($this->_dotEscape) {
+ /* Encode . as =2e for buggy remote servers */
+ unset($this->_safeMap[0x2e]);
+ }
+ }
+
+ /**
+ * Encode stream $in to stream $out.
+ *
+ * QP encoded strings have a maximum line length of 76 characters.
+ * If the first line needs to be shorter, indicate the difference with
+ * $firstLineOffset.
+ *
+ * @param Swift_OutputByteStream $os output stream
+ * @param Swift_InputByteStream $is input stream
+ * @param int $firstLineOffset
+ * @param int $maxLineLength
+ */
+ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ if ($maxLineLength > 76 || $maxLineLength <= 0) {
+ $maxLineLength = 76;
+ }
+
+ $thisLineLength = $maxLineLength - $firstLineOffset;
+
+ $this->_charStream->flushContents();
+ $this->_charStream->importByteStream($os);
+
+ $currentLine = '';
+ $prepend = '';
+ $size=$lineLen=0;
+
+ while (false !== $bytes = $this->_nextSequence()) {
+ // If we're filtering the input
+ if (isset($this->_filter)) {
+ // If we can't filter because we need more bytes
+ while ($this->_filter->shouldBuffer($bytes)) {
+ // Then collect bytes into the buffer
+ if (false === $moreBytes = $this->_nextSequence(1)) {
+ break;
+ }
+
+ foreach ($moreBytes as $b) {
+ $bytes[] = $b;
+ }
+ }
+ // And filter them
+ $bytes = $this->_filter->filter($bytes);
+ }
+
+ $enc = $this->_encodeByteSequence($bytes, $size);
+ if ($currentLine && $lineLen+$size >= $thisLineLength) {
+ $is->write($prepend . $this->_standardize($currentLine));
+ $currentLine = '';
+ $prepend = "=\r\n";
+ $thisLineLength = $maxLineLength;
+ $lineLen=0;
+ }
+ $lineLen+=$size;
+ $currentLine .= $enc;
+ }
+ if (strlen($currentLine)) {
+ $is->write($prepend . $this->_standardize($currentLine));
+ }
+ }
+
+ /**
+ * Get the name of this encoding scheme.
+ * Returns the string 'quoted-printable'.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return 'quoted-printable';
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php
new file mode 100644
index 00000000..8480f99f
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php
@@ -0,0 +1,88 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Proxy for quoted-printable content encoders.
+ *
+ * Switches on the best QP encoder implementation for current charset.
+ *
+ * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
+ */
+class Swift_Mime_ContentEncoder_QpContentEncoderProxy implements Swift_Mime_ContentEncoder
+{
+ /**
+ * @var Swift_Mime_ContentEncoder_QpContentEncoder
+ */
+ private $safeEncoder;
+
+ /**
+ * @var Swift_Mime_ContentEncoder_NativeQpContentEncoder
+ */
+ private $nativeEncoder;
+
+ /**
+ * @var null|string
+ */
+ private $charset;
+
+ /**
+ * Constructor.
+ *
+ * @param Swift_Mime_ContentEncoder_QpContentEncoder $safeEncoder
+ * @param Swift_Mime_ContentEncoder_NativeQpContentEncoder $nativeEncoder
+ * @param string|null $charset
+ */
+ public function __construct(Swift_Mime_ContentEncoder_QpContentEncoder $safeEncoder, Swift_Mime_ContentEncoder_NativeQpContentEncoder $nativeEncoder, $charset)
+ {
+ $this->safeEncoder = $safeEncoder;
+ $this->nativeEncoder = $nativeEncoder;
+ $this->charset = $charset;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function charsetChanged($charset)
+ {
+ $this->charset = $charset;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ $this->getEncoder()->encodeByteStream($os, $is, $firstLineOffset, $maxLineLength);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'quoted-printable';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ return $this->getEncoder()->encodeString($string, $firstLineOffset, $maxLineLength);
+ }
+
+ /**
+ * @return Swift_Mime_ContentEncoder
+ */
+ private function getEncoder()
+ {
+ return 'utf-8' === $this->charset ? $this->nativeEncoder : $this->safeEncoder;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php
new file mode 100644
index 00000000..f717dc78
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles raw Transfer Encoding in Swift Mailer.
+ *
+ *
+ * @author Sebastiaan Stok <s.stok@rollerscapes.net>
+ */
+class Swift_Mime_ContentEncoder_RawContentEncoder implements Swift_Mime_ContentEncoder
+{
+ /**
+ * Encode a given string to produce an encoded string.
+ *
+ * @param string $string
+ * @param int $firstLineOffset ignored
+ * @param int $maxLineLength ignored
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ return $string;
+ }
+
+ /**
+ * Encode stream $in to stream $out.
+ *
+ * @param Swift_OutputByteStream $in
+ * @param Swift_InputByteStream $out
+ * @param int $firstLineOffset ignored
+ * @param int $maxLineLength ignored
+ */
+ public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ while (false !== ($bytes = $os->read(8192))) {
+ $is->write($bytes);
+ }
+ }
+
+ /**
+ * Get the name of this encoding scheme.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return 'raw';
+ }
+
+ /**
+ * Not used.
+ */
+ public function charsetChanged($charset)
+ {
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/EmbeddedFile.php b/vendor/swiftmailer/classes/Swift/Mime/EmbeddedFile.php
new file mode 100644
index 00000000..ec1ef535
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/EmbeddedFile.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An embedded file, in a multipart message.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_EmbeddedFile extends Swift_Mime_Attachment
+{
+ /**
+ * Creates a new Attachment with $headers and $encoder.
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ * @param Swift_Mime_ContentEncoder $encoder
+ * @param Swift_KeyCache $cache
+ * @param Swift_Mime_Grammar $grammar
+ * @param array $mimeTypes optional
+ */
+ public function __construct(Swift_Mime_HeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_Mime_Grammar $grammar, $mimeTypes = array())
+ {
+ parent::__construct($headers, $encoder, $cache, $grammar, $mimeTypes);
+ $this->setDisposition('inline');
+ $this->setId($this->getId());
+ }
+
+ /**
+ * Get the nesting level of this EmbeddedFile.
+ *
+ * Returns {@see LEVEL_RELATED}.
+ *
+ * @return int
+ */
+ public function getNestingLevel()
+ {
+ return self::LEVEL_RELATED;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/EncodingObserver.php b/vendor/swiftmailer/classes/Swift/Mime/EncodingObserver.php
new file mode 100644
index 00000000..e262974b
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/EncodingObserver.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Observes changes for a Mime entity's ContentEncoder.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Mime_EncodingObserver
+{
+ /**
+ * Notify this observer that the observed entity's ContentEncoder has changed.
+ *
+ * @param Swift_Mime_ContentEncoder $encoder
+ */
+ public function encoderChanged(Swift_Mime_ContentEncoder $encoder);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/Grammar.php b/vendor/swiftmailer/classes/Swift/Mime/Grammar.php
new file mode 100644
index 00000000..bd8e6f96
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/Grammar.php
@@ -0,0 +1,176 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Defines the grammar to use for validation, implements the RFC 2822 (and friends) ABNF grammar definitions.
+ *
+ * @author Fabien Potencier
+ * @author Chris Corbyn
+ */
+class Swift_Mime_Grammar
+{
+ /**
+ * Special characters used in the syntax which need to be escaped.
+ *
+ * @var string[]
+ */
+ private static $_specials = array();
+
+ /**
+ * Tokens defined in RFC 2822 (and some related RFCs).
+ *
+ * @var string[]
+ */
+ private static $_grammar = array();
+
+ /**
+ * Initialize some RFC 2822 (and friends) ABNF grammar definitions.
+ */
+ public function __construct()
+ {
+ $this->init();
+ }
+
+ public function __wakeup()
+ {
+ $this->init();
+ }
+
+ protected function init()
+ {
+ if (count(self::$_specials) > 0) {
+ return;
+ }
+
+ self::$_specials = array(
+ '(', ')', '<', '>', '[', ']',
+ ':', ';', '@', ',', '.', '"'
+ );
+
+ /*** Refer to RFC 2822 for ABNF grammar ***/
+
+ // All basic building blocks
+ self::$_grammar['NO-WS-CTL'] = '[\x01-\x08\x0B\x0C\x0E-\x19\x7F]';
+ self::$_grammar['WSP'] = '[ \t]';
+ self::$_grammar['CRLF'] = '(?:\r\n)';
+ self::$_grammar['FWS'] = '(?:(?:' . self::$_grammar['WSP'] . '*' .
+ self::$_grammar['CRLF'] . ')?' . self::$_grammar['WSP'] . ')';
+ self::$_grammar['text'] = '[\x00-\x08\x0B\x0C\x0E-\x7F]';
+ self::$_grammar['quoted-pair'] = '(?:\\\\' . self::$_grammar['text'] . ')';
+ self::$_grammar['ctext'] = '(?:' . self::$_grammar['NO-WS-CTL'] .
+ '|[\x21-\x27\x2A-\x5B\x5D-\x7E])';
+ // Uses recursive PCRE (?1) -- could be a weak point??
+ self::$_grammar['ccontent'] = '(?:' . self::$_grammar['ctext'] . '|' .
+ self::$_grammar['quoted-pair'] . '|(?1))';
+ self::$_grammar['comment'] = '(\((?:' . self::$_grammar['FWS'] . '|' .
+ self::$_grammar['ccontent']. ')*' . self::$_grammar['FWS'] . '?\))';
+ self::$_grammar['CFWS'] = '(?:(?:' . self::$_grammar['FWS'] . '?' .
+ self::$_grammar['comment'] . ')*(?:(?:' . self::$_grammar['FWS'] . '?' .
+ self::$_grammar['comment'] . ')|' . self::$_grammar['FWS'] . '))';
+ self::$_grammar['qtext'] = '(?:' . self::$_grammar['NO-WS-CTL'] .
+ '|[\x21\x23-\x5B\x5D-\x7E])';
+ self::$_grammar['qcontent'] = '(?:' . self::$_grammar['qtext'] . '|' .
+ self::$_grammar['quoted-pair'] . ')';
+ self::$_grammar['quoted-string'] = '(?:' . self::$_grammar['CFWS'] . '?"' .
+ '(' . self::$_grammar['FWS'] . '?' . self::$_grammar['qcontent'] . ')*' .
+ self::$_grammar['FWS'] . '?"' . self::$_grammar['CFWS'] . '?)';
+ self::$_grammar['atext'] = '[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]';
+ self::$_grammar['atom'] = '(?:' . self::$_grammar['CFWS'] . '?' .
+ self::$_grammar['atext'] . '+' . self::$_grammar['CFWS'] . '?)';
+ self::$_grammar['dot-atom-text'] = '(?:' . self::$_grammar['atext'] . '+' .
+ '(\.' . self::$_grammar['atext'] . '+)*)';
+ self::$_grammar['dot-atom'] = '(?:' . self::$_grammar['CFWS'] . '?' .
+ self::$_grammar['dot-atom-text'] . '+' . self::$_grammar['CFWS'] . '?)';
+ self::$_grammar['word'] = '(?:' . self::$_grammar['atom'] . '|' .
+ self::$_grammar['quoted-string'] . ')';
+ self::$_grammar['phrase'] = '(?:' . self::$_grammar['word'] . '+?)';
+ self::$_grammar['no-fold-quote'] = '(?:"(?:' . self::$_grammar['qtext'] .
+ '|' . self::$_grammar['quoted-pair'] . ')*")';
+ self::$_grammar['dtext'] = '(?:' . self::$_grammar['NO-WS-CTL'] .
+ '|[\x21-\x5A\x5E-\x7E])';
+ self::$_grammar['no-fold-literal'] = '(?:\[(?:' . self::$_grammar['dtext'] .
+ '|' . self::$_grammar['quoted-pair'] . ')*\])';
+
+ // Message IDs
+ self::$_grammar['id-left'] = '(?:' . self::$_grammar['dot-atom-text'] . '|' .
+ self::$_grammar['no-fold-quote'] . ')';
+ self::$_grammar['id-right'] = '(?:' . self::$_grammar['dot-atom-text'] . '|' .
+ self::$_grammar['no-fold-literal'] . ')';
+
+ // Addresses, mailboxes and paths
+ self::$_grammar['local-part'] = '(?:' . self::$_grammar['dot-atom'] . '|' .
+ self::$_grammar['quoted-string'] . ')';
+ self::$_grammar['dcontent'] = '(?:' . self::$_grammar['dtext'] . '|' .
+ self::$_grammar['quoted-pair'] . ')';
+ self::$_grammar['domain-literal'] = '(?:' . self::$_grammar['CFWS'] . '?\[(' .
+ self::$_grammar['FWS'] . '?' . self::$_grammar['dcontent'] . ')*?' .
+ self::$_grammar['FWS'] . '?\]' . self::$_grammar['CFWS'] . '?)';
+ self::$_grammar['domain'] = '(?:' . self::$_grammar['dot-atom'] . '|' .
+ self::$_grammar['domain-literal'] . ')';
+ self::$_grammar['addr-spec'] = '(?:' . self::$_grammar['local-part'] . '@' .
+ self::$_grammar['domain'] . ')';
+ }
+
+ /**
+ * Get the grammar defined for $name token.
+ *
+ * @param string $name exactly as written in the RFC
+ *
+ * @return string
+ */
+ public function getDefinition($name)
+ {
+ if (array_key_exists($name, self::$_grammar)) {
+ return self::$_grammar[$name];
+ } else {
+ throw new Swift_RfcComplianceException(
+ "No such grammar '" . $name . "' defined."
+ );
+ }
+ }
+
+ /**
+ * Returns the tokens defined in RFC 2822 (and some related RFCs).
+ *
+ * @return array
+ */
+ public function getGrammarDefinitions()
+ {
+ return self::$_grammar;
+ }
+
+ /**
+ * Returns the current special characters used in the syntax which need to be escaped.
+ *
+ * @return array
+ */
+ public function getSpecials()
+ {
+ return self::$_specials;
+ }
+
+ /**
+ * Escape special characters in a string (convert to quoted-pairs).
+ *
+ * @param string $token
+ * @param string[] $include additional chars to escape
+ * @param string[] $exclude chars from escaping
+ *
+ * @return string
+ */
+ public function escapeSpecials($token, $include = array(), $exclude = array())
+ {
+ foreach (array_merge(array('\\'), array_diff(self::$_specials, $exclude), $include) as $char) {
+ $token = str_replace($char, '\\' . $char, $token);
+ }
+
+ return $token;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/Header.php b/vendor/swiftmailer/classes/Swift/Mime/Header.php
new file mode 100644
index 00000000..7074c4f6
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/Header.php
@@ -0,0 +1,93 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A MIME Header.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Mime_Header
+{
+ /** Text headers */
+ const TYPE_TEXT = 2;
+
+ /** headers (text + params) */
+ const TYPE_PARAMETERIZED = 6;
+
+ /** Mailbox and address headers */
+ const TYPE_MAILBOX = 8;
+
+ /** Date and time headers */
+ const TYPE_DATE = 16;
+
+ /** Identification headers */
+ const TYPE_ID = 32;
+
+ /** Address path headers */
+ const TYPE_PATH = 64;
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType();
+
+ /**
+ * Set the model for the field body.
+ *
+ * The actual types needed will vary depending upon the type of Header.
+ *
+ * @param mixed $model
+ */
+ public function setFieldBodyModel($model);
+
+ /**
+ * Set the charset used when rendering the Header.
+ *
+ * @param string $charset
+ */
+ public function setCharset($charset);
+
+ /**
+ * Get the model for the field body.
+ *
+ * The return type depends on the specifics of the Header.
+ *
+ * @return mixed
+ */
+ public function getFieldBodyModel();
+
+ /**
+ * Get the name of this header (e.g. Subject).
+ *
+ * The name is an identifier and as such will be immutable.
+ *
+ * @return string
+ */
+ public function getFieldName();
+
+ /**
+ * Get the field body, prepared for folding into a final header value.
+ *
+ * @return string
+ */
+ public function getFieldBody();
+
+ /**
+ * Get this Header rendered as a compliant string.
+ *
+ * @return string
+ */
+ public function toString();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/HeaderEncoder.php b/vendor/swiftmailer/classes/Swift/Mime/HeaderEncoder.php
new file mode 100644
index 00000000..6e014a1d
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/HeaderEncoder.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Interface for all Header Encoding schemes.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Mime_HeaderEncoder extends Swift_Encoder
+{
+ /**
+ * Get the MIME name of this content encoding scheme.
+ *
+ * @return string
+ */
+ public function getName();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php b/vendor/swiftmailer/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php
new file mode 100644
index 00000000..6dbc6edc
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/HeaderEncoder/Base64HeaderEncoder.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles Base64 (B) Header Encoding in Swift Mailer.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_HeaderEncoder_Base64HeaderEncoder extends Swift_Encoder_Base64Encoder implements Swift_Mime_HeaderEncoder
+{
+ /**
+ * Get the name of this encoding scheme.
+ * Returns the string 'B'.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return 'B';
+ }
+
+ /**
+ * Takes an unencoded string and produces a Base64 encoded string from it.
+ *
+ * If the charset is iso-2022-jp, it uses mb_encode_mimeheader instead of
+ * default encodeString, otherwise pass to the parent method.
+ *
+ * @param string $string string to encode
+ * @param int $firstLineOffset
+ * @param int $maxLineLength optional, 0 indicates the default of 76 bytes
+ * @param string $charset
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0, $charset = 'utf-8')
+ {
+ if (strtolower($charset) === 'iso-2022-jp') {
+ $old = mb_internal_encoding();
+ mb_internal_encoding('utf-8');
+ $newstring = mb_encode_mimeheader($string, $charset, $this->getName(), "\r\n");
+ mb_internal_encoding($old);
+
+ return $newstring;
+ }
+
+ return parent::encodeString($string, $firstLineOffset, $maxLineLength);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php b/vendor/swiftmailer/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php
new file mode 100644
index 00000000..dd8ff382
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles Quoted Printable (Q) Header Encoding in Swift Mailer.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_HeaderEncoder_QpHeaderEncoder extends Swift_Encoder_QpEncoder implements Swift_Mime_HeaderEncoder
+{
+ /**
+ * Creates a new QpHeaderEncoder for the given CharacterStream.
+ *
+ * @param Swift_CharacterStream $charStream to use for reading characters
+ */
+ public function __construct(Swift_CharacterStream $charStream)
+ {
+ parent::__construct($charStream);
+ }
+
+ protected function initSafeMap()
+ {
+ foreach (array_merge(
+ range(0x61, 0x7A), range(0x41, 0x5A),
+ range(0x30, 0x39), array(0x20, 0x21, 0x2A, 0x2B, 0x2D, 0x2F)
+ ) as $byte) {
+ $this->_safeMap[$byte] = chr($byte);
+ }
+ }
+
+ /**
+ * Get the name of this encoding scheme.
+ *
+ * Returns the string 'Q'.
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return 'Q';
+ }
+
+ /**
+ * Takes an unencoded string and produces a QP encoded string from it.
+ *
+ * @param string $string string to encode
+ * @param int $firstLineOffset optional
+ * @param int $maxLineLength optional, 0 indicates the default of 76 chars
+ *
+ * @return string
+ */
+ public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
+ {
+ return str_replace(array(' ', '=20', "=\r\n"), array('_', '_', "\r\n"),
+ parent::encodeString($string, $firstLineOffset, $maxLineLength)
+ );
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/HeaderFactory.php b/vendor/swiftmailer/classes/Swift/Mime/HeaderFactory.php
new file mode 100644
index 00000000..423cebcf
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/HeaderFactory.php
@@ -0,0 +1,78 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Creates MIME headers.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Mime_HeaderFactory extends Swift_Mime_CharsetObserver
+{
+ /**
+ * Create a new Mailbox Header with a list of $addresses.
+ *
+ * @param string $name
+ * @param array|string $addresses
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createMailboxHeader($name, $addresses = null);
+
+ /**
+ * Create a new Date header using $timestamp (UNIX time).
+ *
+ * @param string $name
+ * @param int $timestamp
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createDateHeader($name, $timestamp = null);
+
+ /**
+ * Create a new basic text header with $name and $value.
+ *
+ * @param string $name
+ * @param string $value
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createTextHeader($name, $value = null);
+
+ /**
+ * Create a new ParameterizedHeader with $name, $value and $params.
+ *
+ * @param string $name
+ * @param string $value
+ * @param array $params
+ *
+ * @return Swift_Mime_ParameterizedHeader
+ */
+ public function createParameterizedHeader($name, $value = null, $params = array());
+
+ /**
+ * Create a new ID header for Message-ID or Content-ID.
+ *
+ * @param string $name
+ * @param string|array $ids
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createIdHeader($name, $ids = null);
+
+ /**
+ * Create a new Path header with an address (path) in it.
+ *
+ * @param string $name
+ * @param string $path
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createPathHeader($name, $path = null);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/HeaderSet.php b/vendor/swiftmailer/classes/Swift/Mime/HeaderSet.php
new file mode 100644
index 00000000..b9140662
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/HeaderSet.php
@@ -0,0 +1,169 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A collection of MIME headers.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Mime_HeaderSet extends Swift_Mime_CharsetObserver
+{
+ /**
+ * Add a new Mailbox Header with a list of $addresses.
+ *
+ * @param string $name
+ * @param array|string $addresses
+ */
+ public function addMailboxHeader($name, $addresses = null);
+
+ /**
+ * Add a new Date header using $timestamp (UNIX time).
+ *
+ * @param string $name
+ * @param int $timestamp
+ */
+ public function addDateHeader($name, $timestamp = null);
+
+ /**
+ * Add a new basic text header with $name and $value.
+ *
+ * @param string $name
+ * @param string $value
+ */
+ public function addTextHeader($name, $value = null);
+
+ /**
+ * Add a new ParameterizedHeader with $name, $value and $params.
+ *
+ * @param string $name
+ * @param string $value
+ * @param array $params
+ */
+ public function addParameterizedHeader($name, $value = null, $params = array());
+
+ /**
+ * Add a new ID header for Message-ID or Content-ID.
+ *
+ * @param string $name
+ * @param string|array $ids
+ */
+ public function addIdHeader($name, $ids = null);
+
+ /**
+ * Add a new Path header with an address (path) in it.
+ *
+ * @param string $name
+ * @param string $path
+ */
+ public function addPathHeader($name, $path = null);
+
+ /**
+ * Returns true if at least one header with the given $name exists.
+ *
+ * If multiple headers match, the actual one may be specified by $index.
+ *
+ * @param string $name
+ * @param int $index
+ *
+ * @return bool
+ */
+ public function has($name, $index = 0);
+
+ /**
+ * Set a header in the HeaderSet.
+ *
+ * The header may be a previously fetched header via {@link get()} or it may
+ * be one that has been created separately.
+ *
+ * If $index is specified, the header will be inserted into the set at this
+ * offset.
+ *
+ * @param Swift_Mime_Header $header
+ * @param int $index
+ */
+ public function set(Swift_Mime_Header $header, $index = 0);
+
+ /**
+ * Get the header with the given $name.
+ * If multiple headers match, the actual one may be specified by $index.
+ * Returns NULL if none present.
+ *
+ * @param string $name
+ * @param int $index
+ *
+ * @return Swift_Mime_Header
+ */
+ public function get($name, $index = 0);
+
+ /**
+ * Get all headers with the given $name.
+ *
+ * @param string $name
+ *
+ * @return array
+ */
+ public function getAll($name = null);
+
+ /**
+ * Return the name of all Headers
+ *
+ * @return array
+ */
+ public function listAll();
+
+ /**
+ * Remove the header with the given $name if it's set.
+ *
+ * If multiple headers match, the actual one may be specified by $index.
+ *
+ * @param string $name
+ * @param int $index
+ */
+ public function remove($name, $index = 0);
+
+ /**
+ * Remove all headers with the given $name.
+ *
+ * @param string $name
+ */
+ public function removeAll($name);
+
+ /**
+ * Create a new instance of this HeaderSet.
+ *
+ * @return Swift_Mime_HeaderSet
+ */
+ public function newInstance();
+
+ /**
+ * Define a list of Header names as an array in the correct order.
+ *
+ * These Headers will be output in the given order where present.
+ *
+ * @param array $sequence
+ */
+ public function defineOrdering(array $sequence);
+
+ /**
+ * Set a list of header names which must always be displayed when set.
+ *
+ * Usually headers without a field value won't be output unless set here.
+ *
+ * @param array $names
+ */
+ public function setAlwaysDisplayed(array $names);
+
+ /**
+ * Returns a string with a representation of all headers.
+ *
+ * @return string
+ */
+ public function toString();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/Headers/AbstractHeader.php b/vendor/swiftmailer/classes/Swift/Mime/Headers/AbstractHeader.php
new file mode 100644
index 00000000..1050de77
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/Headers/AbstractHeader.php
@@ -0,0 +1,502 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An abstract base MIME Header.
+ *
+ * @author Chris Corbyn
+ */
+abstract class Swift_Mime_Headers_AbstractHeader implements Swift_Mime_Header
+{
+ /**
+ * The name of this Header.
+ *
+ * @var string
+ */
+ private $_name;
+
+ /**
+ * The Grammar used for this Header.
+ *
+ * @var Swift_Mime_Grammar
+ */
+ private $_grammar;
+
+ /**
+ * The Encoder used to encode this Header.
+ *
+ * @var Swift_Encoder
+ */
+ private $_encoder;
+
+ /**
+ * The maximum length of a line in the header.
+ *
+ * @var int
+ */
+ private $_lineLength = 78;
+
+ /**
+ * The language used in this Header.
+ *
+ * @var string
+ */
+ private $_lang;
+
+ /**
+ * The character set of the text in this Header.
+ *
+ * @var string
+ */
+ private $_charset = 'utf-8';
+
+ /**
+ * The value of this Header, cached.
+ *
+ * @var string
+ */
+ private $_cachedValue = null;
+
+ /**
+ * Creates a new Header.
+ *
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function __construct(Swift_Mime_Grammar $grammar)
+ {
+ $this->setGrammar($grammar);
+ }
+
+ /**
+ * Set the character set used in this Header.
+ *
+ * @param string $charset
+ */
+ public function setCharset($charset)
+ {
+ $this->clearCachedValueIf($charset != $this->_charset);
+ $this->_charset = $charset;
+ if (isset($this->_encoder)) {
+ $this->_encoder->charsetChanged($charset);
+ }
+ }
+
+ /**
+ * Get the character set used in this Header.
+ *
+ * @return string
+ */
+ public function getCharset()
+ {
+ return $this->_charset;
+ }
+
+ /**
+ * Set the language used in this Header.
+ *
+ * For example, for US English, 'en-us'.
+ * This can be unspecified.
+ *
+ * @param string $lang
+ */
+ public function setLanguage($lang)
+ {
+ $this->clearCachedValueIf($this->_lang != $lang);
+ $this->_lang = $lang;
+ }
+
+ /**
+ * Get the language used in this Header.
+ *
+ * @return string
+ */
+ public function getLanguage()
+ {
+ return $this->_lang;
+ }
+
+ /**
+ * Set the encoder used for encoding the header.
+ *
+ * @param Swift_Mime_HeaderEncoder $encoder
+ */
+ public function setEncoder(Swift_Mime_HeaderEncoder $encoder)
+ {
+ $this->_encoder = $encoder;
+ $this->setCachedValue(null);
+ }
+
+ /**
+ * Get the encoder used for encoding this Header.
+ *
+ * @return Swift_Mime_HeaderEncoder
+ */
+ public function getEncoder()
+ {
+ return $this->_encoder;
+ }
+
+ /**
+ * Set the grammar used for the header.
+ *
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function setGrammar(Swift_Mime_Grammar $grammar)
+ {
+ $this->_grammar = $grammar;
+ $this->setCachedValue(null);
+ }
+
+ /**
+ * Get the grammar used for this Header.
+ *
+ * @return Swift_Mime_Grammar
+ */
+ public function getGrammar()
+ {
+ return $this->_grammar;
+ }
+
+ /**
+ * Get the name of this header (e.g. charset).
+ *
+ * @return string
+ */
+ public function getFieldName()
+ {
+ return $this->_name;
+ }
+
+ /**
+ * Set the maximum length of lines in the header (excluding EOL).
+ *
+ * @param int $lineLength
+ */
+ public function setMaxLineLength($lineLength)
+ {
+ $this->clearCachedValueIf($this->_lineLength != $lineLength);
+ $this->_lineLength = $lineLength;
+ }
+
+ /**
+ * Get the maximum permitted length of lines in this Header.
+ *
+ * @return int
+ */
+ public function getMaxLineLength()
+ {
+ return $this->_lineLength;
+ }
+
+ /**
+ * Get this Header rendered as a RFC 2822 compliant string.
+ *
+ * @return string
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function toString()
+ {
+ return $this->_tokensToString($this->toTokens());
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @return string
+ *
+ * @see toString()
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+
+ // -- Points of extension
+
+ /**
+ * Set the name of this Header field.
+ *
+ * @param string $name
+ */
+ protected function setFieldName($name)
+ {
+ $this->_name = $name;
+ }
+
+ /**
+ * Produces a compliant, formatted RFC 2822 'phrase' based on the string given.
+ *
+ * @param Swift_Mime_Header $header
+ * @param string $string as displayed
+ * @param string $charset of the text
+ * @param Swift_Mime_HeaderEncoder $encoder
+ * @param bool $shorten the first line to make remove for header name
+ *
+ * @return string
+ */
+ protected function createPhrase(Swift_Mime_Header $header, $string, $charset, Swift_Mime_HeaderEncoder $encoder = null, $shorten = false)
+ {
+ // Treat token as exactly what was given
+ $phraseStr = $string;
+ // If it's not valid
+ if (!preg_match('/^' . $this->getGrammar()->getDefinition('phrase') . '$/D', $phraseStr)) {
+ // .. but it is just ascii text, try escaping some characters
+ // and make it a quoted-string
+ if (preg_match('/^' . $this->getGrammar()->getDefinition('text') . '*$/D', $phraseStr)) {
+ $phraseStr = $this->getGrammar()->escapeSpecials(
+ $phraseStr, array('"'), $this->getGrammar()->getSpecials()
+ );
+ $phraseStr = '"' . $phraseStr . '"';
+ } else { // ... otherwise it needs encoding
+ // Determine space remaining on line if first line
+ if ($shorten) {
+ $usedLength = strlen($header->getFieldName() . ': ');
+ } else {
+ $usedLength = 0;
+ }
+ $phraseStr = $this->encodeWords($header, $string, $usedLength);
+ }
+ }
+
+ return $phraseStr;
+ }
+
+ /**
+ * Encode needed word tokens within a string of input.
+ *
+ * @param Swift_Mime_Header $header
+ * @param string $input
+ * @param string $usedLength optional
+ *
+ * @return string
+ */
+ protected function encodeWords(Swift_Mime_Header $header, $input, $usedLength = -1)
+ {
+ $value = '';
+
+ $tokens = $this->getEncodableWordTokens($input);
+
+ foreach ($tokens as $token) {
+ // See RFC 2822, Sect 2.2 (really 2.2 ??)
+ if ($this->tokenNeedsEncoding($token)) {
+ // Don't encode starting WSP
+ $firstChar = substr($token, 0, 1);
+ switch ($firstChar) {
+ case ' ':
+ case "\t":
+ $value .= $firstChar;
+ $token = substr($token, 1);
+ }
+
+ if (-1 == $usedLength) {
+ $usedLength = strlen($header->getFieldName() . ': ') + strlen($value);
+ }
+ $value .= $this->getTokenAsEncodedWord($token, $usedLength);
+
+ $header->setMaxLineLength(76); // Forcefully override
+ } else {
+ $value .= $token;
+ }
+ }
+
+ return $value;
+ }
+
+ /**
+ * Test if a token needs to be encoded or not.
+ *
+ * @param string $token
+ *
+ * @return bool
+ */
+ protected function tokenNeedsEncoding($token)
+ {
+ return preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token);
+ }
+
+ /**
+ * Splits a string into tokens in blocks of words which can be encoded quickly.
+ *
+ * @param string $string
+ *
+ * @return string[]
+ */
+ protected function getEncodableWordTokens($string)
+ {
+ $tokens = array();
+
+ $encodedToken = '';
+ // Split at all whitespace boundaries
+ foreach (preg_split('~(?=[\t ])~', $string) as $token) {
+ if ($this->tokenNeedsEncoding($token)) {
+ $encodedToken .= $token;
+ } else {
+ if (strlen($encodedToken) > 0) {
+ $tokens[] = $encodedToken;
+ $encodedToken = '';
+ }
+ $tokens[] = $token;
+ }
+ }
+ if (strlen($encodedToken)) {
+ $tokens[] = $encodedToken;
+ }
+
+ return $tokens;
+ }
+
+ /**
+ * Get a token as an encoded word for safe insertion into headers.
+ *
+ * @param string $token token to encode
+ * @param int $firstLineOffset optional
+ *
+ * @return string
+ */
+ protected function getTokenAsEncodedWord($token, $firstLineOffset = 0)
+ {
+ // Adjust $firstLineOffset to account for space needed for syntax
+ $charsetDecl = $this->_charset;
+ if (isset($this->_lang)) {
+ $charsetDecl .= '*' . $this->_lang;
+ }
+ $encodingWrapperLength = strlen(
+ '=?' . $charsetDecl . '?' . $this->_encoder->getName() . '??='
+ );
+
+ if ($firstLineOffset >= 75) { //Does this logic need to be here?
+ $firstLineOffset = 0;
+ }
+
+ $encodedTextLines = explode("\r\n",
+ $this->_encoder->encodeString(
+ $token, $firstLineOffset, 75 - $encodingWrapperLength, $this->_charset
+ )
+ );
+
+ if (strtolower($this->_charset) !== 'iso-2022-jp') { // special encoding for iso-2022-jp using mb_encode_mimeheader
+ foreach ($encodedTextLines as $lineNum => $line) {
+ $encodedTextLines[$lineNum] = '=?' . $charsetDecl .
+ '?' . $this->_encoder->getName() .
+ '?' . $line . '?=';
+ }
+ }
+
+ return implode("\r\n ", $encodedTextLines);
+ }
+
+ /**
+ * Generates tokens from the given string which include CRLF as individual tokens.
+ *
+ * @param string $token
+ *
+ * @return string[]
+ */
+ protected function generateTokenLines($token)
+ {
+ return preg_split('~(\r\n)~', $token, -1, PREG_SPLIT_DELIM_CAPTURE);
+ }
+
+ /**
+ * Set a value into the cache.
+ *
+ * @param string $value
+ */
+ protected function setCachedValue($value)
+ {
+ $this->_cachedValue = $value;
+ }
+
+ /**
+ * Get the value in the cache.
+ *
+ * @return string
+ */
+ protected function getCachedValue()
+ {
+ return $this->_cachedValue;
+ }
+
+ /**
+ * Clear the cached value if $condition is met.
+ *
+ * @param bool $condition
+ */
+ protected function clearCachedValueIf($condition)
+ {
+ if ($condition) {
+ $this->setCachedValue(null);
+ }
+ }
+
+
+ /**
+ * Generate a list of all tokens in the final header.
+ *
+ * @param string $string The string to tokenize
+ *
+ * @return array An array of tokens as strings
+ */
+ protected function toTokens($string = null)
+ {
+ if (is_null($string)) {
+ $string = $this->getFieldBody();
+ }
+
+ $tokens = array();
+
+ // Generate atoms; split at all invisible boundaries followed by WSP
+ foreach (preg_split('~(?=[ \t])~', $string) as $token) {
+ $newTokens = $this->generateTokenLines($token);
+ foreach ($newTokens as $newToken) {
+ $tokens[] = $newToken;
+ }
+ }
+
+ return $tokens;
+ }
+
+ /**
+ * Takes an array of tokens which appear in the header and turns them into
+ * an RFC 2822 compliant string, adding FWSP where needed.
+ *
+ * @param string[] $tokens
+ *
+ * @return string
+ */
+ private function _tokensToString(array $tokens)
+ {
+ $lineCount = 0;
+ $headerLines = array();
+ $headerLines[] = $this->_name . ': ';
+ $currentLine =& $headerLines[$lineCount++];
+
+ // Build all tokens back into compliant header
+ foreach ($tokens as $i => $token) {
+ // Line longer than specified maximum or token was just a new line
+ if (("\r\n" == $token) ||
+ ($i > 0 && strlen($currentLine . $token) > $this->_lineLength)
+ && 0 < strlen($currentLine))
+ {
+ $headerLines[] = '';
+ $currentLine =& $headerLines[$lineCount++];
+ }
+
+ // Append token to the line
+ if ("\r\n" != $token) {
+ $currentLine .= $token;
+ }
+ }
+
+ // Implode with FWS (RFC 2822, 2.2.3)
+ return implode("\r\n", $headerLines) . "\r\n";
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/Headers/DateHeader.php b/vendor/swiftmailer/classes/Swift/Mime/Headers/DateHeader.php
new file mode 100644
index 00000000..a1093fb0
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/Headers/DateHeader.php
@@ -0,0 +1,125 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A Date MIME Header for Swift Mailer.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_Headers_DateHeader extends Swift_Mime_Headers_AbstractHeader
+{
+ /**
+ * The UNIX timestamp value of this Header.
+ *
+ * @var int
+ */
+ private $_timestamp;
+
+ /**
+ * Creates a new DateHeader with $name and $timestamp.
+ *
+ * Example:
+ * <code>
+ * <?php
+ * $header = new Swift_Mime_Headers_DateHeader('Date', time());
+ * ?>
+ * </code>
+ *
+ * @param string $name of Header
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function __construct($name, Swift_Mime_Grammar $grammar)
+ {
+ $this->setFieldName($name);
+ parent::__construct($grammar);
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_DATE;
+ }
+
+ /**
+ * Set the model for the field body.
+ *
+ * This method takes a UNIX timestamp.
+ *
+ * @param int $model
+ */
+ public function setFieldBodyModel($model)
+ {
+ $this->setTimestamp($model);
+ }
+
+ /**
+ * Get the model for the field body.
+ *
+ * This method returns a UNIX timestamp.
+ *
+ * @return mixed
+ */
+ public function getFieldBodyModel()
+ {
+ return $this->getTimestamp();
+ }
+
+ /**
+ * Get the UNIX timestamp of the Date in this Header.
+ *
+ * @return int
+ */
+ public function getTimestamp()
+ {
+ return $this->_timestamp;
+ }
+
+ /**
+ * Set the UNIX timestamp of the Date in this Header.
+ *
+ * @param int $timestamp
+ */
+ public function setTimestamp($timestamp)
+ {
+ if (!is_null($timestamp)) {
+ $timestamp = (int) $timestamp;
+ }
+ $this->clearCachedValueIf($this->_timestamp != $timestamp);
+ $this->_timestamp = $timestamp;
+ }
+
+ /**
+ * Get the string value of the body in this Header.
+ *
+ * This is not necessarily RFC 2822 compliant since folding white space will
+ * not be added at this stage (see {@link toString()} for that).
+ *
+ * @see toString()
+ *
+ * @return string
+ */
+ public function getFieldBody()
+ {
+ if (!$this->getCachedValue()) {
+ if (isset($this->_timestamp)) {
+ $this->setCachedValue(date('r', $this->_timestamp));
+ }
+ }
+
+ return $this->getCachedValue();
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/Headers/IdentificationHeader.php b/vendor/swiftmailer/classes/Swift/Mime/Headers/IdentificationHeader.php
new file mode 100644
index 00000000..bf45aa94
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/Headers/IdentificationHeader.php
@@ -0,0 +1,181 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An ID MIME Header for something like Message-ID or Content-ID.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_Headers_IdentificationHeader extends Swift_Mime_Headers_AbstractHeader
+{
+ /**
+ * The IDs used in the value of this Header.
+ *
+ * This may hold multiple IDs or just a single ID.
+ *
+ * @var string[]
+ */
+ private $_ids = array();
+
+ /**
+ * Creates a new IdentificationHeader with the given $name and $id.
+ *
+ * @param string $name
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function __construct($name, Swift_Mime_Grammar $grammar)
+ {
+ $this->setFieldName($name);
+ parent::__construct($grammar);
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_ID;
+ }
+
+ /**
+ * Set the model for the field body.
+ *
+ * This method takes a string ID, or an array of IDs.
+ *
+ * @param mixed $model
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setFieldBodyModel($model)
+ {
+ $this->setId($model);
+ }
+
+ /**
+ * Get the model for the field body.
+ *
+ * This method returns an array of IDs
+ *
+ * @return array
+ */
+ public function getFieldBodyModel()
+ {
+ return $this->getIds();
+ }
+
+ /**
+ * Set the ID used in the value of this header.
+ *
+ * @param string|array $id
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setId($id)
+ {
+ $this->setIds(is_array($id) ? $id : array($id));
+ }
+
+ /**
+ * Get the ID used in the value of this Header.
+ *
+ * If multiple IDs are set only the first is returned.
+ *
+ * @return string
+ */
+ public function getId()
+ {
+ if (count($this->_ids) > 0) {
+ return $this->_ids[0];
+ }
+ }
+
+ /**
+ * Set a collection of IDs to use in the value of this Header.
+ *
+ * @param string[] $ids
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setIds(array $ids)
+ {
+ $actualIds = array();
+
+ foreach ($ids as $id) {
+ $this->_assertValidId($id);
+ $actualIds[] = $id;
+ }
+
+ $this->clearCachedValueIf($this->_ids != $actualIds);
+ $this->_ids = $actualIds;
+ }
+
+ /**
+ * Get the list of IDs used in this Header.
+ *
+ * @return string[]
+ */
+ public function getIds()
+ {
+ return $this->_ids;
+ }
+
+ /**
+ * Get the string value of the body in this Header.
+ *
+ * This is not necessarily RFC 2822 compliant since folding white space will
+ * not be added at this stage (see {@see toString()} for that).
+ *
+ * @see toString()
+ *
+ * @return string
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function getFieldBody()
+ {
+ if (!$this->getCachedValue()) {
+ $angleAddrs = array();
+
+ foreach ($this->_ids as $id) {
+ $angleAddrs[] = '<' . $id . '>';
+ }
+
+ $this->setCachedValue(implode(' ', $angleAddrs));
+ }
+
+ return $this->getCachedValue();
+ }
+
+ /**
+ * Throws an Exception if the id passed does not comply with RFC 2822.
+ *
+ * @param string $id
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ private function _assertValidId($id)
+ {
+ if (!preg_match(
+ '/^' . $this->getGrammar()->getDefinition('id-left') . '@' .
+ $this->getGrammar()->getDefinition('id-right') . '$/D',
+ $id
+ ))
+ {
+ throw new Swift_RfcComplianceException(
+ 'Invalid ID given <' . $id . '>'
+ );
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/Headers/MailboxHeader.php b/vendor/swiftmailer/classes/Swift/Mime/Headers/MailboxHeader.php
new file mode 100644
index 00000000..f8378d04
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/Headers/MailboxHeader.php
@@ -0,0 +1,354 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A Mailbox Address MIME Header for something like From or Sender.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_Headers_MailboxHeader extends Swift_Mime_Headers_AbstractHeader
+{
+ /**
+ * The mailboxes used in this Header.
+ *
+ * @var string[]
+ */
+ private $_mailboxes = array();
+
+ /**
+ * Creates a new MailboxHeader with $name.
+ *
+ * @param string $name of Header
+ * @param Swift_Mime_HeaderEncoder $encoder
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function __construct($name, Swift_Mime_HeaderEncoder $encoder, Swift_Mime_Grammar $grammar)
+ {
+ $this->setFieldName($name);
+ $this->setEncoder($encoder);
+ parent::__construct($grammar);
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_MAILBOX;
+ }
+
+ /**
+ * Set the model for the field body.
+ *
+ * This method takes a string, or an array of addresses.
+ *
+ * @param mixed $model
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setFieldBodyModel($model)
+ {
+ $this->setNameAddresses($model);
+ }
+
+ /**
+ * Get the model for the field body.
+ *
+ * This method returns an associative array like {@link getNameAddresses()}
+ *
+ * @return array
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function getFieldBodyModel()
+ {
+ return $this->getNameAddresses();
+ }
+
+ /**
+ * Set a list of mailboxes to be shown in this Header.
+ *
+ * The mailboxes can be a simple array of addresses, or an array of
+ * key=>value pairs where (email => personalName).
+ * Example:
+ * <code>
+ * <?php
+ * //Sets two mailboxes in the Header, one with a personal name
+ * $header->setNameAddresses(array(
+ * 'chris@swiftmailer.org' => 'Chris Corbyn',
+ * 'mark@swiftmailer.org' //No associated personal name
+ * ));
+ * ?>
+ * </code>
+ *
+ * @see __construct()
+ * @see setAddresses()
+ * @see setValue()
+ *
+ * @param string|string[] $mailboxes
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setNameAddresses($mailboxes)
+ {
+ $this->_mailboxes = $this->normalizeMailboxes((array) $mailboxes);
+ $this->setCachedValue(null); //Clear any cached value
+ }
+
+ /**
+ * Get the full mailbox list of this Header as an array of valid RFC 2822 strings.
+ *
+ * Example:
+ * <code>
+ * <?php
+ * $header = new Swift_Mime_Headers_MailboxHeader('From',
+ * array('chris@swiftmailer.org' => 'Chris Corbyn',
+ * 'mark@swiftmailer.org' => 'Mark Corbyn')
+ * );
+ * print_r($header->getNameAddressStrings());
+ * // array (
+ * // 0 => Chris Corbyn <chris@swiftmailer.org>,
+ * // 1 => Mark Corbyn <mark@swiftmailer.org>
+ * // )
+ * ?>
+ * </code>
+ *
+ * @see getNameAddresses()
+ * @see toString()
+ *
+ * @return string[]
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function getNameAddressStrings()
+ {
+ return $this->_createNameAddressStrings($this->getNameAddresses());
+ }
+
+ /**
+ * Get all mailboxes in this Header as key=>value pairs.
+ *
+ * The key is the address and the value is the name (or null if none set).
+ * Example:
+ * <code>
+ * <?php
+ * $header = new Swift_Mime_Headers_MailboxHeader('From',
+ * array('chris@swiftmailer.org' => 'Chris Corbyn',
+ * 'mark@swiftmailer.org' => 'Mark Corbyn')
+ * );
+ * print_r($header->getNameAddresses());
+ * // array (
+ * // chris@swiftmailer.org => Chris Corbyn,
+ * // mark@swiftmailer.org => Mark Corbyn
+ * // )
+ * ?>
+ * </code>
+ *
+ * @see getAddresses()
+ * @see getNameAddressStrings()
+ *
+ * @return string[]
+ */
+ public function getNameAddresses()
+ {
+ return $this->_mailboxes;
+ }
+
+ /**
+ * Makes this Header represent a list of plain email addresses with no names.
+ *
+ * Example:
+ * <code>
+ * <?php
+ * //Sets three email addresses as the Header data
+ * $header->setAddresses(
+ * array('one@domain.tld', 'two@domain.tld', 'three@domain.tld')
+ * );
+ * ?>
+ * </code>
+ *
+ * @see setNameAddresses()
+ * @see setValue()
+ *
+ * @param string[] $addresses
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setAddresses($addresses)
+ {
+ $this->setNameAddresses(array_values((array) $addresses));
+ }
+
+ /**
+ * Get all email addresses in this Header.
+ *
+ * @see getNameAddresses()
+ *
+ * @return string[]
+ */
+ public function getAddresses()
+ {
+ return array_keys($this->_mailboxes);
+ }
+
+ /**
+ * Remove one or more addresses from this Header.
+ *
+ * @param string|string[] $addresses
+ */
+ public function removeAddresses($addresses)
+ {
+ $this->setCachedValue(null);
+ foreach ((array) $addresses as $address) {
+ unset($this->_mailboxes[$address]);
+ }
+ }
+
+ /**
+ * Get the string value of the body in this Header.
+ *
+ * This is not necessarily RFC 2822 compliant since folding white space will
+ * not be added at this stage (see {@link toString()} for that).
+ *
+ * @see toString()
+ *
+ * @return string
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function getFieldBody()
+ {
+ // Compute the string value of the header only if needed
+ if (is_null($this->getCachedValue())) {
+ $this->setCachedValue($this->createMailboxListString($this->_mailboxes));
+ }
+
+ return $this->getCachedValue();
+ }
+
+ // -- Points of extension
+
+ /**
+ * Normalizes a user-input list of mailboxes into consistent key=>value pairs.
+ *
+ * @param string[] $mailboxes
+ *
+ * @return string[]
+ */
+ protected function normalizeMailboxes(array $mailboxes)
+ {
+ $actualMailboxes = array();
+
+ foreach ($mailboxes as $key => $value) {
+ if (is_string($key)) { //key is email addr
+ $address = $key;
+ $name = $value;
+ } else {
+ $address = $value;
+ $name = null;
+ }
+ $this->_assertValidAddress($address);
+ $actualMailboxes[$address] = $name;
+ }
+
+ return $actualMailboxes;
+ }
+
+ /**
+ * Produces a compliant, formatted display-name based on the string given.
+ *
+ * @param string $displayName as displayed
+ * @param bool $shorten the first line to make remove for header name
+ *
+ * @return string
+ */
+ protected function createDisplayNameString($displayName, $shorten = false)
+ {
+ return $this->createPhrase($this, $displayName,
+ $this->getCharset(), $this->getEncoder(), $shorten
+ );
+ }
+
+ /**
+ * Creates a string form of all the mailboxes in the passed array.
+ *
+ * @param string[] $mailboxes
+ *
+ * @return string
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ protected function createMailboxListString(array $mailboxes)
+ {
+ return implode(', ', $this->_createNameAddressStrings($mailboxes));
+ }
+
+ /**
+ * Redefine the encoding requirements for mailboxes.
+ *
+ * Commas and semicolons are used to separate
+ * multiple addresses, and should therefore be encoded
+ *
+ * @param string $token
+ *
+ * @return bool
+ */
+ protected function tokenNeedsEncoding($token)
+ {
+ return preg_match('/[,;]/', $token) || parent::tokenNeedsEncoding($token);
+ }
+
+ /**
+ * Return an array of strings conforming the the name-addr spec of RFC 2822.
+ *
+ * @param string[] $mailboxes
+ *
+ * @return string[]
+ */
+ private function _createNameAddressStrings(array $mailboxes)
+ {
+ $strings = array();
+
+ foreach ($mailboxes as $email => $name) {
+ $mailboxStr = $email;
+ if (!is_null($name)) {
+ $nameStr = $this->createDisplayNameString($name, empty($strings));
+ $mailboxStr = $nameStr . ' <' . $mailboxStr . '>';
+ }
+ $strings[] = $mailboxStr;
+ }
+
+ return $strings;
+ }
+
+ /**
+ * Throws an Exception if the address passed does not comply with RFC 2822.
+ *
+ * @param string $address
+ *
+ * @throws Swift_RfcComplianceException If invalid.
+ */
+ private function _assertValidAddress($address)
+ {
+ if (!preg_match('/^' . $this->getGrammar()->getDefinition('addr-spec') . '$/D',
+ $address))
+ {
+ throw new Swift_RfcComplianceException(
+ 'Address in mailbox given [' . $address .
+ '] does not comply with RFC 2822, 3.6.2.'
+ );
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/Headers/OpenDKIMHeader.php b/vendor/swiftmailer/classes/Swift/Mime/Headers/OpenDKIMHeader.php
new file mode 100644
index 00000000..0b72e15d
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/Headers/OpenDKIMHeader.php
@@ -0,0 +1,137 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An OpenDKIM Specific Header using only raw header datas without encoding
+ *
+ * @author De Cock Xavier <xdecock@gmail.com>
+ */
+class Swift_Mime_Headers_OpenDKIMHeader implements Swift_Mime_Header
+{
+ /**
+ * The value of this Header.
+ *
+ * @var string
+ */
+ private $_value;
+
+ /**
+ * The name of this Header
+ * @var string
+ */
+ private $_fieldName;
+
+ /**
+ * Creates a new SimpleHeader with $name.
+ *
+ * @param string $name
+ * @param Swift_Mime_HeaderEncoder $encoder
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function __construct($name)
+ {
+ $this->_fieldName = $name;
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_TEXT;
+ }
+
+ /**
+ * Set the model for the field body.
+ *
+ * This method takes a string for the field value.
+ *
+ * @param string $model
+ */
+ public function setFieldBodyModel($model)
+ {
+ $this->setValue($model);
+ }
+
+ /**
+ * Get the model for the field body.
+ *
+ * This method returns a string.
+ *
+ * @return string
+ */
+ public function getFieldBodyModel()
+ {
+ return $this->getValue();
+ }
+
+ /**
+ * Get the (unencoded) value of this header.
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->_value;
+ }
+
+ /**
+ * Set the (unencoded) value of this header.
+ *
+ * @param string $value
+ */
+ public function setValue($value)
+ {
+ $this->_value = $value;
+ }
+
+ /**
+ * Get the value of this header prepared for rendering.
+ *
+ * @return string
+ */
+ public function getFieldBody()
+ {
+ return $this->_value;
+ }
+
+ /**
+ * Get this Header rendered as a RFC 2822 compliant string.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return $this->_fieldName.': '.$this->_value;
+ }
+
+ /**
+ * Set the Header FieldName
+ * @see Swift_Mime_Header::getFieldName()
+ */
+ public function getFieldName()
+ {
+ return $this->_fieldName;
+ }
+
+ /**
+ * Ignored
+ */
+ public function setCharset($charset)
+ {
+
+ }
+
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/Headers/ParameterizedHeader.php b/vendor/swiftmailer/classes/Swift/Mime/Headers/ParameterizedHeader.php
new file mode 100644
index 00000000..6bfdc9bc
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/Headers/ParameterizedHeader.php
@@ -0,0 +1,260 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An abstract base MIME Header.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_Headers_ParameterizedHeader extends Swift_Mime_Headers_UnstructuredHeader implements Swift_Mime_ParameterizedHeader
+{
+ /**
+ * RFC 2231's definition of a token.
+ *
+ * @var string
+ */
+ const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)';
+
+ /**
+ * The Encoder used to encode the parameters.
+ *
+ * @var Swift_Encoder
+ */
+ private $_paramEncoder;
+
+ /**
+ * The parameters as an associative array.
+ *
+ * @var string[]
+ */
+ private $_params = array();
+
+ /**
+ * Creates a new ParameterizedHeader with $name.
+ *
+ * @param string $name
+ * @param Swift_Mime_HeaderEncoder $encoder
+ * @param Swift_Encoder $paramEncoder, optional
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function __construct($name, Swift_Mime_HeaderEncoder $encoder, Swift_Encoder $paramEncoder = null, Swift_Mime_Grammar $grammar)
+ {
+ parent::__construct($name, $encoder, $grammar);
+ $this->_paramEncoder = $paramEncoder;
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_PARAMETERIZED;
+ }
+
+ /**
+ * Set the character set used in this Header.
+ *
+ * @param string $charset
+ */
+ public function setCharset($charset)
+ {
+ parent::setCharset($charset);
+ if (isset($this->_paramEncoder)) {
+ $this->_paramEncoder->charsetChanged($charset);
+ }
+ }
+
+ /**
+ * Set the value of $parameter.
+ *
+ * @param string $parameter
+ * @param string $value
+ */
+ public function setParameter($parameter, $value)
+ {
+ $this->setParameters(array_merge($this->getParameters(), array($parameter => $value)));
+ }
+
+ /**
+ * Get the value of $parameter.
+ *
+ * @param string $parameter
+ *
+ * @return string
+ */
+ public function getParameter($parameter)
+ {
+ $params = $this->getParameters();
+
+ return array_key_exists($parameter, $params)
+ ? $params[$parameter]
+ : null;
+ }
+
+ /**
+ * Set an associative array of parameter names mapped to values.
+ *
+ * @param string[] $parameters
+ */
+ public function setParameters(array $parameters)
+ {
+ $this->clearCachedValueIf($this->_params != $parameters);
+ $this->_params = $parameters;
+ }
+
+ /**
+ * Returns an associative array of parameter names mapped to values.
+ *
+ * @return string[]
+ */
+ public function getParameters()
+ {
+ return $this->_params;
+ }
+
+ /**
+ * Get the value of this header prepared for rendering.
+ *
+ * @return string
+ */
+ public function getFieldBody() //TODO: Check caching here
+ {
+ $body = parent::getFieldBody();
+ foreach ($this->_params as $name => $value) {
+ if (!is_null($value)) {
+ // Add the parameter
+ $body .= '; ' . $this->_createParameter($name, $value);
+ }
+ }
+
+ return $body;
+ }
+
+
+ /**
+ * Generate a list of all tokens in the final header.
+ *
+ * This doesn't need to be overridden in theory, but it is for implementation
+ * reasons to prevent potential breakage of attributes.
+ *
+ * @param string $string The string to tokenize
+ *
+ * @return array An array of tokens as strings
+ */
+ protected function toTokens($string = null)
+ {
+ $tokens = parent::toTokens(parent::getFieldBody());
+
+ // Try creating any parameters
+ foreach ($this->_params as $name => $value) {
+ if (!is_null($value)) {
+ // Add the semi-colon separator
+ $tokens[count($tokens)-1] .= ';';
+ $tokens = array_merge($tokens, $this->generateTokenLines(
+ ' ' . $this->_createParameter($name, $value)
+ ));
+ }
+ }
+
+ return $tokens;
+ }
+
+ /**
+ * Render a RFC 2047 compliant header parameter from the $name and $value.
+ *
+ * @param string $name
+ * @param string $value
+ *
+ * @return string
+ */
+ private function _createParameter($name, $value)
+ {
+ $origValue = $value;
+
+ $encoded = false;
+ // Allow room for parameter name, indices, "=" and DQUOTEs
+ $maxValueLength = $this->getMaxLineLength() - strlen($name . '=*N"";') - 1;
+ $firstLineOffset = 0;
+
+ // If it's not already a valid parameter value...
+ if (!preg_match('/^' . self::TOKEN_REGEX . '$/D', $value)) {
+ // TODO: text, or something else??
+ // ... and it's not ascii
+ if (!preg_match('/^' . $this->getGrammar()->getDefinition('text') . '*$/D', $value)) {
+ $encoded = true;
+ // Allow space for the indices, charset and language
+ $maxValueLength = $this->getMaxLineLength() - strlen($name . '*N*="";') - 1;
+ $firstLineOffset = strlen(
+ $this->getCharset() . "'" . $this->getLanguage() . "'"
+ );
+ }
+ }
+
+ // Encode if we need to
+ if ($encoded || strlen($value) > $maxValueLength) {
+ if (isset($this->_paramEncoder)) {
+ $value = $this->_paramEncoder->encodeString(
+ $origValue, $firstLineOffset, $maxValueLength, $this->getCharset()
+ );
+ } else { // We have to go against RFC 2183/2231 in some areas for interoperability
+ $value = $this->getTokenAsEncodedWord($origValue);
+ $encoded = false;
+ }
+ }
+
+ $valueLines = isset($this->_paramEncoder) ? explode("\r\n", $value) : array($value);
+
+ // Need to add indices
+ if (count($valueLines) > 1) {
+ $paramLines = array();
+ foreach ($valueLines as $i => $line) {
+ $paramLines[] = $name . '*' . $i .
+ $this->_getEndOfParameterValue($line, true, $i == 0);
+ }
+
+ return implode(";\r\n ", $paramLines);
+ } else {
+ return $name . $this->_getEndOfParameterValue(
+ $valueLines[0], $encoded, true
+ );
+ }
+ }
+
+ /**
+ * Returns the parameter value from the "=" and beyond.
+ *
+ * @param string $value to append
+ * @param bool $encoded
+ * @param bool $firstLine
+ *
+ * @return string
+ */
+ private function _getEndOfParameterValue($value, $encoded = false, $firstLine = false)
+ {
+ if (!preg_match('/^' . self::TOKEN_REGEX . '$/D', $value)) {
+ $value = '"' . $value . '"';
+ }
+ $prepend = '=';
+ if ($encoded) {
+ $prepend = '*=';
+ if ($firstLine) {
+ $prepend = '*=' . $this->getCharset() . "'" . $this->getLanguage() .
+ "'";
+ }
+ }
+
+ return $prepend . $value;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/Headers/PathHeader.php b/vendor/swiftmailer/classes/Swift/Mime/Headers/PathHeader.php
new file mode 100644
index 00000000..9db2f9f4
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/Headers/PathHeader.php
@@ -0,0 +1,144 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A Path Header in Swift Mailer, such a Return-Path.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_Headers_PathHeader extends Swift_Mime_Headers_AbstractHeader
+{
+ /**
+ * The address in this Header (if specified).
+ *
+ * @var string
+ */
+ private $_address;
+
+ /**
+ * Creates a new PathHeader with the given $name.
+ *
+ * @param string $name
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function __construct($name, Swift_Mime_Grammar $grammar)
+ {
+ $this->setFieldName($name);
+ parent::__construct($grammar);
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_PATH;
+ }
+
+ /**
+ * Set the model for the field body.
+ * This method takes a string for an address.
+ *
+ * @param string $model
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setFieldBodyModel($model)
+ {
+ $this->setAddress($model);
+ }
+
+ /**
+ * Get the model for the field body.
+ * This method returns a string email address.
+ *
+ * @return mixed
+ */
+ public function getFieldBodyModel()
+ {
+ return $this->getAddress();
+ }
+
+ /**
+ * Set the Address which should appear in this Header.
+ *
+ * @param string $address
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setAddress($address)
+ {
+ if (is_null($address)) {
+ $this->_address = null;
+ } elseif ('' == $address) {
+ $this->_address = '';
+ } else {
+ $this->_assertValidAddress($address);
+ $this->_address = $address;
+ }
+ $this->setCachedValue(null);
+ }
+
+ /**
+ * Get the address which is used in this Header (if any).
+ *
+ * Null is returned if no address is set.
+ *
+ * @return string
+ */
+ public function getAddress()
+ {
+ return $this->_address;
+ }
+
+ /**
+ * Get the string value of the body in this Header.
+ *
+ * This is not necessarily RFC 2822 compliant since folding white space will
+ * not be added at this stage (see {@link toString()} for that).
+ *
+ * @see toString()
+ *
+ * @return string
+ */
+ public function getFieldBody()
+ {
+ if (!$this->getCachedValue()) {
+ if (isset($this->_address)) {
+ $this->setCachedValue('<' . $this->_address . '>');
+ }
+ }
+
+ return $this->getCachedValue();
+ }
+
+ /**
+ * Throws an Exception if the address passed does not comply with RFC 2822.
+ *
+ * @param string $address
+ *
+ * @throws Swift_RfcComplianceException If address is invalid
+ */
+ private function _assertValidAddress($address)
+ {
+ if (!preg_match('/^' . $this->getGrammar()->getDefinition('addr-spec') . '$/D',
+ $address))
+ {
+ throw new Swift_RfcComplianceException(
+ 'Address set in PathHeader does not comply with addr-spec of RFC 2822.'
+ );
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/Headers/UnstructuredHeader.php b/vendor/swiftmailer/classes/Swift/Mime/Headers/UnstructuredHeader.php
new file mode 100644
index 00000000..41d4e63d
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/Headers/UnstructuredHeader.php
@@ -0,0 +1,112 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A Simple MIME Header.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_Headers_UnstructuredHeader extends Swift_Mime_Headers_AbstractHeader
+{
+ /**
+ * The value of this Header.
+ *
+ * @var string
+ */
+ private $_value;
+
+ /**
+ * Creates a new SimpleHeader with $name.
+ *
+ * @param string $name
+ * @param Swift_Mime_HeaderEncoder $encoder
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function __construct($name, Swift_Mime_HeaderEncoder $encoder, Swift_Mime_Grammar $grammar)
+ {
+ $this->setFieldName($name);
+ $this->setEncoder($encoder);
+ parent::__construct($grammar);
+ }
+
+ /**
+ * Get the type of Header that this instance represents.
+ *
+ * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX
+ * @see TYPE_DATE, TYPE_ID, TYPE_PATH
+ *
+ * @return int
+ */
+ public function getFieldType()
+ {
+ return self::TYPE_TEXT;
+ }
+
+ /**
+ * Set the model for the field body.
+ *
+ * This method takes a string for the field value.
+ *
+ * @param string $model
+ */
+ public function setFieldBodyModel($model)
+ {
+ $this->setValue($model);
+ }
+
+ /**
+ * Get the model for the field body.
+ *
+ * This method returns a string.
+ *
+ * @return string
+ */
+ public function getFieldBodyModel()
+ {
+ return $this->getValue();
+ }
+
+ /**
+ * Get the (unencoded) value of this header.
+ *
+ * @return string
+ */
+ public function getValue()
+ {
+ return $this->_value;
+ }
+
+ /**
+ * Set the (unencoded) value of this header.
+ *
+ * @param string $value
+ */
+ public function setValue($value)
+ {
+ $this->clearCachedValueIf($this->_value != $value);
+ $this->_value = $value;
+ }
+
+ /**
+ * Get the value of this header prepared for rendering.
+ *
+ * @return string
+ */
+ public function getFieldBody()
+ {
+ if (!$this->getCachedValue()) {
+ $this->setCachedValue(
+ $this->encodeWords($this, $this->_value)
+ );
+ }
+
+ return $this->getCachedValue();
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/Message.php b/vendor/swiftmailer/classes/Swift/Mime/Message.php
new file mode 100644
index 00000000..29bc4b33
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/Message.php
@@ -0,0 +1,223 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A Message (RFC 2822) object.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Mime_Message extends Swift_Mime_MimeEntity
+{
+ /**
+ * Generates a valid Message-ID and switches to it.
+ *
+ * @return string
+ */
+ public function generateId();
+
+ /**
+ * Set the subject of the message.
+ *
+ * @param string $subject
+ */
+ public function setSubject($subject);
+
+ /**
+ * Get the subject of the message.
+ *
+ * @return string
+ */
+ public function getSubject();
+
+ /**
+ * Set the origination date of the message as a UNIX timestamp.
+ *
+ * @param int $date
+ */
+ public function setDate($date);
+
+ /**
+ * Get the origination date of the message as a UNIX timestamp.
+ *
+ * @return int
+ */
+ public function getDate();
+
+ /**
+ * Set the return-path (bounce-detect) address.
+ *
+ * @param string $address
+ */
+ public function setReturnPath($address);
+
+ /**
+ * Get the return-path (bounce-detect) address.
+ *
+ * @return string
+ */
+ public function getReturnPath();
+
+ /**
+ * Set the sender of this message.
+ *
+ * If multiple addresses are present in the From field, this SHOULD be set.
+ *
+ * According to RFC 2822 it is a requirement when there are multiple From
+ * addresses, but Swift itself does not require it directly.
+ *
+ * An associative array (with one element!) can be used to provide a display-
+ * name: i.e. array('email@address' => 'Real Name').
+ *
+ * If the second parameter is provided and the first is a string, then $name
+ * is associated with the address.
+ *
+ * @param mixed $address
+ * @param string $name optional
+ */
+ public function setSender($address, $name = null);
+
+ /**
+ * Get the sender address for this message.
+ *
+ * This has a higher significance than the From address.
+ *
+ * @return string
+ */
+ public function getSender();
+
+ /**
+ * Set the From address of this message.
+ *
+ * It is permissible for multiple From addresses to be set using an array.
+ *
+ * If multiple From addresses are used, you SHOULD set the Sender address and
+ * according to RFC 2822, MUST set the sender address.
+ *
+ * An array can be used if display names are to be provided: i.e.
+ * array('email@address.com' => 'Real Name').
+ *
+ * If the second parameter is provided and the first is a string, then $name
+ * is associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ */
+ public function setFrom($addresses, $name = null);
+
+ /**
+ * Get the From address(es) of this message.
+ *
+ * This method always returns an associative array where the keys are the
+ * addresses.
+ *
+ * @return string[]
+ */
+ public function getFrom();
+
+ /**
+ * Set the Reply-To address(es).
+ *
+ * Any replies from the receiver will be sent to this address.
+ *
+ * It is permissible for multiple reply-to addresses to be set using an array.
+ *
+ * This method has the same synopsis as {@link setFrom()} and {@link setTo()}.
+ *
+ * If the second parameter is provided and the first is a string, then $name
+ * is associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ */
+ public function setReplyTo($addresses, $name = null);
+
+ /**
+ * Get the Reply-To addresses for this message.
+ *
+ * This method always returns an associative array where the keys provide the
+ * email addresses.
+ *
+ * @return string[]
+ */
+ public function getReplyTo();
+
+ /**
+ * Set the To address(es).
+ *
+ * Recipients set in this field will receive a copy of this message.
+ *
+ * This method has the same synopsis as {@link setFrom()} and {@link setCc()}.
+ *
+ * If the second parameter is provided and the first is a string, then $name
+ * is associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ */
+ public function setTo($addresses, $name = null);
+
+ /**
+ * Get the To addresses for this message.
+ *
+ * This method always returns an associative array, whereby the keys provide
+ * the actual email addresses.
+ *
+ * @return string[]
+ */
+ public function getTo();
+
+ /**
+ * Set the Cc address(es).
+ *
+ * Recipients set in this field will receive a 'carbon-copy' of this message.
+ *
+ * This method has the same synopsis as {@link setFrom()} and {@link setTo()}.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ */
+ public function setCc($addresses, $name = null);
+
+ /**
+ * Get the Cc addresses for this message.
+ *
+ * This method always returns an associative array, whereby the keys provide
+ * the actual email addresses.
+ *
+ * @return string[]
+ */
+ public function getCc();
+
+ /**
+ * Set the Bcc address(es).
+ *
+ * Recipients set in this field will receive a 'blind-carbon-copy' of this
+ * message.
+ *
+ * In other words, they will get the message, but any other recipients of the
+ * message will have no such knowledge of their receipt of it.
+ *
+ * This method has the same synopsis as {@link setFrom()} and {@link setTo()}.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ */
+ public function setBcc($addresses, $name = null);
+
+ /**
+ * Get the Bcc addresses for this message.
+ *
+ * This method always returns an associative array, whereby the keys provide
+ * the actual email addresses.
+ *
+ * @return string[]
+ */
+ public function getBcc();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/MimeEntity.php b/vendor/swiftmailer/classes/Swift/Mime/MimeEntity.php
new file mode 100644
index 00000000..cd8b8a2b
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/MimeEntity.php
@@ -0,0 +1,115 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A MIME entity, such as an attachment.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Mime_MimeEntity extends Swift_Mime_CharsetObserver, Swift_Mime_EncodingObserver
+{
+ /** Main message document; there can only be one of these */
+ const LEVEL_TOP = 16;
+
+ /** An entity which nests with the same precedence as an attachment */
+ const LEVEL_MIXED = 256;
+
+ /** An entity which nests with the same precedence as a mime part */
+ const LEVEL_ALTERNATIVE = 4096;
+
+ /** An entity which nests with the same precedence as embedded content */
+ const LEVEL_RELATED = 65536;
+
+ /**
+ * Get the level at which this entity shall be nested in final document.
+ *
+ * The lower the value, the more outermost the entity will be nested.
+ * @see LEVEL_TOP, LEVEL_MIXED, LEVEL_RELATED, LEVEL_ALTERNATIVE
+ *
+ * @return int
+ */
+ public function getNestingLevel();
+
+ /**
+ * Get the qualified content-type of this mime entity.
+ * @return string
+ */
+ public function getContentType();
+
+ /**
+ * Returns a unique ID for this entity.
+ *
+ * For most entities this will likely be the Content-ID, though it has
+ * no explicit semantic meaning and can be considered an identifier for
+ * programming logic purposes.
+ *
+ * If a Content-ID header is present, this value SHOULD match the value of
+ * the header.
+ *
+ * @return string
+ */
+ public function getId();
+
+ /**
+ * Get all children nested inside this entity.
+ *
+ * These are not just the immediate children, but all children.
+ *
+ * @return Swift_Mime_MimeEntity[]
+ */
+ public function getChildren();
+
+ /**
+ * Set all children nested inside this entity.
+ *
+ * This includes grandchildren.
+ *
+ * @param Swift_Mime_MimeEntity[] $children
+ */
+ public function setChildren(array $children);
+
+ /**
+ * Get the collection of Headers in this Mime entity.
+ *
+ * @return Swift_Mime_HeaderSet
+ */
+ public function getHeaders();
+
+ /**
+ * Get the body content of this entity as a string.
+ *
+ * Returns NULL if no body has been set.
+ *
+ * @return string|null
+ */
+ public function getBody();
+
+ /**
+ * Set the body content of this entity as a string.
+ *
+ * @param string $body
+ * @param string $contentType optional
+ */
+ public function setBody($body, $contentType = null);
+
+ /**
+ * Get this entire entity in its string form.
+ *
+ * @return string
+ */
+ public function toString();
+
+ /**
+ * Get this entire entity as a ByteStream.
+ *
+ * @param Swift_InputByteStream $is to write to
+ */
+ public function toByteStream(Swift_InputByteStream $is);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/MimePart.php b/vendor/swiftmailer/classes/Swift/Mime/MimePart.php
new file mode 100644
index 00000000..f67a864b
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/MimePart.php
@@ -0,0 +1,214 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A MIME part, in a multipart message.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_MimePart extends Swift_Mime_SimpleMimeEntity
+{
+ /** The format parameter last specified by the user */
+ protected $_userFormat;
+
+ /** The charset last specified by the user */
+ protected $_userCharset;
+
+ /** The delsp parameter last specified by the user */
+ protected $_userDelSp;
+
+ /** The nesting level of this MimePart */
+ private $_nestingLevel = self::LEVEL_ALTERNATIVE;
+
+ /**
+ * Create a new MimePart with $headers, $encoder and $cache.
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ * @param Swift_Mime_ContentEncoder $encoder
+ * @param Swift_KeyCache $cache
+ * @param Swift_Mime_Grammar $grammar
+ * @param string $charset
+ */
+ public function __construct(Swift_Mime_HeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_Mime_Grammar $grammar, $charset = null)
+ {
+ parent::__construct($headers, $encoder, $cache, $grammar);
+ $this->setContentType('text/plain');
+ if (!is_null($charset)) {
+ $this->setCharset($charset);
+ }
+ }
+
+ /**
+ * Set the body of this entity, either as a string, or as an instance of
+ * {@link Swift_OutputByteStream}.
+ *
+ * @param mixed $body
+ * @param string $contentType optional
+ * @param string $charset optional
+ *
+ * @return Swift_Mime_MimePart
+ */
+ public function setBody($body, $contentType = null, $charset = null)
+ {
+ if (isset($charset)) {
+ $this->setCharset($charset);
+ }
+ $body = $this->_convertString($body);
+
+ parent::setBody($body, $contentType);
+
+ return $this;
+ }
+
+ /**
+ * Get the character set of this entity.
+ *
+ * @return string
+ */
+ public function getCharset()
+ {
+ return $this->_getHeaderParameter('Content-Type', 'charset');
+ }
+
+ /**
+ * Set the character set of this entity.
+ *
+ * @param string $charset
+ *
+ * @return Swift_Mime_MimePart
+ */
+ public function setCharset($charset)
+ {
+ $this->_setHeaderParameter('Content-Type', 'charset', $charset);
+ if ($charset !== $this->_userCharset) {
+ $this->_clearCache();
+ }
+ $this->_userCharset = $charset;
+ parent::charsetChanged($charset);
+
+ return $this;
+ }
+
+ /**
+ * Get the format of this entity (i.e. flowed or fixed).
+ *
+ * @return string
+ */
+ public function getFormat()
+ {
+ return $this->_getHeaderParameter('Content-Type', 'format');
+ }
+
+ /**
+ * Set the format of this entity (flowed or fixed).
+ *
+ * @param string $format
+ *
+ * @return Swift_Mime_MimePart
+ */
+ public function setFormat($format)
+ {
+ $this->_setHeaderParameter('Content-Type', 'format', $format);
+ $this->_userFormat = $format;
+
+ return $this;
+ }
+
+ /**
+ * Test if delsp is being used for this entity.
+ *
+ * @return bool
+ */
+ public function getDelSp()
+ {
+ return ($this->_getHeaderParameter('Content-Type', 'delsp') == 'yes')
+ ? true
+ : false;
+ }
+
+ /**
+ * Turn delsp on or off for this entity.
+ *
+ * @param bool $delsp
+ *
+ * @return Swift_Mime_MimePart
+ */
+ public function setDelSp($delsp = true)
+ {
+ $this->_setHeaderParameter('Content-Type', 'delsp', $delsp ? 'yes' : null);
+ $this->_userDelSp = $delsp;
+
+ return $this;
+ }
+
+ /**
+ * Get the nesting level of this entity.
+ *
+ * @see LEVEL_TOP, LEVEL_ALTERNATIVE, LEVEL_MIXED, LEVEL_RELATED
+ *
+ * @return int
+ */
+ public function getNestingLevel()
+ {
+ return $this->_nestingLevel;
+ }
+
+ /**
+ * Receive notification that the charset has changed on this document, or a
+ * parent document.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->setCharset($charset);
+ }
+
+ /** Fix the content-type and encoding of this entity */
+ protected function _fixHeaders()
+ {
+ parent::_fixHeaders();
+ if (count($this->getChildren())) {
+ $this->_setHeaderParameter('Content-Type', 'charset', null);
+ $this->_setHeaderParameter('Content-Type', 'format', null);
+ $this->_setHeaderParameter('Content-Type', 'delsp', null);
+ } else {
+ $this->setCharset($this->_userCharset);
+ $this->setFormat($this->_userFormat);
+ $this->setDelSp($this->_userDelSp);
+ }
+ }
+
+ /** Set the nesting level of this entity */
+ protected function _setNestingLevel($level)
+ {
+ $this->_nestingLevel = $level;
+ }
+
+ /** Encode charset when charset is not utf-8 */
+ protected function _convertString($string)
+ {
+ $charset = strtolower($this->getCharset());
+ if (!in_array($charset, array('utf-8', 'iso-8859-1', ''))) {
+ // mb_convert_encoding must be the first one to check, since iconv cannot convert some words.
+ if (function_exists('mb_convert_encoding')) {
+ $string = mb_convert_encoding($string, 'utf-8', $charset);
+ } elseif (function_exists('iconv')) {
+ $string = iconv($charset, 'utf-8//TRANSLIT//IGNORE', $string);
+ } else {
+ throw new Swift_SwiftException('No suitable convert encoding function (use UTF-8 as your charset or install the mbstring or iconv extension).');
+ }
+
+ return $string;
+ }
+
+ return $string;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/ParameterizedHeader.php b/vendor/swiftmailer/classes/Swift/Mime/ParameterizedHeader.php
new file mode 100644
index 00000000..ea793201
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/ParameterizedHeader.php
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A MIME Header with parameters.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Mime_ParameterizedHeader extends Swift_Mime_Header
+{
+ /**
+ * Set the value of $parameter.
+ *
+ * @param string $parameter
+ * @param string $value
+ */
+ public function setParameter($parameter, $value);
+
+ /**
+ * Get the value of $parameter.
+ *
+ * @param string $parameter
+ *
+ * @return string
+ */
+ public function getParameter($parameter);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/SimpleHeaderFactory.php b/vendor/swiftmailer/classes/Swift/Mime/SimpleHeaderFactory.php
new file mode 100644
index 00000000..fe397fd0
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/SimpleHeaderFactory.php
@@ -0,0 +1,188 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Creates MIME headers.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_SimpleHeaderFactory implements Swift_Mime_HeaderFactory
+{
+ /** The HeaderEncoder used by these headers */
+ private $_encoder;
+
+ /** The Encoder used by parameters */
+ private $_paramEncoder;
+
+ /** The Grammar */
+ private $_grammar;
+
+ /** The charset of created Headers */
+ private $_charset;
+
+ /**
+ * Creates a new SimpleHeaderFactory using $encoder and $paramEncoder.
+ *
+ * @param Swift_Mime_HeaderEncoder $encoder
+ * @param Swift_Encoder $paramEncoder
+ * @param Swift_Mime_Grammar $grammar
+ * @param string|null $charset
+ */
+ public function __construct(Swift_Mime_HeaderEncoder $encoder, Swift_Encoder $paramEncoder, Swift_Mime_Grammar $grammar, $charset = null)
+ {
+ $this->_encoder = $encoder;
+ $this->_paramEncoder = $paramEncoder;
+ $this->_grammar = $grammar;
+ $this->_charset = $charset;
+ }
+
+ /**
+ * Create a new Mailbox Header with a list of $addresses.
+ *
+ * @param string $name
+ * @param array|string|null $addresses
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createMailboxHeader($name, $addresses = null)
+ {
+ $header = new Swift_Mime_Headers_MailboxHeader($name, $this->_encoder, $this->_grammar);
+ if (isset($addresses)) {
+ $header->setFieldBodyModel($addresses);
+ }
+ $this->_setHeaderCharset($header);
+
+ return $header;
+ }
+
+ /**
+ * Create a new Date header using $timestamp (UNIX time).
+ * @param string $name
+ * @param int|null $timestamp
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createDateHeader($name, $timestamp = null)
+ {
+ $header = new Swift_Mime_Headers_DateHeader($name, $this->_grammar);
+ if (isset($timestamp)) {
+ $header->setFieldBodyModel($timestamp);
+ }
+ $this->_setHeaderCharset($header);
+
+ return $header;
+ }
+
+ /**
+ * Create a new basic text header with $name and $value.
+ *
+ * @param string $name
+ * @param string $value
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createTextHeader($name, $value = null)
+ {
+ $header = new Swift_Mime_Headers_UnstructuredHeader($name, $this->_encoder, $this->_grammar);
+ if (isset($value)) {
+ $header->setFieldBodyModel($value);
+ }
+ $this->_setHeaderCharset($header);
+
+ return $header;
+ }
+
+ /**
+ * Create a new ParameterizedHeader with $name, $value and $params.
+ *
+ * @param string $name
+ * @param string $value
+ * @param array $params
+ *
+ * @return Swift_Mime_ParameterizedHeader
+ */
+ public function createParameterizedHeader($name, $value = null,
+ $params = array())
+ {
+ $header = new Swift_Mime_Headers_ParameterizedHeader($name,
+ $this->_encoder, (strtolower($name) == 'content-disposition')
+ ? $this->_paramEncoder
+ : null,
+ $this->_grammar
+ );
+ if (isset($value)) {
+ $header->setFieldBodyModel($value);
+ }
+ foreach ($params as $k => $v) {
+ $header->setParameter($k, $v);
+ }
+ $this->_setHeaderCharset($header);
+
+ return $header;
+ }
+
+ /**
+ * Create a new ID header for Message-ID or Content-ID.
+ *
+ * @param string $name
+ * @param string|array $ids
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createIdHeader($name, $ids = null)
+ {
+ $header = new Swift_Mime_Headers_IdentificationHeader($name, $this->_grammar);
+ if (isset($ids)) {
+ $header->setFieldBodyModel($ids);
+ }
+ $this->_setHeaderCharset($header);
+
+ return $header;
+ }
+
+ /**
+ * Create a new Path header with an address (path) in it.
+ *
+ * @param string $name
+ * @param string $path
+ *
+ * @return Swift_Mime_Header
+ */
+ public function createPathHeader($name, $path = null)
+ {
+ $header = new Swift_Mime_Headers_PathHeader($name, $this->_grammar);
+ if (isset($path)) {
+ $header->setFieldBodyModel($path);
+ }
+ $this->_setHeaderCharset($header);
+
+ return $header;
+ }
+
+ /**
+ * Notify this observer that the entity's charset has changed.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->_charset = $charset;
+ $this->_encoder->charsetChanged($charset);
+ $this->_paramEncoder->charsetChanged($charset);
+ }
+
+ /** Apply the charset to the Header */
+ private function _setHeaderCharset(Swift_Mime_Header $header)
+ {
+ if (isset($this->_charset)) {
+ $header->setCharset($this->_charset);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/SimpleHeaderSet.php b/vendor/swiftmailer/classes/Swift/Mime/SimpleHeaderSet.php
new file mode 100644
index 00000000..3bc60e14
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/SimpleHeaderSet.php
@@ -0,0 +1,383 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A collection of MIME headers.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_SimpleHeaderSet implements Swift_Mime_HeaderSet
+{
+ /** HeaderFactory */
+ private $_factory;
+
+ /** Collection of set Headers */
+ private $_headers = array();
+
+ /** Field ordering details */
+ private $_order = array();
+
+ /** List of fields which are required to be displayed */
+ private $_required = array();
+
+ /** The charset used by Headers */
+ private $_charset;
+
+ /**
+ * Create a new SimpleHeaderSet with the given $factory.
+ *
+ * @param Swift_Mime_HeaderFactory $factory
+ * @param string $charset
+ */
+ public function __construct(Swift_Mime_HeaderFactory $factory, $charset = null)
+ {
+ $this->_factory = $factory;
+ if (isset($charset)) {
+ $this->setCharset($charset);
+ }
+ }
+
+ /**
+ * Set the charset used by these headers.
+ *
+ * @param string $charset
+ */
+ public function setCharset($charset)
+ {
+ $this->_charset = $charset;
+ $this->_factory->charsetChanged($charset);
+ $this->_notifyHeadersOfCharset($charset);
+ }
+
+ /**
+ * Add a new Mailbox Header with a list of $addresses.
+ *
+ * @param string $name
+ * @param array|string $addresses
+ */
+ public function addMailboxHeader($name, $addresses = null)
+ {
+ $this->_storeHeader($name,
+ $this->_factory->createMailboxHeader($name, $addresses));
+ }
+
+ /**
+ * Add a new Date header using $timestamp (UNIX time).
+ *
+ * @param string $name
+ * @param int $timestamp
+ */
+ public function addDateHeader($name, $timestamp = null)
+ {
+ $this->_storeHeader($name,
+ $this->_factory->createDateHeader($name, $timestamp));
+ }
+
+ /**
+ * Add a new basic text header with $name and $value.
+ *
+ * @param string $name
+ * @param string $value
+ */
+ public function addTextHeader($name, $value = null)
+ {
+ $this->_storeHeader($name,
+ $this->_factory->createTextHeader($name, $value));
+ }
+
+ /**
+ * Add a new ParameterizedHeader with $name, $value and $params.
+ *
+ * @param string $name
+ * @param string $value
+ * @param array $params
+ */
+ public function addParameterizedHeader($name, $value = null, $params = array())
+ {
+ $this->_storeHeader($name, $this->_factory->createParameterizedHeader($name, $value, $params));
+ }
+
+ /**
+ * Add a new ID header for Message-ID or Content-ID.
+ *
+ * @param string $name
+ * @param string|array $ids
+ */
+ public function addIdHeader($name, $ids = null)
+ {
+ $this->_storeHeader($name, $this->_factory->createIdHeader($name, $ids));
+ }
+
+ /**
+ * Add a new Path header with an address (path) in it.
+ *
+ * @param string $name
+ * @param string $path
+ */
+ public function addPathHeader($name, $path = null)
+ {
+ $this->_storeHeader($name, $this->_factory->createPathHeader($name, $path));
+ }
+
+ /**
+ * Returns true if at least one header with the given $name exists.
+ *
+ * If multiple headers match, the actual one may be specified by $index.
+ *
+ * @param string $name
+ * @param int $index
+ *
+ * @return bool
+ */
+ public function has($name, $index = 0)
+ {
+ $lowerName = strtolower($name);
+
+ return array_key_exists($lowerName, $this->_headers) && array_key_exists($index, $this->_headers[$lowerName]);
+ }
+
+ /**
+ * Set a header in the HeaderSet.
+ *
+ * The header may be a previously fetched header via {@link get()} or it may
+ * be one that has been created separately.
+ *
+ * If $index is specified, the header will be inserted into the set at this
+ * offset.
+ *
+ * @param Swift_Mime_Header $header
+ * @param int $index
+ */
+ public function set(Swift_Mime_Header $header, $index = 0)
+ {
+ $this->_storeHeader($header->getFieldName(), $header, $index);
+ }
+
+ /**
+ * Get the header with the given $name.
+ *
+ * If multiple headers match, the actual one may be specified by $index.
+ * Returns NULL if none present.
+ *
+ * @param string $name
+ * @param int $index
+ *
+ * @return Swift_Mime_Header
+ */
+ public function get($name, $index = 0)
+ {
+ if ($this->has($name, $index)) {
+ $lowerName = strtolower($name);
+
+ return $this->_headers[$lowerName][$index];
+ }
+ }
+
+ /**
+ * Get all headers with the given $name.
+ *
+ * @param string $name
+ *
+ * @return array
+ */
+ public function getAll($name = null)
+ {
+ if (!isset($name)) {
+ $headers = array();
+ foreach ($this->_headers as $collection) {
+ $headers = array_merge($headers, $collection);
+ }
+
+ return $headers;
+ }
+
+ $lowerName = strtolower($name);
+ if (!array_key_exists($lowerName, $this->_headers)) {
+ return array();
+ }
+
+ return $this->_headers[$lowerName];
+ }
+
+ /**
+ * Return the name of all Headers
+ *
+ * @return array
+ */
+ public function listAll()
+ {
+ $headers = $this->_headers;
+ if ($this->_canSort()) {
+ uksort($headers, array($this, '_sortHeaders'));
+ }
+
+ return array_keys($headers);
+ }
+
+ /**
+ * Remove the header with the given $name if it's set.
+ *
+ * If multiple headers match, the actual one may be specified by $index.
+ *
+ * @param string $name
+ * @param int $index
+ */
+ public function remove($name, $index = 0)
+ {
+ $lowerName = strtolower($name);
+ unset($this->_headers[$lowerName][$index]);
+ }
+
+ /**
+ * Remove all headers with the given $name.
+ *
+ * @param string $name
+ */
+ public function removeAll($name)
+ {
+ $lowerName = strtolower($name);
+ unset($this->_headers[$lowerName]);
+ }
+
+ /**
+ * Create a new instance of this HeaderSet.
+ *
+ * @return Swift_Mime_HeaderSet
+ */
+ public function newInstance()
+ {
+ return new self($this->_factory);
+ }
+
+ /**
+ * Define a list of Header names as an array in the correct order.
+ *
+ * These Headers will be output in the given order where present.
+ *
+ * @param array $sequence
+ */
+ public function defineOrdering(array $sequence)
+ {
+ $this->_order = array_flip(array_map('strtolower', $sequence));
+ }
+
+ /**
+ * Set a list of header names which must always be displayed when set.
+ *
+ * Usually headers without a field value won't be output unless set here.
+ *
+ * @param array $names
+ */
+ public function setAlwaysDisplayed(array $names)
+ {
+ $this->_required = array_flip(array_map('strtolower', $names));
+ }
+
+ /**
+ * Notify this observer that the entity's charset has changed.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->setCharset($charset);
+ }
+
+ /**
+ * Returns a string with a representation of all headers.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ $string = '';
+ $headers = $this->_headers;
+ if ($this->_canSort()) {
+ uksort($headers, array($this, '_sortHeaders'));
+ }
+ foreach ($headers as $collection) {
+ foreach ($collection as $header) {
+ if ($this->_isDisplayed($header) || $header->getFieldBody() != '') {
+ $string .= $header->toString();
+ }
+ }
+ }
+
+ return $string;
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @return string
+ *
+ * @see toString()
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+
+ /** Save a Header to the internal collection */
+ private function _storeHeader($name, Swift_Mime_Header $header, $offset = null)
+ {
+ if (!isset($this->_headers[strtolower($name)])) {
+ $this->_headers[strtolower($name)] = array();
+ }
+ if (!isset($offset)) {
+ $this->_headers[strtolower($name)][] = $header;
+ } else {
+ $this->_headers[strtolower($name)][$offset] = $header;
+ }
+ }
+
+ /** Test if the headers can be sorted */
+ private function _canSort()
+ {
+ return count($this->_order) > 0;
+ }
+
+ /** uksort() algorithm for Header ordering */
+ private function _sortHeaders($a, $b)
+ {
+ $lowerA = strtolower($a);
+ $lowerB = strtolower($b);
+ $aPos = array_key_exists($lowerA, $this->_order)
+ ? $this->_order[$lowerA]
+ : -1;
+ $bPos = array_key_exists($lowerB, $this->_order)
+ ? $this->_order[$lowerB]
+ : -1;
+
+ if ($aPos == -1) {
+ return 1;
+ } elseif ($bPos == -1) {
+ return -1;
+ }
+
+ return ($aPos < $bPos) ? -1 : 1;
+ }
+
+ /** Test if the given Header is always displayed */
+ private function _isDisplayed(Swift_Mime_Header $header)
+ {
+ return array_key_exists(strtolower($header->getFieldName()), $this->_required);
+ }
+
+ /** Notify all Headers of the new charset */
+ private function _notifyHeadersOfCharset($charset)
+ {
+ foreach ($this->_headers as $headerGroup) {
+ foreach ($headerGroup as $header) {
+ $header->setCharset($charset);
+ }
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/SimpleMessage.php b/vendor/swiftmailer/classes/Swift/Mime/SimpleMessage.php
new file mode 100644
index 00000000..e0f7e63e
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/SimpleMessage.php
@@ -0,0 +1,651 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * The default email message class.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_SimpleMessage extends Swift_Mime_MimePart implements Swift_Mime_Message
+{
+ /**
+ * Create a new SimpleMessage with $headers, $encoder and $cache.
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ * @param Swift_Mime_ContentEncoder $encoder
+ * @param Swift_KeyCache $cache
+ * @param Swift_Mime_Grammar $grammar
+ * @param string $charset
+ */
+ public function __construct(Swift_Mime_HeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_Mime_Grammar $grammar, $charset = null)
+ {
+ parent::__construct($headers, $encoder, $cache, $grammar, $charset);
+ $this->getHeaders()->defineOrdering(array(
+ 'Return-Path',
+ 'Received',
+ 'DKIM-Signature',
+ 'DomainKey-Signature',
+ 'Sender',
+ 'Message-ID',
+ 'Date',
+ 'Subject',
+ 'From',
+ 'Reply-To',
+ 'To',
+ 'Cc',
+ 'Bcc',
+ 'MIME-Version',
+ 'Content-Type',
+ 'Content-Transfer-Encoding'
+ ));
+ $this->getHeaders()->setAlwaysDisplayed(array('Date', 'Message-ID', 'From'));
+ $this->getHeaders()->addTextHeader('MIME-Version', '1.0');
+ $this->setDate(time());
+ $this->setId($this->getId());
+ $this->getHeaders()->addMailboxHeader('From');
+ }
+
+ /**
+ * Always returns {@link LEVEL_TOP} for a message instance.
+ *
+ * @return int
+ */
+ public function getNestingLevel()
+ {
+ return self::LEVEL_TOP;
+ }
+
+ /**
+ * Set the subject of this message.
+ *
+ * @param string $subject
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function setSubject($subject)
+ {
+ if (!$this->_setHeaderFieldModel('Subject', $subject)) {
+ $this->getHeaders()->addTextHeader('Subject', $subject);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the subject of this message.
+ *
+ * @return string
+ */
+ public function getSubject()
+ {
+ return $this->_getHeaderFieldModel('Subject');
+ }
+
+ /**
+ * Set the date at which this message was created.
+ *
+ * @param int $date
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function setDate($date)
+ {
+ if (!$this->_setHeaderFieldModel('Date', $date)) {
+ $this->getHeaders()->addDateHeader('Date', $date);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the date at which this message was created.
+ *
+ * @return int
+ */
+ public function getDate()
+ {
+ return $this->_getHeaderFieldModel('Date');
+ }
+
+ /**
+ * Set the return-path (the bounce address) of this message.
+ *
+ * @param string $address
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function setReturnPath($address)
+ {
+ if (!$this->_setHeaderFieldModel('Return-Path', $address)) {
+ $this->getHeaders()->addPathHeader('Return-Path', $address);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the return-path (bounce address) of this message.
+ *
+ * @return string
+ */
+ public function getReturnPath()
+ {
+ return $this->_getHeaderFieldModel('Return-Path');
+ }
+
+ /**
+ * Set the sender of this message.
+ *
+ * This does not override the From field, but it has a higher significance.
+ *
+ * @param string $address
+ * @param string $name optional
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function setSender($address, $name = null)
+ {
+ if (!is_array($address) && isset($name)) {
+ $address = array($address => $name);
+ }
+
+ if (!$this->_setHeaderFieldModel('Sender', (array) $address)) {
+ $this->getHeaders()->addMailboxHeader('Sender', (array) $address);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the sender of this message.
+ *
+ * @return string
+ */
+ public function getSender()
+ {
+ return $this->_getHeaderFieldModel('Sender');
+ }
+
+ /**
+ * Add a From: address to this message.
+ *
+ * If $name is passed this name will be associated with the address.
+ *
+ * @param string $address
+ * @param string $name optional
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function addFrom($address, $name = null)
+ {
+ $current = $this->getFrom();
+ $current[$address] = $name;
+
+ return $this->setFrom($current);
+ }
+
+ /**
+ * Set the from address of this message.
+ *
+ * You may pass an array of addresses if this message is from multiple people.
+ *
+ * If $name is passed and the first parameter is a string, this name will be
+ * associated with the address.
+ *
+ * @param string $addresses
+ * @param string $name optional
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function setFrom($addresses, $name = null)
+ {
+ if (!is_array($addresses) && isset($name)) {
+ $addresses = array($addresses => $name);
+ }
+
+ if (!$this->_setHeaderFieldModel('From', (array) $addresses)) {
+ $this->getHeaders()->addMailboxHeader('From', (array) $addresses);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the from address of this message.
+ *
+ * @return mixed
+ */
+ public function getFrom()
+ {
+ return $this->_getHeaderFieldModel('From');
+ }
+
+ /**
+ * Add a Reply-To: address to this message.
+ *
+ * If $name is passed this name will be associated with the address.
+ *
+ * @param string $address
+ * @param string $name optional
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function addReplyTo($address, $name = null)
+ {
+ $current = $this->getReplyTo();
+ $current[$address] = $name;
+
+ return $this->setReplyTo($current);
+ }
+
+ /**
+ * Set the reply-to address of this message.
+ *
+ * You may pass an array of addresses if replies will go to multiple people.
+ *
+ * If $name is passed and the first parameter is a string, this name will be
+ * associated with the address.
+ *
+ * @param string $addresses
+ * @param string $name optional
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function setReplyTo($addresses, $name = null)
+ {
+ if (!is_array($addresses) && isset($name)) {
+ $addresses = array($addresses => $name);
+ }
+
+ if (!$this->_setHeaderFieldModel('Reply-To', (array) $addresses)) {
+ $this->getHeaders()->addMailboxHeader('Reply-To', (array) $addresses);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the reply-to address of this message.
+ *
+ * @return string
+ */
+ public function getReplyTo()
+ {
+ return $this->_getHeaderFieldModel('Reply-To');
+ }
+
+ /**
+ * Add a To: address to this message.
+ *
+ * If $name is passed this name will be associated with the address.
+ *
+ * @param string $address
+ * @param string $name optional
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function addTo($address, $name = null)
+ {
+ $current = $this->getTo();
+ $current[$address] = $name;
+
+ return $this->setTo($current);
+ }
+
+ /**
+ * Set the to addresses of this message.
+ *
+ * If multiple recipients will receive the message an array should be used.
+ * Example: array('receiver@domain.org', 'other@domain.org' => 'A name')
+ *
+ * If $name is passed and the first parameter is a string, this name will be
+ * associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function setTo($addresses, $name = null)
+ {
+ if (!is_array($addresses) && isset($name)) {
+ $addresses = array($addresses => $name);
+ }
+
+ if (!$this->_setHeaderFieldModel('To', (array) $addresses)) {
+ $this->getHeaders()->addMailboxHeader('To', (array) $addresses);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the To addresses of this message.
+ *
+ * @return array
+ */
+ public function getTo()
+ {
+ return $this->_getHeaderFieldModel('To');
+ }
+
+ /**
+ * Add a Cc: address to this message.
+ *
+ * If $name is passed this name will be associated with the address.
+ *
+ * @param string $address
+ * @param string $name optional
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function addCc($address, $name = null)
+ {
+ $current = $this->getCc();
+ $current[$address] = $name;
+
+ return $this->setCc($current);
+ }
+
+ /**
+ * Set the Cc addresses of this message.
+ *
+ * If $name is passed and the first parameter is a string, this name will be
+ * associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function setCc($addresses, $name = null)
+ {
+ if (!is_array($addresses) && isset($name)) {
+ $addresses = array($addresses => $name);
+ }
+
+ if (!$this->_setHeaderFieldModel('Cc', (array) $addresses)) {
+ $this->getHeaders()->addMailboxHeader('Cc', (array) $addresses);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the Cc address of this message.
+ *
+ * @return array
+ */
+ public function getCc()
+ {
+ return $this->_getHeaderFieldModel('Cc');
+ }
+
+ /**
+ * Add a Bcc: address to this message.
+ *
+ * If $name is passed this name will be associated with the address.
+ *
+ * @param string $address
+ * @param string $name optional
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function addBcc($address, $name = null)
+ {
+ $current = $this->getBcc();
+ $current[$address] = $name;
+
+ return $this->setBcc($current);
+ }
+
+ /**
+ * Set the Bcc addresses of this message.
+ *
+ * If $name is passed and the first parameter is a string, this name will be
+ * associated with the address.
+ *
+ * @param mixed $addresses
+ * @param string $name optional
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function setBcc($addresses, $name = null)
+ {
+ if (!is_array($addresses) && isset($name)) {
+ $addresses = array($addresses => $name);
+ }
+
+ if (!$this->_setHeaderFieldModel('Bcc', (array) $addresses)) {
+ $this->getHeaders()->addMailboxHeader('Bcc', (array) $addresses);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the Bcc addresses of this message.
+ *
+ * @return array
+ */
+ public function getBcc()
+ {
+ return $this->_getHeaderFieldModel('Bcc');
+ }
+
+ /**
+ * Set the priority of this message.
+ *
+ * The value is an integer where 1 is the highest priority and 5 is the lowest.
+ *
+ * @param int $priority
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function setPriority($priority)
+ {
+ $priorityMap = array(
+ 1 => 'Highest',
+ 2 => 'High',
+ 3 => 'Normal',
+ 4 => 'Low',
+ 5 => 'Lowest'
+ );
+ $pMapKeys = array_keys($priorityMap);
+ if ($priority > max($pMapKeys)) {
+ $priority = max($pMapKeys);
+ } elseif ($priority < min($pMapKeys)) {
+ $priority = min($pMapKeys);
+ }
+ if (!$this->_setHeaderFieldModel('X-Priority',
+ sprintf('%d (%s)', $priority, $priorityMap[$priority])))
+ {
+ $this->getHeaders()->addTextHeader('X-Priority',
+ sprintf('%d (%s)', $priority, $priorityMap[$priority]));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the priority of this message.
+ *
+ * The returned value is an integer where 1 is the highest priority and 5
+ * is the lowest.
+ *
+ * @return int
+ */
+ public function getPriority()
+ {
+ list($priority) = sscanf($this->_getHeaderFieldModel('X-Priority'),
+ '%[1-5]'
+ );
+
+ return isset($priority) ? $priority : 3;
+ }
+
+ /**
+ * Ask for a delivery receipt from the recipient to be sent to $addresses
+ *
+ * @param array $addresses
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function setReadReceiptTo($addresses)
+ {
+ if (!$this->_setHeaderFieldModel('Disposition-Notification-To', $addresses)) {
+ $this->getHeaders()
+ ->addMailboxHeader('Disposition-Notification-To', $addresses);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the addresses to which a read-receipt will be sent.
+ *
+ * @return string
+ */
+ public function getReadReceiptTo()
+ {
+ return $this->_getHeaderFieldModel('Disposition-Notification-To');
+ }
+
+ /**
+ * Attach a {@link Swift_Mime_MimeEntity} such as an Attachment or MimePart.
+ *
+ * @param Swift_Mime_MimeEntity $entity
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function attach(Swift_Mime_MimeEntity $entity)
+ {
+ $this->setChildren(array_merge($this->getChildren(), array($entity)));
+
+ return $this;
+ }
+
+ /**
+ * Remove an already attached entity.
+ *
+ * @param Swift_Mime_MimeEntity $entity
+ *
+ * @return Swift_Mime_SimpleMessage
+ */
+ public function detach(Swift_Mime_MimeEntity $entity)
+ {
+ $newChildren = array();
+ foreach ($this->getChildren() as $child) {
+ if ($entity !== $child) {
+ $newChildren[] = $child;
+ }
+ }
+ $this->setChildren($newChildren);
+
+ return $this;
+ }
+
+ /**
+ * Attach a {@link Swift_Mime_MimeEntity} and return it's CID source.
+ * This method should be used when embedding images or other data in a message.
+ *
+ * @param Swift_Mime_MimeEntity $entity
+ *
+ * @return string
+ */
+ public function embed(Swift_Mime_MimeEntity $entity)
+ {
+ $this->attach($entity);
+
+ return 'cid:' . $entity->getId();
+ }
+
+ /**
+ * Get this message as a complete string.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ if (count($children = $this->getChildren()) > 0 && $this->getBody() != '') {
+ $this->setChildren(array_merge(array($this->_becomeMimePart()), $children));
+ $string = parent::toString();
+ $this->setChildren($children);
+ } else {
+ $string = parent::toString();
+ }
+
+ return $string;
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @see toString()
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+
+ /**
+ * Write this message to a {@link Swift_InputByteStream}.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function toByteStream(Swift_InputByteStream $is)
+ {
+ if (count($children = $this->getChildren()) > 0 && $this->getBody() != '') {
+ $this->setChildren(array_merge(array($this->_becomeMimePart()), $children));
+ parent::toByteStream($is);
+ $this->setChildren($children);
+ } else {
+ parent::toByteStream($is);
+ }
+ }
+
+
+ /** @see Swift_Mime_SimpleMimeEntity::_getIdField() */
+ protected function _getIdField()
+ {
+ return 'Message-ID';
+ }
+
+ /** Turn the body of this message into a child of itself if needed */
+ protected function _becomeMimePart()
+ {
+ $part = new parent($this->getHeaders()->newInstance(), $this->getEncoder(),
+ $this->_getCache(), $this->_getGrammar(), $this->_userCharset
+ );
+ $part->setContentType($this->_userContentType);
+ $part->setBody($this->getBody());
+ $part->setFormat($this->_userFormat);
+ $part->setDelSp($this->_userDelSp);
+ $part->_setNestingLevel($this->_getTopNestingLevel());
+
+ return $part;
+ }
+
+ /** Get the highest nesting level nested inside this message */
+ private function _getTopNestingLevel()
+ {
+ $highestLevel = $this->getNestingLevel();
+ foreach ($this->getChildren() as $child) {
+ $childLevel = $child->getNestingLevel();
+ if ($highestLevel < $childLevel) {
+ $highestLevel = $childLevel;
+ }
+ }
+
+ return $highestLevel;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Mime/SimpleMimeEntity.php b/vendor/swiftmailer/classes/Swift/Mime/SimpleMimeEntity.php
new file mode 100644
index 00000000..d6950814
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Mime/SimpleMimeEntity.php
@@ -0,0 +1,853 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A MIME entity, in a multipart message.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Mime_SimpleMimeEntity implements Swift_Mime_MimeEntity
+{
+ /** A collection of Headers for this mime entity */
+ private $_headers;
+
+ /** The body as a string, or a stream */
+ private $_body;
+
+ /** The encoder that encodes the body into a streamable format */
+ private $_encoder;
+
+ /** The grammar to use for id validation */
+ private $_grammar;
+
+ /** A mime boundary, if any is used */
+ private $_boundary;
+
+ /** Mime types to be used based on the nesting level */
+ private $_compositeRanges = array(
+ 'multipart/mixed' => array(self::LEVEL_TOP, self::LEVEL_MIXED),
+ 'multipart/alternative' => array(self::LEVEL_MIXED, self::LEVEL_ALTERNATIVE),
+ 'multipart/related' => array(self::LEVEL_ALTERNATIVE, self::LEVEL_RELATED)
+ );
+
+ /** A set of filter rules to define what level an entity should be nested at */
+ private $_compoundLevelFilters = array();
+
+ /** The nesting level of this entity */
+ private $_nestingLevel = self::LEVEL_ALTERNATIVE;
+
+ /** A KeyCache instance used during encoding and streaming */
+ private $_cache;
+
+ /** Direct descendants of this entity */
+ private $_immediateChildren = array();
+
+ /** All descendants of this entity */
+ private $_children = array();
+
+ /** The maximum line length of the body of this entity */
+ private $_maxLineLength = 78;
+
+ /** The order in which alternative mime types should appear */
+ private $_alternativePartOrder = array(
+ 'text/plain' => 1,
+ 'text/html' => 2,
+ 'multipart/related' => 3
+ );
+
+ /** The CID of this entity */
+ private $_id;
+
+ /** The key used for accessing the cache */
+ private $_cacheKey;
+
+ protected $_userContentType;
+
+ /**
+ * Create a new SimpleMimeEntity with $headers, $encoder and $cache.
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ * @param Swift_Mime_ContentEncoder $encoder
+ * @param Swift_KeyCache $cache
+ * @param Swift_Mime_Grammar $grammar
+ */
+ public function __construct(Swift_Mime_HeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_Mime_Grammar $grammar)
+ {
+ $this->_cacheKey = md5(uniqid(getmypid().mt_rand(), true));
+ $this->_cache = $cache;
+ $this->_headers = $headers;
+ $this->_grammar = $grammar;
+ $this->setEncoder($encoder);
+ $this->_headers->defineOrdering(array('Content-Type', 'Content-Transfer-Encoding'));
+
+ // This array specifies that, when the entire MIME document contains
+ // $compoundLevel, then for each child within $level, if its Content-Type
+ // is $contentType then it should be treated as if it's level is
+ // $neededLevel instead. I tried to write that unambiguously! :-\
+ // Data Structure:
+ // array (
+ // $compoundLevel => array(
+ // $level => array(
+ // $contentType => $neededLevel
+ // )
+ // )
+ // )
+
+ $this->_compoundLevelFilters = array(
+ (self::LEVEL_ALTERNATIVE + self::LEVEL_RELATED) => array(
+ self::LEVEL_ALTERNATIVE => array(
+ 'text/plain' => self::LEVEL_ALTERNATIVE,
+ 'text/html' => self::LEVEL_RELATED
+ )
+ )
+ );
+
+ $this->_id = $this->getRandomId();
+ }
+
+ /**
+ * Generate a new Content-ID or Message-ID for this MIME entity.
+ *
+ * @return string
+ */
+ public function generateId()
+ {
+ $this->setId($this->getRandomId());
+
+ return $this->_id;
+ }
+
+ /**
+ * Get the {@link Swift_Mime_HeaderSet} for this entity.
+ *
+ * @return Swift_Mime_HeaderSet
+ */
+ public function getHeaders()
+ {
+ return $this->_headers;
+ }
+
+ /**
+ * Get the nesting level of this entity.
+ *
+ * @see LEVEL_TOP, LEVEL_MIXED, LEVEL_RELATED, LEVEL_ALTERNATIVE
+ *
+ * @return int
+ */
+ public function getNestingLevel()
+ {
+ return $this->_nestingLevel;
+ }
+
+ /**
+ * Get the Content-type of this entity.
+ *
+ * @return string
+ */
+ public function getContentType()
+ {
+ return $this->_getHeaderFieldModel('Content-Type');
+ }
+
+ /**
+ * Set the Content-type of this entity.
+ *
+ * @param string $type
+ *
+ * @return Swift_Mime_SimpleMimeEntity
+ */
+ public function setContentType($type)
+ {
+ $this->_setContentTypeInHeaders($type);
+ // Keep track of the value so that if the content-type changes automatically
+ // due to added child entities, it can be restored if they are later removed
+ $this->_userContentType = $type;
+
+ return $this;
+ }
+
+ /**
+ * Get the CID of this entity.
+ *
+ * The CID will only be present in headers if a Content-ID header is present.
+ *
+ * @return string
+ */
+ public function getId()
+ {
+ $tmp = (array) $this->_getHeaderFieldModel($this->_getIdField());
+
+ return $this->_headers->has($this->_getIdField()) ? current($tmp) : $this->_id;
+ }
+
+ /**
+ * Set the CID of this entity.
+ *
+ * @param string $id
+ *
+ * @return Swift_Mime_SimpleMimeEntity
+ */
+ public function setId($id)
+ {
+ if (!$this->_setHeaderFieldModel($this->_getIdField(), $id)) {
+ $this->_headers->addIdHeader($this->_getIdField(), $id);
+ }
+ $this->_id = $id;
+
+ return $this;
+ }
+
+ /**
+ * Get the description of this entity.
+ *
+ * This value comes from the Content-Description header if set.
+ *
+ * @return string
+ */
+ public function getDescription()
+ {
+ return $this->_getHeaderFieldModel('Content-Description');
+ }
+
+ /**
+ * Set the description of this entity.
+ *
+ * This method sets a value in the Content-ID header.
+ *
+ * @param string $description
+ *
+ * @return Swift_Mime_SimpleMimeEntity
+ */
+ public function setDescription($description)
+ {
+ if (!$this->_setHeaderFieldModel('Content-Description', $description)) {
+ $this->_headers->addTextHeader('Content-Description', $description);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the maximum line length of the body of this entity.
+ *
+ * @return int
+ */
+ public function getMaxLineLength()
+ {
+ return $this->_maxLineLength;
+ }
+
+ /**
+ * Set the maximum line length of lines in this body.
+ *
+ * Though not enforced by the library, lines should not exceed 1000 chars.
+ *
+ * @param int $length
+ *
+ * @return Swift_Mime_SimpleMimeEntity
+ */
+ public function setMaxLineLength($length)
+ {
+ $this->_maxLineLength = $length;
+
+ return $this;
+ }
+
+ /**
+ * Get all children added to this entity.
+ *
+ * @return array of Swift_Mime_Entity
+ */
+ public function getChildren()
+ {
+ return $this->_children;
+ }
+
+ /**
+ * Set all children of this entity.
+ *
+ * @param array $children Swift_Mime_Entity instances
+ * @param int $compoundLevel For internal use only
+ *
+ * @return Swift_Mime_SimpleMimeEntity
+ */
+ public function setChildren(array $children, $compoundLevel = null)
+ {
+ // TODO: Try to refactor this logic
+
+ $compoundLevel = isset($compoundLevel)
+ ? $compoundLevel
+ : $this->_getCompoundLevel($children)
+ ;
+
+ $immediateChildren = array();
+ $grandchildren = array();
+ $newContentType = $this->_userContentType;
+
+ foreach ($children as $child) {
+ $level = $this->_getNeededChildLevel($child, $compoundLevel);
+ if (empty($immediateChildren)) { //first iteration
+ $immediateChildren = array($child);
+ } else {
+ $nextLevel = $this->_getNeededChildLevel($immediateChildren[0], $compoundLevel);
+ if ($nextLevel == $level) {
+ $immediateChildren[] = $child;
+ } elseif ($level < $nextLevel) {
+ // Re-assign immediateChildren to grandchildren
+ $grandchildren = array_merge($grandchildren, $immediateChildren);
+ // Set new children
+ $immediateChildren = array($child);
+ } else {
+ $grandchildren[] = $child;
+ }
+ }
+ }
+
+ if (!empty($immediateChildren)) {
+ $lowestLevel = $this->_getNeededChildLevel($immediateChildren[0], $compoundLevel);
+
+ // Determine which composite media type is needed to accommodate the
+ // immediate children
+ foreach ($this->_compositeRanges as $mediaType => $range) {
+ if ($lowestLevel > $range[0]
+ && $lowestLevel <= $range[1])
+ {
+ $newContentType = $mediaType;
+ break;
+ }
+ }
+
+ // Put any grandchildren in a subpart
+ if (!empty($grandchildren)) {
+ $subentity = $this->_createChild();
+ $subentity->_setNestingLevel($lowestLevel);
+ $subentity->setChildren($grandchildren, $compoundLevel);
+ array_unshift($immediateChildren, $subentity);
+ }
+ }
+
+ $this->_immediateChildren = $immediateChildren;
+ $this->_children = $children;
+ $this->_setContentTypeInHeaders($newContentType);
+ $this->_fixHeaders();
+ $this->_sortChildren();
+
+ return $this;
+ }
+
+ /**
+ * Get the body of this entity as a string.
+ *
+ * @return string
+ */
+ public function getBody()
+ {
+ return ($this->_body instanceof Swift_OutputByteStream)
+ ? $this->_readStream($this->_body)
+ : $this->_body;
+ }
+
+ /**
+ * Set the body of this entity, either as a string, or as an instance of
+ * {@link Swift_OutputByteStream}.
+ *
+ * @param mixed $body
+ * @param string $contentType optional
+ *
+ * @return Swift_Mime_SimpleMimeEntity
+ */
+ public function setBody($body, $contentType = null)
+ {
+ if ($body !== $this->_body) {
+ $this->_clearCache();
+ }
+
+ $this->_body = $body;
+ if (isset($contentType)) {
+ $this->setContentType($contentType);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the encoder used for the body of this entity.
+ *
+ * @return Swift_Mime_ContentEncoder
+ */
+ public function getEncoder()
+ {
+ return $this->_encoder;
+ }
+
+ /**
+ * Set the encoder used for the body of this entity.
+ *
+ * @param Swift_Mime_ContentEncoder $encoder
+ *
+ * @return Swift_Mime_SimpleMimeEntity
+ */
+ public function setEncoder(Swift_Mime_ContentEncoder $encoder)
+ {
+ if ($encoder !== $this->_encoder) {
+ $this->_clearCache();
+ }
+
+ $this->_encoder = $encoder;
+ $this->_setEncoding($encoder->getName());
+ $this->_notifyEncoderChanged($encoder);
+
+ return $this;
+ }
+
+ /**
+ * Get the boundary used to separate children in this entity.
+ *
+ * @return string
+ */
+ public function getBoundary()
+ {
+ if (!isset($this->_boundary)) {
+ $this->_boundary = '_=_swift_v4_' . time() . '_' . md5(getmypid().mt_rand().uniqid('', true)) . '_=_';
+ }
+
+ return $this->_boundary;
+ }
+
+ /**
+ * Set the boundary used to separate children in this entity.
+ *
+ * @param string $boundary
+ *
+ * @return Swift_Mime_SimpleMimeEntity
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ public function setBoundary($boundary)
+ {
+ $this->_assertValidBoundary($boundary);
+ $this->_boundary = $boundary;
+
+ return $this;
+ }
+
+ /**
+ * Receive notification that the charset of this entity, or a parent entity
+ * has changed.
+ *
+ * @param string $charset
+ */
+ public function charsetChanged($charset)
+ {
+ $this->_notifyCharsetChanged($charset);
+ }
+
+ /**
+ * Receive notification that the encoder of this entity or a parent entity
+ * has changed.
+ *
+ * @param Swift_Mime_ContentEncoder $encoder
+ */
+ public function encoderChanged(Swift_Mime_ContentEncoder $encoder)
+ {
+ $this->_notifyEncoderChanged($encoder);
+ }
+
+ /**
+ * Get this entire entity as a string.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ $string = $this->_headers->toString();
+ $string .= $this->_bodyToString();
+
+ return $string;
+ }
+
+ /**
+ * Get this entire entity as a string.
+ *
+ * @return string
+ */
+ protected function _bodyToString()
+ {
+ $string = '';
+
+ if (isset($this->_body) && empty($this->_immediateChildren)) {
+ if ($this->_cache->hasKey($this->_cacheKey, 'body')) {
+ $body = $this->_cache->getString($this->_cacheKey, 'body');
+ } else {
+ $body = "\r\n" . $this->_encoder->encodeString($this->getBody(), 0,
+ $this->getMaxLineLength()
+ );
+ $this->_cache->setString($this->_cacheKey, 'body', $body,
+ Swift_KeyCache::MODE_WRITE
+ );
+ }
+ $string .= $body;
+ }
+
+ if (!empty($this->_immediateChildren)) {
+ foreach ($this->_immediateChildren as $child) {
+ $string .= "\r\n\r\n--" . $this->getBoundary() . "\r\n";
+ $string .= $child->toString();
+ }
+ $string .= "\r\n\r\n--" . $this->getBoundary() . "--\r\n";
+ }
+
+ return $string;
+ }
+
+ /**
+ * Returns a string representation of this object.
+ *
+ * @see toString()
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+
+ /**
+ * Write this entire entity to a {@see Swift_InputByteStream}.
+ *
+ * @param Swift_InputByteStream
+ */
+ public function toByteStream(Swift_InputByteStream $is)
+ {
+ $is->write($this->_headers->toString());
+ $is->commit();
+
+ $this->_bodyToByteStream($is);
+ }
+
+ /**
+ * Write this entire entity to a {@link Swift_InputByteStream}.
+ *
+ * @param Swift_InputByteStream
+ */
+ protected function _bodyToByteStream(Swift_InputByteStream $is)
+ {
+ if (empty($this->_immediateChildren)) {
+ if (isset($this->_body)) {
+ if ($this->_cache->hasKey($this->_cacheKey, 'body')) {
+ $this->_cache->exportToByteStream($this->_cacheKey, 'body', $is);
+ } else {
+ $cacheIs = $this->_cache->getInputByteStream($this->_cacheKey, 'body');
+ if ($cacheIs) {
+ $is->bind($cacheIs);
+ }
+
+ $is->write("\r\n");
+
+ if ($this->_body instanceof Swift_OutputByteStream) {
+ $this->_body->setReadPointer(0);
+
+ $this->_encoder->encodeByteStream($this->_body, $is, 0, $this->getMaxLineLength());
+ } else {
+ $is->write($this->_encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength()));
+ }
+
+ if ($cacheIs) {
+ $is->unbind($cacheIs);
+ }
+ }
+ }
+ }
+
+ if (!empty($this->_immediateChildren)) {
+ foreach ($this->_immediateChildren as $child) {
+ $is->write("\r\n\r\n--" . $this->getBoundary() . "\r\n");
+ $child->toByteStream($is);
+ }
+ $is->write("\r\n\r\n--" . $this->getBoundary() . "--\r\n");
+ }
+ }
+
+ /**
+ * Get the name of the header that provides the ID of this entity
+ */
+ protected function _getIdField()
+ {
+ return 'Content-ID';
+ }
+
+ /**
+ * Get the model data (usually an array or a string) for $field.
+ */
+ protected function _getHeaderFieldModel($field)
+ {
+ if ($this->_headers->has($field)) {
+ return $this->_headers->get($field)->getFieldBodyModel();
+ }
+ }
+
+ /**
+ * Set the model data for $field.
+ */
+ protected function _setHeaderFieldModel($field, $model)
+ {
+ if ($this->_headers->has($field)) {
+ $this->_headers->get($field)->setFieldBodyModel($model);
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Get the parameter value of $parameter on $field header.
+ */
+ protected function _getHeaderParameter($field, $parameter)
+ {
+ if ($this->_headers->has($field)) {
+ return $this->_headers->get($field)->getParameter($parameter);
+ }
+ }
+
+ /**
+ * Set the parameter value of $parameter on $field header.
+ */
+ protected function _setHeaderParameter($field, $parameter, $value)
+ {
+ if ($this->_headers->has($field)) {
+ $this->_headers->get($field)->setParameter($parameter, $value);
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Re-evaluate what content type and encoding should be used on this entity.
+ */
+ protected function _fixHeaders()
+ {
+ if (count($this->_immediateChildren)) {
+ $this->_setHeaderParameter('Content-Type', 'boundary',
+ $this->getBoundary()
+ );
+ $this->_headers->remove('Content-Transfer-Encoding');
+ } else {
+ $this->_setHeaderParameter('Content-Type', 'boundary', null);
+ $this->_setEncoding($this->_encoder->getName());
+ }
+ }
+
+ /**
+ * Get the KeyCache used in this entity.
+ *
+ * @return Swift_KeyCache
+ */
+ protected function _getCache()
+ {
+ return $this->_cache;
+ }
+
+ /**
+ * Get the grammar used for validation.
+ *
+ * @return Swift_Mime_Grammar
+ */
+ protected function _getGrammar()
+ {
+ return $this->_grammar;
+ }
+
+ /**
+ * Empty the KeyCache for this entity.
+ */
+ protected function _clearCache()
+ {
+ $this->_cache->clearKey($this->_cacheKey, 'body');
+ }
+
+ /**
+ * Returns a random Content-ID or Message-ID.
+ *
+ * @return string
+ */
+ protected function getRandomId()
+ {
+ $idLeft = md5(getmypid() . '.' . time() . '.' . uniqid(mt_rand(), true));
+ $idRight = !empty($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'swift.generated';
+ $id = $idLeft . '@' . $idRight;
+
+ try {
+ $this->_assertValidId($id);
+ } catch (Swift_RfcComplianceException $e) {
+ $id = $idLeft . '@swift.generated';
+ }
+
+ return $id;
+ }
+
+ private function _readStream(Swift_OutputByteStream $os)
+ {
+ $string = '';
+ while (false !== $bytes = $os->read(8192)) {
+ $string .= $bytes;
+ }
+
+ return $string;
+ }
+
+ private function _setEncoding($encoding)
+ {
+ if (!$this->_setHeaderFieldModel('Content-Transfer-Encoding', $encoding)) {
+ $this->_headers->addTextHeader('Content-Transfer-Encoding', $encoding);
+ }
+ }
+
+ private function _assertValidBoundary($boundary)
+ {
+ if (!preg_match(
+ '/^[a-z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-z0-9\'\(\)\+_\-,\.\/:=\?]$/Di',
+ $boundary))
+ {
+ throw new Swift_RfcComplianceException('Mime boundary set is not RFC 2046 compliant.');
+ }
+ }
+
+ private function _setContentTypeInHeaders($type)
+ {
+ if (!$this->_setHeaderFieldModel('Content-Type', $type)) {
+ $this->_headers->addParameterizedHeader('Content-Type', $type);
+ }
+ }
+
+ private function _setNestingLevel($level)
+ {
+ $this->_nestingLevel = $level;
+ }
+
+ private function _getCompoundLevel($children)
+ {
+ $level = 0;
+ foreach ($children as $child) {
+ $level |= $child->getNestingLevel();
+ }
+
+ return $level;
+ }
+
+ private function _getNeededChildLevel($child, $compoundLevel)
+ {
+ $filter = array();
+ foreach ($this->_compoundLevelFilters as $bitmask => $rules) {
+ if (($compoundLevel & $bitmask) === $bitmask) {
+ $filter = $rules + $filter;
+ }
+ }
+
+ $realLevel = $child->getNestingLevel();
+ $lowercaseType = strtolower($child->getContentType());
+
+ if (isset($filter[$realLevel])
+ && isset($filter[$realLevel][$lowercaseType]))
+ {
+ return $filter[$realLevel][$lowercaseType];
+ } else {
+ return $realLevel;
+ }
+ }
+
+ private function _createChild()
+ {
+ return new self($this->_headers->newInstance(),
+ $this->_encoder, $this->_cache, $this->_grammar);
+ }
+
+ private function _notifyEncoderChanged(Swift_Mime_ContentEncoder $encoder)
+ {
+ foreach ($this->_immediateChildren as $child) {
+ $child->encoderChanged($encoder);
+ }
+ }
+
+ private function _notifyCharsetChanged($charset)
+ {
+ $this->_encoder->charsetChanged($charset);
+ $this->_headers->charsetChanged($charset);
+ foreach ($this->_immediateChildren as $child) {
+ $child->charsetChanged($charset);
+ }
+ }
+
+ private function _sortChildren()
+ {
+ $shouldSort = false;
+ foreach ($this->_immediateChildren as $child) {
+ // NOTE: This include alternative parts moved into a related part
+ if ($child->getNestingLevel() == self::LEVEL_ALTERNATIVE) {
+ $shouldSort = true;
+ break;
+ }
+ }
+
+ // Sort in order of preference, if there is one
+ if ($shouldSort) {
+ usort($this->_immediateChildren, array($this, '_childSortAlgorithm'));
+ }
+ }
+
+ private function _childSortAlgorithm($a, $b)
+ {
+ $typePrefs = array();
+ $types = array(
+ strtolower($a->getContentType()),
+ strtolower($b->getContentType())
+ );
+ foreach ($types as $type) {
+ $typePrefs[] = (array_key_exists($type, $this->_alternativePartOrder))
+ ? $this->_alternativePartOrder[$type]
+ : (max($this->_alternativePartOrder) + 1);
+ }
+
+ return ($typePrefs[0] >= $typePrefs[1]) ? 1 : -1;
+ }
+
+ // -- Destructor
+
+ /**
+ * Empties it's own contents from the cache.
+ */
+ public function __destruct()
+ {
+ $this->_cache->clearAll($this->_cacheKey);
+ }
+
+ /**
+ * Throws an Exception if the id passed does not comply with RFC 2822.
+ *
+ * @param string $id
+ *
+ * @throws Swift_RfcComplianceException
+ */
+ private function _assertValidId($id)
+ {
+ if (!preg_match(
+ '/^' . $this->_grammar->getDefinition('id-left') . '@' .
+ $this->_grammar->getDefinition('id-right') . '$/D',
+ $id
+ ))
+ {
+ throw new Swift_RfcComplianceException(
+ 'Invalid ID given <' . $id . '>'
+ );
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/MimePart.php b/vendor/swiftmailer/classes/Swift/MimePart.php
new file mode 100644
index 00000000..5702d1c1
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/MimePart.php
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A MIME part, in a multipart message.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_MimePart extends Swift_Mime_MimePart
+{
+ /**
+ * Create a new MimePart.
+ *
+ * Details may be optionally passed into the constructor.
+ *
+ * @param string $body
+ * @param string $contentType
+ * @param string $charset
+ */
+ public function __construct($body = null, $contentType = null, $charset = null)
+ {
+ call_user_func_array(
+ array($this, 'Swift_Mime_MimePart::__construct'),
+ Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('mime.part')
+ );
+
+ if (!isset($charset)) {
+ $charset = Swift_DependencyContainer::getInstance()
+ ->lookup('properties.charset');
+ }
+ $this->setBody($body);
+ $this->setCharset($charset);
+ if ($contentType) {
+ $this->setContentType($contentType);
+ }
+ }
+
+ /**
+ * Create a new MimePart.
+ *
+ * @param string $body
+ * @param string $contentType
+ * @param string $charset
+ *
+ * @return Swift_Mime_MimePart
+ */
+ public static function newInstance($body = null, $contentType = null, $charset = null)
+ {
+ return new self($body, $contentType, $charset);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/NullTransport.php b/vendor/swiftmailer/classes/Swift/NullTransport.php
new file mode 100644
index 00000000..726d83ca
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/NullTransport.php
@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2009 Fabien Potencier <fabien.potencier@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Pretends messages have been sent, but just ignores them.
+ *
+ * @author Fabien Potencier
+ */
+class Swift_NullTransport extends Swift_Transport_NullTransport
+{
+ /**
+ * Create a new NullTransport.
+ */
+ public function __construct()
+ {
+ call_user_func_array(
+ array($this, 'Swift_Transport_NullTransport::__construct'),
+ Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('transport.null')
+ );
+ }
+
+ /**
+ * Create a new NullTransport instance.
+ *
+ * @return Swift_NullTransport
+ */
+ public static function newInstance()
+ {
+ return new self();
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/OutputByteStream.php b/vendor/swiftmailer/classes/Swift/OutputByteStream.php
new file mode 100644
index 00000000..0c2783f0
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/OutputByteStream.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An abstract means of reading data.
+ *
+ * Classes implementing this interface may use a subsystem which requires less
+ * memory than working with large strings of data.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_OutputByteStream
+{
+ /**
+ * Reads $length bytes from the stream into a string and moves the pointer
+ * through the stream by $length.
+ *
+ * If less bytes exist than are requested the remaining bytes are given instead.
+ * If no bytes are remaining at all, boolean false is returned.
+ *
+ * @param int $length
+ *
+ * @return string|bool
+ *
+ * @throws Swift_IoException
+ */
+ public function read($length);
+
+ /**
+ * Move the internal read pointer to $byteOffset in the stream.
+ *
+ * @param int $byteOffset
+ *
+ * @return bool
+ *
+ * @throws Swift_IoException
+ */
+ public function setReadPointer($byteOffset);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/AntiFloodPlugin.php b/vendor/swiftmailer/classes/Swift/Plugins/AntiFloodPlugin.php
new file mode 100644
index 00000000..28f3a817
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/AntiFloodPlugin.php
@@ -0,0 +1,141 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Reduces network flooding when sending large amounts of mail.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Plugins_AntiFloodPlugin implements Swift_Events_SendListener, Swift_Plugins_Sleeper
+{
+ /**
+ * The number of emails to send before restarting Transport.
+ *
+ * @var int
+ */
+ private $_threshold;
+
+ /**
+ * The number of seconds to sleep for during a restart.
+ *
+ * @var int
+ */
+ private $_sleep;
+
+ /**
+ * The internal counter.
+ *
+ * @var int
+ */
+ private $_counter = 0;
+
+ /**
+ * The Sleeper instance for sleeping.
+ *
+ * @var Swift_Plugins_Sleeper
+ */
+ private $_sleeper;
+
+ /**
+ * Create a new AntiFloodPlugin with $threshold and $sleep time.
+ *
+ * @param int $threshold
+ * @param int $sleep time
+ * @param Swift_Plugins_Sleeper $sleeper (not needed really)
+ */
+ public function __construct($threshold = 99, $sleep = 0, Swift_Plugins_Sleeper $sleeper = null)
+ {
+ $this->setThreshold($threshold);
+ $this->setSleepTime($sleep);
+ $this->_sleeper = $sleeper;
+ }
+
+ /**
+ * Set the number of emails to send before restarting.
+ *
+ * @param int $threshold
+ */
+ public function setThreshold($threshold)
+ {
+ $this->_threshold = $threshold;
+ }
+
+ /**
+ * Get the number of emails to send before restarting.
+ *
+ * @return int
+ */
+ public function getThreshold()
+ {
+ return $this->_threshold;
+ }
+
+ /**
+ * Set the number of seconds to sleep for during a restart.
+ *
+ * @param int $sleep time
+ */
+ public function setSleepTime($sleep)
+ {
+ $this->_sleep = $sleep;
+ }
+
+ /**
+ * Get the number of seconds to sleep for during a restart.
+ *
+ * @return int
+ */
+ public function getSleepTime()
+ {
+ return $this->_sleep;
+ }
+
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ ++$this->_counter;
+ if ($this->_counter >= $this->_threshold) {
+ $transport = $evt->getTransport();
+ $transport->stop();
+ if ($this->_sleep) {
+ $this->sleep($this->_sleep);
+ }
+ $transport->start();
+ $this->_counter = 0;
+ }
+ }
+
+ /**
+ * Sleep for $seconds.
+ *
+ * @param int $seconds
+ */
+ public function sleep($seconds)
+ {
+ if (isset($this->_sleeper)) {
+ $this->_sleeper->sleep($seconds);
+ } else {
+ sleep($seconds);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/BandwidthMonitorPlugin.php b/vendor/swiftmailer/classes/Swift/Plugins/BandwidthMonitorPlugin.php
new file mode 100644
index 00000000..af1701a0
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/BandwidthMonitorPlugin.php
@@ -0,0 +1,164 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Reduces network flooding when sending large amounts of mail.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Plugins_BandwidthMonitorPlugin implements Swift_Events_SendListener, Swift_Events_CommandListener, Swift_Events_ResponseListener, Swift_InputByteStream
+{
+ /**
+ * The outgoing traffic counter.
+ *
+ * @var int
+ */
+ private $_out = 0;
+
+ /**
+ * The incoming traffic counter.
+ *
+ * @var int
+ */
+ private $_in = 0;
+
+ /** Bound byte streams */
+ private $_mirrors = array();
+
+ /**
+ * Not used.
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $message = $evt->getMessage();
+ $message->toByteStream($this);
+ }
+
+ /**
+ * Invoked immediately following a command being sent.
+ *
+ * @param Swift_Events_CommandEvent $evt
+ */
+ public function commandSent(Swift_Events_CommandEvent $evt)
+ {
+ $command = $evt->getCommand();
+ $this->_out += strlen($command);
+ }
+
+ /**
+ * Invoked immediately following a response coming back.
+ *
+ * @param Swift_Events_ResponseEvent $evt
+ */
+ public function responseReceived(Swift_Events_ResponseEvent $evt)
+ {
+ $response = $evt->getResponse();
+ $this->_in += strlen($response);
+ }
+
+ /**
+ * Called when a message is sent so that the outgoing counter can be increased.
+ *
+ * @param string $bytes
+ */
+ public function write($bytes)
+ {
+ $this->_out += strlen($bytes);
+ foreach ($this->_mirrors as $stream) {
+ $stream->write($bytes);
+ }
+ }
+
+ /**
+ * Not used.
+ */
+ public function commit()
+ {
+ }
+
+ /**
+ * Attach $is to this stream.
+ *
+ * The stream acts as an observer, receiving all data that is written.
+ * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function bind(Swift_InputByteStream $is)
+ {
+ $this->_mirrors[] = $is;
+ }
+
+ /**
+ * Remove an already bound stream.
+ *
+ * If $is is not bound, no errors will be raised.
+ * If the stream currently has any buffered data it will be written to $is
+ * before unbinding occurs.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function unbind(Swift_InputByteStream $is)
+ {
+ foreach ($this->_mirrors as $k => $stream) {
+ if ($is === $stream) {
+ unset($this->_mirrors[$k]);
+ }
+ }
+ }
+
+ /**
+ * Not used.
+ */
+ public function flushBuffers()
+ {
+ foreach ($this->_mirrors as $stream) {
+ $stream->flushBuffers();
+ }
+ }
+
+ /**
+ * Get the total number of bytes sent to the server.
+ *
+ * @return int
+ */
+ public function getBytesOut()
+ {
+ return $this->_out;
+ }
+
+ /**
+ * Get the total number of bytes received from the server.
+ *
+ * @return int
+ */
+ public function getBytesIn()
+ {
+ return $this->_in;
+ }
+
+ /**
+ * Reset the internal counters to zero.
+ */
+ public function reset()
+ {
+ $this->_out = 0;
+ $this->_in = 0;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/Decorator/Replacements.php b/vendor/swiftmailer/classes/Swift/Plugins/Decorator/Replacements.php
new file mode 100644
index 00000000..86184339
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/Decorator/Replacements.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Allows customization of Messages on-the-fly.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Plugins_Decorator_Replacements
+{
+ /**
+ * Return the array of replacements for $address.
+ *
+ * This method is invoked once for every single recipient of a message.
+ *
+ * If no replacements can be found, an empty value (NULL) should be returned
+ * and no replacements will then be made on the message.
+ *
+ * @param string $address
+ *
+ * @return array
+ */
+ public function getReplacementsFor($address);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/DecoratorPlugin.php b/vendor/swiftmailer/classes/Swift/Plugins/DecoratorPlugin.php
new file mode 100644
index 00000000..e1aaebe9
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/DecoratorPlugin.php
@@ -0,0 +1,207 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Allows customization of Messages on-the-fly.
+ *
+ * @author Chris Corbyn
+ * @author Fabien Potencier
+ */
+class Swift_Plugins_DecoratorPlugin implements Swift_Events_SendListener, Swift_Plugins_Decorator_Replacements
+{
+ /** The replacement map */
+ private $_replacements;
+
+ /** The body as it was before replacements */
+ private $_originalBody;
+
+ /** The original headers of the message, before replacements */
+ private $_originalHeaders = array();
+
+ /** Bodies of children before they are replaced */
+ private $_originalChildBodies = array();
+
+ /** The Message that was last replaced */
+ private $_lastMessage;
+
+ /**
+ * Create a new DecoratorPlugin with $replacements.
+ *
+ * The $replacements can either be an associative array, or an implementation
+ * of {@link Swift_Plugins_Decorator_Replacements}.
+ *
+ * When using an array, it should be of the form:
+ * <code>
+ * $replacements = array(
+ * "address1@domain.tld" => array("{a}" => "b", "{c}" => "d"),
+ * "address2@domain.tld" => array("{a}" => "x", "{c}" => "y")
+ * )
+ * </code>
+ *
+ * When using an instance of {@link Swift_Plugins_Decorator_Replacements},
+ * the object should return just the array of replacements for the address
+ * given to {@link Swift_Plugins_Decorator_Replacements::getReplacementsFor()}.
+ *
+ * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements
+ */
+ public function __construct($replacements)
+ {
+ $this->setReplacements($replacements);
+ }
+
+ /**
+ * Sets replacements.
+ *
+ * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements
+ *
+ * @see __construct()
+ */
+ public function setReplacements($replacements)
+ {
+ if (!($replacements instanceof Swift_Plugins_Decorator_Replacements)) {
+ $this->_replacements = (array) $replacements;
+ } else {
+ $this->_replacements = $replacements;
+ }
+ }
+
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $message = $evt->getMessage();
+ $this->_restoreMessage($message);
+ $to = array_keys($message->getTo());
+ $address = array_shift($to);
+ if ($replacements = $this->getReplacementsFor($address)) {
+ $body = $message->getBody();
+ $search = array_keys($replacements);
+ $replace = array_values($replacements);
+ $bodyReplaced = str_replace(
+ $search, $replace, $body
+ );
+ if ($body != $bodyReplaced) {
+ $this->_originalBody = $body;
+ $message->setBody($bodyReplaced);
+ }
+
+ foreach ($message->getHeaders()->getAll() as $header) {
+ $body = $header->getFieldBodyModel();
+ $count = 0;
+ if (is_array($body)) {
+ $bodyReplaced = array();
+ foreach ($body as $key => $value) {
+ $count1 = 0;
+ $count2 = 0;
+ $key = is_string($key) ? str_replace($search, $replace, $key, $count1) : $key;
+ $value = is_string($value) ? str_replace($search, $replace, $value, $count2) : $value;
+ $bodyReplaced[$key] = $value;
+
+ if (!$count && ($count1 || $count2)) {
+ $count = 1;
+ }
+ }
+ } else {
+ $bodyReplaced = str_replace($search, $replace, $body, $count);
+ }
+
+ if ($count) {
+ $this->_originalHeaders[$header->getFieldName()] = $body;
+ $header->setFieldBodyModel($bodyReplaced);
+ }
+ }
+
+ $children = (array) $message->getChildren();
+ foreach ($children as $child) {
+ list($type, ) = sscanf($child->getContentType(), '%[^/]/%s');
+ if ('text' == $type) {
+ $body = $child->getBody();
+ $bodyReplaced = str_replace(
+ $search, $replace, $body
+ );
+ if ($body != $bodyReplaced) {
+ $child->setBody($bodyReplaced);
+ $this->_originalChildBodies[$child->getId()] = $body;
+ }
+ }
+ }
+ $this->_lastMessage = $message;
+ }
+ }
+
+ /**
+ * Find a map of replacements for the address.
+ *
+ * If this plugin was provided with a delegate instance of
+ * {@link Swift_Plugins_Decorator_Replacements} then the call will be
+ * delegated to it. Otherwise, it will attempt to find the replacements
+ * from the array provided in the constructor.
+ *
+ * If no replacements can be found, an empty value (NULL) is returned.
+ *
+ * @param string $address
+ *
+ * @return array
+ */
+ public function getReplacementsFor($address)
+ {
+ if ($this->_replacements instanceof Swift_Plugins_Decorator_Replacements) {
+ return $this->_replacements->getReplacementsFor($address);
+ } else {
+ return isset($this->_replacements[$address])
+ ? $this->_replacements[$address]
+ : null
+ ;
+ }
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $this->_restoreMessage($evt->getMessage());
+ }
+
+ /** Restore a changed message back to its original state */
+ private function _restoreMessage(Swift_Mime_Message $message)
+ {
+ if ($this->_lastMessage === $message) {
+ if (isset($this->_originalBody)) {
+ $message->setBody($this->_originalBody);
+ $this->_originalBody = null;
+ }
+ if (!empty($this->_originalHeaders)) {
+ foreach ($message->getHeaders()->getAll() as $header) {
+ if (array_key_exists($header->getFieldName(), $this->_originalHeaders)) {
+ $header->setFieldBodyModel($this->_originalHeaders[$header->getFieldName()]);
+ }
+ }
+ $this->_originalHeaders = array();
+ }
+ if (!empty($this->_originalChildBodies)) {
+ $children = (array) $message->getChildren();
+ foreach ($children as $child) {
+ $id = $child->getId();
+ if (array_key_exists($id, $this->_originalChildBodies)) {
+ $child->setBody($this->_originalChildBodies[$id]);
+ }
+ }
+ $this->_originalChildBodies = array();
+ }
+ $this->_lastMessage = null;
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/ImpersonatePlugin.php b/vendor/swiftmailer/classes/Swift/Plugins/ImpersonatePlugin.php
new file mode 100644
index 00000000..e2999490
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/ImpersonatePlugin.php
@@ -0,0 +1,68 @@
+<?php
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Replaces the sender of a message.
+ *
+ * @author Arjen Brouwer
+ */
+class Swift_Plugins_ImpersonatePlugin implements Swift_Events_SendListener
+{
+ /**
+ * The sender to impersonate.
+ *
+ * @var String
+ */
+ private $_sender;
+
+ /**
+ * Create a new ImpersonatePlugin to impersonate $sender.
+ *
+ * @param string $sender address
+ */
+ public function __construct($sender)
+ {
+ $this->_sender = $sender;
+ }
+
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $message = $evt->getMessage();
+ $headers = $message->getHeaders();
+
+ // save current recipients
+ $headers->addPathHeader('X-Swift-Return-Path', $message->getReturnPath());
+
+ // replace them with the one to send to
+ $message->setReturnPath($this->_sender);
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $message = $evt->getMessage();
+
+ // restore original headers
+ $headers = $message->getHeaders();
+
+ if ($headers->has('X-Swift-Return-Path')) {
+ $message->setReturnPath($headers->get('X-Swift-Return-Path')->getAddress());
+ $headers->removeAll('X-Swift-Return-Path');
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/Logger.php b/vendor/swiftmailer/classes/Swift/Plugins/Logger.php
new file mode 100644
index 00000000..915e7206
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/Logger.php
@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Logs events in the Transport system.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Plugins_Logger
+{
+ /**
+ * Add a log entry.
+ *
+ * @param string $entry
+ */
+ public function add($entry);
+
+ /**
+ * Clear the log contents.
+ */
+ public function clear();
+
+ /**
+ * Get this log as a string.
+ *
+ * @return string
+ */
+ public function dump();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/LoggerPlugin.php b/vendor/swiftmailer/classes/Swift/Plugins/LoggerPlugin.php
new file mode 100644
index 00000000..98e59052
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/LoggerPlugin.php
@@ -0,0 +1,141 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Does real time logging of Transport level information.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Plugins_LoggerPlugin implements Swift_Events_CommandListener, Swift_Events_ResponseListener, Swift_Events_TransportChangeListener, Swift_Events_TransportExceptionListener, Swift_Plugins_Logger
+{
+ /** The logger which is delegated to */
+ private $_logger;
+
+ /**
+ * Create a new LoggerPlugin using $logger.
+ *
+ * @param Swift_Plugins_Logger $logger
+ */
+ public function __construct(Swift_Plugins_Logger $logger)
+ {
+ $this->_logger = $logger;
+ }
+
+ /**
+ * Add a log entry.
+ *
+ * @param string $entry
+ */
+ public function add($entry)
+ {
+ $this->_logger->add($entry);
+ }
+
+ /**
+ * Clear the log contents.
+ */
+ public function clear()
+ {
+ $this->_logger->clear();
+ }
+
+ /**
+ * Get this log as a string.
+ *
+ * @return string
+ */
+ public function dump()
+ {
+ return $this->_logger->dump();
+ }
+
+ /**
+ * Invoked immediately following a command being sent.
+ *
+ * @param Swift_Events_CommandEvent $evt
+ */
+ public function commandSent(Swift_Events_CommandEvent $evt)
+ {
+ $command = $evt->getCommand();
+ $this->_logger->add(sprintf(">> %s", $command));
+ }
+
+ /**
+ * Invoked immediately following a response coming back.
+ *
+ * @param Swift_Events_ResponseEvent $evt
+ */
+ public function responseReceived(Swift_Events_ResponseEvent $evt)
+ {
+ $response = $evt->getResponse();
+ $this->_logger->add(sprintf("<< %s", $response));
+ }
+
+ /**
+ * Invoked just before a Transport is started.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt)
+ {
+ $transportName = get_class($evt->getSource());
+ $this->_logger->add(sprintf("++ Starting %s", $transportName));
+ }
+
+ /**
+ * Invoked immediately after the Transport is started.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function transportStarted(Swift_Events_TransportChangeEvent $evt)
+ {
+ $transportName = get_class($evt->getSource());
+ $this->_logger->add(sprintf("++ %s started", $transportName));
+ }
+
+ /**
+ * Invoked just before a Transport is stopped.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt)
+ {
+ $transportName = get_class($evt->getSource());
+ $this->_logger->add(sprintf("++ Stopping %s", $transportName));
+ }
+
+ /**
+ * Invoked immediately after the Transport is stopped.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function transportStopped(Swift_Events_TransportChangeEvent $evt)
+ {
+ $transportName = get_class($evt->getSource());
+ $this->_logger->add(sprintf("++ %s stopped", $transportName));
+ }
+
+ /**
+ * Invoked as a TransportException is thrown in the Transport system.
+ *
+ * @param Swift_Events_TransportExceptionEvent $evt
+ */
+ public function exceptionThrown(Swift_Events_TransportExceptionEvent $evt)
+ {
+ $e = $evt->getException();
+ $message = $e->getMessage();
+ $this->_logger->add(sprintf("!! %s", $message));
+ $message .= PHP_EOL;
+ $message .= 'Log data:' . PHP_EOL;
+ $message .= $this->_logger->dump();
+ $evt->cancelBubble();
+ throw new Swift_TransportException($message);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/Loggers/ArrayLogger.php b/vendor/swiftmailer/classes/Swift/Plugins/Loggers/ArrayLogger.php
new file mode 100644
index 00000000..f1739e8e
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/Loggers/ArrayLogger.php
@@ -0,0 +1,72 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Logs to an Array backend.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Plugins_Loggers_ArrayLogger implements Swift_Plugins_Logger
+{
+ /**
+ * The log contents.
+ *
+ * @var array
+ */
+ private $_log = array();
+
+ /**
+ * Max size of the log.
+ *
+ * @var int
+ */
+ private $_size = 0;
+
+ /**
+ * Create a new ArrayLogger with a maximum of $size entries.
+ *
+ * @var int $size
+ */
+ public function __construct($size = 50)
+ {
+ $this->_size = $size;
+ }
+
+ /**
+ * Add a log entry.
+ *
+ * @param string $entry
+ */
+ public function add($entry)
+ {
+ $this->_log[] = $entry;
+ while (count($this->_log) > $this->_size) {
+ array_shift($this->_log);
+ }
+ }
+
+ /**
+ * Clear the log contents.
+ */
+ public function clear()
+ {
+ $this->_log = array();
+ }
+
+ /**
+ * Get this log as a string.
+ *
+ * @return string
+ */
+ public function dump()
+ {
+ return implode(PHP_EOL, $this->_log);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/Loggers/EchoLogger.php b/vendor/swiftmailer/classes/Swift/Plugins/Loggers/EchoLogger.php
new file mode 100644
index 00000000..e8b6c18a
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/Loggers/EchoLogger.php
@@ -0,0 +1,58 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Prints all log messages in real time.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Plugins_Loggers_EchoLogger implements Swift_Plugins_Logger
+{
+ /** Whether or not HTML should be output */
+ private $_isHtml;
+
+ /**
+ * Create a new EchoLogger.
+ *
+ * @param bool $isHtml
+ */
+ public function __construct($isHtml = true)
+ {
+ $this->_isHtml = $isHtml;
+ }
+
+ /**
+ * Add a log entry.
+ *
+ * @param string $entry
+ */
+ public function add($entry)
+ {
+ if ($this->_isHtml) {
+ printf('%s%s%s', htmlspecialchars($entry, ENT_QUOTES), '<br />', PHP_EOL);
+ } else {
+ printf('%s%s', $entry, PHP_EOL);
+ }
+ }
+
+ /**
+ * Not implemented.
+ */
+ public function clear()
+ {
+ }
+
+ /**
+ * Not implemented.
+ */
+ public function dump()
+ {
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/MessageLogger.php b/vendor/swiftmailer/classes/Swift/Plugins/MessageLogger.php
new file mode 100644
index 00000000..a02ad98e
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/MessageLogger.php
@@ -0,0 +1,75 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores all sent emails for further usage.
+ *
+ * @author Fabien Potencier
+ */
+class Swift_Plugins_MessageLogger implements Swift_Events_SendListener
+{
+ /**
+ * @var array
+ */
+ private $messages;
+
+ public function __construct()
+ {
+ $this->messages = array();
+ }
+
+ /**
+ * Get the message list
+ *
+ * @return array
+ */
+ public function getMessages()
+ {
+ return $this->messages;
+ }
+
+ /**
+ * Get the message count
+ *
+ * @return int count
+ */
+ public function countMessages()
+ {
+ return count($this->messages);
+ }
+
+ /**
+ * Empty the message list
+ *
+ */
+ public function clear()
+ {
+ $this->messages = array();
+ }
+
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $this->messages[] = clone $evt->getMessage();
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/Pop/Pop3Connection.php b/vendor/swiftmailer/classes/Swift/Plugins/Pop/Pop3Connection.php
new file mode 100644
index 00000000..1e18016a
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/Pop/Pop3Connection.php
@@ -0,0 +1,31 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Pop3Connection interface for connecting and disconnecting to a POP3 host.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Plugins_Pop_Pop3Connection
+{
+ /**
+ * Connect to the POP3 host and throw an Exception if it fails.
+ *
+ * @throws Swift_Plugins_Pop_Pop3Exception
+ */
+ public function connect();
+
+ /**
+ * Disconnect from the POP3 host and throw an Exception if it fails.
+ *
+ * @throws Swift_Plugins_Pop_Pop3Exception
+ */
+ public function disconnect();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/Pop/Pop3Exception.php b/vendor/swiftmailer/classes/Swift/Plugins/Pop/Pop3Exception.php
new file mode 100644
index 00000000..87020726
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/Pop/Pop3Exception.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Pop3Exception thrown when an error occurs connecting to a POP3 host.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Plugins_Pop_Pop3Exception extends Swift_IoException
+{
+ /**
+ * Create a new Pop3Exception with $message.
+ *
+ * @param string $message
+ */
+ public function __construct($message)
+ {
+ parent::__construct($message);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/PopBeforeSmtpPlugin.php b/vendor/swiftmailer/classes/Swift/Plugins/PopBeforeSmtpPlugin.php
new file mode 100644
index 00000000..57eea9a7
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/PopBeforeSmtpPlugin.php
@@ -0,0 +1,274 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Makes sure a connection to a POP3 host has been established prior to connecting to SMTP.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Plugins_PopBeforeSmtpPlugin implements Swift_Events_TransportChangeListener, Swift_Plugins_Pop_Pop3Connection
+{
+ /** A delegate connection to use (mostly a test hook) */
+ private $_connection;
+
+ /** Hostname of the POP3 server */
+ private $_host;
+
+ /** Port number to connect on */
+ private $_port;
+
+ /** Encryption type to use (if any) */
+ private $_crypto;
+
+ /** Username to use (if any) */
+ private $_username;
+
+ /** Password to use (if any) */
+ private $_password;
+
+ /** Established connection via TCP socket */
+ private $_socket;
+
+ /** Connect timeout in seconds */
+ private $_timeout = 10;
+
+ /** SMTP Transport to bind to */
+ private $_transport;
+
+ /**
+ * Create a new PopBeforeSmtpPlugin for $host and $port.
+ *
+ * @param string $host
+ * @param int $port
+ * @param string $crypto as "tls" or "ssl"
+ */
+ public function __construct($host, $port = 110, $crypto = null)
+ {
+ $this->_host = $host;
+ $this->_port = $port;
+ $this->_crypto = $crypto;
+ }
+
+ /**
+ * Create a new PopBeforeSmtpPlugin for $host and $port.
+ *
+ * @param string $host
+ * @param int $port
+ * @param string $crypto as "tls" or "ssl"
+ *
+ * @return Swift_Plugins_PopBeforeSmtpPlugin
+ */
+ public static function newInstance($host, $port = 110, $crypto = null)
+ {
+ return new self($host, $port, $crypto);
+ }
+
+ /**
+ * Set a Pop3Connection to delegate to instead of connecting directly.
+ *
+ * @param Swift_Plugins_Pop_Pop3Connection $connection
+ *
+ * @return Swift_Plugins_PopBeforeSmtpPlugin
+ */
+ public function setConnection(Swift_Plugins_Pop_Pop3Connection $connection)
+ {
+ $this->_connection = $connection;
+
+ return $this;
+ }
+
+ /**
+ * Bind this plugin to a specific SMTP transport instance.
+ *
+ * @param Swift_Transport
+ */
+ public function bindSmtp(Swift_Transport $smtp)
+ {
+ $this->_transport = $smtp;
+ }
+
+ /**
+ * Set the connection timeout in seconds (default 10).
+ *
+ * @param int $timeout
+ *
+ * @return Swift_Plugins_PopBeforeSmtpPlugin
+ */
+ public function setTimeout($timeout)
+ {
+ $this->_timeout = (int) $timeout;
+
+ return $this;
+ }
+
+ /**
+ * Set the username to use when connecting (if needed).
+ *
+ * @param string $username
+ *
+ * @return Swift_Plugins_PopBeforeSmtpPlugin
+ */
+ public function setUsername($username)
+ {
+ $this->_username = $username;
+
+ return $this;
+ }
+
+ /**
+ * Set the password to use when connecting (if needed).
+ *
+ * @param string $password
+ *
+ * @return Swift_Plugins_PopBeforeSmtpPlugin
+ */
+ public function setPassword($password)
+ {
+ $this->_password = $password;
+
+ return $this;
+ }
+
+ /**
+ * Connect to the POP3 host and authenticate.
+ *
+ * @throws Swift_Plugins_Pop_Pop3Exception if connection fails
+ */
+ public function connect()
+ {
+ if (isset($this->_connection)) {
+ $this->_connection->connect();
+ } else {
+ if (!isset($this->_socket)) {
+ if (!$socket = fsockopen(
+ $this->_getHostString(), $this->_port, $errno, $errstr, $this->_timeout))
+ {
+ throw new Swift_Plugins_Pop_Pop3Exception(
+ sprintf('Failed to connect to POP3 host [%s]: %s', $this->_host, $errstr)
+ );
+ }
+ $this->_socket = $socket;
+
+ if (false === $greeting = fgets($this->_socket)) {
+ throw new Swift_Plugins_Pop_Pop3Exception(
+ sprintf('Failed to connect to POP3 host [%s]', trim($greeting))
+ );
+ }
+
+ $this->_assertOk($greeting);
+
+ if ($this->_username) {
+ $this->_command(sprintf("USER %s\r\n", $this->_username));
+ $this->_command(sprintf("PASS %s\r\n", $this->_password));
+ }
+ }
+ }
+ }
+
+ /**
+ * Disconnect from the POP3 host.
+ */
+ public function disconnect()
+ {
+ if (isset($this->_connection)) {
+ $this->_connection->disconnect();
+ } else {
+ $this->_command("QUIT\r\n");
+ if (!fclose($this->_socket)) {
+ throw new Swift_Plugins_Pop_Pop3Exception(
+ sprintf('POP3 host [%s] connection could not be stopped', $this->_host)
+ );
+ }
+ $this->_socket = null;
+ }
+ }
+
+ /**
+ * Invoked just before a Transport is started.
+ *
+ * @param Swift_Events_TransportChangeEvent $evt
+ */
+ public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt)
+ {
+ if (isset($this->_transport)) {
+ if ($this->_transport !== $evt->getTransport()) {
+ return;
+ }
+ }
+
+ $this->connect();
+ $this->disconnect();
+ }
+
+ /**
+ * Not used.
+ */
+ public function transportStarted(Swift_Events_TransportChangeEvent $evt)
+ {
+ }
+
+ /**
+ * Not used.
+ */
+ public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt)
+ {
+ }
+
+ /**
+ * Not used.
+ */
+ public function transportStopped(Swift_Events_TransportChangeEvent $evt)
+ {
+ }
+
+ private function _command($command)
+ {
+ if (!fwrite($this->_socket, $command)) {
+ throw new Swift_Plugins_Pop_Pop3Exception(
+ sprintf('Failed to write command [%s] to POP3 host', trim($command))
+ );
+ }
+
+ if (false === $response = fgets($this->_socket)) {
+ throw new Swift_Plugins_Pop_Pop3Exception(
+ sprintf('Failed to read from POP3 host after command [%s]', trim($command))
+ );
+ }
+
+ $this->_assertOk($response);
+
+ return $response;
+ }
+
+ private function _assertOk($response)
+ {
+ if (substr($response, 0, 3) != '+OK') {
+ throw new Swift_Plugins_Pop_Pop3Exception(
+ sprintf('POP3 command failed [%s]', trim($response))
+ );
+ }
+ }
+
+ private function _getHostString()
+ {
+ $host = $this->_host;
+ switch (strtolower($this->_crypto)) {
+ case 'ssl':
+ $host = 'ssl://' . $host;
+ break;
+
+ case 'tls':
+ $host = 'tls://' . $host;
+ break;
+ }
+
+ return $host;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php b/vendor/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php
new file mode 100644
index 00000000..90f380bc
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/RedirectingPlugin.php
@@ -0,0 +1,205 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2009 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Redirects all email to a single recipient.
+ *
+ * @author Fabien Potencier
+ */
+class Swift_Plugins_RedirectingPlugin implements Swift_Events_SendListener
+{
+ /**
+ * The recipient who will receive all messages.
+ *
+ * @var mixed
+ */
+ private $_recipient;
+
+ /**
+ * List of regular expression for recipient whitelisting
+ *
+ * @var array
+ */
+ private $_whitelist = array();
+
+ /**
+ * Create a new RedirectingPlugin.
+ *
+ * @param mixed $recipient
+ * @param array $whitelist
+ */
+ public function __construct($recipient, array $whitelist = array())
+ {
+ $this->_recipient = $recipient;
+ $this->_whitelist = $whitelist;
+ }
+
+ /**
+ * Set the recipient of all messages.
+ *
+ * @param mixed $recipient
+ */
+ public function setRecipient($recipient)
+ {
+ $this->_recipient = $recipient;
+ }
+
+ /**
+ * Get the recipient of all messages.
+ *
+ * @return mixed
+ */
+ public function getRecipient()
+ {
+ return $this->_recipient;
+ }
+
+ /**
+ * Set a list of regular expressions to whitelist certain recipients
+ *
+ * @param array $whitelist
+ */
+ public function setWhitelist(array $whitelist)
+ {
+ $this->_whitelist = $whitelist;
+ }
+
+ /**
+ * Get the whitelist
+ *
+ * @return array
+ */
+ public function getWhitelist()
+ {
+ return $this->_whitelist;
+ }
+
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $message = $evt->getMessage();
+ $headers = $message->getHeaders();
+
+ // conditionally save current recipients
+
+ if ($headers->has('to')) {
+ $headers->addMailboxHeader('X-Swift-To', $message->getTo());
+ }
+
+ if ($headers->has('cc')) {
+ $headers->addMailboxHeader('X-Swift-Cc', $message->getCc());
+ }
+
+ if ($headers->has('bcc')) {
+ $headers->addMailboxHeader('X-Swift-Bcc', $message->getBcc());
+ }
+
+ // Filter remaining headers against whitelist
+ $this->_filterHeaderSet($headers, 'To');
+ $this->_filterHeaderSet($headers, 'Cc');
+ $this->_filterHeaderSet($headers, 'Bcc');
+
+ // Add each hard coded recipient
+ foreach ( (array) $this->_recipient as $recipient) {
+ if (!array_key_exists($recipient, $message->getTo())) {
+ $message->addTo($recipient);
+ }
+ }
+
+ }
+
+ /**
+ * Filter header set against a whitelist of regular expressions
+ *
+ * @param Swift_Mime_HeaderSet $headerSet
+ * @param string $type
+ */
+ private function _filterHeaderSet(Swift_Mime_HeaderSet $headerSet, $type)
+ {
+ foreach ($headerSet->getAll($type) as $headers) {
+ $headers->setNameAddresses($this->_filterNameAddresses($headers->getNameAddresses()));
+ }
+ }
+
+ /**
+ * Filtered list of addresses => name pairs
+ *
+ * @param array $recipients
+ * @return array
+ */
+ private function _filterNameAddresses(array $recipients)
+ {
+ $filtered = array();
+
+ foreach ($recipients as $address => $name) {
+ if ($this->_isWhitelisted($address)) {
+ $filtered[$address] = $name;
+ }
+ }
+
+ return $filtered;
+ }
+
+ /**
+ * Matches address against whitelist of regular expressions
+ *
+ * @param $recipient
+ * @return bool
+ */
+ protected function _isWhitelisted($recipient)
+ {
+ if (in_array($recipient, (array) $this->_recipient)) {
+ return true;
+ }
+
+ foreach ($this->_whitelist as $pattern) {
+ if (preg_match($pattern, $recipient)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $this->_restoreMessage($evt->getMessage());
+ }
+
+ private function _restoreMessage(Swift_Mime_Message $message)
+ {
+ // restore original headers
+ $headers = $message->getHeaders();
+
+ if ($headers->has('X-Swift-To')) {
+ $message->setTo($headers->get('X-Swift-To')->getNameAddresses());
+ $headers->removeAll('X-Swift-To');
+ }
+
+ if ($headers->has('X-Swift-Cc')) {
+ $message->setCc($headers->get('X-Swift-Cc')->getNameAddresses());
+ $headers->removeAll('X-Swift-Cc');
+ }
+
+ if ($headers->has('X-Swift-Bcc')) {
+ $message->setBcc($headers->get('X-Swift-Bcc')->getNameAddresses());
+ $headers->removeAll('X-Swift-Bcc');
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/Reporter.php b/vendor/swiftmailer/classes/Swift/Plugins/Reporter.php
new file mode 100644
index 00000000..294b547d
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/Reporter.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * The Reporter plugin sends pass/fail notification to a Reporter.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Plugins_Reporter
+{
+ /** The recipient was accepted for delivery */
+ const RESULT_PASS = 0x01;
+
+ /** The recipient could not be accepted */
+ const RESULT_FAIL = 0x10;
+
+ /**
+ * Notifies this ReportNotifier that $address failed or succeeded.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string $address
+ * @param int $result from {@link RESULT_PASS, RESULT_FAIL}
+ */
+ public function notify(Swift_Mime_Message $message, $address, $result);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/ReporterPlugin.php b/vendor/swiftmailer/classes/Swift/Plugins/ReporterPlugin.php
new file mode 100644
index 00000000..45294533
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/ReporterPlugin.php
@@ -0,0 +1,73 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Does real time reporting of pass/fail for each recipient.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Plugins_ReporterPlugin implements Swift_Events_SendListener
+{
+ /**
+ * The reporter backend which takes notifications.
+ *
+ * @var Swift_Plugins_Reporter
+ */
+ private $_reporter;
+
+ /**
+ * Create a new ReporterPlugin using $reporter.
+ *
+ * @param Swift_Plugins_Reporter $reporter
+ */
+ public function __construct(Swift_Plugins_Reporter $reporter)
+ {
+ $this->_reporter = $reporter;
+ }
+
+ /**
+ * Not used.
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ }
+
+ /**
+ * Invoked immediately after the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $message = $evt->getMessage();
+ $failures = array_flip($evt->getFailedRecipients());
+ foreach ((array) $message->getTo() as $address => $null) {
+ $this->_reporter->notify(
+ $message, $address, (array_key_exists($address, $failures)
+ ? Swift_Plugins_Reporter::RESULT_FAIL
+ : Swift_Plugins_Reporter::RESULT_PASS)
+ );
+ }
+ foreach ((array) $message->getCc() as $address => $null) {
+ $this->_reporter->notify(
+ $message, $address, (array_key_exists($address, $failures)
+ ? Swift_Plugins_Reporter::RESULT_FAIL
+ : Swift_Plugins_Reporter::RESULT_PASS)
+ );
+ }
+ foreach ((array) $message->getBcc() as $address => $null) {
+ $this->_reporter->notify(
+ $message, $address, (array_key_exists($address, $failures)
+ ? Swift_Plugins_Reporter::RESULT_FAIL
+ : Swift_Plugins_Reporter::RESULT_PASS)
+ );
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/Reporters/HitReporter.php b/vendor/swiftmailer/classes/Swift/Plugins/Reporters/HitReporter.php
new file mode 100644
index 00000000..ea60f51d
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/Reporters/HitReporter.php
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A reporter which "collects" failures for the Reporter plugin.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Plugins_Reporters_HitReporter implements Swift_Plugins_Reporter
+{
+ /**
+ * The list of failures.
+ *
+ * @var array
+ */
+ private $_failures = array();
+
+ private $_failures_cache = array();
+
+ /**
+ * Notifies this ReportNotifier that $address failed or succeeded.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string $address
+ * @param int $result from {@link RESULT_PASS, RESULT_FAIL}
+ */
+ public function notify(Swift_Mime_Message $message, $address, $result)
+ {
+ if (self::RESULT_FAIL == $result && !isset($this->_failures_cache[$address])) {
+ $this->_failures[] = $address;
+ $this->_failures_cache[$address] = true;
+ }
+ }
+
+ /**
+ * Get an array of addresses for which delivery failed.
+ *
+ * @return array
+ */
+ public function getFailedRecipients()
+ {
+ return $this->_failures;
+ }
+
+ /**
+ * Clear the buffer (empty the list).
+ */
+ public function clear()
+ {
+ $this->_failures = $this->_failures_cache = array();
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/Reporters/HtmlReporter.php b/vendor/swiftmailer/classes/Swift/Plugins/Reporters/HtmlReporter.php
new file mode 100644
index 00000000..4480d255
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/Reporters/HtmlReporter.php
@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A HTML output reporter for the Reporter plugin.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Plugins_Reporters_HtmlReporter implements Swift_Plugins_Reporter
+{
+ /**
+ * Notifies this ReportNotifier that $address failed or succeeded.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string $address
+ * @param int $result from {@see RESULT_PASS, RESULT_FAIL}
+ */
+ public function notify(Swift_Mime_Message $message, $address, $result)
+ {
+ if (self::RESULT_PASS == $result) {
+ echo "<div style=\"color: #fff; background: #006600; padding: 2px; margin: 2px;\">" . PHP_EOL;
+ echo "PASS " . $address . PHP_EOL;
+ echo "</div>" . PHP_EOL;
+ flush();
+ } else {
+ echo "<div style=\"color: #fff; background: #880000; padding: 2px; margin: 2px;\">" . PHP_EOL;
+ echo "FAIL " . $address . PHP_EOL;
+ echo "</div>" . PHP_EOL;
+ flush();
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/Sleeper.php b/vendor/swiftmailer/classes/Swift/Plugins/Sleeper.php
new file mode 100644
index 00000000..38727052
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/Sleeper.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Sleeps for a duration of time.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Plugins_Sleeper
+{
+ /**
+ * Sleep for $seconds.
+ *
+ * @param int $seconds
+ */
+ public function sleep($seconds);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/ThrottlerPlugin.php b/vendor/swiftmailer/classes/Swift/Plugins/ThrottlerPlugin.php
new file mode 100644
index 00000000..0d2c135e
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/ThrottlerPlugin.php
@@ -0,0 +1,200 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Throttles the rate at which emails are sent.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Plugins_ThrottlerPlugin extends Swift_Plugins_BandwidthMonitorPlugin implements Swift_Plugins_Sleeper, Swift_Plugins_Timer
+{
+ /** Flag for throttling in bytes per minute */
+ const BYTES_PER_MINUTE = 0x01;
+
+ /** Flag for throttling in emails per second (Amazon SES) */
+ const MESSAGES_PER_SECOND = 0x11;
+
+ /** Flag for throttling in emails per minute */
+ const MESSAGES_PER_MINUTE = 0x10;
+
+ /**
+ * The Sleeper instance for sleeping.
+ *
+ * @var Swift_Plugins_Sleeper
+ */
+ private $_sleeper;
+
+ /**
+ * The Timer instance which provides the timestamp.
+ *
+ * @var Swift_Plugins_Timer
+ */
+ private $_timer;
+
+ /**
+ * The time at which the first email was sent.
+ *
+ * @var int
+ */
+ private $_start;
+
+ /**
+ * The rate at which messages should be sent.
+ *
+ * @var int
+ */
+ private $_rate;
+
+ /**
+ * The mode for throttling.
+ *
+ * This is {@link BYTES_PER_MINUTE} or {@link MESSAGES_PER_MINUTE}
+ *
+ * @var int
+ */
+ private $_mode;
+
+ /**
+ * An internal counter of the number of messages sent.
+ *
+ * @var int
+ */
+ private $_messages = 0;
+
+ /**
+ * Create a new ThrottlerPlugin.
+ *
+ * @param int $rate
+ * @param int $mode, defaults to {@link BYTES_PER_MINUTE}
+ * @param Swift_Plugins_Sleeper $sleeper (only needed in testing)
+ * @param Swift_Plugins_Timer $timer (only needed in testing)
+ */
+ public function __construct($rate, $mode = self::BYTES_PER_MINUTE, Swift_Plugins_Sleeper $sleeper = null, Swift_Plugins_Timer $timer = null)
+ {
+ $this->_rate = $rate;
+ $this->_mode = $mode;
+ $this->_sleeper = $sleeper;
+ $this->_timer = $timer;
+ }
+
+ /**
+ * Invoked immediately before the Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function beforeSendPerformed(Swift_Events_SendEvent $evt)
+ {
+ $time = $this->getTimestamp();
+ if (!isset($this->_start)) {
+ $this->_start = $time;
+ }
+ $duration = $time - $this->_start;
+
+ switch ($this->_mode) {
+ case self::BYTES_PER_MINUTE :
+ $sleep = $this->_throttleBytesPerMinute($duration);
+ break;
+ case self::MESSAGES_PER_SECOND :
+ $sleep = $this->_throttleMessagesPerSecond($duration);
+ break;
+ case self::MESSAGES_PER_MINUTE :
+ $sleep = $this->_throttleMessagesPerMinute($duration);
+ break;
+ default :
+ $sleep = 0;
+ break;
+ }
+
+ if ($sleep > 0) {
+ $this->sleep($sleep);
+ }
+ }
+
+ /**
+ * Invoked when a Message is sent.
+ *
+ * @param Swift_Events_SendEvent $evt
+ */
+ public function sendPerformed(Swift_Events_SendEvent $evt)
+ {
+ parent::sendPerformed($evt);
+ ++$this->_messages;
+ }
+
+ /**
+ * Sleep for $seconds.
+ *
+ * @param int $seconds
+ */
+ public function sleep($seconds)
+ {
+ if (isset($this->_sleeper)) {
+ $this->_sleeper->sleep($seconds);
+ } else {
+ sleep($seconds);
+ }
+ }
+
+ /**
+ * Get the current UNIX timestamp.
+ *
+ * @return int
+ */
+ public function getTimestamp()
+ {
+ if (isset($this->_timer)) {
+ return $this->_timer->getTimestamp();
+ } else {
+ return time();
+ }
+ }
+
+ /**
+ * Get a number of seconds to sleep for.
+ *
+ * @param int $timePassed
+ *
+ * @return int
+ */
+ private function _throttleBytesPerMinute($timePassed)
+ {
+ $expectedDuration = $this->getBytesOut() / ($this->_rate / 60);
+
+ return (int) ceil($expectedDuration - $timePassed);
+ }
+
+ /**
+ * Get a number of seconds to sleep for.
+ *
+ * @param int $timePassed
+ *
+ * @return int
+ */
+ private function _throttleMessagesPerSecond($timePassed)
+ {
+ $expectedDuration = $this->_messages / ($this->_rate);
+
+ return (int) ceil($expectedDuration - $timePassed);
+ }
+
+ /**
+ * Get a number of seconds to sleep for.
+ *
+ * @param int $timePassed
+ *
+ * @return int
+ */
+ private function _throttleMessagesPerMinute($timePassed)
+ {
+ $expectedDuration = $this->_messages / ($this->_rate / 60);
+
+ return (int) ceil($expectedDuration - $timePassed);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Plugins/Timer.php b/vendor/swiftmailer/classes/Swift/Plugins/Timer.php
new file mode 100644
index 00000000..a05e3181
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Plugins/Timer.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Provides timestamp data.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Plugins_Timer
+{
+ /**
+ * Get the current UNIX timestamp.
+ *
+ * @return int
+ */
+ public function getTimestamp();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Preferences.php b/vendor/swiftmailer/classes/Swift/Preferences.php
new file mode 100644
index 00000000..7cd61312
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Preferences.php
@@ -0,0 +1,103 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Changes some global preference settings in Swift Mailer.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Preferences
+{
+ /** Singleton instance */
+ private static $_instance = null;
+
+ /** Constructor not to be used */
+ private function __construct()
+ {
+ }
+
+ /**
+ * Gets the instance of Preferences.
+ *
+ * @return Swift_Preferences
+ */
+ public static function getInstance()
+ {
+ if (!isset(self::$_instance)) {
+ self::$_instance = new self();
+ }
+
+ return self::$_instance;
+ }
+
+ /**
+ * Set the default charset used.
+ *
+ * @param string $charset
+ *
+ * @return Swift_Preferences
+ */
+ public function setCharset($charset)
+ {
+ Swift_DependencyContainer::getInstance()
+ ->register('properties.charset')->asValue($charset);
+
+ return $this;
+ }
+
+ /**
+ * Set the directory where temporary files can be saved.
+ *
+ * @param string $dir
+ *
+ * @return Swift_Preferences
+ */
+ public function setTempDir($dir)
+ {
+ Swift_DependencyContainer::getInstance()
+ ->register('tempdir')->asValue($dir);
+
+ return $this;
+ }
+
+ /**
+ * Set the type of cache to use (i.e. "disk" or "array").
+ *
+ * @param string $type
+ *
+ * @return Swift_Preferences
+ */
+ public function setCacheType($type)
+ {
+ Swift_DependencyContainer::getInstance()
+ ->register('cache')->asAliasOf(sprintf('cache.%s', $type));
+
+ return $this;
+ }
+
+ /**
+ * Set the QuotedPrintable dot escaper preference.
+ *
+ * @param bool $dotEscape
+ *
+ * @return Swift_Preferences
+ */
+ public function setQPDotEscape($dotEscape)
+ {
+ $dotEscape = !empty($dotEscape);
+ Swift_DependencyContainer::getInstance()
+ ->register('mime.qpcontentencoder')
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder')
+ ->withDependencies(array('mime.charstream', 'mime.bytecanonicalizer'))
+ ->addConstructorValue($dotEscape);
+
+ return $this;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/ReplacementFilterFactory.php b/vendor/swiftmailer/classes/Swift/ReplacementFilterFactory.php
new file mode 100644
index 00000000..ca9e4f60
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/ReplacementFilterFactory.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Creates StreamFilters.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_ReplacementFilterFactory
+{
+ /**
+ * Create a filter to replace $search with $replace.
+ *
+ * @param mixed $search
+ * @param mixed $replace
+ *
+ * @return Swift_StreamFilter
+ */
+ public function createFilter($search, $replace);
+}
diff --git a/vendor/swiftmailer/classes/Swift/RfcComplianceException.php b/vendor/swiftmailer/classes/Swift/RfcComplianceException.php
new file mode 100644
index 00000000..cdb2bee2
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/RfcComplianceException.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * RFC Compliance Exception class.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_RfcComplianceException extends Swift_SwiftException
+{
+ /**
+ * Create a new RfcComplianceException with $message.
+ *
+ * @param string $message
+ */
+ public function __construct($message)
+ {
+ parent::__construct($message);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/SendmailTransport.php b/vendor/swiftmailer/classes/Swift/SendmailTransport.php
new file mode 100644
index 00000000..1ef0e5e1
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/SendmailTransport.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * SendmailTransport for sending mail through a Sendmail/Postfix (etc..) binary.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_SendmailTransport extends Swift_Transport_SendmailTransport
+{
+ /**
+ * Create a new SendmailTransport, optionally using $command for sending.
+ *
+ * @param string $command
+ */
+ public function __construct($command = '/usr/sbin/sendmail -bs')
+ {
+ call_user_func_array(
+ array($this, 'Swift_Transport_SendmailTransport::__construct'),
+ Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('transport.sendmail')
+ );
+
+ $this->setCommand($command);
+ }
+
+ /**
+ * Create a new SendmailTransport instance.
+ *
+ * @param string $command
+ *
+ * @return Swift_SendmailTransport
+ */
+ public static function newInstance($command = '/usr/sbin/sendmail -bs')
+ {
+ return new self($command);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/SignedMessage.php b/vendor/swiftmailer/classes/Swift/SignedMessage.php
new file mode 100644
index 00000000..9aef721b
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/SignedMessage.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Signed Message, message that can be signed using a signer.
+ *
+ * This class is only kept for compatibility
+ *
+ *
+ * @author Xavier De Cock <xdecock@gmail.com>
+ * @deprecated
+ */
+class Swift_SignedMessage extends Swift_Message
+{
+
+}
diff --git a/vendor/swiftmailer/classes/Swift/Signer.php b/vendor/swiftmailer/classes/Swift/Signer.php
new file mode 100644
index 00000000..7448179f
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Signer.php
@@ -0,0 +1,20 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Base Class of Signer Infrastructure.
+ *
+ *
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+interface Swift_Signer
+{
+ public function reset();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Signers/BodySigner.php b/vendor/swiftmailer/classes/Swift/Signers/BodySigner.php
new file mode 100644
index 00000000..93dc8ac7
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Signers/BodySigner.php
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Body Signer Interface used to apply Body-Based Signature to a message
+ *
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+interface Swift_Signers_BodySigner extends Swift_Signer
+{
+ /**
+ * Change the Swift_Signed_Message to apply the singing.
+ *
+ * @param Swift_Message $message
+ *
+ * @return Swift_Signers_BodySigner
+ */
+ public function signMessage(Swift_Message $message);
+
+ /**
+ * Return the list of header a signer might tamper
+ *
+ * @return array
+ */
+ public function getAlteredHeaders();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Signers/DKIMSigner.php b/vendor/swiftmailer/classes/Swift/Signers/DKIMSigner.php
new file mode 100644
index 00000000..7e3f215f
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Signers/DKIMSigner.php
@@ -0,0 +1,689 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * DKIM Signer used to apply DKIM Signature to a message
+ *
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+class Swift_Signers_DKIMSigner implements Swift_Signers_HeaderSigner
+{
+ /**
+ * PrivateKey
+ *
+ * @var string
+ */
+ protected $_privateKey;
+
+ /**
+ * DomainName
+ *
+ * @var string
+ */
+ protected $_domainName;
+
+ /**
+ * Selector
+ *
+ * @var string
+ */
+ protected $_selector;
+
+ /**
+ * Hash algorithm used
+ *
+ * @var string
+ */
+ protected $_hashAlgorithm = 'rsa-sha1';
+
+ /**
+ * Body canon method
+ *
+ * @var string
+ */
+ protected $_bodyCanon = 'simple';
+
+ /**
+ * Header canon method
+ *
+ * @var string
+ */
+ protected $_headerCanon = 'simple';
+
+ /**
+ * Headers not being signed
+ *
+ * @var array
+ */
+ protected $_ignoredHeaders = array();
+
+ /**
+ * Signer identity
+ *
+ * @var unknown_type
+ */
+ protected $_signerIdentity;
+
+ /**
+ * BodyLength
+ *
+ * @var int
+ */
+ protected $_bodyLen = 0;
+
+ /**
+ * Maximum signedLen
+ *
+ * @var int
+ */
+ protected $_maxLen = PHP_INT_MAX;
+
+ /**
+ * Embbed bodyLen in signature
+ *
+ * @var bool
+ */
+ protected $_showLen = false;
+
+ /**
+ * When the signature has been applied (true means time()), false means not embedded
+ *
+ * @var mixed
+ */
+ protected $_signatureTimestamp = true;
+
+ /**
+ * When will the signature expires false means not embedded, if sigTimestamp is auto
+ * Expiration is relative, otherwhise it's absolute
+ *
+ * @var int
+ */
+ protected $_signatureExpiration = false;
+
+ /**
+ * Must we embed signed headers?
+ *
+ * @var bool
+ */
+ protected $_debugHeaders = false;
+
+ // work variables
+ /**
+ * Headers used to generate hash
+ *
+ * @var array
+ */
+ protected $_signedHeaders = array();
+
+ /**
+ * If debugHeaders is set store debugDatas here
+ *
+ * @var string
+ */
+ private $_debugHeadersData = '';
+
+ /**
+ * Stores the bodyHash
+ *
+ * @var string
+ */
+ private $_bodyHash = '';
+
+ /**
+ * Stores the signature header
+ *
+ * @var Swift_Mime_Headers_ParameterizedHeader
+ */
+ protected $_dkimHeader;
+
+ /**
+ * Hash Handler
+ *
+ * @var hash_ressource
+ */
+ private $_headerHashHandler;
+
+ private $_bodyHashHandler;
+
+ private $_headerHash;
+
+ private $_headerCanonData = '';
+
+ private $_bodyCanonEmptyCounter = 0;
+
+ private $_bodyCanonIgnoreStart = 2;
+
+ private $_bodyCanonSpace = false;
+
+ private $_bodyCanonLastChar = null;
+
+ private $_bodyCanonLine = '';
+
+ private $_bound = array();
+
+ /**
+ * Constructor
+ *
+ * @param string $privateKey
+ * @param string $domainName
+ * @param string $selector
+ */
+ public function __construct($privateKey, $domainName, $selector)
+ {
+ $this->_privateKey = $privateKey;
+ $this->_domainName = $domainName;
+ $this->_signerIdentity = '@' . $domainName;
+ $this->_selector = $selector;
+ }
+
+ /**
+ * Instanciate DKIMSigner
+ *
+ * @param string $privateKey
+ * @param string $domainName
+ * @param string $selector
+ * @return Swift_Signers_DKIMSigner
+ */
+ public static function newInstance($privateKey, $domainName, $selector)
+ {
+ return new static($privateKey, $domainName, $selector);
+ }
+
+
+ /**
+ * Reset the Signer
+ * @see Swift_Signer::reset()
+ */
+ public function reset()
+ {
+ $this->_headerHash = null;
+ $this->_signedHeaders = array();
+ $this->_headerHashHandler = null;
+ $this->_bodyHash = null;
+ $this->_bodyHashHandler = null;
+ $this->_bodyCanonIgnoreStart = 2;
+ $this->_bodyCanonEmptyCounter = 0;
+ $this->_bodyCanonLastChar = null;
+ $this->_bodyCanonSpace = false;
+ }
+
+ /**
+ * Writes $bytes to the end of the stream.
+ *
+ * Writing may not happen immediately if the stream chooses to buffer. If
+ * you want to write these bytes with immediate effect, call {@link commit()}
+ * after calling write().
+ *
+ * This method returns the sequence ID of the write (i.e. 1 for first, 2 for
+ * second, etc etc).
+ *
+ * @param string $bytes
+ * @return int
+ * @throws Swift_IoException
+ */
+ public function write($bytes)
+ {
+ $this->_canonicalizeBody($bytes);
+ foreach ($this->_bound as $is) {
+ $is->write($bytes);
+ }
+ }
+
+ /**
+ * For any bytes that are currently buffered inside the stream, force them
+ * off the buffer.
+ *
+ * @throws Swift_IoException
+ */
+ public function commit()
+ {
+ // Nothing to do
+ return;
+ }
+
+ /**
+ * Attach $is to this stream.
+ * The stream acts as an observer, receiving all data that is written.
+ * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function bind(Swift_InputByteStream $is)
+ {
+ // Don't have to mirror anything
+ $this->_bound[] = $is;
+
+ return;
+ }
+
+ /**
+ * Remove an already bound stream.
+ * If $is is not bound, no errors will be raised.
+ * If the stream currently has any buffered data it will be written to $is
+ * before unbinding occurs.
+ *
+ * @param Swift_InputByteStream $is
+ */
+ public function unbind(Swift_InputByteStream $is)
+ {
+ // Don't have to mirror anything
+ foreach ($this->_bound as $k => $stream) {
+ if ($stream === $is) {
+ unset($this->_bound[$k]);
+
+ return;
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * Flush the contents of the stream (empty it) and set the internal pointer
+ * to the beginning.
+ *
+ * @throws Swift_IoException
+ */
+ public function flushBuffers()
+ {
+ $this->reset();
+ }
+
+ /**
+ * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1 defaults to rsa-sha256
+ *
+ * @param string $hash
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setHashAlgorithm($hash)
+ {
+ // Unable to sign with rsa-sha256
+ if ($hash == 'rsa-sha1') {
+ $this->_hashAlgorithm = 'rsa-sha1';
+ } else {
+ $this->_hashAlgorithm = 'rsa-sha256';
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the body canonicalization algorithm
+ *
+ * @param string $canon
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setBodyCanon($canon)
+ {
+ if ($canon == 'relaxed') {
+ $this->_bodyCanon = 'relaxed';
+ } else {
+ $this->_bodyCanon = 'simple';
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the header canonicalization algorithm
+ *
+ * @param string $canon
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setHeaderCanon($canon)
+ {
+ if ($canon == 'relaxed') {
+ $this->_headerCanon = 'relaxed';
+ } else {
+ $this->_headerCanon = 'simple';
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the signer identity
+ *
+ * @param string $identity
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setSignerIdentity($identity)
+ {
+ $this->_signerIdentity = $identity;
+
+ return $this;
+ }
+
+ /**
+ * Set the length of the body to sign
+ *
+ * @param mixed $len (bool or int)
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setBodySignedLen($len)
+ {
+ if ($len === true) {
+ $this->_showLen = true;
+ $this->_maxLen = PHP_INT_MAX;
+ } elseif ($len === false) {
+ $this->showLen = false;
+ $this->_maxLen = PHP_INT_MAX;
+ } else {
+ $this->_showLen = true;
+ $this->_maxLen = (int) $len;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the signature timestamp
+ *
+ * @param timestamp $time
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setSignatureTimestamp($time)
+ {
+ $this->_signatureTimestamp = $time;
+
+ return $this;
+ }
+
+ /**
+ * Set the signature expiration timestamp
+ *
+ * @param timestamp $time
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setSignatureExpiration($time)
+ {
+ $this->_signatureExpiration = $time;
+
+ return $this;
+ }
+
+ /**
+ * Enable / disable the DebugHeaders
+ *
+ * @param bool $debug
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setDebugHeaders($debug)
+ {
+ $this->_debugHeaders = (bool) $debug;
+
+ return $this;
+ }
+
+ /**
+ * Start Body
+ *
+ */
+ public function startBody()
+ {
+ // Init
+ switch ($this->_hashAlgorithm) {
+ case 'rsa-sha256' :
+ $this->_bodyHashHandler = hash_init('sha256');
+ break;
+ case 'rsa-sha1' :
+ $this->_bodyHashHandler = hash_init('sha1');
+ break;
+ }
+ $this->_bodyCanonLine = '';
+ }
+
+ /**
+ * End Body
+ *
+ */
+ public function endBody()
+ {
+ $this->_endOfBody();
+ }
+
+ /**
+ * Returns the list of Headers Tampered by this plugin
+ *
+ * @return array
+ */
+ public function getAlteredHeaders()
+ {
+ if ($this->_debugHeaders) {
+ return array('DKIM-Signature', 'X-DebugHash');
+ } else {
+ return array('DKIM-Signature');
+ }
+ }
+
+ /**
+ * Adds an ignored Header
+ *
+ * @param string $header_name
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function ignoreHeader($header_name)
+ {
+ $this->_ignoredHeaders[strtolower($header_name)] = true;
+
+ return $this;
+ }
+
+ /**
+ * Set the headers to sign
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setHeaders(Swift_Mime_HeaderSet $headers)
+ {
+ $this->_headerCanonData = '';
+ // Loop through Headers
+ $listHeaders = $headers->listAll();
+ foreach ($listHeaders as $hName) {
+ // Check if we need to ignore Header
+ if (! isset($this->_ignoredHeaders[strtolower($hName)])) {
+ if ($headers->has($hName)) {
+ $tmp = $headers->getAll($hName);
+ foreach ($tmp as $header) {
+ if ($header->getFieldBody() != '') {
+ $this->_addHeader($header->toString());
+ $this->_signedHeaders[] = $header->getFieldName();
+ }
+ }
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add the signature to the given Headers
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function addSignature(Swift_Mime_HeaderSet $headers)
+ {
+ // Prepare the DKIM-Signature
+ $params = array('v' => '1', 'a' => $this->_hashAlgorithm, 'bh' => base64_encode($this->_bodyHash), 'd' => $this->_domainName, 'h' => implode(': ', $this->_signedHeaders), 'i' => $this->_signerIdentity, 's' => $this->_selector);
+ if ($this->_bodyCanon != 'simple') {
+ $params['c'] = $this->_headerCanon . '/' . $this->_bodyCanon;
+ } elseif ($this->_headerCanon != 'simple') {
+ $params['c'] = $this->_headerCanon;
+ }
+ if ($this->_showLen) {
+ $params['l'] = $this->_bodyLen;
+ }
+ if ($this->_signatureTimestamp === true) {
+ $params['t'] = time();
+ if ($this->_signatureExpiration !== false) {
+ $params['x'] = $params['t'] + $this->_signatureExpiration;
+ }
+ } else {
+ if ($this->_signatureTimestamp !== false) {
+ $params['t'] = $this->_signatureTimestamp;
+ }
+ if ($this->_signatureExpiration !== false) {
+ $params['x'] = $this->_signatureExpiration;
+ }
+ }
+ if ($this->_debugHeaders) {
+ $params['z'] = implode('|', $this->_debugHeadersData);
+ }
+ $string = '';
+ foreach ($params as $k => $v) {
+ $string .= $k . '=' . $v . '; ';
+ }
+ $string = trim($string);
+ $headers->addTextHeader('DKIM-Signature', $string);
+ // Add the last DKIM-Signature
+ $tmp = $headers->getAll('DKIM-Signature');
+ $this->_dkimHeader = end($tmp);
+ $this->_addHeader(trim($this->_dkimHeader->toString()) . "\r\n b=", true);
+ $this->_endOfHeaders();
+ if ($this->_debugHeaders) {
+ $headers->addTextHeader('X-DebugHash', base64_encode($this->_headerHash));
+ }
+ $this->_dkimHeader->setValue($string . " b=" . trim(chunk_split(base64_encode($this->_getEncryptedHash()), 73, " ")));
+
+ return $this;
+ }
+
+ /* Private helpers */
+
+ protected function _addHeader($header, $is_sig = false)
+ {
+ switch ($this->_headerCanon) {
+ case 'relaxed' :
+ // Prepare Header and cascade
+ $exploded = explode(':', $header, 2);
+ $name = strtolower(trim($exploded[0]));
+ $value = str_replace("\r\n", "", $exploded[1]);
+ $value = preg_replace("/[ \t][ \t]+/", " ", $value);
+ $header = $name . ":" . trim($value) . ($is_sig ? '' : "\r\n");
+ case 'simple' :
+ // Nothing to do
+ }
+ $this->_addToHeaderHash($header);
+ }
+
+ protected function _endOfHeaders()
+ {
+ //$this->_headerHash=hash_final($this->_headerHashHandler, true);
+ }
+
+ protected function _canonicalizeBody($string)
+ {
+ $len = strlen($string);
+ $canon = '';
+ $method = ($this->_bodyCanon == "relaxed");
+ for ($i = 0; $i < $len; ++$i) {
+ if ($this->_bodyCanonIgnoreStart > 0) {
+ --$this->_bodyCanonIgnoreStart;
+ continue;
+ }
+ switch ($string[$i]) {
+ case "\r" :
+ $this->_bodyCanonLastChar = "\r";
+ break;
+ case "\n" :
+ if ($this->_bodyCanonLastChar == "\r") {
+ if ($method) {
+ $this->_bodyCanonSpace = false;
+ }
+ if ($this->_bodyCanonLine == '') {
+ ++$this->_bodyCanonEmptyCounter;
+ } else {
+ $this->_bodyCanonLine = '';
+ $canon .= "\r\n";
+ }
+ } else {
+ // Wooops Error
+ // todo handle it but should never happen
+ }
+ break;
+ case " " :
+ case "\t" :
+ if ($method) {
+ $this->_bodyCanonSpace = true;
+ break;
+ }
+ default :
+ if ($this->_bodyCanonEmptyCounter > 0) {
+ $canon .= str_repeat("\r\n", $this->_bodyCanonEmptyCounter);
+ $this->_bodyCanonEmptyCounter = 0;
+ }
+ if ($this->_bodyCanonSpace) {
+ $this->_bodyCanonLine .= ' ';
+ $canon .= ' ';
+ $this->_bodyCanonSpace = false;
+ }
+ $this->_bodyCanonLine .= $string[$i];
+ $canon .= $string[$i];
+ }
+ }
+ $this->_addToBodyHash($canon);
+ }
+
+ protected function _endOfBody()
+ {
+ // Add trailing Line return if last line is non empty
+ if (strlen($this->_bodyCanonLine) > 0) {
+ $this->_addToBodyHash("\r\n");
+ }
+ $this->_bodyHash = hash_final($this->_bodyHashHandler, true);
+ }
+
+ private function _addToBodyHash($string)
+ {
+ $len = strlen($string);
+ if ($len > ($new_len = ($this->_maxLen - $this->_bodyLen))) {
+ $string = substr($string, 0, $new_len);
+ $len = $new_len;
+ }
+ hash_update($this->_bodyHashHandler, $string);
+ $this->_bodyLen += $len;
+ }
+
+ private function _addToHeaderHash($header)
+ {
+ if ($this->_debugHeaders) {
+ $this->_debugHeadersData[] = trim($header);
+ }
+ $this->_headerCanonData .= $header;
+ }
+
+ /**
+ * @throws Swift_SwiftException
+ * @return string
+ */
+ private function _getEncryptedHash()
+ {
+ $signature = '';
+ switch ($this->_hashAlgorithm) {
+ case 'rsa-sha1':
+ $algorithm = OPENSSL_ALGO_SHA1;
+ break;
+ case 'rsa-sha256':
+ $algorithm = OPENSSL_ALGO_SHA256;
+ break;
+ }
+ $pkeyId=openssl_get_privatekey($this->_privateKey);
+ if (!$pkeyId) {
+ throw new Swift_SwiftException('Unable to load DKIM Private Key ['.openssl_error_string().']');
+ }
+ if (openssl_sign($this->_headerCanonData, $signature, $pkeyId, $algorithm)) {
+ return $signature;
+ }
+ throw new Swift_SwiftException('Unable to sign DKIM Hash ['.openssl_error_string().']');
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Signers/DomainKeySigner.php b/vendor/swiftmailer/classes/Swift/Signers/DomainKeySigner.php
new file mode 100644
index 00000000..07be7cd7
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Signers/DomainKeySigner.php
@@ -0,0 +1,512 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * DomainKey Signer used to apply DomainKeys Signature to a message
+ *
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+class Swift_Signers_DomainKeySigner implements Swift_Signers_HeaderSigner
+{
+ /**
+ * PrivateKey
+ *
+ * @var string
+ */
+ protected $_privateKey;
+
+ /**
+ * DomainName
+ *
+ * @var string
+ */
+ protected $_domainName;
+
+ /**
+ * Selector
+ *
+ * @var string
+ */
+ protected $_selector;
+
+ /**
+ * Hash algorithm used
+ *
+ * @var string
+ */
+ protected $_hashAlgorithm = 'rsa-sha1';
+
+ /**
+ * Canonisation method
+ *
+ * @var string
+ */
+ protected $_canon = 'simple';
+
+ /**
+ * Headers not being signed
+ *
+ * @var array
+ */
+ protected $_ignoredHeaders = array();
+
+ /**
+ * Signer identity
+ *
+ * @var string
+ */
+ protected $_signerIdentity;
+
+ /**
+ * Must we embed signed headers?
+ *
+ * @var bool
+ */
+ protected $_debugHeaders = false;
+
+ // work variables
+ /**
+ * Headers used to generate hash
+ *
+ * @var array
+ */
+ private $_signedHeaders = array();
+
+ /**
+ * Stores the signature header
+ *
+ * @var Swift_Mime_Headers_ParameterizedHeader
+ */
+ protected $_domainKeyHeader;
+
+ /**
+ * Hash Handler
+ *
+ * @var resource|null
+ */
+ private $_hashHandler;
+
+ private $_hash;
+
+ private $_canonData = '';
+
+ private $_bodyCanonEmptyCounter = 0;
+
+ private $_bodyCanonIgnoreStart = 2;
+
+ private $_bodyCanonSpace = false;
+
+ private $_bodyCanonLastChar = null;
+
+ private $_bodyCanonLine = '';
+
+ private $_bound = array();
+
+ /**
+ * Constructor
+ *
+ * @param string $privateKey
+ * @param string $domainName
+ * @param string $selector
+ */
+ public function __construct($privateKey, $domainName, $selector)
+ {
+ $this->_privateKey = $privateKey;
+ $this->_domainName = $domainName;
+ $this->_signerIdentity = '@' . $domainName;
+ $this->_selector = $selector;
+ }
+
+ /**
+ * Instanciate DomainKeySigner
+ *
+ * @param string $privateKey
+ * @param string $domainName
+ * @param string $selector
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public static function newInstance($privateKey, $domainName, $selector)
+ {
+ return new static($privateKey, $domainName, $selector);
+ }
+
+ /**
+ * Resets internal states
+ *
+ * @return Swift_Signers_DomainKeysSigner
+ */
+ public function reset()
+ {
+ $this->_hash = null;
+ $this->_hashHandler = null;
+ $this->_bodyCanonIgnoreStart = 2;
+ $this->_bodyCanonEmptyCounter = 0;
+ $this->_bodyCanonLastChar = null;
+ $this->_bodyCanonSpace = false;
+
+ return $this;
+ }
+
+ /**
+ * Writes $bytes to the end of the stream.
+ *
+ * Writing may not happen immediately if the stream chooses to buffer. If
+ * you want to write these bytes with immediate effect, call {@link commit()}
+ * after calling write().
+ *
+ * This method returns the sequence ID of the write (i.e. 1 for first, 2 for
+ * second, etc etc).
+ *
+ * @param string $bytes
+ * @return int
+ * @throws Swift_IoException
+ * @return Swift_Signers_DomainKeysSigner
+ */
+ public function write($bytes)
+ {
+ $this->_canonicalizeBody($bytes);
+ foreach ($this->_bound as $is) {
+ $is->write($bytes);
+ }
+
+ return $this;
+ }
+
+ /**
+ * For any bytes that are currently buffered inside the stream, force them
+ * off the buffer.
+ *
+ * @throws Swift_IoException
+ * @return Swift_Signers_DomainKeysSigner
+ */
+ public function commit()
+ {
+ // Nothing to do
+ return $this;
+ }
+
+ /**
+ * Attach $is to this stream.
+ * The stream acts as an observer, receiving all data that is written.
+ * All {@link write()} and {@link flushBuffers()} operations will be mirrored.
+ *
+ * @param Swift_InputByteStream $is
+ * @return Swift_Signers_DomainKeysSigner
+ */
+ public function bind(Swift_InputByteStream $is)
+ {
+ // Don't have to mirror anything
+ $this->_bound[] = $is;
+
+ return $this;
+ }
+
+ /**
+ * Remove an already bound stream.
+ * If $is is not bound, no errors will be raised.
+ * If the stream currently has any buffered data it will be written to $is
+ * before unbinding occurs.
+ *
+ * @param Swift_InputByteStream $is
+ * @return Swift_Signers_DomainKeysSigner
+ */
+ public function unbind(Swift_InputByteStream $is)
+ {
+ // Don't have to mirror anything
+ foreach ($this->_bound as $k => $stream) {
+ if ($stream === $is) {
+ unset($this->_bound[$k]);
+
+ return;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Flush the contents of the stream (empty it) and set the internal pointer
+ * to the beginning.
+ *
+ * @throws Swift_IoException
+ * @return Swift_Signers_DomainKeysSigner
+ */
+ public function flushBuffers()
+ {
+ $this->reset();
+
+ return $this;
+ }
+
+ /**
+ * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1 defaults to rsa-sha256
+ *
+ * @param string $hash
+ * @return Swift_Signers_DomainKeysSigner
+ */
+ public function setHashAlgorithm($hash)
+ {
+ $this->_hashAlgorithm = 'rsa-sha1';
+
+ return $this;
+ }
+
+ /**
+ * Set the canonicalization algorithm
+ *
+ * @param string $canon simple | nofws defaults to simple
+ * @return Swift_Signers_DomainKeysSigner
+ */
+ public function setCanon($canon)
+ {
+ if ($canon == 'nofws') {
+ $this->_canon = 'nofws';
+ } else {
+ $this->_canon = 'simple';
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the signer identity
+ *
+ * @param string $identity
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function setSignerIdentity($identity)
+ {
+ $this->_signerIdentity = $identity;
+
+ return $this;
+ }
+
+ /**
+ * Enable / disable the DebugHeaders
+ *
+ * @param bool $debug
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function setDebugHeaders($debug)
+ {
+ $this->_debugHeaders = (bool) $debug;
+
+ return $this;
+ }
+
+ /**
+ * Start Body
+ *
+ */
+ public function startBody()
+ {
+ }
+
+ /**
+ * End Body
+ *
+ */
+ public function endBody()
+ {
+ $this->_endOfBody();
+ }
+
+ /**
+ * Returns the list of Headers Tampered by this plugin
+ *
+ * @return array
+ */
+ public function getAlteredHeaders()
+ {
+ if ($this->_debugHeaders) {
+ return array('DomainKey-Signature', 'X-DebugHash');
+ } else {
+ return array('DomainKey-Signature');
+ }
+ }
+
+ /**
+ * Adds an ignored Header
+ *
+ * @param string $header_name
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function ignoreHeader($header_name)
+ {
+ $this->_ignoredHeaders[strtolower($header_name)] = true;
+
+ return $this;
+ }
+
+ /**
+ * Set the headers to sign
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function setHeaders(Swift_Mime_HeaderSet $headers)
+ {
+ $this->_startHash();
+ $this->_canonData = '';
+ // Loop through Headers
+ $listHeaders = $headers->listAll();
+ foreach ($listHeaders as $hName) {
+ // Check if we need to ignore Header
+ if (! isset($this->_ignoredHeaders[strtolower($hName)])) {
+ if ($headers->has($hName)) {
+ $tmp = $headers->getAll($hName);
+ foreach ($tmp as $header) {
+ if ($header->getFieldBody() != '') {
+ $this->_addHeader($header->toString());
+ $this->_signedHeaders[] = $header->getFieldName();
+ }
+ }
+ }
+ }
+ }
+ $this->_endOfHeaders();
+
+ return $this;
+ }
+
+ /**
+ * Add the signature to the given Headers
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ * @return Swift_Signers_DomainKeySigner
+ */
+ public function addSignature(Swift_Mime_HeaderSet $headers)
+ {
+ // Prepare the DomainKey-Signature Header
+ $params = array('a' => $this->_hashAlgorithm, 'b' => chunk_split(base64_encode($this->_getEncryptedHash()), 73, " "), 'c' => $this->_canon, 'd' => $this->_domainName, 'h' => implode(': ', $this->_signedHeaders), 'q' => 'dns', 's' => $this->_selector);
+ $string = '';
+ foreach ($params as $k => $v) {
+ $string .= $k . '=' . $v . '; ';
+ }
+ $string = trim($string);
+ $headers->addTextHeader('DomainKey-Signature', $string);
+
+ return $this;
+ }
+
+ /* Private helpers */
+
+ protected function _addHeader($header)
+ {
+ switch ($this->_canon) {
+ case 'nofws' :
+ // Prepare Header and cascade
+ $exploded = explode(':', $header, 2);
+ $name = strtolower(trim($exploded[0]));
+ $value = str_replace("\r\n", "", $exploded[1]);
+ $value = preg_replace("/[ \t][ \t]+/", " ", $value);
+ $header = $name . ":" . trim($value) . "\r\n";
+ case 'simple' :
+ // Nothing to do
+ }
+ $this->_addToHash($header);
+ }
+
+ protected function _endOfHeaders()
+ {
+ $this->_bodyCanonEmptyCounter = 1;
+ }
+
+ protected function _canonicalizeBody($string)
+ {
+ $len = strlen($string);
+ $canon = '';
+ $nofws = ($this->_canon == "nofws");
+ for ($i = 0; $i < $len; ++$i) {
+ if ($this->_bodyCanonIgnoreStart > 0) {
+ --$this->_bodyCanonIgnoreStart;
+ continue;
+ }
+ switch ($string[$i]) {
+ case "\r" :
+ $this->_bodyCanonLastChar = "\r";
+ break;
+ case "\n" :
+ if ($this->_bodyCanonLastChar == "\r") {
+ if ($nofws) {
+ $this->_bodyCanonSpace = false;
+ }
+ if ($this->_bodyCanonLine == '') {
+ ++$this->_bodyCanonEmptyCounter;
+ } else {
+ $this->_bodyCanonLine = '';
+ $canon .= "\r\n";
+ }
+ } else {
+ // Wooops Error
+ throw new Swift_SwiftException('Invalid new line sequence in mail found \n without preceding \r');
+ }
+ break;
+ case " " :
+ case "\t" :
+ case "\x09": //HTAB
+ if ($nofws) {
+ $this->_bodyCanonSpace = true;
+ break;
+ }
+ default :
+ if ($this->_bodyCanonEmptyCounter > 0) {
+ $canon .= str_repeat("\r\n", $this->_bodyCanonEmptyCounter);
+ $this->_bodyCanonEmptyCounter = 0;
+ }
+ $this->_bodyCanonLine .= $string[$i];
+ $canon .= $string[$i];
+ }
+ }
+ $this->_addToHash($canon);
+ }
+
+ protected function _endOfBody()
+ {
+ if (strlen($this->_bodyCanonLine) > 0) {
+ $this->_addToHash("\r\n");
+ }
+ $this->_hash = hash_final($this->_hashHandler, true);
+ }
+
+ private function _addToHash($string)
+ {
+ $this->_canonData .= $string;
+ hash_update($this->_hashHandler, $string);
+ }
+
+ private function _startHash()
+ {
+ // Init
+ switch ($this->_hashAlgorithm) {
+ case 'rsa-sha1' :
+ $this->_hashHandler = hash_init('sha1');
+ break;
+ }
+ $this->_canonLine = '';
+ }
+
+ /**
+ * @throws Swift_SwiftException
+ * @return string
+ */
+ private function _getEncryptedHash()
+ {
+ $signature = '';
+ $pkeyId=openssl_get_privatekey($this->_privateKey);
+ if (!$pkeyId) {
+ throw new Swift_SwiftException('Unable to load DomainKey Private Key ['.openssl_error_string().']');
+ }
+ if (openssl_sign($this->_canonData, $signature, $pkeyId, OPENSSL_ALGO_SHA1)) {
+ return $signature;
+ }
+ throw new Swift_SwiftException('Unable to sign DomainKey Hash ['.openssl_error_string().']');
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Signers/HeaderSigner.php b/vendor/swiftmailer/classes/Swift/Signers/HeaderSigner.php
new file mode 100644
index 00000000..67c79413
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Signers/HeaderSigner.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Header Signer Interface used to apply Header-Based Signature to a message
+ *
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+interface Swift_Signers_HeaderSigner extends Swift_Signer, Swift_InputByteStream
+{
+ /**
+ * Exclude an header from the signed headers
+ *
+ * @param string $header_name
+ *
+ * @return Swift_Signers_HeaderSigner
+ */
+ public function ignoreHeader($header_name);
+
+ /**
+ * Prepare the Signer to get a new Body
+ *
+ * @return Swift_Signers_HeaderSigner
+ */
+ public function startBody();
+
+ /**
+ * Give the signal that the body has finished streaming
+ *
+ * @return Swift_Signers_HeaderSigner
+ */
+ public function endBody();
+
+ /**
+ * Give the headers already given
+ *
+ * @param Swift_Mime_SimpleHeaderSet $headers
+ *
+ * @return Swift_Signers_HeaderSigner
+ */
+ public function setHeaders(Swift_Mime_HeaderSet $headers);
+
+ /**
+ * Add the header(s) to the headerSet
+ *
+ * @param Swift_Mime_HeaderSet $headers
+ *
+ * @return Swift_Signers_HeaderSigner
+ */
+ public function addSignature(Swift_Mime_HeaderSet $headers);
+
+ /**
+ * Return the list of header a signer might tamper
+ *
+ * @return array
+ */
+ public function getAlteredHeaders();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Signers/OpenDKIMSigner.php b/vendor/swiftmailer/classes/Swift/Signers/OpenDKIMSigner.php
new file mode 100644
index 00000000..6b113892
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Signers/OpenDKIMSigner.php
@@ -0,0 +1,186 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * DKIM Signer used to apply DKIM Signature to a message
+ * Takes advantage of pecl extension
+ *
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+class Swift_Signers_OpenDKIMSigner extends Swift_Signers_DKIMSigner
+{
+ private $_peclLoaded = false;
+
+ private $_dkimHandler = null;
+
+ private $dropFirstLF = true;
+
+ const CANON_RELAXED = 1;
+ const CANON_SIMPLE = 2;
+ const SIG_RSA_SHA1 = 3;
+ const SIG_RSA_SHA256 = 4;
+
+ public function __construct($privateKey, $domainName, $selector)
+ {
+ if (extension_loaded('opendkim')) {
+ $this->_peclLoaded = true;
+ } else {
+ throw new Swift_SwiftException('php-opendkim extension not found');
+ }
+ parent::__construct($privateKey, $domainName, $selector);
+ }
+
+ public static function newInstance($privateKey, $domainName, $selector)
+ {
+ return new static($privateKey, $domainName, $selector);
+ }
+
+ public function addSignature(Swift_Mime_HeaderSet $headers)
+ {
+ $header = new Swift_Mime_Headers_OpenDKIMHeader('DKIM-Signature');
+ $headerVal=$this->_dkimHandler->getSignatureHeader();
+ if (!$headerVal) {
+ throw new Swift_SwiftException('OpenDKIM Error: '.$this->_dkimHandler->getError());
+ }
+ $header->setValue($headerVal);
+ $headers->set($header);
+
+ return $this;
+ }
+
+ public function setHeaders(Swift_Mime_HeaderSet $headers)
+ {
+ $bodyLen = $this->_bodyLen;
+ if (is_bool($bodyLen)) {
+ $bodyLen = - 1;
+ }
+ $hash = ($this->_hashAlgorithm == 'rsa-sha1') ? OpenDKIMSign::ALG_RSASHA1 : OpenDKIMSign::ALG_RSASHA256;
+ $bodyCanon = ($this->_bodyCanon == 'simple') ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED;
+ $headerCanon = ($this->_headerCanon == 'simple') ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED;
+ $this->_dkimHandler = new OpenDKIMSign($this->_privateKey, $this->_selector, $this->_domainName, $headerCanon, $bodyCanon, $hash, $bodyLen);
+ // Hardcode signature Margin for now
+ $this->_dkimHandler->setMargin(78);
+
+ if (!is_numeric($this->_signatureTimestamp)) {
+ OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, time());
+ } else {
+ if (!OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, $this->_signatureTimestamp)) {
+ throw new Swift_SwiftException('Unable to force signature timestamp ['.openssl_error_string().']');
+ }
+ }
+ if (isset($this->_signerIdentity)) {
+ $this->_dkimHandler->setSigner($this->_signerIdentity);
+ }
+ $listHeaders = $headers->listAll();
+ foreach ($listHeaders as $hName) {
+ // Check if we need to ignore Header
+ if (! isset($this->_ignoredHeaders[strtolower($hName)])) {
+ $tmp = $headers->getAll($hName);
+ if ($headers->has($hName)) {
+ foreach ($tmp as $header) {
+ if ($header->getFieldBody() != '') {
+ $htosign = $header->toString();
+ $this->_dkimHandler->header($htosign);
+ $this->_signedHeaders[] = $header->getFieldName();
+ }
+ }
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ public function startBody()
+ {
+ if (! $this->_peclLoaded) {
+ return parent::startBody();
+ }
+ $this->dropFirstLF = true;
+ $this->_dkimHandler->eoh();
+
+ return $this;
+ }
+
+ public function endBody()
+ {
+ if (! $this->_peclLoaded) {
+ return parent::endBody();
+ }
+ $this->_dkimHandler->eom();
+
+ return $this;
+ }
+
+ public function reset()
+ {
+ $this->_dkimHandler = null;
+ parent::reset();
+
+ return $this;
+ }
+
+ /**
+ * Set the signature timestamp
+ *
+ * @param timestamp $time
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setSignatureTimestamp($time)
+ {
+ $this->_signatureTimestamp = $time;
+
+ return $this;
+ }
+
+ /**
+ * Set the signature expiration timestamp
+ *
+ * @param timestamp $time
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setSignatureExpiration($time)
+ {
+ $this->_signatureExpiration = $time;
+
+ return $this;
+ }
+
+ /**
+ * Enable / disable the DebugHeaders
+ *
+ * @param bool $debug
+ * @return Swift_Signers_DKIMSigner
+ */
+ public function setDebugHeaders($debug)
+ {
+ $this->_debugHeaders = (bool) $debug;
+
+ return $this;
+ }
+
+ // Protected
+
+ protected function _canonicalizeBody($string)
+ {
+ if (! $this->_peclLoaded) {
+ return parent::_canonicalizeBody($string);
+ }
+ if (false && $this->dropFirstLF === true) {
+ if ($string[0]=="\r" && $string[1]=="\n") {
+ $string=substr($string, 2);
+ }
+ }
+ $this->dropFirstLF = false;
+ if (strlen($string)) {
+ $this->_dkimHandler->body($string);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Signers/SMimeSigner.php b/vendor/swiftmailer/classes/Swift/Signers/SMimeSigner.php
new file mode 100644
index 00000000..21ed4af1
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Signers/SMimeSigner.php
@@ -0,0 +1,428 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * MIME Message Signer used to apply S/MIME Signature/Encryption to a message.
+ *
+ *
+ * @author Romain-Geissler
+ * @author Sebastiaan Stok <s.stok@rollerscapes.net>
+ */
+class Swift_Signers_SMimeSigner implements Swift_Signers_BodySigner
+{
+ protected $signCertificate;
+ protected $signPrivateKey;
+ protected $encryptCert;
+ protected $signThenEncrypt = true;
+ protected $signLevel;
+ protected $encryptLevel;
+ protected $signOptions;
+ protected $encryptOptions;
+ protected $encryptCipher;
+
+ /**
+ * @var Swift_StreamFilters_StringReplacementFilterFactory
+ */
+ protected $replacementFactory;
+
+ /**
+ * @var Swift_Mime_HeaderFactory
+ */
+ protected $headerFactory;
+
+ /**
+ * Constructor.
+ *
+ * @param string $certificate
+ * @param string $privateKey
+ * @param string $encryptCertificate
+ */
+ public function __construct($signCertificate = null, $signPrivateKey = null, $encryptCertificate = null)
+ {
+ if (null !== $signPrivateKey) {
+ $this->setSignCertificate($signCertificate, $signPrivateKey);
+ }
+
+ if (null !== $encryptCertificate) {
+ $this->setEncryptCertificate($encryptCertificate);
+ }
+
+ $this->replacementFactory = Swift_DependencyContainer::getInstance()
+ ->lookup('transport.replacementfactory');
+
+ $this->signOptions = PKCS7_DETACHED;
+
+ // Supported since php5.4
+ if (defined('OPENSSL_CIPHER_AES_128_CBC')) {
+ $this->encryptCipher = OPENSSL_CIPHER_AES_128_CBC;
+ } else {
+ $this->encryptCipher = OPENSSL_CIPHER_RC2_128;
+ }
+ }
+
+ /**
+ * Returns an new Swift_Signers_SMimeSigner instance.
+ *
+ * @param string $certificate
+ * @param string $privateKey
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public static function newInstance($certificate = null, $privateKey = null)
+ {
+ return new self($certificate, $privateKey);
+ }
+
+ /**
+ * Set the certificate location to use for signing.
+ *
+ * @link http://www.php.net/manual/en/openssl.pkcs7.flags.php
+ *
+ * @param string $certificate
+ * @param string|array $privateKey If the key needs an passphrase use array('file-location', 'passphrase') instead
+ * @param int $signOptions Bitwise operator options for openssl_pkcs7_sign()
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public function setSignCertificate($certificate, $privateKey = null, $signOptions = PKCS7_DETACHED)
+ {
+ $this->signCertificate = 'file://' . str_replace('\\', '/', realpath($certificate));
+
+ if (null !== $privateKey) {
+ if (is_array($privateKey)) {
+ $this->signPrivateKey = $privateKey;
+ $this->signPrivateKey[0] = 'file://' . str_replace('\\', '/', realpath($privateKey[0]));
+ } else {
+ $this->signPrivateKey = 'file://' . str_replace('\\', '/', realpath($privateKey));
+ }
+ }
+
+ $this->signOptions = $signOptions;
+
+ return $this;
+ }
+
+ /**
+ * Set the certificate location to use for encryption.
+ *
+ * @link http://www.php.net/manual/en/openssl.pkcs7.flags.php
+ * @link http://nl3.php.net/manual/en/openssl.ciphers.php
+ *
+ * @param string|array $recipientCerts Either an single X.509 certificate, or an assoc array of X.509 certificates.
+ * @param int $cipher
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public function setEncryptCertificate($recipientCerts, $cipher = null)
+ {
+ if (is_array($recipientCerts)) {
+ $this->encryptCert = array();
+
+ foreach ($recipientCerts as $cert) {
+ $this->encryptCert[] = 'file://' . str_replace('\\', '/', realpath($cert));
+ }
+ } else {
+ $this->encryptCert = 'file://' . str_replace('\\', '/', realpath($recipientCerts));
+ }
+
+ if (null !== $cipher) {
+ $this->encryptCipher = $cipher;
+ }
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSignCertificate()
+ {
+ return $this->signCertificate;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSignPrivateKey()
+ {
+ return $this->signPrivateKey;
+ }
+
+ /**
+ * Set perform signing before encryption.
+ *
+ * The default is to first sign the message and then encrypt.
+ * But some older mail clients, namely Microsoft Outlook 2000 will work when the message first encrypted.
+ * As this goes against the official specs, its recommended to only use 'encryption -> signing' when specifically targeting these 'broken' clients.
+ *
+ * @param string $signThenEncrypt
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public function setSignThenEncrypt($signThenEncrypt = true)
+ {
+ $this->signThenEncrypt = $signThenEncrypt;
+
+ return $this;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isSignThenEncrypt()
+ {
+ return $this->signThenEncrypt;
+ }
+
+ /**
+ * Resets internal states.
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public function reset()
+ {
+ return $this;
+ }
+
+ /**
+ * Change the Swift_Message to apply the signing.
+ *
+ * @param Swift_Message $message
+ *
+ * @return Swift_Signers_SMimeSigner
+ */
+ public function signMessage(Swift_Message $message)
+ {
+ if (null === $this->signCertificate && null === $this->encryptCert) {
+ return $this;
+ }
+
+ // Store the message using ByteStream to a file{1}
+ // Remove all Children
+ // Sign file{1}, parse the new MIME headers and set them on the primary MimeEntity
+ // Set the singed-body as the new body (without boundary)
+
+ $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
+ $this->toSMimeByteStream($messageStream, $message);
+ $message->setEncoder(Swift_DependencyContainer::getInstance()->lookup('mime.rawcontentencoder'));
+
+ $message->setChildren(array());
+ $this->streamToMime($messageStream, $message);
+
+ }
+
+ /**
+ * Return the list of header a signer might tamper.
+ *
+ * @return array
+ */
+ public function getAlteredHeaders()
+ {
+ return array('Content-Type', 'Content-Transfer-Encoding', 'Content-Disposition');
+ }
+
+ /**
+ * @param Swift_InputByteStream $inputStream
+ * @param Swift_Message $mimeEntity
+ */
+ protected function toSMimeByteStream(Swift_InputByteStream $inputStream, Swift_Message $message)
+ {
+ $mimeEntity = $this->createMessage($message);
+ $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ $mimeEntity->toByteStream($messageStream);
+ $messageStream->commit();
+
+ if (null !== $this->signCertificate && null !== $this->encryptCert) {
+ $temporaryStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ if ($this->signThenEncrypt) {
+ $this->messageStreamToSignedByteStream($messageStream, $temporaryStream);
+ $this->messageStreamToEncryptedByteStream($temporaryStream, $inputStream);
+ } else {
+ $this->messageStreamToEncryptedByteStream($messageStream, $temporaryStream);
+ $this->messageStreamToSignedByteStream($temporaryStream, $inputStream);
+ }
+ } elseif ($this->signCertificate !== null) {
+ $this->messageStreamToSignedByteStream($messageStream, $inputStream);
+ } else {
+ $this->messageStreamToEncryptedByteStream($messageStream, $inputStream);
+ }
+ }
+
+ /**
+ * @param Swift_Message $message
+ *
+ * @return Swift_Message
+ */
+ protected function createMessage(Swift_Message $message)
+ {
+ $mimeEntity = new Swift_Message('', $message->getBody(), $message->getContentType(), $message->getCharset());
+ $mimeEntity->setChildren($message->getChildren());
+
+ $messageHeaders = $mimeEntity->getHeaders();
+ $messageHeaders->remove('Message-ID');
+ $messageHeaders->remove('Date');
+ $messageHeaders->remove('Subject');
+ $messageHeaders->remove('MIME-Version');
+ $messageHeaders->remove('To');
+ $messageHeaders->remove('From');
+
+ return $mimeEntity;
+ }
+
+ /**
+ * @param Swift_FileStream $outputStream
+ * @param Swift_InputByteStream $inputStream
+ *
+ * @throws Swift_IoException
+ */
+ protected function messageStreamToSignedByteStream(Swift_FileStream $outputStream, Swift_InputByteStream $inputStream)
+ {
+ $signedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ if (!openssl_pkcs7_sign($outputStream->getPath(), $signedMessageStream->getPath(), $this->signCertificate, $this->signPrivateKey, array(), $this->signOptions)) {
+ throw new Swift_IoException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string()));
+ }
+
+ $this->copyFromOpenSSLOutput($signedMessageStream, $inputStream);
+ }
+
+ /**
+ * @param Swift_FileStream $outputStream
+ * @param Swift_InputByteStream $is
+ *
+ * @throws Swift_IoException
+ */
+ protected function messageStreamToEncryptedByteStream(Swift_FileStream $outputStream, Swift_InputByteStream $is)
+ {
+ $encryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream();
+
+ if (!openssl_pkcs7_encrypt($outputStream->getPath(), $encryptedMessageStream->getPath(), $this->encryptCert, array(), 0, $this->encryptCipher)) {
+ throw new Swift_IoException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string()));
+ }
+
+ $this->copyFromOpenSSLOutput($encryptedMessageStream, $is);
+ }
+
+ /**
+ * @param Swift_OutputByteStream $fromStream
+ * @param Swift_InputByteStream $toStream
+ */
+ protected function copyFromOpenSSLOutput(Swift_OutputByteStream $fromStream, Swift_InputByteStream $toStream)
+ {
+ $bufferLength = 4096;
+ $filteredStream = new Swift_ByteStream_TemporaryFileByteStream();
+ $filteredStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF');
+ $filteredStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF');
+
+ while (false !== ($buffer = $fromStream->read($bufferLength))) {
+ $filteredStream->write($buffer);
+ }
+
+ $filteredStream->flushBuffers();
+
+ while (false !== ($buffer = $filteredStream->read($bufferLength))) {
+ $toStream->write($buffer);
+ }
+
+ $toStream->commit();
+ }
+
+ /**
+ * Merges an OutputByteStream to Swift_Message.
+ *
+ * @param Swift_OutputByteStream $fromStream
+ * @param Swift_Message $message
+ */
+ protected function streamToMime(Swift_OutputByteStream $fromStream, Swift_Message $message)
+ {
+ $bufferLength = 78;
+ $headerData = '';
+
+ $fromStream->setReadPointer(0);
+
+ while (($buffer = $fromStream->read($bufferLength)) !== false) {
+ $headerData .= $buffer;
+
+ if (false !== strpos($buffer, "\r\n\r\n")) {
+ break;
+ }
+ }
+
+ $headersPosEnd = strpos($headerData, "\r\n\r\n");
+ $headerData = trim($headerData);
+ $headerData = substr($headerData, 0, $headersPosEnd);
+ $headerLines = explode("\r\n", $headerData);
+ unset($headerData);
+
+ $headers = array();
+ $currentHeaderName = '';
+
+ foreach ($headerLines as $headerLine) {
+ // Line separated
+ if (ctype_space($headerLines[0]) || false === strpos($headerLine, ':')) {
+ $headers[$currentHeaderName] .= ' ' . trim($headerLine);
+ continue;
+ }
+
+ $header = explode(':', $headerLine, 2);
+ $currentHeaderName = strtolower($header[0]);
+ $headers[$currentHeaderName] = trim($header[1]);
+ }
+
+ $messageStream = new Swift_ByteStream_TemporaryFileByteStream();
+ $messageStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF');
+ $messageStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF');
+
+ $messageHeaders = $message->getHeaders();
+
+ // No need to check for 'application/pkcs7-mime', as this is always base64
+ if ('multipart/signed;' === substr($headers['content-type'], 0, 17)) {
+ if (!preg_match('/boundary=("[^"]+"|(?:[^\s]+|$))/is', $headers['content-type'], $contentTypeData)) {
+ throw new Swift_SwiftException('Failed to find Boundary parameter');
+ }
+
+ $boundary = trim($contentTypeData['1'], '"');
+ $boundaryLen = strlen($boundary);
+
+ // Skip the header and CRLF CRLF
+ $fromStream->setReadPointer($headersPosEnd + 4);
+
+ while (false !== ($buffer = $fromStream->read($bufferLength))) {
+ $messageStream->write($buffer);
+ }
+
+ $messageStream->commit();
+
+ $messageHeaders->remove('Content-Transfer-Encoding');
+ $message->setContentType($headers['content-type']);
+ $message->setBoundary($boundary);
+ $message->setBody($messageStream);
+ } else {
+ $fromStream->setReadPointer($headersPosEnd + 4);
+
+ if (null === $this->headerFactory) {
+ $this->headerFactory = Swift_DependencyContainer::getInstance()->lookup('mime.headerfactory');
+ }
+
+ $message->setContentType($headers['content-type']);
+ $messageHeaders->set($this->headerFactory->createTextHeader('Content-Transfer-Encoding', $headers['content-transfer-encoding']));
+ $messageHeaders->set($this->headerFactory->createTextHeader('Content-Disposition', $headers['content-disposition']));
+
+ while (false !== ($buffer = $fromStream->read($bufferLength))) {
+ $messageStream->write($buffer);
+ }
+
+ $messageStream->commit();
+ $message->setBody($messageStream);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/SmtpTransport.php b/vendor/swiftmailer/classes/Swift/SmtpTransport.php
new file mode 100644
index 00000000..5d4945e1
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/SmtpTransport.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Sends Messages over SMTP with ESMTP support.
+ *
+ * @author Chris Corbyn
+ * @method Swift_SmtpTransport setUsername(string $username) Set the username to authenticate with.
+ * @method string getUsername() Get the username to authenticate with.
+ * @method Swift_SmtpTransport setPassword(string $password) Set the password to authenticate with.
+ * @method string getPassword() Get the password to authenticate with.
+ * @method Swift_SmtpTransport setAuthMode(string $mode) Set the auth mode to use to authenticate.
+ * @method string getAuthMode() Get the auth mode to use to authenticate.
+ */
+class Swift_SmtpTransport extends Swift_Transport_EsmtpTransport
+{
+ /**
+ * Create a new SmtpTransport, optionally with $host, $port and $security.
+ *
+ * @param string $host
+ * @param int $port
+ * @param string $security
+ */
+ public function __construct($host = 'localhost', $port = 25, $security = null)
+ {
+ call_user_func_array(
+ array($this, 'Swift_Transport_EsmtpTransport::__construct'),
+ Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('transport.smtp')
+ );
+
+ $this->setHost($host);
+ $this->setPort($port);
+ $this->setEncryption($security);
+ }
+
+ /**
+ * Create a new SmtpTransport instance.
+ *
+ * @param string $host
+ * @param int $port
+ * @param string $security
+ *
+ * @return Swift_SmtpTransport
+ */
+ public static function newInstance($host = 'localhost', $port = 25, $security = null)
+ {
+ return new self($host, $port, $security);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Spool.php b/vendor/swiftmailer/classes/Swift/Spool.php
new file mode 100644
index 00000000..afae5fac
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Spool.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2009 Fabien Potencier <fabien.potencier@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Interface for spools.
+ *
+ * @author Fabien Potencier
+ */
+interface Swift_Spool
+{
+ /**
+ * Starts this Spool mechanism.
+ */
+ public function start();
+
+ /**
+ * Stops this Spool mechanism.
+ */
+ public function stop();
+
+ /**
+ * Tests if this Spool mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted();
+
+ /**
+ * Queues a message.
+ *
+ * @param Swift_Mime_Message $message The message to store
+ *
+ * @return bool Whether the operation has succeeded
+ */
+ public function queueMessage(Swift_Mime_Message $message);
+
+ /**
+ * Sends messages using the given transport instance.
+ *
+ * @param Swift_Transport $transport A transport instance
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int The number of sent emails
+ */
+ public function flushQueue(Swift_Transport $transport, &$failedRecipients = null);
+}
diff --git a/vendor/swiftmailer/classes/Swift/SpoolTransport.php b/vendor/swiftmailer/classes/Swift/SpoolTransport.php
new file mode 100644
index 00000000..9351c40d
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/SpoolTransport.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2009 Fabien Potencier <fabien.potencier@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages in a queue.
+ *
+ * @author Fabien Potencier
+ */
+class Swift_SpoolTransport extends Swift_Transport_SpoolTransport
+{
+ /**
+ * Create a new SpoolTransport.
+ *
+ * @param Swift_Spool $spool
+ */
+ public function __construct(Swift_Spool $spool)
+ {
+ $arguments = Swift_DependencyContainer::getInstance()
+ ->createDependenciesFor('transport.spool');
+
+ $arguments[] = $spool;
+
+ call_user_func_array(
+ array($this, 'Swift_Transport_SpoolTransport::__construct'),
+ $arguments
+ );
+ }
+
+ /**
+ * Create a new SpoolTransport instance.
+ *
+ * @param Swift_Spool $spool
+ *
+ * @return Swift_SpoolTransport
+ */
+ public static function newInstance(Swift_Spool $spool)
+ {
+ return new self($spool);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/StreamFilter.php b/vendor/swiftmailer/classes/Swift/StreamFilter.php
new file mode 100644
index 00000000..1c3fd3a5
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/StreamFilter.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Processes bytes as they pass through a stream and performs filtering.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_StreamFilter
+{
+ /**
+ * Based on the buffer given, this returns true if more buffering is needed.
+ *
+ * @param mixed $buffer
+ *
+ * @return bool
+ */
+ public function shouldBuffer($buffer);
+
+ /**
+ * Filters $buffer and returns the changes.
+ *
+ * @param mixed $buffer
+ *
+ * @return mixed
+ */
+ public function filter($buffer);
+}
diff --git a/vendor/swiftmailer/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php b/vendor/swiftmailer/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php
new file mode 100644
index 00000000..db6edce9
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php
@@ -0,0 +1,170 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Processes bytes as they pass through a buffer and replaces sequences in it.
+ *
+ * This stream filter deals with Byte arrays rather than simple strings.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_StreamFilters_ByteArrayReplacementFilter implements Swift_StreamFilter
+{
+ /** The needle(s) to search for */
+ private $_search;
+
+ /** The replacement(s) to make */
+ private $_replace;
+
+ /** The Index for searching */
+ private $_index;
+
+ /** The Search Tree */
+ private $_tree = array();
+
+ /** Gives the size of the largest search */
+ private $_treeMaxLen = 0;
+
+ private $_repSize;
+
+ /**
+ * Create a new ByteArrayReplacementFilter with $search and $replace.
+ *
+ * @param array $search
+ * @param array $replace
+ */
+ public function __construct($search, $replace)
+ {
+ $this->_search = $search;
+ $this->_index = array();
+ $this->_tree = array();
+ $this->_replace = array();
+ $this->_repSize = array();
+
+ $tree = null;
+ $i = null;
+ $last_size = $size = 0;
+ foreach ($search as $i => $search_element) {
+ if ($tree !== null) {
+ $tree[-1] = min (count($replace) - 1, $i - 1);
+ $tree[-2] = $last_size;
+ }
+ $tree = &$this->_tree;
+ if (is_array ($search_element)) {
+ foreach ($search_element as $k => $char) {
+ $this->_index[$char] = true;
+ if (!isset($tree[$char])) {
+ $tree[$char] = array();
+ }
+ $tree = &$tree[$char];
+ }
+ $last_size = $k+1;
+ $size = max($size, $last_size);
+ } else {
+ $last_size = 1;
+ if (!isset($tree[$search_element])) {
+ $tree[$search_element] = array();
+ }
+ $tree = &$tree[$search_element];
+ $size = max($last_size, $size);
+ $this->_index[$search_element] = true;
+ }
+ }
+ if ($i !== null) {
+ $tree[-1] = min (count ($replace) - 1, $i);
+ $tree[-2] = $last_size;
+ $this->_treeMaxLen = $size;
+ }
+ foreach ($replace as $rep) {
+ if (!is_array($rep)) {
+ $rep = array ($rep);
+ }
+ $this->_replace[] = $rep;
+ }
+ for ($i = count($this->_replace) - 1; $i >= 0; --$i) {
+ $this->_replace[$i] = $rep = $this->filter($this->_replace[$i], $i);
+ $this->_repSize[$i] = count($rep);
+ }
+ }
+
+ /**
+ * Returns true if based on the buffer passed more bytes should be buffered.
+ *
+ * @param array $buffer
+ *
+ * @return bool
+ */
+ public function shouldBuffer($buffer)
+ {
+ $endOfBuffer = end($buffer);
+
+ return isset ($this->_index[$endOfBuffer]);
+ }
+
+ /**
+ * Perform the actual replacements on $buffer and return the result.
+ *
+ * @param array $buffer
+ * @param int $_minReplaces
+ *
+ * @return array
+ */
+ public function filter($buffer, $_minReplaces = -1)
+ {
+ if ($this->_treeMaxLen == 0) {
+ return $buffer;
+ }
+
+ $newBuffer = array();
+ $buf_size = count($buffer);
+ for ($i = 0; $i < $buf_size; ++$i) {
+ $search_pos = $this->_tree;
+ $last_found = PHP_INT_MAX;
+ // We try to find if the next byte is part of a search pattern
+ for ($j = 0; $j <= $this->_treeMaxLen; ++$j) {
+ // We have a new byte for a search pattern
+ if (isset ($buffer [$p = $i + $j]) && isset($search_pos[$buffer[$p]])) {
+ $search_pos = $search_pos[$buffer[$p]];
+ // We have a complete pattern, save, in case we don't find a better match later
+ if (isset($search_pos[- 1]) && $search_pos[-1] < $last_found
+ && $search_pos[-1] > $_minReplaces)
+ {
+ $last_found = $search_pos[-1];
+ $last_size = $search_pos[-2];
+ }
+ }
+ // We got a complete pattern
+ elseif ($last_found !== PHP_INT_MAX) {
+ // Adding replacement datas to output buffer
+ $rep_size = $this->_repSize[$last_found];
+ for ($j = 0; $j < $rep_size; ++$j) {
+ $newBuffer[] = $this->_replace[$last_found][$j];
+ }
+ // We Move cursor forward
+ $i += $last_size - 1;
+ // Edge Case, last position in buffer
+ if ($i >= $buf_size) {
+ $newBuffer[] = $buffer[$i];
+ }
+
+ // We start the next loop
+ continue 2;
+ } else {
+ // this byte is not in a pattern and we haven't found another pattern
+ break;
+ }
+ }
+ // Normal byte, move it to output buffer
+ $newBuffer[] = $buffer[$i];
+ }
+
+ return $newBuffer;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilter.php b/vendor/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilter.php
new file mode 100644
index 00000000..e6b9e7b8
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilter.php
@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Processes bytes as they pass through a buffer and replaces sequences in it.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_StreamFilters_StringReplacementFilter implements Swift_StreamFilter
+{
+ /** The needle(s) to search for */
+ private $_search;
+
+ /** The replacement(s) to make */
+ private $_replace;
+
+ /**
+ * Create a new StringReplacementFilter with $search and $replace.
+ *
+ * @param string|array $search
+ * @param string|array $replace
+ */
+ public function __construct($search, $replace)
+ {
+ $this->_search = $search;
+ $this->_replace = $replace;
+ }
+
+ /**
+ * Returns true if based on the buffer passed more bytes should be buffered.
+ *
+ * @param string $buffer
+ *
+ * @return bool
+ */
+ public function shouldBuffer($buffer)
+ {
+ $endOfBuffer = substr($buffer, -1);
+ foreach ((array) $this->_search as $needle) {
+ if (false !== strpos($needle, $endOfBuffer)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Perform the actual replacements on $buffer and return the result.
+ *
+ * @param string $buffer
+ *
+ * @return string
+ */
+ public function filter($buffer)
+ {
+ return str_replace($this->_search, $this->_replace, $buffer);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilterFactory.php b/vendor/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilterFactory.php
new file mode 100644
index 00000000..4b12cfff
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/StreamFilters/StringReplacementFilterFactory.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Creates filters for replacing needles in a string buffer.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_StreamFilters_StringReplacementFilterFactory implements Swift_ReplacementFilterFactory
+{
+ /** Lazy-loaded filters */
+ private $_filters = array();
+
+ /**
+ * Create a new StreamFilter to replace $search with $replace in a string.
+ *
+ * @param string $search
+ * @param string $replace
+ *
+ * @return Swift_StreamFilter
+ */
+ public function createFilter($search, $replace)
+ {
+ if (!isset($this->_filters[$search][$replace])) {
+ if (!isset($this->_filters[$search])) {
+ $this->_filters[$search] = array();
+ }
+
+ if (!isset($this->_filters[$search][$replace])) {
+ $this->_filters[$search][$replace] = array();
+ }
+
+ $this->_filters[$search][$replace] = new Swift_StreamFilters_StringReplacementFilter($search, $replace);
+ }
+
+ return $this->_filters[$search][$replace];
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/SwiftException.php b/vendor/swiftmailer/classes/Swift/SwiftException.php
new file mode 100644
index 00000000..22ee3eb4
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/SwiftException.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Base Exception class.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_SwiftException extends Exception
+{
+ /**
+ * Create a new SwiftException with $message.
+ *
+ * @param string $message
+ */
+ public function __construct($message)
+ {
+ parent::__construct($message);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport.php b/vendor/swiftmailer/classes/Swift/Transport.php
new file mode 100644
index 00000000..ac97b409
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Sends Messages via an abstract Transport subsystem.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Transport
+{
+ /**
+ * Test if this Transport mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted();
+
+ /**
+ * Start this Transport mechanism.
+ */
+ public function start();
+
+ /**
+ * Stop this Transport mechanism.
+ */
+ public function stop();
+
+ /**
+ * Send the given Message.
+ *
+ * Recipient/sender data will be retrieved from the Message API.
+ * The return value is the number of recipients who were accepted for delivery.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null);
+
+ /**
+ * Register a plugin in the Transport.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/AbstractSmtpTransport.php b/vendor/swiftmailer/classes/Swift/Transport/AbstractSmtpTransport.php
new file mode 100644
index 00000000..e5874d28
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/AbstractSmtpTransport.php
@@ -0,0 +1,502 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Sends Messages over SMTP.
+ *
+ * @author Chris Corbyn
+ */
+abstract class Swift_Transport_AbstractSmtpTransport implements Swift_Transport
+{
+ /** Input-Output buffer for sending/receiving SMTP commands and responses */
+ protected $_buffer;
+
+ /** Connection status */
+ protected $_started = false;
+
+ /** The domain name to use in HELO command */
+ protected $_domain = '[127.0.0.1]';
+
+ /** The event dispatching layer */
+ protected $_eventDispatcher;
+
+ /** Source Ip */
+ protected $_sourceIp;
+
+ /** Return an array of params for the Buffer */
+ abstract protected function _getBufferParams();
+
+ /**
+ * Creates a new EsmtpTransport using the given I/O buffer.
+ *
+ * @param Swift_Transport_IoBuffer $buf
+ * @param Swift_Events_EventDispatcher $dispatcher
+ */
+ public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher)
+ {
+ $this->_eventDispatcher = $dispatcher;
+ $this->_buffer = $buf;
+ $this->_lookupHostname();
+ }
+
+ /**
+ * Set the name of the local domain which Swift will identify itself as.
+ *
+ * This should be a fully-qualified domain name and should be truly the domain
+ * you're using.
+ *
+ * If your server doesn't have a domain name, use the IP in square
+ * brackets (i.e. [127.0.0.1]).
+ *
+ * @param string $domain
+ *
+ * @return Swift_Transport_AbstractSmtpTransport
+ */
+ public function setLocalDomain($domain)
+ {
+ $this->_domain = $domain;
+
+ return $this;
+ }
+
+ /**
+ * Get the name of the domain Swift will identify as.
+ *
+ * @return string
+ */
+ public function getLocalDomain()
+ {
+ return $this->_domain;
+ }
+
+ /**
+ * Sets the source IP.
+ *
+ * @param string $source
+ */
+ public function setSourceIp($source)
+ {
+ $this->_sourceIp=$source;
+ }
+
+ /**
+ * Returns the IP used to connect to the destination
+ *
+ * @return string
+ */
+ public function getSourceIp()
+ {
+ return $this->_sourceIp;
+ }
+
+ /**
+ * Start the SMTP connection.
+ */
+ public function start()
+ {
+ if (!$this->_started) {
+ if ($evt = $this->_eventDispatcher->createTransportChangeEvent($this)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeTransportStarted');
+ if ($evt->bubbleCancelled()) {
+ return;
+ }
+ }
+
+ try {
+ $this->_buffer->initialize($this->_getBufferParams());
+ } catch (Swift_TransportException $e) {
+ $this->_throwException($e);
+ }
+ $this->_readGreeting();
+ $this->_doHeloCommand();
+
+ if ($evt) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'transportStarted');
+ }
+
+ $this->_started = true;
+ }
+ }
+
+ /**
+ * Test if an SMTP connection has been established.
+ *
+ * @return bool
+ */
+ public function isStarted()
+ {
+ return $this->_started;
+ }
+
+ /**
+ * Send the given Message.
+ *
+ * Recipient/sender data will be retrieved from the Message API.
+ * The return value is the number of recipients who were accepted for delivery.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ $sent = 0;
+ $failedRecipients = (array) $failedRecipients;
+
+ if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
+ if ($evt->bubbleCancelled()) {
+ return 0;
+ }
+ }
+
+ if (!$reversePath = $this->_getReversePath($message)) {
+ throw new Swift_TransportException(
+ 'Cannot send message without a sender address'
+ );
+ }
+
+ $to = (array) $message->getTo();
+ $cc = (array) $message->getCc();
+ $bcc = (array) $message->getBcc();
+
+ $message->setBcc(array());
+
+ try {
+ $sent += $this->_sendTo($message, $reversePath, $to, $failedRecipients);
+ $sent += $this->_sendCc($message, $reversePath, $cc, $failedRecipients);
+ $sent += $this->_sendBcc($message, $reversePath, $bcc, $failedRecipients);
+ } catch (Exception $e) {
+ $message->setBcc($bcc);
+ throw $e;
+ }
+
+ $message->setBcc($bcc);
+
+ if ($evt) {
+ if ($sent == count($to) + count($cc) + count($bcc)) {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS);
+ } elseif ($sent > 0) {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_TENTATIVE);
+ } else {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED);
+ }
+ $evt->setFailedRecipients($failedRecipients);
+ $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+
+ $message->generateId(); //Make sure a new Message ID is used
+
+ return $sent;
+ }
+
+ /**
+ * Stop the SMTP connection.
+ */
+ public function stop()
+ {
+ if ($this->_started) {
+ if ($evt = $this->_eventDispatcher->createTransportChangeEvent($this)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeTransportStopped');
+ if ($evt->bubbleCancelled()) {
+ return;
+ }
+ }
+
+ try {
+ $this->executeCommand("QUIT\r\n", array(221));
+ } catch (Swift_TransportException $e) {}
+
+ try {
+ $this->_buffer->terminate();
+
+ if ($evt) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'transportStopped');
+ }
+ } catch (Swift_TransportException $e) {
+ $this->_throwException($e);
+ }
+ }
+ $this->_started = false;
+ }
+
+ /**
+ * Register a plugin.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ $this->_eventDispatcher->bindEventListener($plugin);
+ }
+
+ /**
+ * Reset the current mail transaction.
+ */
+ public function reset()
+ {
+ $this->executeCommand("RSET\r\n", array(250));
+ }
+
+ /**
+ * Get the IoBuffer where read/writes are occurring.
+ *
+ * @return Swift_Transport_IoBuffer
+ */
+ public function getBuffer()
+ {
+ return $this->_buffer;
+ }
+
+ /**
+ * Run a command against the buffer, expecting the given response codes.
+ *
+ * If no response codes are given, the response will not be validated.
+ * If codes are given, an exception will be thrown on an invalid response.
+ *
+ * @param string $command
+ * @param int[] $codes
+ * @param string[] $failures An array of failures by-reference
+ *
+ * @return string
+ */
+ public function executeCommand($command, $codes = array(), &$failures = null)
+ {
+ $failures = (array) $failures;
+ $seq = $this->_buffer->write($command);
+ $response = $this->_getFullResponse($seq);
+ if ($evt = $this->_eventDispatcher->createCommandEvent($this, $command, $codes)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'commandSent');
+ }
+ $this->_assertResponseCode($response, $codes);
+
+ return $response;
+ }
+
+ /** Read the opening SMTP greeting */
+ protected function _readGreeting()
+ {
+ $this->_assertResponseCode($this->_getFullResponse(0), array(220));
+ }
+
+ /** Send the HELO welcome */
+ protected function _doHeloCommand()
+ {
+ $this->executeCommand(
+ sprintf("HELO %s\r\n", $this->_domain), array(250)
+ );
+ }
+
+ /** Send the MAIL FROM command */
+ protected function _doMailFromCommand($address)
+ {
+ $this->executeCommand(
+ sprintf("MAIL FROM: <%s>\r\n", $address), array(250)
+ );
+ }
+
+ /** Send the RCPT TO command */
+ protected function _doRcptToCommand($address)
+ {
+ $this->executeCommand(
+ sprintf("RCPT TO: <%s>\r\n", $address), array(250, 251, 252)
+ );
+ }
+
+ /** Send the DATA command */
+ protected function _doDataCommand()
+ {
+ $this->executeCommand("DATA\r\n", array(354));
+ }
+
+ /** Stream the contents of the message over the buffer */
+ protected function _streamMessage(Swift_Mime_Message $message)
+ {
+ $this->_buffer->setWriteTranslations(array("\r\n." => "\r\n.."));
+ try {
+ $message->toByteStream($this->_buffer);
+ $this->_buffer->flushBuffers();
+ } catch (Swift_TransportException $e) {
+ $this->_throwException($e);
+ }
+ $this->_buffer->setWriteTranslations(array());
+ $this->executeCommand("\r\n.\r\n", array(250));
+ }
+
+ /** Determine the best-use reverse path for this message */
+ protected function _getReversePath(Swift_Mime_Message $message)
+ {
+ $return = $message->getReturnPath();
+ $sender = $message->getSender();
+ $from = $message->getFrom();
+ $path = null;
+ if (!empty($return)) {
+ $path = $return;
+ } elseif (!empty($sender)) {
+ // Don't use array_keys
+ reset($sender); // Reset Pointer to first pos
+ $path = key($sender); // Get key
+ } elseif (!empty($from)) {
+ reset($from); // Reset Pointer to first pos
+ $path = key($from); // Get key
+ }
+
+ return $path;
+ }
+
+ /** Throw a TransportException, first sending it to any listeners */
+ protected function _throwException(Swift_TransportException $e)
+ {
+ if ($evt = $this->_eventDispatcher->createTransportExceptionEvent($this, $e)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'exceptionThrown');
+ if (!$evt->bubbleCancelled()) {
+ throw $e;
+ }
+ } else {
+ throw $e;
+ }
+ }
+
+ /** Throws an Exception if a response code is incorrect */
+ protected function _assertResponseCode($response, $wanted)
+ {
+ list($code) = sscanf($response, '%3d');
+ $valid = (empty($wanted) || in_array($code, $wanted));
+
+ if ($evt = $this->_eventDispatcher->createResponseEvent($this, $response,
+ $valid))
+ {
+ $this->_eventDispatcher->dispatchEvent($evt, 'responseReceived');
+ }
+
+ if (!$valid) {
+ $this->_throwException(
+ new Swift_TransportException(
+ 'Expected response code ' . implode('/', $wanted) . ' but got code ' .
+ '"' . $code . '", with message "' . $response . '"',
+ $code)
+ );
+ }
+ }
+
+ /** Get an entire multi-line response using its sequence number */
+ protected function _getFullResponse($seq)
+ {
+ $response = '';
+ try {
+ do {
+ $line = $this->_buffer->readLine($seq);
+ $response .= $line;
+ } while (null !== $line && false !== $line && ' ' != $line{3});
+ } catch (Swift_TransportException $e) {
+ $this->_throwException($e);
+ } catch (Swift_IoException $e) {
+ $this->_throwException(
+ new Swift_TransportException(
+ $e->getMessage())
+ );
+ }
+
+ return $response;
+ }
+
+
+ /** Send an email to the given recipients from the given reverse path */
+ private function _doMailTransaction($message, $reversePath, array $recipients, array &$failedRecipients)
+ {
+ $sent = 0;
+ $this->_doMailFromCommand($reversePath);
+ foreach ($recipients as $forwardPath) {
+ try {
+ $this->_doRcptToCommand($forwardPath);
+ $sent++;
+ } catch (Swift_TransportException $e) {
+ $failedRecipients[] = $forwardPath;
+ }
+ }
+
+ if ($sent != 0) {
+ $this->_doDataCommand();
+ $this->_streamMessage($message);
+ } else {
+ $this->reset();
+ }
+
+ return $sent;
+ }
+
+ /** Send a message to the given To: recipients */
+ private function _sendTo(Swift_Mime_Message $message, $reversePath, array $to, array &$failedRecipients)
+ {
+ if (empty($to)) {
+ return 0;
+ }
+
+ return $this->_doMailTransaction($message, $reversePath, array_keys($to),
+ $failedRecipients);
+ }
+
+ /** Send a message to the given Cc: recipients */
+ private function _sendCc(Swift_Mime_Message $message, $reversePath, array $cc, array &$failedRecipients)
+ {
+ if (empty($cc)) {
+ return 0;
+ }
+
+ return $this->_doMailTransaction($message, $reversePath, array_keys($cc),
+ $failedRecipients);
+ }
+
+ /** Send a message to all Bcc: recipients */
+ private function _sendBcc(Swift_Mime_Message $message, $reversePath, array $bcc, array &$failedRecipients)
+ {
+ $sent = 0;
+ foreach ($bcc as $forwardPath => $name) {
+ $message->setBcc(array($forwardPath => $name));
+ $sent += $this->_doMailTransaction(
+ $message, $reversePath, array($forwardPath), $failedRecipients
+ );
+ }
+
+ return $sent;
+ }
+
+ /** Try to determine the hostname of the server this is run on */
+ private function _lookupHostname()
+ {
+ if (!empty($_SERVER['SERVER_NAME'])
+ && $this->_isFqdn($_SERVER['SERVER_NAME']))
+ {
+ $this->_domain = $_SERVER['SERVER_NAME'];
+ } elseif (!empty($_SERVER['SERVER_ADDR'])) {
+ $this->_domain = sprintf('[%s]', $_SERVER['SERVER_ADDR']);
+ }
+ }
+
+ /** Determine is the $hostname is a fully-qualified name */
+ private function _isFqdn($hostname)
+ {
+ // We could do a really thorough check, but there's really no point
+ if (false !== $dotPos = strpos($hostname, '.')) {
+ return ($dotPos > 0) && ($dotPos != strlen($hostname) - 1);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Destructor.
+ */
+ public function __destruct()
+ {
+ $this->stop();
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php
new file mode 100644
index 00000000..98ee0651
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php
@@ -0,0 +1,81 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles CRAM-MD5 authentication.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Transport_Esmtp_Auth_CramMd5Authenticator implements Swift_Transport_Esmtp_Authenticator
+{
+ /**
+ * Get the name of the AUTH mechanism this Authenticator handles.
+ *
+ * @return string
+ */
+ public function getAuthKeyword()
+ {
+ return 'CRAM-MD5';
+ }
+
+ /**
+ * Try to authenticate the user with $username and $password.
+ *
+ * @param Swift_Transport_SmtpAgent $agent
+ * @param string $username
+ * @param string $password
+ *
+ * @return bool
+ */
+ public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password)
+ {
+ try {
+ $challenge = $agent->executeCommand("AUTH CRAM-MD5\r\n", array(334));
+ $challenge = base64_decode(substr($challenge, 4));
+ $message = base64_encode(
+ $username . ' ' . $this->_getResponse($password, $challenge)
+ );
+ $agent->executeCommand(sprintf("%s\r\n", $message), array(235));
+
+ return true;
+ } catch (Swift_TransportException $e) {
+ $agent->executeCommand("RSET\r\n", array(250));
+
+ return false;
+ }
+ }
+
+ /**
+ * Generate a CRAM-MD5 response from a server challenge.
+ *
+ * @param string $secret
+ * @param string $challenge
+ *
+ * @return string
+ */
+ private function _getResponse($secret, $challenge)
+ {
+ if (strlen($secret) > 64) {
+ $secret = pack('H32', md5($secret));
+ }
+
+ if (strlen($secret) < 64) {
+ $secret = str_pad($secret, 64, chr(0));
+ }
+
+ $k_ipad = substr($secret, 0, 64) ^ str_repeat(chr(0x36), 64);
+ $k_opad = substr($secret, 0, 64) ^ str_repeat(chr(0x5C), 64);
+
+ $inner = pack('H32', md5($k_ipad . $challenge));
+ $digest = md5($k_opad . $inner);
+
+ return $digest;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php
new file mode 100644
index 00000000..ebb35520
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles LOGIN authentication.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Transport_Esmtp_Auth_LoginAuthenticator implements Swift_Transport_Esmtp_Authenticator
+{
+ /**
+ * Get the name of the AUTH mechanism this Authenticator handles.
+ *
+ * @return string
+ */
+ public function getAuthKeyword()
+ {
+ return 'LOGIN';
+ }
+
+ /**
+ * Try to authenticate the user with $username and $password.
+ *
+ * @param Swift_Transport_SmtpAgent $agent
+ * @param string $username
+ * @param string $password
+ *
+ * @return bool
+ */
+ public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password)
+ {
+ try {
+ $agent->executeCommand("AUTH LOGIN\r\n", array(334));
+ $agent->executeCommand(sprintf("%s\r\n", base64_encode($username)), array(334));
+ $agent->executeCommand(sprintf("%s\r\n", base64_encode($password)), array(235));
+
+ return true;
+ } catch (Swift_TransportException $e) {
+ $agent->executeCommand("RSET\r\n", array(250));
+
+ return false;
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php
new file mode 100644
index 00000000..1514cbbe
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php
@@ -0,0 +1,699 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * This authentication is for Exchange servers. We support version 1 & 2.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles NTLM authentication.
+ *
+ * @author Ward Peeters <ward@coding-tech.com>
+ */
+class Swift_Transport_Esmtp_Auth_NTLMAuthenticator implements Swift_Transport_Esmtp_Authenticator
+{
+ const NTLMSIG = "NTLMSSP\x00";
+ const DESCONST = "KGS!@#$%";
+
+ /**
+ * Get the name of the AUTH mechanism this Authenticator handles.
+ *
+ * @return string
+ */
+ public function getAuthKeyword()
+ {
+ return 'NTLM';
+ }
+
+ /**
+ * Try to authenticate the user with $username and $password.
+ *
+ * @param Swift_Transport_SmtpAgent $agent
+ * @param string $username
+ * @param string $password
+ *
+ * @return bool
+ */
+ public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password)
+ {
+ if (!function_exists('mcrypt_module_open')) {
+ throw new LogicException('The mcrypt functions need to be enabled to use the NTLM authenticator.');
+ }
+
+ if (!function_exists('openssl_random_pseudo_bytes')) {
+ throw new LogicException('The OpenSSL extension must be enabled to use the NTLM authenticator.');
+ }
+
+ if (!function_exists('bcmul')) {
+ throw new LogicException('The BCMatch functions must be enabled to use the NTLM authenticator.');
+ }
+
+ try {
+ // execute AUTH command and filter out the code at the beginning
+ // AUTH NTLM xxxx
+ $response = base64_decode(substr(trim($this->sendMessage1($agent)), 4));
+
+ // extra parameters for our unit cases
+ $timestamp = func_num_args() > 3 ? func_get_arg(3) : $this->getCorrectTimestamp(bcmul(microtime(true), "1000"));
+ $client = func_num_args() > 4 ? func_get_arg(4) : $this->getRandomBytes(8);
+
+ // Message 3 response
+ $this->sendMessage3($response, $username, $password, $timestamp, $client, $agent);
+
+ return true;
+ } catch (Swift_TransportException $e) {
+ $agent->executeCommand("RSET\r\n", array(250));
+
+ return false;
+ }
+ }
+
+ protected function si2bin($si, $bits = 32)
+ {
+ $bin = null;
+ if ($si >= -pow(2, $bits - 1) && ($si <= pow(2, $bits - 1))) {
+ // positive or zero
+ if ($si >= 0) {
+ $bin = base_convert($si, 10, 2);
+ // pad to $bits bit
+ $bin_length = strlen($bin);
+ if ($bin_length < $bits) {
+ $bin = str_repeat("0", $bits - $bin_length) . $bin;
+ }
+ } else { // negative
+ $si = -$si - pow(2, $bits);
+ $bin = base_convert($si, 10, 2);
+ $bin_length = strlen($bin);
+ if ($bin_length > $bits) {
+ $bin = str_repeat("1", $bits - $bin_length) . $bin;
+ }
+ }
+ }
+
+ return $bin;
+ }
+
+ /**
+ * Send our auth message and returns the response
+ *
+ * @param Swift_Transport_SmtpAgent $agent
+ * @return string SMTP Response
+ */
+ protected function sendMessage1(Swift_Transport_SmtpAgent $agent)
+ {
+ $message = $this->createMessage1();
+
+ return $agent->executeCommand(sprintf("AUTH %s %s\r\n", $this->getAuthKeyword(), base64_encode($message)), array(334));
+ }
+
+ /**
+ * Fetch all details of our response (message 2)
+ *
+ * @param string $response
+ * @return array our response parsed
+ */
+ protected function parseMessage2($response)
+ {
+ $responseHex = bin2hex($response);
+ $length = floor(hexdec(substr($responseHex, 28, 4)) / 256) * 2;
+ $offset = floor(hexdec(substr($responseHex, 32, 4)) / 256) * 2;
+ $challenge = $this->hex2bin(substr($responseHex, 48, 16));
+ $context = $this->hex2bin(substr($responseHex, 64, 16));
+ $targetInfoH = $this->hex2bin(substr($responseHex, 80, 16));
+ $targetName = $this->hex2bin(substr($responseHex, $offset, $length));
+ $offset = floor(hexdec(substr($responseHex, 88, 4)) / 256) * 2;
+ $targetInfoBlock = substr($responseHex, $offset);
+ list($domainName, $serverName, $DNSDomainName, $DNSServerName, $terminatorByte) = $this->readSubBlock($targetInfoBlock);
+
+ return array(
+ $challenge,
+ $context,
+ $targetInfoH,
+ $targetName,
+ $domainName,
+ $serverName,
+ $DNSDomainName,
+ $DNSServerName,
+ $this->hex2bin($targetInfoBlock),
+ $terminatorByte
+ );
+ }
+
+ /**
+ * Read the blob information in from message2
+ *
+ * @param $block
+ * @return array
+ */
+ protected function readSubBlock($block)
+ {
+ // remove terminatorByte cause it's always the same
+ $block = substr($block, 0, -8);
+
+ $length = strlen($block);
+ $offset = 0;
+ $data = array();
+ while ($offset < $length) {
+ $blockLength = hexdec(substr(substr($block, $offset, 8), -4)) / 256;
+ $offset += 8;
+ $data[] = $this->hex2bin(substr($block, $offset, $blockLength * 2));
+ $offset += $blockLength * 2;
+ }
+
+ if (count($data) == 3) {
+ $data[] = $data[2];
+ $data[2] = '';
+ }
+
+ $data[] = $this->createByte('00');
+
+ return $data;
+ }
+
+ /**
+ * Send our final message with all our data
+ *
+ * @param string $response Message 1 response (message 2)
+ * @param string $username
+ * @param string $password
+ * @param string $timestamp
+ * @param string $client
+ * @param Swift_Transport_SmtpAgent $agent
+ * @param bool $v2 Use version2 of the protocol
+ * @return string
+ */
+ protected function sendMessage3($response, $username, $password, $timestamp, $client, Swift_Transport_SmtpAgent $agent, $v2 = true)
+ {
+ list($domain, $username) = $this->getDomainAndUsername($username);
+ //$challenge, $context, $targetInfoH, $targetName, $domainName, $workstation, $DNSDomainName, $DNSServerName, $blob, $ter
+ list($challenge, , , , , $workstation, , , $blob) = $this->parseMessage2($response);
+
+ if (!$v2) {
+ // LMv1
+ $lmResponse = $this->createLMPassword($password, $challenge);
+ // NTLMv1
+ $ntlmResponse = $this->createNTLMPassword($password, $challenge);
+ } else {
+ // LMv2
+ $lmResponse = $this->createLMv2Password($password, $username, $domain, $challenge, $client);
+ // NTLMv2
+ $ntlmResponse = $this->createNTLMv2Hash($password, $username, $domain, $challenge, $blob, $timestamp, $client);
+ }
+
+ $message = $this->createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse);
+
+ return $agent->executeCommand(sprintf("%s\r\n", base64_encode($message)), array(235));
+ }
+
+ /**
+ * Create our message 1
+ *
+ * @return string
+ */
+ protected function createMessage1()
+ {
+ return self::NTLMSIG
+ . $this->createByte('01') // Message 1
+ . $this->createByte('0702'); // Flags
+ }
+
+ /**
+ * Create our message 3
+ *
+ * @param string $domain
+ * @param string $username
+ * @param string $workstation
+ * @param string $lmResponse
+ * @param string $ntlmResponse
+ * @return string
+ */
+ protected function createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse)
+ {
+ // Create security buffers
+ $domainSec = $this->createSecurityBuffer($domain, 64);
+ $domainInfo = $this->readSecurityBuffer(bin2hex($domainSec));
+ $userSec = $this->createSecurityBuffer($username, ($domainInfo[0] + $domainInfo[1]) / 2);
+ $userInfo = $this->readSecurityBuffer(bin2hex($userSec));
+ $workSec = $this->createSecurityBuffer($workstation, ($userInfo[0] + $userInfo[1]) / 2);
+ $workInfo = $this->readSecurityBuffer(bin2hex($workSec));
+ $lmSec = $this->createSecurityBuffer($lmResponse, ($workInfo[0] + $workInfo[1]) / 2, true);
+ $lmInfo = $this->readSecurityBuffer(bin2hex($lmSec));
+ $ntlmSec = $this->createSecurityBuffer($ntlmResponse, ($lmInfo[0] + $lmInfo[1]) / 2, true);
+
+ return self::NTLMSIG
+ . $this->createByte('03') // TYPE 3 message
+ . $lmSec // LM response header
+ . $ntlmSec // NTLM response header
+ . $domainSec // Domain header
+ . $userSec // User header
+ . $workSec // Workstation header
+ . $this->createByte("000000009a", 8) // session key header (empty)
+ . $this->createByte('01020000') // FLAGS
+ . $this->convertTo16bit($domain) // domain name
+ . $this->convertTo16bit($username) // username
+ . $this->convertTo16bit($workstation) // workstation
+ . $lmResponse
+ . $ntlmResponse;
+ }
+
+ /**
+ * @param string $timestamp Epoch timestamp in microseconds
+ * @param string $client Random bytes
+ * @param string $targetInfo
+ * @return string
+ */
+ protected function createBlob($timestamp, $client, $targetInfo)
+ {
+ return $this->createByte('0101')
+ . $this->createByte('00')
+ . $timestamp
+ . $client
+ . $this->createByte('00')
+ . $targetInfo
+ . $this->createByte('00');
+ }
+
+ /**
+ * Get domain and username from our username
+ *
+ * @example DOMAIN\username
+ *
+ * @param string $name
+ * @return array
+ */
+ protected function getDomainAndUsername($name)
+ {
+ if (strpos($name, '\\') !== false) {
+ return explode('\\', $name);
+ }
+
+ list($user, $domain) = explode('@', $name);
+
+ return array($domain, $user);
+ }
+
+ /**
+ * Create LMv1 response
+ *
+ * @param string $password
+ * @param string $challenge
+ * @return string
+ */
+ protected function createLMPassword($password, $challenge)
+ {
+ // FIRST PART
+ $password = $this->createByte(strtoupper($password), 14, false);
+ list($key1, $key2) = str_split($password, 7);
+
+ $desKey1 = $this->createDesKey($key1);
+ $desKey2 = $this->createDesKey($key2);
+
+ $constantDecrypt = $this->createByte($this->desEncrypt(self::DESCONST, $desKey1) . $this->desEncrypt(self::DESCONST, $desKey2), 21, false);
+
+ // SECOND PART
+ list($key1, $key2, $key3) = str_split($constantDecrypt, 7);
+
+ $desKey1 = $this->createDesKey($key1);
+ $desKey2 = $this->createDesKey($key2);
+ $desKey3 = $this->createDesKey($key3);
+
+ return $this->desEncrypt($challenge, $desKey1) . $this->desEncrypt($challenge, $desKey2) . $this->desEncrypt($challenge, $desKey3);
+ }
+
+ /**
+ * Create NTLMv1 response
+ *
+ * @param string $password
+ * @param string $challenge
+ * @return string
+ */
+ protected function createNTLMPassword($password, $challenge)
+ {
+ // FIRST PART
+ $ntlmHash = $this->createByte($this->md4Encrypt($password), 21, false);
+ list($key1, $key2, $key3) = str_split($ntlmHash, 7);
+
+ $desKey1 = $this->createDesKey($key1);
+ $desKey2 = $this->createDesKey($key2);
+ $desKey3 = $this->createDesKey($key3);
+
+ return $this->desEncrypt($challenge, $desKey1) . $this->desEncrypt($challenge, $desKey2) . $this->desEncrypt($challenge, $desKey3);
+ }
+
+ /**
+ * Convert a normal timestamp to a tenth of a microtime epoch time
+ *
+ * @param string $time
+ * @return string
+ */
+ protected function getCorrectTimestamp($time)
+ {
+ // Get our timestamp (tricky!)
+ bcscale(0);
+
+ $time = number_format($time, 0, '.', ''); // save microtime to string
+ $time = bcadd($time, "11644473600000"); // add epoch time
+ $time = bcmul($time, 10000); // tenths of a microsecond.
+
+ $binary = $this->si2bin($time, 64); // create 64 bit binary string
+ $timestamp = "";
+ for ($i = 0; $i < 8; $i++) {
+ $timestamp .= chr(bindec(substr($binary, -(($i + 1) * 8), 8)));
+ }
+
+ return $timestamp;
+ }
+
+ /**
+ * Create LMv2 response
+ *
+ * @param string $password
+ * @param string $username
+ * @param string $domain
+ * @param string $challenge NTLM Challenge
+ * @param string $client Random string
+ * @return string
+ */
+ protected function createLMv2Password($password, $username, $domain, $challenge, $client)
+ {
+ $lmPass = '00'; // by default 00
+ // if $password > 15 than we can't use this method
+ if (strlen($password) <= 15) {
+ $ntlmHash = $this->md4Encrypt($password);
+ $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username) . $domain));
+
+ $lmPass = bin2hex($this->md5Encrypt($ntml2Hash, $challenge . $client) . $client);
+ }
+
+ return $this->createByte($lmPass, 24);
+ }
+
+ /**
+ * Create NTLMv2 response
+ *
+ * @param string $password
+ * @param string $username
+ * @param string $domain
+ * @param string $challenge Hex values
+ * @param string $targetInfo Hex values
+ * @param string $timestamp
+ * @param string $client Random bytes
+ * @return string
+ * @see http://davenport.sourceforge.net/ntlm.html#theNtlmResponse
+ */
+ protected function createNTLMv2Hash($password, $username, $domain, $challenge, $targetInfo, $timestamp, $client)
+ {
+ $ntlmHash = $this->md4Encrypt($password);
+ $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username) . $domain));
+
+ // create blob
+ $blob = $this->createBlob($timestamp, $client, $targetInfo);
+
+ $ntlmv2Response = $this->md5Encrypt($ntml2Hash, $challenge . $blob);
+
+ return $ntlmv2Response . $blob;
+ }
+
+ protected function createDesKey($key)
+ {
+ $material = array(bin2hex($key[0]));
+ $len = strlen($key);
+ for ($i = 1; $i < $len; $i++) {
+ list($high, $low) = str_split(bin2hex($key[$i]));
+ $v = $this->castToByte(ord($key[$i - 1]) << (7 + 1 - $i) | $this->uRShift(hexdec(dechex(hexdec($high) & 0xf) . dechex(hexdec($low) & 0xf)), $i));
+ $material[] = str_pad(substr(dechex($v), -2), 2, '0', STR_PAD_LEFT); // cast to byte
+ }
+ $material[] = str_pad(substr(dechex($this->castToByte(ord($key[6]) << 1)), -2), 2, '0');
+
+ // odd parity
+ foreach ($material as $k => $v) {
+ $b = $this->castToByte(hexdec($v));
+ $needsParity = (($this->uRShift($b, 7) ^ $this->uRShift($b, 6) ^ $this->uRShift($b, 5)
+ ^ $this->uRShift($b, 4) ^ $this->uRShift($b, 3) ^ $this->uRShift($b, 2)
+ ^ $this->uRShift($b, 1)) & 0x01) == 0;
+
+ list($high, $low) = str_split($v);
+ if ($needsParity) {
+ $material[$k] = dechex(hexdec($high) | 0x0) . dechex(hexdec($low) | 0x1);
+ } else {
+ $material[$k] = dechex(hexdec($high) & 0xf) . dechex(hexdec($low) & 0xe);
+ }
+ }
+
+ return $this->hex2bin(implode('', $material));
+ }
+
+ /** HELPER FUNCTIONS */
+ /**
+ * Create our security buffer depending on length and offset
+ *
+ * @param string $value Value we want to put in
+ * @param int $offset start of value
+ * @param bool $is16 Do we 16bit string or not?
+ * @return string
+ */
+ protected function createSecurityBuffer($value, $offset, $is16 = false)
+ {
+ $length = strlen(bin2hex($value));
+ $length = $is16 ? $length / 2 : $length;
+ $length = $this->createByte(str_pad(dechex($length), 2, '0', STR_PAD_LEFT), 2);
+
+ return $length . $length . $this->createByte(dechex($offset), 4);
+ }
+
+ /**
+ * Read our security buffer to fetch length and offset of our value
+ *
+ * @param string $value Securitybuffer in hex
+ * @return array array with length and offset
+ */
+ protected function readSecurityBuffer($value)
+ {
+ $length = floor(hexdec(substr($value, 0, 4)) / 256) * 2;
+ $offset = floor(hexdec(substr($value, 8, 4)) / 256) * 2;
+
+ return array($length, $offset);
+ }
+
+ /**
+ * Cast to byte java equivalent to (byte)
+ *
+ * @param int $v
+ * @return int
+ */
+ protected function castToByte($v)
+ {
+ return (($v + 128) % 256) - 128;
+ }
+
+ /**
+ * Java unsigned right bitwise
+ * $a >>> $b
+ *
+ * @param int $a
+ * @param int $b
+ * @return int
+ */
+ protected function uRShift($a, $b)
+ {
+ if ($b == 0) {
+ return $a;
+ }
+
+ return ($a >> $b) & ~(1 << (8 * PHP_INT_SIZE - 1) >> ($b - 1));
+ }
+
+ /**
+ * Right padding with 0 to certain length
+ *
+ * @param string $input
+ * @param int $bytes Length of bytes
+ * @param bool $isHex Did we provided hex value
+ * @return string
+ */
+ protected function createByte($input, $bytes = 4, $isHex = true)
+ {
+ if ($isHex) {
+ $byte = $this->hex2bin(str_pad($input, $bytes * 2, '00'));
+ } else {
+ $byte = str_pad($input, $bytes, "\x00");
+ }
+
+ return $byte;
+ }
+
+ /**
+ * Create random bytes
+ *
+ * @param $length
+ * @return string
+ */
+ protected function getRandomBytes($length)
+ {
+ $bytes = openssl_random_pseudo_bytes($length, $strong);
+
+ if (false !== $bytes && true === $strong) {
+ return $bytes;
+ }
+
+ throw new RuntimeException('OpenSSL did not produce a secure random number.');
+ }
+
+ /** ENCRYPTION ALGORITHMS */
+ /**
+ * DES Encryption
+ *
+ * @param string $value
+ * @param string $key
+ * @return string
+ */
+ protected function desEncrypt($value, $key)
+ {
+ $cipher = mcrypt_module_open(MCRYPT_DES, '', 'ecb', '');
+ mcrypt_generic_init($cipher, $key, mcrypt_create_iv(mcrypt_enc_get_iv_size($cipher), MCRYPT_DEV_RANDOM));
+
+ return mcrypt_generic($cipher, $value);
+ }
+
+ /**
+ * MD5 Encryption
+ *
+ * @param string $key Encryption key
+ * @param string $msg Message to encrypt
+ * @return string
+ */
+ protected function md5Encrypt($key, $msg)
+ {
+ $blocksize = 64;
+ if (strlen($key) > $blocksize) {
+ $key = pack('H*', md5($key));
+ }
+
+ $key = str_pad($key, $blocksize, "\0");
+ $ipadk = $key ^ str_repeat("\x36", $blocksize);
+ $opadk = $key ^ str_repeat("\x5c", $blocksize);
+
+ return pack('H*', md5($opadk . pack('H*', md5($ipadk . $msg))));
+ }
+
+ /**
+ * MD4 Encryption
+ *
+ * @param string $input
+ * @return string
+ * @see http://php.net/manual/en/ref.hash.php
+ */
+ protected function md4Encrypt($input)
+ {
+ $input = $this->convertTo16bit($input);
+
+ return function_exists('hash') ? $this->hex2bin(hash('md4', $input)) : mhash(MHASH_MD4, $input);
+ }
+
+ /**
+ * Convert UTF-8 to UTF-16
+ *
+ * @param string $input
+ * @return string
+ */
+ protected function convertTo16bit($input)
+ {
+ return iconv('UTF-8', 'UTF-16LE', $input);
+ }
+
+ /**
+ * Hex2bin replacement for < PHP 5.4
+ * @param string $hex
+ * @return string Binary
+ */
+ protected function hex2bin($hex)
+ {
+ if (function_exists('hex2bin')) {
+ return hex2bin($hex);
+ } else {
+ return pack('H*', $hex);
+ }
+ }
+
+ /**
+ * @param string $message
+ */
+ protected function debug($message)
+ {
+ $message = bin2hex($message);
+ $messageId = substr($message, 16, 8);
+ echo substr($message, 0, 16) . " NTLMSSP Signature<br />\n";
+ echo $messageId . " Type Indicator<br />\n";
+
+ if ($messageId == "02000000") {
+ $map = array(
+ 'Challenge',
+ 'Context',
+ 'Target Information Security Buffer',
+ 'Target Name Data',
+ 'NetBIOS Domain Name',
+ 'NetBIOS Server Name',
+ 'DNS Domain Name',
+ 'DNS Server Name',
+ 'BLOB',
+ 'Target Information Terminator',
+ );
+
+ $data = $this->parseMessage2($this->hex2bin($message));
+
+ foreach ($map as $key => $value) {
+ echo bin2hex($data[$key]) . ' - ' . $data[$key] . ' ||| ' . $value . "<br />\n";
+ }
+ } elseif ($messageId == "03000000") {
+ $i = 0;
+ $data[$i++] = substr($message, 24, 16);
+ list($lmLength, $lmOffset) = $this->readSecurityBuffer($data[$i - 1]);
+
+ $data[$i++] = substr($message, 40, 16);
+ list($ntmlLength, $ntmlOffset) = $this->readSecurityBuffer($data[$i - 1]);
+
+ $data[$i++] = substr($message, 56, 16);
+ list($targetLength, $targetOffset) = $this->readSecurityBuffer($data[$i - 1]);
+
+ $data[$i++] = substr($message, 72, 16);
+ list($userLength, $userOffset) = $this->readSecurityBuffer($data[$i - 1]);
+
+ $data[$i++] = substr($message, 88, 16);
+ list($workLength, $workOffset) = $this->readSecurityBuffer($data[$i - 1]);
+
+ $data[$i++] = substr($message, 104, 16);
+ $data[$i++] = substr($message, 120, 8);
+ $data[$i++] = substr($message, $targetOffset, $targetLength);
+ $data[$i++] = substr($message, $userOffset, $userLength);
+ $data[$i++] = substr($message, $workOffset, $workLength);
+ $data[$i++] = substr($message, $lmOffset, $lmLength);
+ $data[$i] = substr($message, $ntmlOffset, $ntmlLength);
+
+ $map = array(
+ 'LM Response Security Buffer',
+ 'NTLM Response Security Buffer',
+ 'Target Name Security Buffer',
+ 'User Name Security Buffer',
+ 'Workstation Name Security Buffer',
+ 'Session Key Security Buffer',
+ 'Flags',
+ 'Target Name Data',
+ 'User Name Data',
+ 'Workstation Name Data',
+ 'LM Response Data',
+ 'NTLM Response Data',
+ );
+
+ foreach ($map as $key => $value) {
+ echo $data[$key] . ' - ' . $this->hex2bin($data[$key]) . ' ||| ' . $value . "<br />\n";
+ }
+ }
+
+ echo "<br /><br />";
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php
new file mode 100644
index 00000000..9143ce94
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php
@@ -0,0 +1,50 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles PLAIN authentication.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Transport_Esmtp_Auth_PlainAuthenticator implements Swift_Transport_Esmtp_Authenticator
+{
+ /**
+ * Get the name of the AUTH mechanism this Authenticator handles.
+ *
+ * @return string
+ */
+ public function getAuthKeyword()
+ {
+ return 'PLAIN';
+ }
+
+ /**
+ * Try to authenticate the user with $username and $password.
+ *
+ * @param Swift_Transport_SmtpAgent $agent
+ * @param string $username
+ * @param string $password
+ *
+ * @return bool
+ */
+ public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password)
+ {
+ try {
+ $message = base64_encode($username . chr(0) . $username . chr(0) . $password);
+ $agent->executeCommand(sprintf("AUTH PLAIN %s\r\n", $message), array(235));
+
+ return true;
+ } catch (Swift_TransportException $e) {
+ $agent->executeCommand("RSET\r\n", array(250));
+
+ return false;
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php
new file mode 100644
index 00000000..38189881
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php
@@ -0,0 +1,69 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Handles XOAUTH2 authentication.
+ *
+ * Example:
+ * <code>
+ * $transport = Swift_SmtpTransport::newInstance('smtp.gmail.com', 587, 'tls')
+ * ->setAuthMode('XOAUTH2')
+ * ->setUsername('YOUR_EMAIL_ADDRESS')
+ * ->setPassword('YOUR_ACCESS_TOKEN');
+ * </code>
+ *
+ * @author xu.li<AthenaLightenedMyPath@gmail.com>
+ * @see https://developers.google.com/google-apps/gmail/xoauth2_protocol
+ */
+class Swift_Transport_Esmtp_Auth_XOAuth2Authenticator implements Swift_Transport_Esmtp_Authenticator
+{
+ /**
+ * Get the name of the AUTH mechanism this Authenticator handles.
+ *
+ * @return string
+ */
+ public function getAuthKeyword()
+ {
+ return 'XOAUTH2';
+ }
+
+ /**
+ * Try to authenticate the user with $email and $token.
+ *
+ * @param Swift_Transport_SmtpAgent $agent
+ * @param string $email
+ * @param string $token
+ *
+ * @return bool
+ */
+ public function authenticate(Swift_Transport_SmtpAgent $agent, $email, $token)
+ {
+ try {
+ $param = $this->constructXOAuth2Params($email, $token);
+ $agent->executeCommand("AUTH XOAUTH2 " . $param . "\r\n", array(235));
+
+ return true;
+ } catch (Swift_TransportException $e) {
+ $agent->executeCommand("RSET\r\n", array(250));
+
+ return false;
+ }
+ }
+
+ /**
+ * Construct the auth parameter
+ *
+ * @see https://developers.google.com/google-apps/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism
+ */
+ protected function constructXOAuth2Params($email, $token)
+ {
+ return base64_encode("user=$email\1auth=Bearer $token\1\1");
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/Esmtp/AuthHandler.php b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/AuthHandler.php
new file mode 100644
index 00000000..ee2f56d2
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/AuthHandler.php
@@ -0,0 +1,264 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An ESMTP handler for AUTH support.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Transport_Esmtp_AuthHandler implements Swift_Transport_EsmtpHandler
+{
+ /**
+ * Authenticators available to process the request.
+ *
+ * @var Swift_Transport_Esmtp_Authenticator[]
+ */
+ private $_authenticators = array();
+
+ /**
+ * The username for authentication.
+ *
+ * @var string
+ */
+ private $_username;
+
+ /**
+ * The password for authentication.
+ *
+ * @var string
+ */
+ private $_password;
+
+ /**
+ * The auth mode for authentication.
+ *
+ * @var string
+ */
+ private $_auth_mode;
+
+ /**
+ * The ESMTP AUTH parameters available.
+ *
+ * @var string[]
+ */
+ private $_esmtpParams = array();
+
+ /**
+ * Create a new AuthHandler with $authenticators for support.
+ *
+ * @param Swift_Transport_Esmtp_Authenticator[] $authenticators
+ */
+ public function __construct(array $authenticators)
+ {
+ $this->setAuthenticators($authenticators);
+ }
+
+ /**
+ * Set the Authenticators which can process a login request.
+ *
+ * @param Swift_Transport_Esmtp_Authenticator[] $authenticators
+ */
+ public function setAuthenticators(array $authenticators)
+ {
+ $this->_authenticators = $authenticators;
+ }
+
+ /**
+ * Get the Authenticators which can process a login request.
+ *
+ * @return Swift_Transport_Esmtp_Authenticator[]
+ */
+ public function getAuthenticators()
+ {
+ return $this->_authenticators;
+ }
+
+ /**
+ * Set the username to authenticate with.
+ *
+ * @param string $username
+ */
+ public function setUsername($username)
+ {
+ $this->_username = $username;
+ }
+
+ /**
+ * Get the username to authenticate with.
+ *
+ * @return string
+ */
+ public function getUsername()
+ {
+ return $this->_username;
+ }
+
+ /**
+ * Set the password to authenticate with.
+ *
+ * @param string $password
+ */
+ public function setPassword($password)
+ {
+ $this->_password = $password;
+ }
+
+ /**
+ * Get the password to authenticate with.
+ *
+ * @return string
+ */
+ public function getPassword()
+ {
+ return $this->_password;
+ }
+
+ /**
+ * Set the auth mode to use to authenticate.
+ *
+ * @param string $mode
+ */
+ public function setAuthMode($mode)
+ {
+ $this->_auth_mode = $mode;
+ }
+
+ /**
+ * Get the auth mode to use to authenticate.
+ *
+ * @return string
+ */
+ public function getAuthMode()
+ {
+ return $this->_auth_mode;
+ }
+
+ /**
+ * Get the name of the ESMTP extension this handles.
+ *
+ * @return bool
+ */
+ public function getHandledKeyword()
+ {
+ return 'AUTH';
+ }
+
+ /**
+ * Set the parameters which the EHLO greeting indicated.
+ *
+ * @param string[] $parameters
+ */
+ public function setKeywordParams(array $parameters)
+ {
+ $this->_esmtpParams = $parameters;
+ }
+
+ /**
+ * Runs immediately after a EHLO has been issued.
+ *
+ * @param Swift_Transport_SmtpAgent $agent to read/write
+ */
+ public function afterEhlo(Swift_Transport_SmtpAgent $agent)
+ {
+ if ($this->_username) {
+ $count = 0;
+ foreach ($this->_getAuthenticatorsForAgent() as $authenticator) {
+ if (in_array(strtolower($authenticator->getAuthKeyword()),
+ array_map('strtolower', $this->_esmtpParams)))
+ {
+ $count++;
+ if ($authenticator->authenticate($agent, $this->_username, $this->_password)) {
+ return;
+ }
+ }
+ }
+ throw new Swift_TransportException(
+ 'Failed to authenticate on SMTP server with username "' .
+ $this->_username . '" using ' . $count . ' possible authenticators'
+ );
+ }
+ }
+
+ /**
+ * Not used.
+ */
+ public function getMailParams()
+ {
+ return array();
+ }
+
+ /**
+ * Not used.
+ */
+ public function getRcptParams()
+ {
+ return array();
+ }
+
+ /**
+ * Not used.
+ */
+ public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = array(), &$failedRecipients = null, &$stop = false)
+ {
+ }
+
+ /**
+ * Returns +1, -1 or 0 according to the rules for usort().
+ *
+ * This method is called to ensure extensions can be execute in an appropriate order.
+ *
+ * @param string $esmtpKeyword to compare with
+ *
+ * @return int
+ */
+ public function getPriorityOver($esmtpKeyword)
+ {
+ return 0;
+ }
+
+ /**
+ * Returns an array of method names which are exposed to the Esmtp class.
+ *
+ * @return string[]
+ */
+ public function exposeMixinMethods()
+ {
+ return array('setUsername', 'getUsername', 'setPassword', 'getPassword', 'setAuthMode', 'getAuthMode');
+ }
+
+ /**
+ * Not used.
+ */
+ public function resetState()
+ {
+ }
+
+ /**
+ * Returns the authenticator list for the given agent.
+ *
+ * @param Swift_Transport_SmtpAgent $agent
+ *
+ * @return array
+ */
+ protected function _getAuthenticatorsForAgent()
+ {
+ if (!$mode = strtolower($this->_auth_mode)) {
+ return $this->_authenticators;
+ }
+
+ foreach ($this->_authenticators as $authenticator) {
+ if (strtolower($authenticator->getAuthKeyword()) == $mode) {
+ return array($authenticator);
+ }
+ }
+
+ throw new Swift_TransportException('Auth mode '.$mode.' is invalid');
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Authenticator.php b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Authenticator.php
new file mode 100644
index 00000000..9078003a
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/Esmtp/Authenticator.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An Authentication mechanism.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Transport_Esmtp_Authenticator
+{
+ /**
+ * Get the name of the AUTH mechanism this Authenticator handles.
+ *
+ * @return string
+ */
+ public function getAuthKeyword();
+
+ /**
+ * Try to authenticate the user with $username and $password.
+ *
+ * @param Swift_Transport_SmtpAgent $agent
+ * @param string $username
+ * @param string $password
+ *
+ * @return bool
+ */
+ public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/EsmtpHandler.php b/vendor/swiftmailer/classes/Swift/Transport/EsmtpHandler.php
new file mode 100644
index 00000000..cb76eddf
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/EsmtpHandler.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * An ESMTP handler.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Transport_EsmtpHandler
+{
+ /**
+ * Get the name of the ESMTP extension this handles.
+ *
+ * @return bool
+ */
+ public function getHandledKeyword();
+
+ /**
+ * Set the parameters which the EHLO greeting indicated.
+ *
+ * @param string[] $parameters
+ */
+ public function setKeywordParams(array $parameters);
+
+ /**
+ * Runs immediately after a EHLO has been issued.
+ *
+ * @param Swift_Transport_SmtpAgent $agent to read/write
+ */
+ public function afterEhlo(Swift_Transport_SmtpAgent $agent);
+
+ /**
+ * Get params which are appended to MAIL FROM:<>.
+ *
+ * @return string[]
+ */
+ public function getMailParams();
+
+ /**
+ * Get params which are appended to RCPT TO:<>.
+ *
+ * @return string[]
+ */
+ public function getRcptParams();
+
+ /**
+ * Runs when a command is due to be sent.
+ *
+ * @param Swift_Transport_SmtpAgent $agent to read/write
+ * @param string $command to send
+ * @param int[] $codes expected in response
+ * @param string[] $failedRecipients to collect failures
+ * @param bool $stop to be set true by-reference if the command is now sent
+ */
+ public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = array(), &$failedRecipients = null, &$stop = false);
+
+ /**
+ * Returns +1, -1 or 0 according to the rules for usort().
+ *
+ * This method is called to ensure extensions can be execute in an appropriate order.
+ *
+ * @param string $esmtpKeyword to compare with
+ *
+ * @return int
+ */
+ public function getPriorityOver($esmtpKeyword);
+
+ /**
+ * Returns an array of method names which are exposed to the Esmtp class.
+ *
+ * @return string[]
+ */
+ public function exposeMixinMethods();
+
+ /**
+ * Tells this handler to clear any buffers and reset its state.
+ */
+ public function resetState();
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/EsmtpTransport.php b/vendor/swiftmailer/classes/Swift/Transport/EsmtpTransport.php
new file mode 100644
index 00000000..d36ae93b
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/EsmtpTransport.php
@@ -0,0 +1,387 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Sends Messages over SMTP with ESMTP support.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Transport_EsmtpTransport extends Swift_Transport_AbstractSmtpTransport implements Swift_Transport_SmtpAgent
+{
+ /**
+ * ESMTP extension handlers.
+ *
+ * @var Swift_Transport_EsmtpHandler[]
+ */
+ private $_handlers = array();
+
+ /**
+ * ESMTP capabilities.
+ *
+ * @var string[]
+ */
+ private $_capabilities = array();
+
+ /**
+ * Connection buffer parameters.
+ *
+ * @var array
+ */
+ private $_params = array(
+ 'protocol' => 'tcp',
+ 'host' => 'localhost',
+ 'port' => 25,
+ 'timeout' => 30,
+ 'blocking' => 1,
+ 'tls' => false,
+ 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET
+ );
+
+ /**
+ * Creates a new EsmtpTransport using the given I/O buffer.
+ *
+ * @param Swift_Transport_IoBuffer $buf
+ * @param Swift_Transport_EsmtpHandler[] $extensionHandlers
+ * @param Swift_Events_EventDispatcher $dispatcher
+ */
+ public function __construct(Swift_Transport_IoBuffer $buf, array $extensionHandlers, Swift_Events_EventDispatcher $dispatcher)
+ {
+ parent::__construct($buf, $dispatcher);
+ $this->setExtensionHandlers($extensionHandlers);
+ }
+
+ /**
+ * Set the host to connect to.
+ *
+ * @param string $host
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setHost($host)
+ {
+ $this->_params['host'] = $host;
+
+ return $this;
+ }
+
+ /**
+ * Get the host to connect to.
+ *
+ * @return string
+ */
+ public function getHost()
+ {
+ return $this->_params['host'];
+ }
+
+ /**
+ * Set the port to connect to.
+ *
+ * @param int $port
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setPort($port)
+ {
+ $this->_params['port'] = (int) $port;
+
+ return $this;
+ }
+
+ /**
+ * Get the port to connect to.
+ *
+ * @return int
+ */
+ public function getPort()
+ {
+ return $this->_params['port'];
+ }
+
+ /**
+ * Set the connection timeout.
+ *
+ * @param int $timeout seconds
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setTimeout($timeout)
+ {
+ $this->_params['timeout'] = (int) $timeout;
+ $this->_buffer->setParam('timeout', (int) $timeout);
+
+ return $this;
+ }
+
+ /**
+ * Get the connection timeout.
+ *
+ * @return int
+ */
+ public function getTimeout()
+ {
+ return $this->_params['timeout'];
+ }
+
+ /**
+ * Set the encryption type (tls or ssl)
+ *
+ * @param string $encryption
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setEncryption($encryption)
+ {
+ if ('tls' == $encryption) {
+ $this->_params['protocol'] = 'tcp';
+ $this->_params['tls'] = true;
+ } else {
+ $this->_params['protocol'] = $encryption;
+ $this->_params['tls'] = false;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the encryption type.
+ *
+ * @return string
+ */
+ public function getEncryption()
+ {
+ return $this->_params['tls'] ? 'tls' : $this->_params['protocol'];
+ }
+
+ /**
+ * Sets the source IP.
+ *
+ * @param string $source
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setSourceIp($source)
+ {
+ $this->_params['sourceIp']=$source;
+
+ return $this;
+ }
+
+ /**
+ * Returns the IP used to connect to the destination.
+ *
+ * @return string
+ */
+ public function getSourceIp()
+ {
+ return $this->_params['sourceIp'];
+ }
+
+ /**
+ * Set ESMTP extension handlers.
+ *
+ * @param Swift_Transport_EsmtpHandler[] $handlers
+ *
+ * @return Swift_Transport_EsmtpTransport
+ */
+ public function setExtensionHandlers(array $handlers)
+ {
+ $assoc = array();
+ foreach ($handlers as $handler) {
+ $assoc[$handler->getHandledKeyword()] = $handler;
+ }
+ uasort($assoc, array($this, '_sortHandlers'));
+ $this->_handlers = $assoc;
+ $this->_setHandlerParams();
+
+ return $this;
+ }
+
+ /**
+ * Get ESMTP extension handlers.
+ *
+ * @return Swift_Transport_EsmtpHandler[]
+ */
+ public function getExtensionHandlers()
+ {
+ return array_values($this->_handlers);
+ }
+
+ /**
+ * Run a command against the buffer, expecting the given response codes.
+ *
+ * If no response codes are given, the response will not be validated.
+ * If codes are given, an exception will be thrown on an invalid response.
+ *
+ * @param string $command
+ * @param int[] $codes
+ * @param string[] $failures An array of failures by-reference
+ *
+ * @return string
+ */
+ public function executeCommand($command, $codes = array(), &$failures = null)
+ {
+ $failures = (array) $failures;
+ $stopSignal = false;
+ $response = null;
+ foreach ($this->_getActiveHandlers() as $handler) {
+ $response = $handler->onCommand(
+ $this, $command, $codes, $failures, $stopSignal
+ );
+ if ($stopSignal) {
+ return $response;
+ }
+ }
+
+ return parent::executeCommand($command, $codes, $failures);
+ }
+
+ // -- Mixin invocation code
+
+ /** Mixin handling method for ESMTP handlers */
+ public function __call($method, $args)
+ {
+ foreach ($this->_handlers as $handler) {
+ if (in_array(strtolower($method),
+ array_map('strtolower', (array) $handler->exposeMixinMethods())
+ ))
+ {
+ $return = call_user_func_array(array($handler, $method), $args);
+ // Allow fluid method calls
+ if (is_null($return) && substr($method, 0, 3) == 'set') {
+ return $this;
+ } else {
+ return $return;
+ }
+ }
+ }
+ trigger_error('Call to undefined method ' . $method, E_USER_ERROR);
+ }
+
+ /** Get the params to initialize the buffer */
+ protected function _getBufferParams()
+ {
+ return $this->_params;
+ }
+
+ /** Overridden to perform EHLO instead */
+ protected function _doHeloCommand()
+ {
+ try {
+ $response = $this->executeCommand(
+ sprintf("EHLO %s\r\n", $this->_domain), array(250)
+ );
+ } catch (Swift_TransportException $e) {
+ return parent::_doHeloCommand();
+ }
+
+ if ($this->_params['tls']) {
+ try {
+ $this->executeCommand("STARTTLS\r\n", array(220));
+
+ if (!$this->_buffer->startTLS()) {
+ throw new Swift_TransportException('Unable to connect with TLS encryption');
+ }
+
+ try {
+ $response = $this->executeCommand(
+ sprintf("EHLO %s\r\n", $this->_domain), array(250)
+ );
+ } catch (Swift_TransportException $e) {
+ return parent::_doHeloCommand();
+ }
+ } catch (Swift_TransportException $e) {
+ $this->_throwException($e);
+ }
+ }
+
+ $this->_capabilities = $this->_getCapabilities($response);
+ $this->_setHandlerParams();
+ foreach ($this->_getActiveHandlers() as $handler) {
+ $handler->afterEhlo($this);
+ }
+ }
+
+ /** Overridden to add Extension support */
+ protected function _doMailFromCommand($address)
+ {
+ $handlers = $this->_getActiveHandlers();
+ $params = array();
+ foreach ($handlers as $handler) {
+ $params = array_merge($params, (array) $handler->getMailParams());
+ }
+ $paramStr = !empty($params) ? ' ' . implode(' ', $params) : '';
+ $this->executeCommand(
+ sprintf("MAIL FROM: <%s>%s\r\n", $address, $paramStr), array(250)
+ );
+ }
+
+ /** Overridden to add Extension support */
+ protected function _doRcptToCommand($address)
+ {
+ $handlers = $this->_getActiveHandlers();
+ $params = array();
+ foreach ($handlers as $handler) {
+ $params = array_merge($params, (array) $handler->getRcptParams());
+ }
+ $paramStr = !empty($params) ? ' ' . implode(' ', $params) : '';
+ $this->executeCommand(
+ sprintf("RCPT TO: <%s>%s\r\n", $address, $paramStr), array(250, 251, 252)
+ );
+ }
+
+ /** Determine ESMTP capabilities by function group */
+ private function _getCapabilities($ehloResponse)
+ {
+ $capabilities = array();
+ $ehloResponse = trim($ehloResponse);
+ $lines = explode("\r\n", $ehloResponse);
+ array_shift($lines);
+ foreach ($lines as $line) {
+ if (preg_match('/^[0-9]{3}[ -]([A-Z0-9-]+)((?:[ =].*)?)$/Di', $line, $matches)) {
+ $keyword = strtoupper($matches[1]);
+ $paramStr = strtoupper(ltrim($matches[2], ' ='));
+ $params = !empty($paramStr) ? explode(' ', $paramStr) : array();
+ $capabilities[$keyword] = $params;
+ }
+ }
+
+ return $capabilities;
+ }
+
+ /** Set parameters which are used by each extension handler */
+ private function _setHandlerParams()
+ {
+ foreach ($this->_handlers as $keyword => $handler) {
+ if (array_key_exists($keyword, $this->_capabilities)) {
+ $handler->setKeywordParams($this->_capabilities[$keyword]);
+ }
+ }
+ }
+
+ /** Get ESMTP handlers which are currently ok to use */
+ private function _getActiveHandlers()
+ {
+ $handlers = array();
+ foreach ($this->_handlers as $keyword => $handler) {
+ if (array_key_exists($keyword, $this->_capabilities)) {
+ $handlers[] = $handler;
+ }
+ }
+
+ return $handlers;
+ }
+
+ /** Custom sort for extension handler ordering */
+ private function _sortHandlers($a, $b)
+ {
+ return $a->getPriorityOver($b->getHandledKeyword());
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/FailoverTransport.php b/vendor/swiftmailer/classes/Swift/Transport/FailoverTransport.php
new file mode 100644
index 00000000..020bd057
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/FailoverTransport.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Contains a list of redundant Transports so when one fails, the next is used.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Transport_FailoverTransport extends Swift_Transport_LoadBalancedTransport
+{
+ /**
+ * Registered transport currently used.
+ *
+ * @var Swift_Transport
+ */
+ private $_currentTransport;
+
+ /**
+ * Creates a new FailoverTransport.
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Send the given Message.
+ *
+ * Recipient/sender data will be retrieved from the Message API.
+ * The return value is the number of recipients who were accepted for delivery.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ $maxTransports = count($this->_transports);
+ $sent = 0;
+
+ for ($i = 0; $i < $maxTransports
+ && $transport = $this->_getNextTransport(); ++$i)
+ {
+ try {
+ if (!$transport->isStarted()) {
+ $transport->start();
+ }
+
+ return $transport->send($message, $failedRecipients);
+ } catch (Swift_TransportException $e) {
+ $this->_killCurrentTransport();
+ }
+ }
+
+ if (count($this->_transports) == 0) {
+ throw new Swift_TransportException(
+ 'All Transports in FailoverTransport failed, or no Transports available'
+ );
+ }
+
+ return $sent;
+ }
+
+ protected function _getNextTransport()
+ {
+ if (!isset($this->_currentTransport)) {
+ $this->_currentTransport = parent::_getNextTransport();
+ }
+
+ return $this->_currentTransport;
+ }
+
+ protected function _killCurrentTransport()
+ {
+ $this->_currentTransport = null;
+ parent::_killCurrentTransport();
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/IoBuffer.php b/vendor/swiftmailer/classes/Swift/Transport/IoBuffer.php
new file mode 100644
index 00000000..71b3f1e5
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/IoBuffer.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Buffers input and output to a resource.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Transport_IoBuffer extends Swift_InputByteStream, Swift_OutputByteStream
+{
+ /** A socket buffer over TCP */
+ const TYPE_SOCKET = 0x0001;
+
+ /** A process buffer with I/O support */
+ const TYPE_PROCESS = 0x0010;
+
+ /**
+ * Perform any initialization needed, using the given $params.
+ *
+ * Parameters will vary depending upon the type of IoBuffer used.
+ *
+ * @param array $params
+ */
+ public function initialize(array $params);
+
+ /**
+ * Set an individual param on the buffer (e.g. switching to SSL).
+ *
+ * @param string $param
+ * @param mixed $value
+ */
+ public function setParam($param, $value);
+
+ /**
+ * Perform any shutdown logic needed.
+ */
+ public function terminate();
+
+ /**
+ * Set an array of string replacements which should be made on data written
+ * to the buffer.
+ *
+ * This could replace LF with CRLF for example.
+ *
+ * @param string[] $replacements
+ */
+ public function setWriteTranslations(array $replacements);
+
+ /**
+ * Get a line of output (including any CRLF).
+ *
+ * The $sequence number comes from any writes and may or may not be used
+ * depending upon the implementation.
+ *
+ * @param int $sequence of last write to scan from
+ *
+ * @return string
+ */
+ public function readLine($sequence);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/LoadBalancedTransport.php b/vendor/swiftmailer/classes/Swift/Transport/LoadBalancedTransport.php
new file mode 100644
index 00000000..dd27a2d9
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/LoadBalancedTransport.php
@@ -0,0 +1,167 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Redundantly and rotationally uses several Transports when sending.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Transport_LoadBalancedTransport implements Swift_Transport
+{
+ /**
+ * Transports which are deemed useless.
+ *
+ * @var Swift_Transport[]
+ */
+ private $_deadTransports = array();
+
+ /**
+ * The Transports which are used in rotation.
+ *
+ * @var Swift_Transport[]
+ */
+ protected $_transports = array();
+
+ /**
+ * Creates a new LoadBalancedTransport.
+ */
+ public function __construct()
+ {
+ }
+
+ /**
+ * Set $transports to delegate to.
+ *
+ * @param Swift_Transport[] $transports
+ */
+ public function setTransports(array $transports)
+ {
+ $this->_transports = $transports;
+ $this->_deadTransports = array();
+ }
+
+ /**
+ * Get $transports to delegate to.
+ *
+ * @return Swift_Transport[]
+ */
+ public function getTransports()
+ {
+ return array_merge($this->_transports, $this->_deadTransports);
+ }
+
+ /**
+ * Test if this Transport mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted()
+ {
+ return count($this->_transports) > 0;
+ }
+
+ /**
+ * Start this Transport mechanism.
+ */
+ public function start()
+ {
+ $this->_transports = array_merge($this->_transports, $this->_deadTransports);
+ }
+
+ /**
+ * Stop this Transport mechanism.
+ */
+ public function stop()
+ {
+ foreach ($this->_transports as $transport) {
+ $transport->stop();
+ }
+ }
+
+ /**
+ * Send the given Message.
+ *
+ * Recipient/sender data will be retrieved from the Message API.
+ * The return value is the number of recipients who were accepted for delivery.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ $maxTransports = count($this->_transports);
+ $sent = 0;
+
+ for ($i = 0; $i < $maxTransports
+ && $transport = $this->_getNextTransport(); ++$i)
+ {
+ try {
+ if (!$transport->isStarted()) {
+ $transport->start();
+ }
+ if ($sent = $transport->send($message, $failedRecipients)) {
+ break;
+ }
+ } catch (Swift_TransportException $e) {
+ $this->_killCurrentTransport();
+ }
+ }
+
+ if (count($this->_transports) == 0) {
+ throw new Swift_TransportException(
+ 'All Transports in LoadBalancedTransport failed, or no Transports available'
+ );
+ }
+
+ return $sent;
+ }
+
+ /**
+ * Register a plugin.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ foreach ($this->_transports as $transport) {
+ $transport->registerPlugin($plugin);
+ }
+ }
+
+ /**
+ * Rotates the transport list around and returns the first instance.
+ *
+ * @return Swift_Transport
+ */
+ protected function _getNextTransport()
+ {
+ if ($next = array_shift($this->_transports)) {
+ $this->_transports[] = $next;
+ }
+
+ return $next;
+ }
+
+ /**
+ * Tag the currently used (top of stack) transport as dead/useless.
+ */
+ protected function _killCurrentTransport()
+ {
+ if ($transport = array_pop($this->_transports)) {
+ try {
+ $transport->stop();
+ } catch (Exception $e) {
+ }
+ $this->_deadTransports[] = $transport;
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/MailInvoker.php b/vendor/swiftmailer/classes/Swift/Transport/MailInvoker.php
new file mode 100644
index 00000000..77489ced
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/MailInvoker.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * This interface intercepts calls to the mail() function.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Transport_MailInvoker
+{
+ /**
+ * Send mail via the mail() function.
+ *
+ * This method takes the same arguments as PHP mail().
+ *
+ * @param string $to
+ * @param string $subject
+ * @param string $body
+ * @param string $headers
+ * @param string $extraParams
+ *
+ * @return bool
+ */
+ public function mail($to, $subject, $body, $headers = null, $extraParams = null);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/MailTransport.php b/vendor/swiftmailer/classes/Swift/Transport/MailTransport.php
new file mode 100644
index 00000000..cf984d47
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/MailTransport.php
@@ -0,0 +1,227 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Sends Messages using the mail() function.
+ *
+ * It is advised that users do not use this transport if at all possible
+ * since a number of plugin features cannot be used in conjunction with this
+ * transport due to the internal interface in PHP itself.
+ *
+ * The level of error reporting with this transport is incredibly weak, again
+ * due to limitations of PHP's internal mail() function. You'll get an
+ * all-or-nothing result from sending.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Transport_MailTransport implements Swift_Transport
+{
+ /** Additional parameters to pass to mail() */
+ private $_extraParams = '-f%s';
+
+ /** The event dispatcher from the plugin API */
+ private $_eventDispatcher;
+
+ /** An invoker that calls the mail() function */
+ private $_invoker;
+
+ /**
+ * Create a new MailTransport with the $log.
+ *
+ * @param Swift_Transport_MailInvoker $invoker
+ * @param Swift_Events_EventDispatcher $eventDispatcher
+ */
+ public function __construct(Swift_Transport_MailInvoker $invoker, Swift_Events_EventDispatcher $eventDispatcher)
+ {
+ $this->_invoker = $invoker;
+ $this->_eventDispatcher = $eventDispatcher;
+ }
+
+ /**
+ * Not used.
+ */
+ public function isStarted()
+ {
+ return false;
+ }
+
+ /**
+ * Not used.
+ */
+ public function start()
+ {
+ }
+
+ /**
+ * Not used.
+ */
+ public function stop()
+ {
+ }
+
+ /**
+ * Set the additional parameters used on the mail() function.
+ *
+ * This string is formatted for sprintf() where %s is the sender address.
+ *
+ * @param string $params
+ *
+ * @return Swift_Transport_MailTransport
+ */
+ public function setExtraParams($params)
+ {
+ $this->_extraParams = $params;
+
+ return $this;
+ }
+
+ /**
+ * Get the additional parameters used on the mail() function.
+ *
+ * This string is formatted for sprintf() where %s is the sender address.
+ *
+ * @return string
+ */
+ public function getExtraParams()
+ {
+ return $this->_extraParams;
+ }
+
+ /**
+ * Send the given Message.
+ *
+ * Recipient/sender data will be retrieved from the Message API.
+ * The return value is the number of recipients who were accepted for delivery.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ $failedRecipients = (array) $failedRecipients;
+
+ if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
+ if ($evt->bubbleCancelled()) {
+ return 0;
+ }
+ }
+
+ $count = (
+ count((array) $message->getTo())
+ + count((array) $message->getCc())
+ + count((array) $message->getBcc())
+ );
+
+ $toHeader = $message->getHeaders()->get('To');
+ $subjectHeader = $message->getHeaders()->get('Subject');
+
+ if (!$toHeader) {
+ throw new Swift_TransportException(
+ 'Cannot send message without a recipient'
+ );
+ }
+ $to = $toHeader->getFieldBody();
+ $subject = $subjectHeader ? $subjectHeader->getFieldBody() : '';
+
+ $reversePath = $this->_getReversePath($message);
+
+ // Remove headers that would otherwise be duplicated
+ $message->getHeaders()->remove('To');
+ $message->getHeaders()->remove('Subject');
+
+ $messageStr = $message->toString();
+
+ $message->getHeaders()->set($toHeader);
+ $message->getHeaders()->set($subjectHeader);
+
+ // Separate headers from body
+ if (false !== $endHeaders = strpos($messageStr, "\r\n\r\n")) {
+ $headers = substr($messageStr, 0, $endHeaders) . "\r\n"; //Keep last EOL
+ $body = substr($messageStr, $endHeaders + 4);
+ } else {
+ $headers = $messageStr . "\r\n";
+ $body = '';
+ }
+
+ unset($messageStr);
+
+ if ("\r\n" != PHP_EOL) {
+ // Non-windows (not using SMTP)
+ $headers = str_replace("\r\n", PHP_EOL, $headers);
+ $body = str_replace("\r\n", PHP_EOL, $body);
+ } else {
+ // Windows, using SMTP
+ $headers = str_replace("\r\n.", "\r\n..", $headers);
+ $body = str_replace("\r\n.", "\r\n..", $body);
+ }
+
+ if ($this->_invoker->mail($to, $subject, $body, $headers,
+ sprintf($this->_extraParams, $reversePath)))
+ {
+ if ($evt) {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS);
+ $evt->setFailedRecipients($failedRecipients);
+ $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+ } else {
+ $failedRecipients = array_merge(
+ $failedRecipients,
+ array_keys((array) $message->getTo()),
+ array_keys((array) $message->getCc()),
+ array_keys((array) $message->getBcc())
+ );
+
+ if ($evt) {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED);
+ $evt->setFailedRecipients($failedRecipients);
+ $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+
+ $message->generateId();
+
+ $count = 0;
+ }
+
+ return $count;
+ }
+
+ /**
+ * Register a plugin.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ $this->_eventDispatcher->bindEventListener($plugin);
+ }
+
+ /** Determine the best-use reverse path for this message */
+ private function _getReversePath(Swift_Mime_Message $message)
+ {
+ $return = $message->getReturnPath();
+ $sender = $message->getSender();
+ $from = $message->getFrom();
+ $path = null;
+ if (!empty($return)) {
+ $path = $return;
+ } elseif (!empty($sender)) {
+ $keys = array_keys($sender);
+ $path = array_shift($keys);
+ } elseif (!empty($from)) {
+ $keys = array_keys($from);
+ $path = array_shift($keys);
+ }
+
+ return $path;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/NullTransport.php b/vendor/swiftmailer/classes/Swift/Transport/NullTransport.php
new file mode 100644
index 00000000..f87cfbf3
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/NullTransport.php
@@ -0,0 +1,93 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2009 Fabien Potencier <fabien.potencier@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Pretends messages have been sent, but just ignores them.
+ *
+ * @author Fabien Potencier
+ */
+class Swift_Transport_NullTransport implements Swift_Transport
+{
+ /** The event dispatcher from the plugin API */
+ private $_eventDispatcher;
+
+ /**
+ * Constructor.
+ */
+ public function __construct(Swift_Events_EventDispatcher $eventDispatcher)
+ {
+ $this->_eventDispatcher = $eventDispatcher;
+ }
+
+ /**
+ * Tests if this Transport mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted()
+ {
+ return true;
+ }
+
+ /**
+ * Starts this Transport mechanism.
+ */
+ public function start()
+ {
+ }
+
+ /**
+ * Stops this Transport mechanism.
+ */
+ public function stop()
+ {
+ }
+
+ /**
+ * Sends the given message.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int The number of sent emails
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
+ if ($evt->bubbleCancelled()) {
+ return 0;
+ }
+ }
+
+ if ($evt) {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS);
+ $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+
+ $count = (
+ count((array) $message->getTo())
+ + count((array) $message->getCc())
+ + count((array) $message->getBcc())
+ );
+
+ return $count;
+ }
+
+ /**
+ * Register a plugin.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ $this->_eventDispatcher->bindEventListener($plugin);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/SendmailTransport.php b/vendor/swiftmailer/classes/Swift/Transport/SendmailTransport.php
new file mode 100644
index 00000000..8f8eb043
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/SendmailTransport.php
@@ -0,0 +1,159 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * SendmailTransport for sending mail through a Sendmail/Postfix (etc..) binary.
+ *
+ * Supported modes are -bs and -t, with any additional flags desired.
+ * It is advised to use -bs mode since error reporting with -t mode is not
+ * possible.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Transport_SendmailTransport extends Swift_Transport_AbstractSmtpTransport
+{
+ /**
+ * Connection buffer parameters.
+ *
+ * @var array
+ */
+ private $_params = array(
+ 'timeout' => 30,
+ 'blocking' => 1,
+ 'command' => '/usr/sbin/sendmail -bs',
+ 'type' => Swift_Transport_IoBuffer::TYPE_PROCESS
+ );
+
+ /**
+ * Create a new SendmailTransport with $buf for I/O.
+ *
+ * @param Swift_Transport_IoBuffer $buf
+ * @param Swift_Events_EventDispatcher $dispatcher
+ */
+ public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher)
+ {
+ parent::__construct($buf, $dispatcher);
+ }
+
+ /**
+ * Start the standalone SMTP session if running in -bs mode.
+ */
+ public function start()
+ {
+ if (false !== strpos($this->getCommand(), ' -bs')) {
+ parent::start();
+ }
+ }
+
+ /**
+ * Set the command to invoke.
+ *
+ * If using -t mode you are strongly advised to include -oi or -i in the flags.
+ * For example: /usr/sbin/sendmail -oi -t
+ * Swift will append a -f<sender> flag if one is not present.
+ *
+ * The recommended mode is "-bs" since it is interactive and failure notifications
+ * are hence possible.
+ *
+ * @param string $command
+ *
+ * @return Swift_Transport_SendmailTransport
+ */
+ public function setCommand($command)
+ {
+ $this->_params['command'] = $command;
+
+ return $this;
+ }
+
+ /**
+ * Get the sendmail command which will be invoked.
+ *
+ * @return string
+ */
+ public function getCommand()
+ {
+ return $this->_params['command'];
+ }
+
+ /**
+ * Send the given Message.
+ *
+ * Recipient/sender data will be retrieved from the Message API.
+ *
+ * The return value is the number of recipients who were accepted for delivery.
+ * NOTE: If using 'sendmail -t' you will not be aware of any failures until
+ * they bounce (i.e. send() will always return 100% success).
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ $failedRecipients = (array) $failedRecipients;
+ $command = $this->getCommand();
+ $buffer = $this->getBuffer();
+
+ if (false !== strpos($command, ' -t')) {
+ if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
+ if ($evt->bubbleCancelled()) {
+ return 0;
+ }
+ }
+
+ if (false === strpos($command, ' -f')) {
+ $command .= ' -f' . escapeshellarg($this->_getReversePath($message));
+ }
+
+ $buffer->initialize(array_merge($this->_params, array('command' => $command)));
+
+ if (false === strpos($command, ' -i') && false === strpos($command, ' -oi')) {
+ $buffer->setWriteTranslations(array("\r\n" => "\n", "\n." => "\n.."));
+ } else {
+ $buffer->setWriteTranslations(array("\r\n"=>"\n"));
+ }
+
+ $count = count((array) $message->getTo())
+ + count((array) $message->getCc())
+ + count((array) $message->getBcc())
+ ;
+ $message->toByteStream($buffer);
+ $buffer->flushBuffers();
+ $buffer->setWriteTranslations(array());
+ $buffer->terminate();
+
+ if ($evt) {
+ $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS);
+ $evt->setFailedRecipients($failedRecipients);
+ $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+
+ $message->generateId();
+ } elseif (false !== strpos($command, ' -bs')) {
+ $count = parent::send($message, $failedRecipients);
+ } else {
+ $this->_throwException(new Swift_TransportException(
+ 'Unsupported sendmail command flags [' . $command . ']. ' .
+ 'Must be one of "-bs" or "-t" but can include additional flags.'
+ ));
+ }
+
+ return $count;
+ }
+
+ /** Get the params to initialize the buffer */
+ protected function _getBufferParams()
+ {
+ return $this->_params;
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/SimpleMailInvoker.php b/vendor/swiftmailer/classes/Swift/Transport/SimpleMailInvoker.php
new file mode 100644
index 00000000..21e629a6
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/SimpleMailInvoker.php
@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * This is the implementation class for {@link Swift_Transport_MailInvoker}.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Transport_SimpleMailInvoker implements Swift_Transport_MailInvoker
+{
+ /**
+ * Send mail via the mail() function.
+ *
+ * This method takes the same arguments as PHP mail().
+ *
+ * @param string $to
+ * @param string $subject
+ * @param string $body
+ * @param string $headers
+ * @param string $extraParams
+ *
+ * @return bool
+ */
+ public function mail($to, $subject, $body, $headers = null, $extraParams = null)
+ {
+ if (!ini_get('safe_mode')) {
+ return @mail($to, $subject, $body, $headers, $extraParams);
+ } else {
+ return @mail($to, $subject, $body, $headers);
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/SmtpAgent.php b/vendor/swiftmailer/classes/Swift/Transport/SmtpAgent.php
new file mode 100644
index 00000000..4763b67e
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/SmtpAgent.php
@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Wraps an IoBuffer to send/receive SMTP commands/responses.
+ *
+ * @author Chris Corbyn
+ */
+interface Swift_Transport_SmtpAgent
+{
+ /**
+ * Get the IoBuffer where read/writes are occurring.
+ *
+ * @return Swift_Transport_IoBuffer
+ */
+ public function getBuffer();
+
+ /**
+ * Run a command against the buffer, expecting the given response codes.
+ *
+ * If no response codes are given, the response will not be validated.
+ * If codes are given, an exception will be thrown on an invalid response.
+ *
+ * @param string $command
+ * @param int[] $codes
+ * @param string[] $failures An array of failures by-reference
+ */
+ public function executeCommand($command, $codes = array(), &$failures = null);
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/SpoolTransport.php b/vendor/swiftmailer/classes/Swift/Transport/SpoolTransport.php
new file mode 100644
index 00000000..6ee9ef5c
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/SpoolTransport.php
@@ -0,0 +1,117 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2009 Fabien Potencier <fabien.potencier@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stores Messages in a queue.
+ *
+ * @author Fabien Potencier
+ */
+class Swift_Transport_SpoolTransport implements Swift_Transport
+{
+ /** The spool instance */
+ private $_spool;
+
+ /** The event dispatcher from the plugin API */
+ private $_eventDispatcher;
+
+ /**
+ * Constructor.
+ */
+ public function __construct(Swift_Events_EventDispatcher $eventDispatcher, Swift_Spool $spool = null)
+ {
+ $this->_eventDispatcher = $eventDispatcher;
+ $this->_spool = $spool;
+ }
+
+ /**
+ * Sets the spool object.
+ *
+ * @param Swift_Spool $spool
+ *
+ * @return Swift_Transport_SpoolTransport
+ */
+ public function setSpool(Swift_Spool $spool)
+ {
+ $this->_spool = $spool;
+
+ return $this;
+ }
+
+ /**
+ * Get the spool object.
+ *
+ * @return Swift_Spool
+ */
+ public function getSpool()
+ {
+ return $this->_spool;
+ }
+
+ /**
+ * Tests if this Transport mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted()
+ {
+ return true;
+ }
+
+ /**
+ * Starts this Transport mechanism.
+ */
+ public function start()
+ {
+ }
+
+ /**
+ * Stops this Transport mechanism.
+ */
+ public function stop()
+ {
+ }
+
+ /**
+ * Sends the given message.
+ *
+ * @param Swift_Mime_Message $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int The number of sent e-mail's
+ */
+ public function send(Swift_Mime_Message $message, &$failedRecipients = null)
+ {
+ if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) {
+ $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed');
+ if ($evt->bubbleCancelled()) {
+ return 0;
+ }
+ }
+
+ $success = $this->_spool->queueMessage($message);
+
+ if ($evt) {
+ $evt->setResult($success ? Swift_Events_SendEvent::RESULT_SUCCESS : Swift_Events_SendEvent::RESULT_FAILED);
+ $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed');
+ }
+
+ return 1;
+ }
+
+ /**
+ * Register a plugin.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin)
+ {
+ $this->_eventDispatcher->bindEventListener($plugin);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Transport/StreamBuffer.php b/vendor/swiftmailer/classes/Swift/Transport/StreamBuffer.php
new file mode 100644
index 00000000..b36f56e7
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Transport/StreamBuffer.php
@@ -0,0 +1,321 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A generic IoBuffer implementation supporting remote sockets and local processes.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_Transport_StreamBuffer extends Swift_ByteStream_AbstractFilterableInputStream implements Swift_Transport_IoBuffer
+{
+ /** A primary socket */
+ private $_stream;
+
+ /** The input stream */
+ private $_in;
+
+ /** The output stream */
+ private $_out;
+
+ /** Buffer initialization parameters */
+ private $_params = array();
+
+ /** The ReplacementFilterFactory */
+ private $_replacementFactory;
+
+ /** Translations performed on data being streamed into the buffer */
+ private $_translations = array();
+
+ /**
+ * Create a new StreamBuffer using $replacementFactory for transformations.
+ *
+ * @param Swift_ReplacementFilterFactory $replacementFactory
+ */
+ public function __construct(Swift_ReplacementFilterFactory $replacementFactory)
+ {
+ $this->_replacementFactory = $replacementFactory;
+ }
+
+ /**
+ * Perform any initialization needed, using the given $params.
+ *
+ * Parameters will vary depending upon the type of IoBuffer used.
+ *
+ * @param array $params
+ */
+ public function initialize(array $params)
+ {
+ $this->_params = $params;
+ switch ($params['type']) {
+ case self::TYPE_PROCESS:
+ $this->_establishProcessConnection();
+ break;
+ case self::TYPE_SOCKET:
+ default:
+ $this->_establishSocketConnection();
+ break;
+ }
+ }
+
+ /**
+ * Set an individual param on the buffer (e.g. switching to SSL).
+ *
+ * @param string $param
+ * @param mixed $value
+ */
+ public function setParam($param, $value)
+ {
+ if (isset($this->_stream)) {
+ switch ($param) {
+ case 'timeout':
+ if ($this->_stream) {
+ stream_set_timeout($this->_stream, $value);
+ }
+ break;
+
+ case 'blocking':
+ if ($this->_stream) {
+ stream_set_blocking($this->_stream, 1);
+ }
+
+ }
+ }
+ $this->_params[$param] = $value;
+ }
+
+ public function startTLS()
+ {
+ return stream_socket_enable_crypto($this->_stream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
+ }
+
+ /**
+ * Perform any shutdown logic needed.
+ */
+ public function terminate()
+ {
+ if (isset($this->_stream)) {
+ switch ($this->_params['type']) {
+ case self::TYPE_PROCESS:
+ fclose($this->_in);
+ fclose($this->_out);
+ proc_close($this->_stream);
+ break;
+ case self::TYPE_SOCKET:
+ default:
+ fclose($this->_stream);
+ break;
+ }
+ }
+ $this->_stream = null;
+ $this->_out = null;
+ $this->_in = null;
+ }
+
+ /**
+ * Set an array of string replacements which should be made on data written
+ * to the buffer.
+ *
+ * This could replace LF with CRLF for example.
+ *
+ * @param string[] $replacements
+ */
+ public function setWriteTranslations(array $replacements)
+ {
+ foreach ($this->_translations as $search => $replace) {
+ if (!isset($replacements[$search])) {
+ $this->removeFilter($search);
+ unset($this->_translations[$search]);
+ }
+ }
+
+ foreach ($replacements as $search => $replace) {
+ if (!isset($this->_translations[$search])) {
+ $this->addFilter(
+ $this->_replacementFactory->createFilter($search, $replace), $search
+ );
+ $this->_translations[$search] = true;
+ }
+ }
+ }
+
+ /**
+ * Get a line of output (including any CRLF).
+ *
+ * The $sequence number comes from any writes and may or may not be used
+ * depending upon the implementation.
+ *
+ * @param int $sequence of last write to scan from
+ *
+ * @return string
+ *
+ * @throws Swift_IoException
+ */
+ public function readLine($sequence)
+ {
+ if (isset($this->_out) && !feof($this->_out)) {
+ $line = fgets($this->_out);
+ if (strlen($line)==0) {
+ $metas = stream_get_meta_data($this->_out);
+ if ($metas['timed_out']) {
+ throw new Swift_IoException(
+ 'Connection to ' .
+ $this->_getReadConnectionDescription() .
+ ' Timed Out'
+ );
+ }
+ }
+
+ return $line;
+ }
+ }
+
+ /**
+ * Reads $length bytes from the stream into a string and moves the pointer
+ * through the stream by $length.
+ *
+ * If less bytes exist than are requested the remaining bytes are given instead.
+ * If no bytes are remaining at all, boolean false is returned.
+ *
+ * @param int $length
+ *
+ * @return string|bool
+ *
+ * @throws Swift_IoException
+ */
+ public function read($length)
+ {
+ if (isset($this->_out) && !feof($this->_out)) {
+ $ret = fread($this->_out, $length);
+ if (strlen($ret)==0) {
+ $metas = stream_get_meta_data($this->_out);
+ if ($metas['timed_out']) {
+ throw new Swift_IoException(
+ 'Connection to ' .
+ $this->_getReadConnectionDescription() .
+ ' Timed Out'
+ );
+ }
+ }
+
+ return $ret;
+ }
+ }
+
+ /** Not implemented */
+ public function setReadPointer($byteOffset)
+ {
+ }
+
+ /** Flush the stream contents */
+ protected function _flush()
+ {
+ if (isset($this->_in)) {
+ fflush($this->_in);
+ }
+ }
+
+ /** Write this bytes to the stream */
+ protected function _commit($bytes)
+ {
+ if (isset($this->_in)) {
+ $bytesToWrite = strlen($bytes);
+ $totalBytesWritten = 0;
+
+ while ($totalBytesWritten < $bytesToWrite) {
+ $bytesWritten = fwrite($this->_in, substr($bytes, $totalBytesWritten));
+ if (false === $bytesWritten || 0 === $bytesWritten) {
+ break;
+ }
+
+ $totalBytesWritten += $bytesWritten;
+ }
+
+ if ($totalBytesWritten > 0) {
+ return ++$this->_sequence;
+ }
+ }
+ }
+
+ /**
+ * Establishes a connection to a remote server.
+ */
+ private function _establishSocketConnection()
+ {
+ $host = $this->_params['host'];
+ if (!empty($this->_params['protocol'])) {
+ $host = $this->_params['protocol'] . '://' . $host;
+ }
+ $timeout = 15;
+ if (!empty($this->_params['timeout'])) {
+ $timeout = $this->_params['timeout'];
+ }
+ $options = array();
+ if (!empty($this->_params['sourceIp'])) {
+ $options['socket']['bindto']=$this->_params['sourceIp'].':0';
+ }
+ $this->_stream = @stream_socket_client($host.':'.$this->_params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, stream_context_create($options));
+ if (false === $this->_stream) {
+ throw new Swift_TransportException(
+ 'Connection could not be established with host ' . $this->_params['host'] .
+ ' [' . $errstr . ' #' . $errno . ']'
+ );
+ }
+ if (!empty($this->_params['blocking'])) {
+ stream_set_blocking($this->_stream, 1);
+ } else {
+ stream_set_blocking($this->_stream, 0);
+ }
+ stream_set_timeout($this->_stream, $timeout);
+ $this->_in =& $this->_stream;
+ $this->_out =& $this->_stream;
+ }
+
+ /**
+ * Opens a process for input/output.
+ */
+ private function _establishProcessConnection()
+ {
+ $command = $this->_params['command'];
+ $descriptorSpec = array(
+ 0 => array('pipe', 'r'),
+ 1 => array('pipe', 'w'),
+ 2 => array('pipe', 'w')
+ );
+ $this->_stream = proc_open($command, $descriptorSpec, $pipes);
+ stream_set_blocking($pipes[2], 0);
+ if ($err = stream_get_contents($pipes[2])) {
+ throw new Swift_TransportException(
+ 'Process could not be started [' . $err . ']'
+ );
+ }
+ $this->_in =& $pipes[0];
+ $this->_out =& $pipes[1];
+ }
+
+ private function _getReadConnectionDescription()
+ {
+ switch ($this->_params['type']) {
+ case self::TYPE_PROCESS:
+ return 'Process '.$this->_params['command'];
+ break;
+
+ case self::TYPE_SOCKET:
+ default:
+ $host = $this->_params['host'];
+ if (!empty($this->_params['protocol'])) {
+ $host = $this->_params['protocol'] . '://' . $host;
+ }
+ $host.=':'.$this->_params['port'];
+
+ return $host;
+ break;
+ }
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/TransportException.php b/vendor/swiftmailer/classes/Swift/TransportException.php
new file mode 100644
index 00000000..bdcd23bb
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/TransportException.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * TransportException thrown when an error occurs in the Transport subsystem.
+ *
+ * @author Chris Corbyn
+ */
+class Swift_TransportException extends Swift_IoException
+{
+ /**
+ * Create a new TransportException with $message.
+ *
+ * @param string $message
+ */
+ public function __construct($message)
+ {
+ parent::__construct($message);
+ }
+}
diff --git a/vendor/swiftmailer/classes/Swift/Validate.php b/vendor/swiftmailer/classes/Swift/Validate.php
new file mode 100644
index 00000000..2a338bdc
--- /dev/null
+++ b/vendor/swiftmailer/classes/Swift/Validate.php
@@ -0,0 +1,42 @@
+<?php
+/*
+ * This file is part of SwiftMailer.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Utility Class allowing users to simply check expressions again Swift Grammar.
+ *
+ * @author Xavier De Cock <xdecock@gmail.com>
+ */
+class Swift_Validate
+{
+ /**
+ * Grammar Object
+ *
+ * @var Swift_Mime_Grammar
+ */
+ private static $grammar = null;
+
+ /**
+ * Checks if an e-mail address matches the current grammars.
+ *
+ * @param string $email
+ *
+ * @return bool
+ */
+ public static function email($email)
+ {
+ if (self::$grammar===null) {
+ self::$grammar = Swift_DependencyContainer::getInstance()
+ ->lookup('mime.grammar');
+ }
+
+ return (bool) preg_match(
+ '/^' . self::$grammar->getDefinition('addr-spec') . '$/D',
+ $email
+ );
+ }
+}
diff --git a/vendor/swiftmailer/dependency_maps/cache_deps.php b/vendor/swiftmailer/dependency_maps/cache_deps.php
new file mode 100644
index 00000000..6023448e
--- /dev/null
+++ b/vendor/swiftmailer/dependency_maps/cache_deps.php
@@ -0,0 +1,23 @@
+<?php
+
+Swift_DependencyContainer::getInstance()
+ ->register('cache')
+ ->asAliasOf('cache.array')
+
+ ->register('tempdir')
+ ->asValue('/tmp')
+
+ ->register('cache.null')
+ ->asSharedInstanceOf('Swift_KeyCache_NullKeyCache')
+
+ ->register('cache.array')
+ ->asSharedInstanceOf('Swift_KeyCache_ArrayKeyCache')
+ ->withDependencies(array('cache.inputstream'))
+
+ ->register('cache.disk')
+ ->asSharedInstanceOf('Swift_KeyCache_DiskKeyCache')
+ ->withDependencies(array('cache.inputstream', 'tempdir'))
+
+ ->register('cache.inputstream')
+ ->asNewInstanceOf('Swift_KeyCache_SimpleKeyCacheInputStream')
+;
diff --git a/vendor/swiftmailer/dependency_maps/message_deps.php b/vendor/swiftmailer/dependency_maps/message_deps.php
new file mode 100644
index 00000000..64d69d21
--- /dev/null
+++ b/vendor/swiftmailer/dependency_maps/message_deps.php
@@ -0,0 +1,9 @@
+<?php
+
+Swift_DependencyContainer::getInstance()
+ ->register('message.message')
+ ->asNewInstanceOf('Swift_Message')
+
+ ->register('message.mimepart')
+ ->asNewInstanceOf('Swift_MimePart')
+;
diff --git a/vendor/swiftmailer/dependency_maps/mime_deps.php b/vendor/swiftmailer/dependency_maps/mime_deps.php
new file mode 100644
index 00000000..a13472e9
--- /dev/null
+++ b/vendor/swiftmailer/dependency_maps/mime_deps.php
@@ -0,0 +1,123 @@
+<?php
+
+require dirname(__FILE__) . '/../mime_types.php';
+
+Swift_DependencyContainer::getInstance()
+ ->register('properties.charset')
+ ->asValue('utf-8')
+
+ ->register('mime.grammar')
+ ->asSharedInstanceOf('Swift_Mime_Grammar')
+
+ ->register('mime.message')
+ ->asNewInstanceOf('Swift_Mime_SimpleMessage')
+ ->withDependencies(array(
+ 'mime.headerset',
+ 'mime.qpcontentencoder',
+ 'cache',
+ 'mime.grammar',
+ 'properties.charset'
+ ))
+
+ ->register('mime.part')
+ ->asNewInstanceOf('Swift_Mime_MimePart')
+ ->withDependencies(array(
+ 'mime.headerset',
+ 'mime.qpcontentencoder',
+ 'cache',
+ 'mime.grammar',
+ 'properties.charset'
+ ))
+
+ ->register('mime.attachment')
+ ->asNewInstanceOf('Swift_Mime_Attachment')
+ ->withDependencies(array(
+ 'mime.headerset',
+ 'mime.base64contentencoder',
+ 'cache',
+ 'mime.grammar'
+ ))
+ ->addConstructorValue($swift_mime_types)
+
+ ->register('mime.embeddedfile')
+ ->asNewInstanceOf('Swift_Mime_EmbeddedFile')
+ ->withDependencies(array(
+ 'mime.headerset',
+ 'mime.base64contentencoder',
+ 'cache',
+ 'mime.grammar'
+ ))
+ ->addConstructorValue($swift_mime_types)
+
+ ->register('mime.headerfactory')
+ ->asNewInstanceOf('Swift_Mime_SimpleHeaderFactory')
+ ->withDependencies(array(
+ 'mime.qpheaderencoder',
+ 'mime.rfc2231encoder',
+ 'mime.grammar',
+ 'properties.charset'
+ ))
+
+ ->register('mime.headerset')
+ ->asNewInstanceOf('Swift_Mime_SimpleHeaderSet')
+ ->withDependencies(array('mime.headerfactory', 'properties.charset'))
+
+ ->register('mime.qpheaderencoder')
+ ->asNewInstanceOf('Swift_Mime_HeaderEncoder_QpHeaderEncoder')
+ ->withDependencies(array('mime.charstream'))
+
+ ->register('mime.base64headerencoder')
+ ->asNewInstanceOf('Swift_Mime_HeaderEncoder_Base64HeaderEncoder')
+ ->withDependencies(array('mime.charstream'))
+
+ ->register('mime.charstream')
+ ->asNewInstanceOf('Swift_CharacterStream_NgCharacterStream')
+ ->withDependencies(array('mime.characterreaderfactory', 'properties.charset'))
+
+ ->register('mime.bytecanonicalizer')
+ ->asSharedInstanceOf('Swift_StreamFilters_ByteArrayReplacementFilter')
+ ->addConstructorValue(array(array(0x0D, 0x0A), array(0x0D), array(0x0A)))
+ ->addConstructorValue(array(array(0x0A), array(0x0A), array(0x0D, 0x0A)))
+
+ ->register('mime.characterreaderfactory')
+ ->asSharedInstanceOf('Swift_CharacterReaderFactory_SimpleCharacterReaderFactory')
+
+ ->register('mime.safeqpcontentencoder')
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder')
+ ->withDependencies(array('mime.charstream', 'mime.bytecanonicalizer'))
+
+ ->register('mime.rawcontentencoder')
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_RawContentEncoder')
+
+ ->register('mime.nativeqpcontentencoder')
+ ->withDependencies(array('properties.charset'))
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_NativeQpContentEncoder')
+
+ ->register('mime.qpcontentencoderproxy')
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoderProxy')
+ ->withDependencies(array('mime.safeqpcontentencoder', 'mime.nativeqpcontentencoder', 'properties.charset'))
+
+ ->register('mime.7bitcontentencoder')
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder')
+ ->addConstructorValue('7bit')
+ ->addConstructorValue(true)
+
+ ->register('mime.8bitcontentencoder')
+ ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder')
+ ->addConstructorValue('8bit')
+ ->addConstructorValue(true)
+
+ ->register('mime.base64contentencoder')
+ ->asSharedInstanceOf('Swift_Mime_ContentEncoder_Base64ContentEncoder')
+
+ ->register('mime.rfc2231encoder')
+ ->asNewInstanceOf('Swift_Encoder_Rfc2231Encoder')
+ ->withDependencies(array('mime.charstream'))
+
+ // As of PHP 5.4.7, the quoted_printable_encode() function behaves correctly.
+ // see https://github.com/php/php-src/commit/18bb426587d62f93c54c40bf8535eb8416603629
+ ->register('mime.qpcontentencoder')
+ ->asAliasOf(version_compare(phpversion(), '5.4.7', '>=') ? 'mime.qpcontentencoderproxy' : 'mime.safeqpcontentencoder')
+;
+
+unset($swift_mime_types);
diff --git a/vendor/swiftmailer/dependency_maps/transport_deps.php b/vendor/swiftmailer/dependency_maps/transport_deps.php
new file mode 100644
index 00000000..17d63dd1
--- /dev/null
+++ b/vendor/swiftmailer/dependency_maps/transport_deps.php
@@ -0,0 +1,76 @@
+<?php
+
+Swift_DependencyContainer::getInstance()
+ ->register('transport.smtp')
+ ->asNewInstanceOf('Swift_Transport_EsmtpTransport')
+ ->withDependencies(array(
+ 'transport.buffer',
+ array('transport.authhandler'),
+ 'transport.eventdispatcher'
+ ))
+
+ ->register('transport.sendmail')
+ ->asNewInstanceOf('Swift_Transport_SendmailTransport')
+ ->withDependencies(array(
+ 'transport.buffer',
+ 'transport.eventdispatcher'
+ ))
+
+ ->register('transport.mail')
+ ->asNewInstanceOf('Swift_Transport_MailTransport')
+ ->withDependencies(array('transport.mailinvoker', 'transport.eventdispatcher'))
+
+ ->register('transport.loadbalanced')
+ ->asNewInstanceOf('Swift_Transport_LoadBalancedTransport')
+
+ ->register('transport.failover')
+ ->asNewInstanceOf('Swift_Transport_FailoverTransport')
+
+ ->register('transport.spool')
+ ->asNewInstanceOf('Swift_Transport_SpoolTransport')
+ ->withDependencies(array('transport.eventdispatcher'))
+
+ ->register('transport.null')
+ ->asNewInstanceOf('Swift_Transport_NullTransport')
+ ->withDependencies(array('transport.eventdispatcher'))
+
+ ->register('transport.mailinvoker')
+ ->asSharedInstanceOf('Swift_Transport_SimpleMailInvoker')
+
+ ->register('transport.buffer')
+ ->asNewInstanceOf('Swift_Transport_StreamBuffer')
+ ->withDependencies(array('transport.replacementfactory'))
+
+ ->register('transport.authhandler')
+ ->asNewInstanceOf('Swift_Transport_Esmtp_AuthHandler')
+ ->withDependencies(array(
+ array(
+ 'transport.crammd5auth',
+ 'transport.loginauth',
+ 'transport.plainauth',
+ 'transport.ntlmauth',
+ 'transport.xoauth2auth',
+ )
+ ))
+
+ ->register('transport.crammd5auth')
+ ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_CramMd5Authenticator')
+
+ ->register('transport.loginauth')
+ ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_LoginAuthenticator')
+
+ ->register('transport.plainauth')
+ ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_PlainAuthenticator')
+
+ ->register('transport.xoauth2auth')
+ ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_XOAuth2Authenticator')
+
+ ->register('transport.ntlmauth')
+ ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_NTLMAuthenticator')
+
+ ->register('transport.eventdispatcher')
+ ->asNewInstanceOf('Swift_Events_SimpleEventDispatcher')
+
+ ->register('transport.replacementfactory')
+ ->asSharedInstanceOf('Swift_StreamFilters_StringReplacementFilterFactory')
+;
diff --git a/vendor/swiftmailer/mime_types.php b/vendor/swiftmailer/mime_types.php
new file mode 100644
index 00000000..f31567d6
--- /dev/null
+++ b/vendor/swiftmailer/mime_types.php
@@ -0,0 +1,1007 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * autogenerated using http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
+ * and https://raw.github.com/minad/mimemagic/master/script/freedesktop.org.xml
+ */
+
+/*
+ * List of MIME type automatically detected in Swift Mailer.
+ */
+
+// You may add or take away what you like (lowercase required)
+
+$swift_mime_types = array(
+ '3dml' => 'text/vnd.in3d.3dml',
+ '3ds' => 'image/x-3ds',
+ '3g2' => 'video/3gpp2',
+ '3gp' => 'video/3gpp',
+ '7z' => 'application/x-7z-compressed',
+ 'aab' => 'application/x-authorware-bin',
+ 'aac' => 'audio/x-aac',
+ 'aam' => 'application/x-authorware-map',
+ 'aas' => 'application/x-authorware-seg',
+ 'abw' => 'application/x-abiword',
+ 'ac' => 'application/pkix-attr-cert',
+ 'acc' => 'application/vnd.americandynamics.acc',
+ 'ace' => 'application/x-ace-compressed',
+ 'acu' => 'application/vnd.acucobol',
+ 'acutc' => 'application/vnd.acucorp',
+ 'adp' => 'audio/adpcm',
+ 'aep' => 'application/vnd.audiograph',
+ 'afm' => 'application/x-font-type1',
+ 'afp' => 'application/vnd.ibm.modcap',
+ 'ahead' => 'application/vnd.ahead.space',
+ 'ai' => 'application/postscript',
+ 'aif' => 'audio/x-aiff',
+ 'aifc' => 'audio/x-aiff',
+ 'aiff' => 'audio/x-aiff',
+ 'air' => 'application/vnd.adobe.air-application-installer-package+zip',
+ 'ait' => 'application/vnd.dvb.ait',
+ 'ami' => 'application/vnd.amiga.ami',
+ 'apk' => 'application/vnd.android.package-archive',
+ 'appcache' => 'text/cache-manifest',
+ 'apr' => 'application/vnd.lotus-approach',
+ 'aps' => 'application/postscript',
+ 'arc' => 'application/x-freearc',
+ 'asc' => 'application/pgp-signature',
+ 'asf' => 'video/x-ms-asf',
+ 'asm' => 'text/x-asm',
+ 'aso' => 'application/vnd.accpac.simply.aso',
+ 'asx' => 'video/x-ms-asf',
+ 'atc' => 'application/vnd.acucorp',
+ 'atom' => 'application/atom+xml',
+ 'atomcat' => 'application/atomcat+xml',
+ 'atomsvc' => 'application/atomsvc+xml',
+ 'atx' => 'application/vnd.antix.game-component',
+ 'au' => 'audio/basic',
+ 'avi' => 'video/x-msvideo',
+ 'aw' => 'application/applixware',
+ 'azf' => 'application/vnd.airzip.filesecure.azf',
+ 'azs' => 'application/vnd.airzip.filesecure.azs',
+ 'azw' => 'application/vnd.amazon.ebook',
+ 'bat' => 'application/x-msdownload',
+ 'bcpio' => 'application/x-bcpio',
+ 'bdf' => 'application/x-font-bdf',
+ 'bdm' => 'application/vnd.syncml.dm+wbxml',
+ 'bed' => 'application/vnd.realvnc.bed',
+ 'bh2' => 'application/vnd.fujitsu.oasysprs',
+ 'bin' => 'application/octet-stream',
+ 'blb' => 'application/x-blorb',
+ 'blorb' => 'application/x-blorb',
+ 'bmi' => 'application/vnd.bmi',
+ 'bmp' => 'image/bmp',
+ 'book' => 'application/vnd.framemaker',
+ 'box' => 'application/vnd.previewsystems.box',
+ 'boz' => 'application/x-bzip2',
+ 'bpk' => 'application/octet-stream',
+ 'btif' => 'image/prs.btif',
+ 'bz' => 'application/x-bzip',
+ 'bz2' => 'application/x-bzip2',
+ 'c' => 'text/x-c',
+ 'c11amc' => 'application/vnd.cluetrust.cartomobile-config',
+ 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg',
+ 'c4d' => 'application/vnd.clonk.c4group',
+ 'c4f' => 'application/vnd.clonk.c4group',
+ 'c4g' => 'application/vnd.clonk.c4group',
+ 'c4p' => 'application/vnd.clonk.c4group',
+ 'c4u' => 'application/vnd.clonk.c4group',
+ 'cab' => 'application/vnd.ms-cab-compressed',
+ 'caf' => 'audio/x-caf',
+ 'cap' => 'application/vnd.tcpdump.pcap',
+ 'car' => 'application/vnd.curl.car',
+ 'cat' => 'application/vnd.ms-pki.seccat',
+ 'cb7' => 'application/x-cbr',
+ 'cba' => 'application/x-cbr',
+ 'cbr' => 'application/x-cbr',
+ 'cbt' => 'application/x-cbr',
+ 'cbz' => 'application/x-cbr',
+ 'cc' => 'text/x-c',
+ 'cct' => 'application/x-director',
+ 'ccxml' => 'application/ccxml+xml',
+ 'cdbcmsg' => 'application/vnd.contact.cmsg',
+ 'cdf' => 'application/x-netcdf',
+ 'cdkey' => 'application/vnd.mediastation.cdkey',
+ 'cdmia' => 'application/cdmi-capability',
+ 'cdmic' => 'application/cdmi-container',
+ 'cdmid' => 'application/cdmi-domain',
+ 'cdmio' => 'application/cdmi-object',
+ 'cdmiq' => 'application/cdmi-queue',
+ 'cdx' => 'chemical/x-cdx',
+ 'cdxml' => 'application/vnd.chemdraw+xml',
+ 'cdy' => 'application/vnd.cinderella',
+ 'cer' => 'application/pkix-cert',
+ 'cfs' => 'application/x-cfs-compressed',
+ 'cgm' => 'image/cgm',
+ 'chat' => 'application/x-chat',
+ 'chm' => 'application/vnd.ms-htmlhelp',
+ 'chrt' => 'application/vnd.kde.kchart',
+ 'cif' => 'chemical/x-cif',
+ 'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
+ 'cil' => 'application/vnd.ms-artgalry',
+ 'cla' => 'application/vnd.claymore',
+ 'class' => 'application/java-vm',
+ 'clkk' => 'application/vnd.crick.clicker.keyboard',
+ 'clkp' => 'application/vnd.crick.clicker.palette',
+ 'clkt' => 'application/vnd.crick.clicker.template',
+ 'clkw' => 'application/vnd.crick.clicker.wordbank',
+ 'clkx' => 'application/vnd.crick.clicker',
+ 'clp' => 'application/x-msclip',
+ 'cmc' => 'application/vnd.cosmocaller',
+ 'cmdf' => 'chemical/x-cmdf',
+ 'cml' => 'chemical/x-cml',
+ 'cmp' => 'application/vnd.yellowriver-custom-menu',
+ 'cmx' => 'image/x-cmx',
+ 'cod' => 'application/vnd.rim.cod',
+ 'com' => 'application/x-msdownload',
+ 'conf' => 'text/plain',
+ 'cpio' => 'application/x-cpio',
+ 'cpp' => 'text/x-c',
+ 'cpt' => 'application/mac-compactpro',
+ 'crd' => 'application/x-mscardfile',
+ 'crl' => 'application/pkix-crl',
+ 'crt' => 'application/x-x509-ca-cert',
+ 'csh' => 'application/x-csh',
+ 'csml' => 'chemical/x-csml',
+ 'csp' => 'application/vnd.commonspace',
+ 'css' => 'text/css',
+ 'cst' => 'application/x-director',
+ 'csv' => 'text/csv',
+ 'cu' => 'application/cu-seeme',
+ 'curl' => 'text/vnd.curl',
+ 'cww' => 'application/prs.cww',
+ 'cxt' => 'application/x-director',
+ 'cxx' => 'text/x-c',
+ 'dae' => 'model/vnd.collada+xml',
+ 'daf' => 'application/vnd.mobius.daf',
+ 'dart' => 'application/vnd.dart',
+ 'dataless' => 'application/vnd.fdsn.seed',
+ 'davmount' => 'application/davmount+xml',
+ 'dbk' => 'application/docbook+xml',
+ 'dcr' => 'application/x-director',
+ 'dcurl' => 'text/vnd.curl.dcurl',
+ 'dd2' => 'application/vnd.oma.dd2+xml',
+ 'ddd' => 'application/vnd.fujixerox.ddd',
+ 'deb' => 'application/x-debian-package',
+ 'def' => 'text/plain',
+ 'deploy' => 'application/octet-stream',
+ 'der' => 'application/x-x509-ca-cert',
+ 'dfac' => 'application/vnd.dreamfactory',
+ 'dgc' => 'application/x-dgc-compressed',
+ 'dic' => 'text/x-c',
+ 'dir' => 'application/x-director',
+ 'dis' => 'application/vnd.mobius.dis',
+ 'dist' => 'application/octet-stream',
+ 'distz' => 'application/octet-stream',
+ 'djv' => 'image/vnd.djvu',
+ 'djvu' => 'image/vnd.djvu',
+ 'dll' => 'application/x-msdownload',
+ 'dmg' => 'application/x-apple-diskimage',
+ 'dmp' => 'application/vnd.tcpdump.pcap',
+ 'dms' => 'application/octet-stream',
+ 'dna' => 'application/vnd.dna',
+ 'doc' => 'application/msword',
+ 'docm' => 'application/vnd.ms-word.document.macroenabled.12',
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'dot' => 'application/msword',
+ 'dotm' => 'application/vnd.ms-word.template.macroenabled.12',
+ 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
+ 'dp' => 'application/vnd.osgi.dp',
+ 'dpg' => 'application/vnd.dpgraph',
+ 'dra' => 'audio/vnd.dra',
+ 'dsc' => 'text/prs.lines.tag',
+ 'dssc' => 'application/dssc+der',
+ 'dtb' => 'application/x-dtbook+xml',
+ 'dtd' => 'application/xml-dtd',
+ 'dts' => 'audio/vnd.dts',
+ 'dtshd' => 'audio/vnd.dts.hd',
+ 'dump' => 'application/octet-stream',
+ 'dvb' => 'video/vnd.dvb.file',
+ 'dvi' => 'application/x-dvi',
+ 'dwf' => 'model/vnd.dwf',
+ 'dwg' => 'image/vnd.dwg',
+ 'dxf' => 'image/vnd.dxf',
+ 'dxp' => 'application/vnd.spotfire.dxp',
+ 'dxr' => 'application/x-director',
+ 'ecelp4800' => 'audio/vnd.nuera.ecelp4800',
+ 'ecelp7470' => 'audio/vnd.nuera.ecelp7470',
+ 'ecelp9600' => 'audio/vnd.nuera.ecelp9600',
+ 'ecma' => 'application/ecmascript',
+ 'edm' => 'application/vnd.novadigm.edm',
+ 'edx' => 'application/vnd.novadigm.edx',
+ 'efif' => 'application/vnd.picsel',
+ 'ei6' => 'application/vnd.pg.osasli',
+ 'elc' => 'application/octet-stream',
+ 'emf' => 'application/x-msmetafile',
+ 'eml' => 'message/rfc822',
+ 'emma' => 'application/emma+xml',
+ 'emz' => 'application/x-msmetafile',
+ 'eol' => 'audio/vnd.digital-winds',
+ 'eot' => 'application/vnd.ms-fontobject',
+ 'eps' => 'application/postscript',
+ 'epub' => 'application/epub+zip',
+ 'es3' => 'application/vnd.eszigno3+xml',
+ 'esa' => 'application/vnd.osgi.subsystem',
+ 'esf' => 'application/vnd.epson.esf',
+ 'et3' => 'application/vnd.eszigno3+xml',
+ 'etx' => 'text/x-setext',
+ 'eva' => 'application/x-eva',
+ 'evy' => 'application/x-envoy',
+ 'exe' => 'application/x-msdownload',
+ 'exi' => 'application/exi',
+ 'ext' => 'application/vnd.novadigm.ext',
+ 'ez' => 'application/andrew-inset',
+ 'ez2' => 'application/vnd.ezpix-album',
+ 'ez3' => 'application/vnd.ezpix-package',
+ 'f' => 'text/x-fortran',
+ 'f4v' => 'video/x-f4v',
+ 'f77' => 'text/x-fortran',
+ 'f90' => 'text/x-fortran',
+ 'fbs' => 'image/vnd.fastbidsheet',
+ 'fcdt' => 'application/vnd.adobe.formscentral.fcdt',
+ 'fcs' => 'application/vnd.isac.fcs',
+ 'fdf' => 'application/vnd.fdf',
+ 'fe_launch' => 'application/vnd.denovo.fcselayout-link',
+ 'fg5' => 'application/vnd.fujitsu.oasysgp',
+ 'fgd' => 'application/x-director',
+ 'fh' => 'image/x-freehand',
+ 'fh4' => 'image/x-freehand',
+ 'fh5' => 'image/x-freehand',
+ 'fh7' => 'image/x-freehand',
+ 'fhc' => 'image/x-freehand',
+ 'fig' => 'application/x-xfig',
+ 'flac' => 'audio/x-flac',
+ 'fli' => 'video/x-fli',
+ 'flo' => 'application/vnd.micrografx.flo',
+ 'flv' => 'video/x-flv',
+ 'flw' => 'application/vnd.kde.kivio',
+ 'flx' => 'text/vnd.fmi.flexstor',
+ 'fly' => 'text/vnd.fly',
+ 'fm' => 'application/vnd.framemaker',
+ 'fnc' => 'application/vnd.frogans.fnc',
+ 'for' => 'text/x-fortran',
+ 'fpx' => 'image/vnd.fpx',
+ 'frame' => 'application/vnd.framemaker',
+ 'fsc' => 'application/vnd.fsc.weblaunch',
+ 'fst' => 'image/vnd.fst',
+ 'ftc' => 'application/vnd.fluxtime.clip',
+ 'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
+ 'fvt' => 'video/vnd.fvt',
+ 'fxp' => 'application/vnd.adobe.fxp',
+ 'fxpl' => 'application/vnd.adobe.fxp',
+ 'fzs' => 'application/vnd.fuzzysheet',
+ 'g2w' => 'application/vnd.geoplan',
+ 'g3' => 'image/g3fax',
+ 'g3w' => 'application/vnd.geospace',
+ 'gac' => 'application/vnd.groove-account',
+ 'gam' => 'application/x-tads',
+ 'gbr' => 'application/rpki-ghostbusters',
+ 'gca' => 'application/x-gca-compressed',
+ 'gdl' => 'model/vnd.gdl',
+ 'geo' => 'application/vnd.dynageo',
+ 'gex' => 'application/vnd.geometry-explorer',
+ 'ggb' => 'application/vnd.geogebra.file',
+ 'ggt' => 'application/vnd.geogebra.tool',
+ 'ghf' => 'application/vnd.groove-help',
+ 'gif' => 'image/gif',
+ 'gim' => 'application/vnd.groove-identity-message',
+ 'gml' => 'application/gml+xml',
+ 'gmx' => 'application/vnd.gmx',
+ 'gnumeric' => 'application/x-gnumeric',
+ 'gph' => 'application/vnd.flographit',
+ 'gpx' => 'application/gpx+xml',
+ 'gqf' => 'application/vnd.grafeq',
+ 'gqs' => 'application/vnd.grafeq',
+ 'gram' => 'application/srgs',
+ 'gramps' => 'application/x-gramps-xml',
+ 'gre' => 'application/vnd.geometry-explorer',
+ 'grv' => 'application/vnd.groove-injector',
+ 'grxml' => 'application/srgs+xml',
+ 'gsf' => 'application/x-font-ghostscript',
+ 'gtar' => 'application/x-gtar',
+ 'gtm' => 'application/vnd.groove-tool-message',
+ 'gtw' => 'model/vnd.gtw',
+ 'gv' => 'text/vnd.graphviz',
+ 'gxf' => 'application/gxf',
+ 'gxt' => 'application/vnd.geonext',
+ 'gz' => 'application/x-gzip',
+ 'h' => 'text/x-c',
+ 'h261' => 'video/h261',
+ 'h263' => 'video/h263',
+ 'h264' => 'video/h264',
+ 'hal' => 'application/vnd.hal+xml',
+ 'hbci' => 'application/vnd.hbci',
+ 'hdf' => 'application/x-hdf',
+ 'hh' => 'text/x-c',
+ 'hlp' => 'application/winhlp',
+ 'hpgl' => 'application/vnd.hp-hpgl',
+ 'hpid' => 'application/vnd.hp-hpid',
+ 'hps' => 'application/vnd.hp-hps',
+ 'hqx' => 'application/mac-binhex40',
+ 'htke' => 'application/vnd.kenameaapp',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'hvd' => 'application/vnd.yamaha.hv-dic',
+ 'hvp' => 'application/vnd.yamaha.hv-voice',
+ 'hvs' => 'application/vnd.yamaha.hv-script',
+ 'i2g' => 'application/vnd.intergeo',
+ 'icc' => 'application/vnd.iccprofile',
+ 'ice' => 'x-conference/x-cooltalk',
+ 'icm' => 'application/vnd.iccprofile',
+ 'ico' => 'image/x-icon',
+ 'ics' => 'text/calendar',
+ 'ief' => 'image/ief',
+ 'ifb' => 'text/calendar',
+ 'ifm' => 'application/vnd.shana.informed.formdata',
+ 'iges' => 'model/iges',
+ 'igl' => 'application/vnd.igloader',
+ 'igm' => 'application/vnd.insors.igm',
+ 'igs' => 'model/iges',
+ 'igx' => 'application/vnd.micrografx.igx',
+ 'iif' => 'application/vnd.shana.informed.interchange',
+ 'imp' => 'application/vnd.accpac.simply.imp',
+ 'ims' => 'application/vnd.ms-ims',
+ 'in' => 'text/plain',
+ 'ink' => 'application/inkml+xml',
+ 'inkml' => 'application/inkml+xml',
+ 'install' => 'application/x-install-instructions',
+ 'iota' => 'application/vnd.astraea-software.iota',
+ 'ipfix' => 'application/ipfix',
+ 'ipk' => 'application/vnd.shana.informed.package',
+ 'irm' => 'application/vnd.ibm.rights-management',
+ 'irp' => 'application/vnd.irepository.package+xml',
+ 'iso' => 'application/x-iso9660-image',
+ 'itp' => 'application/vnd.shana.informed.formtemplate',
+ 'ivp' => 'application/vnd.immervision-ivp',
+ 'ivu' => 'application/vnd.immervision-ivu',
+ 'jad' => 'text/vnd.sun.j2me.app-descriptor',
+ 'jam' => 'application/vnd.jam',
+ 'jar' => 'application/java-archive',
+ 'java' => 'text/x-java-source',
+ 'jisp' => 'application/vnd.jisp',
+ 'jlt' => 'application/vnd.hp-jlyt',
+ 'jnlp' => 'application/x-java-jnlp-file',
+ 'joda' => 'application/vnd.joost.joda-archive',
+ 'jpe' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'jpgm' => 'video/jpm',
+ 'jpgv' => 'video/jpeg',
+ 'jpm' => 'video/jpm',
+ 'js' => 'application/javascript',
+ 'json' => 'application/json',
+ 'jsonml' => 'application/jsonml+json',
+ 'kar' => 'audio/midi',
+ 'karbon' => 'application/vnd.kde.karbon',
+ 'kfo' => 'application/vnd.kde.kformula',
+ 'kia' => 'application/vnd.kidspiration',
+ 'kml' => 'application/vnd.google-earth.kml+xml',
+ 'kmz' => 'application/vnd.google-earth.kmz',
+ 'kne' => 'application/vnd.kinar',
+ 'knp' => 'application/vnd.kinar',
+ 'kon' => 'application/vnd.kde.kontour',
+ 'kpr' => 'application/vnd.kde.kpresenter',
+ 'kpt' => 'application/vnd.kde.kpresenter',
+ 'kpxx' => 'application/vnd.ds-keypoint',
+ 'ksp' => 'application/vnd.kde.kspread',
+ 'ktr' => 'application/vnd.kahootz',
+ 'ktx' => 'image/ktx',
+ 'ktz' => 'application/vnd.kahootz',
+ 'kwd' => 'application/vnd.kde.kword',
+ 'kwt' => 'application/vnd.kde.kword',
+ 'lasxml' => 'application/vnd.las.las+xml',
+ 'latex' => 'application/x-latex',
+ 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
+ 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
+ 'les' => 'application/vnd.hhe.lesson-player',
+ 'lha' => 'application/x-lzh-compressed',
+ 'link66' => 'application/vnd.route66.link66+xml',
+ 'list' => 'text/plain',
+ 'list3820' => 'application/vnd.ibm.modcap',
+ 'listafp' => 'application/vnd.ibm.modcap',
+ 'lnk' => 'application/x-ms-shortcut',
+ 'log' => 'text/plain',
+ 'lostxml' => 'application/lost+xml',
+ 'lrf' => 'application/octet-stream',
+ 'lrm' => 'application/vnd.ms-lrm',
+ 'ltf' => 'application/vnd.frogans.ltf',
+ 'lvp' => 'audio/vnd.lucent.voice',
+ 'lwp' => 'application/vnd.lotus-wordpro',
+ 'lzh' => 'application/x-lzh-compressed',
+ 'm13' => 'application/x-msmediaview',
+ 'm14' => 'application/x-msmediaview',
+ 'm1v' => 'video/mpeg',
+ 'm21' => 'application/mp21',
+ 'm2a' => 'audio/mpeg',
+ 'm2v' => 'video/mpeg',
+ 'm3a' => 'audio/mpeg',
+ 'm3u' => 'audio/x-mpegurl',
+ 'm3u8' => 'application/vnd.apple.mpegurl',
+ 'm4a' => 'audio/mp4',
+ 'm4u' => 'video/vnd.mpegurl',
+ 'm4v' => 'video/x-m4v',
+ 'ma' => 'application/mathematica',
+ 'mads' => 'application/mads+xml',
+ 'mag' => 'application/vnd.ecowin.chart',
+ 'maker' => 'application/vnd.framemaker',
+ 'man' => 'text/troff',
+ 'mar' => 'application/octet-stream',
+ 'mathml' => 'application/mathml+xml',
+ 'mb' => 'application/mathematica',
+ 'mbk' => 'application/vnd.mobius.mbk',
+ 'mbox' => 'application/mbox',
+ 'mc1' => 'application/vnd.medcalcdata',
+ 'mcd' => 'application/vnd.mcd',
+ 'mcurl' => 'text/vnd.curl.mcurl',
+ 'mdb' => 'application/x-msaccess',
+ 'mdi' => 'image/vnd.ms-modi',
+ 'me' => 'text/troff',
+ 'mesh' => 'model/mesh',
+ 'meta4' => 'application/metalink4+xml',
+ 'metalink' => 'application/metalink+xml',
+ 'mets' => 'application/mets+xml',
+ 'mfm' => 'application/vnd.mfmp',
+ 'mft' => 'application/rpki-manifest',
+ 'mgp' => 'application/vnd.osgeo.mapguide.package',
+ 'mgz' => 'application/vnd.proteus.magazine',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'mie' => 'application/x-mie',
+ 'mif' => 'application/vnd.mif',
+ 'mime' => 'message/rfc822',
+ 'mj2' => 'video/mj2',
+ 'mjp2' => 'video/mj2',
+ 'mk3d' => 'video/x-matroska',
+ 'mka' => 'audio/x-matroska',
+ 'mks' => 'video/x-matroska',
+ 'mkv' => 'video/x-matroska',
+ 'mlp' => 'application/vnd.dolby.mlp',
+ 'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
+ 'mmf' => 'application/vnd.smaf',
+ 'mmr' => 'image/vnd.fujixerox.edmics-mmr',
+ 'mng' => 'video/x-mng',
+ 'mny' => 'application/x-msmoney',
+ 'mobi' => 'application/x-mobipocket-ebook',
+ 'mods' => 'application/mods+xml',
+ 'mov' => 'video/quicktime',
+ 'movie' => 'video/x-sgi-movie',
+ 'mp2' => 'audio/mpeg',
+ 'mp21' => 'application/mp21',
+ 'mp2a' => 'audio/mpeg',
+ 'mp3' => 'audio/mpeg',
+ 'mp4' => 'video/mp4',
+ 'mp4a' => 'audio/mp4',
+ 'mp4s' => 'application/mp4',
+ 'mp4v' => 'video/mp4',
+ 'mpc' => 'application/vnd.mophun.certificate',
+ 'mpe' => 'video/mpeg',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mpg4' => 'video/mp4',
+ 'mpga' => 'audio/mpeg',
+ 'mpkg' => 'application/vnd.apple.installer+xml',
+ 'mpm' => 'application/vnd.blueice.multipass',
+ 'mpn' => 'application/vnd.mophun.application',
+ 'mpp' => 'application/vnd.ms-project',
+ 'mpt' => 'application/vnd.ms-project',
+ 'mpy' => 'application/vnd.ibm.minipay',
+ 'mqy' => 'application/vnd.mobius.mqy',
+ 'mrc' => 'application/marc',
+ 'mrcx' => 'application/marcxml+xml',
+ 'ms' => 'text/troff',
+ 'mscml' => 'application/mediaservercontrol+xml',
+ 'mseed' => 'application/vnd.fdsn.mseed',
+ 'mseq' => 'application/vnd.mseq',
+ 'msf' => 'application/vnd.epson.msf',
+ 'msh' => 'model/mesh',
+ 'msi' => 'application/x-msdownload',
+ 'msl' => 'application/vnd.mobius.msl',
+ 'msty' => 'application/vnd.muvee.style',
+ 'mts' => 'model/vnd.mts',
+ 'mus' => 'application/vnd.musician',
+ 'musicxml' => 'application/vnd.recordare.musicxml+xml',
+ 'mvb' => 'application/x-msmediaview',
+ 'mwf' => 'application/vnd.mfer',
+ 'mxf' => 'application/mxf',
+ 'mxl' => 'application/vnd.recordare.musicxml',
+ 'mxml' => 'application/xv+xml',
+ 'mxs' => 'application/vnd.triscape.mxs',
+ 'mxu' => 'video/vnd.mpegurl',
+ 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
+ 'n3' => 'text/n3',
+ 'nb' => 'application/mathematica',
+ 'nbp' => 'application/vnd.wolfram.player',
+ 'nc' => 'application/x-netcdf',
+ 'ncx' => 'application/x-dtbncx+xml',
+ 'nfo' => 'text/x-nfo',
+ 'ngdat' => 'application/vnd.nokia.n-gage.data',
+ 'nitf' => 'application/vnd.nitf',
+ 'nlu' => 'application/vnd.neurolanguage.nlu',
+ 'nml' => 'application/vnd.enliven',
+ 'nnd' => 'application/vnd.noblenet-directory',
+ 'nns' => 'application/vnd.noblenet-sealer',
+ 'nnw' => 'application/vnd.noblenet-web',
+ 'npx' => 'image/vnd.net-fpx',
+ 'nsc' => 'application/x-conference',
+ 'nsf' => 'application/vnd.lotus-notes',
+ 'ntf' => 'application/vnd.nitf',
+ 'nzb' => 'application/x-nzb',
+ 'oa2' => 'application/vnd.fujitsu.oasys2',
+ 'oa3' => 'application/vnd.fujitsu.oasys3',
+ 'oas' => 'application/vnd.fujitsu.oasys',
+ 'obd' => 'application/x-msbinder',
+ 'obj' => 'application/x-tgif',
+ 'oda' => 'application/oda',
+ 'odb' => 'application/vnd.oasis.opendocument.database',
+ 'odc' => 'application/vnd.oasis.opendocument.chart',
+ 'odf' => 'application/vnd.oasis.opendocument.formula',
+ 'odft' => 'application/vnd.oasis.opendocument.formula-template',
+ 'odg' => 'application/vnd.oasis.opendocument.graphics',
+ 'odi' => 'application/vnd.oasis.opendocument.image',
+ 'odm' => 'application/vnd.oasis.opendocument.text-master',
+ 'odp' => 'application/vnd.oasis.opendocument.presentation',
+ 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
+ 'odt' => 'application/vnd.oasis.opendocument.text',
+ 'oga' => 'audio/ogg',
+ 'ogg' => 'audio/ogg',
+ 'ogv' => 'video/ogg',
+ 'ogx' => 'application/ogg',
+ 'omdoc' => 'application/omdoc+xml',
+ 'onepkg' => 'application/onenote',
+ 'onetmp' => 'application/onenote',
+ 'onetoc' => 'application/onenote',
+ 'onetoc2' => 'application/onenote',
+ 'opf' => 'application/oebps-package+xml',
+ 'opml' => 'text/x-opml',
+ 'oprc' => 'application/vnd.palm',
+ 'org' => 'application/vnd.lotus-organizer',
+ 'osf' => 'application/vnd.yamaha.openscoreformat',
+ 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml',
+ 'otc' => 'application/vnd.oasis.opendocument.chart-template',
+ 'otf' => 'application/x-font-otf',
+ 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
+ 'oth' => 'application/vnd.oasis.opendocument.text-web',
+ 'oti' => 'application/vnd.oasis.opendocument.image-template',
+ 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
+ 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
+ 'ott' => 'application/vnd.oasis.opendocument.text-template',
+ 'oxps' => 'application/oxps',
+ 'oxt' => 'application/vnd.openofficeorg.extension',
+ 'p' => 'text/x-pascal',
+ 'p10' => 'application/pkcs10',
+ 'p12' => 'application/x-pkcs12',
+ 'p7b' => 'application/x-pkcs7-certificates',
+ 'p7c' => 'application/pkcs7-mime',
+ 'p7m' => 'application/pkcs7-mime',
+ 'p7r' => 'application/x-pkcs7-certreqresp',
+ 'p7s' => 'application/pkcs7-signature',
+ 'p8' => 'application/pkcs8',
+ 'pas' => 'text/x-pascal',
+ 'paw' => 'application/vnd.pawaafile',
+ 'pbd' => 'application/vnd.powerbuilder6',
+ 'pbm' => 'image/x-portable-bitmap',
+ 'pcap' => 'application/vnd.tcpdump.pcap',
+ 'pcf' => 'application/x-font-pcf',
+ 'pcl' => 'application/vnd.hp-pcl',
+ 'pclxl' => 'application/vnd.hp-pclxl',
+ 'pct' => 'image/x-pict',
+ 'pcurl' => 'application/vnd.curl.pcurl',
+ 'pcx' => 'image/x-pcx',
+ 'pdb' => 'application/vnd.palm',
+ 'pdf' => 'application/pdf',
+ 'pfa' => 'application/x-font-type1',
+ 'pfb' => 'application/x-font-type1',
+ 'pfm' => 'application/x-font-type1',
+ 'pfr' => 'application/font-tdpfr',
+ 'pfx' => 'application/x-pkcs12',
+ 'pgm' => 'image/x-portable-graymap',
+ 'pgn' => 'application/x-chess-pgn',
+ 'pgp' => 'application/pgp-encrypted',
+ 'php' => 'application/x-php',
+ 'php3' => 'application/x-php',
+ 'php4' => 'application/x-php',
+ 'php5' => 'application/x-php',
+ 'pic' => 'image/x-pict',
+ 'pkg' => 'application/octet-stream',
+ 'pki' => 'application/pkixcmp',
+ 'pkipath' => 'application/pkix-pkipath',
+ 'plb' => 'application/vnd.3gpp.pic-bw-large',
+ 'plc' => 'application/vnd.mobius.plc',
+ 'plf' => 'application/vnd.pocketlearn',
+ 'pls' => 'application/pls+xml',
+ 'pml' => 'application/vnd.ctc-posml',
+ 'png' => 'image/png',
+ 'pnm' => 'image/x-portable-anymap',
+ 'portpkg' => 'application/vnd.macports.portpkg',
+ 'pot' => 'application/vnd.ms-powerpoint',
+ 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12',
+ 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
+ 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12',
+ 'ppd' => 'application/vnd.cups-ppd',
+ 'ppm' => 'image/x-portable-pixmap',
+ 'pps' => 'application/vnd.ms-powerpoint',
+ 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12',
+ 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12',
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'pqa' => 'application/vnd.palm',
+ 'prc' => 'application/x-mobipocket-ebook',
+ 'pre' => 'application/vnd.lotus-freelance',
+ 'prf' => 'application/pics-rules',
+ 'ps' => 'application/postscript',
+ 'psb' => 'application/vnd.3gpp.pic-bw-small',
+ 'psd' => 'image/vnd.adobe.photoshop',
+ 'psf' => 'application/x-font-linux-psf',
+ 'pskcxml' => 'application/pskc+xml',
+ 'ptid' => 'application/vnd.pvi.ptid1',
+ 'pub' => 'application/x-mspublisher',
+ 'pvb' => 'application/vnd.3gpp.pic-bw-var',
+ 'pwn' => 'application/vnd.3m.post-it-notes',
+ 'pya' => 'audio/vnd.ms-playready.media.pya',
+ 'pyv' => 'video/vnd.ms-playready.media.pyv',
+ 'qam' => 'application/vnd.epson.quickanime',
+ 'qbo' => 'application/vnd.intu.qbo',
+ 'qfx' => 'application/vnd.intu.qfx',
+ 'qps' => 'application/vnd.publishare-delta-tree',
+ 'qt' => 'video/quicktime',
+ 'qwd' => 'application/vnd.quark.quarkxpress',
+ 'qwt' => 'application/vnd.quark.quarkxpress',
+ 'qxb' => 'application/vnd.quark.quarkxpress',
+ 'qxd' => 'application/vnd.quark.quarkxpress',
+ 'qxl' => 'application/vnd.quark.quarkxpress',
+ 'qxt' => 'application/vnd.quark.quarkxpress',
+ 'ra' => 'audio/x-pn-realaudio',
+ 'ram' => 'audio/x-pn-realaudio',
+ 'rar' => 'application/x-rar-compressed',
+ 'ras' => 'image/x-cmu-raster',
+ 'rcprofile' => 'application/vnd.ipunplugged.rcprofile',
+ 'rdf' => 'application/rdf+xml',
+ 'rdz' => 'application/vnd.data-vision.rdz',
+ 'rep' => 'application/vnd.businessobjects',
+ 'res' => 'application/x-dtbresource+xml',
+ 'rgb' => 'image/x-rgb',
+ 'rif' => 'application/reginfo+xml',
+ 'rip' => 'audio/vnd.rip',
+ 'ris' => 'application/x-research-info-systems',
+ 'rl' => 'application/resource-lists+xml',
+ 'rlc' => 'image/vnd.fujixerox.edmics-rlc',
+ 'rld' => 'application/resource-lists-diff+xml',
+ 'rm' => 'application/vnd.rn-realmedia',
+ 'rmi' => 'audio/midi',
+ 'rmp' => 'audio/x-pn-realaudio-plugin',
+ 'rms' => 'application/vnd.jcp.javame.midlet-rms',
+ 'rmvb' => 'application/vnd.rn-realmedia-vbr',
+ 'rnc' => 'application/relax-ng-compact-syntax',
+ 'roa' => 'application/rpki-roa',
+ 'roff' => 'text/troff',
+ 'rp9' => 'application/vnd.cloanto.rp9',
+ 'rpss' => 'application/vnd.nokia.radio-presets',
+ 'rpst' => 'application/vnd.nokia.radio-preset',
+ 'rq' => 'application/sparql-query',
+ 'rs' => 'application/rls-services+xml',
+ 'rsd' => 'application/rsd+xml',
+ 'rss' => 'application/rss+xml',
+ 'rtf' => 'application/rtf',
+ 'rtx' => 'text/richtext',
+ 's' => 'text/x-asm',
+ 's3m' => 'audio/s3m',
+ 'saf' => 'application/vnd.yamaha.smaf-audio',
+ 'sbml' => 'application/sbml+xml',
+ 'sc' => 'application/vnd.ibm.secure-container',
+ 'scd' => 'application/x-msschedule',
+ 'scm' => 'application/vnd.lotus-screencam',
+ 'scq' => 'application/scvp-cv-request',
+ 'scs' => 'application/scvp-cv-response',
+ 'scurl' => 'text/vnd.curl.scurl',
+ 'sda' => 'application/vnd.stardivision.draw',
+ 'sdc' => 'application/vnd.stardivision.calc',
+ 'sdd' => 'application/vnd.stardivision.impress',
+ 'sdkd' => 'application/vnd.solent.sdkm+xml',
+ 'sdkm' => 'application/vnd.solent.sdkm+xml',
+ 'sdp' => 'application/sdp',
+ 'sdw' => 'application/vnd.stardivision.writer',
+ 'see' => 'application/vnd.seemail',
+ 'seed' => 'application/vnd.fdsn.seed',
+ 'sema' => 'application/vnd.sema',
+ 'semd' => 'application/vnd.semd',
+ 'semf' => 'application/vnd.semf',
+ 'ser' => 'application/java-serialized-object',
+ 'setpay' => 'application/set-payment-initiation',
+ 'setreg' => 'application/set-registration-initiation',
+ 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data',
+ 'sfs' => 'application/vnd.spotfire.sfs',
+ 'sfv' => 'text/x-sfv',
+ 'sgi' => 'image/sgi',
+ 'sgl' => 'application/vnd.stardivision.writer-global',
+ 'sgm' => 'text/sgml',
+ 'sgml' => 'text/sgml',
+ 'sh' => 'application/x-sh',
+ 'shar' => 'application/x-shar',
+ 'shf' => 'application/shf+xml',
+ 'sid' => 'image/x-mrsid-image',
+ 'sig' => 'application/pgp-signature',
+ 'sil' => 'audio/silk',
+ 'silo' => 'model/mesh',
+ 'sis' => 'application/vnd.symbian.install',
+ 'sisx' => 'application/vnd.symbian.install',
+ 'sit' => 'application/x-stuffit',
+ 'sitx' => 'application/x-stuffitx',
+ 'skd' => 'application/vnd.koan',
+ 'skm' => 'application/vnd.koan',
+ 'skp' => 'application/vnd.koan',
+ 'skt' => 'application/vnd.koan',
+ 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12',
+ 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
+ 'slt' => 'application/vnd.epson.salt',
+ 'sm' => 'application/vnd.stepmania.stepchart',
+ 'smf' => 'application/vnd.stardivision.math',
+ 'smi' => 'application/smil+xml',
+ 'smil' => 'application/smil+xml',
+ 'smv' => 'video/x-smv',
+ 'smzip' => 'application/vnd.stepmania.package',
+ 'snd' => 'audio/basic',
+ 'snf' => 'application/x-font-snf',
+ 'so' => 'application/octet-stream',
+ 'spc' => 'application/x-pkcs7-certificates',
+ 'spf' => 'application/vnd.yamaha.smaf-phrase',
+ 'spl' => 'application/x-futuresplash',
+ 'spot' => 'text/vnd.in3d.spot',
+ 'spp' => 'application/scvp-vp-response',
+ 'spq' => 'application/scvp-vp-request',
+ 'spx' => 'audio/ogg',
+ 'sql' => 'application/x-sql',
+ 'src' => 'application/x-wais-source',
+ 'srt' => 'application/x-subrip',
+ 'sru' => 'application/sru+xml',
+ 'srx' => 'application/sparql-results+xml',
+ 'ssdl' => 'application/ssdl+xml',
+ 'sse' => 'application/vnd.kodak-descriptor',
+ 'ssf' => 'application/vnd.epson.ssf',
+ 'ssml' => 'application/ssml+xml',
+ 'st' => 'application/vnd.sailingtracker.track',
+ 'stc' => 'application/vnd.sun.xml.calc.template',
+ 'std' => 'application/vnd.sun.xml.draw.template',
+ 'stf' => 'application/vnd.wt.stf',
+ 'sti' => 'application/vnd.sun.xml.impress.template',
+ 'stk' => 'application/hyperstudio',
+ 'stl' => 'application/vnd.ms-pki.stl',
+ 'str' => 'application/vnd.pg.format',
+ 'stw' => 'application/vnd.sun.xml.writer.template',
+ 'sub' => 'text/vnd.dvb.subtitle',
+ 'sus' => 'application/vnd.sus-calendar',
+ 'susp' => 'application/vnd.sus-calendar',
+ 'sv4cpio' => 'application/x-sv4cpio',
+ 'sv4crc' => 'application/x-sv4crc',
+ 'svc' => 'application/vnd.dvb.service',
+ 'svd' => 'application/vnd.svd',
+ 'svg' => 'image/svg+xml',
+ 'svgz' => 'image/svg+xml',
+ 'swa' => 'application/x-director',
+ 'swf' => 'application/x-shockwave-flash',
+ 'swi' => 'application/vnd.aristanetworks.swi',
+ 'sxc' => 'application/vnd.sun.xml.calc',
+ 'sxd' => 'application/vnd.sun.xml.draw',
+ 'sxg' => 'application/vnd.sun.xml.writer.global',
+ 'sxi' => 'application/vnd.sun.xml.impress',
+ 'sxm' => 'application/vnd.sun.xml.math',
+ 'sxw' => 'application/vnd.sun.xml.writer',
+ 't' => 'text/troff',
+ 't3' => 'application/x-t3vm-image',
+ 'taglet' => 'application/vnd.mynfc',
+ 'tao' => 'application/vnd.tao.intent-module-archive',
+ 'tar' => 'application/x-tar',
+ 'tcap' => 'application/vnd.3gpp2.tcap',
+ 'tcl' => 'application/x-tcl',
+ 'teacher' => 'application/vnd.smart.teacher',
+ 'tei' => 'application/tei+xml',
+ 'teicorpus' => 'application/tei+xml',
+ 'tex' => 'application/x-tex',
+ 'texi' => 'application/x-texinfo',
+ 'texinfo' => 'application/x-texinfo',
+ 'text' => 'text/plain',
+ 'tfi' => 'application/thraud+xml',
+ 'tfm' => 'application/x-tex-tfm',
+ 'tga' => 'image/x-tga',
+ 'thmx' => 'application/vnd.ms-officetheme',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'tmo' => 'application/vnd.tmobile-livetv',
+ 'torrent' => 'application/x-bittorrent',
+ 'tpl' => 'application/vnd.groove-tool-template',
+ 'tpt' => 'application/vnd.trid.tpt',
+ 'tr' => 'text/troff',
+ 'tra' => 'application/vnd.trueapp',
+ 'trm' => 'application/x-msterminal',
+ 'tsd' => 'application/timestamped-data',
+ 'tsv' => 'text/tab-separated-values',
+ 'ttc' => 'application/x-font-ttf',
+ 'ttf' => 'application/x-font-ttf',
+ 'ttl' => 'text/turtle',
+ 'twd' => 'application/vnd.simtech-mindmapper',
+ 'twds' => 'application/vnd.simtech-mindmapper',
+ 'txd' => 'application/vnd.genomatix.tuxedo',
+ 'txf' => 'application/vnd.mobius.txf',
+ 'txt' => 'text/plain',
+ 'u32' => 'application/x-authorware-bin',
+ 'udeb' => 'application/x-debian-package',
+ 'ufd' => 'application/vnd.ufdl',
+ 'ufdl' => 'application/vnd.ufdl',
+ 'ulx' => 'application/x-glulx',
+ 'umj' => 'application/vnd.umajin',
+ 'unityweb' => 'application/vnd.unity',
+ 'uoml' => 'application/vnd.uoml+xml',
+ 'uri' => 'text/uri-list',
+ 'uris' => 'text/uri-list',
+ 'urls' => 'text/uri-list',
+ 'ustar' => 'application/x-ustar',
+ 'utz' => 'application/vnd.uiq.theme',
+ 'uu' => 'text/x-uuencode',
+ 'uva' => 'audio/vnd.dece.audio',
+ 'uvd' => 'application/vnd.dece.data',
+ 'uvf' => 'application/vnd.dece.data',
+ 'uvg' => 'image/vnd.dece.graphic',
+ 'uvh' => 'video/vnd.dece.hd',
+ 'uvi' => 'image/vnd.dece.graphic',
+ 'uvm' => 'video/vnd.dece.mobile',
+ 'uvp' => 'video/vnd.dece.pd',
+ 'uvs' => 'video/vnd.dece.sd',
+ 'uvt' => 'application/vnd.dece.ttml+xml',
+ 'uvu' => 'video/vnd.uvvu.mp4',
+ 'uvv' => 'video/vnd.dece.video',
+ 'uvva' => 'audio/vnd.dece.audio',
+ 'uvvd' => 'application/vnd.dece.data',
+ 'uvvf' => 'application/vnd.dece.data',
+ 'uvvg' => 'image/vnd.dece.graphic',
+ 'uvvh' => 'video/vnd.dece.hd',
+ 'uvvi' => 'image/vnd.dece.graphic',
+ 'uvvm' => 'video/vnd.dece.mobile',
+ 'uvvp' => 'video/vnd.dece.pd',
+ 'uvvs' => 'video/vnd.dece.sd',
+ 'uvvt' => 'application/vnd.dece.ttml+xml',
+ 'uvvu' => 'video/vnd.uvvu.mp4',
+ 'uvvv' => 'video/vnd.dece.video',
+ 'uvvx' => 'application/vnd.dece.unspecified',
+ 'uvvz' => 'application/vnd.dece.zip',
+ 'uvx' => 'application/vnd.dece.unspecified',
+ 'uvz' => 'application/vnd.dece.zip',
+ 'vcard' => 'text/vcard',
+ 'vcd' => 'application/x-cdlink',
+ 'vcf' => 'text/x-vcard',
+ 'vcg' => 'application/vnd.groove-vcard',
+ 'vcs' => 'text/x-vcalendar',
+ 'vcx' => 'application/vnd.vcx',
+ 'vis' => 'application/vnd.visionary',
+ 'viv' => 'video/vnd.vivo',
+ 'vob' => 'video/x-ms-vob',
+ 'vor' => 'application/vnd.stardivision.writer',
+ 'vox' => 'application/x-authorware-bin',
+ 'vrml' => 'model/vrml',
+ 'vsd' => 'application/vnd.visio',
+ 'vsf' => 'application/vnd.vsf',
+ 'vss' => 'application/vnd.visio',
+ 'vst' => 'application/vnd.visio',
+ 'vsw' => 'application/vnd.visio',
+ 'vtu' => 'model/vnd.vtu',
+ 'vxml' => 'application/voicexml+xml',
+ 'w3d' => 'application/x-director',
+ 'wad' => 'application/x-doom',
+ 'wav' => 'audio/x-wav',
+ 'wax' => 'audio/x-ms-wax',
+ 'wbmp' => 'image/vnd.wap.wbmp',
+ 'wbs' => 'application/vnd.criticaltools.wbs+xml',
+ 'wbxml' => 'application/vnd.wap.wbxml',
+ 'wcm' => 'application/vnd.ms-works',
+ 'wdb' => 'application/vnd.ms-works',
+ 'wdp' => 'image/vnd.ms-photo',
+ 'weba' => 'audio/webm',
+ 'webm' => 'video/webm',
+ 'webp' => 'image/webp',
+ 'wg' => 'application/vnd.pmi.widget',
+ 'wgt' => 'application/widget',
+ 'wks' => 'application/vnd.ms-works',
+ 'wm' => 'video/x-ms-wm',
+ 'wma' => 'audio/x-ms-wma',
+ 'wmd' => 'application/x-ms-wmd',
+ 'wmf' => 'application/x-msmetafile',
+ 'wml' => 'text/vnd.wap.wml',
+ 'wmlc' => 'application/vnd.wap.wmlc',
+ 'wmls' => 'text/vnd.wap.wmlscript',
+ 'wmlsc' => 'application/vnd.wap.wmlscriptc',
+ 'wmv' => 'video/x-ms-wmv',
+ 'wmx' => 'video/x-ms-wmx',
+ 'wmz' => 'application/x-msmetafile',
+ 'woff' => 'application/font-woff',
+ 'wpd' => 'application/vnd.wordperfect',
+ 'wpl' => 'application/vnd.ms-wpl',
+ 'wps' => 'application/vnd.ms-works',
+ 'wqd' => 'application/vnd.wqd',
+ 'wri' => 'application/x-mswrite',
+ 'wrl' => 'model/vrml',
+ 'wsdl' => 'application/wsdl+xml',
+ 'wspolicy' => 'application/wspolicy+xml',
+ 'wtb' => 'application/vnd.webturbo',
+ 'wvx' => 'video/x-ms-wvx',
+ 'x32' => 'application/x-authorware-bin',
+ 'x3d' => 'model/x3d+xml',
+ 'x3db' => 'model/x3d+binary',
+ 'x3dbz' => 'model/x3d+binary',
+ 'x3dv' => 'model/x3d+vrml',
+ 'x3dvz' => 'model/x3d+vrml',
+ 'x3dz' => 'model/x3d+xml',
+ 'xaml' => 'application/xaml+xml',
+ 'xap' => 'application/x-silverlight-app',
+ 'xar' => 'application/vnd.xara',
+ 'xbap' => 'application/x-ms-xbap',
+ 'xbd' => 'application/vnd.fujixerox.docuworks.binder',
+ 'xbm' => 'image/x-xbitmap',
+ 'xdf' => 'application/xcap-diff+xml',
+ 'xdm' => 'application/vnd.syncml.dm+xml',
+ 'xdp' => 'application/vnd.adobe.xdp+xml',
+ 'xdssc' => 'application/dssc+xml',
+ 'xdw' => 'application/vnd.fujixerox.docuworks',
+ 'xenc' => 'application/xenc+xml',
+ 'xer' => 'application/patch-ops-error+xml',
+ 'xfdf' => 'application/vnd.adobe.xfdf',
+ 'xfdl' => 'application/vnd.xfdl',
+ 'xht' => 'application/xhtml+xml',
+ 'xhtml' => 'application/xhtml+xml',
+ 'xhvml' => 'application/xv+xml',
+ 'xif' => 'image/vnd.xiff',
+ 'xla' => 'application/vnd.ms-excel',
+ 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12',
+ 'xlc' => 'application/vnd.ms-excel',
+ 'xlf' => 'application/x-xliff+xml',
+ 'xlm' => 'application/vnd.ms-excel',
+ 'xls' => 'application/vnd.ms-excel',
+ 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12',
+ 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12',
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'xlt' => 'application/vnd.ms-excel',
+ 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12',
+ 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
+ 'xlw' => 'application/vnd.ms-excel',
+ 'xm' => 'audio/xm',
+ 'xml' => 'application/xml',
+ 'xo' => 'application/vnd.olpc-sugar',
+ 'xop' => 'application/xop+xml',
+ 'xpi' => 'application/x-xpinstall',
+ 'xpl' => 'application/xproc+xml',
+ 'xpm' => 'image/x-xpixmap',
+ 'xpr' => 'application/vnd.is-xpr',
+ 'xps' => 'application/vnd.ms-xpsdocument',
+ 'xpw' => 'application/vnd.intercon.formnet',
+ 'xpx' => 'application/vnd.intercon.formnet',
+ 'xsl' => 'application/xml',
+ 'xslt' => 'application/xslt+xml',
+ 'xsm' => 'application/vnd.syncml+xml',
+ 'xspf' => 'application/xspf+xml',
+ 'xul' => 'application/vnd.mozilla.xul+xml',
+ 'xvm' => 'application/xv+xml',
+ 'xvml' => 'application/xv+xml',
+ 'xwd' => 'image/x-xwindowdump',
+ 'xyz' => 'chemical/x-xyz',
+ 'xz' => 'application/x-xz',
+ 'yang' => 'application/yang',
+ 'yin' => 'application/yin+xml',
+ 'z1' => 'application/x-zmachine',
+ 'z2' => 'application/x-zmachine',
+ 'z3' => 'application/x-zmachine',
+ 'z4' => 'application/x-zmachine',
+ 'z5' => 'application/x-zmachine',
+ 'z6' => 'application/x-zmachine',
+ 'z7' => 'application/x-zmachine',
+ 'z8' => 'application/x-zmachine',
+ 'zaz' => 'application/vnd.zzazz.deck+xml',
+ 'zip' => 'application/zip',
+ 'zir' => 'application/vnd.zul',
+ 'zirz' => 'application/vnd.zul',
+ 'zmm' => 'application/vnd.handheld-entertainment+xml',
+ '123' => 'application/vnd.lotus-1-2-3'
+);
diff --git a/vendor/swiftmailer/preferences.php b/vendor/swiftmailer/preferences.php
new file mode 100644
index 00000000..42239437
--- /dev/null
+++ b/vendor/swiftmailer/preferences.php
@@ -0,0 +1,35 @@
+<?php
+
+/****************************************************************************/
+/* */
+/* YOU MAY WISH TO MODIFY OR REMOVE THE FOLLOWING LINES WHICH SET DEFAULTS */
+/* */
+/****************************************************************************/
+
+$preferences = Swift_Preferences::getInstance();
+
+// Sets the default charset so that setCharset() is not needed elsewhere
+$preferences->setCharset('utf-8');
+
+// Without these lines the default caching mechanism is "array" but this uses a lot of memory.
+// If possible, use a disk cache to enable attaching large attachments etc.
+// You can override the default temporary directory by setting the TMPDIR environment variable.
+
+// The @ operator in front of is_writable calls is to avoid PHP warnings
+// when using open_basedir
+$tmp = getenv('TMPDIR');
+if ($tmp && @is_writable($tmp)) {
+ $preferences
+ ->setTempDir($tmp)
+ ->setCacheType('disk');
+} elseif (function_exists('sys_get_temp_dir') && @is_writable(sys_get_temp_dir())) {
+ $preferences
+ ->setTempDir(sys_get_temp_dir())
+ ->setCacheType('disk');
+}
+
+// this should only be done when Swiftmailer won't use the native QP content encoder
+// see mime_deps.php
+if (version_compare(phpversion(), '5.4.7', '<')) {
+ $preferences->setQPDotEscape(false);
+}
diff --git a/vendor/swiftmailer/swift_init.php b/vendor/swiftmailer/swift_init.php
new file mode 100644
index 00000000..5c80b05c
--- /dev/null
+++ b/vendor/swiftmailer/swift_init.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Dependency injection initialization for Swift Mailer.
+ */
+
+if (defined('SWIFT_INIT_LOADED')) {
+ return;
+}
+
+define('SWIFT_INIT_LOADED', true);
+
+// Load in dependency maps
+require dirname(__FILE__) . '/dependency_maps/cache_deps.php';
+require dirname(__FILE__) . '/dependency_maps/mime_deps.php';
+require dirname(__FILE__) . '/dependency_maps/message_deps.php';
+require dirname(__FILE__) . '/dependency_maps/transport_deps.php';
+
+// Load in global library preferences
+require dirname(__FILE__) . '/preferences.php';
diff --git a/vendor/swiftmailer/swift_required.php b/vendor/swiftmailer/swift_required.php
new file mode 100644
index 00000000..d64d26ed
--- /dev/null
+++ b/vendor/swiftmailer/swift_required.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Autoloader and dependency injection initialization for Swift Mailer.
+ */
+
+if (class_exists('Swift', false)) {
+ return;
+}
+
+// Load Swift utility class
+require dirname(__FILE__) . '/classes/Swift.php';
+
+if (!function_exists('_swiftmailer_init')) {
+ function _swiftmailer_init()
+ {
+ require dirname(__FILE__) . '/swift_init.php';
+ }
+}
+
+// Start the autoloader and lazy-load the init script to set up dependency injection
+Swift::registerAutoload('_swiftmailer_init');
diff --git a/vendor/swiftmailer/swift_required_pear.php b/vendor/swiftmailer/swift_required_pear.php
new file mode 100644
index 00000000..05acc323
--- /dev/null
+++ b/vendor/swiftmailer/swift_required_pear.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Autoloader and dependency injection initialization for Swift Mailer.
+ */
+
+if (class_exists('Swift', false)) {
+ return;
+}
+
+// Load Swift utility class
+require dirname(__FILE__) . '/Swift.php';
+
+if (!function_exists('_swiftmailer_init')) {
+ function _swiftmailer_init()
+ {
+ require dirname(__FILE__) . '/swift_init.php';
+ }
+}
+
+// Start the autoloader and lazy-load the init script to set up dependency injection
+Swift::registerAutoload('_swiftmailer_init');
diff --git a/vendor/swiftmailer/swiftmailer_generate_mimes_config.php b/vendor/swiftmailer/swiftmailer_generate_mimes_config.php
new file mode 100755
index 00000000..695d94d3
--- /dev/null
+++ b/vendor/swiftmailer/swiftmailer_generate_mimes_config.php
@@ -0,0 +1,201 @@
+#!/usr/bin/php
+
+<?php
+define('APACHE_MIME_TYPES_URL', 'http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types');
+define('FREEDESKTOP_XML_URL', 'https://raw2.github.com/minad/mimemagic/master/script/freedesktop.org.xml');
+
+function generateUpToDateMimeArray()
+{
+ $preamble = "<?php\n\n";
+ $preamble .= "/*\n";
+ $preamble .= " * This file is part of SwiftMailer.\n";
+ $preamble .= " * (c) 2004-2009 Chris Corbyn\n *\n";
+ $preamble .= " * For the full copyright and license information, please view the LICENSE\n";
+ $preamble .= " * file that was distributed with this source code.\n *\n";
+ $preamble .= " * autogenerated using http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types\n";
+ $preamble .= " * and https://raw.github.com/minad/mimemagic/master/script/freedesktop.org.xml\n";
+ $preamble .= " */\n\n";
+ $preamble .= "/*\n";
+ $preamble .= " * List of MIME type automatically detected in Swift Mailer.\n";
+ $preamble .= " */\n\n";
+ $preamble .= "// You may add or take away what you like (lowercase required)\n\n";
+
+ // get current mime types files
+ $mime_types = @file_get_contents(APACHE_MIME_TYPES_URL);
+ $mime_xml = @file_get_contents(FREEDESKTOP_XML_URL);
+
+ // prepare valid mime types
+ $valid_mime_types = array();
+
+ // split mime type and extensions eg. "video/x-matroska mkv mk3d mks"
+ if (preg_match_all('/^#?([a-z0-9\-\+\/\.]+)[\t]+(.*)$/miu', $mime_types, $matches) !== FALSE) {
+ // collection of predefined mimetypes (bugfix for wrong resolved or missing mime types)
+ $valid_mime_types_preset = array(
+ 'php' => 'application/x-php',
+ 'php3' => 'application/x-php',
+ 'php4' => 'application/x-php',
+ 'php5' => 'application/x-php',
+ 'pdf' => 'application/pdf',
+ 'zip' => 'application/zip',
+ 'gif' => 'image/gif',
+ 'jpg' => 'image/jpeg',
+ 'png' => 'image/png',
+ 'css' => 'text/css',
+ 'html' => 'text/html',
+ 'js' => 'text/javascript',
+ 'txt' => 'text/plain',
+ 'xml' => 'text/xml',
+ 'aif' => 'audio/x-aiff',
+ 'aiff' => 'audio/x-aiff',
+ 'avi' => 'video/avi',
+ 'bmp' => 'image/bmp',
+ 'bz2' => 'application/x-bz2',
+ 'csv' => 'text/csv',
+ 'dmg' => 'application/x-apple-diskimage',
+ 'doc' => 'application/msword',
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'eml' => 'message/rfc822',
+ 'aps' => 'application/postscript',
+ 'exe' => 'application/x-ms-dos-executable',
+ 'flv' => 'video/x-flv',
+ 'gif' => 'image/gif',
+ 'gz' => 'application/x-gzip',
+ 'hqx' => 'application/stuffit',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'jar' => 'application/x-java-archive',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'm3u' => 'audio/x-mpegurl',
+ 'm4a' => 'audio/mp4',
+ 'mdb' => 'application/x-msaccess',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'mov' => 'video/quicktime',
+ 'mp3' => 'audio/mpeg',
+ 'mp4' => 'video/mp4',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'odg' => 'vnd.oasis.opendocument.graphics',
+ 'odp' => 'vnd.oasis.opendocument.presentation',
+ 'odt' => 'vnd.oasis.opendocument.text',
+ 'ods' => 'vnd.oasis.opendocument.spreadsheet',
+ 'ogg' => 'audio/ogg',
+ 'pdf' => 'application/pdf',
+ 'png' => 'image/png',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'ps' => 'application/postscript',
+ 'rar' => 'application/x-rar-compressed',
+ 'rtf' => 'application/rtf',
+ 'tar' => 'application/x-tar',
+ 'sit' => 'application/x-stuffit',
+ 'svg' => 'image/svg+xml',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'ttf' => 'application/x-font-truetype',
+ 'txt' => 'text/plain',
+ 'vcf' => 'text/x-vcard',
+ 'wav' => 'audio/wav',
+ 'wma' => 'audio/x-ms-wma',
+ 'wmv' => 'audio/x-ms-wmv',
+ 'xls' => 'application/excel',
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'xml' => 'application/xml',
+ 'zip' => 'application/zip'
+ );
+
+ // wrap array for generating file
+ foreach ($valid_mime_types_preset as $extension => $mime_type) {
+ // generate array for mimetype to extension resolver (only first match)
+ $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'";
+ }
+
+ // collect extensions
+ $valid_extensions = array();
+
+ // all extensions from second match
+ foreach ($matches[2] as $i => $extensions) {
+ // explode multiple extensions from string
+ $extensions = explode(" ", strtolower($extensions));
+
+ // force array for foreach
+ if (!is_array($extensions)) {
+ $extensions = array($extensions);
+ }
+
+ foreach ($extensions as $extension) {
+ // get mime type
+ $mime_type = $matches[1][$i];
+
+ // check if string length lower than 10
+ if (strlen($extension) < 10) {
+ // add extension
+ $valid_extensions[] = $extension;
+
+ if (!isset($valid_mime_types[$mime_type])) {
+ // generate array for mimetype to extension resolver (only first match)
+ $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'";
+ }
+ }
+ }
+ }
+ }
+
+ $xml = simplexml_load_string($mime_xml);
+
+ foreach ($xml as $node) {
+ // check if there is no pattern
+ if (!isset($node->glob["pattern"])) {
+ continue;
+ }
+
+ // get all matching extensions from match
+ foreach ((array) $node->glob["pattern"] as $extension) {
+ // skip none glob extensions
+ if (strpos($extension, '.') === FALSE) {
+ continue;
+ }
+
+ // remove get only last part
+ $extension = explode('.', strtolower($extension));
+ $extension = end($extension);
+
+ // maximum length in database column
+ if (strlen($extension) <= 9) {
+ $valid_extensions[] = $extension;
+ }
+ }
+
+ if (isset($node->glob["pattern"][0])) {
+ // mime type
+ $mime_type = strtolower((string) $node["type"]);
+
+ // get first extension
+ $extension = strtolower(trim($node->glob["ddpattern"][0], '*.'));
+
+ // skip none glob extensions and check if string length between 1 and 10
+ if (strpos($extension, '.') !== FALSE || strlen($extension) < 1 || strlen($extension) > 9) {
+ continue;
+ }
+
+ // check if string length lower than 10
+ if (!isset($valid_mime_types[$mime_type])) {
+ // generate array for mimetype to extension resolver (only first match)
+ $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'";
+ }
+ }
+ }
+
+ // full list of valid extensions only
+ $valid_mime_types = array_unique($valid_mime_types);
+ ksort($valid_mime_types);
+
+ // combine mime types and extensions array
+ $output = "$preamble\$swift_mime_types = array(\n ".implode($valid_mime_types, ",\n ")."\n);";
+
+ // write mime_types.php config file
+ @file_put_contents('./mime_types.php', $output);
+}
+
+generateUpToDateMimeArray();